azure-mock 4.0.0 → 4.1.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.d.ts CHANGED
@@ -10,6 +10,8 @@ import { CreateTableEntityResponse, GetAccessPolicyResponse, GetTableEntityRespo
10
10
  //#region src/constants.d.ts
11
11
  export declare const BLOB_NOT_FOUND_ERROR_CODE = "BlobNotFound";
12
12
  export declare const BLOB_NOT_FOUND_MESSAGE = "The specified blob does not exist.";
13
+ export declare const CONDITION_NOT_MET_ERROR_CODE = "ConditionNotMet";
14
+ export declare const CONDITION_NOT_MET_MESSAGE = "The condition specified using HTTP conditional header(s) is not met.";
13
15
  export declare const MOCK_BLOB_BASE_URL = "https://mockaccount.blob.core.windows.net";
14
16
  export declare const MOCK_QUEUE_BASE_URL = "https://mockaccount.queue.core.windows.net";
15
17
  export declare const MOCK_SEARCH_BASE_URL = "https://mockaccount.search.windows.net";
@@ -39,7 +41,7 @@ export declare class MockBlobBatchClient implements BlobBatchClient {
39
41
  * underlying MockContainerDatabase, and builds a response object that reports
40
42
  * which deletions succeeded and which failed (e.g. for blobs that didn't exist).
41
43
  */
42
- deleteBlobs(urls: string[], credential: AnonymousCredential | StorageSharedKeyCredential, _options?: BlobDeleteOptions): Promise<BlobBatchDeleteBlobsResponse>;
44
+ deleteBlobs(urls: string[], credential: AnonymousCredential | StorageSharedKeyCredential, options?: BlobDeleteOptions): Promise<BlobBatchDeleteBlobsResponse>;
43
45
  getContainer(containerName: string): MapValue<typeof MockContainerDatabase>;
44
46
  }
45
47
  //#endregion
@@ -1234,4 +1236,5 @@ export declare const MockContainerBlobMetadataDatabase: Map<string, Record<strin
1234
1236
  //#endregion
1235
1237
  //#region src/store/MockEventGridDatabase.d.ts
1236
1238
  export declare const MockEventGridDatabase: Map<string, EventGridEvent<unknown>[]>;
1237
- //#endregion
1239
+ //#endregion
1240
+ export {};
package/dist/index.js CHANGED
@@ -1,18 +1,27 @@
1
- import { ID_SEPARATOR, InvalidOperationError, Operation, chunk, exhaustiveGuard, getDecodedUriComponent, getOrCreate, getResult, html, noop, streamToText, takeOne } from "@esposter/shared";
1
+ import { ID_SEPARATOR, InvalidOperationError, Operation, checkIsDeepEqual, chunk, exhaustiveGuard, getDecodedUriComponent, getOrCreate, getResult, html, noop, streamToText, takeOne } from "@esposter/shared";
2
2
  import { toHttpHeadersLike } from "@azure/core-http-compat";
3
3
  import { RestError, createHttpHeaders, createPipelineRequest } from "@azure/core-rest-pipeline";
4
4
  import { AnonymousCredential } from "@azure/storage-blob";
5
5
  import { Readable } from "node:stream";
6
6
  import { AZURE_MAX_PAGE_SIZE, AZURE_MAX_QUEUE_VISIBILITY_TIMEOUT_MS, BinaryOperator, deserializeClause, deserializeKey, getTableNullClause, serializeClauses } from "@esposter/azure";
7
- import deepEqual from "fast-deep-equal";
8
7
  //#region src/constants.ts
9
8
  const BLOB_NOT_FOUND_ERROR_CODE = "BlobNotFound";
10
9
  const BLOB_NOT_FOUND_MESSAGE = "The specified blob does not exist.";
10
+ const CONDITION_NOT_MET_ERROR_CODE = "ConditionNotMet";
11
+ const CONDITION_NOT_MET_MESSAGE = "The condition specified using HTTP conditional header(s) is not met.";
11
12
  const MOCK_BLOB_BASE_URL = "https://mockaccount.blob.core.windows.net";
12
13
  const MOCK_QUEUE_BASE_URL = "https://mockaccount.queue.core.windows.net";
13
14
  const MOCK_SEARCH_BASE_URL = "https://mockaccount.search.windows.net";
14
15
  const MOCK_TABLE_BASE_URL = "https://mockaccount.table.core.windows.net";
15
16
  //#endregion
17
+ //#region src/models/shared/NotImplementedError.ts
18
+ var NotImplementedError = class extends Error {
19
+ constructor(name) {
20
+ super(`${name} is not implemented in the mock`);
21
+ this.name = "NotImplementedError";
22
+ }
23
+ };
24
+ //#endregion
16
25
  //#region src/services/container/getMockBlobKey.ts
17
26
  const getMockBlobKey = (containerName, blobName) => `${encodeURIComponent(containerName)}${ID_SEPARATOR}${encodeURIComponent(blobName)}`;
18
27
  //#endregion
@@ -76,14 +85,17 @@ const getBlobUrlParts = (url) => {
76
85
  };
77
86
  };
78
87
  //#endregion
79
- //#region src/models/shared/NotImplementedError.ts
80
- var NotImplementedError = class extends Error {
81
- constructor(name) {
82
- super(`${name} is not implemented in the mock`);
83
- this.name = "NotImplementedError";
84
- }
88
+ //#region src/services/container/constants.ts
89
+ const MOCK_BLOB_SEEDED_DATE = /* @__PURE__ */ new Date(-864e13);
90
+ const MOCK_BLOB_SEEDED_PROPERTIES = {
91
+ createdOn: MOCK_BLOB_SEEDED_DATE,
92
+ etag: "\"seeded\"",
93
+ lastModified: MOCK_BLOB_SEEDED_DATE
85
94
  };
86
95
  //#endregion
96
+ //#region src/services/container/readMockBlobDates.ts
97
+ const readMockBlobDates = (containerName, blobName) => MockContainerBlobDatesDatabase.get(getMockBlobKey(containerName, blobName)) ?? MOCK_BLOB_SEEDED_PROPERTIES;
98
+ //#endregion
87
99
  //#region src/services/container/toWebResourceLike.ts
88
100
  const toWebResourceLike = (request) => ({
89
101
  abortSignal: request.abortSignal,
@@ -131,7 +143,10 @@ var MockBlobBatchClient = class {
131
143
  * underlying MockContainerDatabase, and builds a response object that reports
132
144
  * which deletions succeeded and which failed (e.g. for blobs that didn't exist).
133
145
  */
134
- deleteBlobs(urls, credential, _options) {
146
+ deleteBlobs(urls, credential, options) {
147
+ const { ifUnmodifiedSince, ...unsupportedConditions } = options?.conditions ?? {};
148
+ const unsupportedConditionName = Object.entries(unsupportedConditions).find(([, value]) => value !== void 0)?.[0];
149
+ if (unsupportedConditionName !== void 0) return Promise.reject(new NotImplementedError(`deleteBlobs with ${unsupportedConditionName}`));
135
150
  const subResponses = [];
136
151
  let subResponsesSucceededCount = 0;
137
152
  let subResponsesFailedCount = 0;
@@ -143,6 +158,11 @@ var MockBlobBatchClient = class {
143
158
  continue;
144
159
  }
145
160
  const { blobName, containerName } = urlParts;
161
+ if (this.#checkIsModifiedSince(containerName, blobName, ifUnmodifiedSince)) {
162
+ subResponses.push(this.#createFailedSubResponse(credential, 412, CONDITION_NOT_MET_ERROR_CODE, CONDITION_NOT_MET_MESSAGE));
163
+ subResponsesFailedCount++;
164
+ continue;
165
+ }
146
166
  if (deleteMockBlob(containerName, blobName)) {
147
167
  subResponses.push({
148
168
  _request: {
@@ -175,6 +195,9 @@ var MockBlobBatchClient = class {
175
195
  getContainer(containerName) {
176
196
  return getMockContainer(containerName);
177
197
  }
198
+ #checkIsModifiedSince(containerName, blobName, ifUnmodifiedSince) {
199
+ return ifUnmodifiedSince !== void 0 && getMockContainer(containerName).has(blobName) && readMockBlobDates(containerName, blobName).lastModified > ifUnmodifiedSince;
200
+ }
178
201
  #createFailedSubResponse(credential, status, errorCode, statusMessage) {
179
202
  return {
180
203
  _request: {
@@ -201,17 +224,6 @@ var MockRestError = class extends RestError {
201
224
  //#region src/services/container/getBlobUrl.ts
202
225
  const getBlobUrl = (containerName, blobName) => `${MOCK_BLOB_BASE_URL}/${containerName}/${blobName.split("/").map((segment) => encodeURIComponent(segment)).join("/")}`;
203
226
  //#endregion
204
- //#region src/services/container/constants.ts
205
- const MOCK_BLOB_SEEDED_DATE = /* @__PURE__ */ new Date(-864e13);
206
- const MOCK_BLOB_SEEDED_PROPERTIES = {
207
- createdOn: MOCK_BLOB_SEEDED_DATE,
208
- etag: "\"seeded\"",
209
- lastModified: MOCK_BLOB_SEEDED_DATE
210
- };
211
- //#endregion
212
- //#region src/services/container/readMockBlobDates.ts
213
- const readMockBlobDates = (containerName, blobName) => MockContainerBlobDatesDatabase.get(getMockBlobKey(containerName, blobName)) ?? MOCK_BLOB_SEEDED_PROPERTIES;
214
- //#endregion
215
227
  //#region src/services/container/storeMockBlobWrite.ts
216
228
  const storeMockBlobWrite = (containerName, blobName, isExisting) => {
217
229
  const key = getMockBlobKey(containerName, blobName);
@@ -290,9 +302,11 @@ var MockBlobClient = class {
290
302
  }
291
303
  download() {
292
304
  const buffer = this.container.get(this.name);
305
+ if (!buffer) throw new MockRestError(BLOB_NOT_FOUND_MESSAGE, 404);
293
306
  return Promise.resolve({
294
- _response: createMockResponse(buffer ? 200 : 404),
295
- readableStreamBody: buffer ? Readable.from(buffer) : void 0
307
+ _response: createMockResponse(200),
308
+ etag: readMockBlobDates(this.containerName, this.name).etag,
309
+ readableStreamBody: Readable.from(buffer)
296
310
  });
297
311
  }
298
312
  downloadToBuffer() {
@@ -436,7 +450,11 @@ var MockBlockBlobClient = class extends MockBlobClient {
436
450
  storeMockBlobWrite(this.containerName, this.name, this.container.has(this.name));
437
451
  storeMockBlobMetadata(this.containerName, this.name, options?.metadata);
438
452
  this.container.set(this.name, buffer);
439
- return { _response: createMockResponse(201) };
453
+ const { etag } = readMockBlobDates(this.containerName, this.name);
454
+ return {
455
+ _response: createMockResponse(201),
456
+ etag
457
+ };
440
458
  }
441
459
  uploadBrowserData() {
442
460
  throw new NotImplementedError(this.uploadBrowserData.name);
@@ -865,7 +883,7 @@ var MockQueueClient = class {
865
883
  //#region src/services/filter/checkIsNullClause.ts
866
884
  const checkIsNullClause = (clause) => {
867
885
  const tableNullClause = getTableNullClause(clause.key);
868
- return deepEqual(clause, tableNullClause);
886
+ return checkIsDeepEqual(clause, tableNullClause);
869
887
  };
870
888
  //#endregion
871
889
  //#region src/services/filter/compare.ts
@@ -1233,28 +1251,12 @@ var MockTableClient = class {
1233
1251
  const existingEntity = this.table.get(key);
1234
1252
  if (!existingEntity) throw new MockRestError("The specified resource does not exist.", 404);
1235
1253
  this.#assertEtag(existingEntity.etag, etag);
1236
- if (mode === "Merge") this.table.set(key, {
1237
- ...existingEntity,
1238
- ...entity,
1239
- etag: this.#getEtag()
1240
- });
1241
- else this.table.set(key, {
1242
- ...entity,
1243
- etag: this.#getEtag()
1244
- });
1254
+ this.#writeEntity(key, entity, mode, existingEntity);
1245
1255
  }
1246
1256
  #applyUpsert(entity, mode = "Merge") {
1247
1257
  const key = this.#getCompositeKey(entity.partitionKey, entity.rowKey);
1248
1258
  const existingEntity = this.table.get(key);
1249
- if (existingEntity && mode === "Merge") this.table.set(key, {
1250
- ...existingEntity,
1251
- ...entity,
1252
- etag: this.#getEtag()
1253
- });
1254
- else this.table.set(key, {
1255
- ...entity,
1256
- etag: this.#getEtag()
1257
- });
1259
+ this.#writeEntity(key, entity, mode, existingEntity);
1258
1260
  }
1259
1261
  #assertEtag(existingEtag, etag) {
1260
1262
  if (etag !== void 0 && etag !== "*" && etag !== existingEtag) throw new MockRestError("The update condition specified in the request was not satisfied.", 412);
@@ -1271,6 +1273,17 @@ var MockTableClient = class {
1271
1273
  etag: entity.etag ?? this.#getEtag()
1272
1274
  };
1273
1275
  }
1276
+ #writeEntity(key, entity, mode, existingEntity) {
1277
+ if (existingEntity && mode === "Merge") this.table.set(key, {
1278
+ ...existingEntity,
1279
+ ...entity,
1280
+ etag: this.#getEtag()
1281
+ });
1282
+ else this.table.set(key, {
1283
+ ...entity,
1284
+ etag: this.#getEtag()
1285
+ });
1286
+ }
1274
1287
  };
1275
1288
  //#endregion
1276
1289
  //#region src/models/webPubSub/MockWebPubSubServiceClient.ts
@@ -1290,4 +1303,4 @@ const applyFilter = (documents, clauses) => {
1290
1303
  return documents.filter((document) => predicate(document));
1291
1304
  };
1292
1305
  //#endregion
1293
- export { BLOB_NOT_FOUND_ERROR_CODE, BLOB_NOT_FOUND_MESSAGE, MOCK_BLOB_BASE_URL, MOCK_BLOB_SEEDED_DATE, MOCK_BLOB_SEEDED_PROPERTIES, MOCK_QUEUE_BASE_URL, MOCK_SEARCH_BASE_URL, MOCK_TABLE_BASE_URL, MockBlobBatchClient, MockBlobClient, MockBlockBlobClient, MockContainerBlobDatesDatabase, MockContainerBlobMetadataDatabase, MockContainerClient, MockContainerDatabase, MockEventGridDatabase, MockEventGridPublisherClient, MockQueueClient, MockQueueDatabase, MockRestError, MockSearchClient, MockSearchDatabase, MockServiceBusDatabase, MockServiceBusSender, MockTableClient, MockTableDatabase, MockWebPubSubServiceClient, NotImplementedError, applyFilter, bodyToBuffer, checkIsNullClause, checkIsReadableStream, compare, compareByCompositeKey, createFilterPredicate, createMockResponse, deleteMockBlob, getAzureErrorXml, getBlobItemXml, getBlobPrefixXml, getBlobUrl, getBlobUrlParts, getListBlobsSegmentResponse, getListBlobsXml, getMockBlobKey, getMockContainer, getMockQueueMessageItem, getMockSasUrl, readMockBlobDates, readMockBlobMetadata, storeMockBlobMetadata, storeMockBlobWrite, toWebResourceLike };
1306
+ export { BLOB_NOT_FOUND_ERROR_CODE, BLOB_NOT_FOUND_MESSAGE, CONDITION_NOT_MET_ERROR_CODE, CONDITION_NOT_MET_MESSAGE, MOCK_BLOB_BASE_URL, MOCK_BLOB_SEEDED_DATE, MOCK_BLOB_SEEDED_PROPERTIES, MOCK_QUEUE_BASE_URL, MOCK_SEARCH_BASE_URL, MOCK_TABLE_BASE_URL, MockBlobBatchClient, MockBlobClient, MockBlockBlobClient, MockContainerBlobDatesDatabase, MockContainerBlobMetadataDatabase, MockContainerClient, MockContainerDatabase, MockEventGridDatabase, MockEventGridPublisherClient, MockQueueClient, MockQueueDatabase, MockRestError, MockSearchClient, MockSearchDatabase, MockServiceBusDatabase, MockServiceBusSender, MockTableClient, MockTableDatabase, MockWebPubSubServiceClient, NotImplementedError, applyFilter, bodyToBuffer, checkIsNullClause, checkIsReadableStream, compare, compareByCompositeKey, createFilterPredicate, createMockResponse, deleteMockBlob, getAzureErrorXml, getBlobItemXml, getBlobPrefixXml, getBlobUrl, getBlobUrlParts, getListBlobsSegmentResponse, getListBlobsXml, getMockBlobKey, getMockContainer, getMockQueueMessageItem, getMockSasUrl, readMockBlobDates, readMockBlobMetadata, storeMockBlobMetadata, storeMockBlobWrite, toWebResourceLike };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "azure-mock",
3
- "version": "4.0.0",
3
+ "version": "4.1.0",
4
4
  "description": "A library that contains azure mock classes.",
5
5
  "keywords": [
6
6
  "azure",
@@ -53,18 +53,17 @@
53
53
  "typecheck": "tsc"
54
54
  },
55
55
  "dependencies": {
56
- "@esposter/azure": "4.0.0",
57
- "@esposter/shared": "4.0.0",
58
- "fast-deep-equal": "^3.1.3"
56
+ "@esposter/azure": "4.1.0",
57
+ "@esposter/shared": "4.1.0"
59
58
  },
60
59
  "devDependencies": {
61
60
  "@arethetypeswrong/core": "^0.18.5",
62
- "@esposter/configuration": "4.0.0",
61
+ "@esposter/configuration": "4.1.0",
63
62
  "publint": "^0.3.25",
64
- "tsdown": "^0.23.0",
63
+ "tsdown": "^0.23.1",
65
64
  "type-fest": "^5.10.0",
66
65
  "typedoc": "^0.28.20",
67
- "vitest": "^5.0.3"
66
+ "vitest": "^5.0.4"
68
67
  },
69
68
  "peerDependencies": {
70
69
  "@azure/core-http-compat": "^2.5.0",
@@ -79,5 +78,5 @@
79
78
  "inlinedDependencies": {
80
79
  "type-fest": "5.10.0"
81
80
  },
82
- "gitHead": "7667bc8c9a2b4e9dcacd6b845ee8cc9951250ae7"
81
+ "gitHead": "68de4c22fa7591bf6f6cc0fab2c9a906d8c4d71a"
83
82
  }