itd-api 0.7.1 → 0.7.2

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 (44) hide show
  1. package/README.md +2 -2
  2. package/dist/index.cjs +81 -8
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +22 -4
  5. package/dist/index.d.ts +22 -4
  6. package/dist/index.js +81 -8
  7. package/dist/index.js.map +1 -1
  8. package/dist/realtime/index.cjs +3 -3
  9. package/dist/realtime/index.d.cts +2 -2
  10. package/dist/realtime/index.d.ts +2 -2
  11. package/dist/realtime/index.js +3 -3
  12. package/dist/rest/index.cjs +70 -6
  13. package/dist/rest/index.cjs.map +1 -1
  14. package/dist/rest/index.d.cts +11 -3
  15. package/dist/rest/index.d.ts +11 -3
  16. package/dist/rest/index.js +70 -6
  17. package/dist/rest/index.js.map +1 -1
  18. package/dist/shared/{auth-provider-CTJkKfgy.cjs → auth-provider-CG8oCQ9F.cjs} +2 -2
  19. package/dist/shared/{auth-provider-CTJkKfgy.cjs.map → auth-provider-CG8oCQ9F.cjs.map} +1 -1
  20. package/dist/shared/{auth-provider-BfogACAb.js → auth-provider-mYqxsSVa.js} +2 -2
  21. package/dist/shared/{auth-provider-BfogACAb.js.map → auth-provider-mYqxsSVa.js.map} +1 -1
  22. package/dist/shared/{render-vtLixIiU.js → render-C6HRPs10.js} +353 -56
  23. package/dist/shared/render-C6HRPs10.js.map +1 -0
  24. package/dist/shared/{render-DZrxhC5_.d.ts → render-CgwKdOzu.d.ts} +101 -40
  25. package/dist/shared/{render-DMp_3Nzk.d.cts → render-DO0F5YSm.d.cts} +101 -40
  26. package/dist/shared/{render-DyeHJNBw.cjs → render-mcuELiYi.cjs} +369 -54
  27. package/dist/shared/render-mcuELiYi.cjs.map +1 -0
  28. package/dist/shared/{url-yjl2c8Ie.cjs → url-BaMCQpYH.cjs} +76 -24
  29. package/dist/shared/url-BaMCQpYH.cjs.map +1 -0
  30. package/dist/shared/{url-B6-bXHKt.d.ts → url-DTfZ2toq.d.cts} +6 -8
  31. package/dist/shared/{url-B6-bXHKt.d.cts → url-DTfZ2toq.d.ts} +6 -8
  32. package/dist/shared/{url-CYXgxqGx.js → url-IU0xN9wX.js} +65 -25
  33. package/dist/shared/url-IU0xN9wX.js.map +1 -0
  34. package/dist/shared/{websocket-CbzB1Leq.js → websocket-BLR8eVJV.js} +2 -2
  35. package/dist/shared/{websocket-CbzB1Leq.js.map → websocket-BLR8eVJV.js.map} +1 -1
  36. package/dist/shared/{websocket-sYlynrr0.cjs → websocket-C_eI4H2o.cjs} +2 -2
  37. package/dist/shared/{websocket-sYlynrr0.cjs.map → websocket-C_eI4H2o.cjs.map} +1 -1
  38. package/dist/shared/{websocket-D1p32SB2.d.cts → websocket-DF7XIMiX.d.cts} +2 -2
  39. package/dist/shared/{websocket-BMtihD56.d.ts → websocket-DYKBr8HF.d.ts} +2 -2
  40. package/package.json +1 -1
  41. package/dist/shared/render-DyeHJNBw.cjs.map +0 -1
  42. package/dist/shared/render-vtLixIiU.js.map +0 -1
  43. package/dist/shared/url-CYXgxqGx.js.map +0 -1
  44. package/dist/shared/url-yjl2c8Ie.cjs.map +0 -1
@@ -1,7 +1,270 @@
1
- const require_url = require("./url-yjl2c8Ie.cjs");
1
+ const require_url = require("./url-BaMCQpYH.cjs");
2
2
  const require_errors = require("./errors-DfU8M5eS.cjs");
3
3
  const require_cookies = require("./cookies-DZwFq6kr.cjs");
4
4
  const require_options = require("./options-Dg5N3r1V.cjs");
5
+ //#region src/core/feature-catalog.ts
6
+ /**
7
+ * Изменяемый слой над каталогом конкретного API.
8
+ *
9
+ * Базовый каталог остаётся замороженным и общим для всех клиентов, а регистрации feature
10
+ * принадлежат одному facade. Поэтому установка модуля в одном клиенте не меняет остальные.
11
+ *
12
+ * @internal
13
+ */
14
+ var ExtensibleOperationCatalog = class {
15
+ #base;
16
+ #operations = /* @__PURE__ */ new Map();
17
+ #operationOwners = /* @__PURE__ */ new Map();
18
+ #bucketOwners = /* @__PURE__ */ new Map();
19
+ #bucketLimits;
20
+ #bucketOverrides;
21
+ constructor(base) {
22
+ this.#base = base;
23
+ this.#bucketLimits = { ...base.bucketLimits };
24
+ this.#bucketOverrides = { ...base.bucketOverrides };
25
+ }
26
+ get bucketLimits() {
27
+ return this.#bucketLimits;
28
+ }
29
+ get bucketOverrides() {
30
+ return this.#bucketOverrides;
31
+ }
32
+ get defaultBucket() {
33
+ return this.#base.defaultBucket;
34
+ }
35
+ retrySafetyOf(id) {
36
+ return this.#operations.get(id)?.retrySafety ?? this.#base.retrySafetyOf(id);
37
+ }
38
+ methodOf(id) {
39
+ return this.#operations.get(id)?.method ?? this.#base.methodOf(id);
40
+ }
41
+ bucketOf(id) {
42
+ return this.#operations.get(id)?.bucket ?? this.#base.bucketOf(id);
43
+ }
44
+ isKnownBucket(name) {
45
+ return this.#bucketOwners.has(name) || this.#base.isKnownBucket(name);
46
+ }
47
+ /** Регистрирует принадлежащий feature бакет и возвращает откат регистрации. */
48
+ registerBucket(owner, name, definition) {
49
+ if (this.#base.isKnownBucket(name) || this.#bucketOwners.has(name)) throw new require_errors.ItdConfigError(`feature «${owner}»: бакет «${name}» уже зарегистрирован`);
50
+ this.#bucketOwners.set(name, owner);
51
+ if (definition.limit !== void 0) this.#bucketLimits[name] = definition.limit;
52
+ if (definition.concurrency !== void 0) this.#bucketOverrides[name] = Object.freeze({ concurrency: definition.concurrency });
53
+ return () => {
54
+ if (this.#bucketOwners.get(name) !== owner) return;
55
+ this.#bucketOwners.delete(name);
56
+ delete this.#bucketLimits[name];
57
+ delete this.#bucketOverrides[name];
58
+ };
59
+ }
60
+ /** Регистрирует операцию и возвращает откат регистрации. */
61
+ registerOperation(owner, id, definition) {
62
+ const ownerPrefix = `${owner}.`;
63
+ if (!id.startsWith(ownerPrefix) || id.length === ownerPrefix.length) throw new require_errors.ItdConfigError(`feature «${owner}»: операция «${id}» должна находиться в пространстве имён «${owner}»`);
64
+ const occupiedBy = this.#operationOwners.get(id);
65
+ if (occupiedBy !== void 0) throw new require_errors.ItdConfigError(`feature «${owner}»: операция «${id}» уже зарегистрирована feature «${occupiedBy}»`);
66
+ if (this.#base.methodOf(id) !== void 0) throw new require_errors.ItdConfigError(`feature «${owner}»: операция «${id}» уже существует в базовом каталоге`);
67
+ this.#operationOwners.set(id, owner);
68
+ this.#operations.set(id, Object.freeze({ ...definition }));
69
+ return () => {
70
+ if (this.#operationOwners.get(id) !== owner) return;
71
+ this.#operationOwners.delete(id);
72
+ this.#operations.delete(id);
73
+ };
74
+ }
75
+ };
76
+ //#endregion
77
+ //#region src/core/features.ts
78
+ function requireName(value, kind) {
79
+ if (typeof value !== "string" || value.trim() === "") throw new require_errors.ItdConfigError(`${kind} должен иметь непустое имя`);
80
+ return value.trim();
81
+ }
82
+ function requireOperationName(value, featureName) {
83
+ const name = requireName(value, `Операция feature «${featureName}»`);
84
+ if (name.includes(".")) throw new require_errors.ItdConfigError(`feature «${featureName}»: локальное имя операции «${name}» не должно содержать точку`);
85
+ return name;
86
+ }
87
+ function validateBucket(owner, localName, bucket) {
88
+ if (typeof bucket !== "object" || bucket === null || Array.isArray(bucket)) throw new require_errors.ItdConfigError(`feature «${owner}»: бакет «${localName}» должен быть объектом`);
89
+ if (bucket.limit !== void 0 && (!Number.isFinite(bucket.limit) || bucket.limit <= 0)) throw new require_errors.ItdConfigError(`feature «${owner}»: limit бакета «${localName}» должен быть положительным числом`);
90
+ if (bucket.concurrency !== void 0 && (!Number.isInteger(bucket.concurrency) || bucket.concurrency < 1)) throw new require_errors.ItdConfigError(`feature «${owner}»: concurrency бакета «${localName}» должен быть целым числом от 1`);
91
+ }
92
+ /** Реестр feature одного facade. @internal */
93
+ var FeatureRegistry = class {
94
+ #deps;
95
+ #features = /* @__PURE__ */ new Map();
96
+ #serviceOwners = /* @__PURE__ */ new Map();
97
+ #disposed = false;
98
+ constructor(deps) {
99
+ this.#deps = deps;
100
+ }
101
+ install(feature) {
102
+ this.#deps.assertActive("установить feature");
103
+ if (this.#disposed) throw new require_errors.ItdStateError("Реестр feature уже освобождён");
104
+ if (typeof feature !== "object" || feature === null) throw new require_errors.ItdConfigError("feature должен быть объектом");
105
+ const name = requireName(feature.name, "Feature");
106
+ if (this.#features.has(name)) throw new require_errors.ItdConfigError(`feature «${name}» уже установлен`);
107
+ if (typeof feature.setup !== "function") throw new require_errors.ItdConfigError(`feature «${name}» должен предоставлять setup()`);
108
+ if (typeof feature.operations !== "object" || feature.operations === null || Array.isArray(feature.operations)) throw new require_errors.ItdConfigError(`feature «${name}» должен объявлять operations`);
109
+ if (feature.services !== void 0 && !Array.isArray(feature.services)) throw new require_errors.ItdConfigError(`feature «${name}»: services должен быть массивом`);
110
+ if (feature.buckets !== void 0 && (typeof feature.buckets !== "object" || feature.buckets === null || Array.isArray(feature.buckets))) throw new require_errors.ItdConfigError(`feature «${name}»: buckets должен быть объектом`);
111
+ const rollback = [];
112
+ const services = /* @__PURE__ */ new Set();
113
+ const bucketNames = /* @__PURE__ */ new Map();
114
+ const operations = /* @__PURE__ */ new Map();
115
+ const controller = new AbortController();
116
+ let committed = false;
117
+ try {
118
+ for (const service of feature.services ?? []) {
119
+ const serviceName = requireName(service?.name, `Сервис feature «${name}»`);
120
+ const owner = this.#serviceOwners.get(serviceName);
121
+ if (owner !== void 0) throw new require_errors.ItdConfigError(`feature «${name}»: сервис «${serviceName}» уже принадлежит feature «${owner}»`);
122
+ if (services.has(serviceName)) throw new require_errors.ItdConfigError(`feature «${name}»: сервис «${serviceName}» объявлен повторно`);
123
+ if (!this.#deps.services.has(serviceName)) {
124
+ this.#deps.services.define(service);
125
+ rollback.push(() => void this.#deps.services.delete(serviceName));
126
+ } else {
127
+ const override = this.#deps.serviceOverrides.find((candidate) => candidate.name.trim() === serviceName);
128
+ if (override) {
129
+ const previous = this.#deps.services.replace(require_url.mergeService(service, override));
130
+ rollback.push(() => void this.#deps.services.replace(previous));
131
+ }
132
+ }
133
+ this.#serviceOwners.set(serviceName, name);
134
+ rollback.push(() => {
135
+ if (this.#serviceOwners.get(serviceName) === name) this.#serviceOwners.delete(serviceName);
136
+ });
137
+ services.add(serviceName);
138
+ }
139
+ for (const [rawLocalName, bucket] of Object.entries(feature.buckets ?? {})) {
140
+ const localName = requireName(rawLocalName, `Бакет feature «${name}»`);
141
+ validateBucket(name, localName, bucket);
142
+ const globalName = `feature:${name}/${localName}`;
143
+ const unregisterCatalog = this.#deps.catalog.registerBucket(name, globalName, bucket);
144
+ rollback.push(unregisterCatalog);
145
+ const unregisterQueue = this.#deps.registerBucket(globalName, bucket);
146
+ if (unregisterQueue) rollback.push(unregisterQueue);
147
+ bucketNames.set(localName, globalName);
148
+ }
149
+ for (const [rawLocalName, definition] of Object.entries(feature.operations)) {
150
+ const localName = requireOperationName(rawLocalName, name);
151
+ if (typeof definition !== "object" || definition === null) throw new require_errors.ItdConfigError(`feature «${name}»: операция «${localName}» должна быть объектом`);
152
+ if (![
153
+ "GET",
154
+ "POST",
155
+ "PUT",
156
+ "PATCH",
157
+ "DELETE"
158
+ ].includes(definition.method)) throw new require_errors.ItdConfigError(`feature «${name}»: операция «${localName}» содержит неизвестный HTTP-метод`);
159
+ if (!Object.values(require_url.RetrySafety).includes(definition.retrySafety)) throw new require_errors.ItdConfigError(`feature «${name}»: операция «${localName}» содержит неизвестную retrySafety`);
160
+ if (definition.service !== void 0 && typeof definition.service !== "string") throw new require_errors.ItdConfigError(`feature «${name}»: service операции «${localName}» должен быть строкой`);
161
+ if (definition.bucket !== void 0 && typeof definition.bucket !== "string") throw new require_errors.ItdConfigError(`feature «${name}»: bucket операции «${localName}» должен быть строкой`);
162
+ if (definition.service !== void 0 && !services.has(definition.service)) throw new require_errors.ItdConfigError(`feature «${name}»: операция «${localName}» ссылается на необъявленный сервис «${definition.service}»`);
163
+ const bucket = definition.bucket === void 0 ? this.#deps.catalog.defaultBucket : bucketNames.get(definition.bucket);
164
+ if (bucket === void 0) throw new require_errors.ItdConfigError(`feature «${name}»: операция «${localName}» ссылается на необъявленный бакет «${definition.bucket}»`);
165
+ const operationId = `${name}.${localName}`;
166
+ const unregister = this.#deps.catalog.registerOperation(name, operationId, {
167
+ method: definition.method,
168
+ retrySafety: definition.retrySafety,
169
+ bucket
170
+ });
171
+ rollback.push(unregister);
172
+ operations.set(localName, {
173
+ operationId,
174
+ method: definition.method,
175
+ service: definition.service
176
+ });
177
+ }
178
+ const context = Object.freeze({
179
+ featureName: name,
180
+ baseUrl: this.#deps.baseUrl,
181
+ signal: controller.signal,
182
+ clock: this.#deps.clock,
183
+ logger: this.#deps.logger,
184
+ request: (operation, options) => {
185
+ try {
186
+ this.#deps.assertActive(`выполнить операцию feature «${name}»`);
187
+ if (!committed || controller.signal.aborted) throw new require_errors.ItdStateError(`feature «${name}» не активен`);
188
+ const resolved = operations.get(operation);
189
+ if (!resolved) throw new require_errors.ItdConfigError(`feature «${name}» не объявляет операцию «${operation}»`);
190
+ const scoped = { ...options };
191
+ delete scoped.operationId;
192
+ delete scoped.method;
193
+ delete scoped.service;
194
+ delete scoped.baseUrl;
195
+ delete scoped.retrySafety;
196
+ delete scoped.rateLimitBucket;
197
+ return this.#deps.http.request({
198
+ ...scoped,
199
+ operationId: resolved.operationId,
200
+ method: resolved.method,
201
+ ...resolved.service === void 0 ? {} : { service: resolved.service }
202
+ });
203
+ } catch (error) {
204
+ return Promise.reject(error);
205
+ }
206
+ },
207
+ serviceBaseUrl: (serviceName) => {
208
+ if (!services.has(serviceName)) throw new require_errors.ItdConfigError(`feature «${name}» не объявляет сервис «${serviceName}»`);
209
+ return this.#deps.services.resolveBaseUrl(serviceName);
210
+ }
211
+ });
212
+ const installation = feature.setup(context);
213
+ if (typeof installation !== "object" || installation === null || !("api" in installation)) throw new require_errors.ItdConfigError(`setup() feature «${name}» должен вернуть объект с полем api`);
214
+ if (installation.close !== void 0 && typeof installation.close !== "function") throw new require_errors.ItdConfigError(`feature «${name}»: close должен быть функцией`);
215
+ if (installation.dispose !== void 0 && typeof installation.dispose !== "function") throw new require_errors.ItdConfigError(`feature «${name}»: dispose должен быть функцией`);
216
+ this.#features.set(name, {
217
+ name,
218
+ controller,
219
+ close: installation.close,
220
+ dispose: installation.dispose,
221
+ cleanup: [...rollback]
222
+ });
223
+ committed = true;
224
+ return installation.api;
225
+ } catch (error) {
226
+ controller.abort(new require_errors.ItdAbortError(`Установка feature «${name}» отменена`));
227
+ for (const undo of rollback.reverse()) undo();
228
+ throw error;
229
+ }
230
+ }
231
+ names() {
232
+ return [...this.#features.keys()];
233
+ }
234
+ has(name) {
235
+ return this.#features.has(name);
236
+ }
237
+ async close() {
238
+ const errors = [];
239
+ for (const feature of [...this.#features.values()].reverse()) try {
240
+ await feature.close?.();
241
+ } catch (error) {
242
+ errors.push(error);
243
+ }
244
+ if (errors.length > 0) throw new AggregateError(errors, "Не удалось закрыть feature");
245
+ }
246
+ async dispose() {
247
+ if (this.#disposed) return;
248
+ this.#disposed = true;
249
+ const errors = [];
250
+ for (const feature of [...this.#features.values()].reverse()) {
251
+ feature.controller.abort(new require_errors.ItdAbortError(`Feature «${feature.name}» освобождён`));
252
+ try {
253
+ await feature.dispose?.();
254
+ } catch (error) {
255
+ errors.push(error);
256
+ }
257
+ for (const cleanup of [...feature.cleanup].reverse()) try {
258
+ cleanup();
259
+ } catch (error) {
260
+ errors.push(error);
261
+ }
262
+ }
263
+ this.#features.clear();
264
+ if (errors.length > 0) throw new AggregateError(errors, "Не удалось освободить feature");
265
+ }
266
+ };
267
+ //#endregion
5
268
  //#region src/resources/pagination.ts
6
269
  /** Схема пагинации эндпоинта. */
7
270
  const PaginationMode = Object.freeze({
@@ -311,6 +574,84 @@ function withPageState(query, state) {
311
574
  };
312
575
  }
313
576
  //#endregion
577
+ //#region src/domain/time.ts
578
+ const NAIVE_STAMP = /^(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2}(?:\.\d+)?)$/;
579
+ /**
580
+ * Приводит отметку времени без часового пояса к ISO-8601, считая её временем UTC.
581
+ *
582
+ * Строку другого вида возвращает нетронутой.
583
+ *
584
+ * @example
585
+ * ```ts
586
+ * utcStampToIso('2026-07-23 23:14:25'); // '2026-07-23T23:14:25Z'
587
+ * utcStampToIso('2026-07-23T23:14:25Z'); // без изменений
588
+ * ```
589
+ */
590
+ function utcStampToIso(value) {
591
+ const match = typeof value === "string" ? NAIVE_STAMP.exec(value) : null;
592
+ if (!match) return value;
593
+ const iso = `${match[1]}T${match[2]}Z`;
594
+ return Number.isFinite(Date.parse(iso)) ? iso : value;
595
+ }
596
+ /**
597
+ * Разбирает дату API в объект `Date`.
598
+ *
599
+ * @returns `null`, если строки нет или она не разбирается
600
+ *
601
+ * @example
602
+ * ```ts
603
+ * const created = toDate(post.createdAt);
604
+ * ```
605
+ */
606
+ function toDate(value) {
607
+ if (!value) return null;
608
+ const date = new Date(value);
609
+ return Number.isFinite(date.getTime()) ? date : null;
610
+ }
611
+ //#endregion
612
+ //#region src/resources/status.ts
613
+ /** Приводит `last_checked` каждого сервиса к ISO. Остальное остаётся как прислал сервер. */
614
+ function normalizeStatus(body) {
615
+ if (!require_url.isRecord(body) || !Array.isArray(body.services)) return body;
616
+ return {
617
+ ...body,
618
+ services: body.services.map((service) => typeof service?.last_checked === "string" ? {
619
+ ...service,
620
+ last_checked: utcStampToIso(service.last_checked)
621
+ } : service)
622
+ };
623
+ }
624
+ /** API встроенного status feature. @internal */
625
+ var StatusResource = class {
626
+ #context;
627
+ constructor(context) {
628
+ this.#context = context;
629
+ }
630
+ async get(options = {}) {
631
+ return normalizeStatus(await this.#context.request("get", {
632
+ path: "/api/status",
633
+ ...options
634
+ }));
635
+ }
636
+ };
637
+ /** Встроенный модуль страницы состояния платформы. @internal */
638
+ function createStatusFeature() {
639
+ return {
640
+ name: "status",
641
+ services: [{
642
+ name: require_url.STATUS_SERVICE,
643
+ baseUrl: require_url.DEFAULT_STATUS_BASE_URL,
644
+ auth: false
645
+ }],
646
+ operations: { get: {
647
+ method: "GET",
648
+ retrySafety: require_url.RetrySafety.Safe,
649
+ service: require_url.STATUS_SERVICE
650
+ } },
651
+ setup: (context) => ({ api: new StatusResource(context) })
652
+ };
653
+ }
654
+ //#endregion
314
655
  //#region src/builders/base.ts
315
656
  /** Метка билдера. Через `Symbol.for` — чтобы распознавание переживало смешивание ESM и CJS. */
316
657
  const BUILDER = Symbol.for("itd.builder");
@@ -1240,59 +1581,19 @@ var NotificationsResource = class extends BaseResource {
1240
1581
  }
1241
1582
  };
1242
1583
  //#endregion
1243
- //#region src/domain/time.ts
1244
- const NAIVE_STAMP = /^(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2}(?:\.\d+)?)$/;
1245
- /**
1246
- * Приводит отметку времени без часового пояса к ISO-8601, считая её временем UTC.
1247
- *
1248
- * Строку другого вида возвращает нетронутой.
1249
- *
1250
- * @example
1251
- * ```ts
1252
- * utcStampToIso('2026-07-23 23:14:25'); // '2026-07-23T23:14:25Z'
1253
- * utcStampToIso('2026-07-23T23:14:25Z'); // без изменений
1254
- * ```
1255
- */
1256
- function utcStampToIso(value) {
1257
- const match = typeof value === "string" ? NAIVE_STAMP.exec(value) : null;
1258
- if (!match) return value;
1259
- const iso = `${match[1]}T${match[2]}Z`;
1260
- return Number.isFinite(Date.parse(iso)) ? iso : value;
1261
- }
1262
- /**
1263
- * Разбирает дату API в объект `Date`.
1264
- *
1265
- * @returns `null`, если строки нет или она не разбирается
1266
- *
1267
- * @example
1268
- * ```ts
1269
- * const created = toDate(post.createdAt);
1270
- * ```
1271
- */
1272
- function toDate(value) {
1273
- if (!value) return null;
1274
- const date = new Date(value);
1275
- return Number.isFinite(date.getTime()) ? date : null;
1276
- }
1277
- //#endregion
1278
1584
  //#region src/resources/platform.ts
1279
- /** Приводит `last_checked` каждого сервиса к ISO. Остальное остаётся как прислал сервер. */
1280
- function normalizeStatus(body) {
1281
- if (!require_url.isRecord(body) || !Array.isArray(body.services)) return body;
1282
- return {
1283
- ...body,
1284
- services: body.services.map((service) => typeof service?.last_checked === "string" ? {
1285
- ...service,
1286
- last_checked: utcStampToIso(service.last_checked)
1287
- } : service)
1288
- };
1289
- }
1290
1585
  /**
1291
1586
  * Сведения о платформе: версии приложений, изменения, анонсы, баннер события.
1292
1587
  *
1293
1588
  * Доступна как `itd.platform`.
1294
1589
  */
1295
1590
  var PlatformResource = class extends BaseResource {
1591
+ #status;
1592
+ /** @internal */
1593
+ constructor(http, status) {
1594
+ super(http);
1595
+ this.#status = status;
1596
+ }
1296
1597
  /**
1297
1598
  * Загружает минимальные и актуальные версии клиентских приложений.
1298
1599
  *
@@ -1351,11 +1652,7 @@ var PlatformResource = class extends BaseResource {
1351
1652
  * ```
1352
1653
  */
1353
1654
  async status(options = {}) {
1354
- return normalizeStatus(await this.http.operation("platform.status", {
1355
- service: require_url.STATUS_SERVICE,
1356
- path: "/api/status",
1357
- ...options
1358
- }));
1655
+ return this.#status.get(options);
1359
1656
  }
1360
1657
  };
1361
1658
  //#endregion
@@ -3684,7 +3981,7 @@ function createResources(deps) {
3684
3981
  return subscription;
3685
3982
  },
3686
3983
  get platform() {
3687
- platform ??= new PlatformResource(deps.http);
3984
+ platform ??= new PlatformResource(deps.http, deps.status);
3688
3985
  return platform;
3689
3986
  },
3690
3987
  get telemetry() {
@@ -4005,6 +4302,18 @@ Object.defineProperty(exports, "BaseResource", {
4005
4302
  return BaseResource;
4006
4303
  }
4007
4304
  });
4305
+ Object.defineProperty(exports, "ExtensibleOperationCatalog", {
4306
+ enumerable: true,
4307
+ get: function() {
4308
+ return ExtensibleOperationCatalog;
4309
+ }
4310
+ });
4311
+ Object.defineProperty(exports, "FeatureRegistry", {
4312
+ enumerable: true,
4313
+ get: function() {
4314
+ return FeatureRegistry;
4315
+ }
4316
+ });
4008
4317
  Object.defineProperty(exports, "IMAGE_MIME_TYPES", {
4009
4318
  enumerable: true,
4010
4319
  get: function() {
@@ -4053,6 +4362,12 @@ Object.defineProperty(exports, "createResources", {
4053
4362
  return createResources;
4054
4363
  }
4055
4364
  });
4365
+ Object.defineProperty(exports, "createStatusFeature", {
4366
+ enumerable: true,
4367
+ get: function() {
4368
+ return createStatusFeature;
4369
+ }
4370
+ });
4056
4371
  Object.defineProperty(exports, "fromStream", {
4057
4372
  enumerable: true,
4058
4373
  get: function() {
@@ -4144,4 +4459,4 @@ Object.defineProperty(exports, "utcStampToIso", {
4144
4459
  }
4145
4460
  });
4146
4461
 
4147
- //# sourceMappingURL=render-DyeHJNBw.cjs.map
4462
+ //# sourceMappingURL=render-mcuELiYi.cjs.map