1
0
mirror of https://github.com/webstudio-is/webstudio.git synced 2025-03-15 09:45:09 +00:00

Add fixtures ()

## Description

See readme. Project created to be able to test/develop cli app.
Whats changed in cli
- [x] - preview flag added (to use preview env to sownload assets)
- [x] - package.json is now merged (deepmerge) when added to the repo

- Next PR
- [ ] - Flag like `"customConditions": ["source"],` could not work

## Steps for reproduction

1. click button
2. expect xyz

## Code Review

- [ ] hi @kof, I need you to do
  - conceptual review (architecture, feature-correctness)
  - detailed review (read every line)
  - test it on preview

## Before requesting a review

- [ ] made a self-review
- [ ] added inline comments where things may be not obvious (the "why",
not "what")

## Before merging

- [ ] tested locally and on preview environment (preview dev login:
5de6)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env.example`
and the `builder/env-check.js` if mandatory
This commit is contained in:
Ivan Starkov
2023-09-06 21:43:29 +03:00
committed by GitHub
parent dbbbf84c34
commit 08b0bfad5d
31 changed files with 2369 additions and 86 deletions

@ -0,0 +1,3 @@
{
"projectId": "cddc1d44-af37-4cb6-a430-d300cf6f932d"
}

@ -0,0 +1,536 @@
{
"build": {
"id": "d8e941cb-835b-4f1f-bf8b-4d546a2a67d8",
"projectId": "cddc1d44-af37-4cb6-a430-d300cf6f932d",
"version": 41,
"createdAt": "2023-09-06T11:37:11.556Z",
"pages": {
"homePage": {
"id": "7Db64ZXgYiRqKSQNR-qTQ",
"name": "Home",
"title": "Home",
"meta": {},
"rootInstanceId": "On9cvWCxr5rdZtY9O1Bv0",
"path": ""
},
"pages": []
},
"breakpoints": [
[
"UoTkWyaFuTYJihS3MFYK5",
{
"id": "UoTkWyaFuTYJihS3MFYK5",
"label": "Base"
}
],
[
"jnlRbFOGvyVBkD8nD2tmp",
{
"id": "jnlRbFOGvyVBkD8nD2tmp",
"label": "Tablet",
"maxWidth": 991
}
],
[
"MzzTm3ImEoIPYnDNKIxdq",
{
"id": "MzzTm3ImEoIPYnDNKIxdq",
"label": "Mobile landscape",
"maxWidth": 767
}
],
[
"e0fdu38A26zqOx-ZyQMP9",
{
"id": "e0fdu38A26zqOx-ZyQMP9",
"label": "Mobile portrait",
"maxWidth": 479
}
]
],
"styles": [
[
"y3sBN2gB0KCBXkheM6GMm:UoTkWyaFuTYJihS3MFYK5:fontSize:",
{
"breakpointId": "UoTkWyaFuTYJihS3MFYK5",
"styleSourceId": "y3sBN2gB0KCBXkheM6GMm",
"property": "fontSize",
"value": {
"type": "unit",
"unit": "em",
"value": 4
}
}
],
[
"NeVTA8c7vqOjhHotkd0Dv:UoTkWyaFuTYJihS3MFYK5:display:",
{
"breakpointId": "UoTkWyaFuTYJihS3MFYK5",
"styleSourceId": "NeVTA8c7vqOjhHotkd0Dv",
"property": "display",
"value": {
"type": "keyword",
"value": "flex"
}
}
],
[
"NeVTA8c7vqOjhHotkd0Dv:UoTkWyaFuTYJihS3MFYK5:justifyContent:",
{
"breakpointId": "UoTkWyaFuTYJihS3MFYK5",
"styleSourceId": "NeVTA8c7vqOjhHotkd0Dv",
"property": "justifyContent",
"value": {
"type": "keyword",
"value": "center"
}
}
],
[
"ureLSWiLGOYeWpki2JUeu:UoTkWyaFuTYJihS3MFYK5:minWidth:",
{
"breakpointId": "UoTkWyaFuTYJihS3MFYK5",
"styleSourceId": "ureLSWiLGOYeWpki2JUeu",
"property": "minWidth",
"value": {
"type": "unit",
"unit": "px",
"value": 0
}
}
],
[
"7HeiD-PCsn4VW6_fz5Skr:UoTkWyaFuTYJihS3MFYK5:minWidth:",
{
"breakpointId": "UoTkWyaFuTYJihS3MFYK5",
"styleSourceId": "7HeiD-PCsn4VW6_fz5Skr",
"property": "minWidth",
"value": {
"type": "unit",
"unit": "px",
"value": 0
}
}
],
[
"ureLSWiLGOYeWpki2JUeu:UoTkWyaFuTYJihS3MFYK5:flexGrow:",
{
"breakpointId": "UoTkWyaFuTYJihS3MFYK5",
"styleSourceId": "ureLSWiLGOYeWpki2JUeu",
"property": "flexGrow",
"value": {
"type": "unit",
"value": 1,
"unit": "number"
}
}
],
[
"ureLSWiLGOYeWpki2JUeu:UoTkWyaFuTYJihS3MFYK5:flexShrink:",
{
"breakpointId": "UoTkWyaFuTYJihS3MFYK5",
"styleSourceId": "ureLSWiLGOYeWpki2JUeu",
"property": "flexShrink",
"value": {
"type": "unit",
"value": 0,
"unit": "number"
}
}
],
[
"7HeiD-PCsn4VW6_fz5Skr:UoTkWyaFuTYJihS3MFYK5:flexGrow:",
{
"breakpointId": "UoTkWyaFuTYJihS3MFYK5",
"styleSourceId": "7HeiD-PCsn4VW6_fz5Skr",
"property": "flexGrow",
"value": {
"type": "unit",
"value": 1,
"unit": "number"
}
}
],
[
"7HeiD-PCsn4VW6_fz5Skr:UoTkWyaFuTYJihS3MFYK5:flexShrink:",
{
"breakpointId": "UoTkWyaFuTYJihS3MFYK5",
"styleSourceId": "7HeiD-PCsn4VW6_fz5Skr",
"property": "flexShrink",
"value": {
"type": "unit",
"value": 0,
"unit": "number"
}
}
],
[
"ureLSWiLGOYeWpki2JUeu:UoTkWyaFuTYJihS3MFYK5:flexBasis:",
{
"breakpointId": "UoTkWyaFuTYJihS3MFYK5",
"styleSourceId": "ureLSWiLGOYeWpki2JUeu",
"property": "flexBasis",
"value": {
"type": "unit",
"unit": "px",
"value": 0
}
}
],
[
"7HeiD-PCsn4VW6_fz5Skr:UoTkWyaFuTYJihS3MFYK5:flexBasis:",
{
"breakpointId": "UoTkWyaFuTYJihS3MFYK5",
"styleSourceId": "7HeiD-PCsn4VW6_fz5Skr",
"property": "flexBasis",
"value": {
"type": "unit",
"unit": "px",
"value": 0
}
}
],
[
"NeVTA8c7vqOjhHotkd0Dv:UoTkWyaFuTYJihS3MFYK5:alignItems:",
{
"breakpointId": "UoTkWyaFuTYJihS3MFYK5",
"styleSourceId": "NeVTA8c7vqOjhHotkd0Dv",
"property": "alignItems",
"value": {
"type": "keyword",
"value": "start"
}
}
],
[
"8VVhDFG7dmCfwcwD4DH8D:UoTkWyaFuTYJihS3MFYK5:aspectRatio:",
{
"breakpointId": "UoTkWyaFuTYJihS3MFYK5",
"styleSourceId": "8VVhDFG7dmCfwcwD4DH8D",
"property": "aspectRatio",
"value": {
"type": "unit",
"unit": "number",
"value": 1
}
}
],
[
"_t7PW0R2Naz9Zy7J1f8eQ:UoTkWyaFuTYJihS3MFYK5:paddingTop:",
{
"breakpointId": "UoTkWyaFuTYJihS3MFYK5",
"styleSourceId": "_t7PW0R2Naz9Zy7J1f8eQ",
"property": "paddingTop",
"value": {
"type": "unit",
"unit": "px",
"value": 16
}
}
],
[
"_t7PW0R2Naz9Zy7J1f8eQ:UoTkWyaFuTYJihS3MFYK5:paddingRight:",
{
"breakpointId": "UoTkWyaFuTYJihS3MFYK5",
"styleSourceId": "_t7PW0R2Naz9Zy7J1f8eQ",
"property": "paddingRight",
"value": {
"type": "unit",
"unit": "px",
"value": 16
}
}
],
[
"_t7PW0R2Naz9Zy7J1f8eQ:UoTkWyaFuTYJihS3MFYK5:paddingLeft:",
{
"breakpointId": "UoTkWyaFuTYJihS3MFYK5",
"styleSourceId": "_t7PW0R2Naz9Zy7J1f8eQ",
"property": "paddingLeft",
"value": {
"type": "unit",
"unit": "px",
"value": 16
}
}
],
[
"_t7PW0R2Naz9Zy7J1f8eQ:UoTkWyaFuTYJihS3MFYK5:paddingBottom:",
{
"breakpointId": "UoTkWyaFuTYJihS3MFYK5",
"styleSourceId": "_t7PW0R2Naz9Zy7J1f8eQ",
"property": "paddingBottom",
"value": {
"type": "unit",
"unit": "px",
"value": 16
}
}
]
],
"styleSources": [
[
"y3sBN2gB0KCBXkheM6GMm",
{
"type": "local",
"id": "y3sBN2gB0KCBXkheM6GMm"
}
],
[
"NeVTA8c7vqOjhHotkd0Dv",
{
"type": "local",
"id": "NeVTA8c7vqOjhHotkd0Dv"
}
],
[
"ureLSWiLGOYeWpki2JUeu",
{
"type": "local",
"id": "ureLSWiLGOYeWpki2JUeu"
}
],
[
"7HeiD-PCsn4VW6_fz5Skr",
{
"type": "local",
"id": "7HeiD-PCsn4VW6_fz5Skr"
}
],
[
"8VVhDFG7dmCfwcwD4DH8D",
{
"type": "local",
"id": "8VVhDFG7dmCfwcwD4DH8D"
}
],
[
"_t7PW0R2Naz9Zy7J1f8eQ",
{
"type": "local",
"id": "_t7PW0R2Naz9Zy7J1f8eQ"
}
]
],
"styleSourceSelections": [
[
"nVMWvMsaLCcb0o1wuNQgg",
{
"instanceId": "nVMWvMsaLCcb0o1wuNQgg",
"values": ["y3sBN2gB0KCBXkheM6GMm"]
}
],
[
"f0kF-WmL7DQg7MSyRvqY1",
{
"instanceId": "f0kF-WmL7DQg7MSyRvqY1",
"values": ["NeVTA8c7vqOjhHotkd0Dv"]
}
],
[
"5XDbqPrZDeCwq4YJ3CHsc",
{
"instanceId": "5XDbqPrZDeCwq4YJ3CHsc",
"values": ["ureLSWiLGOYeWpki2JUeu"]
}
],
[
"qPnkiFGDj8dITWb1kmpGl",
{
"instanceId": "qPnkiFGDj8dITWb1kmpGl",
"values": ["7HeiD-PCsn4VW6_fz5Skr"]
}
],
[
"pX1ovPI7NdC0HRjkw6Kpw",
{
"instanceId": "pX1ovPI7NdC0HRjkw6Kpw",
"values": ["8VVhDFG7dmCfwcwD4DH8D"]
}
],
[
"On9cvWCxr5rdZtY9O1Bv0",
{
"instanceId": "On9cvWCxr5rdZtY9O1Bv0",
"values": ["_t7PW0R2Naz9Zy7J1f8eQ"]
}
]
],
"props": [
[
"rTRZFZEd03RBH4gUWj9LW",
{
"id": "rTRZFZEd03RBH4gUWj9LW",
"instanceId": "pX1ovPI7NdC0HRjkw6Kpw",
"name": "src",
"type": "asset",
"value": "cd939c56-bcdd-4e64-bd9c-567a9bccd3da"
}
]
],
"dataSources": [],
"instances": [
[
"On9cvWCxr5rdZtY9O1Bv0",
{
"type": "instance",
"id": "On9cvWCxr5rdZtY9O1Bv0",
"component": "Body",
"children": [
{
"type": "id",
"value": "nVMWvMsaLCcb0o1wuNQgg"
},
{
"type": "id",
"value": "f0kF-WmL7DQg7MSyRvqY1"
}
]
}
],
[
"nVMWvMsaLCcb0o1wuNQgg",
{
"type": "instance",
"id": "nVMWvMsaLCcb0o1wuNQgg",
"component": "Heading",
"children": [
{
"type": "text",
"value": "DO NOT TOUCH THIS PROJECT, IT'S USED FOR FIXTURES"
}
]
}
],
[
"f0kF-WmL7DQg7MSyRvqY1",
{
"type": "instance",
"id": "f0kF-WmL7DQg7MSyRvqY1",
"component": "Box",
"children": [
{
"type": "id",
"value": "5XDbqPrZDeCwq4YJ3CHsc"
},
{
"type": "id",
"value": "qPnkiFGDj8dITWb1kmpGl"
}
]
}
],
[
"5XDbqPrZDeCwq4YJ3CHsc",
{
"type": "instance",
"id": "5XDbqPrZDeCwq4YJ3CHsc",
"component": "Box",
"children": [
{
"type": "id",
"value": "oLXYe1UQiVMhVnZGvJSMr"
},
{
"type": "id",
"value": "p34JHWcU6UNrd9FVnY80Q"
}
]
}
],
[
"qPnkiFGDj8dITWb1kmpGl",
{
"type": "instance",
"id": "qPnkiFGDj8dITWb1kmpGl",
"component": "Box",
"children": [
{
"type": "id",
"value": "pX1ovPI7NdC0HRjkw6Kpw"
}
]
}
],
[
"oLXYe1UQiVMhVnZGvJSMr",
{
"type": "instance",
"id": "oLXYe1UQiVMhVnZGvJSMr",
"component": "Heading",
"children": [
{
"type": "text",
"value": "Heading"
}
]
}
],
[
"p34JHWcU6UNrd9FVnY80Q",
{
"type": "instance",
"id": "p34JHWcU6UNrd9FVnY80Q",
"component": "Paragraph",
"children": [
{
"type": "text",
"value": "a little kitten painted in black and white gouache with a thick brush"
}
]
}
],
[
"pX1ovPI7NdC0HRjkw6Kpw",
{
"type": "instance",
"id": "pX1ovPI7NdC0HRjkw6Kpw",
"component": "Image",
"children": []
}
]
],
"deployment": {
"domains": [],
"projectDomain": "webstudio-fixture-project-a-0su3o"
}
},
"page": {
"id": "7Db64ZXgYiRqKSQNR-qTQ",
"name": "Home",
"title": "Home",
"meta": {},
"rootInstanceId": "On9cvWCxr5rdZtY9O1Bv0",
"path": ""
},
"pages": [
{
"id": "7Db64ZXgYiRqKSQNR-qTQ",
"name": "Home",
"title": "Home",
"meta": {},
"rootInstanceId": "On9cvWCxr5rdZtY9O1Bv0",
"path": ""
}
],
"assets": [
{
"id": "cd939c56-bcdd-4e64-bd9c-567a9bccd3da",
"name": "_937084ed-a798-49fe-8664-df93a2af605e_uiBk3o6UWdqolyakMvQJ9.jpeg",
"description": null,
"projectId": "cddc1d44-af37-4cb6-a430-d300cf6f932d",
"size": 210614,
"type": "image",
"format": "jpeg",
"createdAt": "2023-09-06T11:28:43.031Z",
"meta": {
"width": 1024,
"height": 1024
}
}
],
"user": {
"email": "hello@webstudio.is"
},
"projectDomain": "webstudio-fixture-project-a-0su3o"
}

@ -0,0 +1,21 @@
# Fixture to test/play with @webstudio/cli
## How to develop
```bash
# Terminal 1
cd packages/webstudio-cli
pnpm dev
```
```bash
# Terminal 2
pnpm webstudio link
# add following link https://webstudio-builder-git-main-webstudio-is.vercel.app/builder/cddc1d44-af37-4cb6-a430-d300cf6f932d?authToken=1cdc6026-dd5b-4624-b89b-9bd45e9bcc3d&mode=preview
pnpm webstudio sync
# data.json generated
pnpm webstudio build --preview && pnpm prettier --write ./app/
# exec `pnpm run dev` to see result
```

@ -0,0 +1,231 @@
/* eslint-disable */
/* This is a auto generated file for building the project */
import * as sdk from "@webstudio-is/react-sdk";
import type { PageData } from "~/routes/_index";
import type { Components } from "@webstudio-is/react-sdk";
import type { Asset } from "@webstudio-is/sdk";
import {
Body as Body_0,
Heading as Heading_0,
Box as Box_0,
Paragraph as Paragraph_0,
Image as Image_0,
} from "@webstudio-is/sdk-components-react";
import * as remixComponents from "@webstudio-is/sdk-components-react-remix";
export const components = new Map(
Object.entries(
Object.assign(
{
Body: Body_0,
Heading: Heading_0,
Box: Box_0,
Paragraph: Paragraph_0,
Image: Image_0,
},
remixComponents
)
)
) as Components;
export const fontAssets: Asset[] = [];
export const pageData: PageData = {
build: {
props: [
[
"rTRZFZEd03RBH4gUWj9LW",
{
id: "rTRZFZEd03RBH4gUWj9LW",
instanceId: "pX1ovPI7NdC0HRjkw6Kpw",
name: "src",
type: "asset",
value: "cd939c56-bcdd-4e64-bd9c-567a9bccd3da",
},
],
],
instances: [
[
"On9cvWCxr5rdZtY9O1Bv0",
{
type: "instance",
id: "On9cvWCxr5rdZtY9O1Bv0",
component: "Body",
children: [
{ type: "id", value: "nVMWvMsaLCcb0o1wuNQgg" },
{ type: "id", value: "f0kF-WmL7DQg7MSyRvqY1" },
],
},
],
[
"nVMWvMsaLCcb0o1wuNQgg",
{
type: "instance",
id: "nVMWvMsaLCcb0o1wuNQgg",
component: "Heading",
children: [
{
type: "text",
value: "DO NOT TOUCH THIS PROJECT, IT'S USED FOR FIXTURES",
},
],
},
],
[
"f0kF-WmL7DQg7MSyRvqY1",
{
type: "instance",
id: "f0kF-WmL7DQg7MSyRvqY1",
component: "Box",
children: [
{ type: "id", value: "5XDbqPrZDeCwq4YJ3CHsc" },
{ type: "id", value: "qPnkiFGDj8dITWb1kmpGl" },
],
},
],
[
"5XDbqPrZDeCwq4YJ3CHsc",
{
type: "instance",
id: "5XDbqPrZDeCwq4YJ3CHsc",
component: "Box",
children: [
{ type: "id", value: "oLXYe1UQiVMhVnZGvJSMr" },
{ type: "id", value: "p34JHWcU6UNrd9FVnY80Q" },
],
},
],
[
"qPnkiFGDj8dITWb1kmpGl",
{
type: "instance",
id: "qPnkiFGDj8dITWb1kmpGl",
component: "Box",
children: [{ type: "id", value: "pX1ovPI7NdC0HRjkw6Kpw" }],
},
],
[
"oLXYe1UQiVMhVnZGvJSMr",
{
type: "instance",
id: "oLXYe1UQiVMhVnZGvJSMr",
component: "Heading",
children: [{ type: "text", value: "Heading" }],
},
],
[
"p34JHWcU6UNrd9FVnY80Q",
{
type: "instance",
id: "p34JHWcU6UNrd9FVnY80Q",
component: "Paragraph",
children: [
{
type: "text",
value:
"a little kitten painted in black and white gouache with a thick brush",
},
],
},
],
[
"pX1ovPI7NdC0HRjkw6Kpw",
{
type: "instance",
id: "pX1ovPI7NdC0HRjkw6Kpw",
component: "Image",
children: [],
},
],
],
dataSources: [],
},
pages: [
{
id: "7Db64ZXgYiRqKSQNR-qTQ",
name: "Home",
title: "Home",
meta: {},
rootInstanceId: "On9cvWCxr5rdZtY9O1Bv0",
path: "",
},
],
page: {
id: "7Db64ZXgYiRqKSQNR-qTQ",
name: "Home",
title: "Home",
meta: {},
rootInstanceId: "On9cvWCxr5rdZtY9O1Bv0",
path: "",
},
assets: [
{
id: "cd939c56-bcdd-4e64-bd9c-567a9bccd3da",
name: "_937084ed-a798-49fe-8664-df93a2af605e_uiBk3o6UWdqolyakMvQJ9.jpeg",
description: null,
projectId: "cddc1d44-af37-4cb6-a430-d300cf6f932d",
size: 210614,
type: "image",
format: "jpeg",
createdAt: "2023-09-06T11:28:43.031Z",
meta: { width: 1024, height: 1024 },
},
],
};
export const user: { email: string | null } | undefined = {
email: "hello@webstudio.is",
};
export const projectId = "cddc1d44-af37-4cb6-a430-d300cf6f932d";
/* eslint-disable */
const indexesWithinAncestors = new Map<string, number>([]);
const rawExecuteComputingExpressions = (
_variables: Map<string, unknown>
): Map<string, unknown> => {
return new Map([]);
};
const executeComputingExpressions = (variables: Map<string, unknown>) => {
const encodedvariables = sdk.encodeVariablesMap(variables);
const encodedResult = rawExecuteComputingExpressions(encodedvariables);
return sdk.decodeVariablesMap(encodedResult);
};
const generatedEffectfulExpressions = new Map<
string,
(args: Map<string, any>, variables: Map<string, any>) => Map<string, unknown>
>([]);
const rawExecuteEffectfulExpression = (
code: string,
args: Map<string, unknown>,
variables: Map<string, unknown>
): Map<string, unknown> => {
if (generatedEffectfulExpressions.has(code)) {
return generatedEffectfulExpressions.get(code)!(args, variables);
}
console.error("Effectful expression not found", code);
throw new Error("Effectful expression not found");
};
const executeEffectfulExpression = (
code: string,
args: Map<string, unknown>,
variables: Map<string, unknown>
) => {
const encodedvariables = sdk.encodeVariablesMap(variables);
const encodedResult = rawExecuteEffectfulExpression(
code,
args,
encodedvariables
);
return sdk.decodeVariablesMap(encodedResult);
};
export const utils = {
indexesWithinAncestors,
executeComputingExpressions,
executeEffectfulExpression,
};
/* eslint-enable */

File diff suppressed because it is too large Load Diff

@ -0,0 +1 @@
export { Root as default } from "@webstudio-is/react-sdk";

@ -0,0 +1,185 @@
/* eslint-disable camelcase */
import {
V2_MetaFunction,
LinksFunction,
LinkDescriptor,
ActionArgs,
json,
} from "@remix-run/node";
import {
InstanceRoot,
type RootPropsData,
type Params,
} from "@webstudio-is/react-sdk";
import { n8nHandler, getFormProperties } from "@webstudio-is/form-handlers";
import { Scripts, ScrollRestoration } from "@remix-run/react";
import {
fontAssets,
components,
pageData,
user,
projectId,
utils,
} from "../__generated__/_index.tsx";
import css from "../__generated__/index.css";
import type { Data } from "@webstudio-is/http-client";
export type PageData = Omit<Data, "build"> & {
build: Pick<Data["build"], "props" | "instances" | "dataSources">;
};
export const meta: V2_MetaFunction = () => {
const { page } = pageData;
return [{ title: page?.title || "Webstudio", ...page?.meta }];
};
export const links: LinksFunction = () => {
const result: LinkDescriptor[] = [];
result.push({
rel: "stylesheet",
href: css,
});
for (const asset of fontAssets) {
if (asset.type === "font") {
result.push({
rel: "preload",
href: "/assets/" + asset.name,
as: "font",
crossOrigin: "anonymous",
// @todo add mimeType
// type: asset.mimeType,
});
}
}
return result;
};
const getRequestHost = (request: Request): string =>
request.headers.get("x-forwarded-host") || request.headers.get("host") || "";
const getMethod = (value: string | undefined) => {
if (value === undefined) {
return "post";
}
switch (value.toLowerCase()) {
case "get":
return "get";
default:
return "post";
}
};
export const action = async ({ request, context }: ActionArgs) => {
const formData = await request.formData();
const formProperties = getFormProperties(
formData,
pageData.build.instances,
pageData.build.props
);
if (formProperties === undefined) {
// We're throwing rather than returning { success: false }
// because this isn't supposed to happen normally: bug or malicious user
throw json("Form not found", { status: 404 });
}
const { action, method } = formProperties;
const email = user?.email;
if (email == null) {
return { success: false };
}
// wrapped in try/catch just in cases new URL() throws
// (should not happen)
let pageUrl: URL;
try {
pageUrl = new URL(request.url);
pageUrl.host = getRequestHost(request);
} catch {
return { success: false };
}
if (action !== undefined) {
try {
// Test that action is full URL
new URL(action);
} catch {
return json(
{
success: false,
error: "Invalid action URL, must be valid http/https protocol",
},
{ status: 200 }
);
}
}
const formInfo = {
formData,
projectId,
action: action ?? null,
method: getMethod(method),
pageUrl: pageUrl.toString(),
toEmail: email,
fromEmail: pageUrl.hostname + "@webstudio.email",
} as const;
const result = await n8nHandler({
formInfo,
hookUrl: context.N8N_FORM_EMAIL_HOOK as string,
});
return result;
};
const Outlet = () => {
const pagesCanvasData: PageData = pageData;
const page = pagesCanvasData.page;
if (page === undefined) {
throw json("Page not found", {
status: 404,
});
}
const assetBaseUrl = "/assets/";
const imageBaseUrl = "/assets/";
const params: Params = {
assetBaseUrl,
imageBaseUrl,
};
const data: RootPropsData = {
build: pagesCanvasData.build,
assets: pagesCanvasData.assets,
page,
pages: pagesCanvasData.pages,
params,
};
return (
<InstanceRoot
data={data}
components={components}
utils={utils}
scripts={
<>
<Scripts />
<ScrollRestoration />
</>
}
/>
);
};
export default Outlet;

@ -0,0 +1,44 @@
{
"private": true,
"sideEffects": false,
"scripts": {
"build": "remix build",
"dev": "remix dev",
"start": "remix-serve build",
"typecheck": "tsc",
"checks": "pnpm typecheck"
},
"dependencies": {
"@remix-run/node": "^1.19.2",
"@remix-run/react": "^1.19.2",
"@webstudio-is/react-sdk": "workspace:^",
"@webstudio-is/sdk-components-react-radix": "workspace:^",
"@webstudio-is/sdk-components-react-remix": "workspace:^",
"@webstudio-is/sdk-components-react": "workspace:^",
"@webstudio-is/form-handlers": "workspace:^",
"@webstudio-is/sdk": "workspace:^",
"isbot": "^3.6.8",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@remix-run/serve": "^1.19.2",
"@remix-run/dev": "^1.19.2",
"@types/react": "^18.2.20",
"@types/react-dom": "^18.2.7",
"@webstudio-is/http-client": "workspace:^",
"eslint": "^8.48.0",
"typescript": "5.2.2",
"@webstudio-is/cli": "workspace:^"
},
"engines": {
"node": ">=18.0.0"
},
"name": "webstudio-remix-vercel",
"version": "0.0.1",
"description": "",
"main": "index.js",
"keywords": [],
"author": "",
"license": "AGPL-3.0-or-later"
}

Binary file not shown.

After

Width: 48px  |  Height: 48px  |  Size: 15 KiB

@ -0,0 +1,18 @@
/** @type {import('@remix-run/dev').AppConfig} */
module.exports = {
ignoredRouteFiles: ["**/.*"],
serverModuleFormat: "cjs",
serverDependenciesToBundle: [
/@webstudio-is\/(?!prisma-client)/,
"nanoevents",
"nanostores",
"@nanostores/react",
],
future: {
v2_errorBoundary: true,
v2_headers: true,
v2_meta: true,
v2_normalizeFormMethod: true,
v2_routeConvention: true,
},
};

@ -0,0 +1,2 @@
/// <reference types="@remix-run/dev" />
/// <reference types="@remix-run/node" />

@ -0,0 +1,25 @@
{
"include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
"compilerOptions": {
"lib": ["DOM", "DOM.Iterable", "ES2022"],
"isolatedModules": true,
"esModuleInterop": true,
"jsx": "react-jsx",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"target": "ES2022",
"strict": true,
"allowJs": true,
"forceConsistentCasingInFileNames": true,
"allowImportingTsExtensions": true,
"baseUrl": ".",
"paths": {
"~/*": ["./app/*"]
},
"customConditions": ["source"],
// Remix takes care of building everything in `remix build`.
"noEmit": true,
"skipLibCheck": true
}
}

@ -18,9 +18,10 @@
"scripts": {
"typecheck": "tsc",
"checks": "pnpm typecheck",
"build:templates": "tsx ./templates/build.ts",
"build:templates": "tsx ./templates/build.ts && prettier --write src/__generated__",
"build": "rm -rf ./lib && esbuild ./src/**/*.ts --outdir=./lib",
"local-run": "tsx --no-warnings ./src/bin.ts"
"local-run": "tsx --no-warnings ./src/bin.ts",
"dev": "esbuild ./src/**/*.ts --watch --outdir=./lib"
},
"license": "AGPL-3.0-or-later",
"dependencies": {
@ -31,6 +32,7 @@
"@webstudio-is/sdk-components-react": "workspace:^",
"@webstudio-is/sdk-components-react-radix": "workspace:^",
"@webstudio-is/sdk-components-react-remix": "workspace:^",
"deepmerge": "^4.3.1",
"env-paths": "^3.0.0",
"ora": "^7.0.1",
"p-limit": "^4.0.0",

File diff suppressed because one or more lines are too long

@ -8,7 +8,8 @@ If needed to make any changes. Add them to ./templates folder and run pnpm run b
import { ASSETS_BASE } from "../config";
export const getRouteTemplate = () => {
return `import {
return `/* eslint-disable camelcase */
import {
V2_MetaFunction,
LinksFunction,
LinkDescriptor,
@ -19,9 +20,9 @@ export const getRouteTemplate = () => {
import {
InstanceRoot,
type RootPropsData,
type Data,
type Params,
} from "@webstudio-is/react-sdk";
import { n8nHandler, hasMatchingForm } from "@webstudio-is/form-handlers";
import { n8nHandler, getFormProperties } from "@webstudio-is/form-handlers";
import { Scripts, ScrollRestoration } from "@remix-run/react";
import {
fontAssets,
@ -32,6 +33,7 @@ import {
utils,
} from "../__generated__/index";
import css from "../__generated__/index.css";
import type { Data } from "@webstudio-is/http-client";
export type PageData = Omit<Data, "build"> & {
build: Pick<Data["build"], "props" | "instances" | "dataSources">;
@ -69,22 +71,43 @@ export const links: LinksFunction = () => {
const getRequestHost = (request: Request): string =>
request.headers.get("x-forwarded-host") || request.headers.get("host") || "";
const getMethod = (value: string | undefined) => {
if (value === undefined) {
return "post";
}
switch (value.toLowerCase()) {
case "get":
return "get";
default:
return "post";
}
};
export const action = async ({ request, context }: ActionArgs) => {
const formData = await request.formData();
// We're throwing rather than returning \`{ success: false }\`
// because this isn't supposed to happen normally: bug or malicious user
if (hasMatchingForm(formData, pageData.build.instances) === false) {
const formProperties = getFormProperties(
formData,
pageData.build.instances,
pageData.build.props
);
if (formProperties === undefined) {
// We're throwing rather than returning { success: false }
// because this isn't supposed to happen normally: bug or malicious user
throw json("Form not found", { status: 404 });
}
const { action, method } = formProperties;
const email = user?.email;
if (email == null) {
return { success: false };
}
// wrapped in try/catch just in cases \`new URL()\` throws
// wrapped in try/catch just in cases new URL() throws
// (should not happen)
let pageUrl: URL;
try {
@ -94,13 +117,30 @@ export const action = async ({ request, context }: ActionArgs) => {
return { success: false };
}
if (action !== undefined) {
try {
// Test that action is full URL
new URL(action);
} catch {
return json(
{
success: false,
error: "Invalid action URL, must be valid http/https protocol",
},
{ status: 200 }
);
}
}
const formInfo = {
formData,
projectId,
action: action ?? null,
method: getMethod(method),
pageUrl: pageUrl.toString(),
toEmail: email,
fromEmail: pageUrl.hostname + "@webstudio.email",
};
} as const;
const result = await n8nHandler({
formInfo,
@ -124,7 +164,7 @@ const Outlet = () => {
const assetBaseUrl = "${ASSETS_BASE}";
const imageBaseUrl = "${ASSETS_BASE}";
const params: Data["params"] = {
const params: Params = {
assetBaseUrl,
imageBaseUrl,
};

@ -14,14 +14,30 @@ export const templates: Record<ProjectTarget, Folder> = {
{
name: "package.json",
content:
'{\n "private": true,\n "sideEffects": false,\n "scripts": {\n "build": "remix build",\n "dev": "remix dev",\n "start": "remix-serve build",\n "typecheck": "tsc"\n },\n "dependencies": {\n "@remix-run/css-bundle": "^1.19.2",\n "@remix-run/node": "^1.19.2",\n "@remix-run/react": "^1.19.2",\n "@webstudio-is/react-sdk": "^0.91.0",\n "@webstudio-is/sdk-components-react-radix": "^0.91.0",\n "@webstudio-is/sdk-components-react-remix": "^0.91.0",\n "@webstudio-is/sdk-components-react": "^0.91.0",\n "@webstudio-is/form-handlers": "^0.91.0",\n "isbot": "^3.6.8",\n "react": "^18.2.0",\n "react-dom": "^18.2.0"\n },\n "devDependencies": {\n "@remix-run/serve": "^1.19.2",\n "@remix-run/dev": "^1.19.2",\n "@remix-run/eslint-config": "^1.19.2",\n "@types/react": "^18.0.35",\n "@types/react-dom": "^18.0.11",\n "eslint": "^8.38.0",\n "typescript": "^5.0.4"\n },\n "engines": {\n "node": ">=18.0.0"\n }\n}\n',
'{\n "private": true,\n "sideEffects": false,\n "scripts": {\n "build": "remix build",\n "dev": "remix dev",\n "start": "remix-serve build",\n "typecheck": "tsc"\n },\n "dependencies": {\n "@remix-run/node": "^1.19.2",\n "@remix-run/react": "^1.19.2",\n "@webstudio-is/react-sdk": "^0.91.0",\n "@webstudio-is/sdk-components-react-radix": "^0.91.0",\n "@webstudio-is/sdk-components-react-remix": "^0.91.0",\n "@webstudio-is/sdk-components-react": "^0.91.0",\n "@webstudio-is/form-handlers": "^0.91.0",\n "@webstudio-is/sdk": "^0.91.0",\n "isbot": "^3.6.8",\n "react": "^18.2.0",\n "react-dom": "^18.2.0"\n },\n "devDependencies": {\n "@remix-run/serve": "^1.19.2",\n "@remix-run/dev": "^1.19.2",\n "@types/react": "^18.2.20",\n "@types/react-dom": "^18.2.7",\n "@webstudio-is/http-client": "^0.91.0",\n "eslint": "^8.48.0",\n "typescript": "5.2.2"\n },\n "engines": {\n "node": ">=18.0.0"\n }\n}\n',
encoding: "utf-8",
merge: true,
},
{
name: "remix.config.js",
content:
'/** @type {import(\'@remix-run/dev\').AppConfig} */\nmodule.exports = {\n ignoredRouteFiles: ["**/.*"],\n serverModuleFormat: "cjs",\n serverDependenciesToBundle: [\n /@webstudio-is\\/(?!prisma-client)/,\n "nanoevents",\n "nanostores",\n "@nanostores/react",\n ],\n future: {\n v2_errorBoundary: true,\n v2_headers: true,\n v2_meta: true,\n v2_normalizeFormMethod: true,\n v2_routeConvention: true,\n },\n};\n',
encoding: "utf-8",
merge: false,
},
{
name: "remix.env.d.ts",
content:
'/// <reference types="@remix-run/dev" />\n/// <reference types="@remix-run/node" />\n',
encoding: "utf-8",
merge: false,
},
{
name: "tsconfig.json",
content:
'{\n "include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],\n "compilerOptions": {\n "lib": ["DOM", "DOM.Iterable", "ES2022"],\n "isolatedModules": true,\n "esModuleInterop": true,\n "jsx": "react-jsx",\n "moduleResolution": "bundler",\n "resolveJsonModule": true,\n "target": "ES2022",\n "strict": true,\n "allowJs": true,\n "forceConsistentCasingInFileNames": true,\n "allowImportingTsExtensions": true,\n "baseUrl": ".",\n "paths": {\n "~/*": ["./app/*"]\n },\n "customConditions": ["source"],\n\n // Remix takes care of building everything in `remix build`.\n "noEmit": true,\n "skipLibCheck": true\n }\n}\n',
encoding: "utf-8",
merge: false,
},
],
subFolders: [
@ -33,6 +49,7 @@ export const templates: Record<ProjectTarget, Folder> = {
content:
'export { Root as default } from "@webstudio-is/react-sdk";\n',
encoding: "utf-8",
merge: false,
},
],
subFolders: [],

@ -2,6 +2,7 @@ export type File = {
name: string;
content: string;
encoding: "utf-8" | "base64";
merge: boolean;
};
export type Folder = {

@ -51,7 +51,7 @@ export const main = async () => {
link
);
cmd.command(["sync"], "sync your project", {}, sync);
cmd.command("$0", "setup the project", {}, initFlow);
cmd.command("$0", "setup the project", buildOptions, initFlow);
await cmd.parse();
} catch (error) {

@ -7,17 +7,21 @@ import type {
} from "./yargs-types";
export const buildOptions = (yargs: CommonYargsArgv) =>
yargs.option("assets", {
type: "boolean",
default: true,
describe: "Download assets",
});
yargs
.option("assets", {
type: "boolean",
default: true,
describe: "Download assets",
})
.option("preview", {
type: "boolean",
default: false,
describe: "use preview (opensource) version of the project",
});
// @todo: use options.assets to define if we need to download assets
export const build = async (
options:
| StrictYargsOptionsToInterface<typeof buildOptions>
| { assets?: boolean }
options: StrictYargsOptionsToInterface<typeof buildOptions>
) => {
try {
await access(LOCAL_DATA_FILE);
@ -31,5 +35,5 @@ export const build = async (
throw error;
}
await prebuild();
await prebuild(options);
};

@ -4,9 +4,12 @@ import { chdir, cwd } from "node:process";
import { join } from "node:path";
import { link } from "./link";
import { sync } from "./sync";
import { build } from "./build";
import { build, buildOptions } from "./build";
import type { StrictYargsOptionsToInterface } from "./yargs-types";
export const initFlow = async () => {
export const initFlow = async (
options: StrictYargsOptionsToInterface<typeof buildOptions>
) => {
const isProjectConfigured = await isFileExists(".webstudio/config.json");
const prompsList: PromptObject[] = [];
@ -46,5 +49,5 @@ export const initFlow = async () => {
If the project is already set up, we can sync and build it.
*/
await sync();
await build({ assets: true });
await build(options);
};

@ -38,7 +38,7 @@ export const sync = async () => {
const { host, token } = globalConfig[localConfig.projectId];
spinner.text = "Loading project data from webstudio";
spinner.text = "Loading project data from webstudio\n";
const project = await loadProjectDataById({
projectId: localConfig.projectId,
authToken: token,

@ -8,6 +8,7 @@ import {
} from "node:fs/promises";
import { join } from "node:path";
import type { Folder } from "./args";
import merge from "deepmerge";
export const isFileExists = async (filePath: string) => {
try {
@ -54,7 +55,24 @@ export const parseFolderAndWriteFiles = async (
for (const file of folder.files) {
const filePath = join(path, file.name);
await ensureFileInPath(filePath);
await writeFile(filePath, file.content, file.encoding);
let content = file.content;
if (file.merge) {
let existingContent = await readFile(filePath, "utf8");
if (existingContent === "") {
existingContent = "{}";
}
content = JSON.stringify(
merge(JSON.parse(file.content), JSON.parse(existingContent)),
null,
" "
);
}
await writeFile(filePath, content, file.encoding);
}
for (const subFolder of folder.subFolders) {

@ -101,7 +101,16 @@ export const downloadAsset = async (
}
};
export const prebuild = async () => {
export const prebuild = async (options: {
/**
* Use preview (opensource) version of the project
**/
preview: boolean;
/**
* Do we need download assets
**/
assets: boolean;
}) => {
const spinner = ora("Scaffolding the project files");
spinner.start();
@ -221,7 +230,9 @@ export const prebuild = async () => {
const assetsToDownload: Promise<void>[] = [];
const fontAssets: FontAsset[] = [];
const assetBuildUrl = `https://${domain}.wstd.io/cgi/asset/`;
const appDomain = options.preview ? "wstd.work" : "wstd.io";
const assetBuildUrl = `https://${domain}.${appDomain}/cgi/asset/`;
for (const asset of siteData.assets) {
if (asset.type === "image") {
@ -329,16 +340,16 @@ import { ${Array.from(componentsSet)
dataSources: new Map(pageData.build.dataSources),
});
const pageExports = `/* eslint-disable camelcase */
/* eslint-disable prefer-const */
const pageExports = `/* eslint-disable */
/* This is a auto generated file for building the project */ \n
import * as sdk from "@webstudio-is/react-sdk";
import type { PageData } from "~/routes/template";
import type { PageData } from "~/routes/_index";
import type { Components } from "@webstudio-is/react-sdk";
import type { Asset } from "@webstudio-is/sdk";
${componentImports}
import * as remixComponents from "@webstudio-is/sdk-components-react-remix";
export const components = new Map(Object.entries(Object.assign({ ${assignComponent} }, remixComponents ))) as Components;
export const fontAssets = ${JSON.stringify(fontAssets)}
export const fontAssets: Asset[] = ${JSON.stringify(fontAssets)}
export const pageData: PageData = ${JSON.stringify(pageData)};
export const user: { email: string | null } | undefined = ${JSON.stringify(
siteData.user

@ -59,10 +59,16 @@ const parseFolder = (folderPath: string): Folder | undefined => {
if (isFile) {
const content = readFileSync(filePath, "utf-8");
let merge = false;
if (file === "package.json") {
merge = true;
}
folder.files.push({
name: file,
content,
encoding: "utf-8",
merge,
});
}
}
@ -155,6 +161,7 @@ const parseAssets = (folderPath: string): Folder | undefined => {
name: file,
content,
encoding: "base64",
merge: false,
});
}
}

@ -8,7 +8,6 @@
"typecheck": "tsc"
},
"dependencies": {
"@remix-run/css-bundle": "^1.19.2",
"@remix-run/node": "^1.19.2",
"@remix-run/react": "^1.19.2",
"@webstudio-is/react-sdk": "^0.91.0",
@ -16,6 +15,7 @@
"@webstudio-is/sdk-components-react-remix": "^0.91.0",
"@webstudio-is/sdk-components-react": "^0.91.0",
"@webstudio-is/form-handlers": "^0.91.0",
"@webstudio-is/sdk": "^0.91.0",
"isbot": "^3.6.8",
"react": "^18.2.0",
"react-dom": "^18.2.0"
@ -23,11 +23,11 @@
"devDependencies": {
"@remix-run/serve": "^1.19.2",
"@remix-run/dev": "^1.19.2",
"@remix-run/eslint-config": "^1.19.2",
"@types/react": "^18.0.35",
"@types/react-dom": "^18.0.11",
"eslint": "^8.38.0",
"typescript": "^5.0.4"
"@types/react": "^18.2.20",
"@types/react-dom": "^18.2.7",
"@webstudio-is/http-client": "^0.91.0",
"eslint": "^8.48.0",
"typescript": "5.2.2"
},
"engines": {
"node": ">=18.0.0"

@ -0,0 +1,2 @@
/// <reference types="@remix-run/dev" />
/// <reference types="@remix-run/node" />

@ -0,0 +1,25 @@
{
"include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
"compilerOptions": {
"lib": ["DOM", "DOM.Iterable", "ES2022"],
"isolatedModules": true,
"esModuleInterop": true,
"jsx": "react-jsx",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"target": "ES2022",
"strict": true,
"allowJs": true,
"forceConsistentCasingInFileNames": true,
"allowImportingTsExtensions": true,
"baseUrl": ".",
"paths": {
"~/*": ["./app/*"]
},
"customConditions": ["source"],
// Remix takes care of building everything in `remix build`.
"noEmit": true,
"skipLibCheck": true
}
}

@ -1,3 +1,4 @@
/* eslint-disable camelcase */
import {
V2_MetaFunction,
LinksFunction,
@ -9,9 +10,9 @@ import {
import {
InstanceRoot,
type RootPropsData,
type Data,
type Params,
} from "@webstudio-is/react-sdk";
import { n8nHandler, hasMatchingForm } from "@webstudio-is/form-handlers";
import { n8nHandler, getFormProperties } from "@webstudio-is/form-handlers";
import { Scripts, ScrollRestoration } from "@remix-run/react";
import {
fontAssets,
@ -22,6 +23,7 @@ import {
utils,
} from "../__generated__/index";
import css from "../__generated__/index.css";
import type { Data } from "@webstudio-is/http-client";
export type PageData = Omit<Data, "build"> & {
build: Pick<Data["build"], "props" | "instances" | "dataSources">;
@ -59,22 +61,43 @@ export const links: LinksFunction = () => {
const getRequestHost = (request: Request): string =>
request.headers.get("x-forwarded-host") || request.headers.get("host") || "";
const getMethod = (value: string | undefined) => {
if (value === undefined) {
return "post";
}
switch (value.toLowerCase()) {
case "get":
return "get";
default:
return "post";
}
};
export const action = async ({ request, context }: ActionArgs) => {
const formData = await request.formData();
// We're throwing rather than returning \`{ success: false }\`
// because this isn't supposed to happen normally: bug or malicious user
if (hasMatchingForm(formData, pageData.build.instances) === false) {
const formProperties = getFormProperties(
formData,
pageData.build.instances,
pageData.build.props
);
if (formProperties === undefined) {
// We're throwing rather than returning { success: false }
// because this isn't supposed to happen normally: bug or malicious user
throw json("Form not found", { status: 404 });
}
const { action, method } = formProperties;
const email = user?.email;
if (email == null) {
return { success: false };
}
// wrapped in try/catch just in cases \`new URL()\` throws
// wrapped in try/catch just in cases new URL() throws
// (should not happen)
let pageUrl: URL;
try {
@ -84,13 +107,30 @@ export const action = async ({ request, context }: ActionArgs) => {
return { success: false };
}
if (action !== undefined) {
try {
// Test that action is full URL
new URL(action);
} catch {
return json(
{
success: false,
error: "Invalid action URL, must be valid http/https protocol",
},
{ status: 200 }
);
}
}
const formInfo = {
formData,
projectId,
action: action ?? null,
method: getMethod(method),
pageUrl: pageUrl.toString(),
toEmail: email,
fromEmail: pageUrl.hostname + "@webstudio.email",
};
} as const;
const result = await n8nHandler({
formInfo,
@ -114,7 +154,7 @@ const Outlet = () => {
const assetBaseUrl = ASSETS_BASE;
const imageBaseUrl = ASSETS_BASE;
const params: Data["params"] = {
const params: Params = {
assetBaseUrl,
imageBaseUrl,
};

101
pnpm-lock.yaml generated

@ -362,6 +362,67 @@ importers:
specifier: 5.2.2
version: 5.2.2
fixtures/webstudio-remix-vercel:
dependencies:
'@remix-run/node':
specifier: ^1.19.2
version: 1.19.2
'@remix-run/react':
specifier: ^1.19.2
version: 1.19.2(react-dom@18.2.0)(react@18.2.0)
'@webstudio-is/form-handlers':
specifier: workspace:^
version: link:../../packages/form-handlers
'@webstudio-is/react-sdk':
specifier: workspace:^
version: link:../../packages/react-sdk
'@webstudio-is/sdk':
specifier: workspace:^
version: link:../../packages/sdk
'@webstudio-is/sdk-components-react':
specifier: workspace:^
version: link:../../packages/sdk-components-react
'@webstudio-is/sdk-components-react-radix':
specifier: workspace:^
version: link:../../packages/sdk-components-react-radix
'@webstudio-is/sdk-components-react-remix':
specifier: workspace:^
version: link:../../packages/sdk-components-react-remix
isbot:
specifier: ^3.6.8
version: 3.6.13
react:
specifier: ^18.2.0
version: 18.2.0
react-dom:
specifier: ^18.2.0
version: 18.2.0(react@18.2.0)
devDependencies:
'@remix-run/dev':
specifier: ^1.19.2
version: 1.19.2(@remix-run/serve@1.19.2)
'@remix-run/serve':
specifier: ^1.19.2
version: 1.19.2
'@types/react':
specifier: ^18.2.20
version: 18.2.21
'@types/react-dom':
specifier: ^18.2.7
version: 18.2.7
'@webstudio-is/cli':
specifier: workspace:^
version: link:../../packages/cli
'@webstudio-is/http-client':
specifier: workspace:^
version: link:../../packages/http-client
eslint:
specifier: ^8.48.0
version: 8.48.0
typescript:
specifier: 5.2.2
version: 5.2.2
packages/asset-uploader:
dependencies:
'@aws-crypto/sha256-js':
@ -468,6 +529,9 @@ importers:
'@webstudio-is/sdk-components-react-remix':
specifier: workspace:^
version: link:../sdk-components-react-remix
deepmerge:
specifier: ^4.3.1
version: 4.3.1
env-paths:
specifier: ^3.0.0
version: 3.0.0
@ -1594,7 +1658,6 @@ packages:
/@aashutoshrathi/word-wrap@1.2.6:
resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==}
engines: {node: '>=0.10.0'}
dev: false
/@alloc/quick-lru@5.2.0:
resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
@ -3729,12 +3792,10 @@ packages:
dependencies:
eslint: 8.48.0
eslint-visitor-keys: 3.4.3
dev: false
/@eslint-community/regexpp@4.6.2:
resolution: {integrity: sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==}
engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
dev: false
/@eslint/eslintrc@2.1.2:
resolution: {integrity: sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==}
@ -3751,12 +3812,10 @@ packages:
strip-json-comments: 3.1.1
transitivePeerDependencies:
- supports-color
dev: false
/@eslint/js@8.48.0:
resolution: {integrity: sha512-ZSjtmelB7IJfWD2Fvb7+Z+ChTIKWq6kjda95fLcQKNS5aheVHn4IkfgRQE3sIIzTcSLwLcLZUD9UBt+V7+h+Pw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dev: false
/@fal-works/esbuild-plugin-global-externals@2.1.2:
resolution: {integrity: sha512-cEee/Z+I12mZcFJshKcCqC8tuX5hG3s+d+9nZ3LabqKF1vKdF41B92pJVCBggjAGORAeOzyyDDKrZwIkLffeOQ==}
@ -3814,16 +3873,13 @@ packages:
minimatch: 3.1.2
transitivePeerDependencies:
- supports-color
dev: false
/@humanwhocodes/module-importer@1.0.1:
resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
engines: {node: '>=12.22'}
dev: false
/@humanwhocodes/object-schema@1.2.1:
resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==}
dev: false
/@iarna/toml@2.2.5:
resolution: {integrity: sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==}
@ -7902,7 +7958,6 @@ packages:
fast-json-stable-stringify: 2.1.0
json-schema-traverse: 0.4.1
uri-js: 4.4.1
dev: false
/ansi-escapes@4.3.2:
resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==}
@ -9034,7 +9089,6 @@ packages:
/deep-is@0.1.4:
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
dev: false
/deep-object-diff@1.1.9:
resolution: {integrity: sha512-Rn+RuwkmkDwCi2/oXOFS9Gsr5lJZu/yTGpK7wAaAIE75CC+LCGEZHpY6VQJa/RoJcrmaA/docWJZvYohlNkWPA==}
@ -9748,12 +9802,10 @@ packages:
dependencies:
esrecurse: 4.3.0
estraverse: 5.3.0
dev: false
/eslint-visitor-keys@3.4.3:
resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dev: false
/eslint@8.48.0:
resolution: {integrity: sha512-sb6DLeIuRXxeM1YljSe1KEx9/YYeZFQWcV8Rq9HfigmdDEugjLEVEa1ozDjL6YDjBpQHPJxJzze+alxi4T3OLg==}
@ -9799,7 +9851,6 @@ packages:
text-table: 0.2.0
transitivePeerDependencies:
- supports-color
dev: false
/espree@9.6.1:
resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==}
@ -9808,7 +9859,6 @@ packages:
acorn: 8.10.0
acorn-jsx: 5.3.2(acorn@8.10.0)
eslint-visitor-keys: 3.4.3
dev: false
/esprima@4.0.1:
resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==}
@ -9820,14 +9870,12 @@ packages:
engines: {node: '>=0.10'}
dependencies:
estraverse: 5.3.0
dev: false
/esrecurse@4.3.0:
resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
engines: {node: '>=4.0'}
dependencies:
estraverse: 5.3.0
dev: false
/estraverse@5.3.0:
resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
@ -10042,7 +10090,6 @@ packages:
/fast-deep-equal@3.1.3:
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
dev: false
/fast-glob@3.2.11:
resolution: {integrity: sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==}
@ -10070,7 +10117,6 @@ packages:
/fast-levenshtein@2.0.6:
resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
dev: false
/fast-shallow-equal@1.0.0:
resolution: {integrity: sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw==}
@ -10124,7 +10170,6 @@ packages:
engines: {node: ^10.12.0 || >=12.0.0}
dependencies:
flat-cache: 3.0.4
dev: false
/file-system-cache@2.3.0:
resolution: {integrity: sha512-l4DMNdsIPsVnKrgEXbJwDJsA5mB8rGwHYERMgqQx/xAUtChPJMre1bXBzDEqqVbWv9AIbFezXMxeEkZDSrXUOQ==}
@ -10204,11 +10249,9 @@ packages:
dependencies:
flatted: 3.2.7
rimraf: 3.0.2
dev: false
/flatted@3.2.7:
resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==}
dev: false
/flow-parser@0.209.1:
resolution: {integrity: sha512-7YdhWfCsLRn31or7oK9M7Svd4WFk1qfj6VIFY/9S6HRyzBBiLlobNbUbitZHfdi0nhkik5S498UmF3phdzM6ug==}
@ -10552,7 +10595,6 @@ packages:
engines: {node: '>=8'}
dependencies:
type-fest: 0.20.2
dev: false
/globalthis@1.0.3:
resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==}
@ -10621,7 +10663,6 @@ packages:
/graphemer@1.4.0:
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
dev: false
/gunzip-maybe@1.4.2:
resolution: {integrity: sha512-4haO1M4mLO91PW57BMsDFf75UmwoRX0GkdD+Faw+Lr+r/OZrOCS0pIBwOL1xCKQqnQzbNFGgK2V2CpBUPeFNTw==}
@ -10850,7 +10891,6 @@ packages:
dependencies:
parent-module: 1.0.1
resolve-from: 4.0.0
dev: false
/import-local@3.1.0:
resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==}
@ -11862,11 +11902,9 @@ packages:
/json-schema-traverse@0.4.1:
resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
dev: false
/json-stable-stringify-without-jsonify@1.0.1:
resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
dev: false
/json5@1.0.2:
resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==}
@ -11942,7 +11980,6 @@ packages:
dependencies:
prelude-ls: 1.2.1
type-check: 0.4.0
dev: false
/lexical@0.11.3:
resolution: {integrity: sha512-xsMKgx/Fa+QHg/nweemU04lCy7TnEr8LyeDtsKUC7fIDN9wH3GqbnQ0+e3Hbg4FmxlhDCiPPt0GcZAROq3R8uw==}
@ -12015,7 +12052,6 @@ packages:
/lodash.merge@4.6.2:
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
dev: false
/lodash@4.17.21:
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
@ -13521,7 +13557,6 @@ packages:
levn: 0.4.1
prelude-ls: 1.2.1
type-check: 0.4.0
dev: false
/ora@5.4.1:
resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==}
@ -13646,7 +13681,6 @@ packages:
engines: {node: '>=6'}
dependencies:
callsites: 3.1.0
dev: false
/parse-entities@4.0.0:
resolution: {integrity: sha512-5nk9Fn03x3rEhGaX1FU6IDwG/k+GxLXlFAkgrbM1asuAFl3BhdQWvASaIsmwWypRNcZKHPYnIuOSfIWEyEQnPQ==}
@ -13971,7 +14005,6 @@ packages:
/prelude-ls@1.2.1:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
engines: {node: '>= 0.8.0'}
dev: false
/prettier@2.8.7:
resolution: {integrity: sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw==}
@ -14108,7 +14141,6 @@ packages:
/punycode@2.3.0:
resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==}
engines: {node: '>=6'}
dev: false
/puppeteer-core@2.1.1:
resolution: {integrity: sha512-n13AWriBMPYxnpbb6bnaY5YoY6rGj8vPLrz6CZF3o0qJNEwlcfJVxBzYZ0NJsQ21UbdJoijPCDrM++SUVEz7+w==}
@ -14752,7 +14784,6 @@ packages:
/resolve-from@4.0.0:
resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
engines: {node: '>=4'}
dev: false
/resolve-from@5.0.0:
resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==}
@ -15600,7 +15631,6 @@ packages:
/text-table@0.2.0:
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
dev: false
/thenify-all@1.6.0:
resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
@ -15835,7 +15865,6 @@ packages:
engines: {node: '>= 0.8.0'}
dependencies:
prelude-ls: 1.2.1
dev: false
/type-detect@4.0.8:
resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==}
@ -15848,7 +15877,6 @@ packages:
/type-fest@0.20.2:
resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==}
engines: {node: '>=10'}
dev: false
/type-fest@0.21.3:
resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==}
@ -16167,7 +16195,6 @@ packages:
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
dependencies:
punycode: 2.3.0
dev: false
/urlpattern-polyfill@4.0.3:
resolution: {integrity: sha512-DOE84vZT2fEcl9gqCUTcnAw5ZY5Id55ikUcziSUntuEFL3pRvavg5kwDmTEUJkeCHInTlV/HexFomgYnzO5kdQ==}

@ -1,3 +1,4 @@
packages:
- 'packages/*'
- 'apps/*'
- "packages/*"
- "apps/*"
- "fixtures/*"