Skip to content

Commit d5a24ce

Browse files
committed
Semi
1 parent e7c9cd7 commit d5a24ce

File tree

3 files changed

+75
-17
lines changed

3 files changed

+75
-17
lines changed

src/api/http.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,20 @@ export async function fetchPost<T>(url: string, body?: T, option?: Option): Prom
3232
}
3333
}
3434

35+
export async function fetchPut<T>(url: string, body?: T, option?: Option): Promise<Response> {
36+
try {
37+
const response = await fetch(url, {
38+
...(option || {}),
39+
method: "PUT",
40+
body: body ? JSON.stringify(body) : null,
41+
})
42+
return response
43+
} catch (e) {
44+
console.error("Failed to fetch post", e)
45+
throw Error(e)
46+
}
47+
}
48+
3549
export async function fetchPutText(url: string, bodyText?: string, option?: Option): Promise<Response> {
3650
try {
3751
const response = await fetch(url, {

src/api/quantified-resume.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { fetchGet, fetchPost } from "./http"
1+
import { fetchGet, fetchPost, fetchPut } from "./http"
22

33
const QR_BUILTIN_TYPE = "BrowserTime"
44
export const DEFAULT_ENDPOINT = "http://localhost:12233"
@@ -22,6 +22,12 @@ export type QrRequestContext = {
2222
endpoint?: string
2323
}
2424

25+
const headers = (): Headers => {
26+
const headers = new Headers()
27+
headers.append("Content-Type", "application/json")
28+
return headers
29+
}
30+
2531
export const listBuckets = async (ctx: QrRequestContext, clientId?: string): Promise<Bucket[]> => {
2632
const response = await fetchGet(`${ctx?.endpoint || DEFAULT_ENDPOINT}/api/0/bucket?bt=${QR_BUILTIN_TYPE}&bt_rid=${clientId || ''}`)
2733
const status = response?.status
@@ -36,7 +42,7 @@ export const listBuckets = async (ctx: QrRequestContext, clientId?: string): Pro
3642
}
3743

3844
export const createBucket = async (ctx: QrRequestContext, bucket: Bucket): Promise<number> => {
39-
const response = await fetchPost(`${ctx?.endpoint || DEFAULT_ENDPOINT}/api/0/bucket`, bucket)
45+
const response = await fetchPost(`${ctx?.endpoint || DEFAULT_ENDPOINT}/api/0/bucket`, bucket, { headers: headers() })
4046
const status = response?.status
4147
if (status === 200) {
4248
return await response.json()
@@ -46,4 +52,18 @@ export const createBucket = async (ctx: QrRequestContext, bucket: Bucket): Promi
4652
console.error(response)
4753
throw new Error("Unexpected status code: " + status)
4854
}
55+
}
56+
57+
export const updateBucket = async (ctx: QrRequestContext, bucket: Bucket): Promise<void> => {
58+
const response = await fetchPut(`${ctx?.endpoint || DEFAULT_ENDPOINT}/api/0/bucket/${bucket?.id}`, bucket, { headers: headers() })
59+
const status = response?.status
60+
if (status === 200) {
61+
return
62+
}
63+
if (status === 422) {
64+
throw new Error("Failed to connect Quantified Resume, please contact the developer")
65+
} else {
66+
console.error(response)
67+
throw new Error("Unexpected status code: " + status)
68+
}
4969
}

src/common/backup/quantified-resume/coordinator.ts

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
import { Bucket, listBuckets } from "@api/quantified-resume"
1+
import { Bucket, createBucket, listBuckets, updateBucket } from "@api/quantified-resume"
2+
import metaMessages, { } from "@i18n/message/common/meta"
3+
import { t } from "@i18n"
4+
import { groupBy } from "@util/array"
25

36
export type QuantifiedResumeCache = {
47
bucketIds: {
@@ -7,6 +10,19 @@ export type QuantifiedResumeCache = {
710
}
811
}
912

13+
async function createNewBucket(context: timer.backup.CoordinatorContext<QuantifiedResumeCache>): Promise<number> {
14+
const { cid, cname } = context || {}
15+
const { endpoint } = context?.ext || {}
16+
const appName = t(metaMessages, { key: msg => msg.name })
17+
const bucket: Bucket = {
18+
name: `${appName}: ${cid}`,
19+
builtin: "BrowserTime",
20+
builtinRefId: cid,
21+
payload: { name: cname }
22+
}
23+
return createBucket({ endpoint }, bucket)
24+
}
25+
1026
async function getBucketId(context: timer.backup.CoordinatorContext<QuantifiedResumeCache>): Promise<number> {
1127
const { cid, cache } = context || {}
1228
// 1. query from cache
@@ -16,25 +32,31 @@ async function getBucketId(context: timer.backup.CoordinatorContext<QuantifiedRe
1632
const { endpoint } = context?.ext || {}
1733
// 2. query again
1834
bucketId = (await listBuckets({ endpoint }, cid))?.[0]?.id
19-
// TODO
2035
if (!bucketId) {
2136
// 3. create one
22-
const bucket: Bucket = {
23-
name: "Time Tracker: " + cid,
24-
builtin: "BrowserTime",
25-
builtinRefId: cid,
26-
payload: {
27-
name: ""
28-
}
29-
}
37+
bucketId = await createNewBucket(context)
3038
}
31-
throw new Error("TODO")
39+
return bucketId
3240
}
3341

3442
export default class QuantifiedResumeCoordinator implements timer.backup.Coordinator<QuantifiedResumeCache> {
35-
36-
updateClients(_: timer.backup.CoordinatorContext<QuantifiedResumeCache>, clients: timer.backup.Client[]): Promise<void> {
37-
throw new Error("Method not implemented.");
43+
async updateClients(context: timer.backup.CoordinatorContext<QuantifiedResumeCache>, clients: timer.backup.Client[]): Promise<void> {
44+
const { endpoint } = context?.ext || {}
45+
const existBuckets = groupBy(await listBuckets({ endpoint }) || [], b => b.builtinRefId, l => l?.[0])
46+
if (!clients?.length) return
47+
const promises = Promise.all(clients.map(
48+
async ({ id, name, minDate, maxDate }) => {
49+
const exist = existBuckets[id]
50+
if (exist) {
51+
// update payload
52+
exist.payload = { name, minDate, maxDate }
53+
await updateBucket({ endpoint }, exist)
54+
} else {
55+
await createNewBucket(context)
56+
}
57+
})
58+
)
59+
await promises
3860
}
3961

4062
async listAllClients(context: timer.backup.CoordinatorContext<QuantifiedResumeCache>): Promise<timer.backup.Client[]> {
@@ -66,7 +88,9 @@ export default class QuantifiedResumeCoordinator implements timer.backup.Coordin
6688

6789
async upload(context: timer.backup.CoordinatorContext<QuantifiedResumeCache>, rows: timer.stat.RowBase[]): Promise<void> {
6890
const bucketId = await getBucketId(context)
69-
throw new Error("Method not implemented.");
91+
rows.forEach(row => {
92+
93+
})
7094
}
7195

7296
async testAuth(_auth: timer.backup.Auth, ext: timer.backup.TypeExt): Promise<string> {

0 commit comments

Comments
 (0)