@brantrusnak/openclaw-omadeus 1.0.1 → 1.0.3
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 -2
- 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 +115 -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 +363 -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/openclaw.plugin.json +144 -28
- package/package.json +12 -7
- package/src/api/auth.api.ts +0 -29
- package/src/api/channel.api.ts +29 -0
- package/src/api/nugget.api.ts +81 -10
- package/src/channel.ts +136 -247
- package/src/inbound-policy.ts +250 -0
- package/src/inbound.ts +20 -0
- package/src/member-resolve.ts +84 -0
- package/src/message-handler.ts +99 -53
- package/src/nugget-lookup.ts +67 -4
- package/src/onboarding.ts +283 -200
- package/src/setup-core.ts +10 -1
- package/src/socket/socket.ts +24 -11
- package/src/types.ts +77 -7
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# OpenClaw Omadeus Plugin
|
|
2
2
|
|
|
3
|
-
Omadeus
|
|
3
|
+
[Omadeus](https://omadeus.com) plugin for [OpenClaw](https://www.npmjs.com/package/openclaw).
|
|
4
4
|
|
|
5
5
|
This plugin connects OpenClaw to Omadeus over WebSocket so OpenClaw can listen
|
|
6
6
|
for Omadeus messages and reply through the selected Omadeus channel.
|
|
@@ -88,15 +88,18 @@ openclaw plugins doctor
|
|
|
88
88
|
|
|
89
89
|
## Local Development
|
|
90
90
|
|
|
91
|
-
|
|
91
|
+
Build the runtime files before linking a local checkout into OpenClaw:
|
|
92
92
|
|
|
93
93
|
```bash
|
|
94
|
+
npm install
|
|
95
|
+
npm run build
|
|
94
96
|
openclaw plugins install . --link
|
|
95
97
|
```
|
|
96
98
|
|
|
97
99
|
Before publishing, inspect the npm package contents:
|
|
98
100
|
|
|
99
101
|
```bash
|
|
102
|
+
npm run prepack
|
|
100
103
|
npm pack --dry-run
|
|
101
104
|
```
|
|
102
105
|
|
package/dist/api.js
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import "./_virtual/_rolldown/runtime.js";
|
|
2
|
+
import { setOmadeusRuntime } from "./src/runtime.js";
|
|
3
|
+
import { omadeusPlugin } from "./src/channel.js";
|
|
4
|
+
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core";
|
|
5
|
+
//#region index.ts
|
|
6
|
+
var openclaw_omadeus_plugin_default = defineChannelPluginEntry({
|
|
7
|
+
id: "omadeus",
|
|
8
|
+
name: "Omadeus",
|
|
9
|
+
description: "Omadeus project management channel plugin",
|
|
10
|
+
plugin: omadeusPlugin,
|
|
11
|
+
setRuntime: setOmadeusRuntime
|
|
12
|
+
});
|
|
13
|
+
//#endregion
|
|
14
|
+
export { openclaw_omadeus_plugin_default as default, omadeusPlugin, setOmadeusRuntime };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import "./_virtual/_rolldown/runtime.js";
|
|
2
|
+
import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/core";
|
|
3
|
+
import { createReplyPrefixContext } from "openclaw/plugin-sdk/channel-runtime";
|
|
4
|
+
import { logInboundDrop } from "openclaw/plugin-sdk/channel-inbound";
|
|
5
|
+
import { resolveControlCommandGate } from "openclaw/plugin-sdk/command-auth";
|
|
6
|
+
import { createChannelPairingController } from "openclaw/plugin-sdk/channel-pairing";
|
|
7
|
+
import { readStoreAllowFromForDmPolicy, resolveDmGroupAccessWithLists } from "openclaw/plugin-sdk/channel-policy";
|
|
8
|
+
import { addWildcardAllowFrom, formatDocsLink, mergeAllowFromEntries } from "openclaw/plugin-sdk/setup";
|
|
9
|
+
//#region runtime-api.ts
|
|
10
|
+
function missingTargetError(provider, hint) {
|
|
11
|
+
const normalizedHint = hint?.trim();
|
|
12
|
+
return /* @__PURE__ */ new Error(`Delivering to ${provider} requires target${normalizedHint ? ` ${normalizedHint}` : ""}`);
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
export { DEFAULT_ACCOUNT_ID, addWildcardAllowFrom, createChannelPairingController, createReplyPrefixContext, formatDocsLink, logInboundDrop, mergeAllowFromEntries, missingTargetError, readStoreAllowFromForDmPolicy, resolveControlCommandGate, resolveDmGroupAccessWithLists };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import "./_virtual/_rolldown/runtime.js";
|
|
2
|
+
import { omadeusPlugin } from "./src/channel.js";
|
|
3
|
+
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core";
|
|
4
|
+
//#region setup-entry.ts
|
|
5
|
+
var setup_entry_default = defineSetupPluginEntry(omadeusPlugin);
|
|
6
|
+
//#endregion
|
|
7
|
+
export { setup_entry_default as default };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
//#region src/allowed-reaction-emojis.ts
|
|
2
|
+
/**
|
|
3
|
+
* Omadeus only accepts these exact reaction strings; any other value is ignored (no API call).
|
|
4
|
+
*/
|
|
5
|
+
const ALLOWED_OMADEUS_REACTION_EMOJI_LIST = [
|
|
6
|
+
"👍",
|
|
7
|
+
"👎",
|
|
8
|
+
"❤️",
|
|
9
|
+
"😂",
|
|
10
|
+
"😮",
|
|
11
|
+
"😢",
|
|
12
|
+
"🙏"
|
|
13
|
+
];
|
|
14
|
+
const ALLOWED = new Set(ALLOWED_OMADEUS_REACTION_EMOJI_LIST);
|
|
15
|
+
function isAllowedOmadeusReactionEmoji(raw) {
|
|
16
|
+
const trimmed = raw.trim();
|
|
17
|
+
if (!trimmed) return false;
|
|
18
|
+
return ALLOWED.has(trimmed);
|
|
19
|
+
}
|
|
20
|
+
//#endregion
|
|
21
|
+
export { ALLOWED_OMADEUS_REACTION_EMOJI_LIST, isAllowedOmadeusReactionEmoji };
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { getCasSession, setCasSession } from "../store.js";
|
|
2
|
+
//#region src/api/auth.api.ts
|
|
3
|
+
const CAS_APPLICATION_ID = 1;
|
|
4
|
+
const CAS_SCOPES = "title,email,avatar,firstName,lastName,birth,phone,countryCode";
|
|
5
|
+
async function createCasToken(params) {
|
|
6
|
+
const { casUrl, email, password } = params;
|
|
7
|
+
const url = `${casUrl}/apiv1/tokens`;
|
|
8
|
+
const jsonBody = JSON.stringify({
|
|
9
|
+
email,
|
|
10
|
+
password
|
|
11
|
+
});
|
|
12
|
+
const res = await fetch(url, {
|
|
13
|
+
method: "CREATE",
|
|
14
|
+
headers: {
|
|
15
|
+
"Content-Type": "application/json;charset=UTF-8",
|
|
16
|
+
"Content-Length": String(jsonBody.length)
|
|
17
|
+
},
|
|
18
|
+
body: jsonBody
|
|
19
|
+
});
|
|
20
|
+
if (!res.ok) {
|
|
21
|
+
const text = await res.text().catch(() => "");
|
|
22
|
+
throw new Error(`CAS token request failed (${res.status}): ${text}`);
|
|
23
|
+
}
|
|
24
|
+
const body = await res.json();
|
|
25
|
+
const refreshCookie = res.headers.get("set-cookie") ?? "";
|
|
26
|
+
setCasSession({
|
|
27
|
+
token: body.token,
|
|
28
|
+
refreshCookie
|
|
29
|
+
});
|
|
30
|
+
return {
|
|
31
|
+
token: body.token,
|
|
32
|
+
refreshCookie
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
async function createAuthorizationCode(params) {
|
|
36
|
+
const { casUrl, token, email, redirectUri } = params;
|
|
37
|
+
const casSession = getCasSession();
|
|
38
|
+
const qs = new URLSearchParams({
|
|
39
|
+
applicationId: String(CAS_APPLICATION_ID),
|
|
40
|
+
scopes: CAS_SCOPES,
|
|
41
|
+
state: email,
|
|
42
|
+
redirectUri: redirectUri ?? ""
|
|
43
|
+
});
|
|
44
|
+
if (redirectUri) qs.set("redirectUri", redirectUri);
|
|
45
|
+
const url = `${casUrl}/apiv1/authorizationcodes?${qs}`;
|
|
46
|
+
const body = "";
|
|
47
|
+
const headers = {
|
|
48
|
+
Authorization: `Bearer ${token}`,
|
|
49
|
+
...casSession?.refreshCookie ? { Cookie: casSession.refreshCookie } : {}
|
|
50
|
+
};
|
|
51
|
+
const res = await fetch(url, {
|
|
52
|
+
method: "CREATE",
|
|
53
|
+
body,
|
|
54
|
+
headers
|
|
55
|
+
});
|
|
56
|
+
if (!res.ok) {
|
|
57
|
+
const text = await res.text().catch(() => "");
|
|
58
|
+
throw new Error(`CAS authorization code request failed (${res.status}): ${text}`);
|
|
59
|
+
}
|
|
60
|
+
const jsonResponse = await res.json();
|
|
61
|
+
const code = jsonResponse.authorizationCode ?? jsonResponse.code;
|
|
62
|
+
if (!code) throw new Error("CAS authorization code response missing code");
|
|
63
|
+
return code;
|
|
64
|
+
}
|
|
65
|
+
async function obtainSessionToken(params) {
|
|
66
|
+
const { maestroUrl, authorizationCode, organizationId } = params;
|
|
67
|
+
const url = `${maestroUrl}/dolphin/apiv1/oauth2/tokens`;
|
|
68
|
+
const res = await fetch(url, {
|
|
69
|
+
method: "OBTAIN",
|
|
70
|
+
headers: { "Content-Type": "application/json;charset=UTF-8" },
|
|
71
|
+
body: JSON.stringify({
|
|
72
|
+
authorizationCode,
|
|
73
|
+
organizationId
|
|
74
|
+
})
|
|
75
|
+
});
|
|
76
|
+
if (!res.ok) {
|
|
77
|
+
const text = await res.text().catch(() => "");
|
|
78
|
+
throw new Error(`Omadeus session token request failed (${res.status}): ${text}`);
|
|
79
|
+
}
|
|
80
|
+
const body = await res.json();
|
|
81
|
+
if (!body.token) throw new Error("Omadeus session token response missing token");
|
|
82
|
+
return body.token;
|
|
83
|
+
}
|
|
84
|
+
async function listOrganizations(params) {
|
|
85
|
+
const { maestroUrl, email } = params;
|
|
86
|
+
const url = `${maestroUrl}/dolphin/apiv1/organizations`;
|
|
87
|
+
const res = await fetch(url, {
|
|
88
|
+
method: "LIST",
|
|
89
|
+
headers: { "Content-Type": "application/json;charset=UTF-8" },
|
|
90
|
+
body: JSON.stringify({ email })
|
|
91
|
+
});
|
|
92
|
+
if (!res.ok) {
|
|
93
|
+
const text = await res.text().catch(() => "");
|
|
94
|
+
throw new Error(`Omadeus list organizations failed (${res.status}): ${text}`);
|
|
95
|
+
}
|
|
96
|
+
return await res.json();
|
|
97
|
+
}
|
|
98
|
+
async function listOrganizationMembers(params) {
|
|
99
|
+
const { maestroUrl, sessionToken, organizationId } = params;
|
|
100
|
+
const url = `${maestroUrl}/dolphin/apiv1/organizations/${organizationId}/members`;
|
|
101
|
+
const res = await fetch(url, {
|
|
102
|
+
method: "LIST",
|
|
103
|
+
headers: {
|
|
104
|
+
Authorization: `Bearer ${sessionToken}`,
|
|
105
|
+
"Content-Type": "application/json;charset=UTF-8"
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
if (!res.ok) {
|
|
109
|
+
const text = await res.text().catch(() => "");
|
|
110
|
+
throw new Error(`Omadeus list organization members failed (${res.status}): ${text}`);
|
|
111
|
+
}
|
|
112
|
+
return await res.json();
|
|
113
|
+
}
|
|
114
|
+
//#endregion
|
|
115
|
+
export { createAuthorizationCode, createCasToken, listOrganizationMembers, listOrganizations, obtainSessionToken };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//#region src/api/channel.api.ts
|
|
2
|
+
async function listMemberChannelViews(params) {
|
|
3
|
+
const { maestroUrl, sessionToken, memberReferenceId, skip = 0, take = 100 } = params;
|
|
4
|
+
const url = `${maestroUrl}/jaguar/apiv1/members/${memberReferenceId}/channelviews?${new URLSearchParams({
|
|
5
|
+
skip: String(skip),
|
|
6
|
+
take: String(take),
|
|
7
|
+
sort: "-recentMessageAt"
|
|
8
|
+
}).toString()}`;
|
|
9
|
+
const res = await fetch(url, {
|
|
10
|
+
method: "LIST",
|
|
11
|
+
headers: {
|
|
12
|
+
Authorization: `Bearer ${sessionToken}`,
|
|
13
|
+
"Content-Type": "application/json;charset=UTF-8"
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
if (!res.ok) {
|
|
17
|
+
const text = await res.text().catch(() => "");
|
|
18
|
+
throw new Error(`Omadeus list channel views failed (${res.status}): ${text}`);
|
|
19
|
+
}
|
|
20
|
+
return await res.json();
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
export { listMemberChannelViews };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { generateTemporaryId, jaguarFetch } from "../utils/http.util.js";
|
|
2
|
+
//#region src/api/message.api.ts
|
|
3
|
+
async function readJsonOrEmpty(res) {
|
|
4
|
+
if (res.status === 204) return;
|
|
5
|
+
const trimmed = (await res.text()).trim();
|
|
6
|
+
if (!trimmed) return;
|
|
7
|
+
try {
|
|
8
|
+
return JSON.parse(trimmed);
|
|
9
|
+
} catch {
|
|
10
|
+
return trimmed;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
async function sendRoomMessage(opts, params) {
|
|
14
|
+
try {
|
|
15
|
+
const res = await jaguarFetch(opts, `/rooms/${params.roomId}/messages`, {
|
|
16
|
+
method: "SEND",
|
|
17
|
+
body: JSON.stringify({
|
|
18
|
+
body: params.body,
|
|
19
|
+
temporaryId: generateTemporaryId(),
|
|
20
|
+
links: "[]"
|
|
21
|
+
})
|
|
22
|
+
});
|
|
23
|
+
if (!res.ok) {
|
|
24
|
+
const text = await res.text().catch(() => "");
|
|
25
|
+
return {
|
|
26
|
+
ok: false,
|
|
27
|
+
error: `${res.status}: ${text.slice(0, 200)}`
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
ok: true,
|
|
32
|
+
message: await res.json()
|
|
33
|
+
};
|
|
34
|
+
} catch (err) {
|
|
35
|
+
return {
|
|
36
|
+
ok: false,
|
|
37
|
+
error: (err instanceof Error ? err.message : String(err)).slice(0, 300)
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async function editMessage(opts, params) {
|
|
42
|
+
const res = await jaguarFetch(opts, `/messages/${params.messageId}`, {
|
|
43
|
+
method: "EDIT",
|
|
44
|
+
body: JSON.stringify({
|
|
45
|
+
body: params.body,
|
|
46
|
+
...params.temporaryId ? { temporaryId: params.temporaryId } : {},
|
|
47
|
+
...params.links ? { links: JSON.stringify(params.links) } : {}
|
|
48
|
+
})
|
|
49
|
+
});
|
|
50
|
+
if (!res.ok) {
|
|
51
|
+
const text = await res.text().catch(() => "");
|
|
52
|
+
throw new Error(`Omadeus edit message failed (${res.status}): ${text.slice(0, 200)}`);
|
|
53
|
+
}
|
|
54
|
+
return await res.json();
|
|
55
|
+
}
|
|
56
|
+
async function deleteMessage(opts, params) {
|
|
57
|
+
const res = await jaguarFetch(opts, `/messages/${params.messageId}`, { method: "DELETE" });
|
|
58
|
+
if (!res.ok) {
|
|
59
|
+
const text = await res.text().catch(() => "");
|
|
60
|
+
throw new Error(`Omadeus delete message failed (${res.status}): ${text.slice(0, 200)}`);
|
|
61
|
+
}
|
|
62
|
+
return await res.json();
|
|
63
|
+
}
|
|
64
|
+
async function addMessageReaction(opts, params) {
|
|
65
|
+
const res = await jaguarFetch(opts, `/messages/${params.messageId}/reactions`, {
|
|
66
|
+
method: "ADD",
|
|
67
|
+
body: JSON.stringify({ emoji: params.emoji })
|
|
68
|
+
});
|
|
69
|
+
if (!res.ok) {
|
|
70
|
+
const text = await res.text().catch(() => "");
|
|
71
|
+
throw new Error(`Omadeus add reaction failed (${res.status}): ${text.slice(0, 200)}`);
|
|
72
|
+
}
|
|
73
|
+
return readJsonOrEmpty(res);
|
|
74
|
+
}
|
|
75
|
+
//#endregion
|
|
76
|
+
export { addMessageReaction, deleteMessage, editMessage, sendRoomMessage };
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { dolphinFetch } from "../utils/http.util.js";
|
|
2
|
+
//#region src/api/nugget.api.ts
|
|
3
|
+
/** Omadeus nugget/task display number (`N###` in UI maps to this field). */
|
|
4
|
+
function readNuggetNumber(record) {
|
|
5
|
+
const value = record["number"];
|
|
6
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
7
|
+
if (typeof value === "string" && /^\d+$/.test(value.trim())) return Number(value.trim());
|
|
8
|
+
}
|
|
9
|
+
function readNumberField(record, key) {
|
|
10
|
+
const value = record[key];
|
|
11
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
12
|
+
if (typeof value === "string" && /^\d+$/.test(value.trim())) return Number(value.trim());
|
|
13
|
+
}
|
|
14
|
+
function findNuggetRowByNumber(rows, nuggetNumber) {
|
|
15
|
+
return rows.find((row) => readNuggetNumber(row) === nuggetNumber);
|
|
16
|
+
}
|
|
17
|
+
function resolveTaskChannelRoomId(record) {
|
|
18
|
+
return readNumberField(record, "privateRoomId") ?? readNumberField(record, "publicRoomId") ?? readNumberField(record, "sharedRoomId");
|
|
19
|
+
}
|
|
20
|
+
function extractRows(payload) {
|
|
21
|
+
if (Array.isArray(payload)) return payload.filter((entry) => !!entry && typeof entry === "object");
|
|
22
|
+
if (!payload || typeof payload !== "object") return [];
|
|
23
|
+
const envelope = payload;
|
|
24
|
+
for (const key of [
|
|
25
|
+
"data",
|
|
26
|
+
"results",
|
|
27
|
+
"items",
|
|
28
|
+
"rows"
|
|
29
|
+
]) {
|
|
30
|
+
const value = envelope[key];
|
|
31
|
+
if (Array.isArray(value)) return value.filter((entry) => !!entry && typeof entry === "object");
|
|
32
|
+
}
|
|
33
|
+
return [];
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Dolphin SEARCH on nuggetviews — arbitrary text query (e.g. N###, task title, or room id string).
|
|
37
|
+
* Prefer filtering results with `findNuggetRowByNumber` or `findNuggetRowByRoomId`.
|
|
38
|
+
*/
|
|
39
|
+
async function searchNuggetRowsByTextQuery(opts, params) {
|
|
40
|
+
const take = params.take ?? 100;
|
|
41
|
+
const q = params.query.trim();
|
|
42
|
+
if (!q) return [];
|
|
43
|
+
const search = new URLSearchParams();
|
|
44
|
+
search.set("take", String(take));
|
|
45
|
+
const res = await dolphinFetch(opts, `/nuggetviews?${search.toString()}`, {
|
|
46
|
+
method: "SEARCH",
|
|
47
|
+
body: JSON.stringify({ query: q }),
|
|
48
|
+
signal: params.signal
|
|
49
|
+
});
|
|
50
|
+
if (!res.ok) {
|
|
51
|
+
const text = await res.text().catch(() => "");
|
|
52
|
+
throw new Error(`Omadeus nugget search failed (${res.status}): ${text.slice(0, 200)}`);
|
|
53
|
+
}
|
|
54
|
+
return extractRows(await res.json());
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Picks a row whose private/public/shared task room id matches a Jaguar `roomId`.
|
|
58
|
+
*/
|
|
59
|
+
function findNuggetRowByRoomId(rows, roomId) {
|
|
60
|
+
for (const row of rows) for (const key of [
|
|
61
|
+
"privateRoomId",
|
|
62
|
+
"publicRoomId",
|
|
63
|
+
"sharedRoomId"
|
|
64
|
+
]) if (readNumberField(row, key) === roomId) return row;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Resolve the nugget/task row for a Jaguar Task or Nugget **chat room** by matching
|
|
68
|
+
* `privateRoomId` / `publicRoomId` / `sharedRoomId` to `roomId` in Dolphin `nuggetviews` search results.
|
|
69
|
+
* Tries search by `roomName` first (usually matches the task title), then by the numeric `roomId` as text.
|
|
70
|
+
*/
|
|
71
|
+
async function findNuggetByTaskChannelRoom(opts, params) {
|
|
72
|
+
const { roomId, roomName, signal } = params;
|
|
73
|
+
const tryQueries = [];
|
|
74
|
+
if (typeof roomName === "string" && roomName.trim()) tryQueries.push(roomName.trim());
|
|
75
|
+
tryQueries.push(String(roomId));
|
|
76
|
+
const tried = /* @__PURE__ */ new Set();
|
|
77
|
+
for (const query of tryQueries) {
|
|
78
|
+
if (tried.has(query)) continue;
|
|
79
|
+
tried.add(query);
|
|
80
|
+
const match = findNuggetRowByRoomId(await searchNuggetRowsByTextQuery(opts, {
|
|
81
|
+
query,
|
|
82
|
+
take: 100,
|
|
83
|
+
signal
|
|
84
|
+
}), roomId);
|
|
85
|
+
if (match) return match;
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Dolphin SEARCH on nuggetviews returns an array of nugget/task rows.
|
|
91
|
+
* User-facing `N111` corresponds to `number: 111` on each row (not `id`).
|
|
92
|
+
*/
|
|
93
|
+
async function searchNuggetByNumber(opts, params) {
|
|
94
|
+
return findNuggetRowByNumber(await searchNuggetRowsByTextQuery(opts, {
|
|
95
|
+
query: `N${params.nuggetNumber}`,
|
|
96
|
+
take: 100,
|
|
97
|
+
signal: params.signal
|
|
98
|
+
}), params.nuggetNumber) ?? null;
|
|
99
|
+
}
|
|
100
|
+
async function resolveTaskRoomIdByNumber(opts, params) {
|
|
101
|
+
const row = await searchNuggetByNumber(opts, params);
|
|
102
|
+
if (!row) return null;
|
|
103
|
+
return resolveTaskChannelRoomId(row) ?? null;
|
|
104
|
+
}
|
|
105
|
+
async function createNugget(opts, params) {
|
|
106
|
+
const res = await dolphinFetch(opts, "/nuggets", {
|
|
107
|
+
method: "CREATE",
|
|
108
|
+
body: JSON.stringify({
|
|
109
|
+
title: params.title,
|
|
110
|
+
stage: params.stage,
|
|
111
|
+
description: params.description,
|
|
112
|
+
kind: params.kind,
|
|
113
|
+
priority: params.priority,
|
|
114
|
+
memberReferenceId: params.memberReferenceId,
|
|
115
|
+
clientId: params.clientId,
|
|
116
|
+
folderId: params.folderId
|
|
117
|
+
}),
|
|
118
|
+
signal: params.signal
|
|
119
|
+
});
|
|
120
|
+
if (!res.ok) {
|
|
121
|
+
const text = await res.text().catch(() => "");
|
|
122
|
+
throw new Error(`Omadeus nugget create failed (${res.status}): ${text.slice(0, 200)}`);
|
|
123
|
+
}
|
|
124
|
+
return await res.json();
|
|
125
|
+
}
|
|
126
|
+
//#endregion
|
|
127
|
+
export { createNugget, findNuggetByTaskChannelRoom, readNuggetNumber, resolveTaskChannelRoomId, resolveTaskRoomIdByNumber, searchNuggetByNumber };
|
package/dist/src/auth.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { clearCasSession } from "./store.js";
|
|
2
|
+
import { createAuthorizationCode, createCasToken, obtainSessionToken } from "./api/auth.api.js";
|
|
3
|
+
import { decodeJwtPayload } from "./utils/jwt.util.js";
|
|
4
|
+
//#region src/auth.ts
|
|
5
|
+
async function authenticate(params) {
|
|
6
|
+
const { casUrl, maestroUrl, email, password, organizationId } = params;
|
|
7
|
+
const { token } = await createCasToken({
|
|
8
|
+
casUrl,
|
|
9
|
+
email,
|
|
10
|
+
password
|
|
11
|
+
});
|
|
12
|
+
const authorizationCode = await createAuthorizationCode({
|
|
13
|
+
casUrl,
|
|
14
|
+
token,
|
|
15
|
+
email,
|
|
16
|
+
redirectUri: maestroUrl
|
|
17
|
+
});
|
|
18
|
+
clearCasSession();
|
|
19
|
+
const dolphinToken = await obtainSessionToken({
|
|
20
|
+
maestroUrl,
|
|
21
|
+
authorizationCode,
|
|
22
|
+
organizationId
|
|
23
|
+
});
|
|
24
|
+
return {
|
|
25
|
+
dolphinToken,
|
|
26
|
+
payload: decodeJwtPayload(dolphinToken)
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { authenticate };
|