orizu 0.1.6 → 0.2.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/README.md +5 -0
- package/dist/credentials.js +27 -3
- package/dist/http.js +17 -4
- package/dist/index.js +179 -100
- package/package.json +1 -1
- package/src/credentials.ts +40 -8
- package/src/http.ts +22 -5
- package/src/index.ts +211 -101
- package/src/types.ts +19 -4
package/package.json
CHANGED
package/src/credentials.ts
CHANGED
|
@@ -13,7 +13,12 @@ import {
|
|
|
13
13
|
import { join } from 'path'
|
|
14
14
|
import { homedir } from 'os'
|
|
15
15
|
import { randomBytes } from 'crypto'
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
ServerCredentials,
|
|
18
|
+
StoredCredentialsV1,
|
|
19
|
+
StoredCredentialsV2,
|
|
20
|
+
StoredCredentialsV3,
|
|
21
|
+
} from './types.js'
|
|
17
22
|
|
|
18
23
|
function getConfigDir(): string {
|
|
19
24
|
if (process.env.ORIZU_CONFIG_DIR) {
|
|
@@ -35,6 +40,15 @@ function isStoredCredentialsV2(value: unknown): value is StoredCredentialsV2 {
|
|
|
35
40
|
return typed.version === 2 && !!typed.servers && typeof typed.servers === 'object'
|
|
36
41
|
}
|
|
37
42
|
|
|
43
|
+
function isStoredCredentialsV3(value: unknown): value is StoredCredentialsV3 {
|
|
44
|
+
if (!value || typeof value !== 'object') {
|
|
45
|
+
return false
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const typed = value as Partial<StoredCredentialsV3>
|
|
49
|
+
return typed.version === 3 && !!typed.servers && typeof typed.servers === 'object'
|
|
50
|
+
}
|
|
51
|
+
|
|
38
52
|
function isStoredCredentialsV1(value: unknown): value is StoredCredentialsV1 {
|
|
39
53
|
if (!value || typeof value !== 'object') {
|
|
40
54
|
return false
|
|
@@ -63,7 +77,7 @@ function migrateToV2(stored: StoredCredentialsV1): StoredCredentialsV2 {
|
|
|
63
77
|
}
|
|
64
78
|
}
|
|
65
79
|
|
|
66
|
-
function writeCredentials(config: StoredCredentialsV2) {
|
|
80
|
+
function writeCredentials(config: StoredCredentialsV2 | StoredCredentialsV3) {
|
|
67
81
|
const dir = getConfigDir()
|
|
68
82
|
mkdirSync(dir, { recursive: true, mode: 0o700 })
|
|
69
83
|
chmodSync(dir, 0o700)
|
|
@@ -98,15 +112,15 @@ function writeCredentials(config: StoredCredentialsV2) {
|
|
|
98
112
|
chmodSync(path, 0o600)
|
|
99
113
|
}
|
|
100
114
|
|
|
101
|
-
function createEmptyCredentialsConfig():
|
|
115
|
+
function createEmptyCredentialsConfig(): StoredCredentialsV3 {
|
|
102
116
|
return {
|
|
103
|
-
version:
|
|
117
|
+
version: 3 as const,
|
|
104
118
|
activeBaseUrl: null,
|
|
105
119
|
servers: {},
|
|
106
120
|
}
|
|
107
121
|
}
|
|
108
122
|
|
|
109
|
-
function loadCredentialsConfigForWrite(): StoredCredentialsV2 {
|
|
123
|
+
function loadCredentialsConfigForWrite(): StoredCredentialsV2 | StoredCredentialsV3 {
|
|
110
124
|
try {
|
|
111
125
|
return loadCredentialsConfig() || createEmptyCredentialsConfig()
|
|
112
126
|
} catch {
|
|
@@ -114,7 +128,7 @@ function loadCredentialsConfigForWrite(): StoredCredentialsV2 {
|
|
|
114
128
|
}
|
|
115
129
|
}
|
|
116
130
|
|
|
117
|
-
export function loadCredentialsConfig(): StoredCredentialsV2 | null {
|
|
131
|
+
export function loadCredentialsConfig(): StoredCredentialsV2 | StoredCredentialsV3 | null {
|
|
118
132
|
const path = getCredentialsPath()
|
|
119
133
|
if (!existsSync(path)) {
|
|
120
134
|
return null
|
|
@@ -130,6 +144,10 @@ export function loadCredentialsConfig(): StoredCredentialsV2 | null {
|
|
|
130
144
|
return null
|
|
131
145
|
}
|
|
132
146
|
|
|
147
|
+
if (isStoredCredentialsV3(parsed)) {
|
|
148
|
+
return parsed
|
|
149
|
+
}
|
|
150
|
+
|
|
133
151
|
if (isStoredCredentialsV2(parsed)) {
|
|
134
152
|
return parsed
|
|
135
153
|
}
|
|
@@ -156,7 +174,14 @@ export function getServerCredentials(baseUrl: string): ServerCredentials | null
|
|
|
156
174
|
}
|
|
157
175
|
|
|
158
176
|
export function saveServerCredentials(baseUrl: string, credentials: ServerCredentials) {
|
|
159
|
-
const
|
|
177
|
+
const loaded = loadCredentialsConfigForWrite()
|
|
178
|
+
const config: StoredCredentialsV3 = loaded.version === 3
|
|
179
|
+
? loaded
|
|
180
|
+
: {
|
|
181
|
+
version: 3,
|
|
182
|
+
activeBaseUrl: loaded.activeBaseUrl,
|
|
183
|
+
servers: loaded.servers,
|
|
184
|
+
}
|
|
160
185
|
|
|
161
186
|
config.servers[baseUrl] = credentials
|
|
162
187
|
config.activeBaseUrl = baseUrl
|
|
@@ -164,7 +189,14 @@ export function saveServerCredentials(baseUrl: string, credentials: ServerCreden
|
|
|
164
189
|
}
|
|
165
190
|
|
|
166
191
|
export function updateServerCredentials(baseUrl: string, credentials: ServerCredentials) {
|
|
167
|
-
const
|
|
192
|
+
const loaded = loadCredentialsConfigForWrite()
|
|
193
|
+
const config: StoredCredentialsV3 = loaded.version === 3
|
|
194
|
+
? loaded
|
|
195
|
+
: {
|
|
196
|
+
version: 3,
|
|
197
|
+
activeBaseUrl: loaded.activeBaseUrl,
|
|
198
|
+
servers: loaded.servers,
|
|
199
|
+
}
|
|
168
200
|
config.servers[baseUrl] = credentials
|
|
169
201
|
writeCredentials(config)
|
|
170
202
|
}
|
package/src/http.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getActiveBaseUrl, getServerCredentials, updateServerCredentials } from './credentials.js'
|
|
2
2
|
import { getFlagBaseUrl, GlobalFlags, normalizeBaseUrl } from './global-flags.js'
|
|
3
|
-
import { LoginResponse, ServerCredentials } from './types.js'
|
|
3
|
+
import { LoginResponse, ServerCredentials, SessionServerCredentials } from './types.js'
|
|
4
4
|
|
|
5
5
|
let runtimeFlags: GlobalFlags = { local: false, server: null }
|
|
6
6
|
|
|
@@ -75,12 +75,24 @@ export function assertSecureTokenTransport(baseUrl: string) {
|
|
|
75
75
|
)
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
function isSessionCredentials(credentials: ServerCredentials): credentials is SessionServerCredentials {
|
|
79
|
+
return 'accessToken' in credentials
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function getAuthorizationToken(credentials: ServerCredentials): string {
|
|
83
|
+
return isSessionCredentials(credentials) ? credentials.accessToken : credentials.apiKey
|
|
84
|
+
}
|
|
85
|
+
|
|
78
86
|
function isExpired(expiresAt: number): boolean {
|
|
79
87
|
const nowUnix = Math.floor(Date.now() / 1000)
|
|
80
88
|
return expiresAt <= nowUnix + 30
|
|
81
89
|
}
|
|
82
90
|
|
|
83
91
|
async function refreshCredentials(baseUrl: string, credentials: ServerCredentials): Promise<ServerCredentials> {
|
|
92
|
+
if (!isSessionCredentials(credentials)) {
|
|
93
|
+
throw new Error('API key credentials do not refresh. Run `orizu login` again if access fails.')
|
|
94
|
+
}
|
|
95
|
+
|
|
84
96
|
assertSecureTokenTransport(baseUrl)
|
|
85
97
|
const response = await fetch(`${baseUrl}/api/cli/auth/refresh`, {
|
|
86
98
|
method: 'POST',
|
|
@@ -93,7 +105,12 @@ async function refreshCredentials(baseUrl: string, credentials: ServerCredential
|
|
|
93
105
|
}
|
|
94
106
|
|
|
95
107
|
const data = await response.json() as LoginResponse
|
|
108
|
+
if (!data.accessToken || !data.refreshToken || !data.expiresAt) {
|
|
109
|
+
throw new Error('Server returned invalid refresh credentials. Run `orizu login` again.')
|
|
110
|
+
}
|
|
111
|
+
|
|
96
112
|
const refreshed = {
|
|
113
|
+
credentialType: 'session' as const,
|
|
97
114
|
accessToken: data.accessToken,
|
|
98
115
|
refreshToken: data.refreshToken,
|
|
99
116
|
expiresAt: data.expiresAt,
|
|
@@ -111,7 +128,7 @@ export async function authedFetch(path: string, init: RequestInit = {}) {
|
|
|
111
128
|
}
|
|
112
129
|
|
|
113
130
|
let activeCredentials = credentials
|
|
114
|
-
if (isExpired(activeCredentials.expiresAt)) {
|
|
131
|
+
if (isSessionCredentials(activeCredentials) && isExpired(activeCredentials.expiresAt)) {
|
|
115
132
|
activeCredentials = await refreshCredentials(baseUrl, activeCredentials)
|
|
116
133
|
}
|
|
117
134
|
|
|
@@ -119,17 +136,17 @@ export async function authedFetch(path: string, init: RequestInit = {}) {
|
|
|
119
136
|
...init,
|
|
120
137
|
headers: {
|
|
121
138
|
...(init.headers || {}),
|
|
122
|
-
Authorization: `Bearer ${activeCredentials
|
|
139
|
+
Authorization: `Bearer ${getAuthorizationToken(activeCredentials)}`,
|
|
123
140
|
},
|
|
124
141
|
})
|
|
125
142
|
|
|
126
|
-
if (response.status === 401) {
|
|
143
|
+
if (response.status === 401 && isSessionCredentials(activeCredentials)) {
|
|
127
144
|
activeCredentials = await refreshCredentials(baseUrl, activeCredentials)
|
|
128
145
|
response = await fetch(`${baseUrl}${path}`, {
|
|
129
146
|
...init,
|
|
130
147
|
headers: {
|
|
131
148
|
...(init.headers || {}),
|
|
132
|
-
Authorization: `Bearer ${activeCredentials
|
|
149
|
+
Authorization: `Bearer ${getAuthorizationToken(activeCredentials)}`,
|
|
133
150
|
},
|
|
134
151
|
})
|
|
135
152
|
}
|