@torrow/sdk-client 0.19.0 → 0.22.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
@@ -10198,9 +10198,38 @@ function projectItemSocial(item) {
10198
10198
  return result;
10199
10199
  }
10200
10200
 
10201
+ // ../../src/resources/calendars/calendar-view-type.ts
10202
+ var CalendarViewTypeValues = /* @__PURE__ */ ((CalendarViewTypeValues2) => {
10203
+ CalendarViewTypeValues2[CalendarViewTypeValues2["Day"] = 0] = "Day";
10204
+ CalendarViewTypeValues2[CalendarViewTypeValues2["Poster"] = 4] = "Poster";
10205
+ CalendarViewTypeValues2[CalendarViewTypeValues2["Schedule"] = 5] = "Schedule";
10206
+ return CalendarViewTypeValues2;
10207
+ })(CalendarViewTypeValues || {});
10208
+ function normalizeCalendarViewIndex(value) {
10209
+ switch (value) {
10210
+ case 4 /* Poster */:
10211
+ return 4 /* Poster */;
10212
+ case 5 /* Schedule */:
10213
+ return 5 /* Schedule */;
10214
+ default:
10215
+ return 0 /* Day */;
10216
+ }
10217
+ }
10218
+
10201
10219
  // ../../src/resources/calendars/read-projection.ts
10202
10220
  function projectCalendarItem(item) {
10203
- return projectItemSocial(item);
10221
+ const projected = projectItemSocial(item);
10222
+ if (projected !== null && typeof projected === "object" && !Array.isArray(projected)) {
10223
+ const result = {
10224
+ ...projected,
10225
+ calendarViewIndex: normalizeCalendarViewIndex(
10226
+ "calendarViewIndex" in projected ? projected.calendarViewIndex : void 0
10227
+ )
10228
+ };
10229
+ Reflect.deleteProperty(result, "scheduleRangeExceptions");
10230
+ return result;
10231
+ }
10232
+ return projected;
10204
10233
  }
10205
10234
 
10206
10235
  // ../../src/resources/notes/read-projection.ts
@@ -10240,7 +10269,16 @@ function projectItemPrice(item) {
10240
10269
 
10241
10270
  // ../../src/resources/cases/read-projection.ts
10242
10271
  function projectCaseItem(item) {
10243
- 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;
10244
10282
  }
10245
10283
 
10246
10284
  // ../../src/resources/loyalty-cards/read-projection.ts
@@ -11928,6 +11966,12 @@ function patchPublicMessage(category, failureAt) {
11928
11966
  }
11929
11967
  }
11930
11968
  async function patchItem(http, itemId, fields, options, adapter) {
11969
+ return patchItemCore(http, itemId, fields, options, adapter);
11970
+ }
11971
+ async function patchDerivedItem(http, itemId, selector, options, adapter) {
11972
+ return patchItemCore(http, itemId, selector, options, adapter, adapter);
11973
+ }
11974
+ async function patchItemCore(http, itemId, input, options, adapter, derived) {
11931
11975
  let failureAt = "ValidateInput" /* ValidateInput */;
11932
11976
  let effect = "NotApplied" /* NotApplied */;
11933
11977
  const trustedErrors = /* @__PURE__ */ new Set();
@@ -11960,16 +12004,20 @@ async function patchItem(http, itemId, fields, options, adapter) {
11960
12004
  if (expectedVersion !== void 0 && !isVersion(expectedVersion) || Object.hasOwn(opts, "versionToCheck") && expectedVersion === void 0 || signal !== void 0 && !isAbortSignal(signal)) {
11961
12005
  throw localError("InvalidInput" /* InvalidInput */);
11962
12006
  }
11963
- const selected = copyValue(fields, /* @__PURE__ */ new Set(), [], adapter.ridPaths);
11964
- if (!isRecord(selected) || Object.keys(selected).length === 0) {
12007
+ const copied = copyValue(input, /* @__PURE__ */ new Set(), [], adapter.ridPaths);
12008
+ if (!isRecord(copied) || !derived && Object.keys(copied).length === 0) {
11965
12009
  throw localError("InvalidInput" /* InvalidInput */);
11966
12010
  }
11967
- for (const [key, value] of Object.entries(selected)) {
11968
- if (!Object.hasOwn(adapter.fields, key) || !validField(value, adapter.fields[key])) {
11969
- throw localError("InvalidInput" /* InvalidInput */);
12011
+ if (derived) {
12012
+ derived.validateSelector(copied);
12013
+ } else {
12014
+ for (const [key, value] of Object.entries(copied)) {
12015
+ if (!Object.hasOwn(adapter.fields, key) || !validField(value, adapter.fields[key])) {
12016
+ throw localError("InvalidInput" /* InvalidInput */);
12017
+ }
11970
12018
  }
12019
+ adapter.validateFields?.(copied);
11971
12020
  }
11972
- adapter.validateFields?.(selected);
11973
12021
  const readQuery = adapter.readQuery ? { ...adapter.readQuery } : void 0;
11974
12022
  const writeQuery = adapter.writeQuery ? { ...adapter.writeQuery } : void 0;
11975
12023
  if (signal?.aborted) {
@@ -12029,12 +12077,28 @@ async function patchItem(http, itemId, fields, options, adapter) {
12029
12077
  if (signal?.aborted) {
12030
12078
  throw localError("Cancelled" /* Cancelled */);
12031
12079
  }
12080
+ const selected = derived ? await derived.deriveSelectedFields(dto, copied, signal) : copied;
12081
+ if (!isRecord(selected) || Object.keys(selected).length === 0) {
12082
+ throw localError("InvalidInput" /* InvalidInput */);
12083
+ }
12084
+ for (const [key, value] of Object.entries(selected)) {
12085
+ if (!Object.hasOwn(adapter.fields, key) || !validField(value, adapter.fields[key])) {
12086
+ throw localError("InvalidInput" /* InvalidInput */);
12087
+ }
12088
+ }
12089
+ if (derived) {
12090
+ adapter.validateFields?.(selected);
12091
+ }
12092
+ if (signal?.aborted) {
12093
+ throw localError("Cancelled" /* Cancelled */);
12094
+ }
12095
+ Object.assign(selected, adapter.deriveFields?.(dto, selected));
12032
12096
  const unchanged = Object.entries(selected).every(([key, value]) => {
12033
12097
  const equal = adapter.equalField?.(key, dto[key], value, dto);
12034
12098
  if (equal !== void 0) {
12035
12099
  return equal;
12036
12100
  }
12037
- if (adapter.fields[key].kind === "Image" /* Image */ && isRecord(dto[key]) && isRecord(value)) {
12101
+ if (adapter.fields[key]?.kind === "Image" /* Image */ && isRecord(dto[key]) && isRecord(value)) {
12038
12102
  return dto[key].id === value.id;
12039
12103
  }
12040
12104
  return equalItemPatchValue(dto[key], value);
@@ -12083,6 +12147,7 @@ async function patchItem(http, itemId, fields, options, adapter) {
12083
12147
  if (!isRecord(ack) || ack.id !== itemId) {
12084
12148
  throw localError("InvalidResponse" /* InvalidResponse */);
12085
12149
  }
12150
+ adapter.assertAck?.(ack, prepared);
12086
12151
  effect = "Applied" /* Applied */;
12087
12152
  failureAt = "ProjectResult" /* ProjectResult */;
12088
12153
  return { itemId, item: projectItem(ack, adapter.project), changed: true };
@@ -12098,67 +12163,12 @@ async function patchItem(http, itemId, fields, options, adapter) {
12098
12163
  }
12099
12164
  }
12100
12165
 
12101
- // ../../src/resources/common/schedule-rids.ts
12102
- function record3(value) {
12103
- return value !== null && typeof value === "object" && !Array.isArray(value);
12104
- }
12105
- function normalizeRangeList(value, path) {
12106
- if (!Array.isArray(value)) {
12107
- return;
12108
- }
12109
- value.forEach((range, index) => {
12110
- if (record3(range)) {
12111
- ensureNestedRidForWrite(range, `${path}[${index}]`);
12112
- }
12113
- });
12114
- }
12115
- function normalizeScheduleRidsForWrite(value, path) {
12116
- if (!record3(value)) {
12117
- return;
12118
- }
12119
- normalizeRangeList(value.scheduleRanges, `${path}.scheduleRanges`);
12120
- const exceptions = value.scheduleRangeExceptions;
12121
- if (record3(exceptions)) {
12122
- normalizeRangeList(exceptions.replacedTimeRanges, `${path}.scheduleRangeExceptions.replacedTimeRanges`);
12123
- normalizeRangeList(exceptions.excludedTimeRanges, `${path}.scheduleRangeExceptions.excludedTimeRanges`);
12124
- }
12125
- }
12126
- function normalizeItemScheduleRidsForWrite(body, path) {
12127
- normalizeScheduleRidsForWrite(body.schedule, `${path}.schedule`);
12128
- const priceInfo = body.priceInfo;
12129
- if (!record3(priceInfo) || !Array.isArray(priceInfo.settings)) {
12130
- return;
12131
- }
12132
- priceInfo.settings.forEach((setting, index) => {
12133
- if (record3(setting)) {
12134
- normalizeScheduleRidsForWrite(setting.schedule, `${path}.priceInfo.settings[${index}].schedule`);
12135
- }
12136
- });
12137
- }
12138
-
12139
12166
  // ../../src/resources/calendars/calendar-patch.ts
12140
- function isRecord2(value) {
12141
- return value !== null && typeof value === "object" && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
12142
- }
12143
12167
  function isCalendarPatchViewIndex(value) {
12144
- return typeof value === "number" && Number.isInteger(value) && value >= -2147483648 && value <= 2147483647;
12145
- }
12146
- function isTimeRange(value, allowMissingRid = false) {
12147
- const rid2 = isRecord2(value) ? value.rid : void 0;
12148
- return isRecord2(value) && Object.keys(value).every((key) => ["rid", "begin", "end", "name"].includes(key)) && (isValidRid(rid2) || allowMissingRid && (rid2 == null || typeof rid2 === "string" && rid2.trim() === "")) && value.begin instanceof Date && Number.isFinite(value.begin.getTime()) && value.end instanceof Date && Number.isFinite(value.end.getTime()) && (value.name == null || typeof value.name === "string");
12149
- }
12150
- function isCalendarPatchExceptions(value) {
12151
- return isRecord2(value) && Object.keys(value).every((key) => ["replacedTimeRanges", "excludedTimeRanges"].includes(key)) && Object.values(value).every(
12152
- (ranges) => ranges == null || Array.isArray(ranges) && ranges.every((range) => isTimeRange(range))
12153
- );
12154
- }
12155
- function isCalendarPatchInputExceptions(value) {
12156
- return isRecord2(value) && Object.keys(value).every((key) => ["replacedTimeRanges", "excludedTimeRanges"].includes(key)) && Object.values(value).every(
12157
- (ranges) => ranges == null || Array.isArray(ranges) && ranges.every((range) => isTimeRange(range, true))
12158
- );
12168
+ return value === 0 /* Day */ || value === 4 /* Poster */ || value === 5 /* Schedule */;
12159
12169
  }
12160
12170
  function projectCalendarPatchItem(item) {
12161
- if (item.description != null && typeof item.description !== "string" || item.name != null && typeof item.name !== "string" || item.calendarViewIndex != null && !isCalendarPatchViewIndex(item.calendarViewIndex) || item.scheduleRangeExceptions != null && !isCalendarPatchExceptions(item.scheduleRangeExceptions)) {
12171
+ if (item.description != null && typeof item.description !== "string" || item.name != null && typeof item.name !== "string") {
12162
12172
  throw itemPatchError("InvalidResponse" /* InvalidResponse */);
12163
12173
  }
12164
12174
  return item;
@@ -12175,26 +12185,13 @@ function assertCalendarPatchSnapshot(item) {
12175
12185
  function createCalendarPatchAdapter() {
12176
12186
  return {
12177
12187
  operation: "CalendarsFacade.patch",
12178
- ridPaths: calendarPatchRidPaths,
12179
12188
  basePath: "/api/v1/calendars",
12180
12189
  objectType: TorrowObjectTypeCode.Calendar,
12181
12190
  discriminator: "CalendarItem" /* CalendarItem */,
12182
12191
  fields: {
12183
12192
  ...commonItemPatchFields,
12184
12193
  description: { kind: "String" /* String */, nullable: true },
12185
- calendarViewIndex: { kind: "Integer" /* Integer */, nullable: true, validate: isCalendarPatchViewIndex },
12186
- scheduleRangeExceptions: {
12187
- kind: "Object" /* Object */,
12188
- nullable: true,
12189
- validate: isCalendarPatchInputExceptions
12190
- }
12191
- },
12192
- validateFields: (fields) => {
12193
- try {
12194
- normalizeScheduleRidsForWrite(fields, "calendar");
12195
- } catch {
12196
- throw itemPatchError("InvalidInput" /* InvalidInput */);
12197
- }
12194
+ calendarViewIndex: { kind: "Integer" /* Integer */, validate: isCalendarPatchViewIndex }
12198
12195
  },
12199
12196
  assertSnapshot: assertCalendarPatchSnapshot,
12200
12197
  project: (item) => projectCalendarItem(projectCalendarPatchItem(item)),
@@ -12219,12 +12216,26 @@ var CalendarsFacade = class extends TorrowItemFacade {
12219
12216
  }
12220
12217
  /** Частично изменяет календарь: полный GET и максимум один CAS PUT, без deep merge/readback/retry. */
12221
12218
  patch(itemId, fields, options) {
12222
- return patchItem(this.http, itemId, fields, options, createCalendarPatchAdapter());
12219
+ let selected = fields;
12220
+ if (fields !== null && typeof fields === "object") {
12221
+ try {
12222
+ const view = Object.getOwnPropertyDescriptor(fields, "calendarViewIndex");
12223
+ if (view && Object.hasOwn(view, "value")) {
12224
+ const descriptors = Object.getOwnPropertyDescriptors(fields);
12225
+ descriptors.calendarViewIndex = { ...view, value: normalizeCalendarViewIndex(view.value) };
12226
+ selected = Object.create(Object.getPrototypeOf(fields), descriptors);
12227
+ }
12228
+ } catch {
12229
+ selected = fields;
12230
+ }
12231
+ }
12232
+ return patchItem(this.http, itemId, selected, options, createCalendarPatchAdapter());
12223
12233
  }
12224
12234
  /** `POST /api/v1/calendars` */
12225
12235
  create(body, options) {
12226
12236
  const payload = applyItemCreateDefaults(structuredClone(body), "CalendarItem" /* CalendarItem */, options?.publicityType);
12227
- normalizeScheduleRidsForWrite(payload, "calendar");
12237
+ payload.calendarViewIndex = normalizeCalendarViewIndex(payload.calendarViewIndex);
12238
+ Reflect.deleteProperty(payload, "scheduleRangeExceptions");
12228
12239
  return this.http.requestJson({
12229
12240
  method: "POST",
12230
12241
  path: BASE,
@@ -12240,7 +12251,8 @@ var CalendarsFacade = class extends TorrowItemFacade {
12240
12251
  update(body, options) {
12241
12252
  const itemId = requireItemUpdateId(body, "Calendar");
12242
12253
  const payload = structuredClone(body);
12243
- normalizeScheduleRidsForWrite(payload, "calendar");
12254
+ payload.calendarViewIndex = normalizeCalendarViewIndex(payload.calendarViewIndex);
12255
+ Reflect.deleteProperty(payload, "scheduleRangeExceptions");
12244
12256
  return this.http.requestJson({
12245
12257
  method: "PUT",
12246
12258
  path: `${BASE}/${encodePathSegment(itemId)}`,
@@ -12438,6 +12450,70 @@ function validateItemPricePatch(fields) {
12438
12450
  }
12439
12451
  }
12440
12452
 
12453
+ // ../../src/resources/common/item-patch-predicates.ts
12454
+ function isItemPatchDtoObject(value) {
12455
+ return value !== null && typeof value === "object" && !Array.isArray(value) && !(value instanceof Date);
12456
+ }
12457
+ function isItemPatchInt32(value) {
12458
+ return typeof value === "number" && Number.isInteger(value) && value >= -2147483648 && value <= 2147483647;
12459
+ }
12460
+ function isItemPatchReferenceId(value) {
12461
+ return typeof value === "string" && value.length > 0 && value.trim() === value;
12462
+ }
12463
+ function isItemPatchObjectArray(value) {
12464
+ return Array.isArray(value) && value.every(isItemPatchDtoObject);
12465
+ }
12466
+
12467
+ // ../../src/resources/common/schedule-rids.ts
12468
+ function record3(value) {
12469
+ return value !== null && typeof value === "object" && !Array.isArray(value);
12470
+ }
12471
+ function normalizeRangeList(value, path) {
12472
+ if (!Array.isArray(value)) {
12473
+ return;
12474
+ }
12475
+ value.forEach((range, index) => {
12476
+ if (record3(range)) {
12477
+ ensureNestedRidForWrite(range, `${path}[${index}]`);
12478
+ }
12479
+ });
12480
+ }
12481
+ function normalizeScheduleRidsForWrite(value, path) {
12482
+ if (!record3(value)) {
12483
+ return;
12484
+ }
12485
+ normalizeRangeList(value.scheduleRanges, `${path}.scheduleRanges`);
12486
+ const exceptions = value.scheduleRangeExceptions;
12487
+ if (record3(exceptions)) {
12488
+ normalizeRangeList(exceptions.replacedTimeRanges, `${path}.scheduleRangeExceptions.replacedTimeRanges`);
12489
+ normalizeRangeList(exceptions.excludedTimeRanges, `${path}.scheduleRangeExceptions.excludedTimeRanges`);
12490
+ }
12491
+ }
12492
+ function normalizeItemScheduleRidsForWrite(body, path) {
12493
+ normalizeScheduleRidsForWrite(body.schedule, `${path}.schedule`);
12494
+ const priceInfo = body.priceInfo;
12495
+ if (!record3(priceInfo) || !Array.isArray(priceInfo.settings)) {
12496
+ return;
12497
+ }
12498
+ priceInfo.settings.forEach((setting, index) => {
12499
+ if (record3(setting)) {
12500
+ normalizeScheduleRidsForWrite(setting.schedule, `${path}.priceInfo.settings[${index}].schedule`);
12501
+ }
12502
+ });
12503
+ }
12504
+
12505
+ // ../../src/resources/common/case-action-rids.ts
12506
+ function normalizeCaseActionRidsForWrite(body, path) {
12507
+ if (!Array.isArray(body.caseActionList)) {
12508
+ return;
12509
+ }
12510
+ body.caseActionList.forEach((action, index) => {
12511
+ if (action !== null && typeof action === "object" && !Array.isArray(action)) {
12512
+ ensureNestedRidForWrite(action, `${path}.caseActionList[${index}]`);
12513
+ }
12514
+ });
12515
+ }
12516
+
12441
12517
  // ../../src/resources/cases/types.ts
12442
12518
  var CaseStateValues = {
12443
12519
  Unknown: "UnknownCaseState",
@@ -12464,30 +12540,29 @@ var CaseTypeValues = {
12464
12540
  State: "State"
12465
12541
  };
12466
12542
 
12467
- // ../../src/resources/common/item-patch-predicates.ts
12468
- function isItemPatchDtoObject(value) {
12469
- return value !== null && typeof value === "object" && !Array.isArray(value) && !(value instanceof Date);
12470
- }
12471
- function isItemPatchInt32(value) {
12472
- return typeof value === "number" && Number.isInteger(value) && value >= -2147483648 && value <= 2147483647;
12473
- }
12474
- function isItemPatchReferenceId(value) {
12475
- return typeof value === "string" && value.length > 0 && value.trim() === value;
12543
+ // ../../src/resources/cases/case-create-visit-card.ts
12544
+ function isValidCaseCardType(value) {
12545
+ return value !== CaseTypeValues.Unknown && Object.values(CaseTypeValues).some((type) => type === value);
12476
12546
  }
12477
- function isItemPatchObjectArray(value) {
12478
- return Array.isArray(value) && value.every(isItemPatchDtoObject);
12479
- }
12480
-
12481
- // ../../src/resources/common/case-action-rids.ts
12482
- function normalizeCaseActionRidsForWrite(body, path) {
12483
- if (!Array.isArray(body.caseActionList)) {
12484
- return;
12485
- }
12486
- body.caseActionList.forEach((action, index) => {
12487
- if (action !== null && typeof action === "object" && !Array.isArray(action)) {
12488
- ensureNestedRidForWrite(action, `${path}.caseActionList[${index}]`);
12489
- }
12490
- });
12547
+ function createCaseVisitCard(source) {
12548
+ const { name, caseType, beginDate, endDate, place, description } = source;
12549
+ return {
12550
+ fields: [
12551
+ { number: 0, value: name ?? "", expression: JSON.stringify({ type: "Name" /* Name */ }) },
12552
+ {
12553
+ number: 1,
12554
+ value: caseType,
12555
+ expression: JSON.stringify({ type: "CaseType" /* CaseType */, caseType, beginDate, endDate })
12556
+ },
12557
+ {
12558
+ number: 2,
12559
+ value: (place ? place : description) ?? "",
12560
+ expression: JSON.stringify({
12561
+ type: place ? "PlaceAddress" /* PlaceAddress */ : "Description" /* Description */
12562
+ })
12563
+ }
12564
+ ]
12565
+ };
12491
12566
  }
12492
12567
 
12493
12568
  // ../../src/resources/cases/case-patch.ts
@@ -12497,19 +12572,6 @@ function optionalDate2(value) {
12497
12572
  function appendices(value) {
12498
12573
  return isItemPatchObjectArray(value) && value.every((item) => optionalDate2(item.openDate) && optionalDate2(item.closeDate));
12499
12574
  }
12500
- function visitCard(value) {
12501
- if (!isItemPatchDtoObject(value) || Object.keys(value).some((key) => key !== "fields")) {
12502
- return false;
12503
- }
12504
- if (value.fields == null) {
12505
- return true;
12506
- }
12507
- return Array.isArray(value.fields) && value.fields.every(
12508
- (field) => isItemPatchDtoObject(field) && Object.entries(field).every(
12509
- ([key, member]) => key === "number" ? isItemPatchInt32(member) : (key === "value" || key === "expression") && (member === null || typeof member === "string")
12510
- )
12511
- );
12512
- }
12513
12575
  function checkinPermission(value) {
12514
12576
  return isItemPatchDtoObject(value) && Object.entries(value).every(
12515
12577
  ([key, member]) => key === "userAccessLevel" ? Object.values(UserAccessLevelValues).some((level) => level === member) : key === "consumerMinTimeSecBetweenCasesInService" && (member === null || isItemPatchInt32(member))
@@ -12532,7 +12594,7 @@ function createCasePatchAdapter() {
12532
12594
  clientGroupId: { kind: "String" /* String */, nullable: true, validate: isItemPatchReferenceId },
12533
12595
  caseType: {
12534
12596
  kind: "String" /* String */,
12535
- validate: (value) => value !== CaseTypeValues.Unknown && Object.values(CaseTypeValues).some((type) => type === value)
12597
+ validate: isValidCaseCardType
12536
12598
  },
12537
12599
  schedule: { kind: "Object" /* Object */, nullable: true, validate: isItemPatchSchedule },
12538
12600
  registrationOpen: { kind: "Integer" /* Integer */, nullable: true, validate: isItemPatchInt32 },
@@ -12551,7 +12613,6 @@ function createCasePatchAdapter() {
12551
12613
  createSingleCases: { kind: "Boolean" /* Boolean */, nullable: true },
12552
12614
  checkinPermission: { kind: "Object" /* Object */, nullable: true, validate: checkinPermission },
12553
12615
  participateFieldRequirements: { kind: "Object" /* Object */, nullable: true },
12554
- visitCard: { kind: "Object" /* Object */, validate: visitCard },
12555
12616
  appendixList: { kind: "Array" /* Array */, nullable: true, validate: appendices },
12556
12617
  resourceGroupList: { kind: "Array" /* Array */, nullable: true, validate: isItemPatchObjectArray },
12557
12618
  caseActionList: { kind: "Array" /* Array */, nullable: true, validate: isItemPatchObjectArray },
@@ -12567,6 +12628,18 @@ function createCasePatchAdapter() {
12567
12628
  throw itemPatchError("InvalidInput" /* InvalidInput */);
12568
12629
  }
12569
12630
  },
12631
+ deriveFields: (dto, selected) => {
12632
+ const final = { ...dto, ...selected };
12633
+ if (!isValidCaseCardType(final.caseType)) {
12634
+ throw itemPatchError("InsufficientData" /* InsufficientData */);
12635
+ }
12636
+ return { visitCard: createCaseVisitCard(final) };
12637
+ },
12638
+ assertAck: (ack, written) => {
12639
+ if (!equalItemPatchValue(ack.visitCard, written.visitCard)) {
12640
+ throw itemPatchError("InvalidResponse" /* InvalidResponse */);
12641
+ }
12642
+ },
12570
12643
  project: (item) => projectCaseItem(item),
12571
12644
  casRefusal: isItemPatchCasRefusal
12572
12645
  };
@@ -12601,6 +12674,20 @@ function cancelCaseParticipation(http, torrowId, body, options) {
12601
12674
 
12602
12675
  // ../../src/resources/cases/CasesFacade.ts
12603
12676
  var BASE3 = "/api/v1/cases";
12677
+ var CARD_SOURCE_FIELDS = /* @__PURE__ */ new Set(["visitCard", "name", "caseType", "beginDate", "endDate", "place", "description"]);
12678
+ function affectsCaseCard(pointer) {
12679
+ if (typeof pointer !== "string" || pointer === "") {
12680
+ return true;
12681
+ }
12682
+ if (!pointer.startsWith("/")) {
12683
+ return true;
12684
+ }
12685
+ const first = pointer.slice(1).split("/")[0];
12686
+ if (/~(?![01])/.test(first)) {
12687
+ return true;
12688
+ }
12689
+ return CARD_SOURCE_FIELDS.has(first.replace(/~1/g, "/").replace(/~0/g, "~"));
12690
+ }
12604
12691
  var CasesFacade = class extends TorrowItemFacade {
12605
12692
  itemObjectTypeCode = TorrowObjectTypeCode.Case;
12606
12693
  /** Чтение полной карточки для метаданных без дочерних данных. */
@@ -12664,7 +12751,11 @@ var CasesFacade = class extends TorrowItemFacade {
12664
12751
  /** `PUT /api/v1/cases/{body.id}` */
12665
12752
  update(body, options) {
12666
12753
  const itemId = requireItemUpdateId(body, "Case");
12754
+ if (!isValidCaseCardType(body.caseType)) {
12755
+ throw new TorrowSdkError({ category: "InvalidInput" /* InvalidInput */ });
12756
+ }
12667
12757
  const payload = structuredClone(body);
12758
+ payload.visitCard = createCaseVisitCard(payload);
12668
12759
  normalizeItemScheduleRidsForWrite(payload, "case");
12669
12760
  normalizeCaseActionRidsForWrite(payload, "case");
12670
12761
  return this.http.requestJson({
@@ -12678,26 +12769,24 @@ var CasesFacade = class extends TorrowItemFacade {
12678
12769
  },
12679
12770
  body: payload,
12680
12771
  signal: options?.signal
12681
- }).then((dto) => projectCaseItem(dto));
12772
+ }).then((dto) => {
12773
+ if (dto === null || typeof dto !== "object" || Array.isArray(dto) || dto.id !== itemId || !equalItemPatchValue(dto.visitCard, payload.visitCard)) {
12774
+ throw new TorrowSdkError({ category: "InvalidResponse" /* InvalidResponse */ });
12775
+ }
12776
+ return projectCaseItem(dto);
12777
+ });
12682
12778
  }
12683
12779
  withCreateDefaults(body, publicityType) {
12684
12780
  const payload = applyItemCreateDefaults(structuredClone(body), "CaseItem" /* CaseItem */, publicityType);
12685
12781
  const prepared = {
12686
12782
  ...payload,
12687
12783
  caseState: payload.caseState ?? CaseStateValues.Verifying,
12688
- caseType: payload.caseType ?? CaseTypeValues.Time,
12689
- // Сервер отклоняет create без VisitCard («Parameter VisitCard cannot have value null»).
12690
- visitCard: payload.visitCard ?? {
12691
- fields: [
12692
- { number: 0, value: payload.name ?? "", expression: '{"type":"Name"}' },
12693
- { number: 1, value: "", expression: null },
12694
- { number: 2, value: "", expression: null }
12695
- ]
12696
- }
12784
+ caseType: payload.caseType ?? CaseTypeValues.Time
12697
12785
  };
12698
- normalizeItemScheduleRidsForWrite(prepared, "case");
12699
- normalizeCaseActionRidsForWrite(prepared, "case");
12700
- return prepared;
12786
+ const withCard = { ...prepared, visitCard: createCaseVisitCard(prepared) };
12787
+ normalizeItemScheduleRidsForWrite(withCard, "case");
12788
+ normalizeCaseActionRidsForWrite(withCard, "case");
12789
+ return withCard;
12701
12790
  }
12702
12791
  /** `DELETE /api/v1/cases/{torrowId}` */
12703
12792
  async delete(torrowId, options) {
@@ -12966,6 +13055,11 @@ var CasesFacade = class extends TorrowItemFacade {
12966
13055
  }
12967
13056
  /** `POST /api/v1/cases/{torrowId}/patch` */
12968
13057
  patchCase(torrowId, body, options) {
13058
+ if (!Array.isArray(body?.patchDoc?.operations) || body.patchDoc.operations.some(
13059
+ (operation) => affectsCaseCard(operation.path) || operation.from != null && affectsCaseCard(operation.from)
13060
+ )) {
13061
+ throw new TorrowSdkError({ category: "InvalidInput" /* InvalidInput */ });
13062
+ }
12969
13063
  return this.http.requestJson({
12970
13064
  method: "POST",
12971
13065
  path: `${BASE3}/${encodePathSegment(torrowId)}/patch`,
@@ -13036,11 +13130,11 @@ function contactVisitCardDefaultSlot0Value(body) {
13036
13130
  return trimNonEmptyString(body.company) ?? "";
13037
13131
  }
13038
13132
  function normalizeContactVisitCardFieldsForWrite(body) {
13039
- let visitCard3 = body.visitCard;
13040
- if (visitCard3 === void 0 || visitCard3 === null || typeof visitCard3 !== "object" || Array.isArray(visitCard3)) {
13041
- visitCard3 = {};
13133
+ let visitCard2 = body.visitCard;
13134
+ if (visitCard2 === void 0 || visitCard2 === null || typeof visitCard2 !== "object" || Array.isArray(visitCard2)) {
13135
+ visitCard2 = {};
13042
13136
  }
13043
- let incoming = Array.isArray(visitCard3.fields) ? visitCard3.fields : [];
13137
+ let incoming = Array.isArray(visitCard2.fields) ? visitCard2.fields : [];
13044
13138
  if (incoming.length === 0) {
13045
13139
  incoming = [
13046
13140
  {
@@ -13068,7 +13162,7 @@ function normalizeContactVisitCardFieldsForWrite(body) {
13068
13162
  for (let i = 0; i < CONTACT_VISIT_CARD_SLOT_COUNT; i++) {
13069
13163
  fields.push(picked[i] ?? { number: i, value: "" });
13070
13164
  }
13071
- body.visitCard = { ...visitCard3, fields };
13165
+ body.visitCard = { ...visitCard2, fields };
13072
13166
  }
13073
13167
 
13074
13168
  // ../../src/resources/contacts/types.ts
@@ -13156,7 +13250,7 @@ var memorableDateShape = {
13156
13250
  order: integer
13157
13251
  };
13158
13252
  var file = (value) => shape(value, { id: (value2) => typeof value2 === "string" && value2.length > 0 }) && record4(value) && Object.hasOwn(value, "id");
13159
- var visitCard2 = (value) => shape(value, {
13253
+ var visitCard = (value) => shape(value, {
13160
13254
  fields: nullable(
13161
13255
  (value2) => Array.isArray(value2) && value2.every((child) => shape(child, { number: integer, value: nullable(text), expression: nullable(text) }))
13162
13256
  )
@@ -13233,7 +13327,7 @@ function createContactPatchAdapter() {
13233
13327
  validate: arrayOf((value) => shape(value, memorableDateShape))
13234
13328
  },
13235
13329
  photos: { kind: "Array" /* Array */, nullable: true, validate: arrayOf(file) },
13236
- visitCard: { kind: "Object" /* Object */, validate: visitCard2 }
13330
+ visitCard: { kind: "Object" /* Object */, validate: visitCard }
13237
13331
  },
13238
13332
  validateFields(fields) {
13239
13333
  selected = structuredClone(fields);
@@ -14473,6 +14567,9 @@ var resourceItemPatchFields = {
14473
14567
  kind: "String" /* String */,
14474
14568
  validate: (value) => Object.values(UsageTypeValues).some((type) => type === value)
14475
14569
  },
14570
+ // Это полная замена списка. Нельзя собирать одно изменение связи снаружи и передавать
14571
+ // сюда массив: внутренний GET/CAS не защитит изменения между внешним и внутренним чтением.
14572
+ // upsertServiceLink/removeServiceLink вычисляют список из собственного raw GET.
14476
14573
  serviceDescriptions: { kind: "Array" /* Array */, validate: isItemPatchObjectArray },
14477
14574
  code: { kind: "String" /* String */, nullable: true },
14478
14575
  duration: { kind: "Integer" /* Integer */, nullable: true, validate: isItemPatchInt32 },
@@ -14511,6 +14608,225 @@ function createResourcePatchAdapter(project) {
14511
14608
  };
14512
14609
  }
14513
14610
 
14611
+ // ../../src/resources/resources/resource-service-link.ts
14612
+ var preservedRootFields = [
14613
+ "name",
14614
+ "description",
14615
+ "contactId",
14616
+ "parentResourceId",
14617
+ "calendarId",
14618
+ "itemId",
14619
+ "timetableId",
14620
+ "schedule",
14621
+ "priceInfo",
14622
+ "usageType",
14623
+ "code",
14624
+ "duration",
14625
+ "amountProperties",
14626
+ "usageCondition",
14627
+ "appendixList",
14628
+ "paymentProperties",
14629
+ "ticketProperties",
14630
+ "loyaltyTransactionPropertiesList",
14631
+ "tags",
14632
+ "uniqueName",
14633
+ "image",
14634
+ "publicityType",
14635
+ "searchMode",
14636
+ "anyoneAccess",
14637
+ "feedbackOptions",
14638
+ "integrationIds"
14639
+ ];
14640
+ function invalidInput() {
14641
+ throw itemPatchError("InvalidInput" /* InvalidInput */);
14642
+ }
14643
+ function insufficientData() {
14644
+ throw itemPatchError("InsufficientData" /* InsufficientData */);
14645
+ }
14646
+ function invalidResponse() {
14647
+ throw itemPatchError("InvalidResponse" /* InvalidResponse */);
14648
+ }
14649
+ function validateSelector(selector) {
14650
+ if (Object.keys(selector).some((key) => !["action", "serviceId", "resourceGroupId", "fields"].includes(key))) {
14651
+ invalidInput();
14652
+ }
14653
+ if (selector.action !== "Upsert" /* Upsert */ && selector.action !== "Remove" /* Remove */) {
14654
+ invalidInput();
14655
+ }
14656
+ try {
14657
+ if (getTorrowObjectTypeFromTorrowId(selector.serviceId) !== "Service") {
14658
+ invalidInput();
14659
+ }
14660
+ } catch {
14661
+ invalidInput();
14662
+ }
14663
+ if (typeof selector.resourceGroupId !== "string" || selector.resourceGroupId.length === 0) {
14664
+ invalidInput();
14665
+ }
14666
+ if (selector.fields === null || typeof selector.fields !== "object" || Array.isArray(selector.fields)) {
14667
+ invalidInput();
14668
+ }
14669
+ if (selector.action === "Remove" /* Remove */ && Object.keys(selector.fields).length > 0) {
14670
+ invalidInput();
14671
+ }
14672
+ for (const [key, value] of Object.entries(selector.fields)) {
14673
+ if (key === "usageAmount") {
14674
+ if (value !== null && (typeof value !== "number" || !Number.isFinite(value))) {
14675
+ invalidInput();
14676
+ }
14677
+ } else if (key === "sortIndex") {
14678
+ if (value !== null && (typeof value !== "number" || !Number.isInteger(value) || value < -2147483648 || value > 2147483647)) {
14679
+ invalidInput();
14680
+ }
14681
+ } else {
14682
+ invalidInput();
14683
+ }
14684
+ }
14685
+ }
14686
+ function checkedDescriptions(dto) {
14687
+ const list = dto.serviceDescriptions;
14688
+ if (list == null || Array.isArray(list) && list.length === 0) {
14689
+ insufficientData();
14690
+ }
14691
+ if (!Array.isArray(list)) {
14692
+ invalidResponse();
14693
+ }
14694
+ const seen = /* @__PURE__ */ new Set();
14695
+ for (const binding of list) {
14696
+ if (binding === null || typeof binding !== "object" || Array.isArray(binding) || typeof binding.id !== "string" || typeof binding.resourceGroupId !== "string" || binding.resourceGroupId.length === 0) {
14697
+ invalidResponse();
14698
+ }
14699
+ try {
14700
+ if (getTorrowObjectTypeFromTorrowId(binding.id) !== "Service") {
14701
+ invalidResponse();
14702
+ }
14703
+ } catch {
14704
+ invalidResponse();
14705
+ }
14706
+ 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)) {
14707
+ invalidResponse();
14708
+ }
14709
+ const pair = `${binding.id.length}:${binding.id}${binding.resourceGroupId}`;
14710
+ if (seen.has(pair)) {
14711
+ invalidResponse();
14712
+ }
14713
+ seen.add(pair);
14714
+ }
14715
+ return list;
14716
+ }
14717
+ function samePair(binding, selector) {
14718
+ return binding.id === selector.serviceId && binding.resourceGroupId === selector.resourceGroupId;
14719
+ }
14720
+ async function changeResourceServiceLink(http, project, resourceId, selector, options) {
14721
+ let before;
14722
+ let expected;
14723
+ let acknowledged;
14724
+ const adapter = createResourcePatchAdapter(project);
14725
+ const result = await patchDerivedItem(http, resourceId, selector, options, {
14726
+ ...adapter,
14727
+ operation: selector.action === "Upsert" /* Upsert */ ? "ResourcesFacade.upsertServiceLink" : "ResourcesFacade.removeServiceLink",
14728
+ validateSelector,
14729
+ async deriveSelectedFields(dto, selected, signal) {
14730
+ const list2 = checkedDescriptions(dto);
14731
+ before = dto;
14732
+ const at = list2.findIndex((binding) => samePair(binding, selected));
14733
+ if (selected.action === "Remove" /* Remove */) {
14734
+ if (at < 0) {
14735
+ expected = list2;
14736
+ return { serviceDescriptions: list2 };
14737
+ }
14738
+ if (list2.length === 1) {
14739
+ insufficientData();
14740
+ }
14741
+ expected = list2.filter((_, index) => index !== at);
14742
+ return { serviceDescriptions: expected };
14743
+ }
14744
+ if (signal?.aborted) {
14745
+ throw itemPatchError("Cancelled" /* Cancelled */);
14746
+ }
14747
+ const service = await http.requestJson({
14748
+ method: "GET",
14749
+ path: `/api/v1/services/${encodePathSegment(selected.serviceId)}`,
14750
+ signal
14751
+ });
14752
+ if (service === null || typeof service !== "object" || Array.isArray(service) || service.id !== selected.serviceId) {
14753
+ invalidResponse();
14754
+ }
14755
+ const groups = service.resourceGroupList;
14756
+ if (!Array.isArray(groups)) {
14757
+ insufficientData();
14758
+ }
14759
+ const matchingGroups = groups.filter((item) => item?.groupId === selected.resourceGroupId);
14760
+ if (matchingGroups.length > 1) {
14761
+ invalidResponse();
14762
+ }
14763
+ const group = matchingGroups[0];
14764
+ if (!group || typeof group.usageType !== "string" || group.usageType.length === 0 || typeof group.groupName !== "string" || typeof service.name !== "string") {
14765
+ insufficientData();
14766
+ }
14767
+ if (group.usageType === UsageTypeValues.Unknown || !Object.values(UsageTypeValues).some((value) => value === group.usageType)) {
14768
+ invalidResponse();
14769
+ }
14770
+ if (dto.usageType !== group.usageType) {
14771
+ invalidInput();
14772
+ }
14773
+ const next = [...list2];
14774
+ if (at < 0) {
14775
+ next.push({
14776
+ id: selected.serviceId,
14777
+ resourceGroupId: selected.resourceGroupId,
14778
+ serviceName: service.name,
14779
+ resourceGroupName: group.groupName,
14780
+ laterBinding: group.bookingProperties != null,
14781
+ ...selected.fields
14782
+ });
14783
+ } else {
14784
+ next[at] = { ...list2[at], ...selected.fields };
14785
+ }
14786
+ expected = next;
14787
+ return { serviceDescriptions: next };
14788
+ },
14789
+ assertAck(ack, written) {
14790
+ if (!before || !expected || !Array.isArray(ack.serviceDescriptions) || !equalItemPatchValue(ack.serviceDescriptions, expected) || !Number.isInteger(ack.meta?.version) || (ack.meta?.version ?? 0) <= 0) {
14791
+ invalidResponse();
14792
+ }
14793
+ const rawAck = ack;
14794
+ const rawWritten = written;
14795
+ for (const key of preservedRootFields) {
14796
+ if (Object.hasOwn(before, key) && !equalItemPatchValue(rawAck[key], rawWritten[key])) {
14797
+ invalidResponse();
14798
+ }
14799
+ }
14800
+ acknowledged = ack.serviceDescriptions;
14801
+ }
14802
+ });
14803
+ const list = result.changed ? acknowledged : before.serviceDescriptions;
14804
+ return {
14805
+ ...result,
14806
+ serviceId: selector.serviceId,
14807
+ resourceGroupId: selector.resourceGroupId,
14808
+ binding: list.find((binding) => samePair(binding, selector)) ?? null
14809
+ };
14810
+ }
14811
+ function upsertResourceServiceLink(http, project, resourceId, serviceId, resourceGroupId, fields, options) {
14812
+ return changeResourceServiceLink(
14813
+ http,
14814
+ project,
14815
+ resourceId,
14816
+ { action: "Upsert" /* Upsert */, serviceId, resourceGroupId, fields },
14817
+ options
14818
+ );
14819
+ }
14820
+ function removeResourceServiceLink(http, project, resourceId, serviceId, resourceGroupId, options) {
14821
+ return changeResourceServiceLink(
14822
+ http,
14823
+ project,
14824
+ resourceId,
14825
+ { action: "Remove" /* Remove */, serviceId, resourceGroupId, fields: {} },
14826
+ options
14827
+ );
14828
+ }
14829
+
14514
14830
  // ../../src/resources/resources/ResourcesFacade.ts
14515
14831
  var BASE7 = "/api/v1/resources";
14516
14832
  var ResourcesFacade = class extends TorrowItemFacade {
@@ -14541,6 +14857,35 @@ var ResourcesFacade = class extends TorrowItemFacade {
14541
14857
  createResourcePatchAdapter((item) => this.toSdkResourceItem(item))
14542
14858
  );
14543
14859
  }
14860
+ /**
14861
+ * Адресно добавляет или изменяет одну связь при полном непустом списке.
14862
+ * Предполагается, что Service не изменяется в течение вызова; CAS защищает Resource.
14863
+ * Серверный отказ проверки Service при PUT передаётся как TorrowSdkError с HTTP-данными.
14864
+ * Проверка Service не атомарна с записью Resource.
14865
+ * При неизвестном результате PUT требуется отдельная сверка, автоматического повтора нет.
14866
+ */
14867
+ upsertServiceLink(resourceId, serviceId, resourceGroupId, fields, options) {
14868
+ return upsertResourceServiceLink(
14869
+ this.http,
14870
+ (item) => this.toSdkResourceItem(item),
14871
+ resourceId,
14872
+ serviceId,
14873
+ resourceGroupId,
14874
+ fields,
14875
+ options
14876
+ );
14877
+ }
14878
+ /** Удаляет одну связь, если после неё остаётся непустой подтверждённый список. */
14879
+ removeServiceLink(resourceId, serviceId, resourceGroupId, options) {
14880
+ return removeResourceServiceLink(
14881
+ this.http,
14882
+ (item) => this.toSdkResourceItem(item),
14883
+ resourceId,
14884
+ serviceId,
14885
+ resourceGroupId,
14886
+ options
14887
+ );
14888
+ }
14544
14889
  /** Поиск по уникальному имени возвращает ту же модель ресурса, что и getById. */
14545
14890
  getByUniqueName(uniqueName, options) {
14546
14891
  return this.readByUniqueName(uniqueName, options).then((item) => this.toSdkResourceItem(item));
@@ -15515,11 +15860,13 @@ var ServicesFacade = class extends TorrowItemFacade {
15515
15860
  }
15516
15861
  /** `POST /api/v1/services/{serviceId}/session` — создать сессию записи (тело `CaseItem`). */
15517
15862
  createSession(serviceId, body, options) {
15863
+ const payload = { ...structuredClone(body), caseType: body.caseType ?? CaseTypeValues.Time };
15864
+ payload.visitCard = createCaseVisitCard(payload);
15518
15865
  return this.http.requestJson({
15519
15866
  method: "POST",
15520
15867
  path: `${BASE9}/${encodePathSegment(serviceId)}/session`,
15521
15868
  query: { profileId: options?.profileId },
15522
- body,
15869
+ body: payload,
15523
15870
  signal: options?.signal
15524
15871
  }).then((dto) => projectCaseItem(dto));
15525
15872
  }
@@ -19243,6 +19590,7 @@ export {
19243
19590
  AvailableResourcesValues,
19244
19591
  BehaviorSettingsEffectStep,
19245
19592
  BlockReasonsFacade,
19593
+ CalendarViewTypeValues,
19246
19594
  CalendarsFacade,
19247
19595
  CaseStateValues,
19248
19596
  CaseTypeValues,