azure-mock 2.35.0 → 2.36.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
@@ -1,6 +1,6 @@
1
+ import { RestError, createHttpHeaders, createPipelineRequest } from "@azure/core-rest-pipeline";
1
2
  import { toHttpHeadersLike } from "@azure/core-http-compat";
2
- import { ID_SEPARATOR, InvalidOperationError, Operation, exhaustiveGuard, getOrCreate, getResultAsync, html, noop, streamToText, takeOne } from "@esposter/shared";
3
- import { createHttpHeaders, createPipelineRequest } from "@azure/core-rest-pipeline";
3
+ import { ID_SEPARATOR, InvalidOperationError, Operation, exhaustiveGuard, getOrCreate, getResult, html, noop, streamToText, takeOne } from "@esposter/shared";
4
4
  import { AnonymousCredential } from "@azure/storage-blob";
5
5
  import { Readable } from "node:stream";
6
6
  import { MAX_QUEUE_VISIBILITY_TIMEOUT_MS, deserializeClause, deserializeKey, getTableNullClause, serializeClauses } from "@esposter/db";
@@ -22,7 +22,7 @@ var __copyProps = (to, from, except, desc) => {
22
22
  }
23
23
  return to;
24
24
  };
25
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
25
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
26
26
  value: mod,
27
27
  enumerable: true
28
28
  }) : target, mod));
@@ -30,12 +30,10 @@ const MOCK_BLOB_BASE_URL = "https://mockaccount.blob.core.windows.net";
30
30
  const MOCK_QUEUE_BASE_URL = "https://mockaccount.queue.core.windows.net";
31
31
  const MOCK_SEARCH_BASE_URL = "https://mockaccount.search.windows.net";
32
32
  const MOCK_TABLE_BASE_URL = "https://mockaccount.table.core.windows.net";
33
- var MockRestError = class extends Error {
34
- statusCode;
33
+ var MockRestError = class extends RestError {
35
34
  constructor(message, statusCode) {
36
- super(message);
35
+ super(message, { statusCode });
37
36
  this.name = "MockRestError";
38
- this.statusCode = statusCode;
39
37
  }
40
38
  };
41
39
  const toWebResourceLike = (request) => ({
@@ -70,7 +68,16 @@ const createMockResponse = (status, url = "") => ({
70
68
  status
71
69
  });
72
70
  const getMockSasUrl = (url, permissions, resourceType) => `${url}?sv=2025-11-05&${resourceType ? `sr=${resourceType}&` : ""}sig=mock-signature&st=1970-01-01T00:00:00Z&se=2099-12-31T23:59:59Z&sp=${permissions?.toString() ?? "r"}`;
73
- const MockContainerDatabase = /* @__PURE__ */ new Map();
71
+ const MockContainerCreatedOnDatabase = /* @__PURE__ */ new Map();
72
+ const MOCK_BLOB_SEEDED_CREATED_ON = /* @__PURE__ */ new Date(-864e13);
73
+ const getMockContainerCreatedOnKey = (containerName, blobName) => `${containerName}/${blobName}`;
74
+ var MockContainerDatabaseMap = class extends Map {
75
+ clear() {
76
+ super.clear();
77
+ MockContainerCreatedOnDatabase.clear();
78
+ }
79
+ };
80
+ const MockContainerDatabase = new MockContainerDatabaseMap();
74
81
  const MockEventGridDatabase = /* @__PURE__ */ new Map();
75
82
  const MockQueueDatabase = /* @__PURE__ */ new Map();
76
83
  const MockSearchDatabase = /* @__PURE__ */ new Map();
@@ -87,6 +94,17 @@ const getAzureErrorXml = (errorCode, errorMessage) => html`<?xml version="1.0" e
87
94
  <code>${errorCode}</code>
88
95
  <Message>${errorMessage}</Message>
89
96
  </Error>`;
97
+ const decodeSegment = (segment) => getResult(() => decodeURIComponent(segment)).unwrapOr(segment);
98
+ const getBlobUrlParts = (url) => {
99
+ const parsedUrl = getResult(() => new URL(url)).unwrapOr(void 0);
100
+ if (!parsedUrl) return void 0;
101
+ const pathSegments = parsedUrl.pathname.split("/").filter(Boolean);
102
+ if (pathSegments.length < 2) return void 0;
103
+ return {
104
+ blobName: decodeSegment(pathSegments.slice(1).join("/")),
105
+ containerName: decodeSegment(takeOne(pathSegments))
106
+ };
107
+ };
90
108
  var MockBlobBatchClient = class {
91
109
  url;
92
110
  constructor(url) {
@@ -103,8 +121,8 @@ var MockBlobBatchClient = class {
103
121
  let subResponsesSucceededCount = 0;
104
122
  let subResponsesFailedCount = 0;
105
123
  for (const url of urls) {
106
- const pathSegments = new URL(url).pathname.split("/").filter(Boolean);
107
- if (pathSegments.length < 2) {
124
+ const urlParts = getBlobUrlParts(url);
125
+ if (!urlParts) {
108
126
  const errorCode = "InvalidUri";
109
127
  const statusMessage = "Invalid blob URL format.";
110
128
  subResponses.push({
@@ -121,11 +139,11 @@ var MockBlobBatchClient = class {
121
139
  subResponsesFailedCount++;
122
140
  continue;
123
141
  }
124
- const containerName = takeOne(pathSegments);
125
- const blobName = pathSegments.slice(1).join("/");
142
+ const { blobName, containerName } = urlParts;
126
143
  const container = this.getContainer(containerName);
127
144
  if (container.has(blobName)) {
128
145
  container.delete(blobName);
146
+ MockContainerCreatedOnDatabase.delete(getMockContainerCreatedOnKey(containerName, blobName));
129
147
  subResponses.push({
130
148
  _request: {
131
149
  credential,
@@ -170,6 +188,7 @@ var MockBlobBatchClient = class {
170
188
  return getOrCreate(MockContainerDatabase, containerName, () => /* @__PURE__ */ new Map());
171
189
  }
172
190
  };
191
+ const getBlobUrl = (containerName, blobName) => `${MOCK_BLOB_BASE_URL}/${containerName}/${blobName.split("/").map((segment) => encodeURIComponent(segment)).join("/")}`;
173
192
  var MockBlobClient = class {
174
193
  connectionString;
175
194
  containerName;
@@ -183,21 +202,21 @@ var MockBlobClient = class {
183
202
  this.connectionString = connectionString;
184
203
  this.containerName = containerName;
185
204
  this.name = blobName;
186
- this.url = `${MOCK_BLOB_BASE_URL}/${this.containerName}/${this.name}`;
205
+ this.url = getBlobUrl(this.containerName, this.name);
187
206
  }
188
207
  abortCopyFromURL() {
189
208
  throw new Error("Method not implemented.");
190
209
  }
191
210
  beginCopyFromURL(copySource) {
192
- const pathSegments = new URL(copySource).pathname.split("/").filter(Boolean);
193
- if (pathSegments.length < 2) throw new MockRestError("Invalid copy source URL format", 400);
194
- const sourceContainerName = takeOne(pathSegments);
195
- const sourceBlobName = pathSegments.slice(1).join("/");
211
+ const sourceParts = getBlobUrlParts(copySource);
212
+ if (!sourceParts) throw new MockRestError("Invalid copy source URL format", 400);
213
+ const { blobName: sourceBlobName, containerName: sourceContainerName } = sourceParts;
196
214
  const sourceContainer = MockContainerDatabase.get(sourceContainerName);
197
215
  if (!sourceContainer) throw new MockRestError("Source container not found", 404);
198
216
  const sourceData = sourceContainer.get(sourceBlobName);
199
217
  if (!sourceData) throw new MockRestError("Source blob not found", 404);
200
218
  this.container.set(this.name, Buffer.from(sourceData));
219
+ MockContainerCreatedOnDatabase.set(getMockContainerCreatedOnKey(this.containerName, this.name), /* @__PURE__ */ new Date());
201
220
  const response = { _response: createMockResponse(202, `${this.url}?comp=copy`) };
202
221
  return Promise.resolve({
203
222
  cancelOperation: () => Promise.resolve(),
@@ -220,11 +239,15 @@ var MockBlobClient = class {
220
239
  delete() {
221
240
  if (!this.container.has(this.name)) throw new MockRestError("The specified blob does not exist.", 404);
222
241
  this.container.delete(this.name);
242
+ MockContainerCreatedOnDatabase.delete(getMockContainerCreatedOnKey(this.containerName, this.name));
223
243
  return Promise.resolve({ _response: createMockResponse(200) });
224
244
  }
225
245
  deleteIfExists() {
226
246
  const succeeded = this.container.has(this.name);
227
- if (succeeded) this.container.delete(this.name);
247
+ if (succeeded) {
248
+ this.container.delete(this.name);
249
+ MockContainerCreatedOnDatabase.delete(getMockContainerCreatedOnKey(this.containerName, this.name));
250
+ }
228
251
  return Promise.resolve({
229
252
  _response: createMockResponse(succeeded ? 200 : 404),
230
253
  succeeded
@@ -249,7 +272,7 @@ var MockBlobClient = class {
249
272
  throw new Error("Method not implemented.");
250
273
  }
251
274
  exists() {
252
- throw new Error("Method not implemented.");
275
+ return Promise.resolve(this.container.has(this.name));
253
276
  }
254
277
  generateSasStringToSign() {
255
278
  throw new Error("Method not implemented.");
@@ -362,8 +385,11 @@ var MockBlockBlobClient = class extends MockBlobClient {
362
385
  syncUploadFromURL() {
363
386
  throw new Error("Method not implemented.");
364
387
  }
365
- async upload(body, _contentLength) {
366
- this.container.set(this.name, await bodyToBuffer(body));
388
+ async upload(body, _contentLength, options) {
389
+ const buffer = await bodyToBuffer(body);
390
+ if (options?.conditions?.ifNoneMatch === "*" && this.container.has(this.name)) throw new MockRestError("The specified blob already exists.", 409);
391
+ this.container.set(this.name, buffer);
392
+ MockContainerCreatedOnDatabase.set(getMockContainerCreatedOnKey(this.containerName, this.name), /* @__PURE__ */ new Date());
367
393
  return { _response: createMockResponse(201) };
368
394
  }
369
395
  uploadBrowserData() {
@@ -438,7 +464,8 @@ var MockContainerClient = class {
438
464
  deleteBlob(blobName) {
439
465
  if (!this.container.has(blobName)) throw new MockRestError("The specified blob does not exist.", 404);
440
466
  this.container.delete(blobName);
441
- return Promise.resolve({ _response: createMockResponse(200, `${this.url}/${blobName}`) });
467
+ MockContainerCreatedOnDatabase.delete(getMockContainerCreatedOnKey(this.containerName, blobName));
468
+ return Promise.resolve({ _response: createMockResponse(200, getBlobUrl(this.containerName, blobName)) });
442
469
  }
443
470
  deleteIfExists() {
444
471
  throw new Error("Method not implemented.");
@@ -528,8 +555,8 @@ var MockContainerClient = class {
528
555
  }
529
556
  };
530
557
  }
531
- listBlobsFlat() {
532
- const blobItemIterator = this.#getBlobItemIterator();
558
+ listBlobsFlat(options) {
559
+ const blobItemIterator = this.#getBlobItemIterator(options);
533
560
  return {
534
561
  byPage: () => async function* () {
535
562
  const allBlobItems = [];
@@ -545,14 +572,14 @@ var MockContainerClient = class {
545
572
  parsedBody: {
546
573
  containerName: this.containerName,
547
574
  marker: "",
548
- prefix: "",
575
+ prefix: options?.prefix ?? "",
549
576
  segment: { blobItems: allBlobItems },
550
577
  serviceEndpoint: ""
551
578
  }
552
579
  },
553
580
  containerName: this.containerName,
554
581
  marker: "",
555
- prefix: "",
582
+ prefix: options?.prefix ?? "",
556
583
  segment: { blobItems: allBlobItems },
557
584
  serviceEndpoint: ""
558
585
  });
@@ -591,6 +618,7 @@ var MockContainerClient = class {
591
618
  blobType: "BlockBlob",
592
619
  contentLength: buffer.length,
593
620
  contentType: "application/octet-stream",
621
+ createdOn: MockContainerCreatedOnDatabase.get(getMockContainerCreatedOnKey(this.containerName, name)) ?? MOCK_BLOB_SEEDED_CREATED_ON,
594
622
  etag: `"${crypto.randomUUID()}"`,
595
623
  lastModified: /* @__PURE__ */ new Date(),
596
624
  leaseState: "available",
@@ -612,21 +640,26 @@ var MockContainerClient = class {
612
640
  ...blobItem
613
641
  });
614
642
  }
615
- async *#getBlobItemIterator() {
616
- for (const [name, buffer] of this.container.entries()) yield await Promise.resolve({
617
- deleted: false,
618
- name,
619
- properties: {
620
- blobType: "BlockBlob",
621
- contentLength: buffer.length,
622
- contentType: "application/octet-stream",
623
- etag: `"${crypto.randomUUID()}"`,
624
- lastModified: /* @__PURE__ */ new Date(),
625
- leaseState: "available",
626
- leaseStatus: "unlocked"
627
- },
628
- snapshot: ""
629
- });
643
+ async *#getBlobItemIterator(options) {
644
+ const prefix = options?.prefix ?? "";
645
+ for (const [name, buffer] of this.container.entries()) {
646
+ if (!name.startsWith(prefix)) continue;
647
+ yield await Promise.resolve({
648
+ deleted: false,
649
+ name,
650
+ properties: {
651
+ blobType: "BlockBlob",
652
+ contentLength: buffer.length,
653
+ contentType: "application/octet-stream",
654
+ createdOn: MockContainerCreatedOnDatabase.get(getMockContainerCreatedOnKey(this.containerName, name)) ?? MOCK_BLOB_SEEDED_CREATED_ON,
655
+ etag: `"${crypto.randomUUID()}"`,
656
+ lastModified: /* @__PURE__ */ new Date(),
657
+ leaseState: "available",
658
+ leaseStatus: "unlocked"
659
+ },
660
+ snapshot: ""
661
+ });
662
+ }
630
663
  }
631
664
  };
632
665
  /**
@@ -837,7 +870,8 @@ var import_fast_deep_equal = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJS
837
870
  };
838
871
  })))(), 1);
839
872
  const isNullClause = (clause) => {
840
- return (0, import_fast_deep_equal.default)(clause, getTableNullClause(clause.key));
873
+ const tableNullClause = getTableNullClause(clause.key);
874
+ return (0, import_fast_deep_equal.default)(clause, tableNullClause);
841
875
  };
842
876
  const createFilterPredicate = (filter) => {
843
877
  const orGroups = filter.replaceAll(String.raw`(`, " ").replaceAll(String.raw`)`, "").split(/\s+and\s+/iu).filter(Boolean).map((group) => group.split(/\s+or\s+/iu).filter(Boolean));
@@ -1004,6 +1038,11 @@ var MockServiceBusSender = class {
1004
1038
  return Promise.resolve();
1005
1039
  }
1006
1040
  };
1041
+ const compareByCompositeKey = (a, b) => {
1042
+ if (a.partitionKey !== b.partitionKey) return a.partitionKey < b.partitionKey ? -1 : 1;
1043
+ else if (a.rowKey === b.rowKey) return 0;
1044
+ else return a.rowKey < b.rowKey ? -1 : 1;
1045
+ };
1007
1046
  /**
1008
1047
  * An in-memory mock of the Azure TableClient.
1009
1048
  * It uses a Map to simulate table storage and correctly implements the TableClient interface.
@@ -1024,9 +1063,7 @@ var MockTableClient = class {
1024
1063
  this.url = `${MOCK_TABLE_BASE_URL}/${this.tableName}`;
1025
1064
  }
1026
1065
  createEntity(entity) {
1027
- const key = this.#getCompositeKey(entity.partitionKey, entity.rowKey);
1028
- if (this.table.has(key)) throw new MockRestError("The specified entity already exists.", 409);
1029
- this.table.set(key, entity);
1066
+ this.#applyCreate(entity);
1030
1067
  return Promise.resolve({
1031
1068
  date: /* @__PURE__ */ new Date(),
1032
1069
  etag: this.#getEtag()
@@ -1036,9 +1073,7 @@ var MockTableClient = class {
1036
1073
  throw new Error("Method not implemented.");
1037
1074
  }
1038
1075
  deleteEntity(partitionKey, rowKey) {
1039
- const key = this.#getCompositeKey(partitionKey, rowKey);
1040
- if (!this.table.has(key)) throw new MockRestError("The specified resource does not exist.", 404);
1041
- this.table.delete(key);
1076
+ this.#applyDelete(partitionKey, rowKey);
1042
1077
  return Promise.resolve({});
1043
1078
  }
1044
1079
  deleteTable() {
@@ -1053,15 +1088,18 @@ var MockTableClient = class {
1053
1088
  if (!entity) throw new MockRestError("The specified resource does not exist.", 404);
1054
1089
  return Promise.resolve({
1055
1090
  ...entity,
1056
- etag: this.#getEtag()
1091
+ etag: entity.etag ?? this.#getEtag()
1057
1092
  });
1058
1093
  }
1059
1094
  listEntities(options) {
1060
1095
  const withMetadata = this.#withMetadata.bind(this);
1061
1096
  const filter = options?.queryOptions?.filter;
1062
- const tableEntities = [...this.table.values()];
1097
+ const tableEntities = [...this.table.values()].toSorted(compareByCompositeKey);
1063
1098
  const predicate = filter ? createFilterPredicate(filter) : void 0;
1064
1099
  const resultTableEntities = predicate ? tableEntities.filter((e) => predicate(e)) : tableEntities;
1100
+ const entityIterator = (async function* (entities) {
1101
+ for (const entity of entities) yield await Promise.resolve(withMetadata(entity));
1102
+ })(resultTableEntities);
1065
1103
  return {
1066
1104
  byPage: ({ maxPageSize } = {}) => (async function* (entities) {
1067
1105
  if (maxPageSize !== void 0 && maxPageSize <= 0) throw new RangeError("maxPageSize must be greater than 0.");
@@ -1074,9 +1112,7 @@ var MockTableClient = class {
1074
1112
  }
1075
1113
  for (let i = 0; i < allEntitiesWithMetadata.length; i += maxPageSize) yield await Promise.resolve(allEntitiesWithMetadata.slice(i, i + maxPageSize));
1076
1114
  })(resultTableEntities),
1077
- next: () => (async function* (entities) {
1078
- for (const entity of entities) yield await Promise.resolve(withMetadata(entity));
1079
- })(resultTableEntities).next(),
1115
+ next: () => entityIterator.next(),
1080
1116
  [Symbol.asyncIterator]() {
1081
1117
  return this;
1082
1118
  }
@@ -1085,24 +1121,24 @@ var MockTableClient = class {
1085
1121
  setAccessPolicy() {
1086
1122
  throw new Error("Method not implemented.");
1087
1123
  }
1088
- async submitTransaction(actions) {
1124
+ submitTransaction(actions) {
1089
1125
  let partitionKey;
1090
1126
  for (const [, entity] of actions) if (partitionKey === void 0) partitionKey = entity.partitionKey;
1091
1127
  else if (entity.partitionKey !== partitionKey) throw new MockRestError("All transaction actions must target the same partitionKey.", 400);
1092
1128
  const snapshot = new Map(this.table);
1093
- await getResultAsync(async () => {
1129
+ getResult(() => {
1094
1130
  for (const [type, entity, updateMode] of actions) switch (type) {
1095
1131
  case "create":
1096
- await this.createEntity(entity);
1132
+ this.#applyCreate(entity);
1097
1133
  break;
1098
1134
  case "delete":
1099
- await this.deleteEntity(entity.partitionKey, entity.rowKey);
1135
+ this.#applyDelete(entity.partitionKey, entity.rowKey);
1100
1136
  break;
1101
1137
  case "update":
1102
- await this.updateEntity(entity, updateMode);
1138
+ this.#applyUpdate(entity, updateMode);
1103
1139
  break;
1104
1140
  case "upsert":
1105
- await this.upsertEntity(entity, updateMode);
1141
+ this.#applyUpsert(entity, updateMode);
1106
1142
  break;
1107
1143
  default: exhaustiveGuard(type);
1108
1144
  }
@@ -1112,57 +1148,77 @@ var MockTableClient = class {
1112
1148
  }).match(noop, (error) => {
1113
1149
  throw error;
1114
1150
  });
1115
- return {
1116
- getResponseForEntity: noop,
1151
+ return Promise.resolve({
1152
+ getResponseForEntity: () => void 0,
1117
1153
  status: 202,
1118
1154
  subResponses: []
1119
- };
1155
+ });
1156
+ }
1157
+ updateEntity(entity, mode = "Merge", options) {
1158
+ this.#applyUpdate(entity, mode, options?.etag);
1159
+ return Promise.resolve({
1160
+ date: /* @__PURE__ */ new Date(),
1161
+ etag: this.#getEtag()
1162
+ });
1120
1163
  }
1121
- updateEntity(entity, mode = "Merge") {
1164
+ upsertEntity(entity, mode = "Merge") {
1165
+ this.#applyUpsert(entity, mode);
1166
+ return Promise.resolve({
1167
+ date: /* @__PURE__ */ new Date(),
1168
+ etag: this.#getEtag()
1169
+ });
1170
+ }
1171
+ #applyCreate(entity) {
1172
+ const key = this.#getCompositeKey(entity.partitionKey, entity.rowKey);
1173
+ if (this.table.has(key)) throw new MockRestError("The specified entity already exists.", 409);
1174
+ this.table.set(key, {
1175
+ ...entity,
1176
+ etag: this.#getEtag()
1177
+ });
1178
+ }
1179
+ #applyDelete(partitionKey, rowKey) {
1180
+ const key = this.#getCompositeKey(partitionKey, rowKey);
1181
+ if (!this.table.has(key)) throw new MockRestError("The specified resource does not exist.", 404);
1182
+ this.table.delete(key);
1183
+ }
1184
+ #applyUpdate(entity, mode = "Merge", etag) {
1122
1185
  const key = this.#getCompositeKey(entity.partitionKey, entity.rowKey);
1123
1186
  const existingEntity = this.table.get(key);
1124
1187
  if (!existingEntity) throw new MockRestError("The specified resource does not exist.", 404);
1125
- else if (mode === "Merge") return this.#mergeEntity(key, existingEntity, entity);
1126
- else {
1127
- this.table.set(key, entity);
1128
- return Promise.resolve({
1129
- date: /* @__PURE__ */ new Date(),
1130
- etag: this.#getEtag()
1131
- });
1132
- }
1188
+ else if (etag !== void 0 && etag !== "*" && etag !== existingEntity.etag) throw new MockRestError("The update condition specified in the request was not satisfied.", 412);
1189
+ else if (mode === "Merge") this.table.set(key, {
1190
+ ...existingEntity,
1191
+ ...entity,
1192
+ etag: this.#getEtag()
1193
+ });
1194
+ else this.table.set(key, {
1195
+ ...entity,
1196
+ etag: this.#getEtag()
1197
+ });
1133
1198
  }
1134
- upsertEntity(entity, mode = "Merge") {
1199
+ #applyUpsert(entity, mode = "Merge") {
1135
1200
  const key = this.#getCompositeKey(entity.partitionKey, entity.rowKey);
1136
1201
  const existingEntity = this.table.get(key);
1137
- if (existingEntity && mode === "Merge") return this.#mergeEntity(key, existingEntity, entity);
1138
- else {
1139
- this.table.set(key, entity);
1140
- return Promise.resolve({
1141
- date: /* @__PURE__ */ new Date(),
1142
- etag: this.#getEtag()
1143
- });
1144
- }
1202
+ if (existingEntity && mode === "Merge") this.table.set(key, {
1203
+ ...existingEntity,
1204
+ ...entity,
1205
+ etag: this.#getEtag()
1206
+ });
1207
+ else this.table.set(key, {
1208
+ ...entity,
1209
+ etag: this.#getEtag()
1210
+ });
1145
1211
  }
1146
1212
  #getCompositeKey(partitionKey, rowKey) {
1147
1213
  return `${partitionKey}${ID_SEPARATOR}${rowKey}`;
1148
1214
  }
1149
1215
  #getEtag() {
1150
- return `W/"datetime'${(/* @__PURE__ */ new Date()).toISOString()}'"`;
1151
- }
1152
- #mergeEntity(key, entity, entityToMerge) {
1153
- this.table.set(key, {
1154
- ...entity,
1155
- ...entityToMerge
1156
- });
1157
- return Promise.resolve({
1158
- date: /* @__PURE__ */ new Date(),
1159
- etag: this.#getEtag()
1160
- });
1216
+ return `W/"${crypto.randomUUID()}"`;
1161
1217
  }
1162
1218
  #withMetadata(entity) {
1163
1219
  return {
1164
1220
  ...entity,
1165
- etag: this.#getEtag()
1221
+ etag: entity.etag ?? this.#getEtag()
1166
1222
  };
1167
1223
  }
1168
1224
  };
@@ -1179,4 +1235,4 @@ const applyFilter = (documents, clauses) => {
1179
1235
  const predicate = createFilterPredicate(serializeClauses(clauses));
1180
1236
  return documents.filter((document) => predicate(document));
1181
1237
  };
1182
- export { MOCK_BLOB_BASE_URL, MOCK_QUEUE_BASE_URL, MOCK_SEARCH_BASE_URL, MOCK_TABLE_BASE_URL, MockBlobBatchClient, MockBlobClient, MockBlockBlobClient, MockContainerClient, MockContainerDatabase, MockEventGridDatabase, MockEventGridPublisherClient, MockQueueClient, MockQueueDatabase, MockRestError, MockSearchClient, MockSearchDatabase, MockServiceBusDatabase, MockServiceBusSender, MockTableClient, MockTableDatabase, MockWebPubSubServiceClient, applyFilter, bodyToBuffer, compare, createFilterPredicate, createMockResponse, getAzureErrorXml, getBlobItemXml, getBlobPrefixXml, getListBlobsXml, getMockSasUrl, isNullClause, isReadableStream, toWebResourceLike };
1238
+ export { MOCK_BLOB_BASE_URL, MOCK_BLOB_SEEDED_CREATED_ON, MOCK_QUEUE_BASE_URL, MOCK_SEARCH_BASE_URL, MOCK_TABLE_BASE_URL, MockBlobBatchClient, MockBlobClient, MockBlockBlobClient, MockContainerClient, MockContainerCreatedOnDatabase, MockContainerDatabase, MockEventGridDatabase, MockEventGridPublisherClient, MockQueueClient, MockQueueDatabase, MockRestError, MockSearchClient, MockSearchDatabase, MockServiceBusDatabase, MockServiceBusSender, MockTableClient, MockTableDatabase, MockWebPubSubServiceClient, applyFilter, bodyToBuffer, compare, compareByCompositeKey, createFilterPredicate, createMockResponse, getAzureErrorXml, getBlobItemXml, getBlobPrefixXml, getBlobUrl, getBlobUrlParts, getListBlobsXml, getMockContainerCreatedOnKey, getMockSasUrl, isNullClause, isReadableStream, toWebResourceLike };