forked from mxx1111/mdlook
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclient.ts
More file actions
108 lines (97 loc) · 3.11 KB
/
Copy pathclient.ts
File metadata and controls
108 lines (97 loc) · 3.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import type { CloudDocument, DocumentConflict } from './types'
import type { ApiError } from '@/services/account/client'
import { MdApiClient } from '@/services/account/client'
function asRecord(value: unknown): Record<string, unknown> | null {
return value && typeof value === `object` && !Array.isArray(value)
? value as Record<string, unknown>
: null
}
function normalizeDocument(value: unknown): CloudDocument | null {
const record = asRecord(value)
if (
!record
|| typeof record.id !== `string`
|| typeof record.title !== `string`
|| typeof record.content !== `string`
|| typeof record.version !== `number`
) {
return null
}
const updatedAt = typeof record.updatedAt === `string`
? record.updatedAt
: typeof record.updatedAt === `number`
? new Date(record.updatedAt).toISOString()
: new Date().toISOString()
return {
id: record.id,
title: record.title,
content: record.content,
version: record.version,
updatedAt,
deleted: record.deleted === true,
}
}
function normalizeDocumentList(value: unknown): CloudDocument[] {
const record = asRecord(value)
let candidate: unknown[] = []
if (Array.isArray(value))
candidate = value
else if (Array.isArray(record?.documents))
candidate = record.documents
else if (Array.isArray(record?.items))
candidate = record.items
return candidate
.map(normalizeDocument)
.filter((document): document is CloudDocument => Boolean(document))
}
export function conflictFromApiError(error: ApiError): DocumentConflict | null {
if (error.status !== 409)
return null
const body = error.body
const extra = asRecord(body?.extra)
const current = normalizeDocument(body?.data)
?? normalizeDocument(extra?.current)
?? normalizeDocument(body?.current)
return current ? { current } : null
}
/**
* blog-system 的文档传输 Adapter。
*
* 只发送 CloudDocument 白名单,LocalDocumentMetadata 永远不会越过这个 seam。
*/
export class DocumentClient extends MdApiClient {
list(updatedSince?: string): Promise<CloudDocument[]> {
const query = updatedSince
? `?updatedSince=${encodeURIComponent(updatedSince)}`
: ``
return this.request<unknown>(`GET`, `/mdlook/documents${query}`)
.then(normalizeDocumentList)
}
get(id: string): Promise<CloudDocument> {
return this.request<unknown>(`GET`, `/mdlook/documents/${encodeURIComponent(id)}`)
.then((value) => {
const document = normalizeDocument(value)
if (!document)
throw new Error(`文档响应格式无效`)
return document
})
}
put(document: CloudDocument): Promise<CloudDocument> {
return this.request<unknown>(
`PUT`,
`/mdlook/documents/${encodeURIComponent(document.id)}`,
{
title: document.title,
content: document.content,
version: document.version,
updatedAt: document.updatedAt,
deleted: document.deleted,
},
).then((value) => {
const saved = normalizeDocument(value)
if (!saved)
throw new Error(`文档保存响应格式无效`)
return saved
})
}
}