itd-api 0.9.0 → 0.9.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.
- package/README.md +4 -4
- package/dist/events/index.cjs +3 -4
- package/dist/events/index.d.cts +3 -3
- package/dist/events/index.d.ts +3 -3
- package/dist/events/index.js +4 -4
- package/dist/index.cjs +198 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -65
- package/dist/index.d.ts +11 -65
- package/dist/index.js +199 -39
- package/dist/index.js.map +1 -1
- package/dist/node/index.cjs +3 -3
- package/dist/node/index.js +3 -3
- package/dist/rest/index.cjs +4 -5
- package/dist/rest/index.d.cts +3 -3
- package/dist/rest/index.d.ts +3 -3
- package/dist/rest/index.js +5 -5
- package/dist/shared/{events-CqtkP65d.d.ts → events-BCn5LRnT.d.cts} +3 -5
- package/dist/shared/{events-C5wnTXPT.js → events-BIBO2Jif.js} +4 -4
- package/dist/shared/{events-C5wnTXPT.js.map → events-BIBO2Jif.js.map} +1 -1
- package/dist/shared/{events-FZfnEez0.cjs → events-BsRm_Fba.cjs} +3 -9
- package/dist/shared/{events-FZfnEez0.cjs.map → events-BsRm_Fba.cjs.map} +1 -1
- package/dist/shared/{events-DGAWlCaI.d.cts → events-t1uGgpkf.d.ts} +3 -5
- package/dist/shared/{multi-storage-SoW05uzO.js → multi-storage-C3Ngtop1.js} +13 -8
- package/dist/shared/multi-storage-C3Ngtop1.js.map +1 -0
- package/dist/shared/{multi-storage-CDKLa956.cjs → multi-storage-s-fPtjoy.cjs} +13 -8
- package/dist/shared/multi-storage-s-fPtjoy.cjs.map +1 -0
- package/dist/shared/{options-DOJYtoti.cjs → options-DjEtbVaf.cjs} +2 -2
- package/dist/shared/{options-DOJYtoti.cjs.map → options-DjEtbVaf.cjs.map} +1 -1
- package/dist/shared/{options-DhgGg7Ms.js → options-i4LrKfqx.js} +2 -2
- package/dist/shared/{options-DhgGg7Ms.js.map → options-i4LrKfqx.js.map} +1 -1
- package/dist/shared/{redact-Ba5iSVYZ.js → redact-DJV0XM3n.js} +40 -15
- package/dist/shared/redact-DJV0XM3n.js.map +1 -0
- package/dist/shared/{redact-BP00URmQ.cjs → redact-lAmck1Z6.cjs} +45 -14
- package/dist/shared/redact-lAmck1Z6.cjs.map +1 -0
- package/dist/shared/{render-hiWFh2s4.js → render--ZXmYEf-.js} +131 -100
- package/dist/shared/render--ZXmYEf-.js.map +1 -0
- package/dist/shared/{render-B4qis7Sb.d.ts → render-BdnBV-aT.d.ts} +112 -16
- package/dist/shared/{render-DDwy2Ame.d.cts → render-DA83gS0f.d.cts} +112 -16
- package/dist/shared/{render-Dqi8Owqk.cjs → render-DqVzx68r.cjs} +129 -104
- package/dist/shared/render-DqVzx68r.cjs.map +1 -0
- package/dist/shared/{storage-QNVxzpDB.cjs → storage-CZJZoaz9.cjs} +4 -2
- package/dist/shared/storage-CZJZoaz9.cjs.map +1 -0
- package/dist/shared/{storage-CfHKzVHf.js → storage-DiDe0PZM.js} +4 -2
- package/dist/shared/storage-DiDe0PZM.js.map +1 -0
- package/dist/shared/{url-XBsMdAcv.d.ts → url-Dbj6V6fk.d.cts} +21 -5
- package/dist/shared/{url-XBsMdAcv.d.cts → url-Dbj6V6fk.d.ts} +21 -5
- package/dist/shared/{url-Bsb3xE5U.cjs → url-Doc0XXW_.cjs} +274 -86
- package/dist/shared/url-Doc0XXW_.cjs.map +1 -0
- package/dist/shared/{url-DP33mp3s.js → url-i2f-X1hX.js} +274 -86
- package/dist/shared/url-i2f-X1hX.js.map +1 -0
- package/dist/web/index.cjs +1 -1
- package/dist/web/index.js +1 -1
- package/package.json +4 -4
- package/dist/shared/multi-storage-CDKLa956.cjs.map +0 -1
- package/dist/shared/multi-storage-SoW05uzO.js.map +0 -1
- package/dist/shared/redact-BP00URmQ.cjs.map +0 -1
- package/dist/shared/redact-Ba5iSVYZ.js.map +0 -1
- package/dist/shared/render-Dqi8Owqk.cjs.map +0 -1
- package/dist/shared/render-hiWFh2s4.js.map +0 -1
- package/dist/shared/storage-CfHKzVHf.js.map +0 -1
- package/dist/shared/storage-QNVxzpDB.cjs.map +0 -1
- package/dist/shared/url-Bsb3xE5U.cjs.map +0 -1
- package/dist/shared/url-DP33mp3s.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
const require_url = require("./url-
|
|
1
|
+
const require_url = require("./url-Doc0XXW_.cjs");
|
|
2
2
|
const require_errors = require("./errors-BmP3TKoW.cjs");
|
|
3
|
-
const require_redact = require("./redact-
|
|
4
|
-
const require_options = require("./options-
|
|
3
|
+
const require_redact = require("./redact-lAmck1Z6.cjs");
|
|
4
|
+
const require_options = require("./options-DjEtbVaf.cjs");
|
|
5
5
|
const require_key_value_store = require("./key-value-store-B5GYVEYZ.cjs");
|
|
6
6
|
//#region src/core/feature-catalog.ts
|
|
7
7
|
/**
|
|
@@ -370,6 +370,22 @@ function createFileResolver(fetchImplementation) {
|
|
|
370
370
|
}
|
|
371
371
|
//#endregion
|
|
372
372
|
//#region src/core/features.ts
|
|
373
|
+
var FeatureInstallationTransaction = class {
|
|
374
|
+
#cleanup = [];
|
|
375
|
+
add(cleanup) {
|
|
376
|
+
this.#cleanup.push(cleanup);
|
|
377
|
+
}
|
|
378
|
+
snapshot() {
|
|
379
|
+
return [...this.#cleanup];
|
|
380
|
+
}
|
|
381
|
+
rollback(reportError) {
|
|
382
|
+
for (let index = this.#cleanup.length - 1; index >= 0; index -= 1) try {
|
|
383
|
+
this.#cleanup[index]?.();
|
|
384
|
+
} catch (error) {
|
|
385
|
+
reportError(error);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
};
|
|
373
389
|
function requireName(value, kind) {
|
|
374
390
|
if (typeof value !== "string" || value.trim() === "") throw new require_errors.ItdConfigError(`${kind} должен иметь непустое имя`);
|
|
375
391
|
return value.trim();
|
|
@@ -385,6 +401,21 @@ function validateBucket(owner, localName, bucket) {
|
|
|
385
401
|
if (bucket.concurrency !== void 0 && (!Number.isInteger(bucket.concurrency) || bucket.concurrency < 1)) throw new require_errors.ItdConfigError(`feature «${owner}»: concurrency бакета «${localName}» должен быть целым числом от 1`);
|
|
386
402
|
if (bucket.rps !== void 0 && (!Number.isFinite(bucket.rps) || bucket.rps <= 0)) throw new require_errors.ItdConfigError(`feature «${owner}»: rps бакета «${localName}» должен быть положительным числом`);
|
|
387
403
|
}
|
|
404
|
+
function validateFeatureDefinition(feature, isInstalled) {
|
|
405
|
+
if (typeof feature !== "object" || feature === null) throw new require_errors.ItdConfigError("feature должен быть объектом");
|
|
406
|
+
const name = requireFeatureName(feature.name);
|
|
407
|
+
if (isInstalled(name)) throw new require_errors.ItdConfigError(`feature «${name}» уже установлен`);
|
|
408
|
+
if (typeof feature.setup !== "function") throw new require_errors.ItdConfigError(`feature «${name}» должен предоставлять setup()`);
|
|
409
|
+
if (typeof feature.operations !== "object" || feature.operations === null || Array.isArray(feature.operations)) throw new require_errors.ItdConfigError(`feature «${name}» должен объявлять operations`);
|
|
410
|
+
if (feature.services !== void 0 && !Array.isArray(feature.services)) throw new require_errors.ItdConfigError(`feature «${name}»: services должен быть массивом`);
|
|
411
|
+
if (feature.buckets !== void 0 && (typeof feature.buckets !== "object" || feature.buckets === null || Array.isArray(feature.buckets))) throw new require_errors.ItdConfigError(`feature «${name}»: buckets должен быть объектом`);
|
|
412
|
+
return name;
|
|
413
|
+
}
|
|
414
|
+
function validateFeatureInstallation(name, installation) {
|
|
415
|
+
if (typeof installation !== "object" || installation === null || !("api" in installation)) throw new require_errors.ItdConfigError(`setup() feature «${name}» должен вернуть объект с полем api`);
|
|
416
|
+
if (installation.close !== void 0 && typeof installation.close !== "function") throw new require_errors.ItdConfigError(`feature «${name}»: close должен быть функцией`);
|
|
417
|
+
if (installation.dispose !== void 0 && typeof installation.dispose !== "function") throw new require_errors.ItdConfigError(`feature «${name}»: dispose должен быть функцией`);
|
|
418
|
+
}
|
|
388
419
|
/** Реестр подключаемых модулей клиента. @internal */
|
|
389
420
|
var FeatureRegistry = class {
|
|
390
421
|
#deps;
|
|
@@ -394,20 +425,89 @@ var FeatureRegistry = class {
|
|
|
394
425
|
constructor(deps) {
|
|
395
426
|
this.#deps = deps;
|
|
396
427
|
}
|
|
397
|
-
|
|
398
|
-
this.#deps.assertActive("установить feature");
|
|
399
|
-
if (this.#disposed) throw new require_errors.ItdStateError("Реестр feature уже освобождён");
|
|
400
|
-
if (typeof feature !== "object" || feature === null) throw new require_errors.ItdConfigError("feature должен быть объектом");
|
|
401
|
-
const name = requireFeatureName(feature.name);
|
|
402
|
-
if (this.#features.has(name)) throw new require_errors.ItdConfigError(`feature «${name}» уже установлен`);
|
|
403
|
-
if (typeof feature.setup !== "function") throw new require_errors.ItdConfigError(`feature «${name}» должен предоставлять setup()`);
|
|
404
|
-
if (typeof feature.operations !== "object" || feature.operations === null || Array.isArray(feature.operations)) throw new require_errors.ItdConfigError(`feature «${name}» должен объявлять operations`);
|
|
405
|
-
if (feature.services !== void 0 && !Array.isArray(feature.services)) throw new require_errors.ItdConfigError(`feature «${name}»: services должен быть массивом`);
|
|
406
|
-
if (feature.buckets !== void 0 && (typeof feature.buckets !== "object" || feature.buckets === null || Array.isArray(feature.buckets))) throw new require_errors.ItdConfigError(`feature «${name}»: buckets должен быть объектом`);
|
|
407
|
-
const rollback = [];
|
|
428
|
+
#registerServices(featureName, definitions, transaction) {
|
|
408
429
|
const services = /* @__PURE__ */ new Set();
|
|
430
|
+
for (const service of definitions) {
|
|
431
|
+
const serviceName = requireName(service?.name, `Сервис feature «${featureName}»`);
|
|
432
|
+
const owner = this.#serviceOwners.get(serviceName);
|
|
433
|
+
if (owner !== void 0) throw new require_errors.ItdConfigError(`feature «${featureName}»: сервис «${serviceName}» уже принадлежит feature «${owner}»`);
|
|
434
|
+
if (services.has(serviceName)) throw new require_errors.ItdConfigError(`feature «${featureName}»: сервис «${serviceName}» объявлен повторно`);
|
|
435
|
+
if (!this.#deps.services.has(serviceName)) {
|
|
436
|
+
this.#deps.services.define(service);
|
|
437
|
+
transaction.add(() => void this.#deps.services.delete(serviceName));
|
|
438
|
+
} else {
|
|
439
|
+
const override = this.#deps.serviceOverrides.find((candidate) => candidate.name.trim() === serviceName);
|
|
440
|
+
if (override) {
|
|
441
|
+
const previous = this.#deps.services.replace(require_url.mergeService(service, override));
|
|
442
|
+
transaction.add(() => void this.#deps.services.replace(previous));
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
this.#serviceOwners.set(serviceName, featureName);
|
|
446
|
+
transaction.add(() => {
|
|
447
|
+
if (this.#serviceOwners.get(serviceName) === featureName) this.#serviceOwners.delete(serviceName);
|
|
448
|
+
});
|
|
449
|
+
services.add(serviceName);
|
|
450
|
+
}
|
|
451
|
+
return services;
|
|
452
|
+
}
|
|
453
|
+
#registerBuckets(featureName, definitions, transaction) {
|
|
409
454
|
const bucketNames = /* @__PURE__ */ new Map();
|
|
455
|
+
for (const [rawLocalName, bucket] of Object.entries(definitions)) {
|
|
456
|
+
const localName = requireName(rawLocalName, `Бакет feature «${featureName}»`);
|
|
457
|
+
validateBucket(featureName, localName, bucket);
|
|
458
|
+
const globalName = `feature:${featureName}/${localName}`;
|
|
459
|
+
transaction.add(this.#deps.catalog.registerBucket(featureName, globalName, bucket));
|
|
460
|
+
const unregisterQueue = this.#deps.registerBucket(globalName, bucket);
|
|
461
|
+
if (unregisterQueue) transaction.add(unregisterQueue);
|
|
462
|
+
bucketNames.set(localName, globalName);
|
|
463
|
+
}
|
|
464
|
+
return bucketNames;
|
|
465
|
+
}
|
|
466
|
+
#registerOperations(featureName, definitions, services, bucketNames, transaction) {
|
|
410
467
|
const operations = /* @__PURE__ */ new Map();
|
|
468
|
+
for (const [rawLocalName, definition] of Object.entries(definitions)) {
|
|
469
|
+
const localName = requireName(rawLocalName, `Операция feature «${featureName}»`);
|
|
470
|
+
if (typeof definition !== "object" || definition === null) throw new require_errors.ItdConfigError(`feature «${featureName}»: операция «${localName}» должна быть объектом`);
|
|
471
|
+
if (![
|
|
472
|
+
"GET",
|
|
473
|
+
"POST",
|
|
474
|
+
"PUT",
|
|
475
|
+
"PATCH",
|
|
476
|
+
"DELETE"
|
|
477
|
+
].includes(definition.method)) throw new require_errors.ItdConfigError(`feature «${featureName}»: операция «${localName}» содержит неизвестный HTTP-метод`);
|
|
478
|
+
if (!Object.values(require_url.RetrySafety).includes(definition.retrySafety)) throw new require_errors.ItdConfigError(`feature «${featureName}»: операция «${localName}» содержит неизвестную retrySafety`);
|
|
479
|
+
if (definition.service !== void 0 && typeof definition.service !== "string") throw new require_errors.ItdConfigError(`feature «${featureName}»: service операции «${localName}» должен быть строкой`);
|
|
480
|
+
if (definition.bucket !== void 0 && typeof definition.bucket !== "string") throw new require_errors.ItdConfigError(`feature «${featureName}»: bucket операции «${localName}» должен быть строкой`);
|
|
481
|
+
if (definition.read !== void 0 && typeof definition.read !== "function") throw new require_errors.ItdConfigError(`feature «${featureName}»: read операции «${localName}» должна быть функцией`);
|
|
482
|
+
if (definition.annotations !== void 0 && (typeof definition.annotations !== "object" || definition.annotations === null || Array.isArray(definition.annotations))) throw new require_errors.ItdConfigError(`feature «${featureName}»: annotations операции «${localName}» должны быть объектом`);
|
|
483
|
+
if (definition.service !== void 0 && !services.has(definition.service)) throw new require_errors.ItdConfigError(`feature «${featureName}»: операция «${localName}» ссылается на необъявленный сервис «${definition.service}»`);
|
|
484
|
+
const bucket = definition.bucket === void 0 ? this.#deps.catalog.defaultBucket : bucketNames.get(definition.bucket);
|
|
485
|
+
if (bucket === void 0) throw new require_errors.ItdConfigError(`feature «${featureName}»: операция «${localName}» ссылается на необъявленный бакет «${definition.bucket}»`);
|
|
486
|
+
const operationId = `${featureName}.${localName}`;
|
|
487
|
+
const contract = require_url.defineOperation(operationId, {
|
|
488
|
+
method: definition.method,
|
|
489
|
+
retrySafety: definition.retrySafety,
|
|
490
|
+
bucket,
|
|
491
|
+
...definition.annotations === void 0 ? {} : { annotations: definition.annotations }
|
|
492
|
+
}, definition.read ?? require_url.identityResult);
|
|
493
|
+
transaction.add(this.#deps.catalog.registerOperation(featureName, operationId, {
|
|
494
|
+
method: contract.method,
|
|
495
|
+
retrySafety: contract.retrySafety,
|
|
496
|
+
bucket,
|
|
497
|
+
...contract.annotations === void 0 ? {} : { annotations: contract.annotations }
|
|
498
|
+
}));
|
|
499
|
+
operations.set(localName, {
|
|
500
|
+
contract,
|
|
501
|
+
service: definition.service
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
return operations;
|
|
505
|
+
}
|
|
506
|
+
install(feature) {
|
|
507
|
+
this.#deps.assertActive("установить feature");
|
|
508
|
+
if (this.#disposed) throw new require_errors.ItdStateError("Реестр feature уже освобождён");
|
|
509
|
+
const name = validateFeatureDefinition(feature, (candidate) => this.#features.has(candidate));
|
|
510
|
+
const transaction = new FeatureInstallationTransaction();
|
|
411
511
|
const controller = new AbortController();
|
|
412
512
|
let committed = false;
|
|
413
513
|
const reportRollbackError = (message, error) => {
|
|
@@ -416,74 +516,9 @@ var FeatureRegistry = class {
|
|
|
416
516
|
} catch {}
|
|
417
517
|
};
|
|
418
518
|
try {
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
if (owner !== void 0) throw new require_errors.ItdConfigError(`feature «${name}»: сервис «${serviceName}» уже принадлежит feature «${owner}»`);
|
|
423
|
-
if (services.has(serviceName)) throw new require_errors.ItdConfigError(`feature «${name}»: сервис «${serviceName}» объявлен повторно`);
|
|
424
|
-
if (!this.#deps.services.has(serviceName)) {
|
|
425
|
-
this.#deps.services.define(service);
|
|
426
|
-
rollback.push(() => void this.#deps.services.delete(serviceName));
|
|
427
|
-
} else {
|
|
428
|
-
const override = this.#deps.serviceOverrides.find((candidate) => candidate.name.trim() === serviceName);
|
|
429
|
-
if (override) {
|
|
430
|
-
const previous = this.#deps.services.replace(require_url.mergeService(service, override));
|
|
431
|
-
rollback.push(() => void this.#deps.services.replace(previous));
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
this.#serviceOwners.set(serviceName, name);
|
|
435
|
-
rollback.push(() => {
|
|
436
|
-
if (this.#serviceOwners.get(serviceName) === name) this.#serviceOwners.delete(serviceName);
|
|
437
|
-
});
|
|
438
|
-
services.add(serviceName);
|
|
439
|
-
}
|
|
440
|
-
for (const [rawLocalName, bucket] of Object.entries(feature.buckets ?? {})) {
|
|
441
|
-
const localName = requireName(rawLocalName, `Бакет feature «${name}»`);
|
|
442
|
-
validateBucket(name, localName, bucket);
|
|
443
|
-
const globalName = `feature:${name}/${localName}`;
|
|
444
|
-
const unregisterCatalog = this.#deps.catalog.registerBucket(name, globalName, bucket);
|
|
445
|
-
rollback.push(unregisterCatalog);
|
|
446
|
-
const unregisterQueue = this.#deps.registerBucket(globalName, bucket);
|
|
447
|
-
if (unregisterQueue) rollback.push(unregisterQueue);
|
|
448
|
-
bucketNames.set(localName, globalName);
|
|
449
|
-
}
|
|
450
|
-
for (const [rawLocalName, definition] of Object.entries(feature.operations)) {
|
|
451
|
-
const localName = requireName(rawLocalName, `Операция feature «${name}»`);
|
|
452
|
-
if (typeof definition !== "object" || definition === null) throw new require_errors.ItdConfigError(`feature «${name}»: операция «${localName}» должна быть объектом`);
|
|
453
|
-
if (![
|
|
454
|
-
"GET",
|
|
455
|
-
"POST",
|
|
456
|
-
"PUT",
|
|
457
|
-
"PATCH",
|
|
458
|
-
"DELETE"
|
|
459
|
-
].includes(definition.method)) throw new require_errors.ItdConfigError(`feature «${name}»: операция «${localName}» содержит неизвестный HTTP-метод`);
|
|
460
|
-
if (!Object.values(require_url.RetrySafety).includes(definition.retrySafety)) throw new require_errors.ItdConfigError(`feature «${name}»: операция «${localName}» содержит неизвестную retrySafety`);
|
|
461
|
-
if (definition.service !== void 0 && typeof definition.service !== "string") throw new require_errors.ItdConfigError(`feature «${name}»: service операции «${localName}» должен быть строкой`);
|
|
462
|
-
if (definition.bucket !== void 0 && typeof definition.bucket !== "string") throw new require_errors.ItdConfigError(`feature «${name}»: bucket операции «${localName}» должен быть строкой`);
|
|
463
|
-
if (definition.read !== void 0 && typeof definition.read !== "function") throw new require_errors.ItdConfigError(`feature «${name}»: read операции «${localName}» должна быть функцией`);
|
|
464
|
-
if (definition.annotations !== void 0 && (typeof definition.annotations !== "object" || definition.annotations === null || Array.isArray(definition.annotations))) throw new require_errors.ItdConfigError(`feature «${name}»: annotations операции «${localName}» должны быть объектом`);
|
|
465
|
-
if (definition.service !== void 0 && !services.has(definition.service)) throw new require_errors.ItdConfigError(`feature «${name}»: операция «${localName}» ссылается на необъявленный сервис «${definition.service}»`);
|
|
466
|
-
const bucket = definition.bucket === void 0 ? this.#deps.catalog.defaultBucket : bucketNames.get(definition.bucket);
|
|
467
|
-
if (bucket === void 0) throw new require_errors.ItdConfigError(`feature «${name}»: операция «${localName}» ссылается на необъявленный бакет «${definition.bucket}»`);
|
|
468
|
-
const operationId = `${name}.${localName}`;
|
|
469
|
-
const contract = require_url.defineOperation(operationId, {
|
|
470
|
-
method: definition.method,
|
|
471
|
-
retrySafety: definition.retrySafety,
|
|
472
|
-
bucket,
|
|
473
|
-
...definition.annotations === void 0 ? {} : { annotations: definition.annotations }
|
|
474
|
-
}, definition.read ?? require_url.identityResult);
|
|
475
|
-
const unregister = this.#deps.catalog.registerOperation(name, operationId, {
|
|
476
|
-
method: contract.method,
|
|
477
|
-
retrySafety: contract.retrySafety,
|
|
478
|
-
bucket,
|
|
479
|
-
...contract.annotations === void 0 ? {} : { annotations: contract.annotations }
|
|
480
|
-
});
|
|
481
|
-
rollback.push(unregister);
|
|
482
|
-
operations.set(localName, {
|
|
483
|
-
contract,
|
|
484
|
-
service: definition.service
|
|
485
|
-
});
|
|
486
|
-
}
|
|
519
|
+
const services = this.#registerServices(name, feature.services ?? [], transaction);
|
|
520
|
+
const bucketNames = this.#registerBuckets(name, feature.buckets ?? {}, transaction);
|
|
521
|
+
const operations = this.#registerOperations(name, feature.operations, services, bucketNames, transaction);
|
|
487
522
|
const context = Object.freeze({
|
|
488
523
|
featureName: name,
|
|
489
524
|
baseUrl: this.#deps.baseUrl,
|
|
@@ -538,7 +573,7 @@ var FeatureRegistry = class {
|
|
|
538
573
|
registered = false;
|
|
539
574
|
unregister();
|
|
540
575
|
};
|
|
541
|
-
if (!committed)
|
|
576
|
+
if (!committed) transaction.add(() => {
|
|
542
577
|
if (!registered) return;
|
|
543
578
|
if (committed) {
|
|
544
579
|
release();
|
|
@@ -563,21 +598,21 @@ var FeatureRegistry = class {
|
|
|
563
598
|
}
|
|
564
599
|
});
|
|
565
600
|
const installation = feature.setup(context);
|
|
566
|
-
|
|
567
|
-
if (installation.close !== void 0 && typeof installation.close !== "function") throw new require_errors.ItdConfigError(`feature «${name}»: close должен быть функцией`);
|
|
568
|
-
if (installation.dispose !== void 0 && typeof installation.dispose !== "function") throw new require_errors.ItdConfigError(`feature «${name}»: dispose должен быть функцией`);
|
|
601
|
+
validateFeatureInstallation(name, installation);
|
|
569
602
|
this.#features.set(name, {
|
|
570
603
|
name,
|
|
571
604
|
controller,
|
|
572
605
|
close: installation.close,
|
|
573
606
|
dispose: installation.dispose,
|
|
574
|
-
cleanup:
|
|
607
|
+
cleanup: transaction.snapshot()
|
|
575
608
|
});
|
|
576
609
|
committed = true;
|
|
577
610
|
return installation.api;
|
|
578
611
|
} catch (error) {
|
|
579
612
|
controller.abort(new require_errors.ItdAbortError(`Установка feature «${name}» отменена`));
|
|
580
|
-
|
|
613
|
+
transaction.rollback((rollbackError) => {
|
|
614
|
+
reportRollbackError(`Не удалось полностью откатить feature «${name}»`, rollbackError);
|
|
615
|
+
});
|
|
581
616
|
throw error;
|
|
582
617
|
}
|
|
583
618
|
}
|
|
@@ -1461,7 +1496,7 @@ function resolveComment(input, allowReplyTo = false) {
|
|
|
1461
1496
|
const COMMENTS_REPLIES = pageOperation("comments.replies", (body) => readPagedPage(body, "replies"));
|
|
1462
1497
|
const COMMENTS_REPLY = require_url.passthroughOperation("comments.reply");
|
|
1463
1498
|
const COMMENTS_UPDATE = require_url.passthroughOperation("comments.update");
|
|
1464
|
-
const COMMENTS_RESTORE = require_url.
|
|
1499
|
+
const COMMENTS_RESTORE = require_url.voidOperation("comments.restore");
|
|
1465
1500
|
const COMMENTS_LIKE = require_url.passthroughOperation("comments.like");
|
|
1466
1501
|
const COMMENTS_UNLIKE = require_url.passthroughOperation("comments.unlike");
|
|
1467
1502
|
const COMMENTS_REMOVE = require_url.voidOperation("comments.remove");
|
|
@@ -1544,7 +1579,7 @@ var CommentsResource = class extends BaseResource {
|
|
|
1544
1579
|
}
|
|
1545
1580
|
/** Восстанавливает удалённый комментарий. */
|
|
1546
1581
|
restore(commentId, options = {}) {
|
|
1547
|
-
return this.
|
|
1582
|
+
return this.voidOperation(COMMENTS_RESTORE, {
|
|
1548
1583
|
path: `/api/comments/${require_redact.encodePathSegment(commentId, "commentId")}/restore`,
|
|
1549
1584
|
...options
|
|
1550
1585
|
});
|
|
@@ -3056,7 +3091,7 @@ const POSTS_STATS = require_url.defineBuiltInOperation("posts.stats", (body) =>
|
|
|
3056
3091
|
const POSTS_CREATE = require_url.passthroughOperation("posts.create");
|
|
3057
3092
|
const POSTS_GET = require_url.passthroughOperation("posts.get");
|
|
3058
3093
|
const POSTS_UPDATE = require_url.passthroughOperation("posts.update");
|
|
3059
|
-
const POSTS_RESTORE = require_url.
|
|
3094
|
+
const POSTS_RESTORE = require_url.voidOperation("posts.restore");
|
|
3060
3095
|
const POSTS_LIKE = require_url.passthroughOperation("posts.like");
|
|
3061
3096
|
const POSTS_UNLIKE = require_url.passthroughOperation("posts.unlike");
|
|
3062
3097
|
const POSTS_REPOST = require_url.passthroughOperation("posts.repost");
|
|
@@ -3213,7 +3248,7 @@ var PostsResource = class extends BaseResource {
|
|
|
3213
3248
|
}
|
|
3214
3249
|
/** Восстанавливает удалённый пост. */
|
|
3215
3250
|
restore(postId, options = {}) {
|
|
3216
|
-
return this.
|
|
3251
|
+
return this.voidOperation(POSTS_RESTORE, {
|
|
3217
3252
|
path: `/api/posts/${require_redact.encodePathSegment(postId, "postId")}/restore`,
|
|
3218
3253
|
...options
|
|
3219
3254
|
});
|
|
@@ -4684,10 +4719,6 @@ function createShopOrderAccessStorage(store, options = {}) {
|
|
|
4684
4719
|
clear: () => backend.delete(key)
|
|
4685
4720
|
};
|
|
4686
4721
|
}
|
|
4687
|
-
/** Создаёт независимое хранилище доступа к заказам в памяти. */
|
|
4688
|
-
function createMemoryShopOrderAccessStorage() {
|
|
4689
|
-
return createShopOrderAccessStorage(new require_key_value_store.MemoryKeyValueStore());
|
|
4690
|
-
}
|
|
4691
4722
|
//#endregion
|
|
4692
4723
|
//#region src/shop/feature.ts
|
|
4693
4724
|
const Operation = Object.freeze({
|
|
@@ -4742,7 +4773,7 @@ function createShopFeature(options = {}) {
|
|
|
4742
4773
|
}
|
|
4743
4774
|
},
|
|
4744
4775
|
setup(context) {
|
|
4745
|
-
const storage = options.storage ??
|
|
4776
|
+
const storage = options.storage ?? new MemoryShopOrderAccessStorage();
|
|
4746
4777
|
let pendingEmail = null;
|
|
4747
4778
|
const readSession = async () => {
|
|
4748
4779
|
const session = await storage.get();
|
|
@@ -5140,12 +5171,6 @@ Object.defineProperty(exports, "createFeatureHost", {
|
|
|
5140
5171
|
return createFeatureHost;
|
|
5141
5172
|
}
|
|
5142
5173
|
});
|
|
5143
|
-
Object.defineProperty(exports, "createMemoryShopOrderAccessStorage", {
|
|
5144
|
-
enumerable: true,
|
|
5145
|
-
get: function() {
|
|
5146
|
-
return createMemoryShopOrderAccessStorage;
|
|
5147
|
-
}
|
|
5148
|
-
});
|
|
5149
5174
|
Object.defineProperty(exports, "createResources", {
|
|
5150
5175
|
enumerable: true,
|
|
5151
5176
|
get: function() {
|
|
@@ -5261,4 +5286,4 @@ Object.defineProperty(exports, "utcStampToIso", {
|
|
|
5261
5286
|
}
|
|
5262
5287
|
});
|
|
5263
5288
|
|
|
5264
|
-
//# sourceMappingURL=render-
|
|
5289
|
+
//# sourceMappingURL=render-DqVzx68r.cjs.map
|