sealos-cli 0.1.0 → 1.1.0
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/README.md +77 -76
- package/dist/bin/cli.cjs +5120 -775
- package/dist/bin/cli.mjs +5120 -775
- package/dist/main.cjs +5116 -775
- package/dist/main.mjs +5120 -775
- package/package.json +6 -5
- package/src/commands/app/index.ts +5 -4
- package/src/commands/database/index.ts +12 -12
- package/src/commands/devbox/index.ts +676 -183
- package/src/commands/quota/index.ts +4 -3
- package/src/commands/s3/index.ts +5 -5
- package/src/commands/template/index.ts +107 -41
- package/src/commands/workspace/index.ts +49 -39
- package/src/docs/database_openapi.json +21 -38
- package/src/docs/devbox_openapi.json +5760 -0
- package/src/docs/template_openapi.json +2661 -1
- package/src/generated/database.ts +1 -5
- package/src/generated/devbox.ts +2500 -0
- package/src/generated/template.ts +228 -0
- package/src/lib/api-client.ts +19 -1
- package/src/lib/auth.ts +17 -8
- package/src/lib/errors.ts +1 -1
- package/src/lib/output.ts +5 -6
- package/src/main.ts +4 -11
- package/src/types/index.ts +0 -12
- package/src/commands/config/index.ts +0 -54
- package/src/lib/api.ts +0 -83
- package/src/lib/config.ts +0 -134
|
@@ -3,16 +3,17 @@ import { handleError } from '../../lib/errors.ts'
|
|
|
3
3
|
|
|
4
4
|
export function createQuotaCommand (): Command {
|
|
5
5
|
const quotaCmd = new Command('quota')
|
|
6
|
-
.description('
|
|
6
|
+
.description('Future quota placeholder outside the v1 release surface')
|
|
7
7
|
|
|
8
|
-
//
|
|
8
|
+
// Future, non-v1 placeholder. Do not register this command until quota APIs
|
|
9
|
+
// are implemented and ready for release.
|
|
9
10
|
|
|
10
11
|
quotaCmd
|
|
11
12
|
.command('get')
|
|
12
13
|
.description('Get quota information')
|
|
13
14
|
.action(async () => {
|
|
14
15
|
try {
|
|
15
|
-
console.log('
|
|
16
|
+
console.log('Quota commands are not part of the v1 release surface yet.')
|
|
16
17
|
} catch (error) {
|
|
17
18
|
handleError(error)
|
|
18
19
|
}
|
package/src/commands/s3/index.ts
CHANGED
|
@@ -3,9 +3,10 @@ import { handleError } from '../../lib/errors.ts'
|
|
|
3
3
|
|
|
4
4
|
export function createS3Command (): Command {
|
|
5
5
|
const s3Cmd = new Command('s3')
|
|
6
|
-
.description('
|
|
6
|
+
.description('Future S3 placeholder outside the v1 release surface')
|
|
7
7
|
|
|
8
|
-
//
|
|
8
|
+
// Future, non-v1 placeholder. Do not register this command until the S3 API
|
|
9
|
+
// integration is implemented and ready for release.
|
|
9
10
|
// - upload
|
|
10
11
|
// - download
|
|
11
12
|
// - list
|
|
@@ -22,14 +23,13 @@ export function createS3Command (): Command {
|
|
|
22
23
|
.option('--acl <acl>', 'Access control: private, public-read')
|
|
23
24
|
.action(async (source, destination, options) => {
|
|
24
25
|
try {
|
|
25
|
-
console.log('
|
|
26
|
+
console.log('S3 commands are not part of the v1 release surface yet.', { source, destination, options })
|
|
26
27
|
} catch (error) {
|
|
27
28
|
handleError(error)
|
|
28
29
|
}
|
|
29
30
|
})
|
|
30
31
|
|
|
31
|
-
//
|
|
32
|
-
// 为了简洁,这里只实现 upload 作为示例
|
|
32
|
+
// This file is kept as a marker for future S3 work only.
|
|
33
33
|
|
|
34
34
|
return s3Cmd
|
|
35
35
|
}
|
|
@@ -16,6 +16,29 @@ interface TemplateDeployOptions {
|
|
|
16
16
|
|
|
17
17
|
export type TemplateDeployMode = 'catalog' | 'raw'
|
|
18
18
|
|
|
19
|
+
interface TemplateInstanceResource {
|
|
20
|
+
name: string
|
|
21
|
+
uid?: string
|
|
22
|
+
resourceType: string
|
|
23
|
+
quota?: {
|
|
24
|
+
cpu?: number
|
|
25
|
+
memory?: number
|
|
26
|
+
storage?: number
|
|
27
|
+
replicas?: number
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
interface TemplateInstanceResult {
|
|
32
|
+
name: string
|
|
33
|
+
uid?: string
|
|
34
|
+
displayName?: string
|
|
35
|
+
createdAt?: string
|
|
36
|
+
resourceType?: string
|
|
37
|
+
dryRun?: boolean
|
|
38
|
+
args?: Record<string, string>
|
|
39
|
+
resources?: TemplateInstanceResource[]
|
|
40
|
+
}
|
|
41
|
+
|
|
19
42
|
export function parseSetArgs (sets: string[]): Record<string, string> {
|
|
20
43
|
const args: Record<string, string> = {}
|
|
21
44
|
for (const s of sets) {
|
|
@@ -110,6 +133,56 @@ export function buildRawTemplateDeployBody (
|
|
|
110
133
|
return body
|
|
111
134
|
}
|
|
112
135
|
|
|
136
|
+
function formatValue (value: unknown): string {
|
|
137
|
+
if (value === undefined || value === null || value === '') return '-'
|
|
138
|
+
return String(value)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function printInstanceResult (instance: TemplateInstanceResult, options: { template?: string; raw?: boolean; dryRun?: boolean } = {}): void {
|
|
142
|
+
if (options.dryRun) {
|
|
143
|
+
console.log(chalk.dim(` Name: ${instance.name}`))
|
|
144
|
+
} else {
|
|
145
|
+
console.log(chalk.dim(` Name: ${instance.name}`))
|
|
146
|
+
if (instance.displayName) {
|
|
147
|
+
console.log(chalk.dim(` Display: ${instance.displayName}`))
|
|
148
|
+
}
|
|
149
|
+
if (instance.uid) {
|
|
150
|
+
console.log(chalk.dim(` UID: ${instance.uid}`))
|
|
151
|
+
}
|
|
152
|
+
if (instance.createdAt) {
|
|
153
|
+
console.log(chalk.dim(` Created: ${instance.createdAt}`))
|
|
154
|
+
}
|
|
155
|
+
if (options.template) {
|
|
156
|
+
console.log(chalk.dim(` Template:${options.template}`))
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const argEntries = Object.entries(instance.args ?? {})
|
|
161
|
+
if (argEntries.length > 0) {
|
|
162
|
+
console.log(chalk.dim('\n Arguments:'))
|
|
163
|
+
outputTable([
|
|
164
|
+
[chalk.bold('Name'), chalk.bold('Value')],
|
|
165
|
+
...argEntries.map(([key, value]) => [key, value])
|
|
166
|
+
])
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (instance.resources && instance.resources.length > 0) {
|
|
170
|
+
console.log(chalk.dim(options.dryRun ? '\n Resources that would be created:' : '\n Resources:'))
|
|
171
|
+
outputTable([
|
|
172
|
+
[chalk.bold('Name'), chalk.bold('Type'), chalk.bold('UID'), chalk.bold('CPU'), chalk.bold('Memory'), chalk.bold('Storage'), chalk.bold('Replicas')],
|
|
173
|
+
...instance.resources.map(resource => [
|
|
174
|
+
formatValue(resource.name),
|
|
175
|
+
formatValue(resource.resourceType),
|
|
176
|
+
formatValue(resource.uid),
|
|
177
|
+
resource.quota?.cpu != null ? `${resource.quota.cpu} vCPU` : '-',
|
|
178
|
+
resource.quota?.memory != null ? `${resource.quota.memory} GiB` : '-',
|
|
179
|
+
resource.quota?.storage != null ? `${resource.quota.storage} GiB` : '-',
|
|
180
|
+
formatValue(resource.quota?.replicas)
|
|
181
|
+
])
|
|
182
|
+
])
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
113
186
|
export function createTemplateCommand (): Command {
|
|
114
187
|
const tplCmd = new Command('template')
|
|
115
188
|
.alias('tpl')
|
|
@@ -135,26 +208,8 @@ export function createTemplateCommand (): Command {
|
|
|
135
208
|
|
|
136
209
|
if (error) throw mapApiError(response.status, error as ApiErrorBody)
|
|
137
210
|
|
|
138
|
-
ctx.spinner.succeed(`Instance "${data.name}" created successfully
|
|
139
|
-
|
|
140
|
-
console.log(chalk.dim(` Created: ${data.createdAt}`))
|
|
141
|
-
|
|
142
|
-
if (data.resources && data.resources.length > 0) {
|
|
143
|
-
console.log(chalk.dim('\n Resources:'))
|
|
144
|
-
const rows: string[][] = [
|
|
145
|
-
[chalk.bold('Name'), chalk.bold('Type'), chalk.bold('CPU'), chalk.bold('Memory'), chalk.bold('Storage')]
|
|
146
|
-
]
|
|
147
|
-
for (const r of data.resources) {
|
|
148
|
-
rows.push([
|
|
149
|
-
r.name,
|
|
150
|
-
r.resourceType,
|
|
151
|
-
r.quota?.cpu != null ? `${r.quota.cpu} vCPU` : '-',
|
|
152
|
-
r.quota?.memory != null ? `${r.quota.memory} GiB` : '-',
|
|
153
|
-
r.quota?.storage != null ? `${r.quota.storage} GiB` : '-'
|
|
154
|
-
])
|
|
155
|
-
}
|
|
156
|
-
outputTable(rows)
|
|
157
|
-
}
|
|
211
|
+
ctx.spinner.succeed(`Instance "${data.name}" created successfully`)
|
|
212
|
+
printInstanceResult(data, { template: catalogTemplate })
|
|
158
213
|
return
|
|
159
214
|
}
|
|
160
215
|
|
|
@@ -171,23 +226,12 @@ export function createTemplateCommand (): Command {
|
|
|
171
226
|
|
|
172
227
|
if (deployOptions.dryRun) {
|
|
173
228
|
ctx.spinner.succeed('Raw template validation passed; no resources were created')
|
|
174
|
-
|
|
175
|
-
if (data.resources && data.resources.length > 0) {
|
|
176
|
-
console.log(chalk.dim('\n Resources that would be created:'))
|
|
177
|
-
for (const r of data.resources) {
|
|
178
|
-
console.log(chalk.dim(` - ${r.resourceType}: ${r.name}`))
|
|
179
|
-
}
|
|
180
|
-
}
|
|
229
|
+
printInstanceResult(data, { raw: true, dryRun: true })
|
|
181
230
|
return
|
|
182
231
|
}
|
|
183
232
|
|
|
184
233
|
ctx.spinner.succeed(`Raw template deployed as "${data.name}"`)
|
|
185
|
-
|
|
186
|
-
console.log(chalk.dim(` UID: ${data.uid}`))
|
|
187
|
-
}
|
|
188
|
-
if ('createdAt' in data) {
|
|
189
|
-
console.log(chalk.dim(` Created: ${data.createdAt}`))
|
|
190
|
-
}
|
|
234
|
+
printInstanceResult(data, { raw: true })
|
|
191
235
|
})
|
|
192
236
|
|
|
193
237
|
// ── list ─────────────────────────────────────────────────────────
|
|
@@ -195,11 +239,12 @@ export function createTemplateCommand (): Command {
|
|
|
195
239
|
.command('list')
|
|
196
240
|
.description('List available templates')
|
|
197
241
|
.option('-c, --category <category>', 'Filter by category')
|
|
242
|
+
.option('-l, --language <language>', 'Language code (for example: en, zh)')
|
|
198
243
|
.option('-o, --output <format>', 'Output format (json|table)', 'table')
|
|
199
|
-
.action(withErrorHandling({ spinnerText: 'Loading templates...' }, async (ctx, options: { category?: string; output: string }) => {
|
|
244
|
+
.action(withErrorHandling({ spinnerText: 'Loading templates...' }, async (ctx, options: { category?: string; language?: string; output: string }) => {
|
|
200
245
|
const client = createTemplateClient()
|
|
201
246
|
const { data, error, response } = await client.GET('/templates', {
|
|
202
|
-
params: { query: {} }
|
|
247
|
+
params: { query: options.language ? { language: options.language } : {} }
|
|
203
248
|
})
|
|
204
249
|
|
|
205
250
|
if (error) throw mapApiError(response.status, error as ApiErrorBody)
|
|
@@ -235,12 +280,14 @@ export function createTemplateCommand (): Command {
|
|
|
235
280
|
.command('get <name>')
|
|
236
281
|
.alias('describe')
|
|
237
282
|
.description('Get template details')
|
|
283
|
+
.option('-l, --language <language>', 'Language code (for example: en, zh)')
|
|
238
284
|
.option('-o, --output <format>', 'Output format (json|table)', 'table')
|
|
239
|
-
.action(withErrorHandling({ spinnerText: 'Loading template...' }, async (ctx, name: string, options: { output: string }) => {
|
|
285
|
+
.action(withErrorHandling({ spinnerText: 'Loading template...' }, async (ctx, name: string, options: { language?: string; output: string }) => {
|
|
240
286
|
const client = createTemplateClient()
|
|
241
287
|
const { data, error, response } = await client.GET('/templates/{name}', {
|
|
242
288
|
params: {
|
|
243
|
-
path: { name }
|
|
289
|
+
path: { name },
|
|
290
|
+
query: options.language ? { language: options.language } : {}
|
|
244
291
|
}
|
|
245
292
|
})
|
|
246
293
|
|
|
@@ -286,6 +333,25 @@ export function createTemplateCommand (): Command {
|
|
|
286
333
|
}
|
|
287
334
|
}))
|
|
288
335
|
|
|
336
|
+
// -- delete --------------------------------------------------------
|
|
337
|
+
tplCmd
|
|
338
|
+
.command('delete <instance>')
|
|
339
|
+
.alias('rm')
|
|
340
|
+
.description('Delete a deployed template instance')
|
|
341
|
+
.action(withAuth({ spinnerText: 'Deleting template instance...' }, async (ctx, instance: string) => {
|
|
342
|
+
const client = createTemplateClient()
|
|
343
|
+
const { error, response } = await client.DELETE('/templates/instances/{instanceName}', {
|
|
344
|
+
headers: ctx.auth,
|
|
345
|
+
params: {
|
|
346
|
+
path: { instanceName: instance }
|
|
347
|
+
}
|
|
348
|
+
})
|
|
349
|
+
|
|
350
|
+
if (error) throw mapApiError(response.status, error as ApiErrorBody)
|
|
351
|
+
|
|
352
|
+
ctx.spinner.succeed(`Instance "${instance}" deleted`)
|
|
353
|
+
}))
|
|
354
|
+
|
|
289
355
|
// ── deploy ──────────────────────────────────────────────────────
|
|
290
356
|
tplCmd
|
|
291
357
|
.command('deploy [template]')
|
|
@@ -298,12 +364,12 @@ export function createTemplateCommand (): Command {
|
|
|
298
364
|
.addHelpText('after', `
|
|
299
365
|
Examples:
|
|
300
366
|
Catalog:
|
|
301
|
-
sealos template deploy perplexica --name my-app --set OPENAI_API_KEY=xxx
|
|
367
|
+
sealos-cli template deploy perplexica --name my-app --set OPENAI_API_KEY=xxx
|
|
302
368
|
|
|
303
369
|
Raw:
|
|
304
|
-
sealos template deploy --file ./template.yaml --dry-run
|
|
305
|
-
sealos template deploy --yaml 'apiVersion: app.sealos.io/v1\nkind: Template\n...'
|
|
306
|
-
cat template.yaml | sealos template deploy --dry-run
|
|
370
|
+
sealos-cli template deploy --file ./template.yaml --dry-run
|
|
371
|
+
sealos-cli template deploy --yaml 'apiVersion: app.sealos.io/v1\nkind: Template\n...'
|
|
372
|
+
cat template.yaml | sealos-cli template deploy --dry-run
|
|
307
373
|
`)
|
|
308
374
|
.action(async (template: string | undefined, options: TemplateDeployOptions) => {
|
|
309
375
|
const mode = resolveTemplateDeployMode(template, options)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Command } from 'commander'
|
|
2
|
-
import {
|
|
3
|
-
import { success,
|
|
2
|
+
import { getAuthInfo, listWorkspaces, switchWorkspace } from '../../lib/auth.ts'
|
|
3
|
+
import { success, outputJson, outputTable } from '../../lib/output.ts'
|
|
4
4
|
import { handleError, AuthError } from '../../lib/errors.ts'
|
|
5
5
|
|
|
6
6
|
export function createWorkspaceCommand (): Command {
|
|
@@ -8,73 +8,83 @@ export function createWorkspaceCommand (): Command {
|
|
|
8
8
|
.alias('ws')
|
|
9
9
|
.description('Manage workspaces')
|
|
10
10
|
|
|
11
|
-
// workspace switch
|
|
12
11
|
workspaceCmd
|
|
13
12
|
.command('switch')
|
|
14
13
|
.description('Switch to another workspace')
|
|
15
|
-
.argument('<
|
|
16
|
-
.
|
|
14
|
+
.argument('<namespace>', 'Workspace id, uid, or team name')
|
|
15
|
+
.option('-o, --output <format>', 'Output format: json, table', 'table')
|
|
16
|
+
.action(async (namespace, options) => {
|
|
17
17
|
try {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
// 更新配置
|
|
23
|
-
const context = getCurrentContext()
|
|
24
|
-
if (context) {
|
|
25
|
-
context.workspace = name
|
|
26
|
-
// TODO: 更新到配置文件
|
|
18
|
+
const result = await switchWorkspace(namespace)
|
|
19
|
+
if (options.output === 'json') {
|
|
20
|
+
outputJson(result)
|
|
21
|
+
return
|
|
27
22
|
}
|
|
28
23
|
|
|
29
|
-
success(`Switched to workspace: ${
|
|
24
|
+
success(`Switched to workspace: ${result.workspace.id || result.workspace.uid || namespace}`)
|
|
30
25
|
} catch (error) {
|
|
31
26
|
handleError(error)
|
|
32
27
|
}
|
|
33
28
|
})
|
|
34
29
|
|
|
35
|
-
// workspace list
|
|
36
30
|
workspaceCmd
|
|
37
31
|
.command('list')
|
|
38
32
|
.description('List all workspaces')
|
|
39
|
-
.
|
|
33
|
+
.option('-o, --output <format>', 'Output format: json, table', 'table')
|
|
34
|
+
.action(async (options) => {
|
|
40
35
|
try {
|
|
41
|
-
const
|
|
42
|
-
if (
|
|
43
|
-
|
|
36
|
+
const result = await listWorkspaces()
|
|
37
|
+
if (options.output === 'json') {
|
|
38
|
+
outputJson(result)
|
|
39
|
+
return
|
|
44
40
|
}
|
|
45
41
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
42
|
+
outputTable([
|
|
43
|
+
['UID', 'ID', 'TEAM', 'ROLE', 'TYPE', 'CURRENT'],
|
|
44
|
+
...result.workspaces.map(workspace => [
|
|
45
|
+
workspace.uid || '',
|
|
46
|
+
workspace.id || '',
|
|
47
|
+
workspace.teamName || '',
|
|
48
|
+
workspace.role || '',
|
|
49
|
+
workspace.nstype || '',
|
|
50
|
+
workspace.id === result.current ? '*' : ''
|
|
51
|
+
])
|
|
52
|
+
])
|
|
55
53
|
} catch (error) {
|
|
56
54
|
handleError(error)
|
|
57
55
|
}
|
|
58
56
|
})
|
|
59
57
|
|
|
60
|
-
// workspace current
|
|
61
58
|
workspaceCmd
|
|
62
59
|
.command('current')
|
|
63
60
|
.description('Show current workspace')
|
|
64
|
-
.
|
|
61
|
+
.option('-o, --output <format>', 'Output format: json, table', 'table')
|
|
62
|
+
.action(async (options) => {
|
|
65
63
|
try {
|
|
66
|
-
const
|
|
67
|
-
if (!
|
|
64
|
+
const authInfo = getAuthInfo()
|
|
65
|
+
if (!authInfo.authenticated) {
|
|
68
66
|
throw new AuthError()
|
|
69
67
|
}
|
|
70
68
|
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
69
|
+
const workspace = authInfo.current_workspace || null
|
|
70
|
+
const result = {
|
|
71
|
+
workspace,
|
|
72
|
+
region: authInfo.region || 'unknown',
|
|
73
|
+
kubeconfig_path: authInfo.kubeconfig_path || 'unknown'
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (options.output === 'json') {
|
|
77
|
+
outputJson(result)
|
|
78
|
+
return
|
|
79
|
+
}
|
|
76
80
|
|
|
77
|
-
outputTable(
|
|
81
|
+
outputTable([
|
|
82
|
+
['Field', 'Value'],
|
|
83
|
+
['Workspace', workspace?.id || authInfo.workspace || 'unknown'],
|
|
84
|
+
['Team', workspace?.teamName || 'unknown'],
|
|
85
|
+
['Region', authInfo.region || 'unknown'],
|
|
86
|
+
['Kubeconfig', authInfo.kubeconfig_path || 'unknown']
|
|
87
|
+
])
|
|
78
88
|
} catch (error) {
|
|
79
89
|
handleError(error)
|
|
80
90
|
}
|
|
@@ -6889,46 +6889,29 @@
|
|
|
6889
6889
|
"application/json": {
|
|
6890
6890
|
"schema": {
|
|
6891
6891
|
"type": "object",
|
|
6892
|
-
"
|
|
6893
|
-
"
|
|
6894
|
-
|
|
6895
|
-
|
|
6896
|
-
|
|
6892
|
+
"propertyNames": {
|
|
6893
|
+
"type": "string",
|
|
6894
|
+
"enum": [
|
|
6895
|
+
"postgresql",
|
|
6896
|
+
"mongodb",
|
|
6897
|
+
"apecloud-mysql",
|
|
6898
|
+
"mysql",
|
|
6899
|
+
"redis",
|
|
6900
|
+
"kafka",
|
|
6901
|
+
"qdrant",
|
|
6902
|
+
"nebula",
|
|
6903
|
+
"weaviate",
|
|
6904
|
+
"milvus",
|
|
6905
|
+
"pulsar",
|
|
6906
|
+
"clickhouse"
|
|
6907
|
+
]
|
|
6908
|
+
},
|
|
6909
|
+
"additionalProperties": {
|
|
6910
|
+
"type": "array",
|
|
6911
|
+
"items": {
|
|
6897
6912
|
"type": "string"
|
|
6898
|
-
},
|
|
6899
|
-
"data": {
|
|
6900
|
-
"type": "object",
|
|
6901
|
-
"propertyNames": {
|
|
6902
|
-
"type": "string",
|
|
6903
|
-
"enum": [
|
|
6904
|
-
"postgresql",
|
|
6905
|
-
"mongodb",
|
|
6906
|
-
"apecloud-mysql",
|
|
6907
|
-
"mysql",
|
|
6908
|
-
"redis",
|
|
6909
|
-
"kafka",
|
|
6910
|
-
"qdrant",
|
|
6911
|
-
"nebula",
|
|
6912
|
-
"weaviate",
|
|
6913
|
-
"milvus",
|
|
6914
|
-
"pulsar",
|
|
6915
|
-
"clickhouse"
|
|
6916
|
-
]
|
|
6917
|
-
},
|
|
6918
|
-
"additionalProperties": {
|
|
6919
|
-
"type": "array",
|
|
6920
|
-
"items": {
|
|
6921
|
-
"type": "string"
|
|
6922
|
-
}
|
|
6923
|
-
}
|
|
6924
6913
|
}
|
|
6925
|
-
}
|
|
6926
|
-
"required": [
|
|
6927
|
-
"code",
|
|
6928
|
-
"message",
|
|
6929
|
-
"data"
|
|
6930
|
-
],
|
|
6931
|
-
"additionalProperties": false
|
|
6914
|
+
}
|
|
6932
6915
|
}
|
|
6933
6916
|
}
|
|
6934
6917
|
}
|