@sanity-labs/client-fake-for-test 0.10.0 → 0.12.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.cts CHANGED
@@ -152,12 +152,12 @@ export declare interface CreateTestClientOptions {
152
152
  */
153
153
  token?: string;
154
154
  /**
155
- * Pluggable write interceptor — runs on each write through the document
156
- * mutation API (create/patch/delete/transaction; not the release/version
157
- * action API) before the store changes, and may throw to reject it. The
158
- * client has no opinion about the policy; callers (e.g. a workflow test bench
159
- * enforcing lake mutation guards) supply it. Inherited by `withConfig`
160
- * siblings. See {@link MutationGuard}.
155
+ * Pluggable write interceptor — runs once for each document's net change in
156
+ * a commit. Document publish/unpublish actions expose their underlying
157
+ * draft/published mutations; release/version actions remain unhooked. Return
158
+ * denial descriptors to reject atomically with `GuardDeniedError`; a
159
+ * thrown callback error propagates unchanged. The client owns no policy.
160
+ * Inherited by `withConfig` siblings. See {@link MutationGuard}.
161
161
  */
162
162
  mutationGuard?: MutationGuard;
163
163
  /**
@@ -246,7 +246,11 @@ export declare interface DocumentBody {
246
246
  [field: string]: unknown;
247
247
  }
248
248
 
249
- export declare type DocumentValuePermission = "create" | "read" | "update";
249
+ export declare type DocumentValuePermission =
250
+ | "create"
251
+ | "manage"
252
+ | "read"
253
+ | "update";
250
254
 
251
255
  /**
252
256
  * Error helpers shared across the fake.
@@ -397,6 +401,30 @@ export declare interface GuardConfig {
397
401
  recorded?: Set<string>;
398
402
  }
399
403
 
404
+ /** HTTP-shaped guard rejection matching the error exposed by `@sanity/client`. */
405
+ export declare class GuardDeniedError extends Error {
406
+ readonly statusCode = 403;
407
+ readonly type = "guardDeniedError";
408
+ readonly denials: MutationGuardDenial[];
409
+ readonly details: GuardDeniedResponse["body"]["error"];
410
+ readonly response: GuardDeniedResponse;
411
+ constructor(denials: readonly MutationGuardDenial[]);
412
+ }
413
+
414
+ export declare interface GuardDeniedResponse {
415
+ body: {
416
+ error: {
417
+ type: "guardDeniedError";
418
+ denials: MutationGuardDenial[];
419
+ };
420
+ };
421
+ url: string;
422
+ method: "POST";
423
+ headers: Record<string, string>;
424
+ statusCode: 403;
425
+ statusMessage: "Forbidden";
426
+ }
427
+
400
428
  export declare const isDraftId: (id: string) => boolean;
401
429
 
402
430
  export declare const isReleaseDocId: (id: string) => boolean;
@@ -416,67 +444,46 @@ export declare interface MultipleMutationResult {
416
444
  }
417
445
 
418
446
  /**
419
- * A pluggable write interceptor, configured via
420
- * `createTestClient({ mutationGuard })`. It runs on each write through the
421
- * document mutation API — `create` / `createOrReplace` / `createIfNotExists` /
422
- * `patch` / `delete` and the equivalent `transaction()` operations — and on the
423
- * document publish/unpublish actions (`sanity.action.document.publish` /
424
- * `.unpublish` via `client.action`) — before the store changes; **throw to
425
- * reject the write** (the throw propagates out of the client call, exactly as
426
- * a real lake rejection would). The release/version action API
427
- * (`client.releases.*`, `createVersion`, the `sanity.action.release.*` and
428
- * `*.version.*` action types) is **not** intercepted.
429
- *
430
- * The client itself has no opinion about *what* a guard is — it only provides
431
- * the seam and the before/after/identity context. Callers (e.g. a workflow test
432
- * bench) supply the policy: evaluate lake mutation guards, enforce field locks,
433
- * etc. Keeping the policy in the caller avoids duplicating guard-evaluation
434
- * logic the client has no business owning.
447
+ * Evaluates one net document change and returns every denying guard. Returning
448
+ * `void` allows observe-only hooks. A thrown value is a callback failure and
449
+ * propagates unchanged; only returned entries become {@link GuardDeniedError}.
435
450
  */
436
451
  export declare type MutationGuard = (
437
452
  context: MutationGuardContext,
438
- ) => void | Promise<void>;
453
+ ) =>
454
+ | readonly MutationGuardDenial[]
455
+ | void
456
+ | Promise<readonly MutationGuardDenial[] | void>;
439
457
 
440
- /** The kind of write a {@link MutationGuard} is asked to vet. */
441
- export declare type MutationGuardAction =
442
- | "create"
443
- | "update"
444
- | "delete"
445
- | "publish"
446
- | "unpublish";
458
+ /** The Content Lake mutation actions that a {@link MutationGuard} can match. */
459
+ export declare type MutationGuardAction = "create" | "update" | "delete";
447
460
 
448
- /**
449
- * The before/after image of a single document write, handed to a
450
- * {@link MutationGuard} before it is applied.
451
- *
452
- * - `before` is null on create and on a publish with no live published
453
- * document; `after` is null on delete and unpublish.
454
- * - On publish/unpublish both images are of the *published* document —
455
- * `after` on publish is the draft's content promoted onto the published id.
456
- * - `identity` is the acting user — the id bound to the client's token
457
- * (its `accessControl.currentUser`), or undefined when the client has no
458
- * identity configured.
459
- *
460
- * Treat `before`/`after` as read-only — they are the live store images, not
461
- * copies; a guard that mutates them corrupts the store.
462
- */
461
+ /** The before/final-after image of one net document change in a commit. */
463
462
  export declare interface MutationGuardContext {
464
463
  action: MutationGuardAction;
465
- before:
466
- | (SanityDocumentLike & {
467
- _id: string;
468
- _type: string;
469
- })
470
- | null;
471
- after:
472
- | (SanityDocumentLike & {
473
- _id: string;
474
- _type: string;
475
- })
476
- | null;
464
+ /** Original live store image. Treat it as read-only; it is not a copy. */
465
+ before: Readonly<
466
+ SanityDocumentLike & {
467
+ _id: string;
468
+ _type: string;
469
+ }
470
+ > | null;
471
+ /** Final live store image. Treat it as read-only; it is not a copy. */
472
+ after: Readonly<
473
+ SanityDocumentLike & {
474
+ _id: string;
475
+ _type: string;
476
+ }
477
+ > | null;
478
+ /** Acting project identity, or `undefined` on an identity-free client. */
477
479
  identity: string | undefined;
478
480
  }
479
481
 
482
+ export declare interface MutationGuardDenial {
483
+ guardID: string;
484
+ name?: string;
485
+ }
486
+
480
487
  /** Append-only record of one committed transaction (a single mutation is a 1-entry transaction). */
481
488
  export declare interface MutationLogEntry {
482
489
  transactionId: string;
@@ -599,6 +606,8 @@ export declare type Perspective = "raw" | "published" | "drafts" | string[];
599
606
  export declare interface ProjectMemberRecord {
600
607
  id: string;
601
608
  isRobot?: boolean;
609
+ /** Project-scoped roles in canonical order, independent of registration order. */
610
+ roles?: NonNullable<CurrentUser["roles"]>;
602
611
  }
603
612
 
604
613
  /**
@@ -853,8 +862,9 @@ export declare interface TestClient {
853
862
  * Dispatch one or more release / version / document actions against the
854
863
  * store. Returns a synthetic `transactionId`. Multi-action arrays are
855
864
  * applied atomically — any failure rolls back the batch. The document
856
- * publish/unpublish actions run through the access gate and the
857
- * `mutationGuard` seam; release/version actions apply unhooked.
865
+ * publish/unpublish actions run through the access gate and expose their
866
+ * net draft/published mutations to `mutationGuard`; release/version actions
867
+ * apply unhooked.
858
868
  */
859
869
  action: (
860
870
  action: Action | Action[],
package/dist/index.d.ts CHANGED
@@ -152,12 +152,12 @@ export declare interface CreateTestClientOptions {
152
152
  */
153
153
  token?: string;
154
154
  /**
155
- * Pluggable write interceptor — runs on each write through the document
156
- * mutation API (create/patch/delete/transaction; not the release/version
157
- * action API) before the store changes, and may throw to reject it. The
158
- * client has no opinion about the policy; callers (e.g. a workflow test bench
159
- * enforcing lake mutation guards) supply it. Inherited by `withConfig`
160
- * siblings. See {@link MutationGuard}.
155
+ * Pluggable write interceptor — runs once for each document's net change in
156
+ * a commit. Document publish/unpublish actions expose their underlying
157
+ * draft/published mutations; release/version actions remain unhooked. Return
158
+ * denial descriptors to reject atomically with `GuardDeniedError`; a
159
+ * thrown callback error propagates unchanged. The client owns no policy.
160
+ * Inherited by `withConfig` siblings. See {@link MutationGuard}.
161
161
  */
162
162
  mutationGuard?: MutationGuard;
163
163
  /**
@@ -246,7 +246,11 @@ export declare interface DocumentBody {
246
246
  [field: string]: unknown;
247
247
  }
248
248
 
249
- export declare type DocumentValuePermission = "create" | "read" | "update";
249
+ export declare type DocumentValuePermission =
250
+ | "create"
251
+ | "manage"
252
+ | "read"
253
+ | "update";
250
254
 
251
255
  /**
252
256
  * Error helpers shared across the fake.
@@ -397,6 +401,30 @@ export declare interface GuardConfig {
397
401
  recorded?: Set<string>;
398
402
  }
399
403
 
404
+ /** HTTP-shaped guard rejection matching the error exposed by `@sanity/client`. */
405
+ export declare class GuardDeniedError extends Error {
406
+ readonly statusCode = 403;
407
+ readonly type = "guardDeniedError";
408
+ readonly denials: MutationGuardDenial[];
409
+ readonly details: GuardDeniedResponse["body"]["error"];
410
+ readonly response: GuardDeniedResponse;
411
+ constructor(denials: readonly MutationGuardDenial[]);
412
+ }
413
+
414
+ export declare interface GuardDeniedResponse {
415
+ body: {
416
+ error: {
417
+ type: "guardDeniedError";
418
+ denials: MutationGuardDenial[];
419
+ };
420
+ };
421
+ url: string;
422
+ method: "POST";
423
+ headers: Record<string, string>;
424
+ statusCode: 403;
425
+ statusMessage: "Forbidden";
426
+ }
427
+
400
428
  export declare const isDraftId: (id: string) => boolean;
401
429
 
402
430
  export declare const isReleaseDocId: (id: string) => boolean;
@@ -416,67 +444,46 @@ export declare interface MultipleMutationResult {
416
444
  }
417
445
 
418
446
  /**
419
- * A pluggable write interceptor, configured via
420
- * `createTestClient({ mutationGuard })`. It runs on each write through the
421
- * document mutation API — `create` / `createOrReplace` / `createIfNotExists` /
422
- * `patch` / `delete` and the equivalent `transaction()` operations — and on the
423
- * document publish/unpublish actions (`sanity.action.document.publish` /
424
- * `.unpublish` via `client.action`) — before the store changes; **throw to
425
- * reject the write** (the throw propagates out of the client call, exactly as
426
- * a real lake rejection would). The release/version action API
427
- * (`client.releases.*`, `createVersion`, the `sanity.action.release.*` and
428
- * `*.version.*` action types) is **not** intercepted.
429
- *
430
- * The client itself has no opinion about *what* a guard is — it only provides
431
- * the seam and the before/after/identity context. Callers (e.g. a workflow test
432
- * bench) supply the policy: evaluate lake mutation guards, enforce field locks,
433
- * etc. Keeping the policy in the caller avoids duplicating guard-evaluation
434
- * logic the client has no business owning.
447
+ * Evaluates one net document change and returns every denying guard. Returning
448
+ * `void` allows observe-only hooks. A thrown value is a callback failure and
449
+ * propagates unchanged; only returned entries become {@link GuardDeniedError}.
435
450
  */
436
451
  export declare type MutationGuard = (
437
452
  context: MutationGuardContext,
438
- ) => void | Promise<void>;
453
+ ) =>
454
+ | readonly MutationGuardDenial[]
455
+ | void
456
+ | Promise<readonly MutationGuardDenial[] | void>;
439
457
 
440
- /** The kind of write a {@link MutationGuard} is asked to vet. */
441
- export declare type MutationGuardAction =
442
- | "create"
443
- | "update"
444
- | "delete"
445
- | "publish"
446
- | "unpublish";
458
+ /** The Content Lake mutation actions that a {@link MutationGuard} can match. */
459
+ export declare type MutationGuardAction = "create" | "update" | "delete";
447
460
 
448
- /**
449
- * The before/after image of a single document write, handed to a
450
- * {@link MutationGuard} before it is applied.
451
- *
452
- * - `before` is null on create and on a publish with no live published
453
- * document; `after` is null on delete and unpublish.
454
- * - On publish/unpublish both images are of the *published* document —
455
- * `after` on publish is the draft's content promoted onto the published id.
456
- * - `identity` is the acting user — the id bound to the client's token
457
- * (its `accessControl.currentUser`), or undefined when the client has no
458
- * identity configured.
459
- *
460
- * Treat `before`/`after` as read-only — they are the live store images, not
461
- * copies; a guard that mutates them corrupts the store.
462
- */
461
+ /** The before/final-after image of one net document change in a commit. */
463
462
  export declare interface MutationGuardContext {
464
463
  action: MutationGuardAction;
465
- before:
466
- | (SanityDocumentLike & {
467
- _id: string;
468
- _type: string;
469
- })
470
- | null;
471
- after:
472
- | (SanityDocumentLike & {
473
- _id: string;
474
- _type: string;
475
- })
476
- | null;
464
+ /** Original live store image. Treat it as read-only; it is not a copy. */
465
+ before: Readonly<
466
+ SanityDocumentLike & {
467
+ _id: string;
468
+ _type: string;
469
+ }
470
+ > | null;
471
+ /** Final live store image. Treat it as read-only; it is not a copy. */
472
+ after: Readonly<
473
+ SanityDocumentLike & {
474
+ _id: string;
475
+ _type: string;
476
+ }
477
+ > | null;
478
+ /** Acting project identity, or `undefined` on an identity-free client. */
477
479
  identity: string | undefined;
478
480
  }
479
481
 
482
+ export declare interface MutationGuardDenial {
483
+ guardID: string;
484
+ name?: string;
485
+ }
486
+
480
487
  /** Append-only record of one committed transaction (a single mutation is a 1-entry transaction). */
481
488
  export declare interface MutationLogEntry {
482
489
  transactionId: string;
@@ -599,6 +606,8 @@ export declare type Perspective = "raw" | "published" | "drafts" | string[];
599
606
  export declare interface ProjectMemberRecord {
600
607
  id: string;
601
608
  isRobot?: boolean;
609
+ /** Project-scoped roles in canonical order, independent of registration order. */
610
+ roles?: NonNullable<CurrentUser["roles"]>;
602
611
  }
603
612
 
604
613
  /**
@@ -853,8 +862,9 @@ export declare interface TestClient {
853
862
  * Dispatch one or more release / version / document actions against the
854
863
  * store. Returns a synthetic `transactionId`. Multi-action arrays are
855
864
  * applied atomically — any failure rolls back the batch. The document
856
- * publish/unpublish actions run through the access gate and the
857
- * `mutationGuard` seam; release/version actions apply unhooked.
865
+ * publish/unpublish actions run through the access gate and expose their
866
+ * net draft/published mutations to `mutationGuard`; release/version actions
867
+ * apply unhooked.
858
868
  */
859
869
  action: (
860
870
  action: Action | Action[],