@qoder-ai/qmind-cli 3.0.0 → 3.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/CHANGELOG.md +10 -0
- package/CHANGELOG.zh-CN.md +10 -0
- package/README.md +12 -13
- package/README.zh-CN.md +12 -13
- package/dist/bot-gateway-Hzjl50zu.js +373 -0
- package/dist/cards-DsMbd-g1.js +132 -0
- package/dist/{imports-Da88W09Q.js → imports-B01ERZgD.js} +3 -3
- package/dist/{management-xYuUDFtg.js → management-BIYQa9Al.js} +5 -4
- package/dist/notes-BvucEfdi.js +128 -0
- package/dist/qmind.js +163 -362
- package/dist/{shared-DwycozMA.js → shared-BkQJzIZF.js} +14 -6
- package/dist/source-upload-DBm1Hyki.js +17 -0
- package/dist/transfers-F1ZLLBdU.js +237 -0
- package/package.json +3 -3
- package/dist/cards-2J6ebaI0.js +0 -75
|
@@ -566,6 +566,7 @@ const sourceListSchema = z.object({
|
|
|
566
566
|
});
|
|
567
567
|
const sourceTreeNodeSchema = z.lazy(() => z.object({
|
|
568
568
|
files: z.array(sourceTreeNodeSchema).default([]),
|
|
569
|
+
hasChildren: z.boolean().optional(),
|
|
569
570
|
id: z.string().min(1),
|
|
570
571
|
name: z.string().default(""),
|
|
571
572
|
path: z.string().default(""),
|
|
@@ -666,11 +667,12 @@ const sourcePreviewSchema = z.preprocess((value) => isRecord(value) ? {
|
|
|
666
667
|
url: httpsUrlSchema
|
|
667
668
|
}));
|
|
668
669
|
/** proto3 JSON serializes the token timeout and version as int64, so both arrive either way. */
|
|
670
|
+
const officeTokenIntegerSchema = z.union([z.number(), z.string().regex(/^\d+$/).transform(Number)]).pipe(z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER));
|
|
669
671
|
const webOfficeTokenFields = {
|
|
670
672
|
accessToken: z.string().min(1),
|
|
671
673
|
accessTokenExpiresAt: timestampSchema.optional(),
|
|
672
|
-
tokenTimeoutMs:
|
|
673
|
-
tokenVersion:
|
|
674
|
+
tokenTimeoutMs: officeTokenIntegerSchema.refine((value) => value > 0),
|
|
675
|
+
tokenVersion: officeTokenIntegerSchema
|
|
674
676
|
};
|
|
675
677
|
function webOfficeTokenAliases(value) {
|
|
676
678
|
return isRecord(value) ? {
|
|
@@ -693,11 +695,11 @@ const sourceWebOfficeSessionSchema = z.preprocess((value) => {
|
|
|
693
695
|
} : aliased;
|
|
694
696
|
}, z.object({
|
|
695
697
|
...webOfficeTokenFields,
|
|
696
|
-
readOnly: z.
|
|
698
|
+
readOnly: z.literal(true),
|
|
697
699
|
reused: z.boolean().default(false),
|
|
698
700
|
sessionId: z.string().min(1),
|
|
699
|
-
sourceFormat: z.string().
|
|
700
|
-
sourceId: z.string().
|
|
701
|
+
sourceFormat: z.string().min(1).transform((value) => value.trim().toLowerCase().replace(/^\./, "")).pipe(z.string().min(1)),
|
|
702
|
+
sourceId: z.string().min(1),
|
|
701
703
|
webOfficeUrl: httpsUrlSchema
|
|
702
704
|
}));
|
|
703
705
|
const sourceWebOfficeTokenSchema = z.preprocess(webOfficeTokenAliases, z.object(webOfficeTokenFields));
|
|
@@ -1038,6 +1040,12 @@ function optionalString(value, field) {
|
|
|
1038
1040
|
if (typeof value !== "string") throw invalidArgument(`${field} must be a string`, field);
|
|
1039
1041
|
return value;
|
|
1040
1042
|
}
|
|
1043
|
+
/** Validate body text without trimming meaningful Markdown indentation or trailing newlines. */
|
|
1044
|
+
function requiredText(value, field) {
|
|
1045
|
+
const text = optionalString(value, field);
|
|
1046
|
+
if (text === void 0 || text.trim().length === 0) throw invalidArgument(`${field} must be a non-empty string`, field);
|
|
1047
|
+
return text;
|
|
1048
|
+
}
|
|
1041
1049
|
function optionalTrimmedString(value, field) {
|
|
1042
1050
|
const string = optionalString(value, field)?.trim();
|
|
1043
1051
|
return string === "" ? void 0 : string;
|
|
@@ -1144,4 +1152,4 @@ function call(context, options) {
|
|
|
1144
1152
|
});
|
|
1145
1153
|
}
|
|
1146
1154
|
//#endregion
|
|
1147
|
-
export {
|
|
1155
|
+
export { QMIND_SOURCE_UPLOAD_MAX_BYTES as $, notebookSchema as A, sourceSchema as B, chatMessageListSchema as C, imageUrlsSchema as D, imageUploadTicketSchema as E, sourceContentSchema as F, sourceWebOfficeTokenSchema as G, sourceUploadCapabilitiesSchema as H, sourceImportResultsSchema as I, taskRunSchema as J, streamWireEventSchema as K, sourceListSchema as L, sharedNotebookListSchema as M, sourceActionAccessSchema as N, importProvidersSchema as O, sourceChildrenCountsSchema as P, QMIND_MULTIPART_UPLOAD_MAX_BYTES as Q, sourcePreviewSchema as R, cardSchema as S, chatSessionSchema as T, sourceUploadTicketSchema as U, sourceTreeSchema as V, sourceWebOfficeSessionSchema as W, voidResponseSchema as X, timestampSchema as Y, wikiBranchListSchema as Z, aliDingImportRunItemListSchema as _, invalidArgument as a, cancelQuestionResultSchema as b, optionalRecord as c, pagination as d, assertCapability as et, positiveInteger as f, stringList as g, requiredText as h, httpUrl as i, retrieveResultSchema as j, notebookListSchema as k, optionalString as l, requiredString as m, call as n, executeUnary as nt, nonNegativeInteger as o, queryPath as p, taskRunListSchema as q, compactUndefined as r, QMindError as rt, optionalBoolean as s, assertNonEmptyPatch as t, executeStream as tt, optionalTrimmedString as u, aliDingImportRunSchema as v, chatSessionListSchema as w, cardListSchema as x, batchMutationResultSchema as y, sourceRawContentSchema as z };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { H as sourceUploadCapabilitiesSchema, m as requiredString, n as call } from "./shared-BkQJzIZF.js";
|
|
2
|
+
//#region ../sdk/src/operations/source-upload.ts
|
|
3
|
+
/** Notebook-scoped edit preflight, not the deployment-level capabilities lookup. */
|
|
4
|
+
async function preflightSourceUpload(context, notebookId, options) {
|
|
5
|
+
const notebook = requiredString(notebookId, "notebookId");
|
|
6
|
+
return call(context, {
|
|
7
|
+
callOptions: options,
|
|
8
|
+
capability: "transfers",
|
|
9
|
+
idempotent: true,
|
|
10
|
+
method: "GET",
|
|
11
|
+
operation: "sources.uploadPreflight",
|
|
12
|
+
path: context.profile.apiPath("notebooks", notebook, "sources", "upload", "capabilities"),
|
|
13
|
+
schema: sourceUploadCapabilitiesSchema
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
export { preflightSourceUpload as t };
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { $ as QMIND_SOURCE_UPLOAD_MAX_BYTES, B as sourceSchema, E as imageUploadTicketSchema, Q as QMIND_MULTIPART_UPLOAD_MAX_BYTES, U as sourceUploadTicketSchema, X as voidResponseSchema, a as invalidArgument, l as optionalString, m as requiredString, nt as executeUnary, p as queryPath, r as compactUndefined, rt as QMindError, u as optionalTrimmedString } from "./shared-BkQJzIZF.js";
|
|
2
|
+
import { t as preflightSourceUpload } from "./source-upload-DBm1Hyki.js";
|
|
3
|
+
//#region ../sdk/src/operations/transfers.ts
|
|
4
|
+
function isRecord(value) {
|
|
5
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6
|
+
}
|
|
7
|
+
function binarySource(value) {
|
|
8
|
+
if (!isRecord(value)) throw invalidArgument("source must be a QMindBinarySource", "source");
|
|
9
|
+
const filename = requiredString(value.filename, "source.filename");
|
|
10
|
+
const mimeType = requiredString(value.mimeType, "source.mimeType");
|
|
11
|
+
const size = value.size;
|
|
12
|
+
if (typeof size !== "number" || !Number.isSafeInteger(size) || size <= 0) throw invalidArgument("source.size must be a positive safe integer", "source.size");
|
|
13
|
+
if (typeof value.open !== "function") throw invalidArgument("source.open must be a function", "source.open");
|
|
14
|
+
const source = value;
|
|
15
|
+
return {
|
|
16
|
+
filename,
|
|
17
|
+
mimeType,
|
|
18
|
+
open: () => source.open(),
|
|
19
|
+
size
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function transferOptions(options) {
|
|
23
|
+
if (options === void 0) return {};
|
|
24
|
+
if (!isRecord(options)) throw invalidArgument("options must be an object", "options");
|
|
25
|
+
if (options.onProgress !== void 0 && typeof options.onProgress !== "function") throw invalidArgument("onProgress must be a function", "onProgress");
|
|
26
|
+
return options;
|
|
27
|
+
}
|
|
28
|
+
function uploadMetadata(value) {
|
|
29
|
+
if (value === void 0) return {};
|
|
30
|
+
if (!isRecord(value)) throw invalidArgument("metadata must be an object", "metadata");
|
|
31
|
+
return {
|
|
32
|
+
parentSourceId: optionalString(value.parentSourceId, "parentSourceId"),
|
|
33
|
+
path: optionalString(value.path, "path"),
|
|
34
|
+
sha256: optionalTrimmedString(value.sha256, "sha256"),
|
|
35
|
+
sourceType: optionalTrimmedString(value.sourceType, "sourceType"),
|
|
36
|
+
title: optionalTrimmedString(value.title, "title")
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function progressReporter(context, operation, strategy, totalBytes, options) {
|
|
40
|
+
let lastUploadedBytes = 0;
|
|
41
|
+
const notify = (phase, uploadedBytes) => {
|
|
42
|
+
if (!Number.isSafeInteger(uploadedBytes) || uploadedBytes < lastUploadedBytes) throw new QMindError("HOST_POLICY_ERROR", "upload progress must be a monotonic integer", {
|
|
43
|
+
access: context.profile.access,
|
|
44
|
+
details: {
|
|
45
|
+
lastUploadedBytes,
|
|
46
|
+
totalBytes,
|
|
47
|
+
uploadedBytes
|
|
48
|
+
},
|
|
49
|
+
operation
|
|
50
|
+
});
|
|
51
|
+
if (uploadedBytes > totalBytes) throw new QMindError("HOST_POLICY_ERROR", "upload progress exceeds source size", {
|
|
52
|
+
access: context.profile.access,
|
|
53
|
+
details: {
|
|
54
|
+
totalBytes,
|
|
55
|
+
uploadedBytes
|
|
56
|
+
},
|
|
57
|
+
operation
|
|
58
|
+
});
|
|
59
|
+
lastUploadedBytes = uploadedBytes;
|
|
60
|
+
const progress = {
|
|
61
|
+
phase,
|
|
62
|
+
strategy,
|
|
63
|
+
totalBytes,
|
|
64
|
+
uploadedBytes
|
|
65
|
+
};
|
|
66
|
+
options.onProgress?.(progress);
|
|
67
|
+
};
|
|
68
|
+
return {
|
|
69
|
+
complete: () => notify("uploading", totalBytes),
|
|
70
|
+
registering: () => notify("registering", totalBytes),
|
|
71
|
+
start: () => notify("uploading", 0),
|
|
72
|
+
update: (uploadedBytes) => notify("uploading", uploadedBytes)
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function requestOptions(options) {
|
|
76
|
+
return {
|
|
77
|
+
...options.signal === void 0 ? {} : { signal: options.signal },
|
|
78
|
+
...options.timeoutMs === void 0 ? {} : { timeoutMs: options.timeoutMs }
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function transferCall(context, operation, request, schema) {
|
|
82
|
+
return executeUnary({
|
|
83
|
+
capability: operation.startsWith("images.") ? "images.presignUpload" : "transfers",
|
|
84
|
+
operation,
|
|
85
|
+
profile: context.profile,
|
|
86
|
+
request,
|
|
87
|
+
schema,
|
|
88
|
+
transport: context.transport
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
function hostRequest(path, method, idempotent, options, body) {
|
|
92
|
+
const authorization = options.authorization?.trim();
|
|
93
|
+
return {
|
|
94
|
+
body,
|
|
95
|
+
destination: {
|
|
96
|
+
kind: "host",
|
|
97
|
+
path
|
|
98
|
+
},
|
|
99
|
+
...authorization === void 0 || authorization.length === 0 ? {} : { headers: { authorization: `Bearer ${authorization}` } },
|
|
100
|
+
idempotent,
|
|
101
|
+
method,
|
|
102
|
+
...requestOptions(options)
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
function signedUploadRequest(ticket, source, progress, options) {
|
|
106
|
+
return {
|
|
107
|
+
body: {
|
|
108
|
+
kind: "binary",
|
|
109
|
+
onProgress: progress.update,
|
|
110
|
+
source
|
|
111
|
+
},
|
|
112
|
+
destination: {
|
|
113
|
+
kind: "signed",
|
|
114
|
+
url: ticket.uploadUrl
|
|
115
|
+
},
|
|
116
|
+
headers: ticket.headers,
|
|
117
|
+
idempotent: true,
|
|
118
|
+
method: "PUT",
|
|
119
|
+
...requestOptions(options)
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function selectSourceUploadStrategy(source, capabilities) {
|
|
123
|
+
const methods = capabilities.uploadMethods.filter(({ available, method, maxSizeBytes }) => available && maxSizeBytes > 0 && (method === "multipart" || method === "presign"));
|
|
124
|
+
if (methods.length === 0) throw new QMindError("UNSUPPORTED_OPERATION", "source upload is unavailable", {
|
|
125
|
+
details: { reason: "upload-unavailable" },
|
|
126
|
+
operation: "sources.uploadPreflight"
|
|
127
|
+
});
|
|
128
|
+
const filename = source.filename.toLowerCase();
|
|
129
|
+
const matching = methods.filter(({ supportedExtensions }) => supportedExtensions.some((extension) => filename.endsWith(extension.toLowerCase())));
|
|
130
|
+
if (matching.length === 0) throw new QMindError("INVALID_ARGUMENT", "file extension is not supported for upload", {
|
|
131
|
+
details: { reason: "unsupported-extension" },
|
|
132
|
+
operation: "sources.uploadPreflight"
|
|
133
|
+
});
|
|
134
|
+
const limit = (method) => Math.min(method.maxSizeBytes, method.method === "multipart" ? QMIND_MULTIPART_UPLOAD_MAX_BYTES : QMIND_SOURCE_UPLOAD_MAX_BYTES);
|
|
135
|
+
if (matching.find((method) => method.method === "multipart" && source.size <= limit(method))) return "multipart";
|
|
136
|
+
if (matching.some((method) => method.method === "presign" && source.size <= limit(method))) return "presigned";
|
|
137
|
+
throw new QMindError("FILE_TOO_LARGE", "file exceeds the available upload size limit", {
|
|
138
|
+
details: {
|
|
139
|
+
limitBytes: Math.max(...matching.map(limit)),
|
|
140
|
+
size: source.size
|
|
141
|
+
},
|
|
142
|
+
operation: "sources.uploadPreflight"
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
function createTransferOperations(context) {
|
|
146
|
+
return {
|
|
147
|
+
async uploadImage(notebookId, sourceId, rawSource, rawOptions) {
|
|
148
|
+
const notebook = requiredString(notebookId, "notebookId");
|
|
149
|
+
const sourceIdValue = requiredString(sourceId, "sourceId");
|
|
150
|
+
const source = binarySource(rawSource);
|
|
151
|
+
const options = transferOptions(rawOptions);
|
|
152
|
+
if (source.size > 52428800) throw new QMindError("FILE_TOO_LARGE", "image exceeds the 50 MiB upload limit", {
|
|
153
|
+
access: context.profile.access,
|
|
154
|
+
details: {
|
|
155
|
+
limitBytes: QMIND_MULTIPART_UPLOAD_MAX_BYTES,
|
|
156
|
+
size: source.size
|
|
157
|
+
},
|
|
158
|
+
operation: "images.upload"
|
|
159
|
+
});
|
|
160
|
+
const ticket = await transferCall(context, "images.presignUpload", hostRequest(context.profile.apiPath("notebooks", notebook, "sources", sourceIdValue, "images", "presign"), "POST", false, options, {
|
|
161
|
+
kind: "json",
|
|
162
|
+
value: {
|
|
163
|
+
filename: source.filename,
|
|
164
|
+
mimeType: source.mimeType,
|
|
165
|
+
size: source.size
|
|
166
|
+
}
|
|
167
|
+
}), imageUploadTicketSchema);
|
|
168
|
+
const progress = progressReporter(context, "images.upload", "presigned", source.size, options);
|
|
169
|
+
progress.start();
|
|
170
|
+
await transferCall(context, "images.upload", signedUploadRequest(ticket, source, progress, options), voidResponseSchema);
|
|
171
|
+
progress.complete();
|
|
172
|
+
return ticket;
|
|
173
|
+
},
|
|
174
|
+
async uploadSource(notebookId, rawSource, rawMetadata, rawOptions) {
|
|
175
|
+
const notebook = requiredString(notebookId, "notebookId");
|
|
176
|
+
const source = binarySource(rawSource);
|
|
177
|
+
const metadata = uploadMetadata(rawMetadata);
|
|
178
|
+
const options = transferOptions(rawOptions);
|
|
179
|
+
if (source.size > 524288e3) throw new QMindError("FILE_TOO_LARGE", "file exceeds the 500 MiB upload limit", {
|
|
180
|
+
access: context.profile.access,
|
|
181
|
+
details: {
|
|
182
|
+
limitBytes: QMIND_SOURCE_UPLOAD_MAX_BYTES,
|
|
183
|
+
size: source.size
|
|
184
|
+
},
|
|
185
|
+
operation: "transfers.source.multipart"
|
|
186
|
+
});
|
|
187
|
+
if (selectSourceUploadStrategy(source, await preflightSourceUpload(context, notebook, options)) === "multipart") {
|
|
188
|
+
const progress = progressReporter(context, "transfers.source.multipart", "multipart", source.size, options);
|
|
189
|
+
progress.start();
|
|
190
|
+
const fields = compactUndefined({
|
|
191
|
+
parent_source_id: metadata.parentSourceId,
|
|
192
|
+
path: metadata.path,
|
|
193
|
+
retain_original_file: "true",
|
|
194
|
+
source_type: metadata.sourceType,
|
|
195
|
+
title: metadata.title
|
|
196
|
+
});
|
|
197
|
+
const result = await transferCall(context, "transfers.source.multipart", hostRequest(queryPath(context.profile.apiPath("notebooks", notebook, "sources", "upload"), [["client", context.client]]), "POST", false, options, {
|
|
198
|
+
file: source,
|
|
199
|
+
fields,
|
|
200
|
+
kind: "multipart",
|
|
201
|
+
onProgress: progress.update
|
|
202
|
+
}), sourceSchema);
|
|
203
|
+
progress.complete();
|
|
204
|
+
return result;
|
|
205
|
+
}
|
|
206
|
+
const ticket = await transferCall(context, "transfers.source.presign", hostRequest(context.profile.apiPath("notebooks", notebook, "sources", "presign"), "POST", false, options, {
|
|
207
|
+
kind: "json",
|
|
208
|
+
value: {
|
|
209
|
+
filename: source.filename,
|
|
210
|
+
mimeType: source.mimeType,
|
|
211
|
+
size: source.size
|
|
212
|
+
}
|
|
213
|
+
}), sourceUploadTicketSchema);
|
|
214
|
+
const progress = progressReporter(context, "transfers.source.upload", "presigned", source.size, options);
|
|
215
|
+
progress.start();
|
|
216
|
+
await transferCall(context, "transfers.source.upload", signedUploadRequest(ticket, source, progress, options), voidResponseSchema);
|
|
217
|
+
progress.complete();
|
|
218
|
+
progress.registering();
|
|
219
|
+
return transferCall(context, "transfers.source.register", hostRequest(context.profile.apiPath("notebooks", notebook, "sources", "register"), "POST", false, options, {
|
|
220
|
+
kind: "json",
|
|
221
|
+
value: compactUndefined({
|
|
222
|
+
filename: source.filename,
|
|
223
|
+
mimeType: source.mimeType,
|
|
224
|
+
parentSourceId: metadata.parentSourceId,
|
|
225
|
+
path: metadata.path,
|
|
226
|
+
sha256: metadata.sha256,
|
|
227
|
+
size: source.size,
|
|
228
|
+
sourceType: metadata.sourceType,
|
|
229
|
+
title: metadata.title,
|
|
230
|
+
uri: ticket.uri
|
|
231
|
+
})
|
|
232
|
+
}), sourceSchema);
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
//#endregion
|
|
237
|
+
export { createTransferOperations };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qoder-ai/qmind-cli",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "QMind command line interface",
|
|
5
5
|
"bin": {
|
|
6
6
|
"qmind": "bin/cli.js"
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"@types/node": "24.13.3",
|
|
38
38
|
"@types/picomatch": "4.0.3",
|
|
39
39
|
"@types/proper-lockfile": "4.1.4",
|
|
40
|
-
"@ali/qmind-node-host": "^2.2.
|
|
41
|
-
"@ali/qmind-sdk": "^0.
|
|
40
|
+
"@ali/qmind-node-host": "^2.2.8",
|
|
41
|
+
"@ali/qmind-sdk": "^0.14.0"
|
|
42
42
|
},
|
|
43
43
|
"license": "UNLICENSED"
|
|
44
44
|
}
|
package/dist/cards-2J6ebaI0.js
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { b as cardListSchema, d as pagination, h as stringList, m as requiredString, n as call, p as queryPath, u as optionalTrimmedString, v as batchMutationResultSchema, x as cardSchema } from "./shared-DwycozMA.js";
|
|
2
|
-
//#region ../sdk/src/operations/cards.ts
|
|
3
|
-
function createCardOperations(context) {
|
|
4
|
-
const listCards = async (notebookId, input = {}, options, featured = false) => {
|
|
5
|
-
const notebook = requiredString(notebookId, "notebookId");
|
|
6
|
-
const normalizedPage = pagination({
|
|
7
|
-
page: input.page ?? 1,
|
|
8
|
-
pageSize: input.pageSize ?? 20
|
|
9
|
-
});
|
|
10
|
-
const category = optionalTrimmedString(input.category, "category");
|
|
11
|
-
const query = optionalTrimmedString(input.query, "query");
|
|
12
|
-
const root = context.profile.apiPath(featured ? "featured-notebooks" : "notebooks", notebook, "cards");
|
|
13
|
-
const path = queryPath(root, [
|
|
14
|
-
["category", category],
|
|
15
|
-
["query", query],
|
|
16
|
-
["page", normalizedPage.page],
|
|
17
|
-
["page_size", normalizedPage.pageSize]
|
|
18
|
-
]);
|
|
19
|
-
return call(context, {
|
|
20
|
-
callOptions: options,
|
|
21
|
-
capability: featured ? "featuredNotebooks.read" : "cards.read",
|
|
22
|
-
idempotent: true,
|
|
23
|
-
method: "GET",
|
|
24
|
-
operation: featured ? "featuredCards.list" : "cards.list",
|
|
25
|
-
path,
|
|
26
|
-
schema: cardListSchema
|
|
27
|
-
});
|
|
28
|
-
};
|
|
29
|
-
return {
|
|
30
|
-
async batchDeleteCards(notebookId, cardIds, options) {
|
|
31
|
-
const notebook = requiredString(notebookId, "notebookId");
|
|
32
|
-
const ids = stringList(cardIds, "cardIds", { min: 1 });
|
|
33
|
-
return call(context, {
|
|
34
|
-
body: { cardIds: ids },
|
|
35
|
-
callOptions: options,
|
|
36
|
-
capability: "cards.write",
|
|
37
|
-
idempotent: false,
|
|
38
|
-
method: "POST",
|
|
39
|
-
operation: "cards.batchDelete",
|
|
40
|
-
path: context.profile.apiPath("notebooks", notebook, "cards", "batch-delete"),
|
|
41
|
-
schema: batchMutationResultSchema
|
|
42
|
-
});
|
|
43
|
-
},
|
|
44
|
-
async deleteCard(notebookId, cardId, options) {
|
|
45
|
-
const notebook = requiredString(notebookId, "notebookId");
|
|
46
|
-
const card = requiredString(cardId, "cardId");
|
|
47
|
-
return call(context, {
|
|
48
|
-
callOptions: options,
|
|
49
|
-
capability: "cards.write",
|
|
50
|
-
idempotent: false,
|
|
51
|
-
method: "DELETE",
|
|
52
|
-
operation: "cards.delete",
|
|
53
|
-
path: context.profile.apiPath("notebooks", notebook, "cards", card),
|
|
54
|
-
schema: batchMutationResultSchema
|
|
55
|
-
});
|
|
56
|
-
},
|
|
57
|
-
async getCard(notebookId, cardId, options) {
|
|
58
|
-
const notebook = requiredString(notebookId, "notebookId");
|
|
59
|
-
const card = requiredString(cardId, "cardId");
|
|
60
|
-
return call(context, {
|
|
61
|
-
callOptions: options,
|
|
62
|
-
capability: "cards.read",
|
|
63
|
-
idempotent: true,
|
|
64
|
-
method: "GET",
|
|
65
|
-
operation: "cards.get",
|
|
66
|
-
path: context.profile.apiPath("notebooks", notebook, "cards", card),
|
|
67
|
-
schema: cardSchema
|
|
68
|
-
});
|
|
69
|
-
},
|
|
70
|
-
listCards: (notebookId, input, options) => listCards(notebookId, input, options),
|
|
71
|
-
listFeaturedCards: (notebookId, input, options) => listCards(notebookId, input, options, true)
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
//#endregion
|
|
75
|
-
export { createCardOperations };
|