@kevisual/api 0.0.42 → 0.0.44
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/dist/query-ai.d.ts +78 -0
- package/dist/query-ai.js +472 -0
- package/dist/query-app.d.ts +18 -0
- package/dist/query-app.js +523 -0
- package/dist/query-config.d.ts +71 -0
- package/dist/query-config.js +336 -0
- package/dist/query-login.d.ts +299 -0
- package/dist/query-login.js +1407 -0
- package/dist/query-proxy.d.ts +215 -0
- package/dist/query-proxy.js +10470 -0
- package/dist/query-resources.d.ts +58 -0
- package/dist/query-resources.js +1734 -0
- package/dist/query-secret.d.ts +45 -0
- package/dist/query-secret.js +299 -0
- package/dist/query-shop.d.ts +12 -0
- package/dist/query-shop.js +447 -0
- package/dist/query-upload.d.ts +153 -0
- package/dist/query-upload.js +355 -0
- package/dist/utils.d.ts +33 -0
- package/dist/utils.js +68 -0
- package/package.json +16 -7
- package/query/query-ai/index.ts +1 -0
- package/query/query-app/index.ts +1 -0
- package/query/query-config/index.ts +1 -0
- package/query/query-login/index.ts +1 -0
- package/query/query-proxy/proxy.ts +14 -8
- package/query/query-proxy/router-api-proxy.ts +1 -1
- package/query/query-shop/index.ts +1 -0
- package/query/query-upload/index.ts +1 -0
- package/query/utils/index.ts +1 -0
- package/query/utils/random.ts +15 -0
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
// query/query-upload/core/upload-progress.ts
|
|
2
|
+
class UploadProgress {
|
|
3
|
+
progress;
|
|
4
|
+
onStart;
|
|
5
|
+
onDone;
|
|
6
|
+
onProgress;
|
|
7
|
+
data;
|
|
8
|
+
end;
|
|
9
|
+
constructor(uploadOpts) {
|
|
10
|
+
this.progress = 0;
|
|
11
|
+
this.end = false;
|
|
12
|
+
const mockFn = () => {};
|
|
13
|
+
this.onStart = uploadOpts.onStart || mockFn;
|
|
14
|
+
this.onDone = uploadOpts.onDone || mockFn;
|
|
15
|
+
this.onProgress = uploadOpts.onProgress || mockFn;
|
|
16
|
+
}
|
|
17
|
+
start(msg) {
|
|
18
|
+
this.progress = 0;
|
|
19
|
+
msg && this.info(msg);
|
|
20
|
+
this.end = false;
|
|
21
|
+
this.onStart?.();
|
|
22
|
+
}
|
|
23
|
+
done() {
|
|
24
|
+
this.progress = 100;
|
|
25
|
+
this.end = true;
|
|
26
|
+
this.onDone?.();
|
|
27
|
+
}
|
|
28
|
+
set(progress, data) {
|
|
29
|
+
this.progress = progress;
|
|
30
|
+
this.data = data;
|
|
31
|
+
this.onProgress?.(progress, data);
|
|
32
|
+
console.log("uploadProgress set", progress, data);
|
|
33
|
+
}
|
|
34
|
+
setOnStart(callback) {
|
|
35
|
+
this.onStart = callback;
|
|
36
|
+
}
|
|
37
|
+
setOnDone(callback) {
|
|
38
|
+
this.onDone = callback;
|
|
39
|
+
}
|
|
40
|
+
setOnProgress(callback) {
|
|
41
|
+
this.onProgress = callback;
|
|
42
|
+
}
|
|
43
|
+
info(msg) {
|
|
44
|
+
console.log(msg);
|
|
45
|
+
}
|
|
46
|
+
error(msg) {
|
|
47
|
+
console.error(msg);
|
|
48
|
+
}
|
|
49
|
+
warn(msg) {
|
|
50
|
+
console.warn(msg);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// query/query-upload/utils/random-id.ts
|
|
55
|
+
var randomId = () => {
|
|
56
|
+
return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// query/query-upload/core/upload-chunk.ts
|
|
60
|
+
var uploadFileChunked = async (file, opts, opts2) => {
|
|
61
|
+
const { directory, appKey, version, username, isPublic, noCheckAppFiles = true } = opts;
|
|
62
|
+
const { uploadProgress, createEventSource, baseUrl = "", token, FormDataFn } = opts2 || {};
|
|
63
|
+
return new Promise(async (resolve, reject) => {
|
|
64
|
+
const taskId = randomId();
|
|
65
|
+
const filename = opts.filename || file.name;
|
|
66
|
+
uploadProgress?.start(`${filename} 上传中...`);
|
|
67
|
+
const searchParams = new URLSearchParams;
|
|
68
|
+
searchParams.set("taskId", taskId);
|
|
69
|
+
if (isPublic) {
|
|
70
|
+
searchParams.set("public", "true");
|
|
71
|
+
}
|
|
72
|
+
if (noCheckAppFiles) {
|
|
73
|
+
searchParams.set("noCheckAppFiles", "1");
|
|
74
|
+
}
|
|
75
|
+
const eventSource = createEventSource(baseUrl + "/api/s1/events", searchParams);
|
|
76
|
+
let isError = false;
|
|
77
|
+
eventSource.onmessage = function(event) {
|
|
78
|
+
console.log("Progress update:", event.data);
|
|
79
|
+
const parseIfJson = (data) => {
|
|
80
|
+
try {
|
|
81
|
+
return JSON.parse(data);
|
|
82
|
+
} catch (e) {
|
|
83
|
+
return data;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
const receivedData = parseIfJson(event.data);
|
|
87
|
+
if (typeof receivedData === "string")
|
|
88
|
+
return;
|
|
89
|
+
const progress = Number(receivedData.progress);
|
|
90
|
+
const progressFixed = progress.toFixed(2);
|
|
91
|
+
uploadProgress?.set(progress, { ...receivedData, progressFixed, filename, taskId });
|
|
92
|
+
};
|
|
93
|
+
eventSource.onerror = function(event) {
|
|
94
|
+
console.log("eventSource.onerror", event);
|
|
95
|
+
isError = true;
|
|
96
|
+
reject(event);
|
|
97
|
+
};
|
|
98
|
+
const chunkSize = 1 * 1024 * 1024;
|
|
99
|
+
const totalChunks = Math.ceil(file.size / chunkSize);
|
|
100
|
+
for (let currentChunk = 0;currentChunk < totalChunks; currentChunk++) {
|
|
101
|
+
const start = currentChunk * chunkSize;
|
|
102
|
+
const end = Math.min(start + chunkSize, file.size);
|
|
103
|
+
const chunk = file.slice(start, end);
|
|
104
|
+
const formData = new FormDataFn;
|
|
105
|
+
formData.append("file", chunk, filename);
|
|
106
|
+
formData.append("chunkIndex", currentChunk.toString());
|
|
107
|
+
formData.append("totalChunks", totalChunks.toString());
|
|
108
|
+
const isLast = currentChunk === totalChunks - 1;
|
|
109
|
+
if (directory) {
|
|
110
|
+
formData.append("directory", directory);
|
|
111
|
+
}
|
|
112
|
+
if (appKey && version) {
|
|
113
|
+
formData.append("appKey", appKey);
|
|
114
|
+
formData.append("version", version);
|
|
115
|
+
}
|
|
116
|
+
if (username) {
|
|
117
|
+
formData.append("username", username);
|
|
118
|
+
}
|
|
119
|
+
try {
|
|
120
|
+
const res = await fetch(baseUrl + "/api/s1/resources/upload/chunk?taskId=" + taskId, {
|
|
121
|
+
method: "POST",
|
|
122
|
+
body: formData,
|
|
123
|
+
headers: {
|
|
124
|
+
"task-id": taskId,
|
|
125
|
+
Authorization: `Bearer ${token}`
|
|
126
|
+
}
|
|
127
|
+
}).then((response) => response.json());
|
|
128
|
+
if (res?.code !== 200) {
|
|
129
|
+
console.log("uploadChunk error", res);
|
|
130
|
+
uploadProgress?.error(res?.message || "上传失败");
|
|
131
|
+
isError = true;
|
|
132
|
+
eventSource.close();
|
|
133
|
+
uploadProgress?.done();
|
|
134
|
+
reject(new Error(res?.message || "上传失败"));
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
if (isLast) {
|
|
138
|
+
fetch(baseUrl + "/api/s1/events/close?taskId=" + taskId);
|
|
139
|
+
eventSource.close();
|
|
140
|
+
uploadProgress?.done();
|
|
141
|
+
resolve(res);
|
|
142
|
+
}
|
|
143
|
+
} catch (error) {
|
|
144
|
+
console.log("Error uploading chunk", error);
|
|
145
|
+
fetch(baseUrl + "/api/s1/events/close?taskId=" + taskId);
|
|
146
|
+
reject(error);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
if (!uploadProgress?.end) {
|
|
151
|
+
uploadProgress?.done();
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
// query/query-upload/core/upload.ts
|
|
157
|
+
var uploadFiles = async (files, opts, opts2) => {
|
|
158
|
+
const { directory, appKey, version, username, noCheckAppFiles = true } = opts;
|
|
159
|
+
const { uploadProgress, createEventSource, baseUrl = "", token, FormDataFn } = opts2 || {};
|
|
160
|
+
const length = files.length;
|
|
161
|
+
const maxSize = opts.maxSize || 20 * 1024 * 1024;
|
|
162
|
+
const totalSize = files.reduce((acc, file) => acc + file.size, 0);
|
|
163
|
+
if (totalSize > maxSize) {
|
|
164
|
+
const maxSizeMB = maxSize / 1024 / 1024;
|
|
165
|
+
uploadProgress?.error("有文件大小不能超过" + maxSizeMB + "MB");
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const maxCount = opts.maxCount || 10;
|
|
169
|
+
if (length > maxCount) {
|
|
170
|
+
uploadProgress?.error(`最多只能上传${maxCount}个文件`);
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
uploadProgress?.info(`上传中,共${length}个文件`);
|
|
174
|
+
return new Promise((resolve, reject) => {
|
|
175
|
+
const formData = new FormDataFn;
|
|
176
|
+
const webkitRelativePath = files[0]?.webkitRelativePath;
|
|
177
|
+
const keepDirectory = webkitRelativePath !== "";
|
|
178
|
+
const root = keepDirectory ? webkitRelativePath.split("/")[0] : "";
|
|
179
|
+
for (let i = 0;i < files.length; i++) {
|
|
180
|
+
const file = files[i];
|
|
181
|
+
if (keepDirectory) {
|
|
182
|
+
const webkitRelativePath2 = file.webkitRelativePath.replace(root + "/", "");
|
|
183
|
+
formData.append("file", file, webkitRelativePath2);
|
|
184
|
+
} else {
|
|
185
|
+
formData.append("file", files[i], files[i].name);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (directory) {
|
|
189
|
+
formData.append("directory", directory);
|
|
190
|
+
}
|
|
191
|
+
if (appKey && version) {
|
|
192
|
+
formData.append("appKey", appKey);
|
|
193
|
+
formData.append("version", version);
|
|
194
|
+
}
|
|
195
|
+
if (username) {
|
|
196
|
+
formData.append("username", username);
|
|
197
|
+
}
|
|
198
|
+
const searchParams = new URLSearchParams;
|
|
199
|
+
const taskId = randomId();
|
|
200
|
+
searchParams.set("taskId", taskId);
|
|
201
|
+
if (noCheckAppFiles) {
|
|
202
|
+
searchParams.set("noCheckAppFiles", "1");
|
|
203
|
+
}
|
|
204
|
+
const eventSource = new EventSource("/api/s1/events?taskId=" + taskId);
|
|
205
|
+
uploadProgress?.start("上传中...");
|
|
206
|
+
eventSource.onopen = async function(event) {
|
|
207
|
+
const res = await fetch("/api/s1/resources/upload?" + searchParams.toString(), {
|
|
208
|
+
method: "POST",
|
|
209
|
+
body: formData,
|
|
210
|
+
headers: {
|
|
211
|
+
"task-id": taskId,
|
|
212
|
+
Authorization: `Bearer ${token}`
|
|
213
|
+
}
|
|
214
|
+
}).then((response) => response.json());
|
|
215
|
+
console.log("upload success", res);
|
|
216
|
+
fetch("/api/s1/events/close?taskId=" + taskId);
|
|
217
|
+
eventSource.close();
|
|
218
|
+
uploadProgress?.done();
|
|
219
|
+
resolve(res);
|
|
220
|
+
};
|
|
221
|
+
eventSource.onmessage = function(event) {
|
|
222
|
+
console.log("Progress update:", event.data);
|
|
223
|
+
const parseIfJson = (data) => {
|
|
224
|
+
try {
|
|
225
|
+
return JSON.parse(data);
|
|
226
|
+
} catch (e) {
|
|
227
|
+
return data;
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
const receivedData = parseIfJson(event.data);
|
|
231
|
+
if (typeof receivedData === "string")
|
|
232
|
+
return;
|
|
233
|
+
const progress = Number(receivedData.progress);
|
|
234
|
+
const progressFixed = progress.toFixed(2);
|
|
235
|
+
console.log("progress", progress);
|
|
236
|
+
uploadProgress?.set(progress, { ...receivedData, taskId, progressFixed });
|
|
237
|
+
};
|
|
238
|
+
eventSource.onerror = function(event) {
|
|
239
|
+
console.log("eventSource.onerror", event);
|
|
240
|
+
reject(event);
|
|
241
|
+
};
|
|
242
|
+
});
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
// query/query-upload/utils/to-file.ts
|
|
246
|
+
var getFileExtension = (filename) => {
|
|
247
|
+
return filename.split(".").pop();
|
|
248
|
+
};
|
|
249
|
+
var getFileType = (extension) => {
|
|
250
|
+
switch (extension) {
|
|
251
|
+
case "js":
|
|
252
|
+
return "text/javascript";
|
|
253
|
+
case "css":
|
|
254
|
+
return "text/css";
|
|
255
|
+
case "html":
|
|
256
|
+
return "text/html";
|
|
257
|
+
case "json":
|
|
258
|
+
return "application/json";
|
|
259
|
+
case "png":
|
|
260
|
+
return "image/png";
|
|
261
|
+
case "jpg":
|
|
262
|
+
return "image/jpeg";
|
|
263
|
+
case "jpeg":
|
|
264
|
+
return "image/jpeg";
|
|
265
|
+
case "gif":
|
|
266
|
+
return "image/gif";
|
|
267
|
+
case "svg":
|
|
268
|
+
return "image/svg+xml";
|
|
269
|
+
case "webp":
|
|
270
|
+
return "image/webp";
|
|
271
|
+
case "ico":
|
|
272
|
+
return "image/x-icon";
|
|
273
|
+
default:
|
|
274
|
+
return "text/plain";
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
var checkIsBase64 = (content) => {
|
|
278
|
+
return content.startsWith("data:");
|
|
279
|
+
};
|
|
280
|
+
var getDirectoryAndName = (filename) => {
|
|
281
|
+
if (!filename) {
|
|
282
|
+
return null;
|
|
283
|
+
}
|
|
284
|
+
if (filename.startsWith(".")) {
|
|
285
|
+
return null;
|
|
286
|
+
} else {
|
|
287
|
+
filename = filename.replace(/^\/+/, "");
|
|
288
|
+
}
|
|
289
|
+
const hasDirectory = filename.includes("/");
|
|
290
|
+
if (!hasDirectory) {
|
|
291
|
+
return { directory: "", name: filename };
|
|
292
|
+
}
|
|
293
|
+
const parts = filename.split("/");
|
|
294
|
+
const name = parts.pop();
|
|
295
|
+
const directory = parts.join("/");
|
|
296
|
+
return { directory, name };
|
|
297
|
+
};
|
|
298
|
+
var toFile = (content, filename) => {
|
|
299
|
+
const directoryAndName = getDirectoryAndName(filename);
|
|
300
|
+
if (!directoryAndName) {
|
|
301
|
+
throw new Error("Invalid filename");
|
|
302
|
+
}
|
|
303
|
+
const { name } = directoryAndName;
|
|
304
|
+
const extension = getFileExtension(name);
|
|
305
|
+
if (!extension) {
|
|
306
|
+
throw new Error("Invalid filename");
|
|
307
|
+
}
|
|
308
|
+
const isBase64 = checkIsBase64(content);
|
|
309
|
+
const type = getFileType(extension);
|
|
310
|
+
if (isBase64) {
|
|
311
|
+
const base64Data = content.split(",")[1];
|
|
312
|
+
const byteCharacters = atob(base64Data);
|
|
313
|
+
const byteNumbers = new Array(byteCharacters.length);
|
|
314
|
+
for (let i = 0;i < byteCharacters.length; i++) {
|
|
315
|
+
byteNumbers[i] = byteCharacters.charCodeAt(i);
|
|
316
|
+
}
|
|
317
|
+
const byteArray = new Uint8Array(byteNumbers);
|
|
318
|
+
const blob = new Blob([byteArray], { type });
|
|
319
|
+
return new File([blob], filename, { type });
|
|
320
|
+
} else {
|
|
321
|
+
const blob = new Blob([content], { type });
|
|
322
|
+
return new File([blob], filename, { type });
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
// query/query-upload/query-upload-browser.ts
|
|
326
|
+
var uploadChunk = async (file, opts, props) => {
|
|
327
|
+
const uploadProgress = new UploadProgress({
|
|
328
|
+
onStart: function() {
|
|
329
|
+
props?.onStart?.();
|
|
330
|
+
},
|
|
331
|
+
onDone: () => {
|
|
332
|
+
props?.onDone?.();
|
|
333
|
+
},
|
|
334
|
+
onProgress: (progress, data) => {
|
|
335
|
+
props?.onProgress?.(progress, data);
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
const result = await uploadFileChunked(file, opts, {
|
|
339
|
+
uploadProgress,
|
|
340
|
+
token: props?.token,
|
|
341
|
+
createEventSource: (url, searchParams) => {
|
|
342
|
+
return new EventSource(url + "?" + searchParams.toString());
|
|
343
|
+
},
|
|
344
|
+
FormDataFn: FormData
|
|
345
|
+
});
|
|
346
|
+
return result;
|
|
347
|
+
};
|
|
348
|
+
export {
|
|
349
|
+
uploadFiles,
|
|
350
|
+
uploadFileChunked,
|
|
351
|
+
uploadChunk,
|
|
352
|
+
toFile,
|
|
353
|
+
randomId,
|
|
354
|
+
UploadProgress
|
|
355
|
+
};
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
declare const letter = "abcdefghijklmnopqrstuvwxyz";
|
|
2
|
+
declare const number = "0123456789";
|
|
3
|
+
declare const alphanumericWithDash = "abcdefghijklmnopqrstuvwxyz0123456789-";
|
|
4
|
+
/**
|
|
5
|
+
* 创建一个随机的字母字符串
|
|
6
|
+
*/
|
|
7
|
+
declare const uuid: any;
|
|
8
|
+
/**
|
|
9
|
+
* 创建一个随机的 id,包含字母和数字
|
|
10
|
+
*/
|
|
11
|
+
declare const nanoid: any;
|
|
12
|
+
/**
|
|
13
|
+
* 创建一个随机的 id,包含字母、数字和短横线
|
|
14
|
+
*/
|
|
15
|
+
declare const nanoidWithDash: any;
|
|
16
|
+
/**
|
|
17
|
+
* 创建一个随机的 id,以字母开头的字符串
|
|
18
|
+
* @param number
|
|
19
|
+
* @returns
|
|
20
|
+
*/
|
|
21
|
+
declare const randomId: (number: number) => string;
|
|
22
|
+
/**
|
|
23
|
+
* 创建一个随机的字母字符串
|
|
24
|
+
* @param number
|
|
25
|
+
* @param opts
|
|
26
|
+
* @returns
|
|
27
|
+
*/
|
|
28
|
+
declare const randomLetter: (number?: number, opts?: {
|
|
29
|
+
before?: string;
|
|
30
|
+
after?: string;
|
|
31
|
+
}) => string;
|
|
32
|
+
|
|
33
|
+
export { alphanumericWithDash, letter, nanoid, nanoidWithDash, number, randomId, randomLetter, uuid };
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// node_modules/.pnpm/nanoid@5.1.6/node_modules/nanoid/index.js
|
|
2
|
+
import { webcrypto as crypto } from "node:crypto";
|
|
3
|
+
var POOL_SIZE_MULTIPLIER = 128;
|
|
4
|
+
var pool;
|
|
5
|
+
var poolOffset;
|
|
6
|
+
function fillPool(bytes) {
|
|
7
|
+
if (!pool || pool.length < bytes) {
|
|
8
|
+
pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER);
|
|
9
|
+
crypto.getRandomValues(pool);
|
|
10
|
+
poolOffset = 0;
|
|
11
|
+
} else if (poolOffset + bytes > pool.length) {
|
|
12
|
+
crypto.getRandomValues(pool);
|
|
13
|
+
poolOffset = 0;
|
|
14
|
+
}
|
|
15
|
+
poolOffset += bytes;
|
|
16
|
+
}
|
|
17
|
+
function random(bytes) {
|
|
18
|
+
fillPool(bytes |= 0);
|
|
19
|
+
return pool.subarray(poolOffset - bytes, poolOffset);
|
|
20
|
+
}
|
|
21
|
+
function customRandom(alphabet, defaultSize, getRandom) {
|
|
22
|
+
let mask = (2 << 31 - Math.clz32(alphabet.length - 1 | 1)) - 1;
|
|
23
|
+
let step = Math.ceil(1.6 * mask * defaultSize / alphabet.length);
|
|
24
|
+
return (size = defaultSize) => {
|
|
25
|
+
if (!size)
|
|
26
|
+
return "";
|
|
27
|
+
let id = "";
|
|
28
|
+
while (true) {
|
|
29
|
+
let bytes = getRandom(step);
|
|
30
|
+
let i = step;
|
|
31
|
+
while (i--) {
|
|
32
|
+
id += alphabet[bytes[i] & mask] || "";
|
|
33
|
+
if (id.length >= size)
|
|
34
|
+
return id;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function customAlphabet(alphabet, size = 21) {
|
|
40
|
+
return customRandom(alphabet, size, random);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// query/utils/random.ts
|
|
44
|
+
var letter = "abcdefghijklmnopqrstuvwxyz";
|
|
45
|
+
var number = "0123456789";
|
|
46
|
+
var alphanumeric = `${letter}${number}`;
|
|
47
|
+
var alphanumericWithDash = `${alphanumeric}-`;
|
|
48
|
+
var uuid = customAlphabet(letter);
|
|
49
|
+
var nanoid = customAlphabet(alphanumeric, 10);
|
|
50
|
+
var nanoidWithDash = customAlphabet(alphanumericWithDash, 10);
|
|
51
|
+
var randomId = (number2) => {
|
|
52
|
+
const _letter = uuid(1);
|
|
53
|
+
return `${_letter}${nanoid(number2)}`;
|
|
54
|
+
};
|
|
55
|
+
var randomLetter = (number2 = 8, opts) => {
|
|
56
|
+
const { before = "", after = "" } = opts || {};
|
|
57
|
+
return `${before}${uuid(number2)}${after}`;
|
|
58
|
+
};
|
|
59
|
+
export {
|
|
60
|
+
uuid,
|
|
61
|
+
randomLetter,
|
|
62
|
+
randomId,
|
|
63
|
+
number,
|
|
64
|
+
nanoidWithDash,
|
|
65
|
+
nanoid,
|
|
66
|
+
letter,
|
|
67
|
+
alphanumericWithDash
|
|
68
|
+
};
|
package/package.json
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kevisual/api",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.44",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "mod.ts",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"build": "bun run bun.config.ts"
|
|
8
|
-
"postbuild": "bun bun.copy.config.mjs"
|
|
7
|
+
"build": "bun run bun.config.ts"
|
|
9
8
|
},
|
|
10
9
|
"publishConfig": {
|
|
11
10
|
"access": "public"
|
|
@@ -22,10 +21,12 @@
|
|
|
22
21
|
"type": "module",
|
|
23
22
|
"devDependencies": {
|
|
24
23
|
"@kevisual/cache": "^0.0.5",
|
|
24
|
+
"@kevisual/code-builder": "^0.0.5",
|
|
25
25
|
"@kevisual/query": "^0.0.39",
|
|
26
|
-
"@kevisual/router": "^0.0.
|
|
26
|
+
"@kevisual/router": "^0.0.69",
|
|
27
27
|
"@kevisual/types": "^0.0.12",
|
|
28
28
|
"@kevisual/use-config": "^1.0.30",
|
|
29
|
+
"@types/spark-md5": "^3.0.5",
|
|
29
30
|
"@types/bun": "^1.3.8",
|
|
30
31
|
"@types/crypto-js": "^4.2.2",
|
|
31
32
|
"@types/node": "^25.2.0",
|
|
@@ -36,7 +37,6 @@
|
|
|
36
37
|
"dependencies": {
|
|
37
38
|
"@kevisual/js-filter": "^0.0.5",
|
|
38
39
|
"@kevisual/load": "^0.0.6",
|
|
39
|
-
"@types/spark-md5": "^3.0.5",
|
|
40
40
|
"es-toolkit": "^1.44.0",
|
|
41
41
|
"eventemitter3": "^5.0.4",
|
|
42
42
|
"fuse.js": "^7.1.0",
|
|
@@ -52,6 +52,15 @@
|
|
|
52
52
|
"./proxy": "./query/query-proxy/index.ts",
|
|
53
53
|
"./secret": "./query/query-secret/index.ts",
|
|
54
54
|
"./resources": "./query/query-resources/index.ts",
|
|
55
|
-
"./query
|
|
55
|
+
"./query-secret": "./dist/query-secret.js",
|
|
56
|
+
"./utils": "./dist/utils.js",
|
|
57
|
+
"./query-upload": "./dist/query-upload.js",
|
|
58
|
+
"./query-app": "./dist/query-app.js",
|
|
59
|
+
"./query-proxy": "./dist/query-proxy.js",
|
|
60
|
+
"./query-shop": "./dist/query-shop.js",
|
|
61
|
+
"./query-config": "./dist/query-config.js",
|
|
62
|
+
"./query-login": "./dist/query-login.js",
|
|
63
|
+
"./query-ai": "./dist/query-ai.js",
|
|
64
|
+
"./query-resources": "./dist/query-resources.js"
|
|
56
65
|
}
|
|
57
|
-
}
|
|
66
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './query-ai.ts'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './query-app.ts'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './query-config.ts';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './query-login-browser.ts';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { QueryClient as Query, Result } from '@kevisual/query';
|
|
2
|
-
import { QueryRouterServer, App, Route } from '@kevisual/router';
|
|
2
|
+
import { QueryRouterServer, type App, type Route, fromJSONSchema, toJSONSchema } from '@kevisual/router/browser';
|
|
3
3
|
import { filter } from '@kevisual/js-filter'
|
|
4
4
|
import { EventEmitter } from 'eventemitter3';
|
|
5
5
|
import { initApi } from './router-api-proxy.ts';
|
|
@@ -190,6 +190,7 @@ export class QueryProxy {
|
|
|
190
190
|
|
|
191
191
|
/**
|
|
192
192
|
* 初始化路由
|
|
193
|
+
* main
|
|
193
194
|
* @returns
|
|
194
195
|
*/
|
|
195
196
|
async init() {
|
|
@@ -246,6 +247,8 @@ export class QueryProxy {
|
|
|
246
247
|
return
|
|
247
248
|
}
|
|
248
249
|
const routes = router.getList();
|
|
250
|
+
// TODO: args
|
|
251
|
+
// const args = fromJSONSchema(r);
|
|
249
252
|
for (const r of routes) {
|
|
250
253
|
console.debug(`注册路由: [${r.path}] ${r?.key}`, 'Context');
|
|
251
254
|
let metadata = r.metadata || {};
|
|
@@ -378,6 +381,13 @@ export class QueryProxy {
|
|
|
378
381
|
return;
|
|
379
382
|
}
|
|
380
383
|
}
|
|
384
|
+
getQueryByViewId(viewId: string): string | undefined {
|
|
385
|
+
const view = this.views.find(v => v.id === viewId);
|
|
386
|
+
if (view) {
|
|
387
|
+
return view.query;
|
|
388
|
+
}
|
|
389
|
+
return undefined;
|
|
390
|
+
}
|
|
381
391
|
/**
|
|
382
392
|
* 列出路由
|
|
383
393
|
* @param filter
|
|
@@ -386,14 +396,10 @@ export class QueryProxy {
|
|
|
386
396
|
*/
|
|
387
397
|
async listRoutes(filterFn?: (item: Route) => boolean, opts?: { viewId?: string, query?: string }) {
|
|
388
398
|
let query = opts?.query;
|
|
389
|
-
if (opts?.viewId) {
|
|
390
|
-
|
|
391
|
-
if (view) {
|
|
392
|
-
query = view.query;
|
|
393
|
-
}
|
|
394
|
-
} if (opts?.query) {
|
|
395
|
-
query = opts.query;
|
|
399
|
+
if (opts?.viewId && !query) {
|
|
400
|
+
query = this.getQueryByViewId(opts.viewId);
|
|
396
401
|
}
|
|
402
|
+
|
|
397
403
|
const routes = this.router.routes.filter(filterFn || (() => true));
|
|
398
404
|
if (query) {
|
|
399
405
|
if (query.toLocaleUpperCase().startsWith('WHERE')) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Query } from "@kevisual/query";
|
|
2
2
|
import { RouterViewApi, RouterItem } from "./proxy.ts";
|
|
3
|
-
import { App, type QueryRouterServer } from "@kevisual/router";
|
|
3
|
+
import { type App, type QueryRouterServer } from "@kevisual/router";
|
|
4
4
|
import { filter } from "@kevisual/js-filter";
|
|
5
5
|
import { isBrowser } from "es-toolkit";
|
|
6
6
|
export const initApi = async (opts: {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './query-shop.ts'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './query-upload-browser.ts';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './random.ts';
|
package/query/utils/random.ts
CHANGED
|
@@ -4,10 +4,19 @@ export const letter = 'abcdefghijklmnopqrstuvwxyz';
|
|
|
4
4
|
export const number = '0123456789';
|
|
5
5
|
const alphanumeric = `${letter}${number}`;
|
|
6
6
|
export const alphanumericWithDash = `${alphanumeric}-`;
|
|
7
|
+
/**
|
|
8
|
+
* 创建一个随机的字母字符串
|
|
9
|
+
*/
|
|
7
10
|
export const uuid = customAlphabet(letter);
|
|
8
11
|
|
|
12
|
+
/**
|
|
13
|
+
* 创建一个随机的 id,包含字母和数字
|
|
14
|
+
*/
|
|
9
15
|
export const nanoid = customAlphabet(alphanumeric, 10);
|
|
10
16
|
|
|
17
|
+
/**
|
|
18
|
+
* 创建一个随机的 id,包含字母、数字和短横线
|
|
19
|
+
*/
|
|
11
20
|
export const nanoidWithDash = customAlphabet(alphanumericWithDash, 10);
|
|
12
21
|
|
|
13
22
|
/**
|
|
@@ -20,6 +29,12 @@ export const randomId = (number: number) => {
|
|
|
20
29
|
return `${_letter}${nanoid(number)}`;
|
|
21
30
|
};
|
|
22
31
|
|
|
32
|
+
/**
|
|
33
|
+
* 创建一个随机的字母字符串
|
|
34
|
+
* @param number
|
|
35
|
+
* @param opts
|
|
36
|
+
* @returns
|
|
37
|
+
*/
|
|
23
38
|
export const randomLetter = (number: number = 8, opts?: { before?: string; after?: string }) => {
|
|
24
39
|
const { before = '', after = '' } = opts || {};
|
|
25
40
|
return `${before}${uuid(number)}${after}`;
|