@saltify/milky-node-sdk 0.1.0-beta.1 → 0.1.0-beta.10
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 +2 -0
- package/dist/index.d.ts +17 -11
- package/dist/index.js +381 -27
- package/package.json +7 -5
package/README.md
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -16,12 +16,12 @@ type ApiCollection = {
|
|
|
16
16
|
get_csrf_token: () => types.GetCSRFTokenOutput;
|
|
17
17
|
send_private_message: (input: z.input<typeof types.SendPrivateMessageInput>) => types.SendPrivateMessageOutput;
|
|
18
18
|
send_group_message: (input: z.input<typeof types.SendGroupMessageInput>) => types.SendGroupMessageOutput;
|
|
19
|
+
recall_private_message: (input: z.input<typeof types.RecallPrivateMessageInput>) => void;
|
|
20
|
+
recall_group_message: (input: z.input<typeof types.RecallGroupMessageInput>) => void;
|
|
19
21
|
get_message: (input: z.input<typeof types.GetMessageInput>) => types.GetMessageOutput;
|
|
20
22
|
get_history_messages: (input: z.input<typeof types.GetHistoryMessagesInput>) => types.GetHistoryMessagesOutput;
|
|
21
23
|
get_resource_temp_url: (input: z.input<typeof types.GetResourceTempUrlInput>) => types.GetResourceTempUrlOutput;
|
|
22
24
|
get_forwarded_messages: (input: z.input<typeof types.GetForwardedMessagesInput>) => types.GetForwardedMessagesOutput;
|
|
23
|
-
recall_private_message: (input: z.input<typeof types.RecallPrivateMessageInput>) => void;
|
|
24
|
-
recall_group_message: (input: z.input<typeof types.RecallGroupMessageInput>) => void;
|
|
25
25
|
mark_message_as_read: (input: z.input<typeof types.MarkMessageAsReadInput>) => void;
|
|
26
26
|
send_friend_nudge: (input: z.input<typeof types.SendFriendNudgeInput>) => void;
|
|
27
27
|
send_profile_like: (input: z.input<typeof types.SendProfileLikeInput>) => void;
|
|
@@ -36,7 +36,7 @@ type ApiCollection = {
|
|
|
36
36
|
set_group_member_mute: (input: z.input<typeof types.SetGroupMemberMuteInput>) => void;
|
|
37
37
|
set_group_whole_mute: (input: z.input<typeof types.SetGroupWholeMuteInput>) => void;
|
|
38
38
|
kick_group_member: (input: z.input<typeof types.KickGroupMemberInput>) => void;
|
|
39
|
-
|
|
39
|
+
get_group_announcements: (input: z.input<typeof types.GetGroupAnnouncementsInput>) => types.GetGroupAnnouncementsOutput;
|
|
40
40
|
send_group_announcement: (input: z.input<typeof types.SendGroupAnnouncementInput>) => void;
|
|
41
41
|
delete_group_announcement: (input: z.input<typeof types.DeleteGroupAnnouncementInput>) => void;
|
|
42
42
|
get_group_essence_messages: (input: z.input<typeof types.GetGroupEssenceMessagesInput>) => types.GetGroupEssenceMessagesOutput;
|
|
@@ -69,20 +69,19 @@ type EventCollection = {
|
|
|
69
69
|
};
|
|
70
70
|
|
|
71
71
|
declare class MilkyClient {
|
|
72
|
-
private readonly
|
|
72
|
+
private readonly eventEmitter;
|
|
73
73
|
private readonly httpApiUrl;
|
|
74
74
|
private readonly eventUrl;
|
|
75
|
-
private readonly wsClient;
|
|
76
75
|
private readonly fetchHeader;
|
|
77
|
-
private
|
|
76
|
+
private disposeCore?;
|
|
78
77
|
/**
|
|
79
|
-
* @param
|
|
80
|
-
* @param
|
|
81
|
-
* @param base The base path for the Milky API
|
|
78
|
+
* @param authority The authority of the Milky API (value of `new URL('https://example.com:443/some-path').host`)
|
|
79
|
+
* @param basePath The base path for the Milky API
|
|
82
80
|
* @param accessToken The access token for authentication (optional)
|
|
83
|
-
* @param
|
|
81
|
+
* @param useTLS Whether to use HTTPS and WSS (default: false)
|
|
82
|
+
* @param useSSE Whether to use Server-Sent Events for event streaming (default: false)
|
|
84
83
|
*/
|
|
85
|
-
constructor(
|
|
84
|
+
constructor(authority: string, basePath?: `/${string}/` | '/', accessToken?: string, useTLS?: boolean, useSSE?: boolean);
|
|
86
85
|
/**
|
|
87
86
|
* Call a Milky API method.
|
|
88
87
|
* @param method The API method to call
|
|
@@ -96,6 +95,13 @@ declare class MilkyClient {
|
|
|
96
95
|
* @param listener The listener function to call when the event is emitted
|
|
97
96
|
*/
|
|
98
97
|
onEvent<K extends keyof EventCollection>(eventType: K, listener: (data: EventCollection[K]) => void): Promise<void>;
|
|
98
|
+
private createSSE;
|
|
99
|
+
private createWebsocket;
|
|
100
|
+
/**
|
|
101
|
+
* Release the WebSocket / Server Sent Event connection.
|
|
102
|
+
*/
|
|
103
|
+
dispose(): void;
|
|
104
|
+
[Symbol.dispose]: () => void;
|
|
99
105
|
}
|
|
100
106
|
|
|
101
107
|
export { MilkyClient };
|
package/dist/index.js
CHANGED
|
@@ -1,36 +1,350 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
8
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
9
|
+
}) : x)(function(x) {
|
|
10
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
11
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
12
|
+
});
|
|
13
|
+
var __commonJS = (cb, mod) => function __require2() {
|
|
14
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
15
|
+
};
|
|
16
|
+
var __copyProps = (to, from, except, desc) => {
|
|
17
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
18
|
+
for (let key of __getOwnPropNames(from))
|
|
19
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
20
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
21
|
+
}
|
|
22
|
+
return to;
|
|
23
|
+
};
|
|
24
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
25
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
26
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
27
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
28
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
29
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
30
|
+
mod
|
|
31
|
+
));
|
|
32
|
+
|
|
33
|
+
// ../../node_modules/.pnpm/eventsource-parser@3.0.6/node_modules/eventsource-parser/dist/index.cjs
|
|
34
|
+
var require_dist = __commonJS({
|
|
35
|
+
"../../node_modules/.pnpm/eventsource-parser@3.0.6/node_modules/eventsource-parser/dist/index.cjs"(exports) {
|
|
36
|
+
"use strict";
|
|
37
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
+
var ParseError = class extends Error {
|
|
39
|
+
constructor(message, options) {
|
|
40
|
+
super(message), this.name = "ParseError", this.type = options.type, this.field = options.field, this.value = options.value, this.line = options.line;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
function noop(_arg) {
|
|
44
|
+
}
|
|
45
|
+
function createParser(callbacks) {
|
|
46
|
+
if (typeof callbacks == "function")
|
|
47
|
+
throw new TypeError(
|
|
48
|
+
"`callbacks` must be an object, got a function instead. Did you mean `{onEvent: fn}`?"
|
|
49
|
+
);
|
|
50
|
+
const { onEvent = noop, onError = noop, onRetry = noop, onComment } = callbacks;
|
|
51
|
+
let incompleteLine = "", isFirstChunk = true, id, data = "", eventType = "";
|
|
52
|
+
function feed(newChunk) {
|
|
53
|
+
const chunk = isFirstChunk ? newChunk.replace(/^\xEF\xBB\xBF/, "") : newChunk, [complete, incomplete] = splitLines(`${incompleteLine}${chunk}`);
|
|
54
|
+
for (const line of complete)
|
|
55
|
+
parseLine(line);
|
|
56
|
+
incompleteLine = incomplete, isFirstChunk = false;
|
|
57
|
+
}
|
|
58
|
+
function parseLine(line) {
|
|
59
|
+
if (line === "") {
|
|
60
|
+
dispatchEvent();
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (line.startsWith(":")) {
|
|
64
|
+
onComment && onComment(line.slice(line.startsWith(": ") ? 2 : 1));
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const fieldSeparatorIndex = line.indexOf(":");
|
|
68
|
+
if (fieldSeparatorIndex !== -1) {
|
|
69
|
+
const field = line.slice(0, fieldSeparatorIndex), offset = line[fieldSeparatorIndex + 1] === " " ? 2 : 1, value = line.slice(fieldSeparatorIndex + offset);
|
|
70
|
+
processField(field, value, line);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
processField(line, "", line);
|
|
74
|
+
}
|
|
75
|
+
function processField(field, value, line) {
|
|
76
|
+
switch (field) {
|
|
77
|
+
case "event":
|
|
78
|
+
eventType = value;
|
|
79
|
+
break;
|
|
80
|
+
case "data":
|
|
81
|
+
data = `${data}${value}
|
|
82
|
+
`;
|
|
83
|
+
break;
|
|
84
|
+
case "id":
|
|
85
|
+
id = value.includes("\0") ? void 0 : value;
|
|
86
|
+
break;
|
|
87
|
+
case "retry":
|
|
88
|
+
/^\d+$/.test(value) ? onRetry(parseInt(value, 10)) : onError(
|
|
89
|
+
new ParseError(`Invalid \`retry\` value: "${value}"`, {
|
|
90
|
+
type: "invalid-retry",
|
|
91
|
+
value,
|
|
92
|
+
line
|
|
93
|
+
})
|
|
94
|
+
);
|
|
95
|
+
break;
|
|
96
|
+
default:
|
|
97
|
+
onError(
|
|
98
|
+
new ParseError(
|
|
99
|
+
`Unknown field "${field.length > 20 ? `${field.slice(0, 20)}\u2026` : field}"`,
|
|
100
|
+
{ type: "unknown-field", field, value, line }
|
|
101
|
+
)
|
|
102
|
+
);
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function dispatchEvent() {
|
|
107
|
+
data.length > 0 && onEvent({
|
|
108
|
+
id,
|
|
109
|
+
event: eventType || void 0,
|
|
110
|
+
// If the data buffer's last character is a U+000A LINE FEED (LF) character,
|
|
111
|
+
// then remove the last character from the data buffer.
|
|
112
|
+
data: data.endsWith(`
|
|
113
|
+
`) ? data.slice(0, -1) : data
|
|
114
|
+
}), id = void 0, data = "", eventType = "";
|
|
115
|
+
}
|
|
116
|
+
function reset(options = {}) {
|
|
117
|
+
incompleteLine && options.consume && parseLine(incompleteLine), isFirstChunk = true, id = void 0, data = "", eventType = "", incompleteLine = "";
|
|
118
|
+
}
|
|
119
|
+
return { feed, reset };
|
|
120
|
+
}
|
|
121
|
+
function splitLines(chunk) {
|
|
122
|
+
const lines = [];
|
|
123
|
+
let incompleteLine = "", searchIndex = 0;
|
|
124
|
+
for (; searchIndex < chunk.length; ) {
|
|
125
|
+
const crIndex = chunk.indexOf("\r", searchIndex), lfIndex = chunk.indexOf(`
|
|
126
|
+
`, searchIndex);
|
|
127
|
+
let lineEnd = -1;
|
|
128
|
+
if (crIndex !== -1 && lfIndex !== -1 ? lineEnd = Math.min(crIndex, lfIndex) : crIndex !== -1 ? crIndex === chunk.length - 1 ? lineEnd = -1 : lineEnd = crIndex : lfIndex !== -1 && (lineEnd = lfIndex), lineEnd === -1) {
|
|
129
|
+
incompleteLine = chunk.slice(searchIndex);
|
|
130
|
+
break;
|
|
131
|
+
} else {
|
|
132
|
+
const line = chunk.slice(searchIndex, lineEnd);
|
|
133
|
+
lines.push(line), searchIndex = lineEnd + 1, chunk[searchIndex - 1] === "\r" && chunk[searchIndex] === `
|
|
134
|
+
` && searchIndex++;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return [lines, incompleteLine];
|
|
138
|
+
}
|
|
139
|
+
exports.ParseError = ParseError;
|
|
140
|
+
exports.createParser = createParser;
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// ../../node_modules/.pnpm/eventsource-client@1.1.4/node_modules/eventsource-client/dist/node.js
|
|
145
|
+
var require_node = __commonJS({
|
|
146
|
+
"../../node_modules/.pnpm/eventsource-client@1.1.4/node_modules/eventsource-client/dist/node.js"(exports) {
|
|
147
|
+
"use strict";
|
|
148
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
149
|
+
var node_stream = __require("stream");
|
|
150
|
+
var eventsourceParser = require_dist();
|
|
151
|
+
var CONNECTING2 = "connecting";
|
|
152
|
+
var OPEN2 = "open";
|
|
153
|
+
var CLOSED2 = "closed";
|
|
154
|
+
var noop = () => {
|
|
155
|
+
};
|
|
156
|
+
function createEventSource$1(optionsOrUrl, { getStream: getStream2 }) {
|
|
157
|
+
const options = typeof optionsOrUrl == "string" || optionsOrUrl instanceof URL ? { url: optionsOrUrl } : optionsOrUrl, { onMessage, onConnect = noop, onDisconnect = noop, onScheduleReconnect = noop } = options, { fetch: fetch2, url, initialLastEventId } = validate(options), requestHeaders = { ...options.headers }, onCloseSubscribers = [], subscribers = onMessage ? [onMessage] : [], emit = (event) => subscribers.forEach((fn) => fn(event)), parser = eventsourceParser.createParser({ onEvent, onRetry });
|
|
158
|
+
let request, currentUrl = url.toString(), controller = new AbortController(), lastEventId = initialLastEventId, reconnectMs = 2e3, reconnectTimer, readyState = CLOSED2;
|
|
159
|
+
return connect(), {
|
|
160
|
+
close,
|
|
161
|
+
connect,
|
|
162
|
+
[Symbol.iterator]: () => {
|
|
163
|
+
throw new Error(
|
|
164
|
+
"EventSource does not support synchronous iteration. Use `for await` instead."
|
|
165
|
+
);
|
|
166
|
+
},
|
|
167
|
+
[Symbol.asyncIterator]: getEventIterator,
|
|
168
|
+
get lastEventId() {
|
|
169
|
+
return lastEventId;
|
|
170
|
+
},
|
|
171
|
+
get url() {
|
|
172
|
+
return currentUrl;
|
|
173
|
+
},
|
|
174
|
+
get readyState() {
|
|
175
|
+
return readyState;
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
function connect() {
|
|
179
|
+
request || (readyState = CONNECTING2, controller = new AbortController(), request = fetch2(url, getRequestOptions()).then(onFetchResponse).catch((err) => {
|
|
180
|
+
request = null, !(err.name === "AbortError" || err.type === "aborted" || controller.signal.aborted) && scheduleReconnect();
|
|
181
|
+
}));
|
|
182
|
+
}
|
|
183
|
+
function close() {
|
|
184
|
+
readyState = CLOSED2, controller.abort(), parser.reset(), clearTimeout(reconnectTimer), onCloseSubscribers.forEach((fn) => fn());
|
|
185
|
+
}
|
|
186
|
+
function getEventIterator() {
|
|
187
|
+
const pullQueue = [], pushQueue = [];
|
|
188
|
+
function pullValue() {
|
|
189
|
+
return new Promise((resolve) => {
|
|
190
|
+
const value = pushQueue.shift();
|
|
191
|
+
value ? resolve({ value, done: false }) : pullQueue.push(resolve);
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
const pushValue = function(value) {
|
|
195
|
+
const resolve = pullQueue.shift();
|
|
196
|
+
resolve ? resolve({ value, done: false }) : pushQueue.push(value);
|
|
197
|
+
};
|
|
198
|
+
function unsubscribe() {
|
|
199
|
+
for (subscribers.splice(subscribers.indexOf(pushValue), 1); pullQueue.shift(); )
|
|
200
|
+
;
|
|
201
|
+
for (; pushQueue.shift(); )
|
|
202
|
+
;
|
|
203
|
+
}
|
|
204
|
+
function onClose() {
|
|
205
|
+
const resolve = pullQueue.shift();
|
|
206
|
+
resolve && (resolve({ done: true, value: void 0 }), unsubscribe());
|
|
207
|
+
}
|
|
208
|
+
return onCloseSubscribers.push(onClose), subscribers.push(pushValue), {
|
|
209
|
+
next() {
|
|
210
|
+
return readyState === CLOSED2 ? this.return() : pullValue();
|
|
211
|
+
},
|
|
212
|
+
return() {
|
|
213
|
+
return unsubscribe(), Promise.resolve({ done: true, value: void 0 });
|
|
214
|
+
},
|
|
215
|
+
throw(error) {
|
|
216
|
+
return unsubscribe(), Promise.reject(error);
|
|
217
|
+
},
|
|
218
|
+
[Symbol.asyncIterator]() {
|
|
219
|
+
return this;
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
function scheduleReconnect() {
|
|
224
|
+
onScheduleReconnect({ delay: reconnectMs }), readyState = CONNECTING2, reconnectTimer = setTimeout(connect, reconnectMs);
|
|
225
|
+
}
|
|
226
|
+
async function onFetchResponse(response) {
|
|
227
|
+
onConnect(), parser.reset();
|
|
228
|
+
const { body, redirected, status } = response;
|
|
229
|
+
if (status === 204) {
|
|
230
|
+
onDisconnect(), close();
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
if (!body)
|
|
234
|
+
throw new Error("Missing response body");
|
|
235
|
+
redirected && (currentUrl = response.url);
|
|
236
|
+
const stream = getStream2(body), decoder = new TextDecoder(), reader = stream.getReader();
|
|
237
|
+
let open = true;
|
|
238
|
+
readyState = OPEN2;
|
|
239
|
+
do {
|
|
240
|
+
const { done, value } = await reader.read();
|
|
241
|
+
value && parser.feed(decoder.decode(value, { stream: !done })), done && (open = false, request = null, parser.reset(), scheduleReconnect(), onDisconnect());
|
|
242
|
+
} while (open);
|
|
243
|
+
}
|
|
244
|
+
function onEvent(msg) {
|
|
245
|
+
typeof msg.id == "string" && (lastEventId = msg.id), emit(msg);
|
|
246
|
+
}
|
|
247
|
+
function onRetry(ms) {
|
|
248
|
+
reconnectMs = ms;
|
|
249
|
+
}
|
|
250
|
+
function getRequestOptions() {
|
|
251
|
+
const { mode, credentials, body, method, redirect, referrer, referrerPolicy } = options, headers = { Accept: "text/event-stream", ...requestHeaders, ...lastEventId ? { "Last-Event-ID": lastEventId } : void 0 };
|
|
252
|
+
return {
|
|
253
|
+
mode,
|
|
254
|
+
credentials,
|
|
255
|
+
body,
|
|
256
|
+
method,
|
|
257
|
+
redirect,
|
|
258
|
+
referrer,
|
|
259
|
+
referrerPolicy,
|
|
260
|
+
headers,
|
|
261
|
+
cache: "no-store",
|
|
262
|
+
signal: controller.signal
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
function validate(options) {
|
|
267
|
+
const fetch2 = options.fetch || globalThis.fetch;
|
|
268
|
+
if (!isFetchLike(fetch2))
|
|
269
|
+
throw new Error("No fetch implementation provided, and one was not found on the global object.");
|
|
270
|
+
if (typeof AbortController != "function")
|
|
271
|
+
throw new Error("Missing AbortController implementation");
|
|
272
|
+
const { url, initialLastEventId } = options;
|
|
273
|
+
if (typeof url != "string" && !(url instanceof URL))
|
|
274
|
+
throw new Error("Invalid URL provided - must be string or URL instance");
|
|
275
|
+
if (typeof initialLastEventId != "string" && initialLastEventId !== void 0)
|
|
276
|
+
throw new Error("Invalid initialLastEventId provided - must be string or undefined");
|
|
277
|
+
return { fetch: fetch2, url, initialLastEventId };
|
|
278
|
+
}
|
|
279
|
+
function isFetchLike(fetch2) {
|
|
280
|
+
return typeof fetch2 == "function";
|
|
281
|
+
}
|
|
282
|
+
var nodeAbstractions = {
|
|
283
|
+
getStream
|
|
284
|
+
};
|
|
285
|
+
function createEventSource2(optionsOrUrl) {
|
|
286
|
+
return createEventSource$1(optionsOrUrl, nodeAbstractions);
|
|
287
|
+
}
|
|
288
|
+
function getStream(body) {
|
|
289
|
+
if ("getReader" in body)
|
|
290
|
+
return body;
|
|
291
|
+
if (typeof body.pipe != "function" || typeof body.on != "function")
|
|
292
|
+
throw new Error("Invalid response body, expected a web or node.js stream");
|
|
293
|
+
if (typeof node_stream.Readable.toWeb != "function")
|
|
294
|
+
throw new Error("Node.js 18 or higher required (`Readable.toWeb()` not defined)");
|
|
295
|
+
return node_stream.Readable.toWeb(node_stream.Readable.from(body));
|
|
296
|
+
}
|
|
297
|
+
exports.CLOSED = CLOSED2;
|
|
298
|
+
exports.CONNECTING = CONNECTING2;
|
|
299
|
+
exports.OPEN = OPEN2;
|
|
300
|
+
exports.createEventSource = createEventSource2;
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
|
|
1
304
|
// src/index.ts
|
|
2
305
|
import EventEmitter from "events";
|
|
306
|
+
|
|
307
|
+
// ../../node_modules/.pnpm/eventsource-client@1.1.4/node_modules/eventsource-client/dist/node.cjs.mjs
|
|
308
|
+
var import_node = __toESM(require_node(), 1);
|
|
309
|
+
var CLOSED = import_node.default.CLOSED;
|
|
310
|
+
var CONNECTING = import_node.default.CONNECTING;
|
|
311
|
+
var OPEN = import_node.default.OPEN;
|
|
312
|
+
var createEventSource = import_node.default.createEventSource;
|
|
313
|
+
|
|
314
|
+
// src/index.ts
|
|
315
|
+
var combineUrl = (base, path) => {
|
|
316
|
+
const baseUrl = base.endsWith("/") ? base.slice(0, -1) : base;
|
|
317
|
+
const pathUrl = path.startsWith("/") ? path.slice(1) : path;
|
|
318
|
+
return `${baseUrl}/${pathUrl}`;
|
|
319
|
+
};
|
|
3
320
|
var MilkyClient = class {
|
|
321
|
+
eventEmitter;
|
|
322
|
+
httpApiUrl;
|
|
323
|
+
eventUrl;
|
|
324
|
+
fetchHeader;
|
|
325
|
+
disposeCore;
|
|
4
326
|
/**
|
|
5
|
-
* @param
|
|
6
|
-
* @param
|
|
7
|
-
* @param base The base path for the Milky API
|
|
327
|
+
* @param authority The authority of the Milky API (value of `new URL('https://example.com:443/some-path').host`)
|
|
328
|
+
* @param basePath The base path for the Milky API
|
|
8
329
|
* @param accessToken The access token for authentication (optional)
|
|
9
|
-
* @param
|
|
330
|
+
* @param useTLS Whether to use HTTPS and WSS (default: false)
|
|
331
|
+
* @param useSSE Whether to use Server-Sent Events for event streaming (default: false)
|
|
10
332
|
*/
|
|
11
|
-
constructor(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
this.
|
|
16
|
-
this.fetchHeader =
|
|
17
|
-
"Content-Type": "application/json",
|
|
18
|
-
"Authorization": `Bearer ${this.accessToken}`
|
|
19
|
-
} : {
|
|
20
|
-
"Content-Type": "application/json"
|
|
21
|
-
};
|
|
22
|
-
this.wsClient = new WebSocket(this.eventUrl);
|
|
333
|
+
constructor(authority, basePath, accessToken, useTLS, useSSE) {
|
|
334
|
+
const httpProtocol = useTLS ? "https" : "http";
|
|
335
|
+
const urlFragment = `${authority}${basePath}`;
|
|
336
|
+
const httpUrlBase = `${httpProtocol}://${urlFragment}`;
|
|
337
|
+
this.fetchHeader = {};
|
|
338
|
+
if (accessToken) this.fetchHeader["Authorization"] = `Bearer ${accessToken}`;
|
|
23
339
|
this.eventEmitter = new EventEmitter();
|
|
24
|
-
this.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
340
|
+
this.httpApiUrl = combineUrl(httpUrlBase, "api");
|
|
341
|
+
this.eventUrl = combineUrl(httpUrlBase, "event");
|
|
342
|
+
if (!useSSE) {
|
|
343
|
+
this.createWebsocket();
|
|
344
|
+
} else {
|
|
345
|
+
this.createSSE();
|
|
346
|
+
}
|
|
28
347
|
}
|
|
29
|
-
httpApiUrl;
|
|
30
|
-
eventUrl;
|
|
31
|
-
wsClient;
|
|
32
|
-
fetchHeader;
|
|
33
|
-
eventEmitter;
|
|
34
348
|
/**
|
|
35
349
|
* Call a Milky API method.
|
|
36
350
|
* @param method The API method to call
|
|
@@ -38,9 +352,13 @@ var MilkyClient = class {
|
|
|
38
352
|
* If the API does not require any input, you can leave it empty.
|
|
39
353
|
*/
|
|
40
354
|
async callApi(method, ...input) {
|
|
41
|
-
const response = await fetch(
|
|
355
|
+
const response = await fetch(combineUrl(this.httpApiUrl, method), {
|
|
42
356
|
method: "POST",
|
|
43
|
-
headers:
|
|
357
|
+
headers: {
|
|
358
|
+
Accept: "application/json",
|
|
359
|
+
"Content-Type": "application/json",
|
|
360
|
+
...this.fetchHeader
|
|
361
|
+
},
|
|
44
362
|
body: JSON.stringify(input[0] ?? {})
|
|
45
363
|
});
|
|
46
364
|
const callResult = await response.json();
|
|
@@ -57,6 +375,42 @@ var MilkyClient = class {
|
|
|
57
375
|
async onEvent(eventType, listener) {
|
|
58
376
|
this.eventEmitter.on(eventType, listener);
|
|
59
377
|
}
|
|
378
|
+
createSSE() {
|
|
379
|
+
const sse = createEventSource({
|
|
380
|
+
url: this.eventUrl,
|
|
381
|
+
headers: {
|
|
382
|
+
Accept: "text/event-stream",
|
|
383
|
+
...this.fetchHeader
|
|
384
|
+
},
|
|
385
|
+
onMessage: ({ event, data }) => {
|
|
386
|
+
if (event !== "milky_event") return;
|
|
387
|
+
const parsedData = JSON.parse(data);
|
|
388
|
+
this.eventEmitter.emit(parsedData.event_type, parsedData);
|
|
389
|
+
}
|
|
390
|
+
});
|
|
391
|
+
sse.connect();
|
|
392
|
+
this.disposeCore = sse.close;
|
|
393
|
+
}
|
|
394
|
+
createWebsocket() {
|
|
395
|
+
if (!globalThis.WebSocket) throw new Error("WebSocket is not supported in this environment.");
|
|
396
|
+
const ws = new WebSocket(this.eventUrl, {
|
|
397
|
+
headers: {
|
|
398
|
+
...this.fetchHeader
|
|
399
|
+
}
|
|
400
|
+
});
|
|
401
|
+
ws.addEventListener("message", (event) => {
|
|
402
|
+
const data = JSON.parse(event.data);
|
|
403
|
+
this.eventEmitter.emit(data.event_type, data);
|
|
404
|
+
});
|
|
405
|
+
this.disposeCore = ws.close;
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* Release the WebSocket / Server Sent Event connection.
|
|
409
|
+
*/
|
|
410
|
+
dispose() {
|
|
411
|
+
this.disposeCore?.();
|
|
412
|
+
}
|
|
413
|
+
[Symbol.dispose] = this.dispose;
|
|
60
414
|
};
|
|
61
415
|
export {
|
|
62
416
|
MilkyClient
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saltify/milky-node-sdk",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.1.0-beta.
|
|
4
|
+
"version": "0.1.0-beta.10",
|
|
5
5
|
"description": "Node.js SDK for Milky protocol",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"typings": "dist/index.d.ts",
|
|
@@ -16,13 +16,15 @@
|
|
|
16
16
|
},
|
|
17
17
|
"license": "CC0-1.0",
|
|
18
18
|
"devDependencies": {
|
|
19
|
-
"@types/node": "^22.17.2"
|
|
19
|
+
"@types/node": "^22.17.2",
|
|
20
|
+
"eventsource-client": "^1.1.4"
|
|
20
21
|
},
|
|
21
22
|
"dependencies": {
|
|
22
|
-
"@saltify/milky-types": "^1.0.0-draft.
|
|
23
|
-
"zod": "^4.
|
|
23
|
+
"@saltify/milky-types": "^1.0.0-draft.19",
|
|
24
|
+
"zod": "^4.1.5"
|
|
24
25
|
},
|
|
25
26
|
"scripts": {
|
|
26
|
-
"build": "tsup"
|
|
27
|
+
"build": "npm run gen:apis && tsup",
|
|
28
|
+
"gen:apis": "tsx ./scripts/gen_code.ts"
|
|
27
29
|
}
|
|
28
30
|
}
|