6d5eb15b1b
Expose authenticated /api/mindspace/v1/oa/drive APIs over each user's oa/ workspace and wire a MindSpace entry at /space/oa/drive. Co-authored-by: Cursor <cursoragent@cursor.com>
85 lines
2.3 KiB
JavaScript
85 lines
2.3 KiB
JavaScript
import { computeUserSpaceQuotaStats } from '../mindspace-space-quota.mjs';
|
|
import { createDriveContext } from './drive-context.mjs';
|
|
import { createDriveHandlers } from './drive-handlers.mjs';
|
|
import { createDriveRuntime } from './drive-runtime.mjs';
|
|
|
|
export function createMindSpaceOaDriveService({
|
|
h5Root,
|
|
getMindSpace = () => null,
|
|
getMindSpaceAssets = () => null,
|
|
getPool = () => null,
|
|
} = {}) {
|
|
if (!h5Root) {
|
|
throw new Error('createMindSpaceOaDriveService requires h5Root');
|
|
}
|
|
|
|
const runtimes = new Map();
|
|
|
|
function getRuntime(userId) {
|
|
const key = String(userId);
|
|
if (!runtimes.has(key)) {
|
|
const ctx = createDriveContext(h5Root, key);
|
|
const runtime = createDriveRuntime(ctx);
|
|
void runtime.bootstrap();
|
|
runtimes.set(key, runtime);
|
|
}
|
|
return runtimes.get(key);
|
|
}
|
|
|
|
async function getQuotaInfo(userId) {
|
|
const mindSpace = getMindSpace();
|
|
if (!mindSpace) return null;
|
|
const quota = await mindSpace.getQuota(userId);
|
|
if (!quota) return null;
|
|
const stats = computeUserSpaceQuotaStats({
|
|
quota_bytes: quota.quotaBytes,
|
|
used_bytes: quota.usedBytes,
|
|
reserved_bytes: quota.reservedBytes,
|
|
});
|
|
return {
|
|
quotaBytes: stats.quotaBytes,
|
|
usedBytes: stats.usedBytes,
|
|
reservedBytes: stats.reservedBytes,
|
|
availableBytes: Math.max(0, stats.availableBytes),
|
|
};
|
|
}
|
|
|
|
async function assertUploadAllowed(userId, sizeBytes) {
|
|
const required = Math.max(0, Number(sizeBytes) || 0);
|
|
if (!required) return;
|
|
const quota = await getQuotaInfo(userId);
|
|
if (!quota) return;
|
|
if (quota.availableBytes < required) {
|
|
throw Object.assign(new Error('剩余空间不足'), {
|
|
code: 'quota_exceeded',
|
|
details: {
|
|
requiredBytes: required,
|
|
availableBytes: Math.max(0, quota.availableBytes),
|
|
},
|
|
});
|
|
}
|
|
}
|
|
|
|
async function afterMutate(userId) {
|
|
const assets = getMindSpaceAssets();
|
|
if (assets?.syncWorkspaceAssets) {
|
|
await assets.syncWorkspaceAssets(userId, { categoryCode: 'oa' }).catch((error) => {
|
|
console.warn('[oa-drive] workspace sync failed:', error?.message ?? error);
|
|
});
|
|
}
|
|
}
|
|
|
|
const handlers = createDriveHandlers({
|
|
getRuntime,
|
|
getQuotaInfo,
|
|
assertUploadAllowed,
|
|
afterMutate,
|
|
});
|
|
|
|
return {
|
|
getRuntime,
|
|
handlers,
|
|
getPool,
|
|
};
|
|
}
|