webstudio 0.304.0 → 0.306.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webstudio",
3
- "version": "0.304.0",
3
+ "version": "0.306.0",
4
4
  "description": "Webstudio CLI",
5
5
  "author": "Webstudio <github@webstudio.is>",
6
6
  "homepage": "https://webstudio.is",
@@ -53,10 +53,10 @@
53
53
  "which": "^5.0.0",
54
54
  "yargs": "^17.7.2",
55
55
  "zod": "^4.4.3",
56
- "@webstudio-is/http-client": "0.304.0",
57
- "@webstudio-is/project-migrations": "0.304.0",
58
- "@webstudio-is/sync-client": "0.0.0",
59
- "@webstudio-is/protocol": "0.304.0"
56
+ "@webstudio-is/project-migrations": "0.306.0",
57
+ "@webstudio-is/http-client": "0.306.0",
58
+ "@webstudio-is/protocol": "0.306.0",
59
+ "@webstudio-is/sync-client": "0.0.0"
60
60
  },
61
61
  "devDependencies": {
62
62
  "@cloudflare/vite-plugin": "^1.1.0",
@@ -80,7 +80,7 @@
80
80
  "@types/which": "^3.0.4",
81
81
  "@types/yargs": "^17.0.33",
82
82
  "@vercel/react-router": "^1.1.0",
83
- "@vitejs/plugin-react": "^4.4.1",
83
+ "@vitejs/plugin-react": "^4.7.0",
84
84
  "h3": "^1.15.1",
85
85
  "ipx": "^3.0.3",
86
86
  "isbot": "^5.1.25",
@@ -95,28 +95,28 @@
95
95
  "shiki": "4.4.1",
96
96
  "ts-expect": "^1.3.0",
97
97
  "typescript": "7.0.2",
98
- "vike": "^0.4.229",
99
- "vite": "^6.3.4",
98
+ "vike": "0.4.267-commit-feffb0f",
99
+ "vite": "7.1.12",
100
100
  "vitest": "^3.1.2",
101
101
  "wrangler": "4.130.0",
102
- "@webstudio-is/css-engine": "0.304.0",
103
- "@webstudio-is/expression": "0.304.0",
104
- "@webstudio-is/content-engine": "0.304.0",
105
- "@webstudio-is/fonts": "0.304.0",
106
- "@webstudio-is/image": "0.304.0",
102
+ "@webstudio-is/css-engine": "0.306.0",
103
+ "@webstudio-is/content-engine": "0.306.0",
104
+ "@webstudio-is/expression": "0.306.0",
105
+ "@webstudio-is/fonts": "0.306.0",
106
+ "@webstudio-is/image": "0.306.0",
107
+ "@webstudio-is/react-sdk": "0.306.0",
108
+ "@webstudio-is/query-builder": "0.306.0",
109
+ "@webstudio-is/sdk": "0.306.0",
107
110
  "@webstudio-is/project-build": "0.0.0",
108
- "@webstudio-is/query-builder": "0.304.0",
109
- "@webstudio-is/sdk-components-react-radix": "0.304.0",
110
- "@webstudio-is/sdk-components-react-remix": "0.304.0",
111
- "@webstudio-is/sdk-components-react": "0.304.0",
112
- "@webstudio-is/sdk-components-react-router": "0.304.0",
113
- "@webstudio-is/vision": "0.0.0",
114
- "@webstudio-is/sdk-components-animation": "0.304.0",
115
- "@webstudio-is/sdk-components-registry": "0.304.0",
111
+ "@webstudio-is/sdk-components-react": "0.306.0",
112
+ "@webstudio-is/sdk-components-animation": "0.306.0",
113
+ "@webstudio-is/sdk-components-react-radix": "0.306.0",
114
+ "@webstudio-is/sdk-components-registry": "0.306.0",
116
115
  "@webstudio-is/tsconfig": "1.0.7",
117
- "@webstudio-is/react-sdk": "0.304.0",
118
- "@webstudio-is/sdk": "0.304.0",
119
- "@webstudio-is/wsauth": "0.304.0"
116
+ "@webstudio-is/sdk-components-react-remix": "0.306.0",
117
+ "@webstudio-is/sdk-components-react-router": "0.306.0",
118
+ "@webstudio-is/wsauth": "0.306.0",
119
+ "@webstudio-is/vision": "0.0.0"
120
120
  },
121
121
  "scripts": {
122
122
  "typecheck": "tsc --noEmit",
@@ -12,7 +12,7 @@
12
12
  "build-cf-types": "wrangler types"
13
13
  },
14
14
  "dependencies": {
15
- "@webstudio-is/wsauth": "0.304.0",
15
+ "@webstudio-is/wsauth": "0.306.0",
16
16
  "@remix-run/cloudflare": "2.16.5",
17
17
  "@remix-run/cloudflare-pages": "2.16.5"
18
18
  },
@@ -12,12 +12,24 @@ import {
12
12
  import { useLoaderData } from "@remix-run/react";
13
13
  import {
14
14
  isLocalResource,
15
- loadResource,
16
15
  loadResources,
16
+ loadResourceWithEmail,
17
+ loadResourcesWithEmail,
17
18
  cachedFetch,
19
+ getSystemSearch,
20
+ } from "@webstudio-is/sdk/runtime";
21
+ import {
22
+ handleManagedFormSubmission,
23
+ getManagedFormFailure,
24
+ readFormDataWithLimit,
25
+ type ManagedFormResponse,
26
+ } from "@webstudio-is/sdk/form/server";
27
+ import {
28
+ managedFormRequestParamName,
18
29
  formIdFieldName,
30
+ managedFormIdFieldName,
19
31
  formBotFieldName,
20
- } from "@webstudio-is/sdk/runtime";
32
+ } from "@webstudio-is/sdk/form";
21
33
  import { authenticateRequest } from "@webstudio-is/wsauth";
22
34
  import {
23
35
  ReactSdkContext,
@@ -37,6 +49,8 @@ import {
37
49
  } from "__CLIENT__";
38
50
  import {
39
51
  getResources,
52
+ getManagedFormSubmissions,
53
+ getManagedFormResourceGraph,
40
54
  getPageMeta,
41
55
  getRemixParams,
42
56
  contactEmail,
@@ -46,6 +60,11 @@ import css from "__CSS__?url";
46
60
  import { sitemap } from "__SITEMAP__";
47
61
  import { authRoutes } from "__AUTH__";
48
62
  import { createGeneratedAssetResourceFetch } from "__ASSET_QUERY_RUNTIME__";
63
+ import {
64
+ createManagedFormEmailSender,
65
+ createManagedFormResourceFetch,
66
+ validateManagedFormEmail,
67
+ } from "__MANAGED_FORM_FETCH__";
49
68
  import { assetUrlsByPath } from "__ASSETS__";
50
69
 
51
70
  const authenticateProductionRequest = (request: Request) => {
@@ -113,7 +132,7 @@ export const loader = async (arg: LoaderFunctionArgs) => {
113
132
  const params = getRemixParams(arg.params);
114
133
  const system = {
115
134
  params,
116
- search: Object.fromEntries(url.searchParams),
135
+ ...getSystemSearch(url.searchParams),
117
136
  origin: url.origin,
118
137
  pathname: url.pathname,
119
138
  };
@@ -257,24 +276,66 @@ const getRequestHost = (request: Request): string =>
257
276
  export const action = async ({
258
277
  request,
259
278
  context,
279
+ params,
260
280
  }: ActionFunctionArgs): Promise<
261
- { success: true } | { success: false; errors: string[] }
281
+ { success: true } | { success: false; errors: string[] } | ManagedFormResponse
262
282
  > => {
263
283
  authenticateProductionRequest(request);
264
284
 
285
+ let isManagedFormRequest = false;
265
286
  try {
266
287
  const url = new URL(request.url);
267
- url.host = getRequestHost(request);
268
-
269
- const formData = await request.formData();
288
+ isManagedFormRequest =
289
+ url.searchParams.get(managedFormRequestParamName) === "1";
290
+ url.searchParams.delete(managedFormRequestParamName);
291
+ if (!isManagedFormRequest) {
292
+ url.host = getRequestHost(request);
293
+ }
294
+ const formData = isManagedFormRequest
295
+ ? await readFormDataWithLimit(request)
296
+ : await request.formData();
270
297
 
271
298
  const system = {
272
- params: {},
273
- search: {},
299
+ params: getRemixParams(params ?? {}),
300
+ ...getSystemSearch(url.searchParams),
274
301
  origin: url.origin,
275
302
  pathname: url.pathname,
276
303
  };
277
304
 
305
+ const managedFormIds = formData.getAll(managedFormIdFieldName);
306
+ if (!isManagedFormRequest && managedFormIds.length > 0) {
307
+ throw new Error("Invalid Form submission");
308
+ }
309
+ if (isManagedFormRequest) {
310
+ if (managedFormIds.length !== 1 || formData.has(formIdFieldName)) {
311
+ throw new Error("Invalid Form submission");
312
+ }
313
+ const protectedFetch = createManagedFormResourceFetch({
314
+ request,
315
+ context,
316
+ projectDomain,
317
+ });
318
+ return await handleManagedFormSubmission({
319
+ request,
320
+ formData,
321
+ url,
322
+ system,
323
+ configuration: (id) => getManagedFormSubmissions().get(id),
324
+ getGraph: (id, values) => getManagedFormResourceGraph(id, values),
325
+ createEmailSender: (data) =>
326
+ createManagedFormEmailSender({ context, formData: data, projectId }),
327
+ validateEmail: validateManagedFormEmail,
328
+ resourceFetch: protectedFetch,
329
+ validateDestination: protectedFetch.validateDestination,
330
+ trustedIp:
331
+ typeof context === "object" &&
332
+ context !== null &&
333
+ "cloudflare" in context
334
+ ? request.headers.get("cf-connecting-ip") ?? undefined
335
+ : undefined,
336
+ });
337
+ }
338
+
278
339
  const resourceName = formData.get(formIdFieldName);
279
340
  const generatedResources = getResources({ system });
280
341
  const actionResource =
@@ -308,7 +369,7 @@ export const action = async ({
308
369
  formData.delete(formIdFieldName);
309
370
  formData.delete(formBotFieldName);
310
371
 
311
- let result: Awaited<ReturnType<typeof loadResource>>;
372
+ let result: Awaited<ReturnType<typeof loadResourceWithEmail>>;
312
373
  if (actionResource === undefined) {
313
374
  if (contactEmail === undefined) {
314
375
  throw new Error("Contact email not found");
@@ -322,14 +383,14 @@ export const action = async ({
322
383
  if (resource === undefined) {
323
384
  throw Error("Resource not found");
324
385
  }
325
- result = await loadResource(fetch, resource);
386
+ result = await loadResourceWithEmail(fetch, resource);
326
387
  } else {
327
388
  const actionFetch = await createGeneratedAssetResourceFetch({
328
389
  request,
329
390
  context,
330
391
  fallback: customFetch,
331
392
  });
332
- const results = await loadResources(
393
+ const results = await loadResourcesWithEmail(
333
394
  actionFetch,
334
395
  {
335
396
  ...generatedResources.data,
@@ -348,7 +409,7 @@ export const action = async ({
348
409
  if (actionResult === undefined) {
349
410
  throw Error("Resource not found");
350
411
  }
351
- result = actionResult as Awaited<ReturnType<typeof loadResource>>;
412
+ result = actionResult as Awaited<ReturnType<typeof loadResourceWithEmail>>;
352
413
  }
353
414
  const { ok, statusText } = result;
354
415
  if (ok) {
@@ -358,6 +419,11 @@ export const action = async ({
358
419
  } catch (error) {
359
420
  console.error(error);
360
421
 
422
+ if (isManagedFormRequest) {
423
+ return getManagedFormFailure(
424
+ error instanceof Error ? error.message : "Unknown error"
425
+ );
426
+ }
361
427
  return {
362
428
  success: false,
363
429
  errors: [error instanceof Error ? error.message : "Unknown error"],
@@ -1,5 +1,5 @@
1
1
  import { type LoaderFunctionArgs, redirect } from "@remix-run/server-runtime";
2
- import { isLocalResource, loadResources } from "@webstudio-is/sdk/runtime";
2
+ import { isLocalResource, loadResources, getSystemSearch } from "@webstudio-is/sdk/runtime";
3
3
  import { authenticateRequest } from "@webstudio-is/wsauth";
4
4
  import { projectDomain } from "__CLIENT__";
5
5
  import { getPageMeta, getRemixParams, getResources } from "__SERVER__";
@@ -71,7 +71,7 @@ export const loader = async (arg: LoaderFunctionArgs) => {
71
71
 
72
72
  const system = {
73
73
  params,
74
- search: Object.fromEntries(url.searchParams),
74
+ ...getSystemSearch(url.searchParams),
75
75
  origin: url.origin,
76
76
  pathname: url.pathname,
77
77
  };
@@ -1,6 +1,6 @@
1
1
  import { renderToString } from "react-dom/server";
2
2
  import { type LoaderFunctionArgs, redirect } from "@remix-run/server-runtime";
3
- import { isLocalResource, loadResources } from "@webstudio-is/sdk/runtime";
3
+ import { isLocalResource, loadResources, getSystemSearch } from "@webstudio-is/sdk/runtime";
4
4
  import { authenticateRequest } from "@webstudio-is/wsauth";
5
5
  import {
6
6
  ReactSdkContext,
@@ -79,7 +79,7 @@ export const loader = async (arg: LoaderFunctionArgs) => {
79
79
 
80
80
  const system = {
81
81
  params,
82
- search: Object.fromEntries(url.searchParams),
82
+ ...getSystemSearch(url.searchParams),
83
83
  origin: url.origin,
84
84
  pathname: url.pathname,
85
85
  };
@@ -13,14 +13,14 @@
13
13
  "@remix-run/node": "2.16.5",
14
14
  "@remix-run/react": "2.16.5",
15
15
  "@remix-run/server-runtime": "2.16.5",
16
- "@webstudio-is/image": "0.304.0",
17
- "@webstudio-is/react-sdk": "0.304.0",
18
- "@webstudio-is/sdk": "0.304.0",
19
- "@webstudio-is/sdk-components-react": "0.304.0",
20
- "@webstudio-is/sdk-components-animation": "0.304.0",
21
- "@webstudio-is/sdk-components-react-radix": "0.304.0",
22
- "@webstudio-is/sdk-components-react-remix": "0.304.0",
23
- "@webstudio-is/wsauth": "0.304.0",
16
+ "@webstudio-is/image": "0.306.0",
17
+ "@webstudio-is/react-sdk": "0.306.0",
18
+ "@webstudio-is/sdk": "0.306.0",
19
+ "@webstudio-is/sdk-components-react": "0.306.0",
20
+ "@webstudio-is/sdk-components-animation": "0.306.0",
21
+ "@webstudio-is/sdk-components-react-radix": "0.306.0",
22
+ "@webstudio-is/sdk-components-react-remix": "0.306.0",
23
+ "@webstudio-is/wsauth": "0.306.0",
24
24
  "isbot": "^5.1.25",
25
25
  "react": "18.3.0-canary-14898b6a9-20240318",
26
26
  "react-dom": "18.3.0-canary-14898b6a9-20240318",
@@ -12,13 +12,25 @@ import {
12
12
  } from "react-router";
13
13
  import {
14
14
  isLocalResource,
15
- loadResource,
16
15
  loadResources,
17
- formIdFieldName,
18
- formBotFieldName,
16
+ loadResourceWithEmail,
17
+ loadResourcesWithEmail,
18
+ getSystemSearch,
19
19
  cachedFetch,
20
20
  } from "@webstudio-is/sdk/runtime";
21
- import { authenticateRequest } from "@webstudio-is/wsauth";
21
+ import {
22
+ handleManagedFormSubmission,
23
+ getManagedFormFailure,
24
+ readFormDataWithLimit,
25
+ type ManagedFormResponse,
26
+ } from "@webstudio-is/sdk/form/server";
27
+ import {
28
+ managedFormRequestParamName,
29
+ formIdFieldName,
30
+ managedFormIdFieldName,
31
+ formBotFieldName,
32
+ } from "@webstudio-is/sdk/form";
33
+ import { authenticateProjectRequest } from "@webstudio-is/wsauth";
22
34
  import {
23
35
  ReactSdkContext,
24
36
  PageSettingsMeta,
@@ -36,6 +48,8 @@ import {
36
48
  } from "__CLIENT__";
37
49
  import {
38
50
  getResources,
51
+ getManagedFormSubmissions,
52
+ getManagedFormResourceGraph,
39
53
  getPageMeta,
40
54
  getRemixParams,
41
55
  contactEmail,
@@ -45,26 +59,13 @@ import css from "__CSS__?url";
45
59
  import { sitemap } from "__SITEMAP__";
46
60
  import { authRoutes } from "__AUTH__";
47
61
  import { createGeneratedAssetResourceFetch } from "__ASSET_QUERY_RUNTIME__";
62
+ import {
63
+ createManagedFormEmailSender,
64
+ createManagedFormResourceFetch,
65
+ validateManagedFormEmail,
66
+ } from "__MANAGED_FORM_FETCH__";
48
67
  import { assetUrlsByPath } from "__ASSETS__";
49
68
 
50
- const authenticateProductionRequest = (request: Request) => {
51
- const host =
52
- request.headers.get("x-forwarded-host") ||
53
- request.headers.get("host") ||
54
- "";
55
-
56
- const requestHost = host.split(":")[0];
57
- if (
58
- projectDomain !== undefined &&
59
- (requestHost === projectDomain ||
60
- requestHost.startsWith(`${projectDomain}.`))
61
- ) {
62
- return;
63
- }
64
-
65
- return authenticateRequest(request, authRoutes);
66
- };
67
-
68
69
  const customFetch: typeof fetch = (input, init) => {
69
70
  if (typeof input !== "string") {
70
71
  return cachedFetch(projectId, input, init);
@@ -99,7 +100,11 @@ const customFetch: typeof fetch = (input, init) => {
99
100
  };
100
101
 
101
102
  export const loader = async (arg: LoaderFunctionArgs) => {
102
- const authRoute = authenticateProductionRequest(arg.request);
103
+ const authRoute = authenticateProjectRequest(
104
+ arg.request,
105
+ authRoutes,
106
+ projectDomain
107
+ );
103
108
 
104
109
  const url = new URL(arg.request.url);
105
110
  const host =
@@ -112,7 +117,7 @@ export const loader = async (arg: LoaderFunctionArgs) => {
112
117
  const params = getRemixParams(arg.params);
113
118
  const system = {
114
119
  params,
115
- search: Object.fromEntries(url.searchParams),
120
+ ...getSystemSearch(url.searchParams),
116
121
  origin: url.origin,
117
122
  pathname: url.pathname,
118
123
  };
@@ -256,24 +261,66 @@ const getRequestHost = (request: Request): string =>
256
261
  export const action = async ({
257
262
  request,
258
263
  context,
264
+ params,
259
265
  }: ActionFunctionArgs): Promise<
260
- { success: true } | { success: false; errors: string[] }
266
+ { success: true } | { success: false; errors: string[] } | ManagedFormResponse
261
267
  > => {
262
- authenticateProductionRequest(request);
268
+ authenticateProjectRequest(request, authRoutes, projectDomain);
263
269
 
270
+ let isManagedFormRequest = false;
264
271
  try {
265
272
  const url = new URL(request.url);
266
- url.host = getRequestHost(request);
267
-
268
- const formData = await request.formData();
273
+ isManagedFormRequest =
274
+ url.searchParams.get(managedFormRequestParamName) === "1";
275
+ url.searchParams.delete(managedFormRequestParamName);
276
+ if (!isManagedFormRequest) {
277
+ url.host = getRequestHost(request);
278
+ }
279
+ const formData = isManagedFormRequest
280
+ ? await readFormDataWithLimit(request)
281
+ : await request.formData();
269
282
 
270
283
  const system = {
271
- params: {},
272
- search: {},
284
+ params: getRemixParams(params ?? {}),
285
+ ...getSystemSearch(url.searchParams),
273
286
  origin: url.origin,
274
287
  pathname: url.pathname,
275
288
  };
276
289
 
290
+ const managedFormIds = formData.getAll(managedFormIdFieldName);
291
+ if (!isManagedFormRequest && managedFormIds.length > 0) {
292
+ throw new Error("Invalid Form submission");
293
+ }
294
+ if (isManagedFormRequest) {
295
+ if (managedFormIds.length !== 1 || formData.has(formIdFieldName)) {
296
+ throw new Error("Invalid Form submission");
297
+ }
298
+ const protectedFetch = createManagedFormResourceFetch({
299
+ request,
300
+ context,
301
+ projectDomain,
302
+ });
303
+ return await handleManagedFormSubmission({
304
+ request,
305
+ formData,
306
+ url,
307
+ system,
308
+ configuration: (formId) => getManagedFormSubmissions().get(formId),
309
+ getGraph: getManagedFormResourceGraph,
310
+ createEmailSender: (formData) =>
311
+ createManagedFormEmailSender({ context, formData, projectId }),
312
+ validateEmail: validateManagedFormEmail,
313
+ resourceFetch: protectedFetch,
314
+ validateDestination: protectedFetch.validateDestination,
315
+ trustedIp:
316
+ typeof context === "object" &&
317
+ context !== null &&
318
+ "cloudflare" in context
319
+ ? request.headers.get("cf-connecting-ip") ?? undefined
320
+ : undefined,
321
+ });
322
+ }
323
+
277
324
  const resourceName = formData.get(formIdFieldName);
278
325
  const generatedResources = getResources({ system });
279
326
  const actionResource =
@@ -307,7 +354,7 @@ export const action = async ({
307
354
  formData.delete(formIdFieldName);
308
355
  formData.delete(formBotFieldName);
309
356
 
310
- let result: Awaited<ReturnType<typeof loadResource>>;
357
+ let result: Awaited<ReturnType<typeof loadResourceWithEmail>>;
311
358
  if (actionResource === undefined) {
312
359
  if (contactEmail === undefined) {
313
360
  throw new Error("Contact email not found");
@@ -321,14 +368,14 @@ export const action = async ({
321
368
  if (resource === undefined) {
322
369
  throw Error("Resource not found");
323
370
  }
324
- result = await loadResource(fetch, resource);
371
+ result = await loadResourceWithEmail(fetch, resource);
325
372
  } else {
326
373
  const actionFetch = await createGeneratedAssetResourceFetch({
327
374
  request,
328
375
  context,
329
376
  fallback: customFetch,
330
377
  });
331
- const results = await loadResources(
378
+ const results = await loadResourcesWithEmail(
332
379
  actionFetch,
333
380
  {
334
381
  ...generatedResources.data,
@@ -347,7 +394,7 @@ export const action = async ({
347
394
  if (actionResult === undefined) {
348
395
  throw Error("Resource not found");
349
396
  }
350
- result = actionResult as Awaited<ReturnType<typeof loadResource>>;
397
+ result = actionResult as Awaited<ReturnType<typeof loadResourceWithEmail>>;
351
398
  }
352
399
  const { ok, statusText } = result;
353
400
  if (ok) {
@@ -357,6 +404,11 @@ export const action = async ({
357
404
  } catch (error) {
358
405
  console.error(error);
359
406
 
407
+ if (isManagedFormRequest) {
408
+ return getManagedFormFailure(
409
+ error instanceof Error ? error.message : "Unknown error"
410
+ );
411
+ }
360
412
  return {
361
413
  success: false,
362
414
  errors: [error instanceof Error ? error.message : "Unknown error"],
@@ -1,30 +1,12 @@
1
1
  import { type LoaderFunctionArgs, redirect } from "react-router";
2
- import { isLocalResource, loadResources } from "@webstudio-is/sdk/runtime";
3
- import { authenticateRequest } from "@webstudio-is/wsauth";
2
+ import { isLocalResource, loadResources, getSystemSearch } from "@webstudio-is/sdk/runtime";
3
+ import { authenticateProjectRequest } from "@webstudio-is/wsauth";
4
4
  import { projectDomain } from "__CLIENT__";
5
5
  import { getPageMeta, getRemixParams, getResources } from "__SERVER__";
6
6
  import { sitemap } from "__SITEMAP__";
7
7
  import { authRoutes } from "__AUTH__";
8
8
  import { createGeneratedAssetResourceFetch } from "__ASSET_QUERY_RUNTIME__";
9
9
 
10
- const authenticateProductionRequest = (request: Request) => {
11
- const host =
12
- request.headers.get("x-forwarded-host") ||
13
- request.headers.get("host") ||
14
- "";
15
-
16
- const requestHost = host.split(":")[0];
17
- if (
18
- projectDomain !== undefined &&
19
- (requestHost === projectDomain ||
20
- requestHost.startsWith(`${projectDomain}.`))
21
- ) {
22
- return;
23
- }
24
-
25
- return authenticateRequest(request, authRoutes);
26
- };
27
-
28
10
  const customFetch: typeof fetch = (input, init) => {
29
11
  if (typeof input !== "string") {
30
12
  return fetch(input, init);
@@ -57,7 +39,11 @@ const customFetch: typeof fetch = (input, init) => {
57
39
  };
58
40
 
59
41
  export const loader = async (arg: LoaderFunctionArgs) => {
60
- const authRoute = authenticateProductionRequest(arg.request);
42
+ const authRoute = authenticateProjectRequest(
43
+ arg.request,
44
+ authRoutes,
45
+ projectDomain
46
+ );
61
47
 
62
48
  const url = new URL(arg.request.url);
63
49
  const host =
@@ -71,7 +57,7 @@ export const loader = async (arg: LoaderFunctionArgs) => {
71
57
 
72
58
  const system = {
73
59
  params,
74
- search: Object.fromEntries(url.searchParams),
60
+ ...getSystemSearch(url.searchParams),
75
61
  origin: url.origin,
76
62
  pathname: url.pathname,
77
63
  };
@@ -1,7 +1,7 @@
1
1
  import { renderToString } from "react-dom/server";
2
2
  import { type LoaderFunctionArgs, redirect } from "react-router";
3
- import { isLocalResource, loadResources } from "@webstudio-is/sdk/runtime";
4
- import { authenticateRequest } from "@webstudio-is/wsauth";
3
+ import { isLocalResource, loadResources, getSystemSearch } from "@webstudio-is/sdk/runtime";
4
+ import { authenticateProjectRequest } from "@webstudio-is/wsauth";
5
5
  import {
6
6
  ReactSdkContext,
7
7
  xmlNodeTagSuffix,
@@ -13,24 +13,6 @@ import { sitemap } from "__SITEMAP__";
13
13
  import { authRoutes } from "__AUTH__";
14
14
  import { createGeneratedAssetResourceFetch } from "__ASSET_QUERY_RUNTIME__";
15
15
 
16
- const authenticateProductionRequest = (request: Request) => {
17
- const host =
18
- request.headers.get("x-forwarded-host") ||
19
- request.headers.get("host") ||
20
- "";
21
-
22
- const requestHost = host.split(":")[0];
23
- if (
24
- projectDomain !== undefined &&
25
- (requestHost === projectDomain ||
26
- requestHost.startsWith(`${projectDomain}.`))
27
- ) {
28
- return;
29
- }
30
-
31
- return authenticateRequest(request, authRoutes);
32
- };
33
-
34
16
  const customFetch: typeof fetch = (input, init) => {
35
17
  if (typeof input !== "string") {
36
18
  return fetch(input, init);
@@ -65,7 +47,11 @@ const customFetch: typeof fetch = (input, init) => {
65
47
  };
66
48
 
67
49
  export const loader = async (arg: LoaderFunctionArgs) => {
68
- const authRoute = authenticateProductionRequest(arg.request);
50
+ const authRoute = authenticateProjectRequest(
51
+ arg.request,
52
+ authRoutes,
53
+ projectDomain
54
+ );
69
55
 
70
56
  const url = new URL(arg.request.url);
71
57
  const host =
@@ -79,7 +65,7 @@ export const loader = async (arg: LoaderFunctionArgs) => {
79
65
 
80
66
  const system = {
81
67
  params,
82
- search: Object.fromEntries(url.searchParams),
68
+ ...getSystemSearch(url.searchParams),
83
69
  origin: url.origin,
84
70
  pathname: url.pathname,
85
71
  };
@@ -15,14 +15,14 @@
15
15
  "@react-router/fs-routes": "^7.5.3",
16
16
  "@react-router/node": "^7.5.3",
17
17
  "@react-router/serve": "^7.5.3",
18
- "@webstudio-is/image": "0.304.0",
19
- "@webstudio-is/react-sdk": "0.304.0",
20
- "@webstudio-is/sdk": "0.304.0",
21
- "@webstudio-is/sdk-components-animation": "0.304.0",
22
- "@webstudio-is/sdk-components-react-radix": "0.304.0",
23
- "@webstudio-is/sdk-components-react-router": "0.304.0",
24
- "@webstudio-is/sdk-components-react": "0.304.0",
25
- "@webstudio-is/wsauth": "0.304.0",
18
+ "@webstudio-is/image": "0.306.0",
19
+ "@webstudio-is/react-sdk": "0.306.0",
20
+ "@webstudio-is/sdk": "0.306.0",
21
+ "@webstudio-is/sdk-components-animation": "0.306.0",
22
+ "@webstudio-is/sdk-components-react-radix": "0.306.0",
23
+ "@webstudio-is/sdk-components-react-router": "0.306.0",
24
+ "@webstudio-is/sdk-components-react": "0.306.0",
25
+ "@webstudio-is/wsauth": "0.306.0",
26
26
  "isbot": "^5.1.25",
27
27
  "react": "18.3.0-canary-14898b6a9-20240318",
28
28
  "react-dom": "18.3.0-canary-14898b6a9-20240318",