@brantrusnak/openclaw-omadeus 1.0.2 → 1.0.4
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 +15 -61
- package/dist/_virtual/_rolldown/runtime.js +4 -0
- package/dist/api.js +5 -0
- package/dist/index.js +14 -0
- package/dist/runtime-api.js +15 -0
- package/dist/setup-entry.js +7 -0
- package/dist/src/allowed-reaction-emojis.js +21 -0
- package/dist/src/api/auth.api.js +118 -0
- package/dist/src/api/channel.api.js +23 -0
- package/dist/src/api/message.api.js +76 -0
- package/dist/src/api/nugget.api.js +127 -0
- package/dist/src/auth.js +30 -0
- package/dist/src/channel.js +626 -0
- package/dist/src/config.js +52 -0
- package/dist/src/defaults.js +5 -0
- package/dist/src/inbound-policy.js +205 -0
- package/dist/src/inbound.js +97 -0
- package/dist/src/member-resolve.js +53 -0
- package/dist/src/message-handler.js +262 -0
- package/dist/src/nugget-lookup.js +140 -0
- package/dist/src/onboarding.js +357 -0
- package/dist/src/outbound.js +17 -0
- package/dist/src/reply-dispatcher.js +46 -0
- package/dist/src/runtime.js +5 -0
- package/dist/src/setup-core.js +46 -0
- package/dist/src/setup-surface.js +2 -0
- package/dist/src/socket/dolphin.socket.js +18 -0
- package/dist/src/socket/jaguar.socket.js +22 -0
- package/dist/src/socket/socket.js +153 -0
- package/dist/src/store.js +13 -0
- package/dist/src/token.js +84 -0
- package/dist/src/types.js +15 -0
- package/dist/src/utils/http.util.js +43 -0
- package/dist/src/utils/jwt.util.js +15 -0
- package/package.json +10 -3
- package/src/api/auth.api.ts +27 -7
- package/src/channel.ts +127 -238
- package/src/member-resolve.ts +1 -1
- package/src/onboarding.ts +117 -163
- package/src/setup-core.ts +10 -1
- package/src/socket/socket.ts +24 -11
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { WebSocket } from "ws";
|
|
2
|
+
//#region src/socket/socket.ts
|
|
3
|
+
const RECONNECT_BASE_MS = 2e3;
|
|
4
|
+
const RECONNECT_MAX_MS = 6e4;
|
|
5
|
+
const HEARTBEAT_INTERVAL_MS = 3e4;
|
|
6
|
+
const HEARTBEAT_MISSED_MAX = 5;
|
|
7
|
+
const KEEP_ALIVE_CONTENT = "keep-alive";
|
|
8
|
+
const KEEP_ALIVE_ACTION = "answer";
|
|
9
|
+
function isServerKeepAlive(data) {
|
|
10
|
+
return data.content === KEEP_ALIVE_CONTENT;
|
|
11
|
+
}
|
|
12
|
+
function isClientKeepAlive(data) {
|
|
13
|
+
return data.data === KEEP_ALIVE_CONTENT;
|
|
14
|
+
}
|
|
15
|
+
function createOmadeusSocketClient(opts) {
|
|
16
|
+
const { maestroUrl, tokenManager, pathSuffix, logPrefix, onEvent, onConnect, onDisconnect, onError, log } = opts;
|
|
17
|
+
let ws = null;
|
|
18
|
+
let reconnectAttempt = 0;
|
|
19
|
+
let reconnectTimer = null;
|
|
20
|
+
let heartbeatTimer = null;
|
|
21
|
+
let heartbeatMissCount = 0;
|
|
22
|
+
let intentionalClose = false;
|
|
23
|
+
function buildWsUrl() {
|
|
24
|
+
const base = maestroUrl.replace(/^http/, "ws");
|
|
25
|
+
const token = tokenManager.getToken();
|
|
26
|
+
return `${base}/${pathSuffix}?token=${encodeURIComponent(token)}`;
|
|
27
|
+
}
|
|
28
|
+
function scheduleReconnect() {
|
|
29
|
+
if (intentionalClose) return;
|
|
30
|
+
const delayMs = Math.min(RECONNECT_BASE_MS * 2 ** reconnectAttempt, RECONNECT_MAX_MS);
|
|
31
|
+
reconnectAttempt++;
|
|
32
|
+
log?.info(`${logPrefix} reconnecting in ${delayMs}ms (attempt ${reconnectAttempt})`);
|
|
33
|
+
reconnectTimer = setTimeout(() => connect(), delayMs);
|
|
34
|
+
}
|
|
35
|
+
function stopHeartbeat() {
|
|
36
|
+
if (heartbeatTimer) {
|
|
37
|
+
clearInterval(heartbeatTimer);
|
|
38
|
+
heartbeatTimer = null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function resetHeartbeat() {
|
|
42
|
+
heartbeatMissCount = 0;
|
|
43
|
+
}
|
|
44
|
+
function sendKeepAlive() {
|
|
45
|
+
if (ws?.readyState !== WebSocket.OPEN) return;
|
|
46
|
+
heartbeatMissCount += 1;
|
|
47
|
+
sendKeepAliveFrame();
|
|
48
|
+
if (heartbeatMissCount >= HEARTBEAT_MISSED_MAX) {
|
|
49
|
+
log?.warn(`${logPrefix} heartbeat unanswered ${heartbeatMissCount} times; reconnecting socket`);
|
|
50
|
+
ws.close();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function startHeartbeat() {
|
|
54
|
+
stopHeartbeat();
|
|
55
|
+
heartbeatTimer = setInterval(() => {
|
|
56
|
+
sendKeepAlive();
|
|
57
|
+
}, HEARTBEAT_INTERVAL_MS);
|
|
58
|
+
}
|
|
59
|
+
function sendKeepAliveFrame() {
|
|
60
|
+
if (ws?.readyState === WebSocket.OPEN) ws.send(JSON.stringify({
|
|
61
|
+
data: KEEP_ALIVE_CONTENT,
|
|
62
|
+
action: KEEP_ALIVE_ACTION
|
|
63
|
+
}));
|
|
64
|
+
}
|
|
65
|
+
function connect() {
|
|
66
|
+
if (ws) {
|
|
67
|
+
ws.removeAllListeners();
|
|
68
|
+
ws.close();
|
|
69
|
+
ws = null;
|
|
70
|
+
}
|
|
71
|
+
intentionalClose = false;
|
|
72
|
+
stopHeartbeat();
|
|
73
|
+
resetHeartbeat();
|
|
74
|
+
if (tokenManager.needsRefresh()) {
|
|
75
|
+
tokenManager.refresh().then(() => connect()).catch((err) => {
|
|
76
|
+
onError?.(err instanceof Error ? err : new Error(String(err)));
|
|
77
|
+
scheduleReconnect();
|
|
78
|
+
});
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const url = buildWsUrl();
|
|
82
|
+
log?.info(`${logPrefix} connecting...`);
|
|
83
|
+
ws = new WebSocket(url);
|
|
84
|
+
ws.on("open", () => {
|
|
85
|
+
reconnectAttempt = 0;
|
|
86
|
+
log?.info(`${logPrefix} connected`);
|
|
87
|
+
onConnect?.();
|
|
88
|
+
resetHeartbeat();
|
|
89
|
+
sendKeepAlive();
|
|
90
|
+
startHeartbeat();
|
|
91
|
+
});
|
|
92
|
+
ws.on("message", (raw) => {
|
|
93
|
+
try {
|
|
94
|
+
const data = JSON.parse(String(raw));
|
|
95
|
+
const action = data.action;
|
|
96
|
+
if (isServerKeepAlive(data) && action === KEEP_ALIVE_ACTION) {
|
|
97
|
+
resetHeartbeat();
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (isClientKeepAlive(data) && action === KEEP_ALIVE_ACTION) {
|
|
101
|
+
resetHeartbeat();
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (isServerKeepAlive(data) && action === "heartbeat") {
|
|
105
|
+
resetHeartbeat();
|
|
106
|
+
sendKeepAliveFrame();
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
resetHeartbeat();
|
|
110
|
+
onEvent?.(data);
|
|
111
|
+
} catch {
|
|
112
|
+
log?.warn(`${logPrefix} unparseable message: ${String(raw).slice(0, 200)}`);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
ws.on("close", (code, reason) => {
|
|
116
|
+
const msg = `code=${code} reason=${String(reason)}`;
|
|
117
|
+
log?.info(`${logPrefix} disconnected: ${msg}`);
|
|
118
|
+
onDisconnect?.(msg);
|
|
119
|
+
ws = null;
|
|
120
|
+
stopHeartbeat();
|
|
121
|
+
resetHeartbeat();
|
|
122
|
+
scheduleReconnect();
|
|
123
|
+
});
|
|
124
|
+
ws.on("error", (err) => {
|
|
125
|
+
log?.error(`${logPrefix} error: ${err.message}`);
|
|
126
|
+
onError?.(err);
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
function disconnect() {
|
|
130
|
+
intentionalClose = true;
|
|
131
|
+
if (reconnectTimer) {
|
|
132
|
+
clearTimeout(reconnectTimer);
|
|
133
|
+
reconnectTimer = null;
|
|
134
|
+
}
|
|
135
|
+
stopHeartbeat();
|
|
136
|
+
resetHeartbeat();
|
|
137
|
+
if (ws) {
|
|
138
|
+
ws.removeAllListeners();
|
|
139
|
+
ws.close();
|
|
140
|
+
ws = null;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return {
|
|
144
|
+
connect,
|
|
145
|
+
disconnect,
|
|
146
|
+
isConnected: () => ws?.readyState === WebSocket.OPEN,
|
|
147
|
+
send: (data) => {
|
|
148
|
+
if (ws?.readyState === WebSocket.OPEN) ws.send(JSON.stringify(data));
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
//#endregion
|
|
153
|
+
export { createOmadeusSocketClient };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region src/store.ts
|
|
2
|
+
let currentSession = null;
|
|
3
|
+
function setCasSession(session) {
|
|
4
|
+
currentSession = session;
|
|
5
|
+
}
|
|
6
|
+
function getCasSession() {
|
|
7
|
+
return currentSession;
|
|
8
|
+
}
|
|
9
|
+
function clearCasSession() {
|
|
10
|
+
currentSession = null;
|
|
11
|
+
}
|
|
12
|
+
//#endregion
|
|
13
|
+
export { clearCasSession, getCasSession, setCasSession };
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { decodeJwtPayload, tokenExpiresInMs } from "./utils/jwt.util.js";
|
|
2
|
+
import { authenticate } from "./auth.js";
|
|
3
|
+
//#region src/token.ts
|
|
4
|
+
const TOKEN_REFRESH_MARGIN_MS = 300 * 1e3;
|
|
5
|
+
const MAX_TIMEOUT_MS = 2147483647;
|
|
6
|
+
/** Whether the token should be refreshed now (within safety margin). */
|
|
7
|
+
function shouldRefreshToken(token) {
|
|
8
|
+
return tokenExpiresInMs(token) < TOKEN_REFRESH_MARGIN_MS;
|
|
9
|
+
}
|
|
10
|
+
function createTokenManager(params) {
|
|
11
|
+
const { casUrl, maestroUrl, email, password, organizationId, initialToken, onRefresh, onError } = params;
|
|
12
|
+
let currentToken = "";
|
|
13
|
+
let currentPayload = null;
|
|
14
|
+
if (initialToken) try {
|
|
15
|
+
const payload = decodeJwtPayload(initialToken);
|
|
16
|
+
currentToken = initialToken;
|
|
17
|
+
currentPayload = payload;
|
|
18
|
+
} catch (err) {
|
|
19
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
20
|
+
onError?.(error);
|
|
21
|
+
}
|
|
22
|
+
let refreshTimer = null;
|
|
23
|
+
const refresh = async () => {
|
|
24
|
+
if (currentToken && !shouldRefreshToken(currentToken)) return;
|
|
25
|
+
const { dolphinToken, payload } = await authenticate({
|
|
26
|
+
casUrl,
|
|
27
|
+
maestroUrl,
|
|
28
|
+
email,
|
|
29
|
+
password,
|
|
30
|
+
organizationId
|
|
31
|
+
});
|
|
32
|
+
currentToken = dolphinToken;
|
|
33
|
+
currentPayload = payload;
|
|
34
|
+
onRefresh?.(dolphinToken);
|
|
35
|
+
};
|
|
36
|
+
const scheduleNextRefresh = () => {
|
|
37
|
+
if (refreshTimer) {
|
|
38
|
+
clearTimeout(refreshTimer);
|
|
39
|
+
refreshTimer = null;
|
|
40
|
+
}
|
|
41
|
+
if (!currentToken) return;
|
|
42
|
+
const desiredDelayMs = tokenExpiresInMs(currentToken) - TOKEN_REFRESH_MARGIN_MS;
|
|
43
|
+
refreshTimer = setTimeout(async () => {
|
|
44
|
+
try {
|
|
45
|
+
await refresh();
|
|
46
|
+
scheduleNextRefresh();
|
|
47
|
+
} catch (err) {
|
|
48
|
+
onError?.(err instanceof Error ? err : new Error(String(err)));
|
|
49
|
+
refreshTimer = setTimeout(() => void scheduleNextRefresh(), 3e4);
|
|
50
|
+
}
|
|
51
|
+
}, Math.min(Math.max(desiredDelayMs, 1e4), MAX_TIMEOUT_MS));
|
|
52
|
+
};
|
|
53
|
+
return {
|
|
54
|
+
getToken() {
|
|
55
|
+
return currentToken;
|
|
56
|
+
},
|
|
57
|
+
getPayload() {
|
|
58
|
+
if (!currentPayload) throw new Error("Omadeus: not authenticated");
|
|
59
|
+
return currentPayload;
|
|
60
|
+
},
|
|
61
|
+
async refresh() {
|
|
62
|
+
try {
|
|
63
|
+
await refresh();
|
|
64
|
+
} catch (err) {
|
|
65
|
+
onError?.(err instanceof Error ? err : new Error(String(err)));
|
|
66
|
+
throw err;
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
startAutoRefresh() {
|
|
70
|
+
scheduleNextRefresh();
|
|
71
|
+
},
|
|
72
|
+
stopAutoRefresh() {
|
|
73
|
+
if (refreshTimer) {
|
|
74
|
+
clearTimeout(refreshTimer);
|
|
75
|
+
refreshTimer = null;
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
needsRefresh() {
|
|
79
|
+
return !currentToken || shouldRefreshToken(currentToken);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
//#endregion
|
|
84
|
+
export { createTokenManager };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//#region src/types.ts
|
|
2
|
+
/** Jaguar entity chats (`subscribableKind`) — DMs and channel rooms use other values. */
|
|
3
|
+
const OMADEUS_INBOUND_ENTITY_KINDS = [
|
|
4
|
+
"task",
|
|
5
|
+
"nugget",
|
|
6
|
+
"project",
|
|
7
|
+
"release",
|
|
8
|
+
"sprint",
|
|
9
|
+
"summary",
|
|
10
|
+
"client",
|
|
11
|
+
"folder"
|
|
12
|
+
];
|
|
13
|
+
const OMADEUS_INBOUND_ENTITY_KIND_SET = new Set(OMADEUS_INBOUND_ENTITY_KINDS);
|
|
14
|
+
//#endregion
|
|
15
|
+
export { OMADEUS_INBOUND_ENTITY_KINDS, OMADEUS_INBOUND_ENTITY_KIND_SET };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
//#region src/utils/http.util.ts
|
|
3
|
+
function authHeaders(token) {
|
|
4
|
+
return {
|
|
5
|
+
Authorization: `Bearer ${token}`,
|
|
6
|
+
"Content-Type": "application/json"
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
async function apiFetch(opts, path, init) {
|
|
10
|
+
const token = opts.tokenManager.getToken();
|
|
11
|
+
if (!token) throw new Error("Omadeus: not authenticated");
|
|
12
|
+
const url = `${opts.maestroUrl}${path}`;
|
|
13
|
+
try {
|
|
14
|
+
return await fetch(url, {
|
|
15
|
+
...init,
|
|
16
|
+
headers: {
|
|
17
|
+
...authHeaders(token),
|
|
18
|
+
...init?.headers
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
} catch (err) {
|
|
22
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
23
|
+
throw new Error(`Omadeus API request to ${url} failed: ${message}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function withApiPrefix(prefix, path) {
|
|
27
|
+
if (!path) return prefix;
|
|
28
|
+
if (path.startsWith("/")) return `${prefix}${path}`;
|
|
29
|
+
return `${prefix}/${path}`;
|
|
30
|
+
}
|
|
31
|
+
const JAGUAR_PREFIX = "/jaguar/apiv1";
|
|
32
|
+
const DOLPHIN_PREFIX = "/dolphin/apiv1";
|
|
33
|
+
async function jaguarFetch(opts, path, init) {
|
|
34
|
+
return apiFetch(opts, withApiPrefix(JAGUAR_PREFIX, path), init);
|
|
35
|
+
}
|
|
36
|
+
async function dolphinFetch(opts, path, init) {
|
|
37
|
+
return apiFetch(opts, withApiPrefix(DOLPHIN_PREFIX, path), init);
|
|
38
|
+
}
|
|
39
|
+
function generateTemporaryId() {
|
|
40
|
+
return `_${randomUUID().replace(/-/g, "").slice(0, 10)}`;
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
export { dolphinFetch, generateTemporaryId, jaguarFetch };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//#region src/utils/jwt.util.ts
|
|
2
|
+
/** Decode the payload portion of a JWT without verifying the signature. */
|
|
3
|
+
function decodeJwtPayload(token) {
|
|
4
|
+
const parts = token.split(".");
|
|
5
|
+
if (parts.length !== 3) throw new Error("Invalid JWT: expected 3 parts");
|
|
6
|
+
const payload = Buffer.from(parts[1], "base64url").toString("utf-8");
|
|
7
|
+
return JSON.parse(payload);
|
|
8
|
+
}
|
|
9
|
+
/** Returns ms until the token expires (negative = already expired). */
|
|
10
|
+
function tokenExpiresInMs(token) {
|
|
11
|
+
const { exp } = decodeJwtPayload(token);
|
|
12
|
+
return exp * 1e3 - Date.now();
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
export { decodeJwtPayload, tokenExpiresInMs };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brantrusnak/openclaw-omadeus",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "OpenClaw Omadeus project management channel plugin",
|
|
6
6
|
"homepage": "https://github.com/brantrusnak/openclaw-omadeus-plugin#readme",
|
|
@@ -14,15 +14,17 @@
|
|
|
14
14
|
"license": "ISC",
|
|
15
15
|
"author": "Brant Rusnak",
|
|
16
16
|
"type": "module",
|
|
17
|
-
"main": "./index.
|
|
17
|
+
"main": "./dist/index.js",
|
|
18
18
|
"scripts": {
|
|
19
|
+
"build": "rolldown -c rolldown.config.mjs",
|
|
19
20
|
"test": "vitest run",
|
|
20
|
-
"prepack": "node ./scripts/verify-npm-files.mjs"
|
|
21
|
+
"prepack": "npm run build && node ./scripts/verify-npm-files.mjs"
|
|
21
22
|
},
|
|
22
23
|
"dependencies": {
|
|
23
24
|
"ws": "^8.20.0"
|
|
24
25
|
},
|
|
25
26
|
"files": [
|
|
27
|
+
"dist",
|
|
26
28
|
"index.ts",
|
|
27
29
|
"setup-entry.ts",
|
|
28
30
|
"api.ts",
|
|
@@ -33,6 +35,7 @@
|
|
|
33
35
|
],
|
|
34
36
|
"devDependencies": {
|
|
35
37
|
"openclaw": ">=2026.4.10",
|
|
38
|
+
"rolldown": "1.0.0-rc.17",
|
|
36
39
|
"vitest": "^4.1.5"
|
|
37
40
|
},
|
|
38
41
|
"peerDependencies": {
|
|
@@ -50,7 +53,11 @@
|
|
|
50
53
|
"extensions": [
|
|
51
54
|
"./index.ts"
|
|
52
55
|
],
|
|
56
|
+
"runtimeExtensions": [
|
|
57
|
+
"./dist/index.js"
|
|
58
|
+
],
|
|
53
59
|
"setupEntry": "./setup-entry.ts",
|
|
60
|
+
"runtimeSetupEntry": "./dist/setup-entry.js",
|
|
54
61
|
"channel": {
|
|
55
62
|
"id": "omadeus",
|
|
56
63
|
"label": "Omadeus",
|
package/src/api/auth.api.ts
CHANGED
|
@@ -9,6 +9,27 @@ import type {
|
|
|
9
9
|
const CAS_APPLICATION_ID = 1;
|
|
10
10
|
const CAS_SCOPES = "title,email,avatar,firstName,lastName,birth,phone,countryCode";
|
|
11
11
|
|
|
12
|
+
function formatFetchError(label: string, url: string, method: string, err: unknown): Error {
|
|
13
|
+
const base = err instanceof Error ? err.message : String(err);
|
|
14
|
+
const cause =
|
|
15
|
+
err instanceof Error && err.cause instanceof Error ? err.cause.message : undefined;
|
|
16
|
+
const detail = cause && cause !== base ? `${base} (${cause})` : base;
|
|
17
|
+
return new Error(`${label} (${method} ${url}) failed: ${detail}`);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async function omadeusFetch(
|
|
21
|
+
label: string,
|
|
22
|
+
url: string,
|
|
23
|
+
init: RequestInit,
|
|
24
|
+
): Promise<Response> {
|
|
25
|
+
const method = init.method ?? "GET";
|
|
26
|
+
try {
|
|
27
|
+
return await fetch(url, init);
|
|
28
|
+
} catch (err) {
|
|
29
|
+
throw formatFetchError(label, url, method, err);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
12
33
|
export async function createCasToken(params: {
|
|
13
34
|
casUrl: string;
|
|
14
35
|
email: string;
|
|
@@ -17,11 +38,10 @@ export async function createCasToken(params: {
|
|
|
17
38
|
const { casUrl, email, password } = params;
|
|
18
39
|
const url = `${casUrl}/apiv1/tokens`;
|
|
19
40
|
const jsonBody = JSON.stringify({ email, password });
|
|
20
|
-
const res = await
|
|
41
|
+
const res = await omadeusFetch("CAS token request", url, {
|
|
21
42
|
method: "CREATE",
|
|
22
43
|
headers: {
|
|
23
44
|
"Content-Type": "application/json;charset=UTF-8",
|
|
24
|
-
"Content-Length": String(jsonBody.length),
|
|
25
45
|
},
|
|
26
46
|
body: jsonBody,
|
|
27
47
|
});
|
|
@@ -44,7 +64,7 @@ export async function getMe(params: {
|
|
|
44
64
|
}): Promise<{ email: string }> {
|
|
45
65
|
const { casUrl, casToken, refreshCookie } = params;
|
|
46
66
|
const url = `${casUrl}/apiv1/members/me`;
|
|
47
|
-
const res = await
|
|
67
|
+
const res = await omadeusFetch("CAS get member", url, {
|
|
48
68
|
method: "GET",
|
|
49
69
|
headers: {
|
|
50
70
|
Authorization: `Bearer ${casToken}`,
|
|
@@ -80,7 +100,7 @@ export async function createAuthorizationCode(params: {
|
|
|
80
100
|
Authorization: `Bearer ${token}`,
|
|
81
101
|
...(casSession?.refreshCookie ? { Cookie: casSession.refreshCookie } : {}),
|
|
82
102
|
};
|
|
83
|
-
const res = await
|
|
103
|
+
const res = await omadeusFetch("CAS authorization code request", url, {
|
|
84
104
|
method: "CREATE",
|
|
85
105
|
body,
|
|
86
106
|
headers,
|
|
@@ -104,7 +124,7 @@ export async function obtainSessionToken(params: {
|
|
|
104
124
|
}): Promise<string> {
|
|
105
125
|
const { maestroUrl, authorizationCode, organizationId } = params;
|
|
106
126
|
const url = `${maestroUrl}/dolphin/apiv1/oauth2/tokens`;
|
|
107
|
-
const res = await
|
|
127
|
+
const res = await omadeusFetch("Omadeus session token request", url, {
|
|
108
128
|
method: "OBTAIN",
|
|
109
129
|
headers: { "Content-Type": "application/json;charset=UTF-8" },
|
|
110
130
|
body: JSON.stringify({ authorizationCode, organizationId }),
|
|
@@ -126,7 +146,7 @@ export async function listOrganizations(params: {
|
|
|
126
146
|
}): Promise<OmadeusOrganization[]> {
|
|
127
147
|
const { maestroUrl, email } = params;
|
|
128
148
|
const url = `${maestroUrl}/dolphin/apiv1/organizations`;
|
|
129
|
-
const res = await
|
|
149
|
+
const res = await omadeusFetch("Omadeus list organizations", url, {
|
|
130
150
|
method: "LIST",
|
|
131
151
|
headers: { "Content-Type": "application/json;charset=UTF-8" },
|
|
132
152
|
body: JSON.stringify({ email }),
|
|
@@ -145,7 +165,7 @@ export async function listOrganizationMembers(params: {
|
|
|
145
165
|
}): Promise<OmadeusOrganizationMember[]> {
|
|
146
166
|
const { maestroUrl, sessionToken, organizationId } = params;
|
|
147
167
|
const url = `${maestroUrl}/dolphin/apiv1/organizations/${organizationId}/members`;
|
|
148
|
-
const res = await
|
|
168
|
+
const res = await omadeusFetch("Omadeus list organization members", url, {
|
|
149
169
|
method: "LIST",
|
|
150
170
|
headers: {
|
|
151
171
|
Authorization: `Bearer ${sessionToken}`,
|