comty.js 0.59.2 → 0.60.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.
Files changed (48) hide show
  1. package/dist/handlers/measurePing.js +0 -0
  2. package/dist/handlers/request.js +0 -0
  3. package/dist/helpers/handleAfterRequest.js +14 -14
  4. package/dist/helpers/handleBeforeRequest.js +3 -9
  5. package/dist/helpers/handleRegenerationEvent.js +0 -0
  6. package/dist/helpers/measurePing.js +62 -0
  7. package/dist/helpers/refreshToken.js +42 -0
  8. package/dist/helpers/withSettings.js +0 -0
  9. package/dist/helpers/withStorage.js +0 -0
  10. package/dist/hooks/useRequest/index.js +3 -4
  11. package/dist/index.js +107 -87
  12. package/dist/models/auth/index.js +115 -33
  13. package/dist/models/chats/index.js +37 -0
  14. package/dist/models/feed/index.js +46 -14
  15. package/dist/models/follows/index.js +36 -18
  16. package/dist/models/index.js +1 -4
  17. package/dist/models/livestream/index.js +0 -0
  18. package/dist/models/music/getters/featuredPlaylists.js +11 -0
  19. package/dist/models/music/getters/index.js +36 -0
  20. package/dist/models/music/getters/myReleases.js +26 -0
  21. package/dist/models/music/getters/playlistData.js +11 -0
  22. package/dist/models/music/getters/playlistItem.js +11 -0
  23. package/dist/models/music/getters/playlists.js +29 -0
  24. package/dist/models/music/getters/releaseData.js +11 -0
  25. package/dist/models/music/getters/releases.js +29 -0
  26. package/dist/models/music/getters/search.js +26 -0
  27. package/dist/models/music/getters/trackData.js +12 -0
  28. package/dist/models/music/getters/trackLyrics.js +31 -0
  29. package/dist/models/music/getters/tracks.js +29 -0
  30. package/dist/models/music/index.js +95 -240
  31. package/dist/models/nfc/index.js +27 -1
  32. package/dist/models/playlists/index.js +0 -0
  33. package/dist/models/post/index.js +133 -70
  34. package/dist/models/search/index.js +17 -4
  35. package/dist/models/session/index.js +105 -56
  36. package/dist/models/sync/cores/spotifyCore.js +0 -0
  37. package/dist/models/sync/index.js +9 -15
  38. package/dist/models/sync/services/spotify.js +0 -0
  39. package/dist/models/sync/services/tidal.js +1 -1
  40. package/dist/models/sync/services/vrc.js +0 -0
  41. package/dist/models/user/index.js +78 -100
  42. package/dist/models/widget/index.js +0 -0
  43. package/dist/remote.js +43 -0
  44. package/dist/remotes.js +5 -63
  45. package/dist/request.js +51 -0
  46. package/dist/utils/generateRequest.js +52 -0
  47. package/dist/utils/importFrom.js +22 -0
  48. package/package.json +5 -4
File without changes
File without changes
@@ -1,34 +1,34 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }var _handleRegenerationEvent = require('./handleRegenerationEvent'); var _handleRegenerationEvent2 = _interopRequireDefault(_handleRegenerationEvent);
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }var _refreshToken = require('./refreshToken'); var _refreshToken2 = _interopRequireDefault(_refreshToken);
2
2
 
3
3
  exports. default = async (data, callback) => {
4
4
  // handle 401, 403 responses
5
5
  if (data instanceof Error) {
6
6
  if (data.code && (data.code === "ECONNABORTED" || data.code === "ERR_NETWORK")) {
7
- console.error(`Request aborted or network error, ignoring`)
7
+ console.error(`Request aborted or network error`)
8
8
  return false
9
9
  }
10
10
 
11
11
  if (data.response.status === 401) {
12
12
  // check if the server issue a refresh token on data
13
- if (data.response.data.refreshToken) {
14
- console.log(`Session expired, but the server issued a refresh token, handling regeneration event`)
13
+ if (data.response.data.expired) {
14
+ try {
15
+ console.log(`Session expired, trying to regenerate...`)
15
16
 
16
- // handle regeneration event
17
- await _handleRegenerationEvent2.default.call(void 0, data.response.data.refreshToken)
17
+ await _refreshToken2.default.call(void 0, )
18
+ } catch (error) {
19
+ __comty_shared_state.eventBus.emit("session.invalid", error.message)
18
20
 
19
- return await callback()
20
- }
21
+ console.error(`Failed to regenerate token: ${error.message}`)
22
+
23
+ throw new Error(`Invalid or Expired session`)
24
+ }
21
25
 
22
- // check if route is from "session" namespace
23
- if (data.config.url.includes("/session")) {
24
- return __comty_shared_state.eventBus.emit("session.invalid", "Session expired, but the server did not issue a refresh token")
26
+ return await callback()
25
27
  }
26
28
  }
27
29
 
28
30
  if (data.response.status === 403) {
29
- if (data.config.url.includes("/session")) {
30
- return __comty_shared_state.eventBus.emit("session.invalid", "Session not valid or not existent")
31
- }
31
+
32
32
  }
33
33
  }
34
34
  }
@@ -1,13 +1,7 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});exports. default = async (request) => {
2
- if (__comty_shared_state.onExpiredExceptionEvent) {
3
- if (__comty_shared_state.excludedExpiredExceptionURL.includes(request.url)) return
4
-
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});exports. default = async () => {
2
+ if (__comty_shared_state.refreshingToken === true) {
5
3
  await new Promise((resolve) => {
6
- __comty_shared_state.eventBus.once("session.regenerated", () => {
7
- console.log(`Session has been regenerated, retrying request`)
8
-
9
- resolve()
10
- })
4
+ __comty_shared_state.eventBus.once("session:refreshed", resolve)
11
5
  })
12
6
  }
13
7
  }
File without changes
@@ -0,0 +1,62 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }var _request = require('../request'); var _request2 = _interopRequireDefault(_request);
2
+
3
+ const fetchers = {
4
+ http: () => new Promise(async (resolve) => {
5
+ const start = Date.now()
6
+
7
+ const failTimeout = setTimeout(() => {
8
+ resolve("timeout")
9
+ }, 5000)
10
+
11
+ _request2.default.call(void 0, {
12
+ method: "GET",
13
+ url: "/ping",
14
+ })
15
+ .then(() => {
16
+ clearTimeout(failTimeout)
17
+ resolve(Date.now() - start)
18
+ })
19
+ .catch((err) => {
20
+ console.log(err)
21
+ clearTimeout(failTimeout)
22
+ resolve("failed")
23
+ })
24
+ }),
25
+ ws: () => new Promise((resolve) => {
26
+ const start = Date.now()
27
+
28
+ const failTimeout = setTimeout(() => {
29
+ resolve("failed")
30
+ }, 5000)
31
+
32
+ globalThis.__comty_shared_state.sockets["main"].on("pong", () => {
33
+ failTimeout && clearTimeout(failTimeout)
34
+
35
+ resolve(Date.now() - start)
36
+ })
37
+
38
+ globalThis.__comty_shared_state.sockets["main"].emit("ping")
39
+ })
40
+ }
41
+
42
+ exports. default = async ({ select } = {}) => {
43
+ let selectedPromises = []
44
+
45
+ if (Array.isArray(select)) {
46
+ select.forEach((item) => {
47
+ if (!fetchers[item]) {
48
+ return
49
+ }
50
+ selectedPromises.push(fetchers[item]())
51
+ })
52
+ } else {
53
+ selectedPromises = [
54
+ fetchers["http"](),
55
+ fetchers["ws"](),
56
+ ]
57
+ }
58
+
59
+ const result = await Promise.all(selectedPromises)
60
+
61
+ return result
62
+ }
@@ -0,0 +1,42 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var _session = require('../models/session'); var _session2 = _interopRequireDefault(_session);
2
+ var _ = require('..');
3
+ exports. default = async () => {
4
+ __comty_shared_state.eventBus.emit("session:refreshing")
5
+ __comty_shared_state.refreshingToken = true
6
+
7
+ // send request to regenerate token
8
+ const response = await __comty_shared_state.baseRequest({
9
+ method: "POST",
10
+ url: "/auth",
11
+ data: {
12
+ authToken: await _session2.default.token,
13
+ refreshToken: await _session2.default.refreshToken,
14
+ }
15
+ }).catch((error) => {
16
+ return false
17
+ })
18
+
19
+ if (!response) {
20
+ __comty_shared_state.refreshingToken = false
21
+
22
+ throw new Error("Failed to regenerate token.")
23
+ }
24
+
25
+ if (!_optionalChain([response, 'access', _3 => _3.data, 'optionalAccess', _4 => _4.token])) {
26
+ __comty_shared_state.refreshingToken = false
27
+
28
+ throw new Error("Failed to regenerate token, invalid server response.")
29
+ }
30
+
31
+ // set new token
32
+ _session2.default.token = response.data.token
33
+ _session2.default.refreshToken = response.data.refreshToken
34
+
35
+ // emit event
36
+ __comty_shared_state.eventBus.emit("session:refreshed")
37
+ __comty_shared_state.refreshingToken = false
38
+
39
+ _.reauthenticateWebsockets.call(void 0, )
40
+
41
+ return true
42
+ }
File without changes
File without changes
@@ -1,14 +1,13 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }var _react = require('react'); var _react2 = _interopRequireDefault(_react);
2
2
 
3
3
  exports. default = (method, ...args) => {
4
- if (typeof method !== "function") {
5
- throw new Error("useRequest: method must be a function")
6
- }
7
-
8
4
  const [loading, setLoading] = _react2.default.useState(true)
9
5
  const [result, setResult] = _react2.default.useState(null)
10
6
  const [error, setError] = _react2.default.useState(null)
11
7
 
8
+ if (typeof method !== "function") {
9
+ return [() => {}, null, new Error("Method is not a function"), () => {}]
10
+ }
12
11
  const makeRequest = (...newArgs) => {
13
12
  method(...newArgs)
14
13
  .then((data) => {
package/dist/index.js CHANGED
@@ -4,13 +4,9 @@ var _events = require('@foxify/events'); var _events2 = _interopRequireDefault(_
4
4
  var _axios = require('axios'); var _axios2 = _interopRequireDefault(_axios);
5
5
  var _socketioclient = require('socket.io-client');
6
6
 
7
- var _remotes = require('./remotes'); var _remotes2 = _interopRequireDefault(_remotes);
8
-
9
- //import request from "./handlers/request"
10
- var _withStorage = require('./helpers/withStorage'); var _withStorage2 = _interopRequireDefault(_withStorage);
11
-
12
- var _session = require('./models/session'); var _session2 = _interopRequireDefault(_session);
13
7
  var _models = require('./models');
8
+ var _withStorage = require('./helpers/withStorage'); var _withStorage2 = _interopRequireDefault(_withStorage);
9
+ var _remote = require('./remote'); var _remote2 = _interopRequireDefault(_remote);
14
10
 
15
11
  globalThis.isServerMode = typeof window === "undefined" && typeof global !== "undefined"
16
12
 
@@ -25,8 +21,19 @@ if (globalThis.isServerMode) {
25
21
  }
26
22
  }
27
23
 
24
+ /**
25
+ * Creates websockets by disconnecting and removing listeners from existing instances,
26
+ * then creating new instances for each websocket in the remote.websockets array.
27
+ * Registers event listeners for connection, disconnection, reconnection, error, and any other events.
28
+ *
29
+ * @return {Promise<void>} A promise that resolves when all websockets have been created and event listeners have been registered.
30
+ */
28
31
  async function createWebsockets() {
29
- const instances = globalThis.__comty_shared_state.wsInstances
32
+ if (!_remote2.default.websockets) {
33
+ return false
34
+ }
35
+
36
+ const instances = globalThis.__comty_shared_state.sockets
30
37
 
31
38
  for (let [key, instance] of Object.entries(instances)) {
32
39
  if (instance.connected) {
@@ -37,66 +44,70 @@ if (globalThis.isServerMode) {
37
44
  // remove current listeners
38
45
  instance.removeAllListeners()
39
46
 
40
- delete globalThis.__comty_shared_state.wsInstances[key]
47
+ delete globalThis.__comty_shared_state.sockets[key]
41
48
  }
42
49
 
43
- for (let [key, remote] of Object.entries(_remotes2.default)) {
44
- if (!remote.hasWebsocket) {
45
- continue
46
- }
47
-
50
+ for (let ws of _remote2.default.websockets) {
48
51
  let opts = {
49
52
  transports: ["websocket"],
50
- autoConnect: _nullishCoalesce(remote.autoConnect, () => ( true)),
51
- ..._nullishCoalesce(remote.wsParams, () => ( {})),
53
+ autoConnect: _nullishCoalesce(ws.autoConnect, () => ( true)),
54
+ forceNew: true,
55
+ path: ws.path,
56
+ ..._nullishCoalesce(ws.params, () => ( {})),
52
57
  }
53
58
 
54
- if (remote.noAuth !== true) {
59
+ if (ws.noAuth !== true) {
55
60
  opts.auth = {
56
- token: _session2.default.token,
61
+ token: _withStorage2.default.engine.get("token"),
57
62
  }
58
63
  }
59
64
 
60
- globalThis.__comty_shared_state.wsInstances[key] = _socketioclient.io.call(void 0, _nullishCoalesce(remote.wsOrigin, () => ( remote.origin)), opts)
65
+ globalThis.__comty_shared_state.sockets[ws.namespace] = _socketioclient.io.call(void 0, _remote2.default.origin, opts)
61
66
  }
62
67
 
63
68
  // regsister events
64
69
  for (let [key, instance] of Object.entries(instances)) {
65
70
  instance.on("connect", () => {
66
- console.debug(`[WS-API][${key}] Connected`)
67
-
68
- if (_remotes2.default[key].useClassicAuth && _remotes2.default[key].noAuth !== true) {
69
- // try to auth
70
- instance.emit("auth", {
71
- token: _session2.default.token,
72
- })
73
- }
71
+ //console.debug(`[WS-API][${key}] Connected`)
74
72
 
75
73
  globalThis.__comty_shared_state.eventBus.emit(`${key}:connected`)
76
74
  })
77
75
 
78
76
  instance.on("disconnect", () => {
79
- console.debug(`[WS-API][${key}] Disconnected`)
77
+ //console.debug(`[WS-API][${key}] Disconnected`)
80
78
 
81
79
  globalThis.__comty_shared_state.eventBus.emit(`${key}:disconnected`)
82
80
  })
83
81
 
82
+ instance.on("reconnect", () => {
83
+ // console.debug(`[WS-API][${key}] Reconnected`)
84
+
85
+ globalThis.__comty_shared_state.eventBus.emit(`${key}:reconnected`)
86
+
87
+ reauthenticateWebsockets()
88
+ })
89
+
84
90
  instance.on("error", (error) => {
85
- console.error(`[WS-API][${key}] Error`, error)
91
+ //console.error(`[WS-API][${key}] Error`, error)
86
92
 
87
93
  globalThis.__comty_shared_state.eventBus.emit(`${key}:error`, error)
88
94
  })
89
95
 
90
96
  instance.onAny((event, ...args) => {
91
- console.debug(`[WS-API][${key}] Event (${event})`, ...args)
97
+ //console.debug(`[WS-API][${key}] Event (${event})`, ...args)
92
98
 
93
99
  globalThis.__comty_shared_state.eventBus.emit(`${key}:${event}`, ...args)
94
100
  })
95
101
  }
96
102
  } exports.createWebsockets = createWebsockets;
97
103
 
104
+ /**
105
+ * Disconnects all websocket instances by calling the `disconnect` method on each instance.
106
+ *
107
+ * @return {Promise<void>} A promise that resolves when all websocket instances have been disconnected.
108
+ */
98
109
  async function disconnectWebsockets() {
99
- const instances = globalThis.__comty_shared_state.wsInstances
110
+ const instances = globalThis.__comty_shared_state.sockets
100
111
 
101
112
  for (let [key, instance] of Object.entries(instances)) {
102
113
  if (instance.connected) {
@@ -105,97 +116,106 @@ if (globalThis.isServerMode) {
105
116
  }
106
117
  } exports.disconnectWebsockets = disconnectWebsockets;
107
118
 
108
- async function reconnectWebsockets({ force = false } = {}) {
109
- const instances = globalThis.__comty_shared_state.wsInstances
119
+ /**
120
+ * Reconnects all websocket instances by disconnecting and reconnecting them with the current token.
121
+ *
122
+ * @return {Promise<void>} A promise that resolves when all websocket instances have been reconnected.
123
+ */
124
+ async function reconnectWebsockets() {
125
+ const instances = globalThis.__comty_shared_state.sockets
110
126
 
111
127
  for (let [key, instance] of Object.entries(instances)) {
112
128
  if (instance.connected) {
113
- if (!instance.auth) {
114
- instance.disconnect()
115
-
116
- instance.auth = {
117
- token: _session2.default.token,
118
- }
119
-
120
- instance.connect()
121
- continue
122
- }
123
-
124
- if (!force) {
125
- instance.emit("reauthenticate", {
126
- token: _session2.default.token,
127
- })
128
-
129
- continue
130
- }
131
-
132
129
  // disconnect first
133
130
  instance.disconnect()
134
131
  }
135
132
 
136
- if (_remotes2.default[key].noAuth !== true) {
137
- instance.auth = {
138
- token: _session2.default.token,
139
- }
133
+ instance.auth = {
134
+ token: _withStorage2.default.engine.get("token"),
140
135
  }
141
136
 
142
137
  instance.connect()
143
138
  }
144
139
  } exports.reconnectWebsockets = reconnectWebsockets;
145
140
 
141
+ /**
142
+ * Reauthenticates all websocket instances with the current token. If a websocket instance is not connected, it connects to the server. If it is connected, it emits an "auth:reauth" event with the current token.
143
+ *
144
+ * @return {Promise<void>} Promise that resolves when all websocket instances have been reauthenticated.
145
+ */
146
+ async function reauthenticateWebsockets() {
147
+ const instances = globalThis.__comty_shared_state.sockets
148
+
149
+ for (let [key, instance] of Object.entries(instances)) {
150
+ const token = _withStorage2.default.engine.get("token")
151
+
152
+ instance.auth = {
153
+ token: token,
154
+ }
155
+
156
+ if (!instance.connected) {
157
+ instance.connect()
158
+ } else {
159
+ instance.emit("auth:reauth", token)
160
+ }
161
+ }
162
+ } exports.reauthenticateWebsockets = reauthenticateWebsockets;
163
+
164
+ /**
165
+ * Create a client with the specified access key, private key, and websocket enablement.
166
+ *
167
+ * @param {Object} options - Optional parameters for accessKey, privateKey, and enableWs
168
+ * @return {Object} sharedState - Object containing eventBus, mainOrigin, baseRequest, sockets, rest, and version
169
+ */
146
170
  function createClient({
147
171
  accessKey = null,
148
172
  privateKey = null,
149
173
  enableWs = false,
174
+ origin = _remote2.default.origin,
150
175
  } = {}) {
151
176
  const sharedState = globalThis.__comty_shared_state = {
152
- onExpiredExceptionEvent: false,
153
- excludedExpiredExceptionURL: ["/session/regenerate"],
154
177
  eventBus: new (0, _events2.default)(),
155
- mainOrigin: _remotes2.default.default.origin,
156
- instances: Object(),
157
- wsInstances: Object(),
178
+ mainOrigin: origin,
179
+ baseRequest: null,
180
+ sockets: new Map(),
158
181
  rest: null,
159
182
  version: _packagejson2.default.version,
160
183
  }
161
184
 
162
- if (globalThis.isServerMode) {
163
- sharedState.rest = _models.createHandlers.call(void 0, )
164
- }
185
+ sharedState.rest = _models.createHandlers.call(void 0, )
165
186
 
166
187
  if (privateKey && accessKey && globalThis.isServerMode) {
167
188
  _withStorage2.default.engine.set("token", `${accessKey}:${privateKey}`)
168
189
  }
169
190
 
170
- // create instances for every remote
171
- for (const [key, remote] of Object.entries(_remotes2.default)) {
172
- sharedState.instances[key] = _axios2.default.create({
173
- baseURL: remote.origin,
174
- headers: {
175
- "Content-Type": "application/json",
176
- }
177
- })
178
-
179
- // create a interceptor to attach the token every request
180
- sharedState.instances[key].interceptors.request.use((config) => {
181
- // check if current request has no Authorization header, if so, attach the token
182
- if (!config.headers["Authorization"]) {
183
- const sessionToken = _session2.default.token
184
-
185
- if (sessionToken) {
186
- config.headers["Authorization"] = `${globalThis.isServerMode ? "Server" : "Bearer"} ${sessionToken}`
187
- } else {
188
- console.warn("Making a request with no session token")
189
- }
191
+ sharedState.baseRequest = _axios2.default.create({
192
+ baseURL: origin,
193
+ headers: {
194
+ "Content-Type": "application/json",
195
+ }
196
+ })
197
+
198
+ // create a interceptor to attach the token every request
199
+ sharedState.baseRequest.interceptors.request.use((config) => {
200
+ // check if current request has no Authorization header, if so, attach the token
201
+ if (!config.headers["Authorization"]) {
202
+ const sessionToken = _withStorage2.default.engine.get("token")
203
+
204
+ if (sessionToken) {
205
+ config.headers["Authorization"] = `${globalThis.isServerMode ? "Server" : "Bearer"} ${sessionToken}`
206
+ } else {
207
+ console.warn("Making a request with no session token")
190
208
  }
209
+ }
191
210
 
192
- return config
193
- })
194
- }
211
+ return config
212
+ })
195
213
 
196
214
  if (enableWs) {
197
215
  createWebsockets()
198
216
  }
199
217
 
200
218
  return sharedState
201
- } exports.default = createClient;
219
+ } exports.createClient = createClient;
220
+
221
+ exports. default = createClient