webstudio 0.123.0 → 0.124.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/README.md CHANGED
@@ -108,7 +108,7 @@ If you want to build a production version of the app, you can run `npm run build
108
108
 
109
109
  ### Vercel
110
110
 
111
- Once you've built the project locally, you can use the [Vercel CLI](https://vercel.com/docs/cli) to deploy your site directly to [Vercel](https://vercel.com):
111
+ Once you've built the project locally, you can use the [Vercel CLI](https://vercel.com/docs/cli) to deploy your project directly to [Vercel](https://vercel.com):
112
112
 
113
113
  ```bash
114
114
  vercel deploy
@@ -118,7 +118,7 @@ Follow the instructions [here](https://vercel.com/docs/cli) to install the `verc
118
118
 
119
119
  ### Netlify
120
120
 
121
- If you want to deploy to netlify, you can use [Netlify CLI](https://docs.netlify.com/cli/get-started/) to deploy your site directly to [Netlify](https://netlify.com/):
121
+ If you want to deploy to netlify, you can use [Netlify CLI](https://docs.netlify.com/cli/get-started/) to deploy your project directly to [Netlify](https://netlify.com/):
122
122
 
123
123
  ```bash
124
124
  netlify deploy
package/lib/cli.js CHANGED
@@ -258,12 +258,16 @@ import pLimit from "p-limit";
258
258
  import ora2 from "ora";
259
259
  import merge from "deepmerge";
260
260
  import {
261
- generateCssText,
261
+ generateCss,
262
262
  generateUtilsExport,
263
263
  generatePageComponent,
264
264
  getIndexesWithinAncestors,
265
265
  namespaceMeta,
266
- normalizeProps
266
+ normalizeProps,
267
+ generateRemixRoute,
268
+ generateRemixParams,
269
+ generateResourcesLoader,
270
+ collectionComponent
267
271
  } from "@webstudio-is/react-sdk";
268
272
  import {
269
273
  createScope,
@@ -382,11 +386,8 @@ var prebuild = async (options) => {
382
386
  }
383
387
  const domain = siteData.build.deployment?.projectDomain;
384
388
  if (domain === void 0) {
385
- throw new Error(`Project domain is missing from the site data`);
389
+ throw new Error(`Project domain is missing from the project data`);
386
390
  }
387
- const remixRoutes = {
388
- routes: []
389
- };
390
391
  const radixComponentNamespacedMetas = Object.entries(
391
392
  radixComponentMetas
392
393
  ).reduce(
@@ -412,14 +413,6 @@ var prebuild = async (options) => {
412
413
  const componentsByPage = {};
413
414
  const siteDataByPage = {};
414
415
  for (const page of Object.values(siteData.pages)) {
415
- const originPath = page.path;
416
- const path = originPath === "" ? "index" : originPath.replace("/", "");
417
- if (path !== "index") {
418
- remixRoutes.routes.push({
419
- path: originPath === "" ? "/" : originPath,
420
- file: `routes/${path}.tsx`
421
- });
422
- }
423
416
  const instanceMap = new Map(siteData.build.instances);
424
417
  const pageInstanceSet = findTreeInstanceIds(
425
418
  instanceMap,
@@ -439,29 +432,41 @@ var prebuild = async (options) => {
439
432
  props.push([prop.id, prop]);
440
433
  }
441
434
  }
435
+ const resourceIds = /* @__PURE__ */ new Set();
442
436
  for (const [dataSourceId, dataSource] of siteData.build.dataSources) {
443
437
  if (dataSource.scopeInstanceId === void 0 || pageInstanceSet.has(dataSource.scopeInstanceId)) {
444
438
  dataSources.push([dataSourceId, dataSource]);
439
+ if (dataSource.type === "resource") {
440
+ resourceIds.add(dataSource.resourceId);
441
+ }
445
442
  }
446
443
  }
447
- siteDataByPage[path] = {
444
+ const resources = [];
445
+ for (const [resourceId, resource] of siteData.build.resources ?? []) {
446
+ if (resourceIds.has(resourceId)) {
447
+ resources.push([resourceId, resource]);
448
+ }
449
+ }
450
+ siteDataByPage[page.path] = {
448
451
  build: {
449
452
  props,
450
453
  instances,
451
- dataSources
454
+ dataSources,
455
+ resources
452
456
  },
453
457
  pages: siteData.pages,
454
458
  page,
455
459
  assets: siteData.assets
456
460
  };
457
- componentsByPage[path] = /* @__PURE__ */ new Set();
461
+ componentsByPage[page.path] = /* @__PURE__ */ new Set();
458
462
  for (const [_instanceId, instance] of instances) {
459
- if (instance.component) {
460
- componentsByPage[path].add(instance.component);
461
- const meta = metas.get(instance.component);
462
- if (meta) {
463
- projectMetas.set(instance.component, meta);
464
- }
463
+ if (instance.component === collectionComponent) {
464
+ continue;
465
+ }
466
+ componentsByPage[page.path].add(instance.component);
467
+ const meta = metas.get(instance.component);
468
+ if (meta) {
469
+ projectMetas.set(instance.component, meta);
465
470
  }
466
471
  }
467
472
  }
@@ -503,6 +508,22 @@ var prebuild = async (options) => {
503
508
  }
504
509
  }
505
510
  }
511
+ spinner.text = "Generating css file";
512
+ const { cssText, classesMap } = generateCss(
513
+ {
514
+ assets: siteData.assets,
515
+ breakpoints: siteData.build?.breakpoints,
516
+ styles: siteData.build?.styles,
517
+ styleSourceSelections: siteData.build?.styleSourceSelections,
518
+ // pass only used metas to not generate unused preset styles
519
+ componentMetas: projectMetas
520
+ },
521
+ {
522
+ assetBaseUrl,
523
+ atomic: siteData.build.pages.settings?.atomicStyles ?? true
524
+ }
525
+ );
526
+ await ensureFileInPath(join4(generatedDir, "index.css"), cssText);
506
527
  spinner.text = "Generating routes and pages";
507
528
  const routeFileTemplate = await readFile4(
508
529
  normalize(
@@ -515,11 +536,11 @@ var prebuild = async (options) => {
515
536
  ),
516
537
  "utf8"
517
538
  );
518
- for (const [pathName, pageComponents] of Object.entries(componentsByPage)) {
539
+ for (const [pathname, pageComponents] of Object.entries(componentsByPage)) {
519
540
  const scope = createScope([
520
541
  // manually maintained list of occupied identifiers
521
542
  "useState",
522
- "ReactNode",
543
+ "Fragment",
523
544
  "PageData",
524
545
  "Asset",
525
546
  "fontAssets",
@@ -528,7 +549,7 @@ var prebuild = async (options) => {
528
549
  "projectId",
529
550
  "formsProperties",
530
551
  "Page",
531
- "props"
552
+ "_props"
532
553
  ]);
533
554
  const namespaces = /* @__PURE__ */ new Map();
534
555
  const BASE_NAMESPACE = "@webstudio-is/sdk-components-react";
@@ -560,25 +581,27 @@ var prebuild = async (options) => {
560
581
  componentImports += `import { ${specifiers} } from "${namespace}";
561
582
  `;
562
583
  }
563
- const pageData = siteDataByPage[pathName];
584
+ const pageData = siteDataByPage[pathname];
564
585
  const renderedPageData = {
565
- site: siteData.build.pages.meta,
586
+ project: siteData.build.pages.meta,
566
587
  page: pageData.page
567
588
  };
568
589
  const rootInstanceId = pageData.page.rootInstanceId;
569
590
  const instances = new Map(pageData.build.instances);
570
591
  const props = new Map(pageData.build.props);
571
592
  const dataSources = new Map(pageData.build.dataSources);
593
+ const resources = new Map(pageData.build.resources);
572
594
  const utilsExport = generateUtilsExport({
573
595
  pages: siteData.build.pages,
574
596
  props
575
597
  });
576
598
  const pageComponent = generatePageComponent({
577
599
  scope,
578
- rootInstanceId,
600
+ page: pageData.page,
579
601
  instances,
580
602
  props,
581
603
  dataSources,
604
+ classesMap,
582
605
  indexesWithinAncestors: getIndexesWithinAncestors(
583
606
  projectMetas,
584
607
  instances,
@@ -588,9 +611,9 @@ var prebuild = async (options) => {
588
611
  const pageExports = `/* eslint-disable */
589
612
  /* This is a auto generated file for building the project */
590
613
 
591
- import { type ReactNode, useState } from "react";
614
+ import { Fragment, useState } from "react";
592
615
  import type { PageData } from "~/routes/_index";
593
- import type { Asset, ImageAsset, SiteMeta } from "@webstudio-is/sdk";
616
+ import type { Asset, ImageAsset, ProjectMeta } from "@webstudio-is/sdk";
594
617
  ${componentImports}
595
618
  export const fontAssets: Asset[] = ${JSON.stringify(fontAssets)}
596
619
  export const imageAssets: ImageAsset[] = ${JSON.stringify(imageAssets)}
@@ -604,31 +627,28 @@ ${pageComponent}
604
627
 
605
628
  export { Page }
606
629
 
630
+ ${generateRemixParams(pathname)}
631
+
607
632
  ${utilsExport}
608
633
  `;
609
- const fileName = pathName === "main" || pathName === "index" ? "_index.tsx" : `${pathName.split("/").map((route) => `[${route}]`).join(".")}._index.tsx`;
610
- const routeFileContent = routeFileTemplate.replace(
611
- "../__generated__/index",
612
- `../__generated__/${fileName}`
634
+ const remixRoute = generateRemixRoute(pathname);
635
+ const fileName = `${remixRoute}.tsx`;
636
+ const routeFileContent = routeFileTemplate.replace('../__generated__/index"', `../__generated__/${remixRoute}"`).replace(
637
+ '../__generated__/index.server"',
638
+ `../__generated__/${remixRoute}.server"`
613
639
  );
614
640
  await ensureFileInPath(join4(routesDir, fileName), routeFileContent);
615
641
  await ensureFileInPath(join4(generatedDir, fileName), pageExports);
642
+ await ensureFileInPath(
643
+ join4(generatedDir, `${remixRoute}.server.tsx`),
644
+ generateResourcesLoader({
645
+ scope,
646
+ page: pageData.page,
647
+ dataSources,
648
+ resources
649
+ })
650
+ );
616
651
  }
617
- spinner.text = "Generating css file";
618
- const cssText = generateCssText(
619
- {
620
- assets: siteData.assets,
621
- breakpoints: siteData.build?.breakpoints,
622
- styles: siteData.build?.styles,
623
- styleSourceSelections: siteData.build?.styleSourceSelections,
624
- // pass only used metas to not generate unused preset styles
625
- componentMetas: projectMetas
626
- },
627
- {
628
- assetBaseUrl
629
- }
630
- );
631
- await ensureFileInPath(join4(generatedDir, "index.css"), cssText);
632
652
  await writeFile4(
633
653
  join4(generatedDir, "[sitemap.xml].ts"),
634
654
  `
@@ -788,7 +808,7 @@ Your project was successfully synced \u{1F389}`)));
788
808
  [
789
809
  "Now you can:",
790
810
  folderName && `Go to your project: ${pc2.dim(`cd ${folderName}`)}`,
791
- `Run ${pc2.dim("npm run dev")} to preview your site on a local server.`,
811
+ `Run ${pc2.dim("npm run dev")} to preview your project on a local server.`,
792
812
  projectTemplate && getDeploymentInstructions(projectTemplate)
793
813
  ].filter(Boolean).join("\n")
794
814
  );
@@ -802,8 +822,10 @@ var getDeploymentInstructions = (deployTarget) => {
802
822
  return [
803
823
  `To deploy to Netlify, run the following commands: `,
804
824
  `Run ${pc2.dim("npx netlify-cli login")} to login to Netlify.`,
805
- `Run ${pc2.dim("npx netlify-cli sites:create")} to create a new site.`,
806
- `Run ${pc2.dim("npx netlify-cli build")} to build the site`,
825
+ `Run ${pc2.dim(
826
+ "npx netlify-cli sites:create"
827
+ )} to create a new project.`,
828
+ `Run ${pc2.dim("npx netlify-cli build")} to build the project`,
807
829
  `Run ${pc2.dim("npx netlify-cli deploy")} to deploy on Netlify.`
808
830
  ].join("\n");
809
831
  }
@@ -815,7 +837,7 @@ import makeCLI from "yargs";
815
837
  // package.json
816
838
  var package_default = {
817
839
  name: "webstudio",
818
- version: "0.123.0",
840
+ version: "0.124.0",
819
841
  description: "Webstudio CLI",
820
842
  author: "Webstudio <github@webstudio.is>",
821
843
  homepage: "https://webstudio.is",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webstudio",
3
- "version": "0.123.0",
3
+ "version": "0.124.0",
4
4
  "description": "Webstudio CLI",
5
5
  "author": "Webstudio <github@webstudio.is>",
6
6
  "homepage": "https://webstudio.is",
@@ -28,21 +28,21 @@
28
28
  "title-case": "^4.1.0",
29
29
  "yargs": "^17.7.2",
30
30
  "zod": "^3.21.4",
31
- "@webstudio-is/http-client": "0.123.0",
32
- "@webstudio-is/sdk": "0.123.0",
33
- "@webstudio-is/image": "0.123.0",
34
- "@webstudio-is/react-sdk": "0.123.0",
35
- "@webstudio-is/sdk-components-react": "0.123.0",
36
- "@webstudio-is/sdk-components-react-radix": "0.123.0",
37
- "@webstudio-is/sdk-components-react-remix": "0.123.0"
31
+ "@webstudio-is/http-client": "0.124.0",
32
+ "@webstudio-is/image": "0.124.0",
33
+ "@webstudio-is/react-sdk": "0.124.0",
34
+ "@webstudio-is/sdk": "0.124.0",
35
+ "@webstudio-is/sdk-components-react-radix": "0.124.0",
36
+ "@webstudio-is/sdk-components-react-remix": "0.124.0",
37
+ "@webstudio-is/sdk-components-react": "0.124.0"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@types/node": "^18.17.1",
41
41
  "@types/prompts": "^2.4.5",
42
42
  "tsx": "^3.12.8",
43
43
  "typescript": "5.2.2",
44
- "@webstudio-is/form-handlers": "0.123.0",
45
- "@webstudio-is/tsconfig": "1.0.7"
44
+ "@webstudio-is/tsconfig": "1.0.7",
45
+ "@webstudio-is/form-handlers": "0.124.0"
46
46
  },
47
47
  "scripts": {
48
48
  "typecheck": "tsc",
@@ -1,7 +1,9 @@
1
- # This template uses this file instead of the typicial Netlify _redirects file.
1
+ # This template uses this file instead of the typicial Netlify \_redirects file.
2
+
2
3
  # For more information about redirects and rewrites, see https://docs.netlify.com/routing/redirects/.
3
4
 
4
- # Do not remove the line below. This is required to serve the site when deployed.
5
- /* /.netlify/functions/server 200
5
+ # Do not remove the line below. This is required to serve the project when deployed.
6
+
7
+ /\* /.netlify/functions/server 200
6
8
 
7
9
  # Add other redirects and rewrites here and/or in your netlify.toml
@@ -7,7 +7,8 @@ import {
7
7
  type LoaderArgs,
8
8
  json,
9
9
  } from "@remix-run/server-runtime";
10
- import type { Page as PageType, SiteMeta } from "@webstudio-is/sdk";
10
+ import { useLoaderData } from "@remix-run/react";
11
+ import type { Page as PageType, ProjectMeta } from "@webstudio-is/sdk";
11
12
  import { ReactSdkContext } from "@webstudio-is/react-sdk";
12
13
  import { n8nHandler, getFormId } from "@webstudio-is/form-handlers";
13
14
  import {
@@ -19,16 +20,21 @@ import {
19
20
  formsProperties,
20
21
  Page,
21
22
  imageAssets,
23
+ getRemixParams,
22
24
  } from "../__generated__/index";
25
+ import { loadResources } from "../__generated__/index.server";
23
26
  import css from "../__generated__/index.css";
24
27
  import { assetBaseUrl, imageBaseUrl, imageLoader } from "~/constants.mjs";
25
28
 
26
29
  export type PageData = {
27
- site?: SiteMeta;
30
+ project?: ProjectMeta;
28
31
  page: PageType;
29
32
  };
30
33
 
31
34
  export const loader = async (arg: LoaderArgs) => {
35
+ const params = getRemixParams(arg.params);
36
+ const resources = await loadResources({ params });
37
+
32
38
  const host =
33
39
  arg.request.headers.get("x-forwarded-host") ||
34
40
  arg.request.headers.get("host") ||
@@ -46,6 +52,8 @@ export const loader = async (arg: LoaderArgs) => {
46
52
  host,
47
53
  url: url.href,
48
54
  excludeFromSearch: arg.context.EXCLUDE_FROM_SEARCH,
55
+ params,
56
+ resources,
49
57
  },
50
58
  // No way for current information to change, so add cache for 10 minutes
51
59
  // In case of CRM Data, this should be set to 0
@@ -60,7 +68,7 @@ export const headers = () => {
60
68
  };
61
69
 
62
70
  export const meta: V2_ServerRuntimeMetaFunction<typeof loader> = ({ data }) => {
63
- const { page, site } = pageData;
71
+ const { page, project } = pageData;
64
72
 
65
73
  const metas: ReturnType<V2_ServerRuntimeMetaFunction> = [];
66
74
 
@@ -84,16 +92,16 @@ export const meta: V2_ServerRuntimeMetaFunction<typeof loader> = ({ data }) => {
84
92
 
85
93
  const origin = `https://${data?.host}`;
86
94
 
87
- if (site?.siteName) {
95
+ if (project?.siteName) {
88
96
  metas.push({
89
97
  property: "og:site_name",
90
- content: site.siteName,
98
+ content: project.siteName,
91
99
  });
92
100
  metas.push({
93
101
  "script:ld+json": {
94
102
  "@context": "https://schema.org",
95
103
  "@type": "WebSite",
96
- name: site.siteName,
104
+ name: project.siteName,
97
105
  url: origin,
98
106
  },
99
107
  });
@@ -152,11 +160,11 @@ export const links: LinksFunction = () => {
152
160
  href: css,
153
161
  });
154
162
 
155
- const { site } = pageData;
163
+ const { project } = pageData;
156
164
 
157
- if (site?.faviconAssetId) {
165
+ if (project?.faviconAssetId) {
158
166
  const imageAsset = imageAssets.find(
159
- (asset) => asset.id === site.faviconAssetId
167
+ (asset) => asset.id === project.faviconAssetId
160
168
  );
161
169
 
162
170
  if (imageAsset) {
@@ -282,6 +290,7 @@ export const action = async ({ request, context }: ActionArgs) => {
282
290
  };
283
291
 
284
292
  const Outlet = () => {
293
+ const { params, resources } = useLoaderData<typeof loader>();
285
294
  return (
286
295
  <ReactSdkContext.Provider
287
296
  value={{
@@ -291,7 +300,7 @@ const Outlet = () => {
291
300
  pagesPaths,
292
301
  }}
293
302
  >
294
- <Page />
303
+ <Page params={params} resources={resources} />
295
304
  </ReactSdkContext.Provider>
296
305
  );
297
306
  };