aws-sdk-vitest-mock 0.5.0 → 0.6.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/README.md CHANGED
@@ -564,6 +564,46 @@ s3Mock.restore();
564
564
  s3Mock.disableDebug();
565
565
  ```
566
566
 
567
+ #### Global Debug Configuration
568
+
569
+ Enable debug logging for all mocks globally, with the ability to override at the individual mock level:
570
+
571
+ ```typescript
572
+ import { setGlobalDebug, mockClient } from "aws-sdk-vitest-mock";
573
+ import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
574
+ import { DynamoDBClient, GetItemCommand } from "@aws-sdk/client-dynamodb";
575
+
576
+ // Enable debug for all mocks
577
+ setGlobalDebug(true);
578
+
579
+ // All mocks will inherit the global debug setting
580
+ const s3Mock = mockClient(S3Client);
581
+ const dynamoMock = mockClient(DynamoDBClient);
582
+
583
+ // Both mocks will log debug information
584
+ s3Mock.on(GetObjectCommand).resolves({ Body: "data" });
585
+ dynamoMock.on(GetItemCommand).resolves({ Item: { id: { S: "1" } } });
586
+
587
+ // Override global setting for a specific mock
588
+ s3Mock.disableDebug(); // This mock won't log, but dynamoMock still will
589
+
590
+ // Disable global debug
591
+ setGlobalDebug(false);
592
+ ```
593
+
594
+ **Debug Priority (highest to lowest):**
595
+
596
+ 1. Individual mock's `enableDebug()` or `disableDebug()` call (explicit override)
597
+ 2. Global debug setting via `setGlobalDebug()`
598
+ 3. Default: disabled
599
+
600
+ **Key behaviors:**
601
+
602
+ - When global debug is enabled, all new and existing mocks will log unless explicitly disabled
603
+ - Individual mock settings always take priority over global settings
604
+ - `reset()` preserves individual debug settings
605
+ - Global debug can be changed at any time and affects all mocks without explicit settings
606
+
567
607
  Debug mode provides comprehensive logging for:
568
608
 
569
609
  **Mock Configuration:**
@@ -650,6 +690,8 @@ test("should call DynamoDB", async () => {
650
690
 
651
691
  ## 📚 API Reference
652
692
 
693
+ > TypeScript documentation for this library can be found at [here](https://sudokar.github.io/aws-sdk-vitest-mock/)
694
+
653
695
  ### `mockClient<TClient>(ClientConstructor)`
654
696
 
655
697
  Creates a mock for an AWS SDK client constructor.
@@ -662,14 +704,18 @@ Mocks an existing AWS SDK client instance.
662
704
 
663
705
  **Returns:** `AwsClientStub<TClient>`
664
706
 
707
+ ### Global Debug Functions
708
+
709
+ - `setGlobalDebug(enabled: boolean)` - Enable or disable debug logging globally for all mocks
710
+
665
711
  ### `AwsClientStub` Methods
666
712
 
667
713
  - `on(Command, matcher?, options?)` - Configure mock for a command
668
714
  - `reset()` - Clear call history while preserving mock configurations
669
715
  - `restore()` - Restore original client behavior
670
716
  - `calls()` - Get call history
671
- - `enableDebug()` - Enable debug logging for troubleshooting
672
- - `disableDebug()` - Disable debug logging
717
+ - `enableDebug()` - Enable debug logging for troubleshooting (overrides global setting)
718
+ - `disableDebug()` - Disable debug logging (overrides global setting)
673
719
 
674
720
  ### `AwsCommandStub` Methods (Chainable)
675
721
 
package/index.cjs CHANGED
@@ -1,18 +1,18 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const v=require("vitest"),m=require("./matchers-Dkkl4vtx.cjs"),x=require("node:fs"),O=require("node:path"),F=require("node:stream");class f extends Error{constructor(t,o,i,n){super(t),this.name="AwsError",this.code=o,this.statusCode=i,this.retryable=n}}const L=e=>{const t=e?`The specified key does not exist. Key: ${e}`:"The specified key does not exist.";return new f(t,"NoSuchKey",404,!1)},D=e=>{const t=e?`The specified bucket does not exist. Bucket: ${e}`:"The specified bucket does not exist.";return new f(t,"NoSuchBucket",404,!1)},I=e=>{const t=e?`Access Denied for resource: ${e}`:"Access Denied";return new f(t,"AccessDenied",403,!1)},T=e=>{const t=e?`Requested resource not found: ${e}`:"Requested resource not found";return new f(t,"ResourceNotFoundException",400,!1)},K=()=>new f("The conditional request failed","ConditionalCheckFailedException",400,!1),M=()=>new f("Rate exceeded","Throttling",400,!0),A=()=>new f("We encountered an internal error. Please try again.","InternalServerError",500,!0);function B(e){try{return JSON.stringify(e,void 0,2)}catch{return typeof e=="object"&&e!==null?"[Complex Object]":typeof e=="string"?e:typeof e=="number"||typeof e=="boolean"?String(e):"[Non-serializable value]"}}function j(){return{enabled:!1,log(e,t){if(this.enabled)if(t===void 0)console.log(`${m.colors.magenta("aws-sdk-vitest-mock(debug):")} ${e}`);else{const o=B(t);console.log(`${m.colors.magenta("aws-sdk-vitest-mock(debug):")} ${e}
2
- ${o}`)}}}}function S(e){e.enabled=!0}function w(e){e.enabled=!1}function q(e){const t=O.resolve(e),o=x.readFileSync(t,"utf8");return e.endsWith(".json")?JSON.parse(o):o}function J(e,t={}){const{pageSize:o=10,tokenKey:i="NextToken",itemsKey:n="Items"}=t;if(e.length===0)return[{[n]:[]}];const s=[];for(let r=0;r<e.length;r+=o){const c=e.slice(r,r+o),u=r+o<e.length,l={[n]:c};if(u){const g=l,a=c[c.length-1];g[i]=a}s.push(l)}return s}function _(){return typeof process<"u"&&process.versions?.node?"node":typeof process<"u"&&process.versions?.bun?"bun":"browser"}function z(e){const t=typeof e=="string"?Buffer.from(e,"utf8"):Buffer.from(e);let o=!1;return new F.Readable({read(){o||(this.push(t),this.push(null),o=!0)}})}function V(e){let t;return typeof e=="string"?t=new TextEncoder().encode(e):e instanceof Buffer?t=new Uint8Array(e):t=e,new ReadableStream({start(o){o.enqueue(t),o.close()}})}function k(e){const t=_();return t==="node"||t==="bun"?z(e):V(e)}function $(e,t){return Object.keys(t).every(o=>{const i=t[o],n=e[o];return i&&typeof i=="object"&&!Array.isArray(i)?typeof n!="object"||n===null?!1:$(n,i):n===i})}function C(e,t){if(e===t)return!0;if(typeof e!="object"||e===null||typeof t!="object"||t===null)return e===t;const o=Object.keys(e),i=Object.keys(t);return o.length!==i.length?!1:i.every(n=>{if(!Object.prototype.hasOwnProperty.call(e,n))return!1;const s=e,r=t,c=s[n],u=r[n];return typeof c=="object"&&c!==null&&typeof u=="object"&&u!==null?C(c,u):c===u})}function N(e){return async function(t){const o=()=>this;e.debugLogger.log(`Received command: ${t.constructor.name}`,t.input);const i=e.map.get(t.constructor);if(i){e.debugLogger.log(`Found ${i.length} mock(s) for ${t.constructor.name}`);const s=i.findIndex(r=>r.strict?r.matcher&&C(t.input,r.matcher):!r.matcher||$(t.input,r.matcher));if(s===-1){e.debugLogger.log(`No matching mock found for ${t.constructor.name}`,t.input);const r=i.map((u,l)=>{const g=u.matcher?JSON.stringify(u.matcher,void 0,2):"any input",a=u.strict?" (strict mode)":"";return` Mock #${l+1}: ${g}${a}`}).join(`
3
- `),c=JSON.stringify(t.input,void 0,2);throw new Error(`No matching mock found for ${t.constructor.name}.
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const j=require("vitest"),D=require("./matchers-CNhdB_9q.cjs"),F=require("node:fs"),I=require("node:path"),M=require("node:stream");class d extends Error{constructor(t,o,i,n){super(t),this.name="AwsError",this.code=o,this.statusCode=i,this.retryable=n}}const T=e=>new d(e?`The specified key does not exist. Key: ${e}`:"The specified key does not exist.","NoSuchKey",404,!1),K=e=>new d(e?`The specified bucket does not exist. Bucket: ${e}`:"The specified bucket does not exist.","NoSuchBucket",404,!1),A=e=>new d(e?`Access Denied for resource: ${e}`:"Access Denied","AccessDenied",403,!1),B=e=>new d(e?`Requested resource not found: ${e}`:"Requested resource not found","ResourceNotFoundException",400,!1),q=()=>new d("The conditional request failed","ConditionalCheckFailedException",400,!1),J=()=>new d("Rate exceeded","Throttling",400,!0),_=()=>new d("We encountered an internal error. Please try again.","InternalServerError",500,!0),z=e=>{try{return JSON.stringify(e,void 0,2)}catch{return typeof e=="object"&&e!==null?"[Complex Object]":typeof e=="string"?e:typeof e=="number"||typeof e=="boolean"?String(e):"[Non-serializable value]"}},v=(e,t)=>{const o=D.colors.magenta("aws-sdk-vitest-mock(debug):");if(t===void 0)console.log(`${o} ${e}`);else{const i=z(t);console.log(`${o} ${e}
2
+ ${i}`)}},L=(e=!1)=>({enabled:e,explicitlySet:!1,log(t,o){this.enabled&&v(t,o)},logDirect(t,o){v(t,o)}}),w=e=>{e.enabled=!0,e.explicitlySet=!0},$=e=>{e.enabled=!1,e.explicitlySet=!0},V=e=>{const t=I.resolve(e),o=F.readFileSync(t,"utf8");return e.endsWith(".json")?JSON.parse(o):o},G=(e,t={})=>{const{pageSize:o=10,tokenKey:i="NextToken",itemsKey:n="Items"}=t;if(e.length===0)return[{[n]:[]}];const s=[];for(let r=0;r<e.length;r+=o){const c=e.slice(r,r+o),l=r+o<e.length,u={[n]:c};if(l){const a=u,g=c[c.length-1];a[i]=g}s.push(u)}return s},U=()=>typeof process<"u"&&process.versions?.node?"node":typeof process<"u"&&process.versions?.bun?"bun":"browser",H=e=>{const t=typeof e=="string"?Buffer.from(e,"utf8"):Buffer.from(e);let o=!1;return new M.Readable({read(){o||(this.push(t),this.push(null),o=!0)}})},Q=e=>{let t;return typeof e=="string"?t=new TextEncoder().encode(e):e instanceof Buffer?t=new Uint8Array(e):t=e,new ReadableStream({start(o){o.enqueue(t),o.close()}})},S=e=>{const t=U();return t==="node"||t==="bun"?H(e):Q(e)};let N=!1;function X(e){N=e}function h(e){return e.explicitlySet?e.enabled:N}function C(e,t){return Object.keys(t).every(o=>{const i=t[o],n=e[o];return i&&typeof i=="object"&&!Array.isArray(i)?typeof n!="object"||n===null?!1:C(n,i):n===i})}function E(e,t){if(e===t)return!0;if(typeof e!="object"||e===null||typeof t!="object"||t===null)return e===t;const o=Object.keys(e),i=Object.keys(t);return o.length!==i.length?!1:i.every(n=>{if(!Object.prototype.hasOwnProperty.call(e,n))return!1;const s=e,r=t,c=s[n],l=r[n];return typeof c=="object"&&c!==null&&typeof l=="object"&&l!==null?E(c,l):c===l})}function Y(e,t,o){const i=t.map((s,r)=>{const c=s.matcher?JSON.stringify(s.matcher,void 0,2):"any input",l=s.strict?" (strict mode)":"";return` Mock #${r+1}: ${c}${l}`}).join(`
3
+ `),n=JSON.stringify(o,void 0,2);return new Error(`No matching mock found for ${e}.
4
4
 
5
- Found ${i.length} mock(s) but none matched the input.
5
+ Found ${t.length} mock(s) but none matched the input.
6
6
 
7
7
  Configured mocks:
8
- ${r}
8
+ ${i}
9
9
 
10
10
  Received input:
11
- ${c}
11
+ ${n}
12
12
 
13
- Tip: Enable debug mode with enableDebug() for detailed matching information.`)}else{const r=i[s];if(!r)throw new Error(`Mock at index ${s} not found`);return e.debugLogger.log(`Using mock at index ${s} for ${t.constructor.name}`),r.once&&(i.splice(s,1),e.debugLogger.log(`Removed one-time mock for ${t.constructor.name}`)),r.handler(t.input,o())}}else e.debugLogger.log(`No mocks configured for ${t.constructor.name}`);const n=JSON.stringify(t.input,void 0,2);throw new Error(`No mock configured for command: ${t.constructor.name}.
13
+ Tip: Enable debug mode with enableDebug() for detailed matching information.`)}function Z(e,t){const o=JSON.stringify(t,void 0,2);return new Error(`No mock configured for command: ${e}.
14
14
 
15
15
  Received input:
16
- ${n}
16
+ ${o}
17
17
 
18
- Did you forget to call mockClient.on(${t.constructor.name})?`)}}function R(e,t,o,i={}){const n=(r,c,u)=>{const l={matcher:o,handler:r,once:c,strict:!!i.strict},g=e.map.get(t)??[];if(c){const a=g.findIndex(d=>!d.once);a===-1?g.push(l):g.splice(a,0,l),e.map.set(t,g),e.debugLogger.log(`Configured ${u}Once for ${t.name}`,o?{matcher:o,strict:!!i.strict}:void 0)}else{const a=g.filter(d=>d.once||JSON.stringify(d.matcher)!==JSON.stringify(o));a.push(l),e.map.set(t,a),e.debugLogger.log(`Configured ${u} for ${t.name}`,o?{matcher:o,strict:!!i.strict}:void 0)}},s={resolves(r){return n(()=>Promise.resolve(r),!1,"resolves"),s},rejects(r){return n(()=>{const c=typeof r=="string"?new Error(r):r;return Promise.reject(c)},!1,"rejects"),s},callsFake(r){return n(r,!1,"callsFake"),s},resolvesOnce(r){return n(()=>Promise.resolve(r),!0,"resolves"),s},rejectsOnce(r){return n(()=>{const c=typeof r=="string"?new Error(r):r;return Promise.reject(c)},!0,"rejects"),s},callsFakeOnce(r){return n(r,!0,"callsFake"),s},resolvesStream(r){return n(()=>Promise.resolve({Body:k(r)}),!1,"resolvesStream"),s},resolvesStreamOnce(r){return n(()=>Promise.resolve({Body:k(r)}),!0,"resolvesStream"),s},resolvesWithDelay(r,c){const u=l=>{setTimeout(()=>l(r),c)};return n(()=>new Promise(u),!1,"resolvesWithDelay"),s},rejectsWithDelay(r,c){const u=typeof r=="string"?new Error(r):r,l=(g,a)=>{setTimeout(()=>a(u),c)};return n(()=>new Promise(l),!1,"rejectsWithDelay"),s},rejectsWithNoSuchKey(r){return n(()=>Promise.reject(L(r)),!1,"rejectsWithNoSuchKey"),s},rejectsWithNoSuchBucket(r){return n(()=>Promise.reject(D(r)),!1,"rejectsWithNoSuchBucket"),s},rejectsWithAccessDenied(r){return n(()=>Promise.reject(I(r)),!1,"rejectsWithAccessDenied"),s},rejectsWithResourceNotFound(r){return n(()=>Promise.reject(T(r)),!1,"rejectsWithResourceNotFound"),s},rejectsWithConditionalCheckFailed(){return n(()=>Promise.reject(K()),!1,"rejectsWithConditionalCheckFailed"),s},rejectsWithThrottling(){return n(()=>Promise.reject(M()),!1,"rejectsWithThrottling"),s},rejectsWithInternalServerError(){return n(()=>Promise.reject(A()),!1,"rejectsWithInternalServerError"),s},resolvesPaginated(r,c={}){const u=J(r,c);let l=0;return e.debugLogger.log(`Configured resolvesPaginated for ${t.name}`,{pageSize:c.pageSize,itemsCount:r.length}),n(g=>{const a=c.tokenKey||"NextToken",d=c.inputTokenKey||a,h=g[d];if(h!=null){const E=c.itemsKey||"Items";let y=0;for(const W of u){const p=W[E];if(p&&p.length>0){const P=p[p.length-1];if(JSON.stringify(P)===JSON.stringify(h)){l=y+1;break}}y++}}else l=0;const b=u[l]||u[u.length-1]||u[0];if(!b)throw new Error("No paginated responses available");return l=Math.min(l+1,u.length-1),Promise.resolve(b)},!1,"resolvesPaginated"),s},resolvesFromFile(r){return e.debugLogger.log(`Configured resolvesFromFile for ${t.name}`,{filePath:r}),n(()=>{const c=q(r);return Promise.resolve(c)},!1,"resolvesFromFile"),s}};return s}const U=e=>{const t={map:new WeakMap,debugLogger:j()},o=e.prototype,i=v.vi.spyOn(o,"send").mockImplementation(N(t));return{client:void 0,on:(s,r,c)=>R(t,s,r,c),reset:()=>{t.debugLogger.log("Clearing call history (mocks preserved)"),i.mockClear()},restore:()=>{t.debugLogger.log("Restoring original client behavior and clearing all mocks"),i.mockRestore(),t.map=new WeakMap},calls:()=>i.mock.calls.map(s=>s[0]),__rawCalls:()=>i.mock.calls,enableDebug:()=>{S(t.debugLogger)},disableDebug:()=>{w(t.debugLogger)}}},G=e=>{const t={map:new WeakMap,debugLogger:j()},o=v.vi.spyOn(e,"send").mockImplementation(N(t));return{client:e,on:(n,s,r)=>R(t,n,s,r),reset:()=>{t.debugLogger.log("Clearing call history (mocks preserved) for client instance"),o.mockClear()},restore:()=>{t.debugLogger.log("Restoring original client behavior and clearing all mocks for client instance"),o.mockRestore(),t.map=new WeakMap},calls:()=>o.mock.calls.map(n=>n[0]),__rawCalls:()=>o.mock.calls,enableDebug:()=>{S(t.debugLogger)},disableDebug:()=>{w(t.debugLogger)}}};exports.matchers=m.matchers;exports.mockClient=U;exports.mockClientInstance=G;
18
+ Did you forget to call mockClient.on(${e})?`)}function ee(e,t){return e.findIndex(o=>o.strict?o.matcher&&E(t,o.matcher):!o.matcher||C(t,o.matcher))}function x(e){return async function(t){const o=()=>this,i=h(e.debugLogger),n=t.constructor.name;i&&e.debugLogger.logDirect(`Received command: ${n}`,t.input);const s=e.map.get(t.constructor);if(!s)throw i&&e.debugLogger.logDirect(`No mocks configured for ${n}`),Z(n,t.input);i&&e.debugLogger.logDirect(`Found ${s.length} mock(s) for ${n}`);const r=ee(s,t.input);if(r===-1)throw i&&e.debugLogger.logDirect(`No matching mock found for ${n}`,t.input),Y(n,s,t.input);const c=s[r];if(!c)throw new Error(`Mock at index ${r} not found`);return i&&e.debugLogger.logDirect(`Using mock at index ${r} for ${n}`),c.once&&(s.splice(r,1),i&&e.debugLogger.logDirect(`Removed one-time mock for ${n}`)),c.handler(t.input,o())}}function R(e,t,o,i={}){const n=(r,c,l)=>{const u={matcher:o,handler:r,once:c,strict:!!i.strict},a=e.map.get(t)??[],g=h(e.debugLogger);if(c){const f=a.findIndex(p=>!p.once);f===-1?a.push(u):a.splice(f,0,u),e.map.set(t,a),g&&e.debugLogger.logDirect(`Configured ${l}Once for ${t.name}`,o?{matcher:o,strict:!!i.strict}:void 0)}else{const f=a.filter(p=>p.once||JSON.stringify(p.matcher)!==JSON.stringify(o));f.push(u),e.map.set(t,f),g&&e.debugLogger.logDirect(`Configured ${l} for ${t.name}`,o?{matcher:o,strict:!!i.strict}:void 0)}},s={resolves(r){return n(()=>Promise.resolve(r),!1,"resolves"),s},rejects(r){return n(()=>{const c=typeof r=="string"?new Error(r):r;return Promise.reject(c)},!1,"rejects"),s},callsFake(r){return n(r,!1,"callsFake"),s},resolvesOnce(r){return n(()=>Promise.resolve(r),!0,"resolves"),s},rejectsOnce(r){return n(()=>{const c=typeof r=="string"?new Error(r):r;return Promise.reject(c)},!0,"rejects"),s},callsFakeOnce(r){return n(r,!0,"callsFake"),s},resolvesStream(r){return n(()=>Promise.resolve({Body:S(r)}),!1,"resolvesStream"),s},resolvesStreamOnce(r){return n(()=>Promise.resolve({Body:S(r)}),!0,"resolvesStream"),s},resolvesWithDelay(r,c){const l=u=>{setTimeout(()=>u(r),c)};return n(()=>new Promise(l),!1,"resolvesWithDelay"),s},rejectsWithDelay(r,c){const l=typeof r=="string"?new Error(r):r,u=(a,g)=>{setTimeout(()=>g(l),c)};return n(()=>new Promise(u),!1,"rejectsWithDelay"),s},rejectsWithNoSuchKey(r){return n(()=>Promise.reject(T(r)),!1,"rejectsWithNoSuchKey"),s},rejectsWithNoSuchBucket(r){return n(()=>Promise.reject(K(r)),!1,"rejectsWithNoSuchBucket"),s},rejectsWithAccessDenied(r){return n(()=>Promise.reject(A(r)),!1,"rejectsWithAccessDenied"),s},rejectsWithResourceNotFound(r){return n(()=>Promise.reject(B(r)),!1,"rejectsWithResourceNotFound"),s},rejectsWithConditionalCheckFailed(){return n(()=>Promise.reject(q()),!1,"rejectsWithConditionalCheckFailed"),s},rejectsWithThrottling(){return n(()=>Promise.reject(J()),!1,"rejectsWithThrottling"),s},rejectsWithInternalServerError(){return n(()=>Promise.reject(_()),!1,"rejectsWithInternalServerError"),s},resolvesPaginated(r,c={}){const l=G(r,c);let u=0;return e.debugLogger.log(`Configured resolvesPaginated for ${t.name}`,{pageSize:c.pageSize,itemsCount:r.length}),n(a=>{const g=c.tokenKey||"NextToken",f=c.inputTokenKey||g,m=a[f];if(m!=null){const W=c.itemsKey||"Items";let k=0;for(const P of l){const b=P[W];if(b&&b.length>0){const O=b[b.length-1];if(JSON.stringify(O)===JSON.stringify(m)){u=k+1;break}}k++}}else u=0;const y=l[u]||l[l.length-1]||l[0];if(!y)throw new Error("No paginated responses available");return u=Math.min(u+1,l.length-1),Promise.resolve(y)},!1,"resolvesPaginated"),s},resolvesFromFile(r){return e.debugLogger.log(`Configured resolvesFromFile for ${t.name}`,{filePath:r}),n(()=>{const c=V(r);return Promise.resolve(c)},!1,"resolvesFromFile"),s}};return s}const te=e=>{const t={map:new WeakMap,debugLogger:L()},o=e.prototype,i=j.vi.spyOn(o,"send").mockImplementation(x(t));return{client:void 0,on:(s,r,c)=>R(t,s,r,c),reset:()=>{h(t.debugLogger)&&t.debugLogger.logDirect("Clearing call history (mocks preserved)"),i.mockClear()},restore:()=>{h(t.debugLogger)&&t.debugLogger.logDirect("Restoring original client behavior and clearing all mocks"),i.mockRestore(),t.map=new WeakMap},calls:()=>i.mock.calls.map(s=>s[0]),__rawCalls:()=>i.mock.calls,enableDebug:()=>{w(t.debugLogger)},disableDebug:()=>{$(t.debugLogger)}}},re=e=>{const t={map:new WeakMap,debugLogger:L()},o=j.vi.spyOn(e,"send").mockImplementation(x(t));return{client:e,on:(n,s,r)=>R(t,n,s,r),reset:()=>{h(t.debugLogger)&&t.debugLogger.logDirect("Clearing call history (mocks preserved) for client instance"),o.mockClear()},restore:()=>{h(t.debugLogger)&&t.debugLogger.logDirect("Restoring original client behavior and clearing all mocks for client instance"),o.mockRestore(),t.map=new WeakMap},calls:()=>o.mock.calls.map(n=>n[0]),__rawCalls:()=>o.mock.calls,enableDebug:()=>{w(t.debugLogger)},disableDebug:()=>{$(t.debugLogger)}}};exports.matchers=D.matchers;exports.mockClient=te;exports.mockClientInstance=re;exports.setGlobalDebug=X;
package/index.d.ts CHANGED
@@ -29,7 +29,7 @@
29
29
  * Core Functions for mocking AWS SDK clients
30
30
  * @category Core Functions
31
31
  */
32
- export { mockClient, mockClientInstance } from './lib/mock-client.js';
32
+ export { mockClient, mockClientInstance, setGlobalDebug, } from './lib/mock-client.js';
33
33
  /**
34
34
  * Command stub interface for configuring mock behaviors
35
35
  * @category Command Stub
package/index.js CHANGED
@@ -1,233 +1,237 @@
1
- import { vi as v } from "vitest";
2
- import { c as y } from "./matchers-ClGOsQx8.js";
3
- import { m as ne } from "./matchers-ClGOsQx8.js";
4
- import { readFileSync as P } from "node:fs";
5
- import F from "node:path";
6
- import { Readable as O } from "node:stream";
7
- class f extends Error {
8
- constructor(t, n, i, o) {
9
- super(t), this.name = "AwsError", this.code = n, this.statusCode = i, this.retryable = o;
1
+ import { vi as j } from "vitest";
2
+ import { c as F } from "./matchers-DmTtFk31.js";
3
+ import { m as ge } from "./matchers-DmTtFk31.js";
4
+ import { readFileSync as O } from "node:fs";
5
+ import I from "node:path";
6
+ import { Readable as M } from "node:stream";
7
+ class d extends Error {
8
+ constructor(t, o, i, n) {
9
+ super(t), this.name = "AwsError", this.code = o, this.statusCode = i, this.retryable = n;
10
10
  }
11
11
  }
12
- const L = (e) => {
13
- const t = e ? `The specified key does not exist. Key: ${e}` : "The specified key does not exist.";
14
- return new f(t, "NoSuchKey", 404, !1);
15
- }, D = (e) => {
16
- const t = e ? `The specified bucket does not exist. Bucket: ${e}` : "The specified bucket does not exist.";
17
- return new f(t, "NoSuchBucket", 404, !1);
18
- }, I = (e) => {
19
- const t = e ? `Access Denied for resource: ${e}` : "Access Denied";
20
- return new f(t, "AccessDenied", 403, !1);
21
- }, T = (e) => {
22
- const t = e ? `Requested resource not found: ${e}` : "Requested resource not found";
23
- return new f(t, "ResourceNotFoundException", 400, !1);
24
- }, K = () => new f(
12
+ const T = (e) => new d(
13
+ e ? `The specified key does not exist. Key: ${e}` : "The specified key does not exist.",
14
+ "NoSuchKey",
15
+ 404,
16
+ !1
17
+ ), K = (e) => new d(
18
+ e ? `The specified bucket does not exist. Bucket: ${e}` : "The specified bucket does not exist.",
19
+ "NoSuchBucket",
20
+ 404,
21
+ !1
22
+ ), A = (e) => new d(
23
+ e ? `Access Denied for resource: ${e}` : "Access Denied",
24
+ "AccessDenied",
25
+ 403,
26
+ !1
27
+ ), B = (e) => new d(
28
+ e ? `Requested resource not found: ${e}` : "Requested resource not found",
29
+ "ResourceNotFoundException",
30
+ 400,
31
+ !1
32
+ ), J = () => new d(
25
33
  "The conditional request failed",
26
34
  "ConditionalCheckFailedException",
27
35
  400,
28
36
  !1
29
- ), M = () => new f("Rate exceeded", "Throttling", 400, !0), A = () => new f(
37
+ ), _ = () => new d("Rate exceeded", "Throttling", 400, !0), q = () => new d(
30
38
  "We encountered an internal error. Please try again.",
31
39
  "InternalServerError",
32
40
  500,
33
41
  !0
34
- );
35
- function B(e) {
42
+ ), z = (e) => {
36
43
  try {
37
44
  return JSON.stringify(e, void 0, 2);
38
45
  } catch {
39
46
  return typeof e == "object" && e !== null ? "[Complex Object]" : typeof e == "string" ? e : typeof e == "number" || typeof e == "boolean" ? String(e) : "[Non-serializable value]";
40
47
  }
41
- }
42
- function j() {
43
- return {
44
- enabled: !1,
45
- log(e, t) {
46
- if (this.enabled)
47
- if (t === void 0)
48
- console.log(
49
- `${y.magenta("aws-sdk-vitest-mock(debug):")} ${e}`
50
- );
51
- else {
52
- const n = B(t);
53
- console.log(
54
- `${y.magenta("aws-sdk-vitest-mock(debug):")} ${e}
55
- ${n}`
56
- );
57
- }
58
- }
59
- };
60
- }
61
- function S(e) {
62
- e.enabled = !0;
63
- }
64
- function w(e) {
65
- e.enabled = !1;
66
- }
67
- function J(e) {
68
- const t = F.resolve(e), n = P(t, "utf8");
69
- return e.endsWith(".json") ? JSON.parse(n) : n;
70
- }
71
- function _(e, t = {}) {
72
- const { pageSize: n = 10, tokenKey: i = "NextToken", itemsKey: o = "Items" } = t;
48
+ }, v = (e, t) => {
49
+ const o = F.magenta("aws-sdk-vitest-mock(debug):");
50
+ if (t === void 0)
51
+ console.log(`${o} ${e}`);
52
+ else {
53
+ const i = z(t);
54
+ console.log(`${o} ${e}
55
+ ${i}`);
56
+ }
57
+ }, L = (e = !1) => ({
58
+ enabled: e,
59
+ explicitlySet: !1,
60
+ log(t, o) {
61
+ this.enabled && v(t, o);
62
+ },
63
+ logDirect(t, o) {
64
+ v(t, o);
65
+ }
66
+ }), w = (e) => {
67
+ e.enabled = !0, e.explicitlySet = !0;
68
+ }, D = (e) => {
69
+ e.enabled = !1, e.explicitlySet = !0;
70
+ }, V = (e) => {
71
+ const t = I.resolve(e), o = O(t, "utf8");
72
+ return e.endsWith(".json") ? JSON.parse(o) : o;
73
+ }, U = (e, t = {}) => {
74
+ const { pageSize: o = 10, tokenKey: i = "NextToken", itemsKey: n = "Items" } = t;
73
75
  if (e.length === 0)
74
- return [{ [o]: [] }];
76
+ return [{ [n]: [] }];
75
77
  const s = [];
76
- for (let r = 0; r < e.length; r += n) {
77
- const c = e.slice(r, r + n), l = r + n < e.length, u = { [o]: c };
78
+ for (let r = 0; r < e.length; r += o) {
79
+ const c = e.slice(r, r + o), l = r + o < e.length, u = { [n]: c };
78
80
  if (l) {
79
- const g = u, a = c[c.length - 1];
80
- g[i] = a;
81
+ const a = u, g = c[c.length - 1];
82
+ a[i] = g;
81
83
  }
82
84
  s.push(u);
83
85
  }
84
86
  return s;
85
- }
86
- function q() {
87
- return typeof process < "u" && process.versions?.node ? "node" : typeof process < "u" && process.versions?.bun ? "bun" : "browser";
88
- }
89
- function z(e) {
87
+ }, G = () => typeof process < "u" && process.versions?.node ? "node" : typeof process < "u" && process.versions?.bun ? "bun" : "browser", H = (e) => {
90
88
  const t = typeof e == "string" ? Buffer.from(e, "utf8") : Buffer.from(e);
91
- let n = !1;
92
- return new O({
89
+ let o = !1;
90
+ return new M({
93
91
  read() {
94
- n || (this.push(t), this.push(null), n = !0);
92
+ o || (this.push(t), this.push(null), o = !0);
95
93
  }
96
94
  });
97
- }
98
- function V(e) {
95
+ }, Q = (e) => {
99
96
  let t;
100
97
  return typeof e == "string" ? t = new TextEncoder().encode(e) : e instanceof Buffer ? t = new Uint8Array(e) : t = e, new ReadableStream({
101
- start(n) {
102
- n.enqueue(t), n.close();
98
+ start(o) {
99
+ o.enqueue(t), o.close();
103
100
  }
104
101
  });
102
+ }, S = (e) => {
103
+ const t = G();
104
+ return t === "node" || t === "bun" ? H(e) : Q(e);
105
+ };
106
+ let $ = !1;
107
+ function ce(e) {
108
+ $ = e;
105
109
  }
106
- function k(e) {
107
- const t = q();
108
- return t === "node" || t === "bun" ? z(e) : V(e);
110
+ function p(e) {
111
+ return e.explicitlySet ? e.enabled : $;
109
112
  }
110
- function $(e, t) {
111
- return Object.keys(t).every((n) => {
112
- const i = t[n], o = e[n];
113
- return i && typeof i == "object" && !Array.isArray(i) ? typeof o != "object" || o === null ? !1 : $(
114
- o,
113
+ function N(e, t) {
114
+ return Object.keys(t).every((o) => {
115
+ const i = t[o], n = e[o];
116
+ return i && typeof i == "object" && !Array.isArray(i) ? typeof n != "object" || n === null ? !1 : N(
117
+ n,
115
118
  i
116
- ) : o === i;
119
+ ) : n === i;
117
120
  });
118
121
  }
119
- function N(e, t) {
122
+ function x(e, t) {
120
123
  if (e === t) return !0;
121
124
  if (typeof e != "object" || e === null || typeof t != "object" || t === null)
122
125
  return e === t;
123
- const n = Object.keys(e), i = Object.keys(t);
124
- return n.length !== i.length ? !1 : i.every((o) => {
125
- if (!Object.prototype.hasOwnProperty.call(e, o)) return !1;
126
- const s = e, r = t, c = s[o], l = r[o];
127
- return typeof c == "object" && c !== null && typeof l == "object" && l !== null ? N(c, l) : c === l;
126
+ const o = Object.keys(e), i = Object.keys(t);
127
+ return o.length !== i.length ? !1 : i.every((n) => {
128
+ if (!Object.prototype.hasOwnProperty.call(e, n)) return !1;
129
+ const s = e, r = t, c = s[n], l = r[n];
130
+ return typeof c == "object" && c !== null && typeof l == "object" && l !== null ? x(c, l) : c === l;
128
131
  });
129
132
  }
130
- function C(e) {
131
- return async function(t) {
132
- const n = () => this;
133
- e.debugLogger.log(
134
- `Received command: ${t.constructor.name}`,
135
- t.input
136
- );
137
- const i = e.map.get(
138
- t.constructor
139
- );
140
- if (i) {
141
- e.debugLogger.log(
142
- `Found ${i.length} mock(s) for ${t.constructor.name}`
143
- );
144
- const s = i.findIndex((r) => r.strict ? r.matcher && N(t.input, r.matcher) : !r.matcher || $(t.input, r.matcher));
145
- if (s === -1) {
146
- e.debugLogger.log(
147
- `No matching mock found for ${t.constructor.name}`,
148
- t.input
149
- );
150
- const r = i.map((l, u) => {
151
- const g = l.matcher ? JSON.stringify(l.matcher, void 0, 2) : "any input", a = l.strict ? " (strict mode)" : "";
152
- return ` Mock #${u + 1}: ${g}${a}`;
153
- }).join(`
154
- `), c = JSON.stringify(t.input, void 0, 2);
155
- throw new Error(
156
- `No matching mock found for ${t.constructor.name}.
133
+ function X(e, t, o) {
134
+ const i = t.map((s, r) => {
135
+ const c = s.matcher ? JSON.stringify(s.matcher, void 0, 2) : "any input", l = s.strict ? " (strict mode)" : "";
136
+ return ` Mock #${r + 1}: ${c}${l}`;
137
+ }).join(`
138
+ `), n = JSON.stringify(o, void 0, 2);
139
+ return new Error(
140
+ `No matching mock found for ${e}.
157
141
 
158
- Found ${i.length} mock(s) but none matched the input.
142
+ Found ${t.length} mock(s) but none matched the input.
159
143
 
160
144
  Configured mocks:
161
- ${r}
145
+ ${i}
162
146
 
163
147
  Received input:
164
- ${c}
148
+ ${n}
165
149
 
166
150
  Tip: Enable debug mode with enableDebug() for detailed matching information.`
167
- );
168
- } else {
169
- const r = i[s];
170
- if (!r)
171
- throw new Error(`Mock at index ${s} not found`);
172
- return e.debugLogger.log(
173
- `Using mock at index ${s} for ${t.constructor.name}`
174
- ), r.once && (i.splice(s, 1), e.debugLogger.log(
175
- `Removed one-time mock for ${t.constructor.name}`
176
- )), r.handler(
177
- t.input,
178
- n()
179
- );
180
- }
181
- } else
182
- e.debugLogger.log(
183
- `No mocks configured for ${t.constructor.name}`
184
- );
185
- const o = JSON.stringify(t.input, void 0, 2);
186
- throw new Error(
187
- `No mock configured for command: ${t.constructor.name}.
151
+ );
152
+ }
153
+ function Y(e, t) {
154
+ const o = JSON.stringify(t, void 0, 2);
155
+ return new Error(
156
+ `No mock configured for command: ${e}.
188
157
 
189
158
  Received input:
190
159
  ${o}
191
160
 
192
- Did you forget to call mockClient.on(${t.constructor.name})?`
161
+ Did you forget to call mockClient.on(${e})?`
162
+ );
163
+ }
164
+ function Z(e, t) {
165
+ return e.findIndex((o) => o.strict ? o.matcher && x(t, o.matcher) : !o.matcher || N(t, o.matcher));
166
+ }
167
+ function E(e) {
168
+ return async function(t) {
169
+ const o = () => this, i = p(e.debugLogger), n = t.constructor.name;
170
+ i && e.debugLogger.logDirect(
171
+ `Received command: ${n}`,
172
+ t.input
173
+ );
174
+ const s = e.map.get(
175
+ t.constructor
193
176
  );
177
+ if (!s)
178
+ throw i && e.debugLogger.logDirect(
179
+ `No mocks configured for ${n}`
180
+ ), Y(n, t.input);
181
+ i && e.debugLogger.logDirect(
182
+ `Found ${s.length} mock(s) for ${n}`
183
+ );
184
+ const r = Z(s, t.input);
185
+ if (r === -1)
186
+ throw i && e.debugLogger.logDirect(
187
+ `No matching mock found for ${n}`,
188
+ t.input
189
+ ), X(n, s, t.input);
190
+ const c = s[r];
191
+ if (!c)
192
+ throw new Error(`Mock at index ${r} not found`);
193
+ return i && e.debugLogger.logDirect(
194
+ `Using mock at index ${r} for ${n}`
195
+ ), c.once && (s.splice(r, 1), i && e.debugLogger.logDirect(
196
+ `Removed one-time mock for ${n}`
197
+ )), c.handler(t.input, o());
194
198
  };
195
199
  }
196
- function R(e, t, n, i = {}) {
197
- const o = (r, c, l) => {
200
+ function C(e, t, o, i = {}) {
201
+ const n = (r, c, l) => {
198
202
  const u = {
199
- matcher: n,
203
+ matcher: o,
200
204
  handler: r,
201
205
  once: c,
202
206
  strict: !!i.strict
203
- }, g = e.map.get(t) ?? [];
207
+ }, a = e.map.get(t) ?? [], g = p(e.debugLogger);
204
208
  if (c) {
205
- const a = g.findIndex((d) => !d.once);
206
- a === -1 ? g.push(u) : g.splice(a, 0, u), e.map.set(
209
+ const f = a.findIndex((h) => !h.once);
210
+ f === -1 ? a.push(u) : a.splice(f, 0, u), e.map.set(
207
211
  t,
208
- g
209
- ), e.debugLogger.log(
212
+ a
213
+ ), g && e.debugLogger.logDirect(
210
214
  `Configured ${l}Once for ${t.name}`,
211
- n ? { matcher: n, strict: !!i.strict } : void 0
215
+ o ? { matcher: o, strict: !!i.strict } : void 0
212
216
  );
213
217
  } else {
214
- const a = g.filter(
215
- (d) => d.once || JSON.stringify(d.matcher) !== JSON.stringify(n)
218
+ const f = a.filter(
219
+ (h) => h.once || JSON.stringify(h.matcher) !== JSON.stringify(o)
216
220
  );
217
- a.push(u), e.map.set(
221
+ f.push(u), e.map.set(
218
222
  t,
219
- a
220
- ), e.debugLogger.log(
223
+ f
224
+ ), g && e.debugLogger.logDirect(
221
225
  `Configured ${l} for ${t.name}`,
222
- n ? { matcher: n, strict: !!i.strict } : void 0
226
+ o ? { matcher: o, strict: !!i.strict } : void 0
223
227
  );
224
228
  }
225
229
  }, s = {
226
230
  resolves(r) {
227
- return o(() => Promise.resolve(r), !1, "resolves"), s;
231
+ return n(() => Promise.resolve(r), !1, "resolves"), s;
228
232
  },
229
233
  rejects(r) {
230
- return o(
234
+ return n(
231
235
  () => {
232
236
  const c = typeof r == "string" ? new Error(r) : r;
233
237
  return Promise.reject(c);
@@ -237,13 +241,13 @@ function R(e, t, n, i = {}) {
237
241
  ), s;
238
242
  },
239
243
  callsFake(r) {
240
- return o(r, !1, "callsFake"), s;
244
+ return n(r, !1, "callsFake"), s;
241
245
  },
242
246
  resolvesOnce(r) {
243
- return o(() => Promise.resolve(r), !0, "resolves"), s;
247
+ return n(() => Promise.resolve(r), !0, "resolves"), s;
244
248
  },
245
249
  rejectsOnce(r) {
246
- return o(
250
+ return n(
247
251
  () => {
248
252
  const c = typeof r == "string" ? new Error(r) : r;
249
253
  return Promise.reject(c);
@@ -253,18 +257,18 @@ function R(e, t, n, i = {}) {
253
257
  ), s;
254
258
  },
255
259
  callsFakeOnce(r) {
256
- return o(r, !0, "callsFake"), s;
260
+ return n(r, !0, "callsFake"), s;
257
261
  },
258
262
  resolvesStream(r) {
259
- return o(
260
- () => Promise.resolve({ Body: k(r) }),
263
+ return n(
264
+ () => Promise.resolve({ Body: S(r) }),
261
265
  !1,
262
266
  "resolvesStream"
263
267
  ), s;
264
268
  },
265
269
  resolvesStreamOnce(r) {
266
- return o(
267
- () => Promise.resolve({ Body: k(r) }),
270
+ return n(
271
+ () => Promise.resolve({ Body: S(r) }),
268
272
  !0,
269
273
  "resolvesStream"
270
274
  ), s;
@@ -273,96 +277,96 @@ function R(e, t, n, i = {}) {
273
277
  const l = (u) => {
274
278
  setTimeout(() => u(r), c);
275
279
  };
276
- return o(() => new Promise(l), !1, "resolvesWithDelay"), s;
280
+ return n(() => new Promise(l), !1, "resolvesWithDelay"), s;
277
281
  },
278
282
  rejectsWithDelay(r, c) {
279
- const l = typeof r == "string" ? new Error(r) : r, u = (g, a) => {
280
- setTimeout(() => a(l), c);
283
+ const l = typeof r == "string" ? new Error(r) : r, u = (a, g) => {
284
+ setTimeout(() => g(l), c);
281
285
  };
282
- return o(() => new Promise(u), !1, "rejectsWithDelay"), s;
286
+ return n(() => new Promise(u), !1, "rejectsWithDelay"), s;
283
287
  },
284
288
  rejectsWithNoSuchKey(r) {
285
- return o(
286
- () => Promise.reject(L(r)),
289
+ return n(
290
+ () => Promise.reject(T(r)),
287
291
  !1,
288
292
  "rejectsWithNoSuchKey"
289
293
  ), s;
290
294
  },
291
295
  rejectsWithNoSuchBucket(r) {
292
- return o(
293
- () => Promise.reject(D(r)),
296
+ return n(
297
+ () => Promise.reject(K(r)),
294
298
  !1,
295
299
  "rejectsWithNoSuchBucket"
296
300
  ), s;
297
301
  },
298
302
  rejectsWithAccessDenied(r) {
299
- return o(
300
- () => Promise.reject(I(r)),
303
+ return n(
304
+ () => Promise.reject(A(r)),
301
305
  !1,
302
306
  "rejectsWithAccessDenied"
303
307
  ), s;
304
308
  },
305
309
  rejectsWithResourceNotFound(r) {
306
- return o(
307
- () => Promise.reject(T(r)),
310
+ return n(
311
+ () => Promise.reject(B(r)),
308
312
  !1,
309
313
  "rejectsWithResourceNotFound"
310
314
  ), s;
311
315
  },
312
316
  rejectsWithConditionalCheckFailed() {
313
- return o(
314
- () => Promise.reject(K()),
317
+ return n(
318
+ () => Promise.reject(J()),
315
319
  !1,
316
320
  "rejectsWithConditionalCheckFailed"
317
321
  ), s;
318
322
  },
319
323
  rejectsWithThrottling() {
320
- return o(
321
- () => Promise.reject(M()),
324
+ return n(
325
+ () => Promise.reject(_()),
322
326
  !1,
323
327
  "rejectsWithThrottling"
324
328
  ), s;
325
329
  },
326
330
  rejectsWithInternalServerError() {
327
- return o(
328
- () => Promise.reject(A()),
331
+ return n(
332
+ () => Promise.reject(q()),
329
333
  !1,
330
334
  "rejectsWithInternalServerError"
331
335
  ), s;
332
336
  },
333
337
  resolvesPaginated(r, c = {}) {
334
- const l = _(r, c);
338
+ const l = U(r, c);
335
339
  let u = 0;
336
340
  return e.debugLogger.log(
337
341
  `Configured resolvesPaginated for ${t.name}`,
338
342
  { pageSize: c.pageSize, itemsCount: r.length }
339
- ), o(
340
- (g) => {
341
- const a = c.tokenKey || "NextToken", d = c.inputTokenKey || a, m = g[d];
342
- if (m != null) {
343
- const E = c.itemsKey || "Items";
344
- let b = 0;
345
- for (const x of l) {
346
- const p = x[E];
347
- if (p && p.length > 0) {
348
- const W = p[p.length - 1];
349
- if (JSON.stringify(W) === JSON.stringify(m)) {
350
- u = b + 1;
343
+ ), n(
344
+ (a) => {
345
+ const g = c.tokenKey || "NextToken", f = c.inputTokenKey || g, b = a[f];
346
+ if (b != null) {
347
+ const R = c.itemsKey || "Items";
348
+ let k = 0;
349
+ for (const W of l) {
350
+ const m = W[R];
351
+ if (m && m.length > 0) {
352
+ const P = m[m.length - 1];
353
+ if (JSON.stringify(P) === JSON.stringify(b)) {
354
+ u = k + 1;
351
355
  break;
352
356
  }
353
357
  }
354
- b++;
358
+ k++;
355
359
  }
356
360
  } else
357
361
  u = 0;
358
- const h = (
362
+ const y = (
359
363
  // eslint-disable-next-line security/detect-object-injection
360
364
  l[u] || // eslint-disable-next-line unicorn/prefer-at -- TypeScript target doesn't support Array.at() method
361
365
  l[l.length - 1] || l[0]
362
366
  );
363
- if (!h)
367
+ if (!y)
364
368
  throw new Error("No paginated responses available");
365
- return u = Math.min(u + 1, l.length - 1), Promise.resolve(h);
369
+ return u = Math.min(u + 1, l.length - 1), Promise.resolve(y);
366
370
  },
367
371
  !1,
368
372
  "resolvesPaginated"
@@ -372,9 +376,9 @@ function R(e, t, n, i = {}) {
372
376
  return e.debugLogger.log(
373
377
  `Configured resolvesFromFile for ${t.name}`,
374
378
  { filePath: r }
375
- ), o(
379
+ ), n(
376
380
  () => {
377
- const c = J(r);
381
+ const c = V(r);
378
382
  return Promise.resolve(c);
379
383
  },
380
384
  !1,
@@ -384,71 +388,74 @@ function R(e, t, n, i = {}) {
384
388
  };
385
389
  return s;
386
390
  }
387
- const ee = (e) => {
391
+ const ie = (e) => {
388
392
  const t = {
389
393
  map: /* @__PURE__ */ new WeakMap(),
390
- debugLogger: j()
391
- }, n = e.prototype, i = v.spyOn(n, "send").mockImplementation(C(t));
394
+ debugLogger: L()
395
+ }, o = e.prototype, i = j.spyOn(o, "send").mockImplementation(E(t));
392
396
  return {
393
397
  client: void 0,
394
- on: (s, r, c) => R(
398
+ on: (s, r, c) => C(
395
399
  t,
396
400
  s,
397
401
  r,
398
402
  c
399
403
  ),
400
404
  reset: () => {
401
- t.debugLogger.log("Clearing call history (mocks preserved)"), i.mockClear();
405
+ p(t.debugLogger) && t.debugLogger.logDirect(
406
+ "Clearing call history (mocks preserved)"
407
+ ), i.mockClear();
402
408
  },
403
409
  restore: () => {
404
- t.debugLogger.log(
410
+ p(t.debugLogger) && t.debugLogger.logDirect(
405
411
  "Restoring original client behavior and clearing all mocks"
406
412
  ), i.mockRestore(), t.map = /* @__PURE__ */ new WeakMap();
407
413
  },
408
414
  calls: () => i.mock.calls.map((s) => s[0]),
409
415
  __rawCalls: () => i.mock.calls,
410
416
  enableDebug: () => {
411
- S(t.debugLogger);
417
+ w(t.debugLogger);
412
418
  },
413
419
  disableDebug: () => {
414
- w(t.debugLogger);
420
+ D(t.debugLogger);
415
421
  }
416
422
  };
417
- }, te = (e) => {
423
+ }, le = (e) => {
418
424
  const t = {
419
425
  map: /* @__PURE__ */ new WeakMap(),
420
- debugLogger: j()
421
- }, n = v.spyOn(e, "send").mockImplementation(C(t));
426
+ debugLogger: L()
427
+ }, o = j.spyOn(e, "send").mockImplementation(E(t));
422
428
  return {
423
429
  client: e,
424
- on: (o, s, r) => R(
430
+ on: (n, s, r) => C(
425
431
  t,
426
- o,
432
+ n,
427
433
  s,
428
434
  r
429
435
  ),
430
436
  reset: () => {
431
- t.debugLogger.log(
437
+ p(t.debugLogger) && t.debugLogger.logDirect(
432
438
  "Clearing call history (mocks preserved) for client instance"
433
- ), n.mockClear();
439
+ ), o.mockClear();
434
440
  },
435
441
  restore: () => {
436
- t.debugLogger.log(
442
+ p(t.debugLogger) && t.debugLogger.logDirect(
437
443
  "Restoring original client behavior and clearing all mocks for client instance"
438
- ), n.mockRestore(), t.map = /* @__PURE__ */ new WeakMap();
444
+ ), o.mockRestore(), t.map = /* @__PURE__ */ new WeakMap();
439
445
  },
440
- calls: () => n.mock.calls.map((o) => o[0]),
441
- __rawCalls: () => n.mock.calls,
446
+ calls: () => o.mock.calls.map((n) => n[0]),
447
+ __rawCalls: () => o.mock.calls,
442
448
  enableDebug: () => {
443
- S(t.debugLogger);
449
+ w(t.debugLogger);
444
450
  },
445
451
  disableDebug: () => {
446
- w(t.debugLogger);
452
+ D(t.debugLogger);
447
453
  }
448
454
  };
449
455
  };
450
456
  export {
451
- ne as matchers,
452
- ee as mockClient,
453
- te as mockClientInstance
457
+ ge as matchers,
458
+ ie as mockClient,
459
+ le as mockClientInstance,
460
+ ce as setGlobalDebug
454
461
  };
@@ -3,6 +3,27 @@ import { HttpHandlerOptions, MetadataBearer } from '@smithy/types';
3
3
  import { Mock } from 'vitest';
4
4
  import { PaginatorOptions } from './utils/paginator-helpers.js';
5
5
  import { StreamInput } from './utils/stream-helpers.js';
6
+ /**
7
+ * Set global debug mode for all mocks.
8
+ * When enabled, all mocks will log debug information unless explicitly disabled at the mock level.
9
+ *
10
+ * @param enabled - Whether to enable debug logging globally
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * import { setGlobalDebug, mockClient } from 'aws-sdk-vitest-mock';
15
+ * import { S3Client } from '@aws-sdk/client-s3';
16
+ *
17
+ * // Enable debug for all mocks
18
+ * setGlobalDebug(true);
19
+ *
20
+ * const s3Mock = mockClient(S3Client); // Automatically has debug enabled
21
+ *
22
+ * // Disable debug for a specific mock
23
+ * s3Mock.disableDebug(); // This mock won't log, but others will
24
+ * ```
25
+ */
26
+ export declare function setGlobalDebug(enabled: boolean): void;
6
27
  export type StructuralCommand<TInput extends object, TOutput extends MetadataBearer> = SmithyCommand<TInput, TOutput, any, any, any> | {
7
28
  readonly input: TInput;
8
29
  readonly __awsSdkVitestMockOutput?: TOutput;
@@ -1,7 +1,9 @@
1
1
  export interface DebugLogger {
2
2
  enabled: boolean;
3
+ explicitlySet: boolean;
3
4
  log: (message: string, data?: unknown) => void;
5
+ logDirect: (message: string, data?: unknown) => void;
4
6
  }
5
- export declare function createDebugLogger(): DebugLogger;
6
- export declare function enableDebug(logger: DebugLogger): void;
7
- export declare function disableDebug(logger: DebugLogger): void;
7
+ export declare const createDebugLogger: (initialEnabled?: boolean) => DebugLogger;
8
+ export declare const enableDebug: (logger: DebugLogger) => void;
9
+ export declare const disableDebug: (logger: DebugLogger) => void;
@@ -1 +1 @@
1
- export declare function loadFixture(filePath: string): unknown;
1
+ export declare const loadFixture: (filePath: string) => unknown;
@@ -95,4 +95,4 @@ export interface PaginatedResponse<T = unknown> {
95
95
  * // ]
96
96
  * ```
97
97
  */
98
- export declare function createPaginatedResponses<T>(items: T[], options?: PaginatorOptions): PaginatedResponse<T>[];
98
+ export declare const createPaginatedResponses: <T>(items: T[], options?: PaginatorOptions) => PaginatedResponse<T>[];
@@ -3,4 +3,4 @@ export type StreamInput = string | Buffer | Uint8Array;
3
3
  /**
4
4
  * Creates an appropriate stream for the current environment
5
5
  */
6
- export declare function createStream(data: StreamInput): Readable | ReadableStream<Uint8Array>;
6
+ export declare const createStream: (data: StreamInput) => Readable | ReadableStream<Uint8Array>;
@@ -1,4 +1,4 @@
1
- "use strict";const e={red:t=>`\x1B[31m${t}\x1B[39m`,green:t=>`\x1B[32m${t}\x1B[39m`,yellow:t=>`\x1B[33m${t}\x1B[39m`,blue:t=>`\x1B[34m${t}\x1B[39m`,magenta:t=>`\x1B[35m${t}\x1B[39m`,cyan:t=>`\x1B[36m${t}\x1B[39m`,gray:t=>`\x1B[90m${t}\x1B[39m`,bold:t=>`\x1B[1m${t}\x1B[22m`},$=t=>{const c=t.__rawCalls();return Array.isArray(c)?c.filter(a=>Array.isArray(a)&&a.length>0):[]},f={toHaveReceivedCommand(t,c){const a=$(t),r=a.some(o=>o[0]instanceof c),m=c.name;return{pass:r,message:()=>{if(r)return`Expected AWS SDK mock not to have received command ${e.red(m)}`;const o=a.map(n=>n[0].constructor?.name??"Unknown");return o.length===0?`Expected AWS SDK mock to have received command ${e.red(m)}, but ${e.gray("no commands were received")}`:`Expected AWS SDK mock to have received command ${e.red(m)}, but received: ${e.yellow(o.join(", "))}`}}},toHaveReceivedCommandTimes(t,c,a){const r=$(t).filter(n=>n[0]instanceof c),m=r.length===a,o=c.name;return{pass:m,message:()=>m?`Expected AWS SDK mock not to have received command ${o} ${a} times`:`Expected AWS SDK mock to have received command ${o} ${a} times, but received ${r.length} times`}},toHaveReceivedCommandWith(t,c,a){const r=$(t).filter(n=>n[0]instanceof c),m=r.some(n=>this.equals(n[0].input,a)),o=c.name;return{pass:m,message:()=>{if(m){const s=e.red(o),u=e.cyan(JSON.stringify(a,void 0,2));return`Expected AWS SDK mock not to have received command ${s} with input:
1
+ "use strict";const e={red:t=>`\x1B[31m${t}\x1B[39m`,green:t=>`\x1B[32m${t}\x1B[39m`,yellow:t=>`\x1B[33m${t}\x1B[39m`,blue:t=>`\x1B[34m${t}\x1B[39m`,magenta:t=>`\x1B[35m${t}\x1B[39m`,cyan:t=>`\x1B[36m${t}\x1B[39m`,gray:t=>`\x1B[90m${t}\x1B[39m`,bold:t=>`\x1B[1m${t}\x1B[22m`},$=t=>{const c=t.__rawCalls();return Array.isArray(c)?c.filter(a=>Array.isArray(a)&&a.length>0):[]},f={toHaveReceivedCommand(t,c){const a=$(t),r=a.some(([o])=>o instanceof c),m=c.name;return{pass:r,message:()=>{if(r)return`Expected AWS SDK mock not to have received command ${e.red(m)}`;const o=a.map(([n])=>n.constructor?.name??"Unknown");return o.length===0?`Expected AWS SDK mock to have received command ${e.red(m)}, but ${e.gray("no commands were received")}`:`Expected AWS SDK mock to have received command ${e.red(m)}, but received: ${e.yellow(o.join(", "))}`}}},toHaveReceivedCommandTimes(t,c,a){const r=$(t).filter(n=>n[0]instanceof c),m=r.length===a,o=c.name;return{pass:m,message:()=>m?`Expected AWS SDK mock not to have received command ${o} ${a} times`:`Expected AWS SDK mock to have received command ${o} ${a} times, but received ${r.length} times`}},toHaveReceivedCommandWith(t,c,a){const r=$(t).filter(n=>n[0]instanceof c),m=r.some(n=>this.equals(n[0].input,a)),o=c.name;return{pass:m,message:()=>{if(m){const s=e.red(o),u=e.cyan(JSON.stringify(a,void 0,2));return`Expected AWS SDK mock not to have received command ${s} with input:
2
2
  ${u}`}if(r.length===0){const s=e.red(o),u=e.cyan(JSON.stringify(a,void 0,2)),i=e.gray(`${o} was never called`);return`Expected AWS SDK mock to have received command ${s} with input:
3
3
  ${u}
4
4
 
@@ -31,13 +31,13 @@ const e = {
31
31
  * ```
32
32
  */
33
33
  toHaveReceivedCommand(t, c) {
34
- const a = $(t), r = a.some((o) => o[0] instanceof c), m = c.name;
34
+ const a = $(t), r = a.some(([o]) => o instanceof c), m = c.name;
35
35
  return {
36
36
  pass: r,
37
37
  message: () => {
38
38
  if (r)
39
39
  return `Expected AWS SDK mock not to have received command ${e.red(m)}`;
40
- const o = a.map((n) => n[0].constructor?.name ?? "Unknown");
40
+ const o = a.map(([n]) => n.constructor?.name ?? "Unknown");
41
41
  return o.length === 0 ? `Expected AWS SDK mock to have received command ${e.red(m)}, but ${e.gray("no commands were received")}` : `Expected AWS SDK mock to have received command ${e.red(m)}, but received: ${e.yellow(o.join(", "))}`;
42
42
  }
43
43
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aws-sdk-vitest-mock",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "type": "module",
5
5
  "main": "./index.cjs",
6
6
  "module": "./index.js",
package/vitest-setup.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";const e=require("vitest"),t=require("./matchers-Dkkl4vtx.cjs");e.expect.extend(t.matchers);
1
+ "use strict";const e=require("vitest"),t=require("./matchers-CNhdB_9q.cjs");e.expect.extend(t.matchers);
package/vitest-setup.js CHANGED
@@ -1,3 +1,3 @@
1
1
  import { expect as m } from "vitest";
2
- import { m as e } from "./matchers-ClGOsQx8.js";
2
+ import { m as e } from "./matchers-DmTtFk31.js";
3
3
  m.extend(e);