@mints-cloud/cxf-codegen 1.0.2 → 1.0.3

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
@@ -17,10 +17,11 @@ Your project needs thin wrapper files that import from this library. The `create
17
17
  ```tsx
18
18
  import '@/styles/globals.css'
19
19
  import '@mints-cloud/cxf-codegen/register';
20
+ import type { AppProps } from 'next/app';
20
21
  import CxfApp from '@mints-cloud/cxf-codegen/pages/app';
21
22
  import projectcss from '../components/plasmic/<your-project>/plasmic.module.css';
22
23
 
23
- export default function App(props) {
24
+ export default function App(props: AppProps) {
24
25
  return <CxfApp {...props} tokenClass={projectcss.plasmic_tokens} />;
25
26
  }
26
27
  ```
@@ -12,6 +12,11 @@ export interface ApiCallProps {
12
12
  onSuccess?: (data: any) => void;
13
13
  onError?: (error: string) => void;
14
14
  loadingContent?: React.ReactNode;
15
+ /**
16
+ * In Plasmic Studio canvas, throttle automatic GET refetches to this interval.
17
+ * Defaults to 5 minutes. Runtime pages are unaffected.
18
+ */
19
+ canvasAutoFetchCooldownMs?: number;
15
20
  children?: React.ReactNode;
16
21
  }
17
22
  export declare function ApiCall(props: ApiCallProps): import("react/jsx-runtime").JSX.Element | null;
@@ -1 +1 @@
1
- {"version":3,"file":"ApiCall.d.ts","sourceRoot":"","sources":["../../src/components/ApiCall.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,MAAM,MAAM,OAAO,GAAG,UAAU,GAAG,SAAS,GAAG,KAAK,GAAG,MAAM,CAAC;AAE9D,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAC;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,WAAW,CAAC,EAAE,GAAG,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;IAChC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,cAAc,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACjC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAsBD,wBAAgB,OAAO,CAAC,KAAK,EAAE,YAAY,kDAqD1C;AAED,eAAe,OAAO,CAAC"}
1
+ {"version":3,"file":"ApiCall.d.ts","sourceRoot":"","sources":["../../src/components/ApiCall.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,MAAM,MAAM,OAAO,GAAG,UAAU,GAAG,SAAS,GAAG,KAAK,GAAG,MAAM,CAAC;AAE9D,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAC;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,WAAW,CAAC,EAAE,GAAG,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;IAChC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,cAAc,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACjC;;;OAGG;IACH,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAsBD,wBAAgB,OAAO,CAAC,KAAK,EAAE,YAAY,kDAyD1C;AAED,eAAe,OAAO,CAAC"}
@@ -57,7 +57,7 @@ function buildEndpointPath(apiType, rawPath) {
57
57
  }
58
58
  }
59
59
  function ApiCall(props) {
60
- const { apiType = "contact", path, method = "GET", params, body, initialData, autoFetch, trigger, onSuccess, onError, loadingContent, children, } = props;
60
+ const { apiType = "contact", path, method = "GET", params, body, initialData, autoFetch, trigger, onSuccess, onError, loadingContent, canvasAutoFetchCooldownMs, children, } = props;
61
61
  const endpointPath = React.useMemo(() => buildEndpointPath(apiType, path), [apiType, path]);
62
62
  const shouldAutoFetch = autoFetch !== undefined ? autoFetch : method === "GET";
63
63
  const { preloaded, hasExactPreload } = (0, api_call_hooks_1.useIsrPrefetch)(endpointPath, params, method, initialData);
@@ -73,13 +73,15 @@ function ApiCall(props) {
73
73
  onSuccess,
74
74
  onError,
75
75
  unwrapData: true,
76
+ canvasAutoFetchCooldownMs,
76
77
  });
77
78
  // If no children, render nothing (still performs the call + callbacks)
78
79
  if (!children)
79
80
  return null;
80
81
  // If children exist, respect loadingContent for UX
81
- if (loading)
82
+ if (loading) {
82
83
  return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: loadingContent ?? (0, jsx_runtime_1.jsx)("div", { children: "Loading\u2026" }) });
84
+ }
83
85
  const responseData = {
84
86
  data: error ? null : data,
85
87
  error,
@@ -15,11 +15,12 @@ export interface UseApiFetchOptions {
15
15
  onSuccess?: (data: any) => void;
16
16
  onError?: (error: string) => void;
17
17
  unwrapData?: boolean;
18
+ canvasAutoFetchCooldownMs?: number;
18
19
  }
19
20
  export declare function useApiFetch(options: UseApiFetchOptions): {
20
21
  data: any;
21
22
  error: string | null;
22
23
  loading: boolean;
23
- fetchData: () => (() => void) | undefined;
24
+ fetchData: (reason?: "auto" | "trigger" | "manual") => (() => void) | undefined;
24
25
  };
25
26
  //# sourceMappingURL=api-call-hooks.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"api-call-hooks.d.ts","sourceRoot":"","sources":["../../src/lib/api-call-hooks.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,GAAG,CAAC;IACf,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,cAAc,CAC5B,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,EACvC,MAAM,CAAC,EAAE,MAAM,EACf,WAAW,CAAC,EAAE,GAAG,GAChB,mBAAmB,CA+CrB;AAED,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAC;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,SAAS,CAAC,EAAE,GAAG,CAAC;IAChB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;IAChC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAkCD,wBAAgB,WAAW,CAAC,OAAO,EAAE,kBAAkB;;;;;EAyLtD"}
1
+ {"version":3,"file":"api-call-hooks.d.ts","sourceRoot":"","sources":["../../src/lib/api-call-hooks.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,GAAG,CAAC;IACf,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,cAAc,CAC5B,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,EACvC,MAAM,CAAC,EAAE,MAAM,EACf,WAAW,CAAC,EAAE,GAAG,GAChB,mBAAmB,CA+CrB;AAED,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAC;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,SAAS,CAAC,EAAE,GAAG,CAAC;IAChB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;IAChC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,yBAAyB,CAAC,EAAE,MAAM,CAAC;CACpC;AAmED,wBAAgB,WAAW,CAAC,OAAO,EAAE,kBAAkB;;;;yBA0ER,MAAM,GAAG,SAAS,GAAG,QAAQ;EAuI3E"}
@@ -77,6 +77,21 @@ function useIsrPrefetch(endpointPath, params, method, initialData) {
77
77
  : { preloaded: undefined, hasExactPreload: false };
78
78
  }, [initialData, endpointPath, params, endpointDataMap, isGet]);
79
79
  }
80
+ const EDITOR_AUTO_FETCH_COOLDOWN_MS = 5 * 60 * 1000;
81
+ const editorAutoFetchTimestamps = new Map();
82
+ const MAX_EDITOR_FETCH_KEYS = 20;
83
+ function pruneOldestEditorFetchEntries() {
84
+ if (editorAutoFetchTimestamps.size <= MAX_EDITOR_FETCH_KEYS)
85
+ return;
86
+ const overflowCount = editorAutoFetchTimestamps.size - MAX_EDITOR_FETCH_KEYS;
87
+ let removed = 0;
88
+ for (const key of editorAutoFetchTimestamps.keys()) {
89
+ editorAutoFetchTimestamps.delete(key);
90
+ removed += 1;
91
+ if (removed >= overflowCount)
92
+ break;
93
+ }
94
+ }
80
95
  function unwrapResponseData(data, shouldUnwrap) {
81
96
  if (!shouldUnwrap ||
82
97
  !data ||
@@ -88,6 +103,25 @@ function unwrapResponseData(data, shouldUnwrap) {
88
103
  }
89
104
  return data.data;
90
105
  }
106
+ function stableSerialize(value) {
107
+ if (value === undefined)
108
+ return "";
109
+ if (value === null)
110
+ return "null";
111
+ if (Array.isArray(value)) {
112
+ return `[${value.map((item) => stableSerialize(item)).join(",")}]`;
113
+ }
114
+ if (typeof value === "object") {
115
+ const keys = Object.keys(value).sort();
116
+ return `{${keys.map((k) => `${JSON.stringify(k)}:${stableSerialize(value[k])}`).join(",")}}`;
117
+ }
118
+ return JSON.stringify(value);
119
+ }
120
+ function isPlasmicHostRuntime() {
121
+ if (typeof window === "undefined")
122
+ return false;
123
+ return window.location.pathname.includes("/plasmic-host");
124
+ }
91
125
  function getUtmParamsFromLocation() {
92
126
  if (typeof window === "undefined")
93
127
  return null;
@@ -109,7 +143,13 @@ function getUtmParamsFromLocation() {
109
143
  }
110
144
  }
111
145
  function useApiFetch(options) {
112
- const { endpointPath, method = "GET", params, body, preloaded, hasExactPreload, shouldAutoFetch = true, trigger, onSuccess, onError, unwrapData = false, } = options;
146
+ const { endpointPath, method = "GET", params, body, preloaded, hasExactPreload, shouldAutoFetch = true, trigger, onSuccess, onError, unwrapData = false, canvasAutoFetchCooldownMs = EDITOR_AUTO_FETCH_COOLDOWN_MS, } = options;
147
+ const paramsSignature = stableSerialize(params);
148
+ const bodySignature = stableSerialize(body);
149
+ const paramsRef = React.useRef(params);
150
+ const bodyRef = React.useRef(body);
151
+ paramsRef.current = params;
152
+ bodyRef.current = body;
113
153
  // Also check context directly in case preloaded prop hasn't updated yet during hydration
114
154
  const endpointDataMap = React.useContext(server_props_1.EndpointDataContext);
115
155
  const contextData = React.useMemo(() => {
@@ -155,23 +195,36 @@ function useApiFetch(options) {
155
195
  isHydratingRef.current = false;
156
196
  }
157
197
  }, [effectivePreloaded, data]);
158
- const fetchData = React.useCallback(() => {
198
+ const fetchData = React.useCallback((reason = "manual") => {
159
199
  if (!endpointPath)
160
200
  return;
161
201
  const controller = new AbortController();
162
202
  (async () => {
163
203
  try {
204
+ const normalizedPath = (0, server_props_1.normalizeEndpointPath)(endpointPath);
205
+ const requestKey = `${method}:${normalizedPath}:${paramsSignature}:${bodySignature}`;
206
+ if (reason === "auto" &&
207
+ method === "GET" &&
208
+ isPlasmicHostRuntime()) {
209
+ const now = Date.now();
210
+ const lastFetchAt = editorAutoFetchTimestamps.get(requestKey) ?? 0;
211
+ if (now - lastFetchAt < canvasAutoFetchCooldownMs) {
212
+ setLoading(false);
213
+ return;
214
+ }
215
+ editorAutoFetchTimestamps.set(requestKey, now);
216
+ pruneOldestEditorFetchEntries();
217
+ }
164
218
  setLoading(true);
165
219
  setError(null);
166
220
  hasTriggeredSuccessRef.current = false;
167
221
  hasTriggeredErrorRef.current = false;
168
- const normalizedPath = (0, server_props_1.normalizeEndpointPath)(endpointPath);
169
222
  // Merge current page UTM params into request params for GET requests.
170
223
  // Explicit params take precedence over UTM values if keys overlap.
171
224
  const utmParams = method === "GET" ? getUtmParamsFromLocation() : null;
172
225
  const mergedParams = method === "GET"
173
- ? { ...(utmParams || {}), ...(params || {}) }
174
- : params;
226
+ ? { ...(utmParams || {}), ...(paramsRef.current || {}) }
227
+ : paramsRef.current;
175
228
  const queryString = method === "GET" ? (0, server_props_1.buildQueryString)(mergedParams) : "";
176
229
  const url = `/api/${normalizedPath}${queryString}`;
177
230
  const fetchOptions = {
@@ -183,8 +236,8 @@ function useApiFetch(options) {
183
236
  credentials: "include",
184
237
  signal: controller.signal,
185
238
  };
186
- if (method !== "GET" && body) {
187
- fetchOptions.body = JSON.stringify(body);
239
+ if (method !== "GET" && bodyRef.current) {
240
+ fetchOptions.body = JSON.stringify(bodyRef.current);
188
241
  }
189
242
  const resp = await fetch(url, fetchOptions);
190
243
  if (!resp.ok) {
@@ -213,13 +266,13 @@ function useApiFetch(options) {
213
266
  }
214
267
  })();
215
268
  return () => controller.abort();
216
- }, [endpointPath, method, params, body, unwrapData]);
269
+ }, [endpointPath, method, paramsSignature, bodySignature, unwrapData, canvasAutoFetchCooldownMs]);
217
270
  const prevTriggerRef = React.useRef(trigger);
218
271
  React.useEffect(() => {
219
272
  if (trigger !== undefined && trigger !== prevTriggerRef.current) {
220
273
  prevTriggerRef.current = trigger;
221
274
  if (trigger > 0)
222
- fetchData();
275
+ fetchData("trigger");
223
276
  }
224
277
  }, [trigger, fetchData]);
225
278
  // Only fetch if we should auto-fetch AND we don't have exact preloaded data
@@ -236,14 +289,14 @@ function useApiFetch(options) {
236
289
  // Re-check context and preloaded after hydration delay
237
290
  const stillNoData = effectivePreloaded === undefined || effectivePreloaded === null;
238
291
  if (stillNoData && shouldAutoFetch && !hasExactPreload) {
239
- fetchData();
292
+ fetchData("auto");
240
293
  }
241
294
  }, 0);
242
295
  return () => clearTimeout(timeoutId);
243
296
  }
244
297
  // Fetch if we don't have preloaded data (non-hydration case)
245
298
  if (!hasPreloadedData) {
246
- return fetchData();
299
+ return fetchData("auto");
247
300
  }
248
301
  }, [shouldAutoFetch, hasExactPreload, hasPreloadedData, effectivePreloaded, fetchData]);
249
302
  React.useEffect(() => {
@@ -5,6 +5,7 @@ export declare function setAuthCookies(res: NextApiResponse, tokens: {
5
5
  accessToken: string | null;
6
6
  refreshToken: string | null;
7
7
  }): void;
8
+ export declare function forwardExtraCookies(res: NextApiResponse, setCookieHeaders: string[]): void;
8
9
  export declare function handleError(res: NextApiResponse, err: any): void;
9
10
  export declare function sendResponse(res: NextApiResponse, response: Response): Promise<void>;
10
11
  //# sourceMappingURL=api-route-helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"api-route-helpers.d.ts","sourceRoot":"","sources":["../../src/lib/api-route-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,MAAM,CAAC;AAG5D,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,CAAC,GAAG,MAAM,CAavE;AAED,wBAAgB,aAAa,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAOjF;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,eAAe,EAAE,MAAM,EAAE;IAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,QAavH;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,GAAG,QAMzD;AAED,wBAAsB,YAAY,CAAC,GAAG,EAAE,eAAe,EAAE,QAAQ,EAAE,QAAQ,iBAwB1E"}
1
+ {"version":3,"file":"api-route-helpers.d.ts","sourceRoot":"","sources":["../../src/lib/api-route-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,MAAM,CAAC;AAG5D,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,CAAC,GAAG,MAAM,CAavE;AAED,wBAAgB,aAAa,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAOjF;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,eAAe,EAAE,MAAM,EAAE;IAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,QAavH;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,EAAE,QAYnF;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,GAAG,QAMzD;AAED,wBAAsB,YAAY,CAAC,GAAG,EAAE,eAAe,EAAE,QAAQ,EAAE,QAAQ,iBAwB1E"}
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.buildQueryString = buildQueryString;
4
4
  exports.normalizePath = normalizePath;
5
5
  exports.setAuthCookies = setAuthCookies;
6
+ exports.forwardExtraCookies = forwardExtraCookies;
6
7
  exports.handleError = handleError;
7
8
  exports.sendResponse = sendResponse;
8
9
  const cxf_auth_1 = require("./cxf-auth");
@@ -42,6 +43,18 @@ function setAuthCookies(res, tokens) {
42
43
  res.setHeader("Set-Cookie", cookies);
43
44
  }
44
45
  }
46
+ function forwardExtraCookies(res, setCookieHeaders) {
47
+ const authCookieNames = new Set([cxf_auth_1.CXF_COOKIE_NAMES.ACCESS_TOKEN, cxf_auth_1.CXF_COOKIE_NAMES.REFRESH_TOKEN]);
48
+ const extraCookies = setCookieHeaders.filter((header) => {
49
+ const name = header.split("=")[0]?.trim();
50
+ return !authCookieNames.has(name);
51
+ });
52
+ if (extraCookies.length > 0) {
53
+ const existing = res.getHeader("Set-Cookie");
54
+ const current = Array.isArray(existing) ? existing : existing ? [String(existing)] : [];
55
+ res.setHeader("Set-Cookie", [...current, ...extraCookies]);
56
+ }
57
+ }
45
58
  function handleError(res, err) {
46
59
  const dev = process.env.NODE_ENV !== "production";
47
60
  return res.status(500).json({
@@ -14,15 +14,18 @@ export interface CxfTokens {
14
14
  }
15
15
  export declare function getTokensFromCookies(cookieHeader?: string | null): CxfTokens;
16
16
  export declare function buildAuthHeaders(tokens: CxfTokens, apiKey?: string | null, userToken?: string | null): Record<string, string>;
17
- export declare function makeAuthenticatedRequest(url: string, options?: {
17
+ export interface AuthenticatedRequestOptions {
18
18
  method?: string;
19
- body?: any;
19
+ body?: string | Record<string, unknown>;
20
+ rawBody?: Buffer | Uint8Array;
21
+ contentType?: string;
20
22
  tokens?: CxfTokens;
21
23
  apiKey?: string | null;
22
24
  userToken?: string | null;
23
25
  cookieHeader?: string | null;
24
26
  retryOnAuthError?: boolean;
25
- }): Promise<{
27
+ }
28
+ export declare function makeAuthenticatedRequest(url: string, options?: AuthenticatedRequestOptions): Promise<{
26
29
  response: Response;
27
30
  newTokens: CxfTokens;
28
31
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"cxf-auth.d.ts","sourceRoot":"","sources":["../../src/lib/cxf-auth.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,gBAAgB;;;CAGnB,CAAC;AAEX,eAAO,MAAM,gBAAgB;;;;;CAKnB,CAAC;AAEX,MAAM,WAAW,SAAS;IACxB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAiBD,wBAAgB,oBAAoB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAS5E;AAED,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,SAAS,EACjB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,EACtB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GACxB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAYxB;AAED,wBAAsB,wBAAwB,CAC5C,GAAG,EAAE,MAAM,EACX,OAAO,GAAE;IACP,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,gBAAgB,CAAC,EAAE,OAAO,CAAC;CACvB,GACL,OAAO,CAAC;IACT,QAAQ,EAAE,QAAQ,CAAC;IACnB,SAAS,EAAE,SAAS,CAAC;CACtB,CAAC,CAmDD;AAMD,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,EAAE,CAUpE;AAED,wBAAgB,0BAA0B,CACxC,gBAAgB,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,GAC5C,SAAS,CAmBX;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAS3D;AAED,wBAAgB,aAAa,IAAI,MAAM,CAMtC;AAED,wBAAgB,YAAY,CAAC,IAAI,GAAE,QAAQ,GAAG,KAAK,GAAG,MAAiB,GAAG,MAAM,GAAG,IAAI,CAYtF;AAMD,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,OAAO,GAAE;IACP,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACf,GACL,MAAM,CAaR;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAuB1D;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAQvC"}
1
+ {"version":3,"file":"cxf-auth.d.ts","sourceRoot":"","sources":["../../src/lib/cxf-auth.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,gBAAgB;;;CAGnB,CAAC;AAEX,eAAO,MAAM,gBAAgB;;;;;CAKnB,CAAC;AAEX,MAAM,WAAW,SAAS;IACxB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAiBD,wBAAgB,oBAAoB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAS5E;AAED,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,SAAS,EACjB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,EACtB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GACxB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAWxB;AAED,MAAM,WAAW,2BAA2B;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,OAAO,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,wBAAsB,wBAAwB,CAC5C,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,2BAAgC,GACxC,OAAO,CAAC;IACT,QAAQ,EAAE,QAAQ,CAAC;IACnB,SAAS,EAAE,SAAS,CAAC;CACtB,CAAC,CA0DD;AAMD,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,EAAE,CAUpE;AAED,wBAAgB,0BAA0B,CACxC,gBAAgB,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,GAC5C,SAAS,CAmBX;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAS3D;AAED,wBAAgB,aAAa,IAAI,MAAM,CAMtC;AAED,wBAAgB,YAAY,CAAC,IAAI,GAAE,QAAQ,GAAG,KAAK,GAAG,MAAiB,GAAG,MAAM,GAAG,IAAI,CAYtF;AAMD,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,OAAO,GAAE;IACP,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACf,GACL,MAAM,CAaR;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAuB1D;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAQvC"}
@@ -47,7 +47,6 @@ function getTokensFromCookies(cookieHeader) {
47
47
  function buildAuthHeaders(tokens, apiKey, userToken) {
48
48
  const headers = {
49
49
  Accept: "application/json",
50
- "Content-Type": "application/json",
51
50
  };
52
51
  if (apiKey)
53
52
  headers[exports.CXF_HEADER_NAMES.API_KEY] = apiKey;
@@ -60,16 +59,22 @@ function buildAuthHeaders(tokens, apiKey, userToken) {
60
59
  return headers;
61
60
  }
62
61
  async function makeAuthenticatedRequest(url, options = {}) {
63
- const { method = "GET", body, tokens: providedTokens, apiKey, userToken, cookieHeader, retryOnAuthError = true, } = options;
62
+ const { method = "GET", body, rawBody, contentType, tokens: providedTokens, apiKey, userToken, cookieHeader, retryOnAuthError = true, } = options;
64
63
  const tokens = providedTokens || getTokensFromCookies(cookieHeader);
65
- const buildRequestOptions = (tokens, cookieStr) => {
66
- const headers = buildAuthHeaders(tokens, apiKey, userToken);
64
+ const buildRequestOptions = (reqTokens, cookieStr) => {
65
+ const headers = buildAuthHeaders(reqTokens, apiKey, userToken);
67
66
  if (cookieStr) {
68
67
  headers.Cookie = cookieStr;
69
68
  }
70
69
  const requestOptions = { method, headers };
71
- if (body && method !== "GET" && method !== "HEAD") {
72
- requestOptions.body = typeof body === "string" ? body : JSON.stringify(body);
70
+ if (method !== "GET" && method !== "HEAD") {
71
+ headers["Content-Type"] = contentType || "application/json";
72
+ if (rawBody) {
73
+ requestOptions.body = new Uint8Array(rawBody);
74
+ }
75
+ else if (body) {
76
+ requestOptions.body = typeof body === "string" ? body : JSON.stringify(body);
77
+ }
73
78
  }
74
79
  return requestOptions;
75
80
  };
@@ -1 +1 @@
1
- {"version":3,"file":"server-props.d.ts","sourceRoot":"","sources":["../../src/lib/server-props.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,MAAM,CAAC;AAG1D,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAKpD,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,sBAAuB,SAAQ,eAAe;IAC7D,QAAQ,EAAE,YAAY,CAAC;CACxB;AAID,eAAO,MAAM,mBAAmB,oCAA+C,CAAC;AAEhF,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAGlE;AAGD,wBAAgB,gBAAgB,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAgBrE;AAID,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAI3F;AAeD,MAAM,MAAM,eAAe,GAAG;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CAAE,CAAC;AACrF,eAAO,MAAM,wBAAwB;cACzB,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI;SAC3B,CAAC;AAIhB,wBAAgB,yBAAyB,CAAC,EACxC,QAAQ,EACR,SAAS,GACV,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,SAAS,EAAE,eAAe,EAAE,CAAC;CAC9B,2CAUA;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,OAAO,EACP,cAAc,EACd,YAAY,GACb,EAAE,sBAAsB,2CAwCxB;AAqID;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,eAAe,GAAG,eAAe,EAC3E,IAAI,EAAE,MAAM,EACZ,gBAAgB,EAAE,aAAa,CAAC,GAAG,CAAC,EACpC,OAAO,GAAE;IACP,IAAI,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,cAAc,EAAE,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC,CAAC;CACxE,GACL;IACD,cAAc,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC;IACnC,kBAAkB,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC,CAAC;CAC5C,CAwGA"}
1
+ {"version":3,"file":"server-props.d.ts","sourceRoot":"","sources":["../../src/lib/server-props.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,MAAM,CAAC;AAG1D,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAKpD,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,sBAAuB,SAAQ,eAAe;IAC7D,QAAQ,EAAE,YAAY,CAAC;CACxB;AAID,eAAO,MAAM,mBAAmB,oCAA+C,CAAC;AAEhF,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAGlE;AAGD,wBAAgB,gBAAgB,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAgBrE;AAID,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAI3F;AA+DD,MAAM,MAAM,eAAe,GAAG;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CAAE,CAAC;AACrF,eAAO,MAAM,wBAAwB;cACzB,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI;SAC3B,CAAC;AAIhB,wBAAgB,yBAAyB,CAAC,EACxC,QAAQ,EACR,SAAS,GACV,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,SAAS,EAAE,eAAe,EAAE,CAAC;CAC9B,2CAUA;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,OAAO,EACP,cAAc,EACd,YAAY,GACb,EAAE,sBAAsB,2CAwCxB;AAqID;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,eAAe,GAAG,eAAe,EAC3E,IAAI,EAAE,MAAM,EACZ,gBAAgB,EAAE,aAAa,CAAC,GAAG,CAAC,EACpC,OAAO,GAAE;IACP,IAAI,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,cAAc,EAAE,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC,CAAC;CACxE,GACL;IACD,cAAc,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC;IACnC,kBAAkB,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC,CAAC;CAC5C,CA0GA"}
@@ -93,6 +93,46 @@ function extractUtmParamsFromQuery(query) {
93
93
  }
94
94
  return result;
95
95
  }
96
+ function extractDynamicParamNames(routePattern) {
97
+ const names = [];
98
+ if (!routePattern)
99
+ return names;
100
+ const regex = /\[\[?\.\.\.([^\]]+)\]?\]|\[([^\]]+)\]/g;
101
+ let match = null;
102
+ while ((match = regex.exec(routePattern))) {
103
+ const paramName = match[1] || match[2];
104
+ if (paramName && !names.includes(paramName)) {
105
+ names.push(paramName);
106
+ }
107
+ }
108
+ return names;
109
+ }
110
+ function extractRouteParams(context, dynamicParamNames) {
111
+ const result = {};
112
+ if (dynamicParamNames.length === 0)
113
+ return result;
114
+ const paramsSource = (context?.params || context?.query || {});
115
+ for (const name of dynamicParamNames) {
116
+ const value = paramsSource[name];
117
+ if (value != null) {
118
+ result[name] = value;
119
+ }
120
+ }
121
+ return result;
122
+ }
123
+ function mergeRequestParams(routeParams, utmParams, explicitParams) {
124
+ const merged = { ...(routeParams || {}), ...(utmParams || {}) };
125
+ if (!explicitParams || typeof explicitParams !== "object")
126
+ return merged;
127
+ for (const key of Object.keys(explicitParams)) {
128
+ const value = explicitParams[key];
129
+ // Nullish explicit values should not erase route-derived defaults.
130
+ if (value !== null && value !== undefined) {
131
+ merged[key] = value;
132
+ }
133
+ }
134
+ return merged;
135
+ }
96
136
  exports.PrefetchCollectorContext = React.createContext(null);
97
137
  // Provider that collects prefetch requests during component rendering
98
138
  // Used during build-time prepass to discover all API calls
@@ -267,6 +307,7 @@ async function fetchEndpointData(endpointPath, params, cookieHeader) {
267
307
  * - SSR: Fresh data on every request, always has access to request cookies
268
308
  */
269
309
  function createServerProps(path, PlasmicComponent, options = {}) {
310
+ const dynamicParamNames = extractDynamicParamNames(path);
270
311
  const { mode = "isr", revalidate = 60, endpoints = [] } = options;
271
312
  const finalRevalidate = process.env.NODE_ENV === "production" ? revalidate : 60;
272
313
  const isSSR = mode === "ssr";
@@ -312,18 +353,19 @@ function createServerProps(path, PlasmicComponent, options = {}) {
312
353
  const cookieHeader = isSSR
313
354
  ? context.req?.headers?.cookie || null
314
355
  : context.req?.headers?.cookie || null;
356
+ const routeParams = extractRouteParams(context, dynamicParamNames);
315
357
  const utmFromRequest = isSSR ? extractUtmParamsFromQuery(context?.query) : {};
316
358
  const endpointData = {};
317
359
  if (merged.length > 0) {
318
360
  const seen = new Set();
319
361
  const fetchPromises = merged.map(async (cfg) => {
320
- // Merge UTM params from the incoming request; explicit params override UTM values.
321
- const paramsWithUtm = { ...(utmFromRequest || {}), ...(cfg.params || {}) };
322
- const key = buildEndpointKey(cfg.endpointPath, paramsWithUtm);
362
+ // Merge route params + UTM params from the request; explicit component params override when non-null.
363
+ const requestParams = mergeRequestParams(routeParams, utmFromRequest, cfg.params);
364
+ const key = buildEndpointKey(cfg.endpointPath, requestParams);
323
365
  if (seen.has(key))
324
366
  return; // Deduplicate
325
367
  seen.add(key);
326
- const data = await fetchEndpointData(cfg.endpointPath, paramsWithUtm, cookieHeader);
368
+ const data = await fetchEndpointData(cfg.endpointPath, requestParams, cookieHeader);
327
369
  if (data !== null) {
328
370
  endpointData[key] = data;
329
371
  }
@@ -1,4 +1,9 @@
1
1
  import type { NextApiRequest, NextApiResponse } from "next";
2
+ export declare const config: {
3
+ api: {
4
+ bodyParser: boolean;
5
+ };
6
+ };
2
7
  export declare function cxfApiHandler(req: NextApiRequest, res: NextApiResponse): Promise<void>;
3
8
  export default cxfApiHandler;
4
9
  //# sourceMappingURL=cxf.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cxf.d.ts","sourceRoot":"","sources":["../../../src/pages/api/cxf.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,MAAM,CAAC;AAI5D,wBAAsB,aAAa,CAAC,GAAG,EAAE,cAAc,EAAE,GAAG,EAAE,eAAe,iBAmD5E;AAED,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"cxf.d.ts","sourceRoot":"","sources":["../../../src/pages/api/cxf.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,MAAM,CAAC;AAK5D,eAAO,MAAM,MAAM;;;;CAElB,CAAC;AAcF,wBAAsB,aAAa,CAAC,GAAG,EAAE,cAAc,EAAE,GAAG,EAAE,eAAe,iBAqE5E;AAED,eAAe,aAAa,CAAC"}
@@ -1,8 +1,24 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.config = void 0;
3
4
  exports.cxfApiHandler = cxfApiHandler;
4
5
  const cxf_auth_1 = require("../../lib/cxf-auth");
5
6
  const api_route_helpers_1 = require("../../lib/api-route-helpers");
7
+ // Disable Next.js body parser to support multipart/binary requests
8
+ exports.config = {
9
+ api: { bodyParser: false },
10
+ };
11
+ /**
12
+ * Reads the raw body from a Next.js request as a Buffer.
13
+ */
14
+ function getRawBody(req) {
15
+ return new Promise((resolve, reject) => {
16
+ const chunks = [];
17
+ req.on("data", (chunk) => chunks.push(chunk));
18
+ req.on("end", () => resolve(Buffer.concat(chunks)));
19
+ req.on("error", reject);
20
+ });
21
+ }
6
22
  async function cxfApiHandler(req, res) {
7
23
  const allowedMethods = ["GET", "POST", "PATCH", "PUT", "DELETE"];
8
24
  if (!allowedMethods.includes(req.method || "")) {
@@ -25,20 +41,37 @@ async function cxfApiHandler(req, res) {
25
41
  ? normalizedPath
26
42
  : `v1/endpoints/${normalizedPath}`;
27
43
  const targetUrl = `${baseUrl}/api/${targetPath}${(0, api_route_helpers_1.buildQueryString)(req.query)}`;
28
- const body = req.method !== "GET" && req.method !== "HEAD" && req.body ? req.body : undefined;
29
44
  const retryOnAuthError = !normalizedPath.match(/^(v1\/(login|register)|dev\/v1\/)/);
30
- const { response, newTokens } = await (0, cxf_auth_1.makeAuthenticatedRequest)(targetUrl, {
45
+ const isGet = req.method === "GET" || req.method === "HEAD";
46
+ const requestOptions = {
31
47
  method: req.method || "GET",
32
- body,
33
48
  apiKey,
34
49
  userToken: null,
35
50
  cookieHeader: req.headers.cookie || null,
36
51
  retryOnAuthError,
37
- });
52
+ };
53
+ if (!isGet) {
54
+ const rawBody = await getRawBody(req);
55
+ const contentType = req.headers["content-type"] || "";
56
+ const isMultipart = contentType.includes("multipart/form-data");
57
+ if (rawBody.length > 0) {
58
+ if (isMultipart) {
59
+ // Forward raw body preserving multipart boundaries
60
+ requestOptions.rawBody = rawBody;
61
+ requestOptions.contentType = contentType;
62
+ }
63
+ else {
64
+ // JSON/text body
65
+ requestOptions.body = rawBody.toString("utf-8");
66
+ }
67
+ }
68
+ }
69
+ const { response, newTokens } = await (0, cxf_auth_1.makeAuthenticatedRequest)(targetUrl, requestOptions);
38
70
  const setCookieHeaders = (0, cxf_auth_1.extractSetCookieHeaders)(response);
39
71
  const tokens = (0, cxf_auth_1.extractTokensFromSetCookie)(setCookieHeaders);
40
72
  const finalTokens = tokens.accessToken || tokens.refreshToken ? tokens : newTokens;
41
73
  (0, api_route_helpers_1.setAuthCookies)(res, finalTokens);
74
+ (0, api_route_helpers_1.forwardExtraCookies)(res, setCookieHeaders);
42
75
  return (0, api_route_helpers_1.sendResponse)(res, response);
43
76
  }
44
77
  catch (err) {
@@ -1,8 +1,9 @@
1
1
  import type { AppProps } from "next/app";
2
+ import * as React from "react";
2
3
  type CxfAppProps = AppProps & {
3
4
  tokenClass?: string;
4
5
  appRootId?: string;
5
6
  };
6
- export declare function CxfApp({ Component, pageProps, tokenClass, appRootId }: CxfAppProps): import("react/jsx-runtime").JSX.Element;
7
+ export declare function CxfApp({ Component, pageProps, tokenClass, appRootId }: CxfAppProps): string | number | bigint | boolean | Iterable<React.ReactNode> | Promise<React.AwaitedReactNode> | import("react/jsx-runtime").JSX.Element | null | undefined;
7
8
  export default CxfApp;
8
9
  //# sourceMappingURL=app.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/pages/app.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAMzC,KAAK,WAAW,GAAG,QAAQ,GAAG;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAYF,wBAAgB,MAAM,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,SAAyB,EAAE,EAAE,WAAW,2CA+KlG;AAED,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/pages/app.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAGzC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,KAAK,WAAW,GAAG,QAAQ,GAAG;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAYF,wBAAgB,MAAM,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,SAAyB,EAAE,EAAE,WAAW,iKAkLlG;AAED,eAAe,MAAM,CAAC"}
package/dist/pages/app.js CHANGED
@@ -173,15 +173,18 @@ function CxfApp({ Component, pageProps, tokenClass, appRootId = "plasmic-app" })
173
173
  Component.isrEnabled ||
174
174
  serverPageProps.queryCache ||
175
175
  serverPageProps.endpointData);
176
+ const wrapWithTokenClass = (node) => {
177
+ if (!tokenClass) {
178
+ return node;
179
+ }
180
+ return (0, jsx_runtime_1.jsx)("div", { className: tokenClass, children: node });
181
+ };
176
182
  // Fast path: minimal server-side rendering for ISR pages.
177
183
  if (typeof window === "undefined" && isServerPage) {
178
- return ((0, jsx_runtime_1.jsx)(react_web_1.PlasmicRootProvider, { Head: head_1.default, Link: link_1.default, children: (0, jsx_runtime_1.jsx)(Component, { ...safePageProps }) }));
184
+ return wrapWithTokenClass((0, jsx_runtime_1.jsx)(react_web_1.PlasmicRootProvider, { Head: head_1.default, Link: link_1.default, children: (0, jsx_runtime_1.jsx)(Component, { ...safePageProps }) }));
179
185
  }
180
186
  // Regular path: full initialization for client-side and non-ISR pages.
181
187
  const content = ((0, jsx_runtime_1.jsx)(react_web_1.PlasmicRootProvider, { Head: head_1.default, Link: link_1.default, children: (0, jsx_runtime_1.jsx)(query_1.PlasmicQueryDataProvider, { suspense: true, children: (0, jsx_runtime_1.jsx)(Component, { ...safePageProps }) }) }));
182
- if (tokenClass) {
183
- return (0, jsx_runtime_1.jsx)("div", { className: tokenClass, children: content });
184
- }
185
- return content;
188
+ return wrapWithTokenClass(content);
186
189
  }
187
190
  exports.default = CxfApp;
@@ -1 +1 @@
1
- {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../src/register.ts"],"names":[],"mappings":"AAGA,wBAAgB,sBAAsB,SAmFrC"}
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../src/register.ts"],"names":[],"mappings":"AAGA,wBAAgB,sBAAsB,SA4GrC"}
package/dist/register.js CHANGED
@@ -51,6 +51,14 @@ function registerCodeComponents() {
51
51
  description: "Automatically fetch on mount (default: true for GET, false for others).",
52
52
  advanced: true,
53
53
  },
54
+ canvasAutoFetchCooldownMs: {
55
+ type: "number",
56
+ displayName: "Canvas refresh interval (ms)",
57
+ description: "In Plasmic Studio only, identical GET requests are throttled to this interval (default: 300000). Runtime pages are unaffected.",
58
+ defaultValue: 300000,
59
+ advanced: true,
60
+ hidden: (props) => props.method && props.method !== "GET",
61
+ },
54
62
  trigger: {
55
63
  type: "number",
56
64
  displayName: "Trigger",
@@ -85,6 +93,23 @@ function registerCodeComponents() {
85
93
  },
86
94
  },
87
95
  },
96
+ actions: [
97
+ {
98
+ type: "button-action",
99
+ label: "Refetch now",
100
+ hidden: (props) => props.method && props.method !== "GET",
101
+ onClick: ({ componentProps, studioOps }) => {
102
+ const nextTrigger = Number(componentProps?.trigger ?? 0) + 1;
103
+ if (typeof studioOps?.updateProps === "function") {
104
+ studioOps.updateProps({ trigger: nextTrigger });
105
+ return;
106
+ }
107
+ if (typeof studioOps?.updateStates === "function") {
108
+ studioOps.updateStates({ trigger: nextTrigger });
109
+ }
110
+ },
111
+ },
112
+ ],
88
113
  });
89
114
  }
90
115
  // Auto-register when imported
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mints-cloud/cxf-codegen",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Plasmic CXF codegen library for Next.js applications",
5
5
  "author": "Ruben Gomez",
6
6
  "license": "MIT",