@oj-module/cli 0.2.53 → 0.2.54
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/devkit/SKILL.md +2 -2
- package/devkit/manual.md +32 -25
- package/package.json +2 -2
- package/shell-dist/assets/runtime.js +7 -4
- package/shell-dist/index.html +3 -3
- package/shell-dist/versions.json +3 -3
- package/src/__tests__/templates-tenant-scope.test.ts +3 -2
- package/src/config.ts +9 -0
- package/src/contract/__tests__/client-path.test.ts +30 -0
- package/src/contract/__tests__/emit-client.test.ts +18 -0
- package/src/contract/__tests__/handler-scan.test.ts +23 -0
- package/src/contract/check.ts +5 -5
- package/src/contract/client-path.ts +30 -0
- package/src/contract/emit-client.ts +18 -4
- package/src/contract/handler-scan.ts +40 -3
- package/src/contract/run.ts +5 -3
- package/src/init.ts +19 -1
- package/templates/README.md +40 -44
- package/templates/init.include.yaml +12 -8
- package/templates/openapi.json +1393 -34
- package/templates/src/_platform/api/contacts/api.ts +29 -1
- package/templates/src/_platform/api/contacts/detail/api.ts +25 -1
- package/templates/src/_platform/api/solutions/api.ts +60 -1
- package/templates/src/_platform/web/__client/api.schemas.ts +99 -35
- package/templates/src/_platform/web/__client/api.ts +103 -59
- package/templates/src/app/web/entry.ts +77 -0
- package/templates/src/{home/web → app/web/home}/__client/api.ts +5 -2
- package/templates/src/app/web/home/routes.ts +41 -0
- package/templates/src/app/web/login/routes.ts +71 -0
- package/templates/src/{notification/web → app/web/notification}/__client/api.schemas.ts +14 -0
- package/templates/src/{notification/web → app/web/notification}/__client/api.ts +67 -20
- package/templates/src/app/web/notification/routes.ts +70 -0
- package/templates/src/{personal-center/web → app/web/personal-center}/__client/api.ts +5 -2
- package/templates/src/app/web/personal-center/routes.ts +49 -0
- package/templates/src/{system/web → app/web/system}/__client/api.schemas.ts +28 -22
- package/templates/src/{system/web → app/web/system}/__client/api.ts +103 -58
- package/templates/src/{system/web → app/web/system}/pages/users/index.tsx +3 -3
- package/templates/src/{system/web → app/web/system}/pages/wecom/index.tsx +12 -3
- package/templates/src/{system/web/entry.ts → app/web/system/routes.ts} +24 -35
- package/templates/src/auth/api/api.ts +59 -0
- package/templates/src/auth/api/ldap-login/api.ts +37 -1
- package/templates/src/auth/api/wecom/api.ts +23 -0
- package/templates/src/auth/web/__client/api.schemas.ts +133 -13
- package/templates/src/auth/web/__client/api.ts +129 -31
- package/templates/src/notification/api/api.ts +17 -0
- package/templates/src/notification/api/del/api.ts +2 -0
- package/templates/src/system/api/roles/api.ts +3 -0
- package/templates/src/system/api/roles/bindings/api.ts +3 -0
- package/templates/src/system/api/settings/api.ts +3 -0
- package/templates/src/system/api/users/forbidden/api.ts +3 -0
- package/templates/src/system/api/users/password/api.ts +3 -0
- package/templates/src/system/api/users/roles/api.ts +3 -0
- package/templates/src/web/api/get-async-routes/api.ts +16 -1
- package/templates/src/web/api/hello/api.ts +13 -1
- package/templates/src/web/api/user-info/api.ts +21 -1
- package/templates/src/web/web/__client/api.schemas.ts +28 -0
- package/templates/src/web/web/__client/api.ts +33 -9
- package/templates/web.config.ts +21 -15
- package/vendor/host-versions.json +3 -3
- package/templates/src/home/web/entry.ts +0 -49
- package/templates/src/login/web/entry.ts +0 -79
- package/templates/src/notification/web/entry.ts +0 -84
- package/templates/src/personal-center/web/entry.ts +0 -60
- /package/templates/src/{home/web → app/web/home}/__client/api.schemas.ts +0 -0
- /package/templates/src/{home/web → app/web/home}/locales/en-US.json +0 -0
- /package/templates/src/{home/web → app/web/home}/locales/zh-CN.json +0 -0
- /package/templates/src/{home/web → app/web/home}/pages/components/bar-chart.tsx +0 -0
- /package/templates/src/{home/web → app/web/home}/pages/components/card-list.tsx +0 -0
- /package/templates/src/{home/web → app/web/home}/pages/components/line-chart.tsx +0 -0
- /package/templates/src/{home/web → app/web/home}/pages/components/pie-chart.tsx +0 -0
- /package/templates/src/{home/web → app/web/home}/pages/index.tsx +0 -0
- /package/templates/src/{login/web → app/web/login}/auth-provider.ts +0 -0
- /package/templates/src/{login/web → app/web/login}/locales/en-US.json +0 -0
- /package/templates/src/{login/web → app/web/login}/locales/zh-CN.json +0 -0
- /package/templates/src/{login/web → app/web/login}/pages/change-password.tsx +0 -0
- /package/templates/src/{login/web → app/web/login}/pages/login.tsx +0 -0
- /package/templates/src/{login/web → app/web/login}/wecom.ts +0 -0
- /package/templates/src/{notification/web → app/web/notification}/locales/en-US.json +0 -0
- /package/templates/src/{notification/web → app/web/notification}/locales/zh-CN.json +0 -0
- /package/templates/src/{notification/web → app/web/notification}/pages/center/index.tsx +0 -0
- /package/templates/src/{personal-center/web → app/web/personal-center}/__client/api.schemas.ts +0 -0
- /package/templates/src/{personal-center/web → app/web/personal-center}/locales/en-US.json +0 -0
- /package/templates/src/{personal-center/web → app/web/personal-center}/locales/zh-CN.json +0 -0
- /package/templates/src/{personal-center/web → app/web/personal-center}/pages/my-profile/index.tsx +0 -0
- /package/templates/src/{system/web → app/web/system}/locales/en-US.json +0 -0
- /package/templates/src/{system/web → app/web/system}/locales/zh-CN.json +0 -0
- /package/templates/src/{system/web → app/web/system}/pages/departments/index.tsx +0 -0
- /package/templates/src/{system/web → app/web/system}/pages/departments/sync-bar.tsx +0 -0
- /package/templates/src/{system/web → app/web/system}/pages/departments/tree.ts +0 -0
- /package/templates/src/{system/web → app/web/system}/pages/errors.ts +0 -0
- /package/templates/src/{system/web → app/web/system}/pages/forbidden.tsx +0 -0
- /package/templates/src/{system/web → app/web/system}/pages/login-methods/index.tsx +0 -0
- /package/templates/src/{system/web → app/web/system}/pages/oplog/index.tsx +0 -0
- /package/templates/src/{system/web → app/web/system}/pages/roles/index.tsx +0 -0
- /package/templates/src/{system/web → app/web/system}/pages/settings/index.tsx +0 -0
- /package/templates/src/{system/web → app/web/system}/pages/users/roles.tsx +0 -0
|
@@ -6,7 +6,7 @@ import { searchContacts } from "../_shared/service/domain/contacts";
|
|
|
6
6
|
import { assertTenantSelf } from "../_shared/service/infra/access";
|
|
7
7
|
import { rateLimit } from "../_shared/service/infra/rate";
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
const handler = {
|
|
10
10
|
// GET /api/_platform/contacts?keyword=&limit= —— 人员目录(AC1-22~24)。
|
|
11
11
|
async get() {
|
|
12
12
|
await respond(async () => {
|
|
@@ -23,3 +23,31 @@ export default {
|
|
|
23
23
|
});
|
|
24
24
|
},
|
|
25
25
|
};
|
|
26
|
+
|
|
27
|
+
// 入参:keyword 必填(服务层红线 2~64 字符),limit 可选(钳 200)
|
|
28
|
+
handler.get.schema = {
|
|
29
|
+
query: {
|
|
30
|
+
type: "object",
|
|
31
|
+
required: ["keyword"],
|
|
32
|
+
properties: {
|
|
33
|
+
keyword: { type: "string", minLength: 2 },
|
|
34
|
+
limit: { type: "number" },
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// 出参:目录红线只出 id/username/display_name(不含 email/avatar/roles)
|
|
40
|
+
handler.get.response = {
|
|
41
|
+
type: "array",
|
|
42
|
+
items: {
|
|
43
|
+
type: "object",
|
|
44
|
+
required: ["id", "username", "display_name"],
|
|
45
|
+
properties: {
|
|
46
|
+
id: { type: "number" },
|
|
47
|
+
username: { type: "string" },
|
|
48
|
+
display_name: { type: ["string", "null"] },
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export default handler;
|
|
@@ -4,7 +4,7 @@ import { contactDetail } from "../../_shared/service/domain/contacts";
|
|
|
4
4
|
import { assertTenantSelf } from "../../_shared/service/infra/access";
|
|
5
5
|
import { rateLimit } from "../../_shared/service/infra/rate";
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
const handler = {
|
|
8
8
|
async get() {
|
|
9
9
|
await respond(async () => {
|
|
10
10
|
const uid = http.user?.id;
|
|
@@ -19,3 +19,27 @@ export default {
|
|
|
19
19
|
});
|
|
20
20
|
},
|
|
21
21
|
};
|
|
22
|
+
|
|
23
|
+
// 入参:id 必填(详情按 id 取单条)
|
|
24
|
+
handler.get.schema = {
|
|
25
|
+
query: {
|
|
26
|
+
type: "object",
|
|
27
|
+
required: ["id"],
|
|
28
|
+
properties: { id: { type: "number" } },
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// 出参:详情比目录多 email/avatar(安全评审 P2:仅详情端点给)
|
|
33
|
+
handler.get.response = {
|
|
34
|
+
type: "object",
|
|
35
|
+
required: ["id", "username", "display_name", "email", "avatar_base64"],
|
|
36
|
+
properties: {
|
|
37
|
+
id: { type: "number" },
|
|
38
|
+
username: { type: "string" },
|
|
39
|
+
display_name: { type: ["string", "null"] },
|
|
40
|
+
email: { type: ["string", "null"] },
|
|
41
|
+
avatar_base64: { type: ["string", "null"] },
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export default handler;
|
|
@@ -167,7 +167,7 @@ async function listMigrationFiles(env: SolutionsEnv, name: string, version: stri
|
|
|
167
167
|
}
|
|
168
168
|
|
|
169
169
|
export function createSolutionsApi(env: SolutionsEnv) {
|
|
170
|
-
|
|
170
|
+
const api = {
|
|
171
171
|
// GET /api/_platform/solutions/routes —— 前端归并数据源(登录即可)。
|
|
172
172
|
routes: {
|
|
173
173
|
async get() {
|
|
@@ -217,6 +217,65 @@ export function createSolutionsApi(env: SolutionsEnv) {
|
|
|
217
217
|
},
|
|
218
218
|
},
|
|
219
219
|
};
|
|
220
|
+
|
|
221
|
+
// ---- 契约(v0.1.72:入参 .schema / 出参平级 .response)----
|
|
222
|
+
// 路由行出参:SolutionRouteRow(前端归并与深检共用形状)
|
|
223
|
+
const routeRow = {
|
|
224
|
+
type: "object",
|
|
225
|
+
required: ["path", "module", "category", "order", "title_key", "required_permission", "enabled"],
|
|
226
|
+
properties: {
|
|
227
|
+
path: { type: "string" },
|
|
228
|
+
module: { type: "string" },
|
|
229
|
+
category: { type: "string", enum: ["main", "admin", "hidden"] },
|
|
230
|
+
order: { type: "number" },
|
|
231
|
+
title_key: { type: ["string", "null"] },
|
|
232
|
+
required_permission: { type: ["string", "null"] },
|
|
233
|
+
enabled: { type: "boolean" },
|
|
234
|
+
},
|
|
235
|
+
};
|
|
236
|
+
api.routes.get.response = { type: "array", items: routeRow };
|
|
237
|
+
|
|
238
|
+
// 深检报告出参:VerifyReport(ok/checks/advise)
|
|
239
|
+
const verifyReport = {
|
|
240
|
+
type: "object",
|
|
241
|
+
required: ["ok", "checks", "advise"],
|
|
242
|
+
properties: {
|
|
243
|
+
ok: { type: "boolean" },
|
|
244
|
+
checks: {
|
|
245
|
+
type: "array",
|
|
246
|
+
items: {
|
|
247
|
+
type: "object",
|
|
248
|
+
required: ["id", "severity", "subject", "advise_key"],
|
|
249
|
+
properties: {
|
|
250
|
+
id: { type: "string" },
|
|
251
|
+
severity: { type: "string", enum: ["error", "warn", "info"] },
|
|
252
|
+
subject: { type: "string" },
|
|
253
|
+
advise_key: { type: "string" },
|
|
254
|
+
},
|
|
255
|
+
},
|
|
256
|
+
},
|
|
257
|
+
advise: { type: "array", items: { type: "string" } },
|
|
258
|
+
},
|
|
259
|
+
};
|
|
260
|
+
// verify:name 必填(端点门,缺参 400)
|
|
261
|
+
api.verify.post.schema = {
|
|
262
|
+
query: {
|
|
263
|
+
type: "object",
|
|
264
|
+
required: ["name"],
|
|
265
|
+
properties: { name: { type: "string", minLength: 1 } },
|
|
266
|
+
},
|
|
267
|
+
};
|
|
268
|
+
api.verify.post.response = verifyReport;
|
|
269
|
+
api.verify.last.get.schema = {
|
|
270
|
+
query: {
|
|
271
|
+
type: "object",
|
|
272
|
+
required: ["name"],
|
|
273
|
+
properties: { name: { type: "string", minLength: 1 } },
|
|
274
|
+
},
|
|
275
|
+
};
|
|
276
|
+
api.verify.last.get.response = verifyReport;
|
|
277
|
+
|
|
278
|
+
return api;
|
|
220
279
|
}
|
|
221
280
|
|
|
222
281
|
export default createSolutionsApi(solutionsEnv());
|
|
@@ -4,6 +4,29 @@
|
|
|
4
4
|
import { z } from "@oj-module/runtime";
|
|
5
5
|
|
|
6
6
|
export const schemas = {
|
|
7
|
+
"platformContactsGet": {
|
|
8
|
+
query: z.object({
|
|
9
|
+
"keyword": z.string().min(2),
|
|
10
|
+
"limit": z.number().optional()
|
|
11
|
+
}),
|
|
12
|
+
data: z.array(z.object({
|
|
13
|
+
"id": z.number(),
|
|
14
|
+
"username": z.string(),
|
|
15
|
+
"display_name": z.string().nullable()
|
|
16
|
+
})),
|
|
17
|
+
},
|
|
18
|
+
"platformContactsDetailGet": {
|
|
19
|
+
query: z.object({
|
|
20
|
+
"id": z.number()
|
|
21
|
+
}),
|
|
22
|
+
data: z.object({
|
|
23
|
+
"id": z.number(),
|
|
24
|
+
"username": z.string(),
|
|
25
|
+
"display_name": z.string().nullable(),
|
|
26
|
+
"email": z.string().nullable(),
|
|
27
|
+
"avatar_base64": z.string().nullable()
|
|
28
|
+
}),
|
|
29
|
+
},
|
|
7
30
|
"platformMarketInstallPost": {
|
|
8
31
|
body: z.object({
|
|
9
32
|
"source": z.enum(["cdn", "file"]),
|
|
@@ -101,19 +124,6 @@ export const schemas = {
|
|
|
101
124
|
data: z.array(z.object({
|
|
102
125
|
|
|
103
126
|
}).catchall(z.unknown())),
|
|
104
|
-
},
|
|
105
|
-
"platformOrgTreeGet": {
|
|
106
|
-
query: z.object({
|
|
107
|
-
"scope": z.enum(["self", "all"]).optional()
|
|
108
|
-
}),
|
|
109
|
-
data: z.array(z.object({
|
|
110
|
-
"id": z.number(),
|
|
111
|
-
"parentId": z.number().nullable(),
|
|
112
|
-
"name": z.string().nullable(),
|
|
113
|
-
"nameEn": z.string().nullable().optional(),
|
|
114
|
-
"orderNo": z.number(),
|
|
115
|
-
"memberCount": z.number()
|
|
116
|
-
})),
|
|
117
127
|
},
|
|
118
128
|
"platformOrgDepartmentsGet": {
|
|
119
129
|
query: z.object({
|
|
@@ -136,6 +146,16 @@ export const schemas = {
|
|
|
136
146
|
"page": z.number(),
|
|
137
147
|
"size": z.number(),
|
|
138
148
|
"truncated": z.boolean()
|
|
149
|
+
}),
|
|
150
|
+
},
|
|
151
|
+
"platformOrgIsMemberGet": {
|
|
152
|
+
query: z.object({
|
|
153
|
+
"scope": z.enum(["self", "all"]).optional(),
|
|
154
|
+
"uid": z.number().optional(),
|
|
155
|
+
"dept": z.number()
|
|
156
|
+
}),
|
|
157
|
+
data: z.object({
|
|
158
|
+
"isMember": z.boolean()
|
|
139
159
|
}),
|
|
140
160
|
},
|
|
141
161
|
"platformOrgMembersGet": {
|
|
@@ -160,24 +180,6 @@ export const schemas = {
|
|
|
160
180
|
"page": z.number(),
|
|
161
181
|
"size": z.number(),
|
|
162
182
|
"truncated": z.boolean()
|
|
163
|
-
}),
|
|
164
|
-
},
|
|
165
|
-
"platformOrgUserGet": {
|
|
166
|
-
query: z.object({
|
|
167
|
-
"scope": z.enum(["self", "all"]).optional(),
|
|
168
|
-
"uid": z.number().optional()
|
|
169
|
-
}),
|
|
170
|
-
data: z.object({
|
|
171
|
-
"userId": z.number(),
|
|
172
|
-
"username": z.string(),
|
|
173
|
-
"displayName": z.string().nullable().optional(),
|
|
174
|
-
"position": z.string().nullable(),
|
|
175
|
-
"mainDeptId": z.number().nullable(),
|
|
176
|
-
"mainDeptPath": z.array(z.string()),
|
|
177
|
-
"departments": z.array(z.object({
|
|
178
|
-
"deptId": z.number(),
|
|
179
|
-
"deptPath": z.array(z.string())
|
|
180
|
-
}))
|
|
181
183
|
}),
|
|
182
184
|
},
|
|
183
185
|
"platformOrgPickerGet": {
|
|
@@ -218,14 +220,76 @@ export const schemas = {
|
|
|
218
220
|
"userIds": z.array(z.number())
|
|
219
221
|
}),
|
|
220
222
|
},
|
|
221
|
-
"
|
|
223
|
+
"platformOrgTreeGet": {
|
|
224
|
+
query: z.object({
|
|
225
|
+
"scope": z.enum(["self", "all"]).optional()
|
|
226
|
+
}),
|
|
227
|
+
data: z.array(z.object({
|
|
228
|
+
"id": z.number(),
|
|
229
|
+
"parentId": z.number().nullable(),
|
|
230
|
+
"name": z.string().nullable(),
|
|
231
|
+
"nameEn": z.string().nullable().optional(),
|
|
232
|
+
"orderNo": z.number(),
|
|
233
|
+
"memberCount": z.number()
|
|
234
|
+
})),
|
|
235
|
+
},
|
|
236
|
+
"platformOrgUserGet": {
|
|
222
237
|
query: z.object({
|
|
223
238
|
"scope": z.enum(["self", "all"]).optional(),
|
|
224
|
-
"uid": z.number().optional()
|
|
225
|
-
"dept": z.number()
|
|
239
|
+
"uid": z.number().optional()
|
|
226
240
|
}),
|
|
227
241
|
data: z.object({
|
|
228
|
-
"
|
|
242
|
+
"userId": z.number(),
|
|
243
|
+
"username": z.string(),
|
|
244
|
+
"displayName": z.string().nullable().optional(),
|
|
245
|
+
"position": z.string().nullable(),
|
|
246
|
+
"mainDeptId": z.number().nullable(),
|
|
247
|
+
"mainDeptPath": z.array(z.string()),
|
|
248
|
+
"departments": z.array(z.object({
|
|
249
|
+
"deptId": z.number(),
|
|
250
|
+
"deptPath": z.array(z.string())
|
|
251
|
+
}))
|
|
252
|
+
}),
|
|
253
|
+
},
|
|
254
|
+
"platformSolutionsRoutesGet": {
|
|
255
|
+
data: z.array(z.object({
|
|
256
|
+
"path": z.string(),
|
|
257
|
+
"module": z.string(),
|
|
258
|
+
"category": z.enum(["main", "admin", "hidden"]),
|
|
259
|
+
"order": z.number(),
|
|
260
|
+
"title_key": z.string().nullable(),
|
|
261
|
+
"required_permission": z.string().nullable(),
|
|
262
|
+
"enabled": z.boolean()
|
|
263
|
+
})),
|
|
264
|
+
},
|
|
265
|
+
"platformSolutionsVerifyPost": {
|
|
266
|
+
query: z.object({
|
|
267
|
+
"name": z.string().min(1)
|
|
268
|
+
}),
|
|
269
|
+
data: z.object({
|
|
270
|
+
"ok": z.boolean(),
|
|
271
|
+
"checks": z.array(z.object({
|
|
272
|
+
"id": z.string(),
|
|
273
|
+
"severity": z.enum(["error", "warn", "info"]),
|
|
274
|
+
"subject": z.string(),
|
|
275
|
+
"advise_key": z.string()
|
|
276
|
+
})),
|
|
277
|
+
"advise": z.array(z.string())
|
|
278
|
+
}),
|
|
279
|
+
},
|
|
280
|
+
"platformSolutionsVerifyLastGet": {
|
|
281
|
+
query: z.object({
|
|
282
|
+
"name": z.string().min(1)
|
|
283
|
+
}),
|
|
284
|
+
data: z.object({
|
|
285
|
+
"ok": z.boolean(),
|
|
286
|
+
"checks": z.array(z.object({
|
|
287
|
+
"id": z.string(),
|
|
288
|
+
"severity": z.enum(["error", "warn", "info"]),
|
|
289
|
+
"subject": z.string(),
|
|
290
|
+
"advise_key": z.string()
|
|
291
|
+
})),
|
|
292
|
+
"advise": z.array(z.string())
|
|
229
293
|
}),
|
|
230
294
|
},
|
|
231
295
|
};
|
|
@@ -33,7 +33,7 @@ export function create_platformClient(ctx: ModuleContext) {
|
|
|
33
33
|
}
|
|
34
34
|
ctx.register.apiPrefix(API_PREFIX);
|
|
35
35
|
bindRequest(ctx.utils.request);
|
|
36
|
-
return { platformContactsGet, platformContactsDetailGet, platformMarketInstallPost, platformMarketInstallCancelPost, platformMarketTaskGet, platformMarketEnablePost, platformMarketMetaGet, platformMarketTrustGet, platformMarketTrustPost, platformMarketTrustKeyPost, platformMarketTrustKeyDelete, platformMarketIndexGet, platformMarketUninstallImpactGet, platformMarketUninstallPost, platformMarketHistoryGet,
|
|
36
|
+
return { platformContactsGet, platformContactsDetailGet, platformMarketInstallPost, platformMarketInstallCancelPost, platformMarketTaskGet, platformMarketEnablePost, platformMarketMetaGet, platformMarketTrustGet, platformMarketTrustPost, platformMarketTrustKeyPost, platformMarketTrustKeyDelete, platformMarketIndexGet, platformMarketUninstallImpactGet, platformMarketUninstallPost, platformMarketHistoryGet, platformOrgDepartmentsGet, platformOrgIsMemberGet, platformOrgMembersGet, platformOrgPickerGet, platformOrgResolvePost, platformOrgTreeGet, platformOrgUserGet, platformSolutionsRoutesGet, platformSolutionsVerifyPost, platformSolutionsVerifyLastGet };
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
/**
|
|
@@ -64,14 +64,23 @@ async function toApiError(e: unknown): Promise<unknown> {
|
|
|
64
64
|
return e;
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
export
|
|
67
|
+
export type PlatformContactsGetQuery = z.input<(typeof schemas)["platformContactsGet"]["query"]>;
|
|
68
|
+
export type PlatformContactsGetData = z.infer<(typeof schemas)["platformContactsGet"]["data"]>;
|
|
69
|
+
|
|
70
|
+
export async function platformContactsGet(query: PlatformContactsGetQuery): Promise<PlatformContactsGetData> {
|
|
68
71
|
const client = ensureReq();
|
|
69
72
|
try {
|
|
70
|
-
const env = await client.get(`_platform/contacts
|
|
73
|
+
const env = await client.get(`_platform/contacts`, { searchParams: query as Record<string, string | number | boolean> }).json<OjEnvelope<PlatformContactsGetData>>();
|
|
71
74
|
// 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
|
|
72
75
|
if (typeof env.code === "number" && env.code !== 0)
|
|
73
76
|
throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
|
|
74
|
-
const data = env.data as
|
|
77
|
+
const data = env.data as PlatformContactsGetData;
|
|
78
|
+
if (import.meta.env.DEV) {
|
|
79
|
+
const { schemas } = await import("./api.schemas");
|
|
80
|
+
const r = schemas["platformContactsGet"].data.safeParse(data);
|
|
81
|
+
if (!r.success)
|
|
82
|
+
throw new ContractApiError(-1, `[契约违例] platformContactsGet 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
|
|
83
|
+
}
|
|
75
84
|
return data;
|
|
76
85
|
}
|
|
77
86
|
catch (e) {
|
|
@@ -79,14 +88,23 @@ export async function platformContactsGet(): Promise<unknown> {
|
|
|
79
88
|
}
|
|
80
89
|
}
|
|
81
90
|
|
|
82
|
-
export
|
|
91
|
+
export type PlatformContactsDetailGetQuery = z.input<(typeof schemas)["platformContactsDetailGet"]["query"]>;
|
|
92
|
+
export type PlatformContactsDetailGetData = z.infer<(typeof schemas)["platformContactsDetailGet"]["data"]>;
|
|
93
|
+
|
|
94
|
+
export async function platformContactsDetailGet(query: PlatformContactsDetailGetQuery): Promise<PlatformContactsDetailGetData> {
|
|
83
95
|
const client = ensureReq();
|
|
84
96
|
try {
|
|
85
|
-
const env = await client.get(`_platform/contacts/detail
|
|
97
|
+
const env = await client.get(`_platform/contacts/detail`, { searchParams: query as Record<string, string | number | boolean> }).json<OjEnvelope<PlatformContactsDetailGetData>>();
|
|
86
98
|
// 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
|
|
87
99
|
if (typeof env.code === "number" && env.code !== 0)
|
|
88
100
|
throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
|
|
89
|
-
const data = env.data as
|
|
101
|
+
const data = env.data as PlatformContactsDetailGetData;
|
|
102
|
+
if (import.meta.env.DEV) {
|
|
103
|
+
const { schemas } = await import("./api.schemas");
|
|
104
|
+
const r = schemas["platformContactsDetailGet"].data.safeParse(data);
|
|
105
|
+
if (!r.success)
|
|
106
|
+
throw new ContractApiError(-1, `[契约违例] platformContactsDetailGet 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
|
|
107
|
+
}
|
|
90
108
|
return data;
|
|
91
109
|
}
|
|
92
110
|
catch (e) {
|
|
@@ -402,14 +420,23 @@ export async function platformMarketHistoryGet(): Promise<PlatformMarketHistoryG
|
|
|
402
420
|
}
|
|
403
421
|
}
|
|
404
422
|
|
|
405
|
-
export
|
|
423
|
+
export type PlatformOrgDepartmentsGetQuery = z.input<(typeof schemas)["platformOrgDepartmentsGet"]["query"]>;
|
|
424
|
+
export type PlatformOrgDepartmentsGetData = z.infer<(typeof schemas)["platformOrgDepartmentsGet"]["data"]>;
|
|
425
|
+
|
|
426
|
+
export async function platformOrgDepartmentsGet(query: PlatformOrgDepartmentsGetQuery): Promise<PlatformOrgDepartmentsGetData> {
|
|
406
427
|
const client = ensureReq();
|
|
407
428
|
try {
|
|
408
|
-
const env = await client.get(`_platform/
|
|
429
|
+
const env = await client.get(`_platform/org/departments`, { searchParams: query as Record<string, string | number | boolean> }).json<OjEnvelope<PlatformOrgDepartmentsGetData>>();
|
|
409
430
|
// 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
|
|
410
431
|
if (typeof env.code === "number" && env.code !== 0)
|
|
411
432
|
throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
|
|
412
|
-
const data = env.data as
|
|
433
|
+
const data = env.data as PlatformOrgDepartmentsGetData;
|
|
434
|
+
if (import.meta.env.DEV) {
|
|
435
|
+
const { schemas } = await import("./api.schemas");
|
|
436
|
+
const r = schemas["platformOrgDepartmentsGet"].data.safeParse(data);
|
|
437
|
+
if (!r.success)
|
|
438
|
+
throw new ContractApiError(-1, `[契约违例] platformOrgDepartmentsGet 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
|
|
439
|
+
}
|
|
413
440
|
return data;
|
|
414
441
|
}
|
|
415
442
|
catch (e) {
|
|
@@ -417,14 +444,23 @@ export async function platformSolutionsRoutesGet(): Promise<unknown> {
|
|
|
417
444
|
}
|
|
418
445
|
}
|
|
419
446
|
|
|
420
|
-
export
|
|
447
|
+
export type PlatformOrgIsMemberGetQuery = z.input<(typeof schemas)["platformOrgIsMemberGet"]["query"]>;
|
|
448
|
+
export type PlatformOrgIsMemberGetData = z.infer<(typeof schemas)["platformOrgIsMemberGet"]["data"]>;
|
|
449
|
+
|
|
450
|
+
export async function platformOrgIsMemberGet(query: PlatformOrgIsMemberGetQuery): Promise<PlatformOrgIsMemberGetData> {
|
|
421
451
|
const client = ensureReq();
|
|
422
452
|
try {
|
|
423
|
-
const env = await client.
|
|
453
|
+
const env = await client.get(`_platform/org/is-member`, { searchParams: query as Record<string, string | number | boolean> }).json<OjEnvelope<PlatformOrgIsMemberGetData>>();
|
|
424
454
|
// 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
|
|
425
455
|
if (typeof env.code === "number" && env.code !== 0)
|
|
426
456
|
throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
|
|
427
|
-
const data = env.data as
|
|
457
|
+
const data = env.data as PlatformOrgIsMemberGetData;
|
|
458
|
+
if (import.meta.env.DEV) {
|
|
459
|
+
const { schemas } = await import("./api.schemas");
|
|
460
|
+
const r = schemas["platformOrgIsMemberGet"].data.safeParse(data);
|
|
461
|
+
if (!r.success)
|
|
462
|
+
throw new ContractApiError(-1, `[契约违例] platformOrgIsMemberGet 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
|
|
463
|
+
}
|
|
428
464
|
return data;
|
|
429
465
|
}
|
|
430
466
|
catch (e) {
|
|
@@ -432,14 +468,23 @@ export async function platformSolutionsVerifyPost(): Promise<unknown> {
|
|
|
432
468
|
}
|
|
433
469
|
}
|
|
434
470
|
|
|
435
|
-
export
|
|
471
|
+
export type PlatformOrgMembersGetQuery = z.input<(typeof schemas)["platformOrgMembersGet"]["query"]>;
|
|
472
|
+
export type PlatformOrgMembersGetData = z.infer<(typeof schemas)["platformOrgMembersGet"]["data"]>;
|
|
473
|
+
|
|
474
|
+
export async function platformOrgMembersGet(query: PlatformOrgMembersGetQuery): Promise<PlatformOrgMembersGetData> {
|
|
436
475
|
const client = ensureReq();
|
|
437
476
|
try {
|
|
438
|
-
const env = await client.get(`_platform/
|
|
477
|
+
const env = await client.get(`_platform/org/members`, { searchParams: query as Record<string, string | number | boolean> }).json<OjEnvelope<PlatformOrgMembersGetData>>();
|
|
439
478
|
// 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
|
|
440
479
|
if (typeof env.code === "number" && env.code !== 0)
|
|
441
480
|
throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
|
|
442
|
-
const data = env.data as
|
|
481
|
+
const data = env.data as PlatformOrgMembersGetData;
|
|
482
|
+
if (import.meta.env.DEV) {
|
|
483
|
+
const { schemas } = await import("./api.schemas");
|
|
484
|
+
const r = schemas["platformOrgMembersGet"].data.safeParse(data);
|
|
485
|
+
if (!r.success)
|
|
486
|
+
throw new ContractApiError(-1, `[契约违例] platformOrgMembersGet 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
|
|
487
|
+
}
|
|
443
488
|
return data;
|
|
444
489
|
}
|
|
445
490
|
catch (e) {
|
|
@@ -447,22 +492,22 @@ export async function platformSolutionsVerifyLastGet(): Promise<unknown> {
|
|
|
447
492
|
}
|
|
448
493
|
}
|
|
449
494
|
|
|
450
|
-
export type
|
|
451
|
-
export type
|
|
495
|
+
export type PlatformOrgPickerGetQuery = z.input<(typeof schemas)["platformOrgPickerGet"]["query"]>;
|
|
496
|
+
export type PlatformOrgPickerGetData = z.infer<(typeof schemas)["platformOrgPickerGet"]["data"]>;
|
|
452
497
|
|
|
453
|
-
export async function
|
|
498
|
+
export async function platformOrgPickerGet(query: PlatformOrgPickerGetQuery): Promise<PlatformOrgPickerGetData> {
|
|
454
499
|
const client = ensureReq();
|
|
455
500
|
try {
|
|
456
|
-
const env = await client.get(`_platform/org/
|
|
501
|
+
const env = await client.get(`_platform/org/picker`, { searchParams: query as Record<string, string | number | boolean> }).json<OjEnvelope<PlatformOrgPickerGetData>>();
|
|
457
502
|
// 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
|
|
458
503
|
if (typeof env.code === "number" && env.code !== 0)
|
|
459
504
|
throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
|
|
460
|
-
const data = env.data as
|
|
505
|
+
const data = env.data as PlatformOrgPickerGetData;
|
|
461
506
|
if (import.meta.env.DEV) {
|
|
462
507
|
const { schemas } = await import("./api.schemas");
|
|
463
|
-
const r = schemas["
|
|
508
|
+
const r = schemas["platformOrgPickerGet"].data.safeParse(data);
|
|
464
509
|
if (!r.success)
|
|
465
|
-
throw new ContractApiError(-1, `[契约违例]
|
|
510
|
+
throw new ContractApiError(-1, `[契约违例] platformOrgPickerGet 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
|
|
466
511
|
}
|
|
467
512
|
return data;
|
|
468
513
|
}
|
|
@@ -471,22 +516,23 @@ export async function platformOrgTreeGet(query: PlatformOrgTreeGetQuery): Promis
|
|
|
471
516
|
}
|
|
472
517
|
}
|
|
473
518
|
|
|
474
|
-
export type
|
|
475
|
-
export type
|
|
519
|
+
export type PlatformOrgResolvePostQuery = z.input<(typeof schemas)["platformOrgResolvePost"]["query"]>;
|
|
520
|
+
export type PlatformOrgResolvePostBody = z.input<(typeof schemas)["platformOrgResolvePost"]["body"]>;
|
|
521
|
+
export type PlatformOrgResolvePostData = z.infer<(typeof schemas)["platformOrgResolvePost"]["data"]>;
|
|
476
522
|
|
|
477
|
-
export async function
|
|
523
|
+
export async function platformOrgResolvePost(input: { query: PlatformOrgResolvePostQuery, body: PlatformOrgResolvePostBody }): Promise<PlatformOrgResolvePostData> {
|
|
478
524
|
const client = ensureReq();
|
|
479
525
|
try {
|
|
480
|
-
const env = await client.
|
|
526
|
+
const env = await client.post(`_platform/org/resolve`, { searchParams: input.query as Record<string, string | number | boolean>, json: input.body }).json<OjEnvelope<PlatformOrgResolvePostData>>();
|
|
481
527
|
// 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
|
|
482
528
|
if (typeof env.code === "number" && env.code !== 0)
|
|
483
529
|
throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
|
|
484
|
-
const data = env.data as
|
|
530
|
+
const data = env.data as PlatformOrgResolvePostData;
|
|
485
531
|
if (import.meta.env.DEV) {
|
|
486
532
|
const { schemas } = await import("./api.schemas");
|
|
487
|
-
const r = schemas["
|
|
533
|
+
const r = schemas["platformOrgResolvePost"].data.safeParse(data);
|
|
488
534
|
if (!r.success)
|
|
489
|
-
throw new ContractApiError(-1, `[契约违例]
|
|
535
|
+
throw new ContractApiError(-1, `[契约违例] platformOrgResolvePost 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
|
|
490
536
|
}
|
|
491
537
|
return data;
|
|
492
538
|
}
|
|
@@ -495,22 +541,22 @@ export async function platformOrgDepartmentsGet(query: PlatformOrgDepartmentsGet
|
|
|
495
541
|
}
|
|
496
542
|
}
|
|
497
543
|
|
|
498
|
-
export type
|
|
499
|
-
export type
|
|
544
|
+
export type PlatformOrgTreeGetQuery = z.input<(typeof schemas)["platformOrgTreeGet"]["query"]>;
|
|
545
|
+
export type PlatformOrgTreeGetData = z.infer<(typeof schemas)["platformOrgTreeGet"]["data"]>;
|
|
500
546
|
|
|
501
|
-
export async function
|
|
547
|
+
export async function platformOrgTreeGet(query: PlatformOrgTreeGetQuery): Promise<PlatformOrgTreeGetData> {
|
|
502
548
|
const client = ensureReq();
|
|
503
549
|
try {
|
|
504
|
-
const env = await client.get(`_platform/org/
|
|
550
|
+
const env = await client.get(`_platform/org/tree`, { searchParams: query as Record<string, string | number | boolean> }).json<OjEnvelope<PlatformOrgTreeGetData>>();
|
|
505
551
|
// 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
|
|
506
552
|
if (typeof env.code === "number" && env.code !== 0)
|
|
507
553
|
throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
|
|
508
|
-
const data = env.data as
|
|
554
|
+
const data = env.data as PlatformOrgTreeGetData;
|
|
509
555
|
if (import.meta.env.DEV) {
|
|
510
556
|
const { schemas } = await import("./api.schemas");
|
|
511
|
-
const r = schemas["
|
|
557
|
+
const r = schemas["platformOrgTreeGet"].data.safeParse(data);
|
|
512
558
|
if (!r.success)
|
|
513
|
-
throw new ContractApiError(-1, `[契约违例]
|
|
559
|
+
throw new ContractApiError(-1, `[契约违例] platformOrgTreeGet 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
|
|
514
560
|
}
|
|
515
561
|
return data;
|
|
516
562
|
}
|
|
@@ -543,22 +589,21 @@ export async function platformOrgUserGet(query: PlatformOrgUserGetQuery): Promis
|
|
|
543
589
|
}
|
|
544
590
|
}
|
|
545
591
|
|
|
546
|
-
export type
|
|
547
|
-
export type PlatformOrgPickerGetData = z.infer<(typeof schemas)["platformOrgPickerGet"]["data"]>;
|
|
592
|
+
export type PlatformSolutionsRoutesGetData = z.infer<(typeof schemas)["platformSolutionsRoutesGet"]["data"]>;
|
|
548
593
|
|
|
549
|
-
export async function
|
|
594
|
+
export async function platformSolutionsRoutesGet(): Promise<PlatformSolutionsRoutesGetData> {
|
|
550
595
|
const client = ensureReq();
|
|
551
596
|
try {
|
|
552
|
-
const env = await client.get(`_platform/
|
|
597
|
+
const env = await client.get(`_platform/solutions/routes`).json<OjEnvelope<PlatformSolutionsRoutesGetData>>();
|
|
553
598
|
// 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
|
|
554
599
|
if (typeof env.code === "number" && env.code !== 0)
|
|
555
600
|
throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
|
|
556
|
-
const data = env.data as
|
|
601
|
+
const data = env.data as PlatformSolutionsRoutesGetData;
|
|
557
602
|
if (import.meta.env.DEV) {
|
|
558
603
|
const { schemas } = await import("./api.schemas");
|
|
559
|
-
const r = schemas["
|
|
604
|
+
const r = schemas["platformSolutionsRoutesGet"].data.safeParse(data);
|
|
560
605
|
if (!r.success)
|
|
561
|
-
throw new ContractApiError(-1, `[契约违例]
|
|
606
|
+
throw new ContractApiError(-1, `[契约违例] platformSolutionsRoutesGet 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
|
|
562
607
|
}
|
|
563
608
|
return data;
|
|
564
609
|
}
|
|
@@ -567,23 +612,22 @@ export async function platformOrgPickerGet(query: PlatformOrgPickerGetQuery): Pr
|
|
|
567
612
|
}
|
|
568
613
|
}
|
|
569
614
|
|
|
570
|
-
export type
|
|
571
|
-
export type
|
|
572
|
-
export type PlatformOrgResolvePostData = z.infer<(typeof schemas)["platformOrgResolvePost"]["data"]>;
|
|
615
|
+
export type PlatformSolutionsVerifyPostQuery = z.input<(typeof schemas)["platformSolutionsVerifyPost"]["query"]>;
|
|
616
|
+
export type PlatformSolutionsVerifyPostData = z.infer<(typeof schemas)["platformSolutionsVerifyPost"]["data"]>;
|
|
573
617
|
|
|
574
|
-
export async function
|
|
618
|
+
export async function platformSolutionsVerifyPost(query: PlatformSolutionsVerifyPostQuery): Promise<PlatformSolutionsVerifyPostData> {
|
|
575
619
|
const client = ensureReq();
|
|
576
620
|
try {
|
|
577
|
-
const env = await client.post(`_platform/
|
|
621
|
+
const env = await client.post(`_platform/solutions/verify`, { searchParams: query as Record<string, string | number | boolean> }).json<OjEnvelope<PlatformSolutionsVerifyPostData>>();
|
|
578
622
|
// 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
|
|
579
623
|
if (typeof env.code === "number" && env.code !== 0)
|
|
580
624
|
throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
|
|
581
|
-
const data = env.data as
|
|
625
|
+
const data = env.data as PlatformSolutionsVerifyPostData;
|
|
582
626
|
if (import.meta.env.DEV) {
|
|
583
627
|
const { schemas } = await import("./api.schemas");
|
|
584
|
-
const r = schemas["
|
|
628
|
+
const r = schemas["platformSolutionsVerifyPost"].data.safeParse(data);
|
|
585
629
|
if (!r.success)
|
|
586
|
-
throw new ContractApiError(-1, `[契约违例]
|
|
630
|
+
throw new ContractApiError(-1, `[契约违例] platformSolutionsVerifyPost 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
|
|
587
631
|
}
|
|
588
632
|
return data;
|
|
589
633
|
}
|
|
@@ -592,22 +636,22 @@ export async function platformOrgResolvePost(input: { query: PlatformOrgResolveP
|
|
|
592
636
|
}
|
|
593
637
|
}
|
|
594
638
|
|
|
595
|
-
export type
|
|
596
|
-
export type
|
|
639
|
+
export type PlatformSolutionsVerifyLastGetQuery = z.input<(typeof schemas)["platformSolutionsVerifyLastGet"]["query"]>;
|
|
640
|
+
export type PlatformSolutionsVerifyLastGetData = z.infer<(typeof schemas)["platformSolutionsVerifyLastGet"]["data"]>;
|
|
597
641
|
|
|
598
|
-
export async function
|
|
642
|
+
export async function platformSolutionsVerifyLastGet(query: PlatformSolutionsVerifyLastGetQuery): Promise<PlatformSolutionsVerifyLastGetData> {
|
|
599
643
|
const client = ensureReq();
|
|
600
644
|
try {
|
|
601
|
-
const env = await client.get(`_platform/
|
|
645
|
+
const env = await client.get(`_platform/solutions/verify/last`, { searchParams: query as Record<string, string | number | boolean> }).json<OjEnvelope<PlatformSolutionsVerifyLastGetData>>();
|
|
602
646
|
// 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
|
|
603
647
|
if (typeof env.code === "number" && env.code !== 0)
|
|
604
648
|
throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
|
|
605
|
-
const data = env.data as
|
|
649
|
+
const data = env.data as PlatformSolutionsVerifyLastGetData;
|
|
606
650
|
if (import.meta.env.DEV) {
|
|
607
651
|
const { schemas } = await import("./api.schemas");
|
|
608
|
-
const r = schemas["
|
|
652
|
+
const r = schemas["platformSolutionsVerifyLastGet"].data.safeParse(data);
|
|
609
653
|
if (!r.success)
|
|
610
|
-
throw new ContractApiError(-1, `[契约违例]
|
|
654
|
+
throw new ContractApiError(-1, `[契约违例] platformSolutionsVerifyLastGet 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
|
|
611
655
|
}
|
|
612
656
|
return data;
|
|
613
657
|
}
|