@heliosgraphics/epoque 0.0.1-alpha.0 → 0.0.1-alpha.1
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/package.json +1 -1
- package/src/api.ts +21 -6
- package/src/cli.ts +7 -15
- package/src/config.ts +0 -8
package/package.json
CHANGED
package/src/api.ts
CHANGED
|
@@ -2,8 +2,8 @@ import { readFile } from "node:fs/promises"
|
|
|
2
2
|
import type { RemoteArchive, RemoteArticle, RemoteArticleImage, RemoteCollection } from "./types"
|
|
3
3
|
|
|
4
4
|
interface ApiErrorBody {
|
|
5
|
-
error?:
|
|
6
|
-
message?:
|
|
5
|
+
error?: unknown
|
|
6
|
+
message?: unknown
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
type JsonBody = Record<string, unknown> | Array<unknown>
|
|
@@ -77,9 +77,7 @@ export class EpoqueApi {
|
|
|
77
77
|
|
|
78
78
|
const response = await fetch(`${this.#origin}${path}`, { body, headers, method: options.method ?? "GET" })
|
|
79
79
|
|
|
80
|
-
if (!response.ok)
|
|
81
|
-
throw new Error(await getResponseError(response))
|
|
82
|
-
}
|
|
80
|
+
if (!response.ok) throw new Error(await getResponseError(response))
|
|
83
81
|
|
|
84
82
|
if (response.status === 204) return undefined as T
|
|
85
83
|
|
|
@@ -87,11 +85,28 @@ export class EpoqueApi {
|
|
|
87
85
|
}
|
|
88
86
|
}
|
|
89
87
|
|
|
88
|
+
const getErrorMessage = (value: unknown): string | null => {
|
|
89
|
+
if (typeof value === "string") return value.trim() || null
|
|
90
|
+
if (!value || typeof value !== "object") return null
|
|
91
|
+
if (Array.isArray(value)) return getErrorMessage(value[0])
|
|
92
|
+
|
|
93
|
+
const record = value as Record<string, unknown>
|
|
94
|
+
const details = getErrorMessage(record.details)
|
|
95
|
+
const message = getErrorMessage(record.message)
|
|
96
|
+
|
|
97
|
+
if (details && message) return `${message}: ${details}`
|
|
98
|
+
|
|
99
|
+
return details ?? message ?? getErrorMessage(record.error) ?? getErrorMessage(record.code)
|
|
100
|
+
}
|
|
101
|
+
|
|
90
102
|
const getResponseError = async (response: Response): Promise<string> => {
|
|
91
103
|
try {
|
|
92
104
|
const body = (await response.json()) as ApiErrorBody
|
|
105
|
+
const message = getErrorMessage(body.error) ?? getErrorMessage(body.message)
|
|
106
|
+
|
|
107
|
+
if (response.status === 401 && message === "unauthorized") return "invalid API key"
|
|
93
108
|
|
|
94
|
-
return
|
|
109
|
+
return message ?? `request failed with ${response.status}`
|
|
95
110
|
} catch (_error) {
|
|
96
111
|
return `request failed with ${response.status}`
|
|
97
112
|
}
|
package/src/cli.ts
CHANGED
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
import { createInterface } from "node:readline/promises"
|
|
4
4
|
import { stdin as input, stdout as output } from "node:process"
|
|
5
5
|
import { EpoqueApi } from "./api"
|
|
6
|
-
import { getApiKey,
|
|
6
|
+
import { getApiKey, normalizeOrigin, readGlobalConfig, writeGlobalConfig } from "./config"
|
|
7
7
|
import { syncFolder } from "./sync"
|
|
8
8
|
|
|
9
9
|
const HELP = `Usage:
|
|
10
|
-
epoque login
|
|
11
|
-
epoque sync [--dry-run]
|
|
10
|
+
epoque login
|
|
11
|
+
epoque sync [--dry-run]
|
|
12
12
|
`
|
|
13
13
|
|
|
14
14
|
const promptLine = async (question: string): Promise<string> => {
|
|
@@ -68,17 +68,10 @@ const promptSecret = async (question: string): Promise<string> => {
|
|
|
68
68
|
})
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
const getFlagValue = (args: Array<string>, name: string): string | undefined => {
|
|
72
|
-
const index = args.indexOf(name)
|
|
73
|
-
if (index === -1) return undefined
|
|
74
|
-
|
|
75
|
-
return args[index + 1]
|
|
76
|
-
}
|
|
77
|
-
|
|
78
71
|
const hasFlag = (args: Array<string>, name: string): boolean => args.includes(name)
|
|
79
72
|
|
|
80
|
-
const login = async (
|
|
81
|
-
const origin = normalizeOrigin(
|
|
73
|
+
const login = async (): Promise<void> => {
|
|
74
|
+
const origin = normalizeOrigin(undefined)
|
|
82
75
|
const apiKey = (await promptSecret("API key: ")).trim()
|
|
83
76
|
|
|
84
77
|
if (!apiKey) throw new Error("api key is required")
|
|
@@ -93,8 +86,7 @@ const login = async (args: Array<string>): Promise<void> => {
|
|
|
93
86
|
|
|
94
87
|
const sync = async (args: Array<string>): Promise<void> => {
|
|
95
88
|
const cwd = process.cwd()
|
|
96
|
-
const
|
|
97
|
-
const origin = normalizeOrigin(getFlagValue(args, "--origin") ?? projectConfig?.origin ?? (await getStoredOrigin()))
|
|
89
|
+
const origin = normalizeOrigin(undefined)
|
|
98
90
|
const apiKey = await getApiKey()
|
|
99
91
|
|
|
100
92
|
if (!apiKey) throw new Error("not logged in. Run `epoque login` first or set EPOQUE_API_KEY")
|
|
@@ -118,7 +110,7 @@ const main = async (): Promise<void> => {
|
|
|
118
110
|
|
|
119
111
|
switch (command) {
|
|
120
112
|
case "login":
|
|
121
|
-
await login(
|
|
113
|
+
await login()
|
|
122
114
|
return
|
|
123
115
|
case "sync":
|
|
124
116
|
await sync(args)
|
package/src/config.ts
CHANGED
|
@@ -42,14 +42,6 @@ export const getApiKey = async (): Promise<string | null> => {
|
|
|
42
42
|
return config.apiKey ?? null
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
export const getStoredOrigin = async (originOverride?: string): Promise<string> => {
|
|
46
|
-
if (originOverride) return normalizeOrigin(originOverride)
|
|
47
|
-
|
|
48
|
-
const config = await readGlobalConfig()
|
|
49
|
-
|
|
50
|
-
return normalizeOrigin(config.origin)
|
|
51
|
-
}
|
|
52
|
-
|
|
53
45
|
export const readProjectConfig = async (cwd: string): Promise<ProjectConfig | null> => {
|
|
54
46
|
try {
|
|
55
47
|
const content = await readFile(getProjectConfigPath(cwd), "utf8")
|