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/README.md
CHANGED
|
@@ -50,6 +50,7 @@ orizu login
|
|
|
50
50
|
```
|
|
51
51
|
|
|
52
52
|
This will open a browser tab for you to login with. You must either have an account on the [Orizu platform](https://orizu.ai) or it will help you create one.
|
|
53
|
+
Approving the login creates a personal access token for the CLI and stores it in your local Orizu credentials file. You can revoke CLI tokens from the Personal Tokens page in Orizu.
|
|
53
54
|
|
|
54
55
|
**Check the signed-in user**
|
|
55
56
|
|
|
@@ -120,6 +121,10 @@ orizu logout
|
|
|
120
121
|
<td>Append dataset rows</td>
|
|
121
122
|
<td><code>orizu datasets append --dataset <datasetId> --file ./datasets/support-extra.jsonl</code></td>
|
|
122
123
|
</tr>
|
|
124
|
+
<tr>
|
|
125
|
+
<td>Delete a dataset</td>
|
|
126
|
+
<td><code>orizu datasets delete --dataset <datasetId></code> (interactive confirmation required)</td>
|
|
127
|
+
</tr>
|
|
123
128
|
<tr>
|
|
124
129
|
<td>Lock a dataset</td>
|
|
125
130
|
<td><code>orizu datasets lock --dataset <datasetId> --reason "Finalize for labeling"</code></td>
|
package/dist/credentials.js
CHANGED
|
@@ -18,6 +18,13 @@ function isStoredCredentialsV2(value) {
|
|
|
18
18
|
const typed = value;
|
|
19
19
|
return typed.version === 2 && !!typed.servers && typeof typed.servers === 'object';
|
|
20
20
|
}
|
|
21
|
+
function isStoredCredentialsV3(value) {
|
|
22
|
+
if (!value || typeof value !== 'object') {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
const typed = value;
|
|
26
|
+
return typed.version === 3 && !!typed.servers && typeof typed.servers === 'object';
|
|
27
|
+
}
|
|
21
28
|
function isStoredCredentialsV1(value) {
|
|
22
29
|
if (!value || typeof value !== 'object') {
|
|
23
30
|
return false;
|
|
@@ -74,7 +81,7 @@ function writeCredentials(config) {
|
|
|
74
81
|
}
|
|
75
82
|
function createEmptyCredentialsConfig() {
|
|
76
83
|
return {
|
|
77
|
-
version:
|
|
84
|
+
version: 3,
|
|
78
85
|
activeBaseUrl: null,
|
|
79
86
|
servers: {},
|
|
80
87
|
};
|
|
@@ -101,6 +108,9 @@ export function loadCredentialsConfig() {
|
|
|
101
108
|
console.warn('Warning: credentials file contains invalid JSON — please re-login with `orizu login`');
|
|
102
109
|
return null;
|
|
103
110
|
}
|
|
111
|
+
if (isStoredCredentialsV3(parsed)) {
|
|
112
|
+
return parsed;
|
|
113
|
+
}
|
|
104
114
|
if (isStoredCredentialsV2(parsed)) {
|
|
105
115
|
return parsed;
|
|
106
116
|
}
|
|
@@ -121,13 +131,27 @@ export function getServerCredentials(baseUrl) {
|
|
|
121
131
|
return config.servers[baseUrl] || null;
|
|
122
132
|
}
|
|
123
133
|
export function saveServerCredentials(baseUrl, credentials) {
|
|
124
|
-
const
|
|
134
|
+
const loaded = loadCredentialsConfigForWrite();
|
|
135
|
+
const config = loaded.version === 3
|
|
136
|
+
? loaded
|
|
137
|
+
: {
|
|
138
|
+
version: 3,
|
|
139
|
+
activeBaseUrl: loaded.activeBaseUrl,
|
|
140
|
+
servers: loaded.servers,
|
|
141
|
+
};
|
|
125
142
|
config.servers[baseUrl] = credentials;
|
|
126
143
|
config.activeBaseUrl = baseUrl;
|
|
127
144
|
writeCredentials(config);
|
|
128
145
|
}
|
|
129
146
|
export function updateServerCredentials(baseUrl, credentials) {
|
|
130
|
-
const
|
|
147
|
+
const loaded = loadCredentialsConfigForWrite();
|
|
148
|
+
const config = loaded.version === 3
|
|
149
|
+
? loaded
|
|
150
|
+
: {
|
|
151
|
+
version: 3,
|
|
152
|
+
activeBaseUrl: loaded.activeBaseUrl,
|
|
153
|
+
servers: loaded.servers,
|
|
154
|
+
};
|
|
131
155
|
config.servers[baseUrl] = credentials;
|
|
132
156
|
writeCredentials(config);
|
|
133
157
|
}
|
package/dist/http.js
CHANGED
|
@@ -55,11 +55,20 @@ export function assertSecureTokenTransport(baseUrl) {
|
|
|
55
55
|
}
|
|
56
56
|
throw new Error(`Refusing to send CLI tokens to ${baseUrl}. Use HTTPS, or --local for loopback development.`);
|
|
57
57
|
}
|
|
58
|
+
function isSessionCredentials(credentials) {
|
|
59
|
+
return 'accessToken' in credentials;
|
|
60
|
+
}
|
|
61
|
+
function getAuthorizationToken(credentials) {
|
|
62
|
+
return isSessionCredentials(credentials) ? credentials.accessToken : credentials.apiKey;
|
|
63
|
+
}
|
|
58
64
|
function isExpired(expiresAt) {
|
|
59
65
|
const nowUnix = Math.floor(Date.now() / 1000);
|
|
60
66
|
return expiresAt <= nowUnix + 30;
|
|
61
67
|
}
|
|
62
68
|
async function refreshCredentials(baseUrl, credentials) {
|
|
69
|
+
if (!isSessionCredentials(credentials)) {
|
|
70
|
+
throw new Error('API key credentials do not refresh. Run `orizu login` again if access fails.');
|
|
71
|
+
}
|
|
63
72
|
assertSecureTokenTransport(baseUrl);
|
|
64
73
|
const response = await fetch(`${baseUrl}/api/cli/auth/refresh`, {
|
|
65
74
|
method: 'POST',
|
|
@@ -70,7 +79,11 @@ async function refreshCredentials(baseUrl, credentials) {
|
|
|
70
79
|
throw new Error('Session expired. Run `orizu login` again.');
|
|
71
80
|
}
|
|
72
81
|
const data = await response.json();
|
|
82
|
+
if (!data.accessToken || !data.refreshToken || !data.expiresAt) {
|
|
83
|
+
throw new Error('Server returned invalid refresh credentials. Run `orizu login` again.');
|
|
84
|
+
}
|
|
73
85
|
const refreshed = {
|
|
86
|
+
credentialType: 'session',
|
|
74
87
|
accessToken: data.accessToken,
|
|
75
88
|
refreshToken: data.refreshToken,
|
|
76
89
|
expiresAt: data.expiresAt,
|
|
@@ -86,23 +99,23 @@ export async function authedFetch(path, init = {}) {
|
|
|
86
99
|
throw new Error(`Not logged in for ${baseUrl}. Run \`orizu login --server ${baseUrl}\` (or \`--local\`) first.`);
|
|
87
100
|
}
|
|
88
101
|
let activeCredentials = credentials;
|
|
89
|
-
if (isExpired(activeCredentials.expiresAt)) {
|
|
102
|
+
if (isSessionCredentials(activeCredentials) && isExpired(activeCredentials.expiresAt)) {
|
|
90
103
|
activeCredentials = await refreshCredentials(baseUrl, activeCredentials);
|
|
91
104
|
}
|
|
92
105
|
let response = await fetch(`${baseUrl}${path}`, {
|
|
93
106
|
...init,
|
|
94
107
|
headers: {
|
|
95
108
|
...(init.headers || {}),
|
|
96
|
-
Authorization: `Bearer ${activeCredentials
|
|
109
|
+
Authorization: `Bearer ${getAuthorizationToken(activeCredentials)}`,
|
|
97
110
|
},
|
|
98
111
|
});
|
|
99
|
-
if (response.status === 401) {
|
|
112
|
+
if (response.status === 401 && isSessionCredentials(activeCredentials)) {
|
|
100
113
|
activeCredentials = await refreshCredentials(baseUrl, activeCredentials);
|
|
101
114
|
response = await fetch(`${baseUrl}${path}`, {
|
|
102
115
|
...init,
|
|
103
116
|
headers: {
|
|
104
117
|
...(init.headers || {}),
|
|
105
|
-
Authorization: `Bearer ${activeCredentials
|
|
118
|
+
Authorization: `Bearer ${getAuthorizationToken(activeCredentials)}`,
|
|
106
119
|
},
|
|
107
120
|
});
|
|
108
121
|
}
|