itd-api 0.7.2 → 0.9.0

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 (104) hide show
  1. package/README.md +72 -27
  2. package/dist/events/index.cjs +53 -0
  3. package/dist/events/index.d.cts +3 -0
  4. package/dist/events/index.d.ts +3 -0
  5. package/dist/events/index.js +5 -0
  6. package/dist/index.cjs +234 -200
  7. package/dist/index.cjs.map +1 -1
  8. package/dist/index.d.cts +70 -64
  9. package/dist/index.d.ts +70 -64
  10. package/dist/index.js +202 -179
  11. package/dist/index.js.map +1 -1
  12. package/dist/node/index.cjs +6 -5
  13. package/dist/node/index.cjs.map +1 -1
  14. package/dist/node/index.d.cts +2 -2
  15. package/dist/node/index.d.ts +2 -2
  16. package/dist/node/index.js +5 -4
  17. package/dist/node/index.js.map +1 -1
  18. package/dist/rest/index.cjs +32 -26
  19. package/dist/rest/index.cjs.map +1 -1
  20. package/dist/rest/index.d.cts +9 -7
  21. package/dist/rest/index.d.ts +9 -7
  22. package/dist/rest/index.js +19 -21
  23. package/dist/rest/index.js.map +1 -1
  24. package/dist/shared/{errors-DfU8M5eS.cjs → errors-BmP3TKoW.cjs} +3 -3
  25. package/dist/shared/{errors-DfU8M5eS.cjs.map → errors-BmP3TKoW.cjs.map} +1 -1
  26. package/dist/shared/{errors-Bhrd2fJd.js → errors-GI10kZxk.js} +3 -3
  27. package/dist/shared/{errors-Bhrd2fJd.js.map → errors-GI10kZxk.js.map} +1 -1
  28. package/dist/shared/{websocket-BLR8eVJV.js → events-C5wnTXPT.js} +770 -490
  29. package/dist/shared/events-C5wnTXPT.js.map +1 -0
  30. package/dist/shared/events-CqtkP65d.d.ts +698 -0
  31. package/dist/shared/events-DGAWlCaI.d.cts +698 -0
  32. package/dist/shared/{websocket-C_eI4H2o.cjs → events-FZfnEez0.cjs} +834 -518
  33. package/dist/shared/events-FZfnEez0.cjs.map +1 -0
  34. package/dist/shared/{storage-BPJR_k4-.cjs → key-value-store-B5GYVEYZ.cjs} +2 -86
  35. package/dist/shared/key-value-store-B5GYVEYZ.cjs.map +1 -0
  36. package/dist/shared/{storage-D86edNCB.js → key-value-store-Bt2PSMxY.js} +3 -69
  37. package/dist/shared/key-value-store-Bt2PSMxY.js.map +1 -0
  38. package/dist/shared/key-value-store-COZaNHZS.d.cts +69 -0
  39. package/dist/shared/key-value-store-COZaNHZS.d.ts +69 -0
  40. package/dist/shared/{multi-storage-DccjD7Ww.d.ts → multi-storage-BEL7tcKn.d.cts} +3 -2
  41. package/dist/shared/{multi-storage--yTEqiod.cjs → multi-storage-CDKLa956.cjs} +11 -10
  42. package/dist/shared/{multi-storage--yTEqiod.cjs.map → multi-storage-CDKLa956.cjs.map} +1 -1
  43. package/dist/shared/{multi-storage-CjAPB5Kq.d.cts → multi-storage-LkljOSzA.d.ts} +3 -2
  44. package/dist/shared/{multi-storage-CkvTUC5m.js → multi-storage-SoW05uzO.js} +5 -4
  45. package/dist/shared/{multi-storage-CkvTUC5m.js.map → multi-storage-SoW05uzO.js.map} +1 -1
  46. package/dist/shared/{options-Dg5N3r1V.cjs → options-DOJYtoti.cjs} +8 -6
  47. package/dist/shared/options-DOJYtoti.cjs.map +1 -0
  48. package/dist/shared/{options-DtATYdLr.js → options-DhgGg7Ms.js} +8 -6
  49. package/dist/shared/options-DhgGg7Ms.js.map +1 -0
  50. package/dist/shared/{cookies-DZwFq6kr.cjs → redact-BP00URmQ.cjs} +312 -2
  51. package/dist/shared/redact-BP00URmQ.cjs.map +1 -0
  52. package/dist/shared/{cookies-tX2sNwxb.js → redact-Ba5iSVYZ.js} +235 -3
  53. package/dist/shared/redact-Ba5iSVYZ.js.map +1 -0
  54. package/dist/shared/{render-CgwKdOzu.d.ts → render-B4qis7Sb.d.ts} +775 -313
  55. package/dist/shared/{render-DO0F5YSm.d.cts → render-DDwy2Ame.d.cts} +775 -313
  56. package/dist/shared/{render-mcuELiYi.cjs → render-Dqi8Owqk.cjs} +1464 -662
  57. package/dist/shared/render-Dqi8Owqk.cjs.map +1 -0
  58. package/dist/shared/{render-C6HRPs10.js → render-hiWFh2s4.js} +1366 -618
  59. package/dist/shared/render-hiWFh2s4.js.map +1 -0
  60. package/dist/shared/storage-BQrtKon9.d.cts +86 -0
  61. package/dist/shared/storage-CTRGT5wF.d.ts +86 -0
  62. package/dist/shared/storage-CfHKzVHf.js +71 -0
  63. package/dist/shared/storage-CfHKzVHf.js.map +1 -0
  64. package/dist/shared/storage-QNVxzpDB.cjs +88 -0
  65. package/dist/shared/storage-QNVxzpDB.cjs.map +1 -0
  66. package/dist/shared/{url-BaMCQpYH.cjs → url-Bsb3xE5U.cjs} +577 -466
  67. package/dist/shared/url-Bsb3xE5U.cjs.map +1 -0
  68. package/dist/shared/{url-IU0xN9wX.js → url-DP33mp3s.js} +508 -409
  69. package/dist/shared/url-DP33mp3s.js.map +1 -0
  70. package/dist/shared/{url-DTfZ2toq.d.ts → url-XBsMdAcv.d.cts} +1313 -1200
  71. package/dist/shared/{url-DTfZ2toq.d.cts → url-XBsMdAcv.d.ts} +1313 -1200
  72. package/dist/web/index.cjs +5 -4
  73. package/dist/web/index.cjs.map +1 -1
  74. package/dist/web/index.d.cts +1 -1
  75. package/dist/web/index.d.ts +1 -1
  76. package/dist/web/index.js +3 -2
  77. package/dist/web/index.js.map +1 -1
  78. package/package.json +16 -15
  79. package/dist/realtime/index.cjs +0 -165
  80. package/dist/realtime/index.cjs.map +0 -1
  81. package/dist/realtime/index.d.cts +0 -51
  82. package/dist/realtime/index.d.ts +0 -51
  83. package/dist/realtime/index.js +0 -120
  84. package/dist/realtime/index.js.map +0 -1
  85. package/dist/shared/auth-provider-CG8oCQ9F.cjs +0 -108
  86. package/dist/shared/auth-provider-CG8oCQ9F.cjs.map +0 -1
  87. package/dist/shared/auth-provider-mYqxsSVa.js +0 -91
  88. package/dist/shared/auth-provider-mYqxsSVa.js.map +0 -1
  89. package/dist/shared/cookies-DZwFq6kr.cjs.map +0 -1
  90. package/dist/shared/cookies-tX2sNwxb.js.map +0 -1
  91. package/dist/shared/options-Dg5N3r1V.cjs.map +0 -1
  92. package/dist/shared/options-DtATYdLr.js.map +0 -1
  93. package/dist/shared/render-C6HRPs10.js.map +0 -1
  94. package/dist/shared/render-mcuELiYi.cjs.map +0 -1
  95. package/dist/shared/storage-BPJR_k4-.cjs.map +0 -1
  96. package/dist/shared/storage-C_eICCep.d.cts +0 -152
  97. package/dist/shared/storage-C_eICCep.d.ts +0 -152
  98. package/dist/shared/storage-D86edNCB.js.map +0 -1
  99. package/dist/shared/url-BaMCQpYH.cjs.map +0 -1
  100. package/dist/shared/url-IU0xN9wX.js.map +0 -1
  101. package/dist/shared/websocket-BLR8eVJV.js.map +0 -1
  102. package/dist/shared/websocket-C_eI4H2o.cjs.map +0 -1
  103. package/dist/shared/websocket-DF7XIMiX.d.cts +0 -562
  104. package/dist/shared/websocket-DYKBr8HF.d.ts +0 -562
package/dist/index.cjs CHANGED
@@ -1,12 +1,65 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_url = require("./shared/url-BaMCQpYH.cjs");
3
- const require_errors = require("./shared/errors-DfU8M5eS.cjs");
4
- const require_cookies = require("./shared/cookies-DZwFq6kr.cjs");
5
- const require_render = require("./shared/render-mcuELiYi.cjs");
6
- const require_websocket = require("./shared/websocket-C_eI4H2o.cjs");
7
- const require_storage = require("./shared/storage-BPJR_k4-.cjs");
8
- const require_options = require("./shared/options-Dg5N3r1V.cjs");
9
- const require_multi_storage = require("./shared/multi-storage--yTEqiod.cjs");
2
+ const require_url = require("./shared/url-Bsb3xE5U.cjs");
3
+ const require_errors = require("./shared/errors-BmP3TKoW.cjs");
4
+ const require_redact = require("./shared/redact-BP00URmQ.cjs");
5
+ const require_render = require("./shared/render-Dqi8Owqk.cjs");
6
+ const require_options = require("./shared/options-DOJYtoti.cjs");
7
+ const require_events = require("./shared/events-FZfnEez0.cjs");
8
+ const require_key_value_store = require("./shared/key-value-store-B5GYVEYZ.cjs");
9
+ const require_storage = require("./shared/storage-QNVxzpDB.cjs");
10
+ const require_multi_storage = require("./shared/multi-storage-CDKLa956.cjs");
11
+ //#region src/notifications-api.ts
12
+ var ClientNotifications = class extends require_render.NotificationsResource {
13
+ #createEvents;
14
+ #events;
15
+ constructor(http, createEvents) {
16
+ super(http);
17
+ this.#createEvents = createEvents;
18
+ }
19
+ get events() {
20
+ this.#events ??= this.#createEvents(this);
21
+ return this.#events;
22
+ }
23
+ };
24
+ /** Создаёт API уведомлений полного клиента. @internal */
25
+ function createNotificationsApi(http, createEvents) {
26
+ return new ClientNotifications(http, createEvents);
27
+ }
28
+ //#endregion
29
+ //#region src/operations/auth.ts
30
+ /** Чем закончился запрос входа. */
31
+ const SignInStatus = Object.freeze({
32
+ Authenticated: "authenticated",
33
+ OtpRequired: "otp_required"
34
+ });
35
+ function requireString(body, key, message) {
36
+ const value = require_url.pickString(body, key);
37
+ if (!value) throw new require_errors.ItdConfigError(message);
38
+ return value;
39
+ }
40
+ const AUTH_CHECK = require_url.passthroughOperation("auth.check");
41
+ const AUTH_SIGN_UP = require_url.defineBuiltInOperation("auth.signUp", (body) => requireString(body, "flowToken", "Сервер не вернул flowToken при регистрации"));
42
+ const AUTH_SIGN_IN = require_url.defineBuiltInOperation("auth.signIn", (body) => {
43
+ const accessToken = require_url.pickString(body, "accessToken");
44
+ return accessToken ? {
45
+ status: SignInStatus.Authenticated,
46
+ accessToken
47
+ } : {
48
+ status: SignInStatus.OtpRequired,
49
+ flowToken: require_url.pickString(body, "flowToken")
50
+ };
51
+ });
52
+ const AUTH_VERIFY_OTP = require_url.defineBuiltInOperation("auth.verifyOtp", (body) => requireString(body, "accessToken", "Сервер не вернул accessToken после подтверждения кода"));
53
+ const AUTH_REFRESH = require_url.defineBuiltInOperation("auth.refresh", (body) => require_url.pickString(body, "accessToken"));
54
+ const AUTH_RESEND_OTP = require_url.voidOperation("auth.resendOtp");
55
+ const AUTH_LOGOUT = require_url.voidOperation("auth.logout");
56
+ const AUTH_FORGOT_PASSWORD = require_url.defineBuiltInOperation("auth.forgotPassword", (body) => requireString(body, "flowToken", "Сервер не вернул flowToken при запросе сброса пароля"));
57
+ const AUTH_RESET_PASSWORD = require_url.voidOperation("auth.resetPassword");
58
+ const AUTH_CHANGE_PASSWORD = require_url.voidOperation("auth.changePassword");
59
+ const AUTH_SESSIONS = require_url.defineBuiltInOperation("auth.sessions", (body) => require_url.pickArray(body, "sessions"));
60
+ const AUTH_REVOKE_SESSION = require_url.voidOperation("auth.revokeSession");
61
+ const AUTH_REVOKE_OTHER_SESSIONS = require_url.voidOperation("auth.revokeOtherSessions");
62
+ //#endregion
10
63
  //#region src/session/jwt.ts
11
64
  /**
12
65
  * Разбирает строку base64url.
@@ -123,7 +176,7 @@ function resolveSessionConfig(options, runtime) {
123
176
  * достижимой из любой сборки, включая анонимную.
124
177
  */
125
178
  function createItdAuth(options, deps) {
126
- return new AuthManager(resolveSessionConfig(options, deps.config), deps.handler, deps.cookies, { onAccountChange: deps.onAccountChange });
179
+ return new AuthManager(resolveSessionConfig(options, deps.config), deps.http, deps.cookies, { onAccountChange: deps.onAccountChange });
127
180
  }
128
181
  /** Пути эндпоинтов авторизации. */
129
182
  const AUTH_PATHS = {
@@ -158,11 +211,6 @@ const AUTH_PATHS = {
158
211
  * ```
159
212
  */
160
213
  const TURNSTILE_SITE_KEY = "0x4AAAAAACHhxczw6fJGwPBg";
161
- function readAccessToken(payload) {
162
- if (typeof payload !== "object" || payload === null) return void 0;
163
- const token = payload.accessToken;
164
- return typeof token === "string" && token.length > 0 ? token : void 0;
165
- }
166
214
  /** Убирает поле, которое сохраняли промежуточные версии с поддержкой `getUserId()`. */
167
215
  function withoutLegacyUserId(session) {
168
216
  const clean = { ...session };
@@ -184,7 +232,7 @@ function nextAuthScope() {
184
232
  */
185
233
  var AuthManager = class {
186
234
  #config;
187
- #send;
235
+ #http;
188
236
  #jar;
189
237
  #emitter;
190
238
  #hooks;
@@ -223,12 +271,12 @@ var AuthManager = class {
223
271
  * воскресить уже очищенную сессию поверх `signOut`.
224
272
  */
225
273
  #authEpoch = 0;
226
- constructor(config, send, jar, hooks = {}) {
274
+ constructor(config, http, jar, hooks = {}) {
227
275
  this.#config = config;
228
- this.#send = send;
276
+ this.#http = http;
229
277
  this.#jar = jar;
230
278
  this.#hooks = hooks;
231
- this.#emitter = new require_websocket.Emitter((error) => require_websocket.reportListenerError(config.logger, "авторизации", error));
279
+ this.#emitter = new require_events.Emitter((error) => require_events.reportListenerError(config.logger, "авторизации", error));
232
280
  }
233
281
  /** Подписка на события авторизации. */
234
282
  get on() {
@@ -238,7 +286,7 @@ var AuthManager = class {
238
286
  get once() {
239
287
  return this.#emitter.once.bind(this.#emitter);
240
288
  }
241
- /** Снимает lifecycle-подписки при терминальном освобождении владельца. @internal */
289
+ /** Снимает служебные подписки при окончательном освобождении владельца. @internal */
242
290
  dispose() {
243
291
  this.#invalidateInFlight();
244
292
  this.#emitter.removeAllListeners();
@@ -294,7 +342,7 @@ var AuthManager = class {
294
342
  this.#externalIdentity = current;
295
343
  return token;
296
344
  }
297
- /** Меняет fallback и завершает realtime, только если фактически сменился аккаунт. */
345
+ /** Обновляет резервный идентификатор и закрывает события при смене аккаунта. */
298
346
  #transitionAuth(accessToken, rotateFallback = true) {
299
347
  const knownPrevious = this.#session !== void 0;
300
348
  const previous = this.#identityForToken(this.#session?.accessToken);
@@ -367,7 +415,7 @@ var AuthManager = class {
367
415
  }
368
416
  async #resolveDeviceId() {
369
417
  const session = await this.#loadSession();
370
- const deviceId = this.#config.deviceId ?? session?.deviceId ?? require_url.createDeviceId();
418
+ const deviceId = this.#config.deviceId ?? session?.deviceId ?? require_redact.createDeviceId();
371
419
  this.#deviceId = deviceId;
372
420
  if (session?.deviceId !== deviceId) await this.#saveSession({
373
421
  ...session ?? {},
@@ -522,7 +570,7 @@ var AuthManager = class {
522
570
  const refreshToken = this.#session?.refreshToken;
523
571
  if (!refreshToken) return;
524
572
  if (this.#jar.has("refresh_token")) return;
525
- this.#jar.set(this.#config.baseUrl, require_cookies.REFRESH_COOKIE, refreshToken, require_cookies.REFRESH_COOKIE_PATH);
573
+ this.#jar.set(this.#config.baseUrl, require_redact.REFRESH_COOKIE, refreshToken, require_redact.REFRESH_COOKIE_PATH);
526
574
  }
527
575
  #sessionFromConfig(auth) {
528
576
  if (!auth) return null;
@@ -566,16 +614,14 @@ var AuthManager = class {
566
614
  if (!this.#hasRefreshSession()) return this.#reloginOrNull();
567
615
  const epoch = this.#authEpoch;
568
616
  try {
569
- const accessToken = readAccessToken(await this.#send({
570
- operationId: "auth.refresh",
571
- method: require_url.operationMethod("auth.refresh"),
617
+ const accessToken = await this.#http.execute(AUTH_REFRESH, {
572
618
  path: AUTH_PATHS.refresh,
573
619
  skipAuth: true,
574
620
  skipAuthRefresh: true
575
- }));
621
+ });
576
622
  if (!accessToken) return this.#reloginOrNull();
577
623
  if (this.#authEpoch !== epoch) return this.#session?.accessToken ?? null;
578
- const rotated = this.#jar.getValue(require_cookies.REFRESH_COOKIE, this.#config.baseUrl + require_cookies.REFRESH_COOKIE_PATH);
624
+ const rotated = this.#jar.getValue(require_redact.REFRESH_COOKIE, this.#config.baseUrl + require_redact.REFRESH_COOKIE_PATH);
579
625
  this.#transitionAuth(accessToken, false);
580
626
  await this.#saveSession({
581
627
  ...this.#session ?? {},
@@ -639,9 +685,7 @@ var AuthManager = class {
639
685
  }
640
686
  async #performSignIn(credentials) {
641
687
  const turnstileToken = await this.#resolveTurnstileToken(credentials);
642
- const accessToken = readAccessToken(await this.#send({
643
- operationId: "auth.signIn",
644
- method: require_url.operationMethod("auth.signIn"),
688
+ const result = await this.#http.execute(AUTH_SIGN_IN, {
645
689
  path: AUTH_PATHS.signIn,
646
690
  body: {
647
691
  email: credentials.email,
@@ -650,8 +694,9 @@ var AuthManager = class {
650
694
  },
651
695
  skipAuth: true,
652
696
  skipAuthRefresh: true
653
- }));
654
- if (!accessToken) throw new require_errors.ItdConfigError("Вход по email и паролю требует подтверждения кодом из письма. Автоматический вход невозможен: воспользуйтесь itd.auth.signInWithOtp() и передайте полученный accessToken в конфигурацию клиента.");
697
+ });
698
+ if (result.status !== SignInStatus.Authenticated) throw new require_errors.ItdConfigError("Вход по email и паролю требует подтверждения кодом из письма. Автоматический вход невозможен: воспользуйтесь itd.auth.signInWithOtp() и передайте полученный accessToken в конфигурацию клиента.");
699
+ const accessToken = result.accessToken;
655
700
  this.#invalidateInFlight();
656
701
  this.#transitionAuth(accessToken);
657
702
  await this.#saveSession({
@@ -665,11 +710,12 @@ var AuthManager = class {
665
710
  };
666
711
  //#endregion
667
712
  //#region src/resources/auth.ts
668
- /** Чем закончился вход: сразу токеном или запросом кода подтверждения. */
669
- const SignInStatus = Object.freeze({
670
- Authenticated: "authenticated",
671
- OtpRequired: "otp_required"
672
- });
713
+ /**
714
+ * Результат входа.
715
+ *
716
+ * Сервер может как сразу выдать токен, так и потребовать код подтверждения — размеченное
717
+ * объединение делает оба случая явными.
718
+ */
673
719
  /**
674
720
  * Авторизация, сессии и пароли.
675
721
  *
@@ -687,7 +733,7 @@ var AuthResource = class extends require_render.BaseResource {
687
733
  * Без авторизации возвращает `authenticated: false` и `user: null`.
688
734
  */
689
735
  check(options = {}) {
690
- return this.http.operation("auth.check", {
736
+ return this.http.execute(AUTH_CHECK, {
691
737
  path: "/api/profile",
692
738
  ...options
693
739
  });
@@ -697,17 +743,14 @@ var AuthResource = class extends require_render.BaseResource {
697
743
  *
698
744
  * @returns `flowToken`, который нужно передать в {@link verifyOtp}
699
745
  */
700
- async signUp(credentials, options = {}) {
701
- const body = await this.http.operation("auth.signUp", {
746
+ signUp(credentials, options = {}) {
747
+ return this.http.execute(AUTH_SIGN_UP, {
702
748
  path: AUTH_PATHS.signUp,
703
749
  body: credentials,
704
750
  skipAuth: true,
705
751
  skipAuthRefresh: true,
706
752
  ...options
707
753
  });
708
- const flowToken = require_url.pickString(body, "flowToken");
709
- if (!flowToken) throw new require_errors.ItdConfigError("Сервер не вернул flowToken при регистрации");
710
- return flowToken;
711
754
  }
712
755
  /**
713
756
  * Выполняет вход.
@@ -720,25 +763,15 @@ var AuthResource = class extends require_render.BaseResource {
720
763
  * @param credentials email, пароль и обязательный токен капчи — см. {@link CaptchaCredentials}
721
764
  */
722
765
  async signIn(credentials, options = {}) {
723
- const body = await this.http.operation("auth.signIn", {
766
+ const result = await this.http.execute(AUTH_SIGN_IN, {
724
767
  path: AUTH_PATHS.signIn,
725
768
  body: credentials,
726
769
  skipAuth: true,
727
770
  skipAuthRefresh: true,
728
771
  ...options
729
772
  });
730
- const accessToken = require_url.pickString(body, "accessToken");
731
- if (accessToken) {
732
- await this.#auth.setAccessToken(accessToken);
733
- return {
734
- status: SignInStatus.Authenticated,
735
- accessToken
736
- };
737
- }
738
- return {
739
- status: SignInStatus.OtpRequired,
740
- flowToken: require_url.pickString(body, "flowToken")
741
- };
773
+ if (result.status === SignInStatus.Authenticated) await this.#auth.setAccessToken(result.accessToken);
774
+ return result;
742
775
  }
743
776
  /**
744
777
  * Подтверждает вход кодом из письма.
@@ -746,21 +779,19 @@ var AuthResource = class extends require_render.BaseResource {
746
779
  * Полученный токен сохраняется в клиенте автоматически.
747
780
  */
748
781
  async verifyOtp(input, options = {}) {
749
- const body = await this.http.operation("auth.verifyOtp", {
782
+ const accessToken = await this.http.execute(AUTH_VERIFY_OTP, {
750
783
  path: AUTH_PATHS.verifyOtp,
751
784
  body: input,
752
785
  skipAuth: true,
753
786
  skipAuthRefresh: true,
754
787
  ...options
755
788
  });
756
- const accessToken = require_url.pickString(body, "accessToken");
757
- if (!accessToken) throw new require_errors.ItdConfigError("Сервер не вернул accessToken после подтверждения кода");
758
789
  await this.#auth.setAccessToken(accessToken);
759
790
  return accessToken;
760
791
  }
761
792
  /** Отправляет код подтверждения повторно. */
762
793
  resendOtp(input, options = {}) {
763
- return this.http.operation("auth.resendOtp", {
794
+ return this.voidOperation(AUTH_RESEND_OTP, {
764
795
  path: AUTH_PATHS.resendOtp,
765
796
  body: input,
766
797
  skipAuth: true,
@@ -829,7 +860,7 @@ var AuthResource = class extends require_render.BaseResource {
829
860
  }
830
861
  /** Завершает текущую сессию на сервере и очищает локальную. */
831
862
  async logout(options = {}) {
832
- await this.http.operation("auth.logout", {
863
+ await this.voidOperation(AUTH_LOGOUT, {
833
864
  path: AUTH_PATHS.logout,
834
865
  skipAuthRefresh: true,
835
866
  ...options
@@ -857,17 +888,14 @@ var AuthResource = class extends require_render.BaseResource {
857
888
  *
858
889
  * @returns `flowToken`, который нужно передать в {@link resetPassword}
859
890
  */
860
- async forgotPassword(input, options = {}) {
861
- const body = await this.http.operation("auth.forgotPassword", {
891
+ forgotPassword(input, options = {}) {
892
+ return this.http.execute(AUTH_FORGOT_PASSWORD, {
862
893
  path: AUTH_PATHS.forgotPassword,
863
894
  body: input,
864
895
  skipAuth: true,
865
896
  skipAuthRefresh: true,
866
897
  ...options
867
898
  });
868
- const flowToken = require_url.pickString(body, "flowToken");
869
- if (!flowToken) throw new require_errors.ItdConfigError("Сервер не вернул flowToken при запросе сброса пароля");
870
- return flowToken;
871
899
  }
872
900
  /**
873
901
  * Устанавливает новый пароль по коду из письма.
@@ -876,7 +904,7 @@ var AuthResource = class extends require_render.BaseResource {
876
904
  * при нехватке любого отвечает `422`.
877
905
  */
878
906
  resetPassword(input, options = {}) {
879
- return this.http.operation("auth.resetPassword", {
907
+ return this.voidOperation(AUTH_RESET_PASSWORD, {
880
908
  path: AUTH_PATHS.resetPassword,
881
909
  body: input,
882
910
  skipAuth: true,
@@ -924,7 +952,7 @@ var AuthResource = class extends require_render.BaseResource {
924
952
  * ```
925
953
  */
926
954
  changePassword(input, options = {}) {
927
- return this.http.operation("auth.changePassword", {
955
+ return this.voidOperation(AUTH_CHANGE_PASSWORD, {
928
956
  path: AUTH_PATHS.changePassword,
929
957
  body: {
930
958
  currentPassword: input.currentPassword,
@@ -934,23 +962,22 @@ var AuthResource = class extends require_render.BaseResource {
934
962
  });
935
963
  }
936
964
  /** Загружает список активных сессий. У текущей поле `isCurrent` равно `true`. */
937
- async sessions(options = {}) {
938
- const body = await this.http.operation("auth.sessions", {
965
+ sessions(options = {}) {
966
+ return this.http.execute(AUTH_SESSIONS, {
939
967
  path: AUTH_PATHS.sessions,
940
968
  ...options
941
969
  });
942
- return require_url.pickArray(body, "sessions");
943
970
  }
944
971
  /** Завершает указанную сессию. */
945
972
  revokeSession(sessionId, options = {}) {
946
- return this.http.operation("auth.revokeSession", {
973
+ return this.voidOperation(AUTH_REVOKE_SESSION, {
947
974
  path: `${AUTH_PATHS.sessions}/${encodeURIComponent(sessionId)}`,
948
975
  ...options
949
976
  });
950
977
  }
951
978
  /** Завершает все сессии, кроме текущей. */
952
979
  revokeOtherSessions(options = {}) {
953
- return this.http.operation("auth.revokeOtherSessions", {
980
+ return this.voidOperation(AUTH_REVOKE_OTHER_SESSIONS, {
954
981
  path: AUTH_PATHS.sessions,
955
982
  ...options
956
983
  });
@@ -1014,8 +1041,6 @@ function createManagedClient(options, internals) {
1014
1041
  var ItdClient = class ItdClient {
1015
1042
  #runtime;
1016
1043
  #features;
1017
- /** Порождённые потоки уведомлений — чтобы `close()` мог закрыть их разом. */
1018
- #streams = /* @__PURE__ */ new Set();
1019
1044
  /** Общий результат терминальной очистки для идемпотентных повторных вызовов. */
1020
1045
  #disposePromise;
1021
1046
  /** Ресурсы конвейера запросов; создаются при первом обращении. */
@@ -1075,34 +1100,76 @@ var ItdClient = class ItdClient {
1075
1100
  get telemetry() {
1076
1101
  return this.#resources.telemetry;
1077
1102
  }
1103
+ /** Каталог, доставка и заказы магазина ИТД. */
1104
+ get shop() {
1105
+ return this.#resources.shop;
1106
+ }
1078
1107
  constructor(options = {}) {
1108
+ const notificationEventsOptions = require_events.resolveNotificationEventsOptions(options.events?.notifications);
1079
1109
  const internals = CLIENT_INTERNALS.get(options) ?? {};
1080
1110
  const catalog = new require_render.ExtensibleOperationCatalog(require_url.ITD_CATALOG);
1111
+ let featureHost;
1081
1112
  this.#runtime = require_url.createClientRuntime(options, {
1082
1113
  catalog,
1083
1114
  queues: internals.queues,
1084
1115
  assertActive: (action) => assertClientActive(this, action),
1085
1116
  auth: (deps) => createItdAuth(options, {
1086
1117
  ...deps,
1087
- onAccountChange: () => this.#disconnectStreams()
1118
+ onAccountChange: () => featureHost?.stop()
1088
1119
  })
1089
1120
  });
1090
- this.#features = new require_render.FeatureRegistry({
1091
- http: this.#runtime.http,
1092
- services: this.#runtime.services,
1093
- serviceOverrides: this.#runtime.config.services,
1121
+ this.#features = featureHost = require_render.createFeatureHost(this.#runtime, {
1094
1122
  catalog,
1095
- baseUrl: this.#runtime.config.baseUrl,
1096
- clock: this.#runtime.config.clock,
1097
- logger: this.#runtime.config.logger,
1098
- assertActive: (action) => assertClientActive(this, action),
1099
- registerBucket: (name, definition) => this.#runtime.registerRateLimitBucket(name, definition)
1123
+ assertActive: (action) => assertClientActive(this, action)
1100
1124
  });
1101
1125
  const status = this.#features.install(require_render.createStatusFeature());
1102
1126
  this.#resources = require_render.createResources({
1103
1127
  http: this.#runtime.http,
1104
- fetch: this.#runtime.config.fetch,
1105
- status
1128
+ files: this.#features.files,
1129
+ status,
1130
+ createNotifications: (http) => createNotificationsApi(http, (notifications) => {
1131
+ let events;
1132
+ let lifecycleGeneration = 0;
1133
+ let lifecycleActive = false;
1134
+ let unregister;
1135
+ const releaseAfterDrain = (generation) => {
1136
+ events.drain().then(() => {
1137
+ if (lifecycleActive || generation !== lifecycleGeneration) return;
1138
+ unregister?.();
1139
+ unregister = void 0;
1140
+ });
1141
+ };
1142
+ events = new require_events.NotificationEvents({
1143
+ connection: this.#runtime.connection(),
1144
+ request: ({ operationId, path, query, signal }) => this.#runtime.http.execute(require_events.EVENT_OPERATIONS[operationId], {
1145
+ path,
1146
+ query,
1147
+ signal
1148
+ }),
1149
+ getAuthIdentity: () => this.#runtime.auth.getCurrentAuthIdentity(),
1150
+ getAuthScope: () => this.#runtime.auth.getAuthScope(),
1151
+ fetchUnreadCount: (signal) => notifications.count({ signal }),
1152
+ onConnect: () => {
1153
+ lifecycleGeneration += 1;
1154
+ unregister ??= this.#features.manage({
1155
+ kind: `notifications:${events.transport}`,
1156
+ stop: () => {
1157
+ if (lifecycleActive) events.disconnect();
1158
+ },
1159
+ drain: () => events.drain()
1160
+ });
1161
+ lifecycleActive = true;
1162
+ },
1163
+ onClose: () => {
1164
+ lifecycleActive = false;
1165
+ releaseAfterDrain(++lifecycleGeneration);
1166
+ },
1167
+ logger: this.#runtime.config.logger,
1168
+ clock: this.#runtime.config.clock
1169
+ }, notificationEventsOptions);
1170
+ require_events.setNotificationEventsConnectGuard(events, () => assertClientActive(this, "подключить канал событий уведомлений"));
1171
+ return events;
1172
+ })
1106
1173
  });
1107
1174
  CLIENT_PLUGIN_REGISTRIES.set(this, this.#runtime.plugins);
1108
1175
  }
@@ -1146,19 +1213,19 @@ var ItdClient = class ItdClient {
1146
1213
  return this.#runtime.rateLimitState();
1147
1214
  }
1148
1215
  /**
1149
- * Устанавливает предметный модуль поверх общей сессии и request pipeline клиента.
1216
+ * Устанавливает предметный модуль с общей сессией и обработкой запросов клиента.
1150
1217
  *
1151
- * Сервисы, операции и бакеты feature регистрируются до синхронного `setup()`. Возвращаемое
1152
- * значение — типизированный API модуля; повторное имя feature отклоняется.
1218
+ * Сервисы, операции и бакеты регистрируются до синхронного `setup()`. Возвращает
1219
+ * типизированный API модуля.
1153
1220
  */
1154
1221
  install(feature) {
1155
1222
  return this.#features.install(feature);
1156
1223
  }
1157
1224
  /**
1158
- * Устанавливает feature и публикует его API как readonly-свойство этого же клиента.
1225
+ * Устанавливает модуль и добавляет его API в свойство клиента только для чтения.
1159
1226
  *
1160
1227
  * Возвращаемое пересечение сохраняет тип уже подключённых свойств, поэтому вызовы можно
1161
- * объединять в цепочку: `new ItdClient().withFeature('chats', chatsFeature)`.
1228
+ * объединять в цепочку: `new ItdClient().withFeature('pixelBattle', pixelBattleFeature)`.
1162
1229
  */
1163
1230
  withFeature(key, feature) {
1164
1231
  assertClientActive(this, "установить feature");
@@ -1174,20 +1241,18 @@ var ItdClient = class ItdClient {
1174
1241
  });
1175
1242
  return this;
1176
1243
  }
1177
- /** Имена установленных feature в порядке установки. */
1244
+ /** Имена установленных модулей в порядке установки. */
1178
1245
  featureNames() {
1179
1246
  return this.#features.names();
1180
1247
  }
1181
- /** Установлен ли feature с таким именем. */
1248
+ /** Установлен ли модуль с таким именем. */
1182
1249
  hasFeature(name) {
1183
1250
  return this.#features.has(name);
1184
1251
  }
1185
1252
  /**
1186
1253
  * Подключает плагин.
1187
1254
  *
1188
- * Плагин может независимо регистрировать transformer логической операции и interceptor
1189
- * транспортной попытки. Оба контракта охватывают все методы клиента. Подключать плагин
1190
- * можно в любой момент, но обычно это делают сразу после создания клиента.
1255
+ * Плагин может регистрировать обёртки операций и перехватчики сетевых попыток.
1191
1256
  *
1192
1257
  * @throws {ItdConfigError} если плагин задан неверно или уже подключён
1193
1258
  * @throws {ItdStateError} если клиент уже освобождён через {@link dispose}
@@ -1290,85 +1355,27 @@ var ItdClient = class ItdClient {
1290
1355
  return this.#runtime.auth.on(event, listener);
1291
1356
  }
1292
1357
  /**
1293
- * Создаёт поток уведомлений в реальном времени.
1294
- *
1295
- * Каждый вызов даёт новый независимый поток; обычно он нужен один на приложение.
1296
- * Соединение поднимается методом `connect()` и держится само. Замена авторизации на токен
1297
- * другого пользователя завершает все потоки клиента; смена только сессии их не затрагивает.
1298
- *
1299
- * @example
1300
- * ```ts
1301
- * import { NotificationType } from 'itd-api';
1302
- *
1303
- * const stream = itd.realtime();
1304
- *
1305
- * stream.onNotification(NotificationType.PostComment, async ({ update }) => {
1306
- * await handleComment(update.data.notification);
1307
- * });
1308
- * stream.on('unreadCount', (count) => setBadge(count));
1309
- *
1310
- * await stream.connect();
1311
- * ```
1312
- *
1313
- * @throws {ItdStateError} если клиент уже освобождён через {@link dispose}
1314
- */
1315
- realtime(options = {}) {
1316
- assertClientActive(this, "создать realtime-поток");
1317
- let stream;
1318
- stream = new require_websocket.ItdRealtime({
1319
- baseUrl: this.#runtime.config.baseUrl,
1320
- fetch: this.#runtime.config.fetch,
1321
- request: ({ operationId, path, query, signal }) => this.#runtime.http.operation(operationId, {
1322
- path,
1323
- query,
1324
- signal
1325
- }),
1326
- baseHeaders: (url) => this.#runtime.platformHeaders(url),
1327
- getAuthIdentity: () => this.#runtime.auth.getCurrentAuthIdentity(),
1328
- getAuthScope: () => this.#runtime.auth.getAuthScope(),
1329
- getToken: () => this.#runtime.auth.token(),
1330
- refresh: () => this.#runtime.auth.onUnauthorized(),
1331
- fetchUnreadCount: () => this.notifications.count(),
1332
- onConnect: () => this.#streams.add(stream),
1333
- onClose: () => this.#streams.delete(stream),
1334
- logger: this.#runtime.config.logger,
1335
- clock: this.#runtime.config.clock
1336
- }, options);
1337
- require_websocket.setRealtimeConnectGuard(stream, () => assertClientActive(this, "подключить realtime-поток"));
1338
- this.#streams.add(stream);
1339
- return stream;
1340
- }
1341
- /**
1342
1358
  * Освобождает ресурсы клиента: закрывает все потоки уведомлений, отправляет открытые
1343
1359
  * накопители {@link telemetry}, затем останавливает очередь запросов.
1344
1360
  *
1345
- * Метод дожидается активных обработчиков потока, но не дольше `shutdownTimeout`. После
1346
- * вызова клиентом можно пользоваться снова; ранее созданный поток можно запустить
1347
- * повторным `connect()`.
1361
+ * Метод дожидается завершения активных обработчиков и освобождения ресурсов остановленных
1362
+ * событийных соединений, но не дольше `shutdownTimeout`. После вызова клиентом можно
1363
+ * пользоваться снова; ранее созданный поток можно запустить повторным `connect()`.
1348
1364
  *
1349
1365
  * Общая очередь, полученная от {@link ItdAccounts}, не останавливается: её гасит сам
1350
1366
  * контейнер, когда закрывает все аккаунты разом.
1351
1367
  *
1352
1368
  * Терминальное освобождение — это {@link dispose}.
1353
1369
  *
1354
- * @throws {ItdStateError} если обработчики потока не завершились за отведённый срок
1370
+ * @throws {ItdStateError} если остановка событийного соединения не завершилась за отведённый срок
1355
1371
  */
1356
1372
  async close() {
1357
1373
  return this.#close(false);
1358
1374
  }
1359
1375
  async #close(disposeCleanup) {
1360
- const streams = this.#disconnectStreams();
1361
1376
  if (disposeCleanup) this.#resources.prepareTelemetryClose();
1362
- const { shutdownTimeout, clock } = this.#runtime.config;
1363
- const deadline = require_url.createDeadline(shutdownTimeout, clock);
1364
- let stuck = [];
1365
1377
  const errors = [];
1366
1378
  try {
1367
- try {
1368
- stuck = (await Promise.all(streams.map(async (stream) => await deadline.wait(stream.drain()) ? void 0 : stream))).filter((stream) => stream !== void 0);
1369
- } catch (error) {
1370
- errors.push(error);
1371
- }
1372
1379
  try {
1373
1380
  await this.#features.close();
1374
1381
  } catch (error) {
@@ -1380,10 +1387,8 @@ var ItdClient = class ItdClient {
1380
1387
  errors.push(error);
1381
1388
  }
1382
1389
  } finally {
1383
- deadline.cancel();
1384
1390
  this.#runtime.close();
1385
1391
  }
1386
- if (stuck.length > 0) errors.push(new require_errors.ItdStateError(`обработчики потоков (${stuck.map((stream) => stream.transport).join(", ")}) не завершились за ${shutdownTimeout} мс; ожидание прекращено`));
1387
1392
  if (errors.length === 1) throw errors[0];
1388
1393
  if (errors.length > 1) throw new AggregateError(errors, "Не удалось закрыть клиент");
1389
1394
  }
@@ -1393,10 +1398,11 @@ var ItdClient = class ItdClient {
1393
1398
  *
1394
1399
  * Терминальное состояние устанавливается сразу при первом вызове. После этого новые
1395
1400
  * запросы, подключение плагинов, регистрация сервисов и создание или повторный запуск
1396
- * realtime-потоков завершаются с {@link ItdStateError}. Повторные вызовы возвращают
1401
+ * событийных каналов завершаются с {@link ItdStateError}. Повторные вызовы возвращают
1397
1402
  * тот же результат очистки.
1398
1403
  *
1399
- * Ожидание обработчиков потока и операций плагинов ограничено `shutdownTimeout`.
1404
+ * Ожидание остановки событийных соединений и операций плагинов ограничено
1405
+ * `shutdownTimeout`.
1400
1406
  *
1401
1407
  * @example
1402
1408
  * ```ts
@@ -1430,13 +1436,6 @@ var ItdClient = class ItdClient {
1430
1436
  }
1431
1437
  if (errors.length > 0) throw new AggregateError(errors, "Не удалось освободить клиент");
1432
1438
  }
1433
- /** Завершает потоки до того, как запросы начнут использовать другой аккаунт. */
1434
- #disconnectStreams() {
1435
- const streams = [...this.#streams];
1436
- for (const stream of streams) stream.disconnect();
1437
- this.#streams.clear();
1438
- return streams;
1439
- }
1440
1439
  /** Позволяет использовать клиент с `await using`. */
1441
1440
  [Symbol.asyncDispose]() {
1442
1441
  return this.dispose();
@@ -1502,6 +1501,25 @@ function createClient(options = {}) {
1502
1501
  function validateAccountName(name) {
1503
1502
  if (typeof name !== "string" || name.trim() === "") throw new require_errors.ItdConfigError("имя аккаунта должно быть непустой строкой");
1504
1503
  }
1504
+ /** Проверяет фабрики до создания первого аккаунта. */
1505
+ function resolveAccountFeatures(features) {
1506
+ if (features === void 0) return [];
1507
+ if (!Array.isArray(features)) throw new require_errors.ItdConfigError("features должен быть массивом фабрик подключаемых модулей");
1508
+ const keys = /* @__PURE__ */ new Set();
1509
+ return features.map((feature, index) => {
1510
+ if (typeof feature !== "object" || feature === null || typeof feature.create !== "function") throw new require_errors.ItdConfigError(`features[${index}] должен предоставлять create()`);
1511
+ if (feature.key !== void 0) {
1512
+ if (typeof feature.key !== "string" || feature.key.trim() === "" || feature.key !== feature.key.trim()) throw new require_errors.ItdConfigError(`features[${index}].key должен быть непустой строкой без пробелов`);
1513
+ if (keys.has(feature.key)) throw new require_errors.ItdConfigError(`Свойство подключаемого модуля «${feature.key}» объявлено повторно`);
1514
+ keys.add(feature.key);
1515
+ }
1516
+ const create = feature.create.bind(feature);
1517
+ return Object.freeze({
1518
+ ...feature.key === void 0 ? {} : { key: feature.key },
1519
+ create
1520
+ });
1521
+ });
1522
+ }
1505
1523
  const DISPOSED_ACCOUNTS = /* @__PURE__ */ new WeakSet();
1506
1524
  function assertAccountsActive(accounts, action) {
1507
1525
  if (!DISPOSED_ACCOUNTS.has(accounts)) return;
@@ -1553,6 +1571,8 @@ var ItdAccounts = class ItdAccounts {
1553
1571
  #eventUnsubscribers = /* @__PURE__ */ new Map();
1554
1572
  /** Плагины для всех: и для уже заведённых аккаунтов, и для будущих. */
1555
1573
  #plugins;
1574
+ /** Фабрики модулей для новых и восстанавливаемых аккаунтов. */
1575
+ #features;
1556
1576
  /** Имена плагинов, чья асинхронная очистка ещё не завершилась. */
1557
1577
  #removingPlugins = /* @__PURE__ */ new Set();
1558
1578
  /** Общая очередь. `undefined`, когда у каждого аккаунта своя. */
@@ -1563,17 +1583,18 @@ var ItdAccounts = class ItdAccounts {
1563
1583
  /** Общий результат терминальной очистки для идемпотентных повторных вызовов. */
1564
1584
  #disposePromise;
1565
1585
  constructor(options = {}) {
1566
- const { storage, plugins, rateLimitScope, ...base } = options;
1586
+ const { storage, plugins, features, rateLimitScope, ...base } = options;
1567
1587
  if (rateLimitScope !== void 0 && rateLimitScope !== "account" && rateLimitScope !== "shared") throw new require_errors.ItdConfigError("rateLimitScope должен быть 'account' или 'shared'");
1568
1588
  this.#base = base;
1569
1589
  this.#storage = storage ?? new require_multi_storage.MemoryMultiTokenStorage();
1570
1590
  this.#plugins = require_url.orderPluginDefinitions(plugins ?? []);
1591
+ this.#features = resolveAccountFeatures(features);
1571
1592
  this.#rateLimitScope = rateLimitScope ?? "shared";
1572
1593
  const rateLimit = this.#rateLimitScope === "shared" ? require_url.resolveRateLimit(base.rateLimit, require_url.ITD_CATALOG) : void 0;
1573
1594
  this.#queues = rateLimit ? new require_url.RequestQueuePool(rateLimit, base.clock ?? require_url.systemClock) : void 0;
1574
1595
  const logger = typeof base.logger === "object" ? base.logger : void 0;
1575
1596
  this.#logger = logger;
1576
- this.#emitter = new require_websocket.Emitter((error) => require_websocket.reportListenerError(logger, "аккаунтов", error));
1597
+ this.#emitter = new require_events.Emitter((error) => require_events.reportListenerError(logger, "аккаунтов", error));
1577
1598
  }
1578
1599
  /** Общее хранилище сессий — то же, что передано опцией `storage`. */
1579
1600
  get storage() {
@@ -1594,7 +1615,7 @@ var ItdAccounts = class ItdAccounts {
1594
1615
  /**
1595
1616
  * Заводит аккаунт.
1596
1617
  *
1597
- * Возвращается обычный `ItdClient` — со всеми ресурсами, плагинами и `realtime()`.
1618
+ * Возвращается обычный `ItdClient` — со всеми ресурсами, плагинами и каналом событий.
1598
1619
  * Хранилище ему подставляется само: срез общего по имени аккаунта.
1599
1620
  *
1600
1621
  * Опция `auth` не обязательна: когда сессия этого аккаунта уже лежит в хранилище,
@@ -1620,10 +1641,15 @@ var ItdAccounts = class ItdAccounts {
1620
1641
  try {
1621
1642
  client = createManagedClient(this.#mergeOptions(options, storageControl.storage), this.#queues ? { queues: this.#queues } : {});
1622
1643
  for (const plugin of this.#plugins) client.use(plugin);
1644
+ for (const feature of this.#features) {
1645
+ const manifest = feature.create();
1646
+ if (feature.key === void 0) client.install(manifest);
1647
+ else client.withFeature(feature.key, manifest);
1648
+ }
1623
1649
  } catch (error) {
1624
1650
  storageControl.revoke();
1625
1651
  if (client) client.dispose().catch((cleanupError) => {
1626
- this.#reportPluginCleanup("неудачного добавления аккаунта", cleanupError);
1652
+ this.#reportCleanup("неудачного добавления аккаунта", cleanupError);
1627
1653
  });
1628
1654
  throw error;
1629
1655
  }
@@ -1747,7 +1773,7 @@ var ItdAccounts = class ItdAccounts {
1747
1773
  }
1748
1774
  } catch (error) {
1749
1775
  for (const client of installed.reverse()) client.unuse(plugin.name).catch((cleanupError) => {
1750
- this.#reportPluginCleanup(`отката плагина «${plugin.name}»`, cleanupError);
1776
+ this.#reportCleanup(`отката плагина «${plugin.name}»`, cleanupError);
1751
1777
  });
1752
1778
  throw error;
1753
1779
  }
@@ -1863,6 +1889,7 @@ var ItdAccounts = class ItdAccounts {
1863
1889
  Promise.resolve().then(() => this.#queues?.clear())
1864
1890
  ]);
1865
1891
  this.#plugins.splice(0);
1892
+ this.#features.splice(0);
1866
1893
  this.#removingPlugins.clear();
1867
1894
  const errors = results.filter((result) => result.status === "rejected").map((result) => result.reason);
1868
1895
  if (errors.length > 0) throw new AggregateError(errors, "Не удалось освободить аккаунты");
@@ -1872,11 +1899,7 @@ var ItdAccounts = class ItdAccounts {
1872
1899
  return this.dispose();
1873
1900
  }
1874
1901
  static {
1875
- if (typeof Symbol.asyncDispose !== "symbol") {
1876
- const prototype = ItdAccounts.prototype;
1877
- prototype[Symbol.for("Symbol.asyncDispose")] = prototype.undefined;
1878
- delete prototype.undefined;
1879
- }
1902
+ require_url.installAsyncDisposeFallback(ItdAccounts);
1880
1903
  }
1881
1904
  /**
1882
1905
  * Собирает опции клиента: общие, поверх них — аккаунтные, и обязательно свой срез
@@ -1901,9 +1924,9 @@ var ItdAccounts = class ItdAccounts {
1901
1924
  storage
1902
1925
  };
1903
1926
  }
1904
- /** Не теряет ошибку фонового teardown, который синхронный API не может await-нуть. */
1905
- #reportPluginCleanup(scope, error) {
1906
- const message = `Не удалось завершить teardown после ${scope}`;
1927
+ /** Не теряет ошибку фонового освобождения ресурсов, которого синхронный API не ждёт. */
1928
+ #reportCleanup(scope, error) {
1929
+ const message = `Не удалось освободить ресурсы после ${scope}`;
1907
1930
  if (this.#logger) this.#logger.error(message, error);
1908
1931
  else console.error(`[itd-api] ${message}`, error);
1909
1932
  }
@@ -1943,6 +1966,10 @@ exports.BUCKET_LIMITS = require_url.BUCKET_LIMITS;
1943
1966
  exports.CommentSort = require_url.CommentSort;
1944
1967
  exports.DEFAULT_BASE_URL = require_url.DEFAULT_BASE_URL;
1945
1968
  exports.DEFAULT_RATE_LIMIT_BUCKET = require_url.DEFAULT_RATE_LIMIT_BUCKET;
1969
+ exports.EventChannel = require_events.EventChannel;
1970
+ exports.EventChannelStatus = require_url.EventChannelStatus;
1971
+ exports.EventComposer = require_events.EventComposer;
1972
+ exports.EventRouter = require_events.EventRouter;
1946
1973
  exports.FeedTab = require_url.FeedTab;
1947
1974
  exports.FileTransferMode = require_options.FileTransferMode;
1948
1975
  exports.IMAGE_MIME_TYPES = require_render.IMAGE_MIME_TYPES;
@@ -1966,58 +1993,65 @@ exports.ItdNetworkError = require_errors.ItdNetworkError;
1966
1993
  exports.ItdNotFoundError = require_errors.ItdNotFoundError;
1967
1994
  exports.ItdPhoneVerificationError = require_errors.ItdPhoneVerificationError;
1968
1995
  exports.ItdRateLimitError = require_errors.ItdRateLimitError;
1969
- exports.ItdRealtime = require_websocket.ItdRealtime;
1970
1996
  exports.ItdServerError = require_errors.ItdServerError;
1971
1997
  exports.ItdStateError = require_errors.ItdStateError;
1972
1998
  exports.ItdTimeoutError = require_errors.ItdTimeoutError;
1973
1999
  exports.ItdValidationError = require_errors.ItdValidationError;
1974
2000
  exports.LIBRARY_VERSION = require_url.LIBRARY_VERSION;
1975
2001
  exports.LikesVisibility = require_url.LikesVisibility;
1976
- exports.MemoryKeyValueStore = require_storage.MemoryKeyValueStore;
2002
+ exports.MemoryKeyValueStore = require_key_value_store.MemoryKeyValueStore;
1977
2003
  exports.MemoryMultiTokenStorage = require_multi_storage.MemoryMultiTokenStorage;
2004
+ exports.MemoryShopOrderAccessStorage = require_render.MemoryShopOrderAccessStorage;
1978
2005
  exports.MemoryTokenStorage = require_storage.MemoryTokenStorage;
2006
+ exports.NotificationEvents = require_events.NotificationEvents;
2007
+ exports.NotificationEventsClient = require_events.NotificationEventsClient;
2008
+ exports.NotificationEventsTransport = require_events.NotificationEventsTransport;
1979
2009
  exports.NotificationType = require_url.NotificationType;
2010
+ exports.NotificationUpdateOrigin = require_events.NotificationUpdateOrigin;
2011
+ exports.NotificationUpdateType = require_events.NotificationUpdateType;
1980
2012
  exports.OPERATIONS = require_url.OPERATIONS;
1981
2013
  exports.PaginationMode = require_render.PaginationMode;
1982
2014
  exports.Paginator = require_render.Paginator;
1983
2015
  exports.RateLimitPacing = require_url.RateLimitPacing;
1984
- exports.RealtimeComposer = require_websocket.RealtimeComposer;
1985
- exports.RealtimeRouter = require_websocket.RealtimeRouter;
1986
- exports.RealtimeStatus = require_url.RealtimeStatus;
1987
- exports.RealtimeTransportKind = require_websocket.RealtimeTransportKind;
1988
- exports.RealtimeUpdateOrigin = require_websocket.RealtimeUpdateOrigin;
1989
- exports.RealtimeUpdateType = require_websocket.RealtimeUpdateType;
1990
2016
  exports.ReportReason = require_url.ReportReason;
1991
2017
  exports.ReportTargetType = require_url.ReportTargetType;
1992
2018
  exports.RetrySafety = require_url.RetrySafety;
1993
- exports.RuntimeMode = require_url.RuntimeMode;
2019
+ exports.RuntimeMode = require_redact.RuntimeMode;
1994
2020
  exports.STATUS_SERVICE = require_url.STATUS_SERVICE;
1995
2021
  exports.ServiceState = require_url.ServiceState;
2022
+ exports.ShopConsentKind = require_render.ShopConsentKind;
2023
+ exports.ShopOrderStatus = require_render.ShopOrderStatus;
2024
+ exports.ShopProductCategory = require_render.ShopProductCategory;
2025
+ exports.ShopProductStatus = require_render.ShopProductStatus;
1996
2026
  exports.SignInStatus = SignInStatus;
1997
2027
  exports.SpanRenderFormat = require_render.SpanRenderFormat;
1998
2028
  exports.SpanType = require_url.SpanType;
1999
2029
  exports.TURNSTILE_SITE_KEY = TURNSTILE_SITE_KEY;
2000
- exports.UnauthorizedStreamError = require_websocket.UnauthorizedStreamError;
2030
+ exports.UnauthorizedStreamError = require_events.UnauthorizedStreamError;
2001
2031
  exports.VIDEO_MIME_TYPES = require_render.VIDEO_MIME_TYPES;
2002
2032
  exports.ViewReason = require_url.ViewReason;
2003
2033
  exports.ViewSource = require_url.ViewSource;
2004
2034
  exports.WallAccess = require_url.WallAccess;
2005
- exports.WebSocketTransport = require_websocket.WebSocketTransport;
2035
+ exports.WebSocketTransport = require_events.WebSocketTransport;
2006
2036
  exports.autoSpans = require_render.autoSpans;
2007
2037
  exports.canonicalNotificationType = require_url.canonicalNotificationType;
2008
2038
  exports.comment = require_render.comment;
2009
2039
  exports.createAccounts = createAccounts;
2010
2040
  exports.createClient = createClient;
2011
- exports.createKeyValueStore = require_storage.createKeyValueStore;
2041
+ exports.createKeyValueStore = require_key_value_store.createKeyValueStore;
2042
+ exports.createMemoryShopOrderAccessStorage = require_render.createMemoryShopOrderAccessStorage;
2012
2043
  exports.createMultiTokenStorage = require_multi_storage.createMultiTokenStorage;
2013
- exports.createRecordKeyValueStore = require_storage.createRecordKeyValueStore;
2044
+ exports.createNotificationEventsClient = require_events.createNotificationEventsClient;
2045
+ exports.createRecordKeyValueStore = require_key_value_store.createRecordKeyValueStore;
2046
+ exports.createShopFeature = require_render.createShopFeature;
2047
+ exports.createShopOrderAccessStorage = require_render.createShopOrderAccessStorage;
2014
2048
  exports.createTokenStorage = require_storage.createTokenStorage;
2015
2049
  exports.formatNotificationText = require_url.formatNotificationText;
2016
2050
  exports.fromStream = require_render.fromStream;
2017
2051
  exports.fromUrl = require_render.fromUrl;
2018
2052
  exports.isBuilder = require_render.isBuilder;
2019
2053
  exports.isBuiltInOperationId = require_url.isBuiltInOperationId;
2020
- exports.isEnumerableKeyValueStore = require_storage.isEnumerableKeyValueStore;
2054
+ exports.isEnumerableKeyValueStore = require_key_value_store.isEnumerableKeyValueStore;
2021
2055
  exports.isItdApiError = require_errors.isItdApiError;
2022
2056
  exports.isItdAuthError = require_errors.isItdAuthError;
2023
2057
  exports.isItdConflictError = require_errors.isItdConflictError;
@@ -2045,13 +2079,13 @@ exports.post = require_render.post;
2045
2079
  exports.renderSpans = require_render.renderSpans;
2046
2080
  exports.report = require_render.report;
2047
2081
  exports.resolveNotificationUrl = require_url.resolveNotificationUrl;
2048
- exports.runRealtimeMiddleware = require_websocket.runRealtimeMiddleware;
2082
+ exports.runEventMiddleware = require_events.runEventMiddleware;
2049
2083
  exports.scopedTokenStorage = require_multi_storage.scopedTokenStorage;
2050
2084
  exports.statusDays = require_render.statusDays;
2051
2085
  exports.systemClock = require_url.systemClock;
2052
2086
  exports.toDate = require_render.toDate;
2053
2087
  exports.utcStampToIso = require_render.utcStampToIso;
2054
- exports.withCodec = require_storage.withCodec;
2055
- exports.withNamespace = require_storage.withNamespace;
2088
+ exports.withCodec = require_key_value_store.withCodec;
2089
+ exports.withNamespace = require_key_value_store.withNamespace;
2056
2090
 
2057
2091
  //# sourceMappingURL=index.cjs.map