@torrow/sdk-client 0.21.0 → 0.23.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.
package/dist/index.js CHANGED
@@ -239,7 +239,7 @@ function normalizeTransportError(cause, request, signal, url, parsing = false) {
239
239
  if (cause instanceof TorrowSdkError) {
240
240
  return cause;
241
241
  }
242
- const cancelled = signal?.aborted || record(cause)?.name === "AbortError";
242
+ const cancelled = signal?.aborted || record(cause)?.name === "AbortError" /* Abort */;
243
243
  const category = cancelled ? "Cancelled" /* Cancelled */ : parsing ? "InvalidResponse" /* InvalidResponse */ : request === "Started" /* Started */ && cause instanceof TypeError ? "TransportFailure" /* TransportFailure */ : "Unknown" /* Unknown */;
244
244
  return new TorrowSdkError({ category, request, sensitive: { cause, url } });
245
245
  }
@@ -10269,7 +10269,16 @@ function projectItemPrice(item) {
10269
10269
 
10270
10270
  // ../../src/resources/cases/read-projection.ts
10271
10271
  function projectCaseItem(item) {
10272
- return projectReadChild(projectItemPrice(projectItemSocial(item)), "personalInfo", projectCasePersonalInfo);
10272
+ const projected = projectReadChild(
10273
+ projectItemPrice(projectItemSocial(item)),
10274
+ "personalInfo",
10275
+ projectCasePersonalInfo
10276
+ );
10277
+ if (projected !== null && typeof projected === "object" && !Array.isArray(projected)) {
10278
+ const { visitCard: _visitCard, ...subject } = projected;
10279
+ return subject;
10280
+ }
10281
+ return projected;
10273
10282
  }
10274
10283
 
10275
10284
  // ../../src/resources/loyalty-cards/read-projection.ts
@@ -10951,6 +10960,21 @@ async function readOptionalFileMetadata(options) {
10951
10960
  }
10952
10961
  }
10953
10962
 
10963
+ // ../../src/resources/common/nested-rid-error.ts
10964
+ var NestedRidErrorCode = /* @__PURE__ */ ((NestedRidErrorCode2) => {
10965
+ NestedRidErrorCode2["InvalidRid"] = "InvalidRid";
10966
+ return NestedRidErrorCode2;
10967
+ })(NestedRidErrorCode || {});
10968
+ var NestedRidError = class extends Error {
10969
+ /** Машинная причина отказа; текст `message` остаётся диагностикой для человека. */
10970
+ code;
10971
+ /** Сохраняет прежнее сообщение об ошибке RID и задаёт машинную причину. */
10972
+ constructor(code, message) {
10973
+ super(message);
10974
+ this.code = code;
10975
+ }
10976
+ };
10977
+
10954
10978
  // ../../src/resources/common/nested-rid.ts
10955
10979
  function ensureNestedRidForWrite(item, path) {
10956
10980
  const { rid: rid2 } = item;
@@ -10959,7 +10983,10 @@ function ensureNestedRidForWrite(item, path) {
10959
10983
  return;
10960
10984
  }
10961
10985
  if (!isValidRid(rid2)) {
10962
- throw new Error(`Invalid rid for ${path}: expected ${TORROW_OBJECT_ID_HEX_LENGTH} hexadecimal characters`);
10986
+ throw new NestedRidError(
10987
+ "InvalidRid" /* InvalidRid */,
10988
+ `Invalid rid for ${path}: expected ${TORROW_OBJECT_ID_HEX_LENGTH} hexadecimal characters`
10989
+ );
10963
10990
  }
10964
10991
  }
10965
10992
 
@@ -11957,6 +11984,12 @@ function patchPublicMessage(category, failureAt) {
11957
11984
  }
11958
11985
  }
11959
11986
  async function patchItem(http, itemId, fields, options, adapter) {
11987
+ return patchItemCore(http, itemId, fields, options, adapter);
11988
+ }
11989
+ async function patchDerivedItem(http, itemId, selector, options, adapter) {
11990
+ return patchItemCore(http, itemId, selector, options, adapter, adapter);
11991
+ }
11992
+ async function patchItemCore(http, itemId, input, options, adapter, derived) {
11960
11993
  let failureAt = "ValidateInput" /* ValidateInput */;
11961
11994
  let effect = "NotApplied" /* NotApplied */;
11962
11995
  const trustedErrors = /* @__PURE__ */ new Set();
@@ -11989,16 +12022,20 @@ async function patchItem(http, itemId, fields, options, adapter) {
11989
12022
  if (expectedVersion !== void 0 && !isVersion(expectedVersion) || Object.hasOwn(opts, "versionToCheck") && expectedVersion === void 0 || signal !== void 0 && !isAbortSignal(signal)) {
11990
12023
  throw localError("InvalidInput" /* InvalidInput */);
11991
12024
  }
11992
- const selected = copyValue(fields, /* @__PURE__ */ new Set(), [], adapter.ridPaths);
11993
- if (!isRecord(selected) || Object.keys(selected).length === 0) {
12025
+ const copied = copyValue(input, /* @__PURE__ */ new Set(), [], adapter.ridPaths);
12026
+ if (!isRecord(copied) || !derived && Object.keys(copied).length === 0) {
11994
12027
  throw localError("InvalidInput" /* InvalidInput */);
11995
12028
  }
11996
- for (const [key, value] of Object.entries(selected)) {
11997
- if (!Object.hasOwn(adapter.fields, key) || !validField(value, adapter.fields[key])) {
11998
- throw localError("InvalidInput" /* InvalidInput */);
12029
+ if (derived) {
12030
+ derived.validateSelector(copied);
12031
+ } else {
12032
+ for (const [key, value] of Object.entries(copied)) {
12033
+ if (!Object.hasOwn(adapter.fields, key) || !validField(value, adapter.fields[key])) {
12034
+ throw localError("InvalidInput" /* InvalidInput */);
12035
+ }
11999
12036
  }
12037
+ adapter.validateFields?.(copied);
12000
12038
  }
12001
- adapter.validateFields?.(selected);
12002
12039
  const readQuery = adapter.readQuery ? { ...adapter.readQuery } : void 0;
12003
12040
  const writeQuery = adapter.writeQuery ? { ...adapter.writeQuery } : void 0;
12004
12041
  if (signal?.aborted) {
@@ -12058,12 +12095,28 @@ async function patchItem(http, itemId, fields, options, adapter) {
12058
12095
  if (signal?.aborted) {
12059
12096
  throw localError("Cancelled" /* Cancelled */);
12060
12097
  }
12098
+ const selected = derived ? await derived.deriveSelectedFields(dto, copied, signal) : copied;
12099
+ if (!isRecord(selected) || Object.keys(selected).length === 0) {
12100
+ throw localError("InvalidInput" /* InvalidInput */);
12101
+ }
12102
+ for (const [key, value] of Object.entries(selected)) {
12103
+ if (!Object.hasOwn(adapter.fields, key) || !validField(value, adapter.fields[key])) {
12104
+ throw localError("InvalidInput" /* InvalidInput */);
12105
+ }
12106
+ }
12107
+ if (derived) {
12108
+ adapter.validateFields?.(selected);
12109
+ }
12110
+ if (signal?.aborted) {
12111
+ throw localError("Cancelled" /* Cancelled */);
12112
+ }
12113
+ Object.assign(selected, adapter.deriveFields?.(dto, selected));
12061
12114
  const unchanged = Object.entries(selected).every(([key, value]) => {
12062
12115
  const equal = adapter.equalField?.(key, dto[key], value, dto);
12063
12116
  if (equal !== void 0) {
12064
12117
  return equal;
12065
12118
  }
12066
- if (adapter.fields[key].kind === "Image" /* Image */ && isRecord(dto[key]) && isRecord(value)) {
12119
+ if (adapter.fields[key]?.kind === "Image" /* Image */ && isRecord(dto[key]) && isRecord(value)) {
12067
12120
  return dto[key].id === value.id;
12068
12121
  }
12069
12122
  return equalItemPatchValue(dto[key], value);
@@ -12112,6 +12165,7 @@ async function patchItem(http, itemId, fields, options, adapter) {
12112
12165
  if (!isRecord(ack) || ack.id !== itemId) {
12113
12166
  throw localError("InvalidResponse" /* InvalidResponse */);
12114
12167
  }
12168
+ adapter.assertAck?.(ack, prepared);
12115
12169
  effect = "Applied" /* Applied */;
12116
12170
  failureAt = "ProjectResult" /* ProjectResult */;
12117
12171
  return { itemId, item: projectItem(ack, adapter.project), changed: true };
@@ -12414,32 +12468,6 @@ function validateItemPricePatch(fields) {
12414
12468
  }
12415
12469
  }
12416
12470
 
12417
- // ../../src/resources/cases/types.ts
12418
- var CaseStateValues = {
12419
- Unknown: "UnknownCaseState",
12420
- Verifying: "Verifying",
12421
- Waiting: "Waiting",
12422
- Processing: "Processing",
12423
- Preparing: "Preparing",
12424
- Completed: "Completed",
12425
- Closed: "Closed",
12426
- Rejected: "Rejected",
12427
- Canceled: "Canceled",
12428
- TimeControlled: "TimeControlled",
12429
- TaskNotCompleted: "TaskNotCompleted",
12430
- TaskCompleted: "TaskCompleted"
12431
- };
12432
- var CaseTypeValues = {
12433
- Unknown: "UnknownTimeType",
12434
- Time: "Time",
12435
- RepeatedTime: "RepeatedTime",
12436
- Today: "Today",
12437
- Week: "Week",
12438
- Later: "Later",
12439
- Date: "Date",
12440
- State: "State"
12441
- };
12442
-
12443
12471
  // ../../src/resources/common/item-patch-predicates.ts
12444
12472
  function isItemPatchDtoObject(value) {
12445
12473
  return value !== null && typeof value === "object" && !Array.isArray(value) && !(value instanceof Date);
@@ -12504,6 +12532,57 @@ function normalizeCaseActionRidsForWrite(body, path) {
12504
12532
  });
12505
12533
  }
12506
12534
 
12535
+ // ../../src/resources/cases/types.ts
12536
+ var CaseStateValues = {
12537
+ Unknown: "UnknownCaseState",
12538
+ Verifying: "Verifying",
12539
+ Waiting: "Waiting",
12540
+ Processing: "Processing",
12541
+ Preparing: "Preparing",
12542
+ Completed: "Completed",
12543
+ Closed: "Closed",
12544
+ Rejected: "Rejected",
12545
+ Canceled: "Canceled",
12546
+ TimeControlled: "TimeControlled",
12547
+ TaskNotCompleted: "TaskNotCompleted",
12548
+ TaskCompleted: "TaskCompleted"
12549
+ };
12550
+ var CaseTypeValues = {
12551
+ Unknown: "UnknownTimeType",
12552
+ Time: "Time",
12553
+ RepeatedTime: "RepeatedTime",
12554
+ Today: "Today",
12555
+ Week: "Week",
12556
+ Later: "Later",
12557
+ Date: "Date",
12558
+ State: "State"
12559
+ };
12560
+
12561
+ // ../../src/resources/cases/case-create-visit-card.ts
12562
+ function isValidCaseCardType(value) {
12563
+ return value !== CaseTypeValues.Unknown && Object.values(CaseTypeValues).some((type) => type === value);
12564
+ }
12565
+ function createCaseVisitCard(source) {
12566
+ const { name, caseType, beginDate, endDate, place, description } = source;
12567
+ return {
12568
+ fields: [
12569
+ { number: 0, value: name ?? "", expression: JSON.stringify({ type: "Name" /* Name */ }) },
12570
+ {
12571
+ number: 1,
12572
+ value: caseType,
12573
+ expression: JSON.stringify({ type: "CaseType" /* CaseType */, caseType, beginDate, endDate })
12574
+ },
12575
+ {
12576
+ number: 2,
12577
+ value: (place ? place : description) ?? "",
12578
+ expression: JSON.stringify({
12579
+ type: place ? "PlaceAddress" /* PlaceAddress */ : "Description" /* Description */
12580
+ })
12581
+ }
12582
+ ]
12583
+ };
12584
+ }
12585
+
12507
12586
  // ../../src/resources/cases/case-patch.ts
12508
12587
  function optionalDate2(value) {
12509
12588
  return value == null || value instanceof Date && Number.isFinite(value.getTime());
@@ -12511,19 +12590,6 @@ function optionalDate2(value) {
12511
12590
  function appendices(value) {
12512
12591
  return isItemPatchObjectArray(value) && value.every((item) => optionalDate2(item.openDate) && optionalDate2(item.closeDate));
12513
12592
  }
12514
- function visitCard(value) {
12515
- if (!isItemPatchDtoObject(value) || Object.keys(value).some((key) => key !== "fields")) {
12516
- return false;
12517
- }
12518
- if (value.fields == null) {
12519
- return true;
12520
- }
12521
- return Array.isArray(value.fields) && value.fields.every(
12522
- (field) => isItemPatchDtoObject(field) && Object.entries(field).every(
12523
- ([key, member]) => key === "number" ? isItemPatchInt32(member) : (key === "value" || key === "expression") && (member === null || typeof member === "string")
12524
- )
12525
- );
12526
- }
12527
12593
  function checkinPermission(value) {
12528
12594
  return isItemPatchDtoObject(value) && Object.entries(value).every(
12529
12595
  ([key, member]) => key === "userAccessLevel" ? Object.values(UserAccessLevelValues).some((level) => level === member) : key === "consumerMinTimeSecBetweenCasesInService" && (member === null || isItemPatchInt32(member))
@@ -12546,7 +12612,7 @@ function createCasePatchAdapter() {
12546
12612
  clientGroupId: { kind: "String" /* String */, nullable: true, validate: isItemPatchReferenceId },
12547
12613
  caseType: {
12548
12614
  kind: "String" /* String */,
12549
- validate: (value) => value !== CaseTypeValues.Unknown && Object.values(CaseTypeValues).some((type) => type === value)
12615
+ validate: isValidCaseCardType
12550
12616
  },
12551
12617
  schedule: { kind: "Object" /* Object */, nullable: true, validate: isItemPatchSchedule },
12552
12618
  registrationOpen: { kind: "Integer" /* Integer */, nullable: true, validate: isItemPatchInt32 },
@@ -12565,7 +12631,6 @@ function createCasePatchAdapter() {
12565
12631
  createSingleCases: { kind: "Boolean" /* Boolean */, nullable: true },
12566
12632
  checkinPermission: { kind: "Object" /* Object */, nullable: true, validate: checkinPermission },
12567
12633
  participateFieldRequirements: { kind: "Object" /* Object */, nullable: true },
12568
- visitCard: { kind: "Object" /* Object */, validate: visitCard },
12569
12634
  appendixList: { kind: "Array" /* Array */, nullable: true, validate: appendices },
12570
12635
  resourceGroupList: { kind: "Array" /* Array */, nullable: true, validate: isItemPatchObjectArray },
12571
12636
  caseActionList: { kind: "Array" /* Array */, nullable: true, validate: isItemPatchObjectArray },
@@ -12581,6 +12646,18 @@ function createCasePatchAdapter() {
12581
12646
  throw itemPatchError("InvalidInput" /* InvalidInput */);
12582
12647
  }
12583
12648
  },
12649
+ deriveFields: (dto, selected) => {
12650
+ const final = { ...dto, ...selected };
12651
+ if (!isValidCaseCardType(final.caseType)) {
12652
+ throw itemPatchError("InsufficientData" /* InsufficientData */);
12653
+ }
12654
+ return { visitCard: createCaseVisitCard(final) };
12655
+ },
12656
+ assertAck: (ack, written) => {
12657
+ if (!equalItemPatchValue(ack.visitCard, written.visitCard)) {
12658
+ throw itemPatchError("InvalidResponse" /* InvalidResponse */);
12659
+ }
12660
+ },
12584
12661
  project: (item) => projectCaseItem(item),
12585
12662
  casRefusal: isItemPatchCasRefusal
12586
12663
  };
@@ -12615,6 +12692,20 @@ function cancelCaseParticipation(http, torrowId, body, options) {
12615
12692
 
12616
12693
  // ../../src/resources/cases/CasesFacade.ts
12617
12694
  var BASE3 = "/api/v1/cases";
12695
+ var CARD_SOURCE_FIELDS = /* @__PURE__ */ new Set(["visitCard", "name", "caseType", "beginDate", "endDate", "place", "description"]);
12696
+ function affectsCaseCard(pointer) {
12697
+ if (typeof pointer !== "string" || pointer === "") {
12698
+ return true;
12699
+ }
12700
+ if (!pointer.startsWith("/")) {
12701
+ return true;
12702
+ }
12703
+ const first = pointer.slice(1).split("/")[0];
12704
+ if (/~(?![01])/.test(first)) {
12705
+ return true;
12706
+ }
12707
+ return CARD_SOURCE_FIELDS.has(first.replace(/~1/g, "/").replace(/~0/g, "~"));
12708
+ }
12618
12709
  var CasesFacade = class extends TorrowItemFacade {
12619
12710
  itemObjectTypeCode = TorrowObjectTypeCode.Case;
12620
12711
  /** Чтение полной карточки для метаданных без дочерних данных. */
@@ -12678,7 +12769,11 @@ var CasesFacade = class extends TorrowItemFacade {
12678
12769
  /** `PUT /api/v1/cases/{body.id}` */
12679
12770
  update(body, options) {
12680
12771
  const itemId = requireItemUpdateId(body, "Case");
12772
+ if (!isValidCaseCardType(body.caseType)) {
12773
+ throw new TorrowSdkError({ category: "InvalidInput" /* InvalidInput */ });
12774
+ }
12681
12775
  const payload = structuredClone(body);
12776
+ payload.visitCard = createCaseVisitCard(payload);
12682
12777
  normalizeItemScheduleRidsForWrite(payload, "case");
12683
12778
  normalizeCaseActionRidsForWrite(payload, "case");
12684
12779
  return this.http.requestJson({
@@ -12692,26 +12787,24 @@ var CasesFacade = class extends TorrowItemFacade {
12692
12787
  },
12693
12788
  body: payload,
12694
12789
  signal: options?.signal
12695
- }).then((dto) => projectCaseItem(dto));
12790
+ }).then((dto) => {
12791
+ if (dto === null || typeof dto !== "object" || Array.isArray(dto) || dto.id !== itemId || !equalItemPatchValue(dto.visitCard, payload.visitCard)) {
12792
+ throw new TorrowSdkError({ category: "InvalidResponse" /* InvalidResponse */ });
12793
+ }
12794
+ return projectCaseItem(dto);
12795
+ });
12696
12796
  }
12697
12797
  withCreateDefaults(body, publicityType) {
12698
12798
  const payload = applyItemCreateDefaults(structuredClone(body), "CaseItem" /* CaseItem */, publicityType);
12699
12799
  const prepared = {
12700
12800
  ...payload,
12701
12801
  caseState: payload.caseState ?? CaseStateValues.Verifying,
12702
- caseType: payload.caseType ?? CaseTypeValues.Time,
12703
- // Сервер отклоняет create без VisitCard («Parameter VisitCard cannot have value null»).
12704
- visitCard: payload.visitCard ?? {
12705
- fields: [
12706
- { number: 0, value: payload.name ?? "", expression: '{"type":"Name"}' },
12707
- { number: 1, value: "", expression: null },
12708
- { number: 2, value: "", expression: null }
12709
- ]
12710
- }
12802
+ caseType: payload.caseType ?? CaseTypeValues.Time
12711
12803
  };
12712
- normalizeItemScheduleRidsForWrite(prepared, "case");
12713
- normalizeCaseActionRidsForWrite(prepared, "case");
12714
- return prepared;
12804
+ const withCard = { ...prepared, visitCard: createCaseVisitCard(prepared) };
12805
+ normalizeItemScheduleRidsForWrite(withCard, "case");
12806
+ normalizeCaseActionRidsForWrite(withCard, "case");
12807
+ return withCard;
12715
12808
  }
12716
12809
  /** `DELETE /api/v1/cases/{torrowId}` */
12717
12810
  async delete(torrowId, options) {
@@ -12980,6 +13073,11 @@ var CasesFacade = class extends TorrowItemFacade {
12980
13073
  }
12981
13074
  /** `POST /api/v1/cases/{torrowId}/patch` */
12982
13075
  patchCase(torrowId, body, options) {
13076
+ if (!Array.isArray(body?.patchDoc?.operations) || body.patchDoc.operations.some(
13077
+ (operation) => affectsCaseCard(operation.path) || operation.from != null && affectsCaseCard(operation.from)
13078
+ )) {
13079
+ throw new TorrowSdkError({ category: "InvalidInput" /* InvalidInput */ });
13080
+ }
12983
13081
  return this.http.requestJson({
12984
13082
  method: "POST",
12985
13083
  path: `${BASE3}/${encodePathSegment(torrowId)}/patch`,
@@ -13050,11 +13148,11 @@ function contactVisitCardDefaultSlot0Value(body) {
13050
13148
  return trimNonEmptyString(body.company) ?? "";
13051
13149
  }
13052
13150
  function normalizeContactVisitCardFieldsForWrite(body) {
13053
- let visitCard3 = body.visitCard;
13054
- if (visitCard3 === void 0 || visitCard3 === null || typeof visitCard3 !== "object" || Array.isArray(visitCard3)) {
13055
- visitCard3 = {};
13151
+ let visitCard2 = body.visitCard;
13152
+ if (visitCard2 === void 0 || visitCard2 === null || typeof visitCard2 !== "object" || Array.isArray(visitCard2)) {
13153
+ visitCard2 = {};
13056
13154
  }
13057
- let incoming = Array.isArray(visitCard3.fields) ? visitCard3.fields : [];
13155
+ let incoming = Array.isArray(visitCard2.fields) ? visitCard2.fields : [];
13058
13156
  if (incoming.length === 0) {
13059
13157
  incoming = [
13060
13158
  {
@@ -13082,7 +13180,7 @@ function normalizeContactVisitCardFieldsForWrite(body) {
13082
13180
  for (let i = 0; i < CONTACT_VISIT_CARD_SLOT_COUNT; i++) {
13083
13181
  fields.push(picked[i] ?? { number: i, value: "" });
13084
13182
  }
13085
- body.visitCard = { ...visitCard3, fields };
13183
+ body.visitCard = { ...visitCard2, fields };
13086
13184
  }
13087
13185
 
13088
13186
  // ../../src/resources/contacts/types.ts
@@ -13170,7 +13268,7 @@ var memorableDateShape = {
13170
13268
  order: integer
13171
13269
  };
13172
13270
  var file = (value) => shape(value, { id: (value2) => typeof value2 === "string" && value2.length > 0 }) && record4(value) && Object.hasOwn(value, "id");
13173
- var visitCard2 = (value) => shape(value, {
13271
+ var visitCard = (value) => shape(value, {
13174
13272
  fields: nullable(
13175
13273
  (value2) => Array.isArray(value2) && value2.every((child) => shape(child, { number: integer, value: nullable(text), expression: nullable(text) }))
13176
13274
  )
@@ -13247,7 +13345,7 @@ function createContactPatchAdapter() {
13247
13345
  validate: arrayOf((value) => shape(value, memorableDateShape))
13248
13346
  },
13249
13347
  photos: { kind: "Array" /* Array */, nullable: true, validate: arrayOf(file) },
13250
- visitCard: { kind: "Object" /* Object */, validate: visitCard2 }
13348
+ visitCard: { kind: "Object" /* Object */, validate: visitCard }
13251
13349
  },
13252
13350
  validateFields(fields) {
13253
13351
  selected = structuredClone(fields);
@@ -14487,6 +14585,9 @@ var resourceItemPatchFields = {
14487
14585
  kind: "String" /* String */,
14488
14586
  validate: (value) => Object.values(UsageTypeValues).some((type) => type === value)
14489
14587
  },
14588
+ // Это полная замена списка. Нельзя собирать одно изменение связи снаружи и передавать
14589
+ // сюда массив: внутренний GET/CAS не защитит изменения между внешним и внутренним чтением.
14590
+ // upsertServiceLink/removeServiceLink вычисляют список из собственного raw GET.
14490
14591
  serviceDescriptions: { kind: "Array" /* Array */, validate: isItemPatchObjectArray },
14491
14592
  code: { kind: "String" /* String */, nullable: true },
14492
14593
  duration: { kind: "Integer" /* Integer */, nullable: true, validate: isItemPatchInt32 },
@@ -14525,6 +14626,225 @@ function createResourcePatchAdapter(project) {
14525
14626
  };
14526
14627
  }
14527
14628
 
14629
+ // ../../src/resources/resources/resource-service-link.ts
14630
+ var preservedRootFields = [
14631
+ "name",
14632
+ "description",
14633
+ "contactId",
14634
+ "parentResourceId",
14635
+ "calendarId",
14636
+ "itemId",
14637
+ "timetableId",
14638
+ "schedule",
14639
+ "priceInfo",
14640
+ "usageType",
14641
+ "code",
14642
+ "duration",
14643
+ "amountProperties",
14644
+ "usageCondition",
14645
+ "appendixList",
14646
+ "paymentProperties",
14647
+ "ticketProperties",
14648
+ "loyaltyTransactionPropertiesList",
14649
+ "tags",
14650
+ "uniqueName",
14651
+ "image",
14652
+ "publicityType",
14653
+ "searchMode",
14654
+ "anyoneAccess",
14655
+ "feedbackOptions",
14656
+ "integrationIds"
14657
+ ];
14658
+ function invalidInput() {
14659
+ throw itemPatchError("InvalidInput" /* InvalidInput */);
14660
+ }
14661
+ function insufficientData() {
14662
+ throw itemPatchError("InsufficientData" /* InsufficientData */);
14663
+ }
14664
+ function invalidResponse() {
14665
+ throw itemPatchError("InvalidResponse" /* InvalidResponse */);
14666
+ }
14667
+ function validateSelector(selector) {
14668
+ if (Object.keys(selector).some((key) => !["action", "serviceId", "resourceGroupId", "fields"].includes(key))) {
14669
+ invalidInput();
14670
+ }
14671
+ if (selector.action !== "Upsert" /* Upsert */ && selector.action !== "Remove" /* Remove */) {
14672
+ invalidInput();
14673
+ }
14674
+ try {
14675
+ if (getTorrowObjectTypeFromTorrowId(selector.serviceId) !== "Service") {
14676
+ invalidInput();
14677
+ }
14678
+ } catch {
14679
+ invalidInput();
14680
+ }
14681
+ if (typeof selector.resourceGroupId !== "string" || selector.resourceGroupId.length === 0) {
14682
+ invalidInput();
14683
+ }
14684
+ if (selector.fields === null || typeof selector.fields !== "object" || Array.isArray(selector.fields)) {
14685
+ invalidInput();
14686
+ }
14687
+ if (selector.action === "Remove" /* Remove */ && Object.keys(selector.fields).length > 0) {
14688
+ invalidInput();
14689
+ }
14690
+ for (const [key, value] of Object.entries(selector.fields)) {
14691
+ if (key === "usageAmount") {
14692
+ if (value !== null && (typeof value !== "number" || !Number.isFinite(value))) {
14693
+ invalidInput();
14694
+ }
14695
+ } else if (key === "sortIndex") {
14696
+ if (value !== null && (typeof value !== "number" || !Number.isInteger(value) || value < -2147483648 || value > 2147483647)) {
14697
+ invalidInput();
14698
+ }
14699
+ } else {
14700
+ invalidInput();
14701
+ }
14702
+ }
14703
+ }
14704
+ function checkedDescriptions(dto) {
14705
+ const list = dto.serviceDescriptions;
14706
+ if (list == null || Array.isArray(list) && list.length === 0) {
14707
+ insufficientData();
14708
+ }
14709
+ if (!Array.isArray(list)) {
14710
+ invalidResponse();
14711
+ }
14712
+ const seen = /* @__PURE__ */ new Set();
14713
+ for (const binding of list) {
14714
+ if (binding === null || typeof binding !== "object" || Array.isArray(binding) || typeof binding.id !== "string" || typeof binding.resourceGroupId !== "string" || binding.resourceGroupId.length === 0) {
14715
+ invalidResponse();
14716
+ }
14717
+ try {
14718
+ if (getTorrowObjectTypeFromTorrowId(binding.id) !== "Service") {
14719
+ invalidResponse();
14720
+ }
14721
+ } catch {
14722
+ invalidResponse();
14723
+ }
14724
+ if (binding.serviceName != null && typeof binding.serviceName !== "string" || binding.resourceGroupName != null && typeof binding.resourceGroupName !== "string" || binding.laterBinding != null && typeof binding.laterBinding !== "boolean" || binding.usageAmount != null && (typeof binding.usageAmount !== "number" || !Number.isFinite(binding.usageAmount)) || binding.sortIndex != null && (typeof binding.sortIndex !== "number" || !Number.isInteger(binding.sortIndex) || binding.sortIndex < -2147483648 || binding.sortIndex > 2147483647)) {
14725
+ invalidResponse();
14726
+ }
14727
+ const pair = `${binding.id.length}:${binding.id}${binding.resourceGroupId}`;
14728
+ if (seen.has(pair)) {
14729
+ invalidResponse();
14730
+ }
14731
+ seen.add(pair);
14732
+ }
14733
+ return list;
14734
+ }
14735
+ function samePair(binding, selector) {
14736
+ return binding.id === selector.serviceId && binding.resourceGroupId === selector.resourceGroupId;
14737
+ }
14738
+ async function changeResourceServiceLink(http, project, resourceId, selector, options) {
14739
+ let before;
14740
+ let expected;
14741
+ let acknowledged;
14742
+ const adapter = createResourcePatchAdapter(project);
14743
+ const result = await patchDerivedItem(http, resourceId, selector, options, {
14744
+ ...adapter,
14745
+ operation: selector.action === "Upsert" /* Upsert */ ? "ResourcesFacade.upsertServiceLink" : "ResourcesFacade.removeServiceLink",
14746
+ validateSelector,
14747
+ async deriveSelectedFields(dto, selected, signal) {
14748
+ const list2 = checkedDescriptions(dto);
14749
+ before = dto;
14750
+ const at = list2.findIndex((binding) => samePair(binding, selected));
14751
+ if (selected.action === "Remove" /* Remove */) {
14752
+ if (at < 0) {
14753
+ expected = list2;
14754
+ return { serviceDescriptions: list2 };
14755
+ }
14756
+ if (list2.length === 1) {
14757
+ insufficientData();
14758
+ }
14759
+ expected = list2.filter((_, index) => index !== at);
14760
+ return { serviceDescriptions: expected };
14761
+ }
14762
+ if (signal?.aborted) {
14763
+ throw itemPatchError("Cancelled" /* Cancelled */);
14764
+ }
14765
+ const service = await http.requestJson({
14766
+ method: "GET",
14767
+ path: `/api/v1/services/${encodePathSegment(selected.serviceId)}`,
14768
+ signal
14769
+ });
14770
+ if (service === null || typeof service !== "object" || Array.isArray(service) || service.id !== selected.serviceId) {
14771
+ invalidResponse();
14772
+ }
14773
+ const groups = service.resourceGroupList;
14774
+ if (!Array.isArray(groups)) {
14775
+ insufficientData();
14776
+ }
14777
+ const matchingGroups = groups.filter((item) => item?.groupId === selected.resourceGroupId);
14778
+ if (matchingGroups.length > 1) {
14779
+ invalidResponse();
14780
+ }
14781
+ const group = matchingGroups[0];
14782
+ if (!group || typeof group.usageType !== "string" || group.usageType.length === 0 || typeof group.groupName !== "string" || typeof service.name !== "string") {
14783
+ insufficientData();
14784
+ }
14785
+ if (group.usageType === UsageTypeValues.Unknown || !Object.values(UsageTypeValues).some((value) => value === group.usageType)) {
14786
+ invalidResponse();
14787
+ }
14788
+ if (dto.usageType !== group.usageType) {
14789
+ invalidInput();
14790
+ }
14791
+ const next = [...list2];
14792
+ if (at < 0) {
14793
+ next.push({
14794
+ id: selected.serviceId,
14795
+ resourceGroupId: selected.resourceGroupId,
14796
+ serviceName: service.name,
14797
+ resourceGroupName: group.groupName,
14798
+ laterBinding: group.bookingProperties != null,
14799
+ ...selected.fields
14800
+ });
14801
+ } else {
14802
+ next[at] = { ...list2[at], ...selected.fields };
14803
+ }
14804
+ expected = next;
14805
+ return { serviceDescriptions: next };
14806
+ },
14807
+ assertAck(ack, written) {
14808
+ if (!before || !expected || !Array.isArray(ack.serviceDescriptions) || !equalItemPatchValue(ack.serviceDescriptions, expected) || !Number.isInteger(ack.meta?.version) || (ack.meta?.version ?? 0) <= 0) {
14809
+ invalidResponse();
14810
+ }
14811
+ const rawAck = ack;
14812
+ const rawWritten = written;
14813
+ for (const key of preservedRootFields) {
14814
+ if (Object.hasOwn(before, key) && !equalItemPatchValue(rawAck[key], rawWritten[key])) {
14815
+ invalidResponse();
14816
+ }
14817
+ }
14818
+ acknowledged = ack.serviceDescriptions;
14819
+ }
14820
+ });
14821
+ const list = result.changed ? acknowledged : before.serviceDescriptions;
14822
+ return {
14823
+ ...result,
14824
+ serviceId: selector.serviceId,
14825
+ resourceGroupId: selector.resourceGroupId,
14826
+ binding: list.find((binding) => samePair(binding, selector)) ?? null
14827
+ };
14828
+ }
14829
+ function upsertResourceServiceLink(http, project, resourceId, serviceId, resourceGroupId, fields, options) {
14830
+ return changeResourceServiceLink(
14831
+ http,
14832
+ project,
14833
+ resourceId,
14834
+ { action: "Upsert" /* Upsert */, serviceId, resourceGroupId, fields },
14835
+ options
14836
+ );
14837
+ }
14838
+ function removeResourceServiceLink(http, project, resourceId, serviceId, resourceGroupId, options) {
14839
+ return changeResourceServiceLink(
14840
+ http,
14841
+ project,
14842
+ resourceId,
14843
+ { action: "Remove" /* Remove */, serviceId, resourceGroupId, fields: {} },
14844
+ options
14845
+ );
14846
+ }
14847
+
14528
14848
  // ../../src/resources/resources/ResourcesFacade.ts
14529
14849
  var BASE7 = "/api/v1/resources";
14530
14850
  var ResourcesFacade = class extends TorrowItemFacade {
@@ -14555,6 +14875,35 @@ var ResourcesFacade = class extends TorrowItemFacade {
14555
14875
  createResourcePatchAdapter((item) => this.toSdkResourceItem(item))
14556
14876
  );
14557
14877
  }
14878
+ /**
14879
+ * Адресно добавляет или изменяет одну связь при полном непустом списке.
14880
+ * Предполагается, что Service не изменяется в течение вызова; CAS защищает Resource.
14881
+ * Серверный отказ проверки Service при PUT передаётся как TorrowSdkError с HTTP-данными.
14882
+ * Проверка Service не атомарна с записью Resource.
14883
+ * При неизвестном результате PUT требуется отдельная сверка, автоматического повтора нет.
14884
+ */
14885
+ upsertServiceLink(resourceId, serviceId, resourceGroupId, fields, options) {
14886
+ return upsertResourceServiceLink(
14887
+ this.http,
14888
+ (item) => this.toSdkResourceItem(item),
14889
+ resourceId,
14890
+ serviceId,
14891
+ resourceGroupId,
14892
+ fields,
14893
+ options
14894
+ );
14895
+ }
14896
+ /** Удаляет одну связь, если после неё остаётся непустой подтверждённый список. */
14897
+ removeServiceLink(resourceId, serviceId, resourceGroupId, options) {
14898
+ return removeResourceServiceLink(
14899
+ this.http,
14900
+ (item) => this.toSdkResourceItem(item),
14901
+ resourceId,
14902
+ serviceId,
14903
+ resourceGroupId,
14904
+ options
14905
+ );
14906
+ }
14558
14907
  /** Поиск по уникальному имени возвращает ту же модель ресурса, что и getById. */
14559
14908
  getByUniqueName(uniqueName, options) {
14560
14909
  return this.readByUniqueName(uniqueName, options).then((item) => this.toSdkResourceItem(item));
@@ -15529,11 +15878,13 @@ var ServicesFacade = class extends TorrowItemFacade {
15529
15878
  }
15530
15879
  /** `POST /api/v1/services/{serviceId}/session` — создать сессию записи (тело `CaseItem`). */
15531
15880
  createSession(serviceId, body, options) {
15881
+ const payload = { ...structuredClone(body), caseType: body.caseType ?? CaseTypeValues.Time };
15882
+ payload.visitCard = createCaseVisitCard(payload);
15532
15883
  return this.http.requestJson({
15533
15884
  method: "POST",
15534
15885
  path: `${BASE9}/${encodePathSegment(serviceId)}/session`,
15535
15886
  query: { profileId: options?.profileId },
15536
- body,
15887
+ body: payload,
15537
15888
  signal: options?.signal
15538
15889
  }).then((dto) => projectCaseItem(dto));
15539
15890
  }
@@ -18659,6 +19010,30 @@ function getTimeStepUiMode(session) {
18659
19010
  return TimeStepUiModeValues.SelectTime;
18660
19011
  }
18661
19012
 
19013
+ // ../../src/resources/services/service-builder-error.ts
19014
+ var ServiceBuilderErrorCode = /* @__PURE__ */ ((ServiceBuilderErrorCode2) => {
19015
+ ServiceBuilderErrorCode2["InvalidConfiguration"] = "InvalidConfiguration";
19016
+ return ServiceBuilderErrorCode2;
19017
+ })(ServiceBuilderErrorCode || {});
19018
+ var ServiceBuilderError = class extends TypeError {
19019
+ /** Стабильная машинная причина отказа конфигурации. */
19020
+ code;
19021
+ /** Создаёт локальный отказ с прежним сообщением и машинным кодом. */
19022
+ constructor(code, message) {
19023
+ super(message);
19024
+ this.code = code;
19025
+ }
19026
+ };
19027
+ var ServiceBuilderRangeError = class extends RangeError {
19028
+ /** Стабильная машинная причина отказа числового диапазона. */
19029
+ code;
19030
+ /** Создаёт локальный отказ диапазона с прежним сообщением и машинным кодом. */
19031
+ constructor(code, message) {
19032
+ super(message);
19033
+ this.code = code;
19034
+ }
19035
+ };
19036
+
18662
19037
  // ../../src/resources/services/service-builder.ts
18663
19038
  var RESOURCE_USAGE_TYPES = /* @__PURE__ */ new Set(["Specification", "Rent", "Sale"]);
18664
19039
  var GROUP_ID_PATTERN = /^[0-9a-f]{24}$/i;
@@ -18714,7 +19089,10 @@ function assertStepPosition(position, length) {
18714
19089
  return length + 1;
18715
19090
  }
18716
19091
  if (!Number.isInteger(position) || position < 1 || position > length + 1) {
18717
- throw new RangeError(`stepOrder must be an integer from 1 to ${length + 1}`);
19092
+ throw new ServiceBuilderRangeError(
19093
+ "InvalidConfiguration" /* InvalidConfiguration */,
19094
+ `stepOrder must be an integer from 1 to ${length + 1}`
19095
+ );
18718
19096
  }
18719
19097
  return position;
18720
19098
  }
@@ -18734,14 +19112,18 @@ var ServiceBuilder = class _ServiceBuilder {
18734
19112
  }
18735
19113
  withType(type, options) {
18736
19114
  if (type === ServiceType.Custom) {
18737
- throw new TypeError("ServiceType.Custom requires explicit sessionDurationProperties");
19115
+ throw new ServiceBuilderError(
19116
+ "InvalidConfiguration" /* InvalidConfiguration */,
19117
+ "ServiceType.Custom requires explicit sessionDurationProperties"
19118
+ );
18738
19119
  }
18739
19120
  this.draft.sessionDurationProperties = createServiceSessionDurationProperties(type, options);
18740
19121
  return this;
18741
19122
  }
18742
19123
  withSessionDurationProperties(properties) {
18743
19124
  if (!properties.sessionDurationType || !SESSION_DURATION_TYPES.has(properties.sessionDurationType) || !properties.timeSelectionType || !TIME_SELECTION_TYPES.has(properties.timeSelectionType) || !properties.stateManagementType || !STATE_MANAGEMENT_TYPES.has(properties.stateManagementType)) {
18744
- throw new TypeError(
19125
+ throw new ServiceBuilderError(
19126
+ "InvalidConfiguration" /* InvalidConfiguration */,
18745
19127
  "sessionDurationProperties must include sessionDurationType, timeSelectionType, and stateManagementType"
18746
19128
  );
18747
19129
  }
@@ -18750,12 +19132,18 @@ var ServiceBuilder = class _ServiceBuilder {
18750
19132
  }
18751
19133
  addResourceStep(input) {
18752
19134
  if (!RESOURCE_USAGE_TYPES.has(input.usageType)) {
18753
- throw new TypeError(`Unsupported resource group usageType: ${String(input.usageType)}`);
19135
+ throw new ServiceBuilderError(
19136
+ "InvalidConfiguration" /* InvalidConfiguration */,
19137
+ `Unsupported resource group usageType: ${String(input.usageType)}`
19138
+ );
18754
19139
  }
18755
19140
  const minResources = input.minResources ?? 1;
18756
19141
  const maxResources = input.maxResources ?? 1;
18757
19142
  if (input.autoChoiceResource === true && (minResources !== 1 || maxResources !== 1)) {
18758
- throw new RangeError("autoChoiceResource requires exactly one resource");
19143
+ throw new ServiceBuilderRangeError(
19144
+ "InvalidConfiguration" /* InvalidConfiguration */,
19145
+ "autoChoiceResource requires exactly one resource"
19146
+ );
18759
19147
  }
18760
19148
  const group = this.addResourceGroup(input, input.usageType);
18761
19149
  const groupId = group.groupId;
@@ -18793,18 +19181,27 @@ var ServiceBuilder = class _ServiceBuilder {
18793
19181
  setResourceGroupResourceIds(resourceGroupId, resourceIds) {
18794
19182
  const normalizedGroupId = resourceGroupId.trim();
18795
19183
  if (!normalizedGroupId) {
18796
- throw new TypeError("resourceGroupId must not be empty");
19184
+ throw new ServiceBuilderError("InvalidConfiguration" /* InvalidConfiguration */, "resourceGroupId must not be empty");
18797
19185
  }
18798
19186
  const normalizedResourceIds = resourceIds.map((resourceId) => resourceId.trim());
18799
19187
  if (normalizedResourceIds.some((resourceId) => !resourceId)) {
18800
- throw new TypeError("resourceIds must not contain empty ids");
19188
+ throw new ServiceBuilderError(
19189
+ "InvalidConfiguration" /* InvalidConfiguration */,
19190
+ "resourceIds must not contain empty ids"
19191
+ );
18801
19192
  }
18802
19193
  if (new Set(normalizedResourceIds).size !== normalizedResourceIds.length) {
18803
- throw new TypeError("resourceIds must not contain duplicates");
19194
+ throw new ServiceBuilderError(
19195
+ "InvalidConfiguration" /* InvalidConfiguration */,
19196
+ "resourceIds must not contain duplicates"
19197
+ );
18804
19198
  }
18805
19199
  const groups = this.draft.resourceGroupList ?? [];
18806
19200
  if (!groups.some((group) => group.groupId === normalizedGroupId)) {
18807
- throw new TypeError(`Service resource group not found: ${normalizedGroupId}`);
19201
+ throw new ServiceBuilderError(
19202
+ "InvalidConfiguration" /* InvalidConfiguration */,
19203
+ `Service resource group not found: ${normalizedGroupId}`
19204
+ );
18808
19205
  }
18809
19206
  this.draft.resourceGroupList = groups.map(
18810
19207
  (group) => group.groupId === normalizedGroupId ? { ...group, resourceIdList: [...normalizedResourceIds] } : group
@@ -18833,7 +19230,10 @@ var ServiceBuilder = class _ServiceBuilder {
18833
19230
  }
18834
19231
  addSingletonStep(stepType, stepOrder) {
18835
19232
  if (this.draft.stepDescriptionList?.some((step) => step.stepType === stepType)) {
18836
- throw new TypeError(`Service already contains step type ${stepType}`);
19233
+ throw new ServiceBuilderError(
19234
+ "InvalidConfiguration" /* InvalidConfiguration */,
19235
+ `Service already contains step type ${stepType}`
19236
+ );
18837
19237
  }
18838
19238
  this.insertStep({ stepType }, stepOrder);
18839
19239
  return this;
@@ -18842,21 +19242,36 @@ var ServiceBuilder = class _ServiceBuilder {
18842
19242
  const key = input.key.trim();
18843
19243
  const groupName = input.groupName.trim();
18844
19244
  if (!key) {
18845
- throw new TypeError("Resource group key must not be empty");
19245
+ throw new ServiceBuilderError(
19246
+ "InvalidConfiguration" /* InvalidConfiguration */,
19247
+ "Resource group key must not be empty"
19248
+ );
18846
19249
  }
18847
19250
  if (!groupName) {
18848
- throw new TypeError("Resource group name must not be empty");
19251
+ throw new ServiceBuilderError(
19252
+ "InvalidConfiguration" /* InvalidConfiguration */,
19253
+ "Resource group name must not be empty"
19254
+ );
18849
19255
  }
18850
19256
  if (this.addedGroups.has(key)) {
18851
- throw new TypeError(`Duplicate resource group key: ${key}`);
19257
+ throw new ServiceBuilderError(
19258
+ "InvalidConfiguration" /* InvalidConfiguration */,
19259
+ `Duplicate resource group key: ${key}`
19260
+ );
18852
19261
  }
18853
19262
  const groupId = input.groupId ?? generateServiceResourceGroupId();
18854
19263
  if (!GROUP_ID_PATTERN.test(groupId)) {
18855
- throw new TypeError("Resource group id must be a 24-character hexadecimal string");
19264
+ throw new ServiceBuilderError(
19265
+ "InvalidConfiguration" /* InvalidConfiguration */,
19266
+ "Resource group id must be a 24-character hexadecimal string"
19267
+ );
18856
19268
  }
18857
19269
  const groups = [...this.draft.resourceGroupList ?? []];
18858
19270
  if (groups.some((group2) => group2.groupId === groupId)) {
18859
- throw new TypeError(`Duplicate resource group id: ${groupId}`);
19271
+ throw new ServiceBuilderError(
19272
+ "InvalidConfiguration" /* InvalidConfiguration */,
19273
+ `Duplicate resource group id: ${groupId}`
19274
+ );
18860
19275
  }
18861
19276
  const minResources = input.minResources ?? 1;
18862
19277
  const maxResources = input.maxResources ?? 1;
@@ -18866,11 +19281,17 @@ var ServiceBuilder = class _ServiceBuilder {
18866
19281
  ["maxTotalAmount", input.maxTotalAmount]
18867
19282
  ]) {
18868
19283
  if (value != null && (!Number.isInteger(value) || value < 0)) {
18869
- throw new RangeError(`${name} must be a non-negative integer`);
19284
+ throw new ServiceBuilderRangeError(
19285
+ "InvalidConfiguration" /* InvalidConfiguration */,
19286
+ `${name} must be a non-negative integer`
19287
+ );
18870
19288
  }
18871
19289
  }
18872
19290
  if (minResources > maxResources) {
18873
- throw new RangeError("minResources must not exceed maxResources");
19291
+ throw new ServiceBuilderRangeError(
19292
+ "InvalidConfiguration" /* InvalidConfiguration */,
19293
+ "minResources must not exceed maxResources"
19294
+ );
18874
19295
  }
18875
19296
  const group = {
18876
19297
  groupId,
@@ -18923,10 +19344,16 @@ var ServiceBuilder = class _ServiceBuilder {
18923
19344
  const ids = /* @__PURE__ */ new Set();
18924
19345
  for (const group of groups) {
18925
19346
  if (!group.groupId || !GROUP_ID_PATTERN.test(group.groupId)) {
18926
- throw new TypeError("Every resource group must have a valid 24-character hexadecimal id");
19347
+ throw new ServiceBuilderError(
19348
+ "InvalidConfiguration" /* InvalidConfiguration */,
19349
+ "Every resource group must have a valid 24-character hexadecimal id"
19350
+ );
18927
19351
  }
18928
19352
  if (ids.has(group.groupId)) {
18929
- throw new TypeError(`Duplicate resource group id: ${group.groupId}`);
19353
+ throw new ServiceBuilderError(
19354
+ "InvalidConfiguration" /* InvalidConfiguration */,
19355
+ `Duplicate resource group id: ${group.groupId}`
19356
+ );
18930
19357
  }
18931
19358
  ids.add(group.groupId);
18932
19359
  }
@@ -18937,10 +19364,16 @@ var ServiceBuilder = class _ServiceBuilder {
18937
19364
  }
18938
19365
  const groupId = getResourceGroupIdFromStep(step);
18939
19366
  if (!groupId || !ids.has(groupId)) {
18940
- throw new TypeError(`Resource step references an unknown resource group: ${groupId ?? ""}`);
19367
+ throw new ServiceBuilderError(
19368
+ "InvalidConfiguration" /* InvalidConfiguration */,
19369
+ `Resource step references an unknown resource group: ${groupId ?? ""}`
19370
+ );
18941
19371
  }
18942
19372
  if (usedIds.has(groupId)) {
18943
- throw new TypeError(`Resource group is used by more than one step: ${groupId}`);
19373
+ throw new ServiceBuilderError(
19374
+ "InvalidConfiguration" /* InvalidConfiguration */,
19375
+ `Resource group is used by more than one step: ${groupId}`
19376
+ );
18944
19377
  }
18945
19378
  usedIds.add(groupId);
18946
19379
  }
@@ -19061,6 +19494,21 @@ function getTicketPaymentUrl(caseItem) {
19061
19494
  return normalizePaymentUrl(getTicketPaymentUrlRaw(caseItem));
19062
19495
  }
19063
19496
 
19497
+ // ../../src/resources/resources/resource-builder-error.ts
19498
+ var ResourceBuilderErrorCode = /* @__PURE__ */ ((ResourceBuilderErrorCode2) => {
19499
+ ResourceBuilderErrorCode2["InvalidServiceLink"] = "InvalidServiceLink";
19500
+ return ResourceBuilderErrorCode2;
19501
+ })(ResourceBuilderErrorCode || {});
19502
+ var ResourceBuilderError = class extends TypeError {
19503
+ /** Стабильная машинная причина отказа связи. */
19504
+ code;
19505
+ /** Сохраняет прежний текст TypeError и предоставляет машинный код. */
19506
+ constructor(code, message) {
19507
+ super(message);
19508
+ this.code = code;
19509
+ }
19510
+ };
19511
+
19064
19512
  // ../../src/resources/resources/resource-builder.ts
19065
19513
  function cloneValue2(value) {
19066
19514
  if (value instanceof Date) {
@@ -19096,21 +19544,30 @@ var ResourceBuilder = class _ResourceBuilder {
19096
19544
  attachToService(service, resourceGroupId, options) {
19097
19545
  const serviceId = service.id?.trim();
19098
19546
  if (!serviceId) {
19099
- throw new TypeError("Service must have a non-empty id");
19547
+ throw new ResourceBuilderError("InvalidServiceLink" /* InvalidServiceLink */, "Service must have a non-empty id");
19100
19548
  }
19101
19549
  const normalizedGroupId = resourceGroupId.trim();
19102
19550
  if (!normalizedGroupId) {
19103
- throw new TypeError("resourceGroupId must not be empty");
19551
+ throw new ResourceBuilderError("InvalidServiceLink" /* InvalidServiceLink */, "resourceGroupId must not be empty");
19104
19552
  }
19105
19553
  const group = service.resourceGroupList?.find((item) => item.groupId === normalizedGroupId);
19106
19554
  if (!group) {
19107
- throw new TypeError(`Service resource group not found: ${normalizedGroupId}`);
19555
+ throw new ResourceBuilderError(
19556
+ "InvalidServiceLink" /* InvalidServiceLink */,
19557
+ `Service resource group not found: ${normalizedGroupId}`
19558
+ );
19108
19559
  }
19109
19560
  if (!group.usageType) {
19110
- throw new TypeError("Service resource group has no usageType");
19561
+ throw new ResourceBuilderError(
19562
+ "InvalidServiceLink" /* InvalidServiceLink */,
19563
+ "Service resource group has no usageType"
19564
+ );
19111
19565
  }
19112
19566
  if (this.draft.usageType != null && this.draft.usageType !== group.usageType) {
19113
- throw new TypeError("Resource usageType does not match the service resource group");
19567
+ throw new ResourceBuilderError(
19568
+ "InvalidServiceLink" /* InvalidServiceLink */,
19569
+ "Resource usageType does not match the service resource group"
19570
+ );
19114
19571
  }
19115
19572
  const descriptions = [...this.draft.serviceDescriptions ?? []];
19116
19573
  const matching = descriptions.filter((item) => isSameBinding(item, serviceId, normalizedGroupId));
@@ -19297,6 +19754,8 @@ export {
19297
19754
  LoyaltyCardUpdateNonKeyInformationValues,
19298
19755
  LoyaltyCardsFacade,
19299
19756
  LoyaltySystemsFacade,
19757
+ NestedRidError,
19758
+ NestedRidErrorCode,
19300
19759
  NoteTypeValues,
19301
19760
  NotesFacade,
19302
19761
  OtpErrorReason,
@@ -19314,12 +19773,17 @@ export {
19314
19773
  RelationsFacade,
19315
19774
  ReportsFacade,
19316
19775
  ResourceBuilder,
19776
+ ResourceBuilderError,
19777
+ ResourceBuilderErrorCode,
19317
19778
  ResourcesFacade,
19318
19779
  SearchFacade,
19319
19780
  SendCodeAccountTypeValueList,
19320
19781
  SendCodeAccountTypeValues,
19321
19782
  ServiceBehaviorSettingsIssueReason,
19322
19783
  ServiceBuilder,
19784
+ ServiceBuilderError,
19785
+ ServiceBuilderErrorCode,
19786
+ ServiceBuilderRangeError,
19323
19787
  ServiceCheckInWizardStepParameterName,
19324
19788
  ServiceCheckInWizardStepType,
19325
19789
  ServiceOrderConflictErrorNameValues,