@sanity-labs/client-fake-for-test 0.9.0 → 0.10.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
@@ -108,7 +108,8 @@ export declare interface CreateTestClientOptions {
108
108
  /**
109
109
  * Opt-in access-control simulation. When set, the client exposes
110
110
  * `request({ url })` that serves `/users/me` (host-aware), the
111
- * configured ACL path, and `/projects/<projectId>/users/<ids>`,
111
+ * configured ACL path, `/projects/<projectId>` (members), and
112
+ * `/projects/<projectId>/users/<ids>`,
112
113
  * AND every mutation is gated through the supplied `grants`
113
114
  * — writes that the grants don't permit throw a `WriteAccessDeniedError`
114
115
  * shaped like Sanity's 403. Lets tests demonstrate the full
@@ -166,6 +167,8 @@ export declare interface CreateTestClientOptions {
166
167
  * tests stay green.
167
168
  */
168
169
  perspective?: Perspective;
170
+ /** Prefix composed with request tags and used alone for untagged requests. */
171
+ requestTagPrefix?: string;
169
172
  /**
170
173
  * Which API host the root handle models: the project host (default
171
174
  * `true`) or the global host (`false`) — same flag as the real
@@ -592,6 +595,12 @@ export declare type PatchOp =
592
595
 
593
596
  export declare type Perspective = "raw" | "published" | "drafts" | string[];
594
597
 
598
+ /** One row of the `/projects/<projectId>` members response. */
599
+ export declare interface ProjectMemberRecord {
600
+ id: string;
601
+ isRobot?: boolean;
602
+ }
603
+
595
604
  /**
596
605
  * A row served by the project-users directory endpoint
597
606
  * (`/projects/<projectId>/users/<id>`), mirroring Sanity's project user
@@ -873,6 +882,7 @@ export declare interface TestClient {
873
882
  projectId: string;
874
883
  dataset: string;
875
884
  perspective: Perspective;
885
+ requestTagPrefix?: string;
876
886
  token?: string;
877
887
  useProjectHostname: boolean;
878
888
  };
@@ -887,6 +897,8 @@ export declare interface TestClient {
887
897
  projectId: string;
888
898
  dataset: string;
889
899
  perspective: Perspective;
900
+ /** Prefix composed with request tags and used alone for untagged requests. */
901
+ requestTagPrefix: string;
890
902
  /**
891
903
  * Model the global API host (`false`) instead of the project host
892
904
  * (default `true`). A global-hosted sibling's `/users/me` serves the
package/dist/index.d.ts CHANGED
@@ -108,7 +108,8 @@ export declare interface CreateTestClientOptions {
108
108
  /**
109
109
  * Opt-in access-control simulation. When set, the client exposes
110
110
  * `request({ url })` that serves `/users/me` (host-aware), the
111
- * configured ACL path, and `/projects/<projectId>/users/<ids>`,
111
+ * configured ACL path, `/projects/<projectId>` (members), and
112
+ * `/projects/<projectId>/users/<ids>`,
112
113
  * AND every mutation is gated through the supplied `grants`
113
114
  * — writes that the grants don't permit throw a `WriteAccessDeniedError`
114
115
  * shaped like Sanity's 403. Lets tests demonstrate the full
@@ -166,6 +167,8 @@ export declare interface CreateTestClientOptions {
166
167
  * tests stay green.
167
168
  */
168
169
  perspective?: Perspective;
170
+ /** Prefix composed with request tags and used alone for untagged requests. */
171
+ requestTagPrefix?: string;
169
172
  /**
170
173
  * Which API host the root handle models: the project host (default
171
174
  * `true`) or the global host (`false`) — same flag as the real
@@ -592,6 +595,12 @@ export declare type PatchOp =
592
595
 
593
596
  export declare type Perspective = "raw" | "published" | "drafts" | string[];
594
597
 
598
+ /** One row of the `/projects/<projectId>` members response. */
599
+ export declare interface ProjectMemberRecord {
600
+ id: string;
601
+ isRobot?: boolean;
602
+ }
603
+
595
604
  /**
596
605
  * A row served by the project-users directory endpoint
597
606
  * (`/projects/<projectId>/users/<id>`), mirroring Sanity's project user
@@ -873,6 +882,7 @@ export declare interface TestClient {
873
882
  projectId: string;
874
883
  dataset: string;
875
884
  perspective: Perspective;
885
+ requestTagPrefix?: string;
876
886
  token?: string;
877
887
  useProjectHostname: boolean;
878
888
  };
@@ -887,6 +897,8 @@ export declare interface TestClient {
887
897
  projectId: string;
888
898
  dataset: string;
889
899
  perspective: Perspective;
900
+ /** Prefix composed with request tags and used alone for untagged requests. */
901
+ requestTagPrefix: string;
890
902
  /**
891
903
  * Model the global API host (`false`) instead of the project host
892
904
  * (default `true`). A global-hosted sibling's `/users/me` serves the
package/dist/index.js CHANGED
@@ -97,7 +97,18 @@ function serveProjectUsers(args) {
97
97
  return identity === void 0 ? [] : [toRecord(identity)];
98
98
  });
99
99
  }
100
- const PROJECT_USERS_PATH = /^\/projects\/([^/]+)\/users\/([^/]+)$/;
100
+ const PROJECT_USERS_PATH = /^\/projects\/([^/]+)\/users\/([^/]+)$/, PROJECT_PATH = /^\/projects\/([^/]+)$/;
101
+ function serveProject(args) {
102
+ const ids = /* @__PURE__ */ new Set();
103
+ for (const identity of args.identities)
104
+ ids.add(projectUserOf(identity, args.pathProjectId).id);
105
+ return {
106
+ members: [...ids].map((id) => ({
107
+ id,
108
+ ...id.startsWith("p-") ? { isRobot: !0 } : {}
109
+ }))
110
+ };
111
+ }
101
112
  function makeRequestImpl(ctx) {
102
113
  const { getAccess, projectId, dataset, useProjectHostname, listIdentities } = ctx;
103
114
  return async (opts) => {
@@ -113,8 +124,14 @@ function makeRequestImpl(ctx) {
113
124
  pathProjectId,
114
125
  identities: listIdentities()
115
126
  });
127
+ const project = path?.match(PROJECT_PATH), [, membersProjectId] = project ?? [];
128
+ if (membersProjectId !== void 0)
129
+ return serveProject({
130
+ pathProjectId: membersProjectId,
131
+ identities: listIdentities()
132
+ });
116
133
  throw fakeError(
117
- `request(): no handler for path "${path}". With access control configured, the fake serves "/users/me", "${aclPath}", and "/projects/<projectId>/users/<ids>". For any other endpoint, register a stub (client.stub("request", fn)) or intercept the HTTP call with a tool like MSW.`
134
+ `request(): no handler for path "${path}". With access control configured, the fake serves "/users/me", "${aclPath}", "/projects/<projectId>" (members), and "/projects/<projectId>/users/<ids>". For any other endpoint, register a stub (client.stub("request", fn)) or intercept the HTTP call with a tool like MSW.`
118
135
  );
119
136
  };
120
137
  }
@@ -825,7 +842,7 @@ const ISSUES_URL = "https://github.com/sanity-labs/client-fake-for-test/issues",
825
842
  },
826
843
  request: {
827
844
  what: "generic HTTP request hook \u2014 only wired up when the handle has an acting identity",
828
- workaround: "Create the client with `accessControl`, or bind a registered token (`identities` + `token` / `withConfig({ token })`), to enable request() (it serves /users/me, the ACL path, and /projects/<projectId>/users/<ids>). Or register a stub."
845
+ workaround: "Create the client with `accessControl`, or bind a registered token (`identities` + `token` / `withConfig({ token })`), to enable request() (it serves /users/me, the ACL path, /projects/<projectId>, and /projects/<projectId>/users/<ids>). Or register a stub."
829
846
  },
830
847
  dryRun: {
831
848
  what: "not a method \u2014 did you mean the `{ dryRun }` mutation option?",
@@ -1014,6 +1031,7 @@ function createTestClient(options = {}) {
1014
1031
  dataset: defaultDataset,
1015
1032
  accessControl: options.accessControl,
1016
1033
  perspective: options.perspective ?? "raw",
1034
+ requestTagPrefix: options.requestTagPrefix,
1017
1035
  mutationGuard: options.mutationGuard,
1018
1036
  token: options.token,
1019
1037
  useProjectHostname: options.useProjectHostname ?? !0
@@ -1076,6 +1094,7 @@ function makeHandle(handleArgs) {
1076
1094
  dataset,
1077
1095
  accessControl,
1078
1096
  perspective,
1097
+ requestTagPrefix,
1079
1098
  mutationGuard,
1080
1099
  token,
1081
1100
  useProjectHostname
@@ -1099,14 +1118,15 @@ function makeHandle(handleArgs) {
1099
1118
  let s = registry.get(key);
1100
1119
  return s === void 0 && (s = createTestStore(), registry.set(key, s)), s;
1101
1120
  })(), concurrentEditKey = (id) => registryKey(projectId, dataset) + " " + id, record = (transactionId, mutations, tag) => {
1121
+ const effectiveTag = effectiveRequestTag(tag);
1102
1122
  backend.log.push({
1103
1123
  transactionId,
1104
1124
  projectId,
1105
1125
  dataset,
1106
1126
  mutations,
1107
- ...tag !== void 0 ? { tag } : {}
1127
+ ...effectiveTag !== void 0 ? { tag: effectiveTag } : {}
1108
1128
  });
1109
- }, writeResult = (documents, results, transactionId, opts) => formatMutationResult(
1129
+ }, effectiveRequestTag = (tag) => requestTagPrefix === void 0 ? tag : tag ? `${requestTagPrefix}.${tag}` : requestTagPrefix, writeResult = (documents, results, transactionId, opts) => formatMutationResult(
1110
1130
  documents,
1111
1131
  results,
1112
1132
  transactionId,
@@ -1422,6 +1442,7 @@ function makeHandle(handleArgs) {
1422
1442
  projectId,
1423
1443
  dataset,
1424
1444
  perspective,
1445
+ ...requestTagPrefix !== void 0 ? { requestTagPrefix } : {},
1425
1446
  ...token !== void 0 ? { token } : {},
1426
1447
  useProjectHostname
1427
1448
  }),
@@ -1434,6 +1455,7 @@ function makeHandle(handleArgs) {
1434
1455
  dataset: config.dataset ?? dataset,
1435
1456
  accessControl: rebinds ? config.accessControl : accessControl,
1436
1457
  perspective: config.perspective ?? perspective,
1458
+ requestTagPrefix: config.requestTagPrefix ?? requestTagPrefix,
1437
1459
  mutationGuard,
1438
1460
  token: rebinds ? config.token : token,
1439
1461
  useProjectHostname: config.useProjectHostname ?? useProjectHostname
@@ -1471,7 +1493,7 @@ function makeHandle(handleArgs) {
1471
1493
  return wrapWithGuards(client, {
1472
1494
  getStub: (name) => backend.stubs.get(name),
1473
1495
  onCall: (method, args) => {
1474
- const rec = { method, args, projectId, dataset }, tag = tagFromArgs(method, args);
1496
+ const rec = { method, args, projectId, dataset }, tag = OPTIONS_ARG_POSITION[method] === void 0 ? void 0 : effectiveRequestTag(tagFromArgs(method, args));
1475
1497
  return tag !== void 0 && (rec.tag = tag), backend.calls.push(rec), (outcome) => {
1476
1498
  "error" in outcome ? rec.error = outcome.error : rec.result = outcome.result;
1477
1499
  };