@axcode/axcloud-sdk 0.1.0 → 0.1.1

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.mjs CHANGED
@@ -116,6 +116,14 @@ var AxCloudClient = class {
116
116
  }
117
117
  return url.toString();
118
118
  }
119
+ /**
120
+ * API key should only be sent to public endpoints.
121
+ * This avoids leaking public keys to authenticated/internal routes.
122
+ */
123
+ shouldAttachApiKey(path) {
124
+ const normalized = path.startsWith("/") ? path : `/${path}`;
125
+ return normalized.startsWith("/public/") || normalized.startsWith("/api/public/") || normalized.startsWith("/content/public/");
126
+ }
119
127
  /**
120
128
  * Make an authenticated request
121
129
  */
@@ -128,7 +136,7 @@ var AxCloudClient = class {
128
136
  const customHeadersRecord = customHeaders;
129
137
  Object.assign(headers, customHeadersRecord);
130
138
  }
131
- if (this.apiKey) {
139
+ if (this.apiKey && this.shouldAttachApiKey(path)) {
132
140
  headers["x-api-key"] = this.apiKey;
133
141
  }
134
142
  if (this.getAccessToken) {
@@ -247,30 +255,55 @@ function userHasAllPermissions(user, permissions) {
247
255
 
248
256
  // src/core/forms.ts
249
257
  async function submitForm(apiUrl, submission) {
250
- const url = `${apiUrl.replace(/\/$/, "")}/public/submit`;
251
- const response = await fetch(url, {
252
- method: "POST",
253
- headers: {
254
- "Content-Type": "application/json"
255
- },
256
- body: JSON.stringify({
257
- api_key: submission.apiKey,
258
- site: submission.site,
259
- form_type: submission.formType,
260
- email: submission.email,
261
- data: submission.data || {}
262
- })
263
- });
264
- if (!response.ok) {
265
- const error = await response.json().catch(() => ({ message: "Form submission failed" }));
266
- throw new Error(error.message || "Form submission failed");
258
+ const baseUrl = apiUrl.replace(/\/$/, "");
259
+ try {
260
+ const response = await fetch(`${baseUrl}/public/submit`, {
261
+ method: "POST",
262
+ headers: {
263
+ "Content-Type": "application/json"
264
+ },
265
+ body: JSON.stringify({
266
+ api_key: submission.apiKey,
267
+ site: submission.site,
268
+ form_type: submission.formType,
269
+ email: submission.email,
270
+ data: submission.data || {}
271
+ })
272
+ });
273
+ if (!response.ok) {
274
+ const error = await response.json().catch(() => ({ message: "Form submission failed" }));
275
+ throw new Error(error.message || "Form submission failed");
276
+ }
277
+ const result = await response.json();
278
+ return {
279
+ success: result.success,
280
+ message: result.message,
281
+ submissionId: result.submission_id
282
+ };
283
+ } catch (primaryError) {
284
+ try {
285
+ const notifyResponse = await fetch(`${baseUrl}/public/notify`, {
286
+ method: "POST",
287
+ headers: { "Content-Type": "application/json" },
288
+ body: JSON.stringify({
289
+ api_key: submission.apiKey,
290
+ site: submission.site,
291
+ form_type: submission.formType,
292
+ email: submission.email
293
+ })
294
+ });
295
+ if (notifyResponse.ok) {
296
+ const result = await notifyResponse.json();
297
+ return {
298
+ success: true,
299
+ message: result.message || "Thanks! We'll notify you when we launch.",
300
+ submissionId: "fallback"
301
+ };
302
+ }
303
+ } catch {
304
+ }
305
+ throw primaryError;
267
306
  }
268
- const result = await response.json();
269
- return {
270
- success: result.success,
271
- message: result.message,
272
- submissionId: result.submission_id
273
- };
274
307
  }
275
308
  function createFormHelper(config) {
276
309
  return {
@@ -570,8 +603,8 @@ function useUser() {
570
603
  };
571
604
  }
572
605
  function useOrg() {
573
- const { client, orgId, stage, config } = useAxCloudContext();
574
- const usePublicEndpoint = Boolean(config.apiKey);
606
+ const { client, orgId, stage, isPublicMode } = useAxCloudContext();
607
+ const usePublicEndpoint = isPublicMode;
575
608
  const query = useQuery({
576
609
  queryKey: ["axcloud", "organization", orgId, stage, usePublicEndpoint],
577
610
  queryFn: async () => {
@@ -630,7 +663,20 @@ function useNews(options = {}) {
630
663
  } = options;
631
664
  const usePublicEndpoint = isPublicMode || publicOnly;
632
665
  const query = useQuery({
633
- queryKey: ["axcloud", "news", orgId, usePublicEndpoint, options],
666
+ queryKey: [
667
+ "axcloud",
668
+ "news",
669
+ orgId,
670
+ usePublicEndpoint,
671
+ page,
672
+ pageSize,
673
+ status,
674
+ visibility,
675
+ sectionId,
676
+ search,
677
+ sortBy,
678
+ sortOrder
679
+ ],
634
680
  queryFn: async () => {
635
681
  const endpoint = usePublicEndpoint ? `/content/public/${orgId}/news` : `/content/members/${orgId}/news`;
636
682
  return client.get(endpoint, {
@@ -661,6 +707,7 @@ var MEMBER_ENDPOINT_TYPES = ["news", "pages", "events"];
661
707
  function useContent(contentType, options = {}) {
662
708
  const { client, orgId, isPublicMode } = useAxCloudContext();
663
709
  const {
710
+ publicOnly = false,
664
711
  page = 1,
665
712
  pageSize = 20,
666
713
  status = "published",
@@ -671,9 +718,24 @@ function useContent(contentType, options = {}) {
671
718
  sortOrder = "desc"
672
719
  } = options;
673
720
  const query = useQuery({
674
- queryKey: ["axcloud", "content", orgId, contentType, isPublicMode, options],
721
+ queryKey: [
722
+ "axcloud",
723
+ "content",
724
+ orgId,
725
+ contentType,
726
+ isPublicMode,
727
+ publicOnly,
728
+ page,
729
+ pageSize,
730
+ status,
731
+ visibility,
732
+ sectionId,
733
+ search,
734
+ sortBy,
735
+ sortOrder
736
+ ],
675
737
  queryFn: async () => {
676
- const useMemberEndpoint = !isPublicMode && MEMBER_ENDPOINT_TYPES.includes(contentType);
738
+ const useMemberEndpoint = !isPublicMode && !publicOnly && MEMBER_ENDPOINT_TYPES.includes(contentType);
677
739
  const endpoint = useMemberEndpoint ? `/content/members/${orgId}/${contentType}` : `/content/public/${orgId}/${contentType}`;
678
740
  return client.get(endpoint, {
679
741
  page,
@@ -779,7 +841,7 @@ function useForms(options = {}) {
779
841
  const { client, stage } = useAxCloudContext();
780
842
  const { formType, status, limit = 50, cursor } = options;
781
843
  const query = useQuery({
782
- queryKey: ["axcloud", "forms", "submissions", stage, options],
844
+ queryKey: ["axcloud", "forms", "submissions", stage, formType, status, limit, cursor],
783
845
  queryFn: async () => {
784
846
  const params = { limit };
785
847
  if (formType) params.form_type = formType;
@@ -840,13 +902,13 @@ function useUpdateFormSubmission() {
840
902
  }
841
903
  var LINKED_ACCOUNTS_QUERY_KEY = ["axcloud", "linked-accounts"];
842
904
  function useLinkedAccounts() {
905
+ const { client, stage } = useAxCloudContext();
843
906
  const { isAuthenticated } = useAuth();
844
907
  const queryClient = useQueryClient();
845
908
  const query = useQuery({
846
- queryKey: LINKED_ACCOUNTS_QUERY_KEY,
909
+ queryKey: [...LINKED_ACCOUNTS_QUERY_KEY, stage],
847
910
  queryFn: async () => {
848
- const client = getClient();
849
- return client.get("/api/users/me/identities");
911
+ return client.get(`/${stage}/api/users/me/identities`);
850
912
  },
851
913
  enabled: isAuthenticated,
852
914
  staleTime: 1e3 * 60 * 5
@@ -854,9 +916,8 @@ function useLinkedAccounts() {
854
916
  });
855
917
  const linkMutation = useMutation({
856
918
  mutationFn: async (provider) => {
857
- const client = getClient();
858
919
  const response = await client.post(
859
- `/api/users/me/identities/${provider}/link`,
920
+ `/${stage}/api/users/me/identities/${provider}/link`,
860
921
  {}
861
922
  );
862
923
  if (response.authorization_url) {
@@ -870,9 +931,8 @@ function useLinkedAccounts() {
870
931
  });
871
932
  const unlinkMutation = useMutation({
872
933
  mutationFn: async (provider) => {
873
- const client = getClient();
874
934
  return client.delete(
875
- `/api/users/me/identities/${provider}`
935
+ `/${stage}/api/users/me/identities/${provider}`
876
936
  );
877
937
  },
878
938
  onSuccess: () => {