@foir/sdk 0.10.0 → 0.11.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/next.js CHANGED
@@ -101,19 +101,46 @@ var FoirRequestError = class extends Error {
101
101
  return typeof seconds === "number" && seconds > 0 ? seconds * 1e3 : void 0;
102
102
  }
103
103
  };
104
+ var DISPATCH_RESERVED_HEADERS = /* @__PURE__ */ new Set([
105
+ "x-api-key",
106
+ "authorization",
107
+ "x-foir-token",
108
+ "x-foir-context"
109
+ ]);
110
+ function refuseCredentialHeaders(extra) {
111
+ if (!extra) return;
112
+ for (const name of Object.keys(extra)) {
113
+ if (DISPATCH_RESERVED_HEADERS.has(name.toLowerCase())) {
114
+ throw new FoirRequestError(
115
+ `[foir] a client built from a dispatch token cannot send "${name}" in \`headers\`. The dispatch token is the credential, and an api key or a bearer beside it would make the request two actors at once. Build a separate client for the other credential.`
116
+ );
117
+ }
118
+ }
119
+ }
104
120
  function buildFoirHeaders(input) {
105
121
  const headers = {
106
- "Content-Type": "application/json",
107
- "x-api-key": input.apiKey
122
+ "Content-Type": "application/json"
108
123
  };
109
- if (input.draftChannel) {
110
- headers["X-Foir-Schema-Channel"] = "draft";
111
- }
112
- if (input.bearerToken) {
113
- headers["Authorization"] = `Bearer ${input.bearerToken}`;
114
- }
115
- if (input.orgId) {
116
- headers["X-Org-Id"] = input.orgId;
124
+ if (input.dispatchToken !== void 0) {
125
+ refuseCredentialHeaders(input.extra);
126
+ headers["X-Foir-Token"] = input.dispatchToken;
127
+ if (input.dispatchContext) {
128
+ headers["X-Foir-Context"] = input.dispatchContext;
129
+ }
130
+ } else {
131
+ headers["x-api-key"] = input.apiKey;
132
+ if (input.draftChannel) {
133
+ headers["X-Foir-Schema-Channel"] = "draft";
134
+ }
135
+ if (input.bearerToken) {
136
+ headers["Authorization"] = `Bearer ${input.bearerToken}`;
137
+ }
138
+ if (input.orgId) {
139
+ headers["X-Org-Id"] = input.orgId;
140
+ }
141
+ if (input.orgUrl) {
142
+ headers["X-Org-Url"] = input.orgUrl;
143
+ }
117
144
  }
118
145
  if (input.extra) {
119
146
  for (const [key, value] of Object.entries(input.extra)) {
@@ -157,12 +184,15 @@ function refusePrunedDocument(json, options) {
157
184
  `[foir] selections stripped from this query: ${selections.map(describe).join(", ")}`
158
185
  );
159
186
  }
187
+ function answeredAnything(data) {
188
+ return typeof data === "object" && data !== null && Object.values(data).some((value) => value !== null && value !== void 0);
189
+ }
160
190
  function readFoirEnvelope(json, options) {
161
191
  reportAuthDowngrade(json);
162
192
  refusePrunedDocument(json, options);
163
193
  if (json.errors?.length) {
164
194
  const msg = json.errors.map((e) => e.message).join("; ");
165
- if (json.data && !options?.strict) {
195
+ if (answeredAnything(json.data) && !options?.strict) {
166
196
  console.warn(`[foir] GraphQL partial errors (data returned): ${msg}`);
167
197
  } else {
168
198
  throw new FoirRequestError(`[foir] GraphQL errors: ${msg}`, {
@@ -681,10 +711,42 @@ async function resolveBearerToken(config) {
681
711
  if (typeof source === "function") return await source() ?? void 0;
682
712
  return source ?? void 0;
683
713
  }
714
+ async function resolveDispatchToken(dispatch) {
715
+ const token = (await dispatch.token())?.trim();
716
+ if (!token) {
717
+ throw new FoirRequestError(
718
+ "[foir] the dispatch token provider returned no token. A client built from a dispatch calls Foir as that operation and holds no other credential. Build it from the token the endpoint was handed: `(await requireScopedToken(request)).dispatch`."
719
+ );
720
+ }
721
+ return token;
722
+ }
723
+ async function resolveFoirAuth(config) {
724
+ if (config.dispatch !== void 0) {
725
+ return {
726
+ headers: buildFoirHeaders({
727
+ dispatchToken: await resolveDispatchToken(config.dispatch),
728
+ dispatchContext: config.dispatch.context ?? void 0,
729
+ extra: config.headers
730
+ })
731
+ };
732
+ }
733
+ const bearerToken = await resolveBearerToken(config);
734
+ return {
735
+ headers: buildFoirHeaders({
736
+ apiKey: config.apiKey,
737
+ draftChannel: config.channel === "draft",
738
+ bearerToken,
739
+ orgId: config.orgId,
740
+ orgUrl: config.orgUrl,
741
+ extra: config.headers
742
+ }),
743
+ key: { apiKey: config.apiKey, bearerToken }
744
+ };
745
+ }
684
746
  function foirRoute(input) {
685
747
  if (!input.apiKey.startsWith("pk_")) return { lane: "origin", reason: "key" };
686
748
  if (input.bearerToken) return { lane: "origin", reason: "bearer" };
687
- if (input.orgId) return { lane: "origin", reason: "org" };
749
+ if (input.orgId || input.orgUrl) return { lane: "origin", reason: "org" };
688
750
  if (input.mutation) return { lane: "origin", reason: "operation" };
689
751
  if (input.writeToken) return { lane: "origin", reason: "floor" };
690
752
  if (input.channel === "draft") return { lane: "origin", reason: "channel" };
@@ -702,22 +764,16 @@ async function executeFoirDocument(config, plan) {
702
764
  async function runFoirDocument(config, document, mutation, variables, options) {
703
765
  const doFetch = config.fetch ?? globalThis.fetch;
704
766
  const endpoint = foirDataEndpoint(config.apiUrl, "/graphql");
705
- const bearerToken = await resolveBearerToken(config);
706
- const headers = buildFoirHeaders({
707
- apiKey: config.apiKey,
708
- draftChannel: config.channel === "draft",
709
- bearerToken,
710
- orgId: config.orgId,
711
- extra: config.headers
712
- });
767
+ const { headers, key } = await resolveFoirAuth(config);
713
768
  const hash = await documentHash(document);
714
- const route = foirRoute({
715
- apiKey: config.apiKey,
716
- bearerToken,
769
+ const sharedKey = key !== void 0 && foirRoute({
770
+ apiKey: key.apiKey,
771
+ bearerToken: key.bearerToken,
717
772
  orgId: config.orgId,
773
+ orgUrl: config.orgUrl,
718
774
  mutation,
719
775
  channel: config.channel
720
- });
776
+ }).lane === "shared" ? key.apiKey : void 0;
721
777
  const post = (body) => doFetch(endpoint, {
722
778
  method: "POST",
723
779
  headers,
@@ -727,8 +783,8 @@ async function runFoirDocument(config, document, mutation, variables, options) {
727
783
  const extensions = persistedQueryExtension(hash);
728
784
  let res;
729
785
  try {
730
- if (route.lane === "shared") {
731
- res = await doFetch(buildCdnUrl(endpoint, config.apiKey, hash, variables), {
786
+ if (sharedKey !== void 0) {
787
+ res = await doFetch(buildCdnUrl(endpoint, sharedKey, hash, variables), {
732
788
  method: "GET",
733
789
  headers,
734
790
  ...config.requestInit
@@ -766,20 +822,16 @@ async function readErrorBody(res) {
766
822
  }
767
823
 
768
824
  // src/data/manifest.ts
769
- async function fetchFoirManifest(config) {
770
- const url = foirDataEndpoint(config.apiUrl, "/v1/manifest");
825
+ async function fetchFoirManifest(config, options = {}) {
826
+ const base = foirDataEndpoint(config.apiUrl, "/v1/manifest");
827
+ const url = options.operation === void 0 ? base : `${base}?operation=${encodeURIComponent(options.operation)}`;
771
828
  const doFetch = config.fetch ?? globalThis.fetch;
829
+ const { headers } = await resolveFoirAuth(config);
772
830
  let res;
773
831
  try {
774
832
  res = await doFetch(url, {
775
833
  method: "GET",
776
- headers: buildFoirHeaders({
777
- apiKey: config.apiKey,
778
- draftChannel: config.channel === "draft",
779
- bearerToken: await resolveBearerToken(config),
780
- orgId: config.orgId,
781
- extra: config.headers
782
- }),
834
+ headers,
783
835
  ...config.requestInit
784
836
  });
785
837
  } catch (err) {
@@ -851,6 +903,7 @@ function authClientConfig(env, options) {
851
903
  channel: isFoirPreview(env) ? "draft" : "published",
852
904
  bearerToken: options?.bearerToken,
853
905
  orgId: options?.orgId,
906
+ orgUrl: options?.orgUrl,
854
907
  headers: options?.headers,
855
908
  fetch: options?.fetch
856
909
  };
package/dist/push.js CHANGED
@@ -103,19 +103,46 @@ function readFoirRetryAfterMs(headers) {
103
103
  const seconds = Number(headers.get("Retry-After"));
104
104
  return Number.isFinite(seconds) && seconds > 0 ? seconds * 1e3 : void 0;
105
105
  }
106
+ var DISPATCH_RESERVED_HEADERS = /* @__PURE__ */ new Set([
107
+ "x-api-key",
108
+ "authorization",
109
+ "x-foir-token",
110
+ "x-foir-context"
111
+ ]);
112
+ function refuseCredentialHeaders(extra) {
113
+ if (!extra) return;
114
+ for (const name of Object.keys(extra)) {
115
+ if (DISPATCH_RESERVED_HEADERS.has(name.toLowerCase())) {
116
+ throw new FoirRequestError(
117
+ `[foir] a client built from a dispatch token cannot send "${name}" in \`headers\`. The dispatch token is the credential, and an api key or a bearer beside it would make the request two actors at once. Build a separate client for the other credential.`
118
+ );
119
+ }
120
+ }
121
+ }
106
122
  function buildFoirHeaders(input) {
107
123
  const headers = {
108
- "Content-Type": "application/json",
109
- "x-api-key": input.apiKey
124
+ "Content-Type": "application/json"
110
125
  };
111
- if (input.draftChannel) {
112
- headers["X-Foir-Schema-Channel"] = "draft";
113
- }
114
- if (input.bearerToken) {
115
- headers["Authorization"] = `Bearer ${input.bearerToken}`;
116
- }
117
- if (input.orgId) {
118
- headers["X-Org-Id"] = input.orgId;
126
+ if (input.dispatchToken !== void 0) {
127
+ refuseCredentialHeaders(input.extra);
128
+ headers["X-Foir-Token"] = input.dispatchToken;
129
+ if (input.dispatchContext) {
130
+ headers["X-Foir-Context"] = input.dispatchContext;
131
+ }
132
+ } else {
133
+ headers["x-api-key"] = input.apiKey;
134
+ if (input.draftChannel) {
135
+ headers["X-Foir-Schema-Channel"] = "draft";
136
+ }
137
+ if (input.bearerToken) {
138
+ headers["Authorization"] = `Bearer ${input.bearerToken}`;
139
+ }
140
+ if (input.orgId) {
141
+ headers["X-Org-Id"] = input.orgId;
142
+ }
143
+ if (input.orgUrl) {
144
+ headers["X-Org-Url"] = input.orgUrl;
145
+ }
119
146
  }
120
147
  if (input.extra) {
121
148
  for (const [key, value] of Object.entries(input.extra)) {
@@ -159,12 +186,15 @@ function refusePrunedDocument(json, options) {
159
186
  `[foir] selections stripped from this query: ${selections.map(describe).join(", ")}`
160
187
  );
161
188
  }
189
+ function answeredAnything(data) {
190
+ return typeof data === "object" && data !== null && Object.values(data).some((value) => value !== null && value !== void 0);
191
+ }
162
192
  function readFoirEnvelope(json, options) {
163
193
  reportAuthDowngrade(json);
164
194
  refusePrunedDocument(json, options);
165
195
  if (json.errors?.length) {
166
196
  const msg = json.errors.map((e) => e.message).join("; ");
167
- if (json.data && !options?.strict) {
197
+ if (answeredAnything(json.data) && !options?.strict) {
168
198
  console.warn(`[foir] GraphQL partial errors (data returned): ${msg}`);
169
199
  } else {
170
200
  throw new FoirRequestError(`[foir] GraphQL errors: ${msg}`, {
@@ -232,12 +262,13 @@ async function foirRequest(env, document, variables, options) {
232
262
  apiKey,
233
263
  draftChannel: isFoirPreview(env),
234
264
  bearerToken: options?.bearerToken,
235
- orgId: options?.orgId
265
+ orgId: options?.orgId,
266
+ orgUrl: options?.orgUrl
236
267
  });
237
268
  const documentText = print2(document);
238
269
  let res;
239
270
  try {
240
- if (isCdnEligible(env, documentText, options?.bearerToken, options?.orgId)) {
271
+ if (isCdnEligible(env, documentText, options?.bearerToken, options?.orgId ?? options?.orgUrl)) {
241
272
  const hash = await documentHash(documentText);
242
273
  let shared = await fetch(buildCdnUrl(endpoint, apiKey, hash, variables), {
243
274
  method: "GET",
@@ -793,10 +824,42 @@ async function resolveBearerToken(config) {
793
824
  if (typeof source === "function") return await source() ?? void 0;
794
825
  return source ?? void 0;
795
826
  }
827
+ async function resolveDispatchToken(dispatch) {
828
+ const token = (await dispatch.token())?.trim();
829
+ if (!token) {
830
+ throw new FoirRequestError(
831
+ "[foir] the dispatch token provider returned no token. A client built from a dispatch calls Foir as that operation and holds no other credential. Build it from the token the endpoint was handed: `(await requireScopedToken(request)).dispatch`."
832
+ );
833
+ }
834
+ return token;
835
+ }
836
+ async function resolveFoirAuth(config) {
837
+ if (config.dispatch !== void 0) {
838
+ return {
839
+ headers: buildFoirHeaders({
840
+ dispatchToken: await resolveDispatchToken(config.dispatch),
841
+ dispatchContext: config.dispatch.context ?? void 0,
842
+ extra: config.headers
843
+ })
844
+ };
845
+ }
846
+ const bearerToken = await resolveBearerToken(config);
847
+ return {
848
+ headers: buildFoirHeaders({
849
+ apiKey: config.apiKey,
850
+ draftChannel: config.channel === "draft",
851
+ bearerToken,
852
+ orgId: config.orgId,
853
+ orgUrl: config.orgUrl,
854
+ extra: config.headers
855
+ }),
856
+ key: { apiKey: config.apiKey, bearerToken }
857
+ };
858
+ }
796
859
  function foirRoute(input) {
797
860
  if (!input.apiKey.startsWith("pk_")) return { lane: "origin", reason: "key" };
798
861
  if (input.bearerToken) return { lane: "origin", reason: "bearer" };
799
- if (input.orgId) return { lane: "origin", reason: "org" };
862
+ if (input.orgId || input.orgUrl) return { lane: "origin", reason: "org" };
800
863
  if (input.mutation) return { lane: "origin", reason: "operation" };
801
864
  if (input.writeToken) return { lane: "origin", reason: "floor" };
802
865
  if (input.channel === "draft") return { lane: "origin", reason: "channel" };
@@ -814,22 +877,16 @@ async function executeFoirDocument(config, plan) {
814
877
  async function runFoirDocument(config, document, mutation, variables, options) {
815
878
  const doFetch = config.fetch ?? globalThis.fetch;
816
879
  const endpoint = foirDataEndpoint(config.apiUrl, "/graphql");
817
- const bearerToken = await resolveBearerToken(config);
818
- const headers = buildFoirHeaders({
819
- apiKey: config.apiKey,
820
- draftChannel: config.channel === "draft",
821
- bearerToken,
822
- orgId: config.orgId,
823
- extra: config.headers
824
- });
880
+ const { headers, key } = await resolveFoirAuth(config);
825
881
  const hash = await documentHash(document);
826
- const route = foirRoute({
827
- apiKey: config.apiKey,
828
- bearerToken,
882
+ const sharedKey = key !== void 0 && foirRoute({
883
+ apiKey: key.apiKey,
884
+ bearerToken: key.bearerToken,
829
885
  orgId: config.orgId,
886
+ orgUrl: config.orgUrl,
830
887
  mutation,
831
888
  channel: config.channel
832
- });
889
+ }).lane === "shared" ? key.apiKey : void 0;
833
890
  const post = (body) => doFetch(endpoint, {
834
891
  method: "POST",
835
892
  headers,
@@ -839,8 +896,8 @@ async function runFoirDocument(config, document, mutation, variables, options) {
839
896
  const extensions = persistedQueryExtension(hash);
840
897
  let res;
841
898
  try {
842
- if (route.lane === "shared") {
843
- res = await doFetch(buildCdnUrl(endpoint, config.apiKey, hash, variables), {
899
+ if (sharedKey !== void 0) {
900
+ res = await doFetch(buildCdnUrl(endpoint, sharedKey, hash, variables), {
844
901
  method: "GET",
845
902
  headers,
846
903
  ...config.requestInit
@@ -878,20 +935,16 @@ async function readErrorBody(res) {
878
935
  }
879
936
 
880
937
  // src/data/manifest.ts
881
- async function fetchFoirManifest(config) {
882
- const url = foirDataEndpoint(config.apiUrl, "/v1/manifest");
938
+ async function fetchFoirManifest(config, options = {}) {
939
+ const base = foirDataEndpoint(config.apiUrl, "/v1/manifest");
940
+ const url = options.operation === void 0 ? base : `${base}?operation=${encodeURIComponent(options.operation)}`;
883
941
  const doFetch = config.fetch ?? globalThis.fetch;
942
+ const { headers } = await resolveFoirAuth(config);
884
943
  let res;
885
944
  try {
886
945
  res = await doFetch(url, {
887
946
  method: "GET",
888
- headers: buildFoirHeaders({
889
- apiKey: config.apiKey,
890
- draftChannel: config.channel === "draft",
891
- bearerToken: await resolveBearerToken(config),
892
- orgId: config.orgId,
893
- extra: config.headers
894
- }),
947
+ headers,
895
948
  ...config.requestInit
896
949
  });
897
950
  } catch (err) {
@@ -963,6 +1016,7 @@ function authClientConfig(env, options) {
963
1016
  channel: isFoirPreview(env) ? "draft" : "published",
964
1017
  bearerToken: options?.bearerToken,
965
1018
  orgId: options?.orgId,
1019
+ orgUrl: options?.orgUrl,
966
1020
  headers: options?.headers,
967
1021
  fetch: options?.fetch
968
1022
  };
package/dist/react.js CHANGED
@@ -95,19 +95,46 @@ var FoirRequestError = class extends Error {
95
95
  return typeof seconds === "number" && seconds > 0 ? seconds * 1e3 : void 0;
96
96
  }
97
97
  };
98
+ var DISPATCH_RESERVED_HEADERS = /* @__PURE__ */ new Set([
99
+ "x-api-key",
100
+ "authorization",
101
+ "x-foir-token",
102
+ "x-foir-context"
103
+ ]);
104
+ function refuseCredentialHeaders(extra) {
105
+ if (!extra) return;
106
+ for (const name of Object.keys(extra)) {
107
+ if (DISPATCH_RESERVED_HEADERS.has(name.toLowerCase())) {
108
+ throw new FoirRequestError(
109
+ `[foir] a client built from a dispatch token cannot send "${name}" in \`headers\`. The dispatch token is the credential, and an api key or a bearer beside it would make the request two actors at once. Build a separate client for the other credential.`
110
+ );
111
+ }
112
+ }
113
+ }
98
114
  function buildFoirHeaders(input) {
99
115
  const headers = {
100
- "Content-Type": "application/json",
101
- "x-api-key": input.apiKey
116
+ "Content-Type": "application/json"
102
117
  };
103
- if (input.draftChannel) {
104
- headers["X-Foir-Schema-Channel"] = "draft";
105
- }
106
- if (input.bearerToken) {
107
- headers["Authorization"] = `Bearer ${input.bearerToken}`;
108
- }
109
- if (input.orgId) {
110
- headers["X-Org-Id"] = input.orgId;
118
+ if (input.dispatchToken !== void 0) {
119
+ refuseCredentialHeaders(input.extra);
120
+ headers["X-Foir-Token"] = input.dispatchToken;
121
+ if (input.dispatchContext) {
122
+ headers["X-Foir-Context"] = input.dispatchContext;
123
+ }
124
+ } else {
125
+ headers["x-api-key"] = input.apiKey;
126
+ if (input.draftChannel) {
127
+ headers["X-Foir-Schema-Channel"] = "draft";
128
+ }
129
+ if (input.bearerToken) {
130
+ headers["Authorization"] = `Bearer ${input.bearerToken}`;
131
+ }
132
+ if (input.orgId) {
133
+ headers["X-Org-Id"] = input.orgId;
134
+ }
135
+ if (input.orgUrl) {
136
+ headers["X-Org-Url"] = input.orgUrl;
137
+ }
111
138
  }
112
139
  if (input.extra) {
113
140
  for (const [key, value] of Object.entries(input.extra)) {
@@ -151,12 +178,15 @@ function refusePrunedDocument(json, options) {
151
178
  `[foir] selections stripped from this query: ${selections.map(describe).join(", ")}`
152
179
  );
153
180
  }
181
+ function answeredAnything(data) {
182
+ return typeof data === "object" && data !== null && Object.values(data).some((value) => value !== null && value !== void 0);
183
+ }
154
184
  function readFoirEnvelope(json, options) {
155
185
  reportAuthDowngrade(json);
156
186
  refusePrunedDocument(json, options);
157
187
  if (json.errors?.length) {
158
188
  const msg = json.errors.map((e) => e.message).join("; ");
159
- if (json.data && !options?.strict) {
189
+ if (answeredAnything(json.data) && !options?.strict) {
160
190
  console.warn(`[foir] GraphQL partial errors (data returned): ${msg}`);
161
191
  } else {
162
192
  throw new FoirRequestError(`[foir] GraphQL errors: ${msg}`, {
@@ -675,10 +705,42 @@ async function resolveBearerToken(config) {
675
705
  if (typeof source === "function") return await source() ?? void 0;
676
706
  return source ?? void 0;
677
707
  }
708
+ async function resolveDispatchToken(dispatch) {
709
+ const token = (await dispatch.token())?.trim();
710
+ if (!token) {
711
+ throw new FoirRequestError(
712
+ "[foir] the dispatch token provider returned no token. A client built from a dispatch calls Foir as that operation and holds no other credential. Build it from the token the endpoint was handed: `(await requireScopedToken(request)).dispatch`."
713
+ );
714
+ }
715
+ return token;
716
+ }
717
+ async function resolveFoirAuth(config) {
718
+ if (config.dispatch !== void 0) {
719
+ return {
720
+ headers: buildFoirHeaders({
721
+ dispatchToken: await resolveDispatchToken(config.dispatch),
722
+ dispatchContext: config.dispatch.context ?? void 0,
723
+ extra: config.headers
724
+ })
725
+ };
726
+ }
727
+ const bearerToken = await resolveBearerToken(config);
728
+ return {
729
+ headers: buildFoirHeaders({
730
+ apiKey: config.apiKey,
731
+ draftChannel: config.channel === "draft",
732
+ bearerToken,
733
+ orgId: config.orgId,
734
+ orgUrl: config.orgUrl,
735
+ extra: config.headers
736
+ }),
737
+ key: { apiKey: config.apiKey, bearerToken }
738
+ };
739
+ }
678
740
  function foirRoute(input) {
679
741
  if (!input.apiKey.startsWith("pk_")) return { lane: "origin", reason: "key" };
680
742
  if (input.bearerToken) return { lane: "origin", reason: "bearer" };
681
- if (input.orgId) return { lane: "origin", reason: "org" };
743
+ if (input.orgId || input.orgUrl) return { lane: "origin", reason: "org" };
682
744
  if (input.mutation) return { lane: "origin", reason: "operation" };
683
745
  if (input.writeToken) return { lane: "origin", reason: "floor" };
684
746
  if (input.channel === "draft") return { lane: "origin", reason: "channel" };
@@ -696,22 +758,16 @@ async function executeFoirDocument(config, plan) {
696
758
  async function runFoirDocument(config, document2, mutation, variables, options) {
697
759
  const doFetch = config.fetch ?? globalThis.fetch;
698
760
  const endpoint = foirDataEndpoint(config.apiUrl, "/graphql");
699
- const bearerToken = await resolveBearerToken(config);
700
- const headers = buildFoirHeaders({
701
- apiKey: config.apiKey,
702
- draftChannel: config.channel === "draft",
703
- bearerToken,
704
- orgId: config.orgId,
705
- extra: config.headers
706
- });
761
+ const { headers, key } = await resolveFoirAuth(config);
707
762
  const hash = await documentHash(document2);
708
- const route = foirRoute({
709
- apiKey: config.apiKey,
710
- bearerToken,
763
+ const sharedKey = key !== void 0 && foirRoute({
764
+ apiKey: key.apiKey,
765
+ bearerToken: key.bearerToken,
711
766
  orgId: config.orgId,
767
+ orgUrl: config.orgUrl,
712
768
  mutation,
713
769
  channel: config.channel
714
- });
770
+ }).lane === "shared" ? key.apiKey : void 0;
715
771
  const post = (body) => doFetch(endpoint, {
716
772
  method: "POST",
717
773
  headers,
@@ -721,8 +777,8 @@ async function runFoirDocument(config, document2, mutation, variables, options)
721
777
  const extensions = persistedQueryExtension(hash);
722
778
  let res;
723
779
  try {
724
- if (route.lane === "shared") {
725
- res = await doFetch(buildCdnUrl(endpoint, config.apiKey, hash, variables), {
780
+ if (sharedKey !== void 0) {
781
+ res = await doFetch(buildCdnUrl(endpoint, sharedKey, hash, variables), {
726
782
  method: "GET",
727
783
  headers,
728
784
  ...config.requestInit
@@ -760,20 +816,16 @@ async function readErrorBody(res) {
760
816
  }
761
817
 
762
818
  // src/data/manifest.ts
763
- async function fetchFoirManifest(config) {
764
- const url = foirDataEndpoint(config.apiUrl, "/v1/manifest");
819
+ async function fetchFoirManifest(config, options = {}) {
820
+ const base = foirDataEndpoint(config.apiUrl, "/v1/manifest");
821
+ const url = options.operation === void 0 ? base : `${base}?operation=${encodeURIComponent(options.operation)}`;
765
822
  const doFetch = config.fetch ?? globalThis.fetch;
823
+ const { headers } = await resolveFoirAuth(config);
766
824
  let res;
767
825
  try {
768
826
  res = await doFetch(url, {
769
827
  method: "GET",
770
- headers: buildFoirHeaders({
771
- apiKey: config.apiKey,
772
- draftChannel: config.channel === "draft",
773
- bearerToken: await resolveBearerToken(config),
774
- orgId: config.orgId,
775
- extra: config.headers
776
- }),
828
+ headers,
777
829
  ...config.requestInit
778
830
  });
779
831
  } catch (err) {
@@ -845,6 +897,7 @@ function authClientConfig(env, options) {
845
897
  channel: isFoirPreview(env) ? "draft" : "published",
846
898
  bearerToken: options?.bearerToken,
847
899
  orgId: options?.orgId,
900
+ orgUrl: options?.orgUrl,
848
901
  headers: options?.headers,
849
902
  fetch: options?.fetch
850
903
  };
@@ -2,6 +2,7 @@ export { createServerClient, ServerClientError } from './server-client';
2
2
  export { verifyWebhookSignature } from './webhook-helpers';
3
3
  export { verifyScopedToken, parseContextHeader, parseSubject, recordsReadModels, recordsWriteModels, type ScopedTokenClaims, type ScopedTokenSubject, type VerifyScopedTokenOptions, } from './verify-scoped-token';
4
4
  export { requireScopedToken, ScopedTokenError, type RequireScopedTokenOptions, type ScopedTokenIngress, } from './require-scoped-token';
5
+ export { readDispatch, OperationPayloadError, type BodyCarrier, } from './read-dispatch';
5
6
  export type { ServerClient, ServerClientOptions, GraphQLResponse, EditorPlacement, } from './types';
6
7
  export type { OperationPayload, OperationTrigger, OperationRecordContext, OperationContext, OperationResult, OperationCallback, } from './operation-types';
7
8
  export { createCallbackClient } from './callback-client';