mirror of
https://github.com/router-for-me/Cli-Proxy-API-Management-Center.git
synced 2026-06-16 21:03:58 +08:00
refactor(auth-files): simplify batch response and field normalization
Backend batch upload/delete handlers always return a complete payload: status (string), uploaded/deleted (number), files (string array), and failed (only on partial). See auth_files.go:702-711. The fallback chains that re-derived uploaded/deleted counts and file names from the requestedNames list were unreachable. Likewise, runtime_only is always a real bool from Go (auth_files.go:403), and entry.modified is never emitted, so isRuntimeOnlyEntry collapses to a strict equality check and readDateField drops the modified alias.
This commit is contained in:
@@ -91,86 +91,26 @@ const normalizeBatchFailures = (value: unknown): AuthFileBatchFailure[] => {
|
|||||||
}, []);
|
}, []);
|
||||||
};
|
};
|
||||||
|
|
||||||
const deriveSuccessfulFileNames = (requestedNames: string[], failed: AuthFileBatchFailure[]): string[] => {
|
|
||||||
const failedNames = new Set(
|
|
||||||
failed
|
|
||||||
.map((entry) => entry.name.trim())
|
|
||||||
.filter(Boolean)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (failedNames.size === 0) {
|
|
||||||
return [...requestedNames];
|
|
||||||
}
|
|
||||||
|
|
||||||
return requestedNames.filter((name) => !failedNames.has(name));
|
|
||||||
};
|
|
||||||
|
|
||||||
const normalizeBatchUploadResponse = (
|
const normalizeBatchUploadResponse = (
|
||||||
payload: AuthFileBatchUploadResponse | undefined,
|
payload: AuthFileBatchUploadResponse | undefined
|
||||||
requestedNames: string[]
|
|
||||||
): AuthFileBatchUploadResult => {
|
): AuthFileBatchUploadResult => {
|
||||||
const failed = normalizeBatchFailures(payload?.failed);
|
const failed = normalizeBatchFailures(payload?.failed);
|
||||||
const uploadedFilesFromPayload = normalizeBatchFileNames(payload?.files);
|
|
||||||
const uploaded =
|
|
||||||
typeof payload?.uploaded === 'number'
|
|
||||||
? payload.uploaded
|
|
||||||
: uploadedFilesFromPayload.length > 0
|
|
||||||
? uploadedFilesFromPayload.length
|
|
||||||
: requestedNames.length === 1 && failed.length === 0
|
|
||||||
? 1
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
let uploadedFiles = uploadedFilesFromPayload;
|
|
||||||
if (uploadedFiles.length === 0 && uploaded > 0) {
|
|
||||||
if (failed.length === 0 && uploaded === requestedNames.length) {
|
|
||||||
uploadedFiles = [...requestedNames];
|
|
||||||
} else {
|
|
||||||
const derivedNames = deriveSuccessfulFileNames(requestedNames, failed);
|
|
||||||
if (derivedNames.length === uploaded) {
|
|
||||||
uploadedFiles = derivedNames;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
status: typeof payload?.status === 'string' ? payload.status : failed.length > 0 ? 'partial' : 'ok',
|
status: payload?.status ?? (failed.length > 0 ? 'partial' : 'ok'),
|
||||||
uploaded,
|
uploaded: payload?.uploaded ?? 0,
|
||||||
files: uploadedFiles,
|
files: normalizeBatchFileNames(payload?.files),
|
||||||
failed,
|
failed,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const normalizeBatchDeleteResponse = (
|
const normalizeBatchDeleteResponse = (
|
||||||
payload: AuthFileBatchDeleteResponse | undefined,
|
payload: AuthFileBatchDeleteResponse | undefined
|
||||||
requestedNames: string[]
|
|
||||||
): AuthFileBatchDeleteResult => {
|
): AuthFileBatchDeleteResult => {
|
||||||
const failed = normalizeBatchFailures(payload?.failed);
|
const failed = normalizeBatchFailures(payload?.failed);
|
||||||
const deletedFilesFromPayload = normalizeBatchFileNames(payload?.files);
|
|
||||||
const deleted =
|
|
||||||
typeof payload?.deleted === 'number'
|
|
||||||
? payload.deleted
|
|
||||||
: deletedFilesFromPayload.length > 0
|
|
||||||
? deletedFilesFromPayload.length
|
|
||||||
: requestedNames.length === 1 && failed.length === 0
|
|
||||||
? 1
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
let deletedFiles = deletedFilesFromPayload;
|
|
||||||
if (deletedFiles.length === 0 && deleted > 0) {
|
|
||||||
if (failed.length === 0 && deleted === requestedNames.length) {
|
|
||||||
deletedFiles = [...requestedNames];
|
|
||||||
} else {
|
|
||||||
const derivedNames = deriveSuccessfulFileNames(requestedNames, failed);
|
|
||||||
if (derivedNames.length === deleted) {
|
|
||||||
deletedFiles = derivedNames;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
status: typeof payload?.status === 'string' ? payload.status : failed.length > 0 ? 'partial' : 'ok',
|
status: payload?.status ?? (failed.length > 0 ? 'partial' : 'ok'),
|
||||||
deleted,
|
deleted: payload?.deleted ?? 0,
|
||||||
files: deletedFiles,
|
files: normalizeBatchFileNames(payload?.files),
|
||||||
failed,
|
failed,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -181,7 +121,7 @@ const readTextField = (entry: AuthFileEntry, key: string): string => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const readDateField = (entry: AuthFileEntry): number => {
|
const readDateField = (entry: AuthFileEntry): number => {
|
||||||
const candidates = [entry['modtime'], entry.modified, entry['updated_at'], entry['last_refresh']];
|
const candidates = [entry['modtime'], entry['updated_at'], entry['last_refresh']];
|
||||||
|
|
||||||
for (const value of candidates) {
|
for (const value of candidates) {
|
||||||
if (typeof value === 'number' && Number.isFinite(value)) {
|
if (typeof value === 'number' && Number.isFinite(value)) {
|
||||||
@@ -204,12 +144,7 @@ const readDateField = (entry: AuthFileEntry): number => {
|
|||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
const isRuntimeOnlyEntry = (entry: AuthFileEntry): boolean => {
|
const isRuntimeOnlyEntry = (entry: AuthFileEntry): boolean => entry['runtime_only'] === true;
|
||||||
const value = entry['runtime_only'] ?? entry.runtimeOnly;
|
|
||||||
if (typeof value === 'boolean') return value;
|
|
||||||
if (typeof value === 'string') return value.trim().toLowerCase() === 'true';
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
const hasMeaningfulValue = (value: unknown): boolean => {
|
const hasMeaningfulValue = (value: unknown): boolean => {
|
||||||
if (value == null) return false;
|
if (value == null) return false;
|
||||||
@@ -423,7 +358,7 @@ export const authFilesApi = {
|
|||||||
formData.append('file', file, file.name);
|
formData.append('file', file, file.name);
|
||||||
});
|
});
|
||||||
const payload = await apiClient.postForm<AuthFileBatchUploadResponse>('/auth-files', formData);
|
const payload = await apiClient.postForm<AuthFileBatchUploadResponse>('/auth-files', formData);
|
||||||
return normalizeBatchUploadResponse(payload, requestedNames);
|
return normalizeBatchUploadResponse(payload);
|
||||||
},
|
},
|
||||||
|
|
||||||
upload: (file: File) => authFilesApi.uploadFiles([file]),
|
upload: (file: File) => authFilesApi.uploadFiles([file]),
|
||||||
@@ -437,7 +372,7 @@ export const authFilesApi = {
|
|||||||
const payload = await apiClient.delete<AuthFileBatchDeleteResponse>('/auth-files', {
|
const payload = await apiClient.delete<AuthFileBatchDeleteResponse>('/auth-files', {
|
||||||
data: { names: requestedNames },
|
data: { names: requestedNames },
|
||||||
});
|
});
|
||||||
return normalizeBatchDeleteResponse(payload, requestedNames);
|
return normalizeBatchDeleteResponse(payload);
|
||||||
},
|
},
|
||||||
|
|
||||||
deleteFile: (name: string) => authFilesApi.deleteFiles([name]),
|
deleteFile: (name: string) => authFilesApi.deleteFiles([name]),
|
||||||
|
|||||||
Reference in New Issue
Block a user