Merge branch 'compact-ide' into 'dev'

Added compact IDE component

See merge request ligolang/ligo!516
This commit is contained in:
Sander 2020-04-25 10:51:01 +00:00
commit 8e34c4a678
23 changed files with 12085 additions and 8944 deletions

File diff suppressed because it is too large Load Diff

View File

@ -27,6 +27,7 @@
}, },
"dependencies": { "dependencies": {
"@docusaurus/plugin-sitemap": "^2.0.0-alpha.37", "@docusaurus/plugin-sitemap": "^2.0.0-alpha.37",
"@ligo/syntax": "file:src/@ligo/syntax" "@ligo/syntax": "file:src/@ligo/syntax",
"@ligolang/compact-ligo-ide": "^3.0.3"
} }
} }

View File

@ -8,7 +8,10 @@
import React, { useEffect, useState, useRef } from 'react'; import React, { useEffect, useState, useRef } from 'react';
import classnames from 'classnames'; import classnames from 'classnames';
import Highlight, { defaultProps } from 'prism-react-renderer'; import Highlight, { defaultProps } from 'prism-react-renderer';
import { CompactLigoIde } from '@ligolang/compact-ligo-ide';
const { Prism } = require("prism-react-renderer"); const { Prism } = require("prism-react-renderer");
Prism.languages = { Prism.languages = {
...Prism.languages, ...Prism.languages,
pascaligo: { pascaligo: {
@ -59,7 +62,8 @@ Prism.languages = {
'punctuation': /\(\.|\.\)|[()\[\]:;,.]/ 'punctuation': /\(\.|\.\)|[()\[\]:;,.]/
}, },
reasonligo: reasonligo:
{...Prism.languages.reason, {
...Prism.languages.reason,
'comment': [ 'comment': [
/(^|[^\\])\/\*[\s\S]*?\*\//, /(^|[^\\])\/\*[\s\S]*?\*\//,
/\(\*[\s\S]*?\*\)/, /\(\*[\s\S]*?\*\)/,
@ -67,12 +71,14 @@ Prism.languages = {
] ]
}, },
cameligo: {...Prism.languages.ocaml, cameligo: {
...Prism.languages.ocaml,
'comment': [ 'comment': [
/(^|[^\\])\/\*[\s\S]*?\*\//, /(^|[^\\])\/\*[\s\S]*?\*\//,
/\(\*[\s\S]*?\*\)/, /\(\*[\s\S]*?\*\)/,
/\/\/.*/ /\/\/.*/
]} ]
}
}; };
import defaultTheme from 'prism-react-renderer/themes/palenight'; import defaultTheme from 'prism-react-renderer/themes/palenight';
import Clipboard from 'clipboard'; import Clipboard from 'clipboard';
@ -134,6 +140,21 @@ export default ({children, className: languageClassName, metastring}) => {
}; };
}, [button.current, target.current]); }, [button.current, target.current]);
// Compact Ligo IDE support - begin
if (languageClassName === 'language-compactLigoIde') {
const theme = isDarkTheme ? 'dark' : 'light';
const webIdeUrlRegex = /webIdeUrl=(.*)/;
if (metastring && webIdeUrlRegex.test(metastring)) {
const webIdeUrl = metastring.match(webIdeUrlRegex)[1];
return <CompactLigoIde webIdeUrl={webIdeUrl} theme={theme}>{children}</CompactLigoIde>
}
return <CompactLigoIde theme={theme}>{children}</CompactLigoIde>
}
// Compact Ligo IDE support -- end
let language = let language =
languageClassName && languageClassName.replace(/language-/, ''); languageClassName && languageClassName.replace(/language-/, '');

View File

@ -1058,3 +1058,11 @@ a:hover {
.boolean-example-table > .example .codeBlockLines_src-theme-CodeBlock- { .boolean-example-table > .example .codeBlockLines_src-theme-CodeBlock- {
background-color: transparent; background-color: transparent;
} }
.compactLigoIde {
height: 400px;
}
.compactLigoIde pre {
border-radius: 0px;
}

View File

@ -0,0 +1,8 @@
{
"presets": [
"@babel/preset-react",
"@babel/preset-env",
"@babel/preset-typescript"
],
"plugins": ["@babel/plugin-transform-react-jsx"]
}

6
tools/compact-ligo-ide/.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
*.log
node_modules/
lib/
.cache/
dist/

View File

@ -0,0 +1,9 @@
src
demo
*.lock
.babelrc
.gitignore
webpack.config.js
tsconfig.json
webpack.config.js

View File

@ -0,0 +1,194 @@
A React component for embedding Ligo code snippets on a page.
# Quick start
1. Install package `yarn add @ligolang/compact-ligo-ide`
2. Add `CompactLigoIde` component to a page
```jsx
import { Code, Language } from "@ligolang/compact-ligo-ide";
const App = () => {
const codeWithConfig = `(*_*
name: CameLigo Contract
dryRun:
entrypoint: main
parameters: Increment 2
storage: 0
*_*)
// variant defining pseudo multi-entrypoint actions
type action is
| Increment of int
| Decrement of int
function add (const a : int ; const b : int) : int is
block { skip } with a + b
function subtract (const a : int ; const b : int) : int is
block { skip } with a - b
// real entrypoint that re-routes the flow based
// on the action provided
function main (const p : action ; const s : int) :
(list(operation) * int) is
block { skip } with ((nil : list(operation)),
case p of
| Increment(n) -> add(s, n)
| Decrement(n) -> subtract(s, n)
end)`;
const editor = {
title: 'Smart Contract',
language: Language.CameLigo
};
const compile = {
entrypoint: 'main'
};
const dryRun = {
entrypoint: 'main',
parameters: 'Increment 1',
storage: '0'
};
const deploy = {
entrypoint: 'main',
storage: '0'
};
const evaluateFunction = {
entrypoint: 'add',
parameters: '5, 3'
};
return <CompactLigoIde
theme="light"
editor={editor}
compile={compile}
dryRun={dryRun}
deploy={deploy}
evaluateFunction={evaluateFunction}>
{codeWithConfig}
</CompactLigoIde>
};
```
3. Apply styling
```css
<style type="text/css">
.compactLigoIde {
height: 600px;
width: 600px;
}
</style>
```
# Configuration
Compact Ligo IDE can be configured via component parameters and/or by passing configuration as a child. The example above illustrastes how to do so.
## Available configuration
```js
interface CompactLigoIdeProps {
editor?: Partial<EditorConfig>;
compile?: Partial<CompileConfig>;
dryRun?: Partial<DryRunConfig>;
deploy?: Partial<DeployConfig>;
evaluateFunction?: Partial<EvaluateFunctionConfig>;
evaluateValue?: Partial<EvaluateValueConfig>;
result?: string;
webIdeUrl?: string;
theme?: "dark" | "light";
children?: string;
}
interface EditorConfig {
language: Language;
code: string;
dirty: boolean;
title: string;
}
interface CompileConfig {
entrypoint: string;
}
interface DryRunConfig {
entrypoint: string;
parameters: string;
storage: string;
}
interface DeployConfig {
entrypoint: string;
storage: string;
}
interface EvaluateFunctionConfig {
entrypoint: string;
parameters: string;
}
interface EvaluateValueConfig {
entrypoint: string;
}
```
Alternatively, the component can be configured by passing the configuration like so:
```
(*_*
name: PascaLIGO Contract
language: pascaligo
compile:
entrypoint: main
dryRun:
entrypoint: main
parameters: Increment (1)
storage: 0
deploy:
entrypoint: main
storage: 0
evaluateValue:
entrypoint: ""
evaluateFunction:
entrypoint: add
parameters: (5, 6)
*_*)
// variant defining pseudo multi-entrypoint actions
type action is
| Increment of int
| Decrement of int
function add (const a : int ; const b : int) : int is
block { skip } with a + b
function subtract (const a : int ; const b : int) : int is
block { skip } with a - b
// real entrypoint that re-routes the flow based
// on the action provided
function main (const p : action ; const s : int) :
(list(operation) * int) is
block { skip } with ((nil : list(operation)),
case p of
| Increment(n) -> add(s, n)
| Decrement(n) -> subtract(s, n)
end)
```
# Contribute
## Starting dev server
1. Install dependencies with `yarn install`
2. Run `yarn start`
3. Open http://localhost:1234 in a browser
## Build package
Run `yarn build`.
## Publish package
Run `npm publish --access=public`.

View File

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>React TypeScript App</title>
<style type="text/css">
.compactLigoIde {
height: 400px;
width: 600px;
}
</style>
</head>
<body>
<div id="root"></div>
<script src="./index.tsx"></script>
</body>
</html>

View File

@ -0,0 +1,73 @@
import React, { useState } from 'react';
import { render } from 'react-dom';
import { CompactLigoIde, Language } from '../src';
const App = () => {
const codeWithConfig = `(*_*
name: CameLigo Contract
dryRun:
entrypoint: main
parameters: Increment 2
storage: 0
*_*)
// variant defining pseudo multi-entrypoint actions
type action is
| Increment of int
| Decrement of int
function add (const a : int ; const b : int) : int is
block { skip } with a + b
function subtract (const a : int ; const b : int) : int is
block { skip } with a - b
// real entrypoint that re-routes the flow based
// on the action provided
function main (const p : action ; const s : int) :
(list(operation) * int) is
block { skip } with ((nil : list(operation)),
case p of
| Increment(n) -> add(s, n)
| Decrement(n) -> subtract(s, n)
end)`;
const editor = {
title: 'Smart Contract',
language: Language.CameLigo
};
const compile = {
entrypoint: 'main'
};
const dryRun = {
entrypoint: 'main',
parameters: 'Increment 1',
storage: '0'
};
const deploy = {
entrypoint: 'main',
storage: '0'
};
const evaluateFunction = {
entrypoint: 'add',
parameters: '5, 3'
};
const [theme, setTheme] = useState('light');
return <>
<button onClick={() => theme === 'light' ? setTheme('dark') : setTheme('light')}>Toggle Theme</button>
<CompactLigoIde
theme={theme}
editor={editor}
compile={compile}
dryRun={dryRun}
deploy={deploy}
evaluateFunction={evaluateFunction}>
{codeWithConfig}
</CompactLigoIde>
</>;
};
render(<App />, document.getElementById("root"));

View File

@ -0,0 +1,55 @@
{
"name": "@ligolang/compact-ligo-ide",
"version": "3.0.3",
"main": "./lib/index.js",
"scripts": {
"start": "parcel ./demo/index.html",
"build": "webpack"
},
"typings": "./typings/index.d.ts",
"files": [
"lib",
"typings/index.d.ts"
],
"license": "ISC",
"peerDependencies": {
"react": "^16.13.1",
"react-dom": "^16.13.1"
},
"devDependencies": {
"@babel/cli": "^7.8.4",
"@babel/core": "^7.8.7",
"@babel/plugin-transform-react-jsx": "^7.8.3",
"@babel/preset-env": "^7.8.7",
"@babel/preset-react": "^7.8.3",
"@babel/preset-typescript": "^7.8.3",
"@types/node": "^13.9.5",
"@types/react": "^16.9.23",
"@types/react-dom": "^16.9.5",
"@types/styled-components": "^5.0.1",
"babel-loader": "8.0.6",
"css-loader": "^3.4.2",
"parcel-bundler": "^1.12.4",
"path": "^0.12.7",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"style-loader": "^1.1.3",
"typescript": "^3.8.3",
"webpack": "4.41.5",
"webpack-cli": "^3.3.11",
"webpack-node-externals": "^1.7.2"
},
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^1.2.28",
"@fortawesome/free-solid-svg-icons": "^5.13.0",
"@fortawesome/react-fontawesome": "^0.1.9",
"@types/react-helmet": "^5.0.15",
"@types/styled-theming": "^2.2.2",
"axios": "^0.19.2",
"monaco-editor": "npm:@ligolang/monaco-editor@0.18.1",
"react-helmet": "^5.2.1",
"styled-components": "^5.0.1",
"styled-theming": "^2.2.0",
"yaml": "^1.9.2"
}
}

View File

@ -0,0 +1,145 @@
import axios from 'axios';
import React from 'react';
import styled, { ThemeProvider } from 'styled-components';
import { faExternalLinkAlt } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Editor } from './editor';
import { CompactLigoIdeProps, DEFAULT_COMPACT_LIGO_IDE_PROPS, ShareParams } from '../types';
import YAML from 'yaml';
const Container = styled.div`
position: relative;
display: flex;
flex-direction: column;
`;
const Button = styled.div`
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
position: absolute;
width: 60px;
height: 30px;
top: 0;
right: 0;
z-index: 1;
padding: 5px;
color: white;
:hover {
background: #fc683a;
}
`;
const Icon = styled(FontAwesomeIcon)`
pointer-events: none;
margin-left: 3px;
`;
const OutputContainer = styled.div`
position: relative;
`;
const Output = styled.pre`
background-color: rgba(14, 116, 255, 1);
color: white;
padding: 20px;
margin: 0;
overflow: auto;
max-height: 200px;
`;
function parseConfig(content: string): CompactLigoIdeProps {
const METADATA_REGEX = /\(\*_\*([^]*?)\*_\*\)\s*/;
const match = content.match(METADATA_REGEX);
if (!match || !match[1]) {
return { editor: { code: content } };
}
try {
const config = YAML.parse(match[1]);
return {
editor: {
title: config.name,
language: config.language,
code: content.replace(METADATA_REGEX, '')
},
compile: { ...config.compile },
dryRun: { ...config.dryRun },
deploy: { ...config.deploy },
evaluateFunction: { ...config.evaluateFunction },
evaluateValue: { ...config.evaluateValue }
};
} catch (ex) {
throw new Error(`Unable to parse configuration.`);
}
}
export function CompactLigoIde(props: CompactLigoIdeProps) {
const yamlConfig = props.children ? parseConfig(props.children) : {};
const shareParams: ShareParams = {
editor: {
...DEFAULT_COMPACT_LIGO_IDE_PROPS.editor,
...yamlConfig.editor,
...props.editor
},
compile: {
...DEFAULT_COMPACT_LIGO_IDE_PROPS.compile,
...yamlConfig.compile,
...props.compile
},
dryRun: {
...DEFAULT_COMPACT_LIGO_IDE_PROPS.dryRun,
...yamlConfig.dryRun,
...props.dryRun
},
deploy: {
...DEFAULT_COMPACT_LIGO_IDE_PROPS.deploy,
...yamlConfig.deploy,
...props.deploy
},
evaluateFunction: {
...DEFAULT_COMPACT_LIGO_IDE_PROPS.evaluateFunction,
...yamlConfig.evaluateFunction,
...props.evaluateFunction
},
evaluateValue: {
...DEFAULT_COMPACT_LIGO_IDE_PROPS.evaluateValue,
...yamlConfig.evaluateValue,
...props.evaluateValue
}
};
const result = props.result || DEFAULT_COMPACT_LIGO_IDE_PROPS.result;
const webIdeUrl = props.webIdeUrl || DEFAULT_COMPACT_LIGO_IDE_PROPS.webIdeUrl;
const theme = props.theme || DEFAULT_COMPACT_LIGO_IDE_PROPS.theme;
async function openInIde() {
const response = await axios.post(`${webIdeUrl}/api/share`, { ...shareParams });
const { hash } = await response.data;
window.open(`${webIdeUrl}/p/${hash}`, "_blank");
}
return (
<ThemeProvider theme={{ mode: theme }}>
<Container className="compactLigoIde">
<Editor
value={shareParams.editor.code}
language={shareParams.editor.language}
></Editor>
<OutputContainer>
<Output>{result}</Output>
<Button onClick={openInIde} title="Open in Ligo Web IDE">
<span>IDE<Icon icon={faExternalLinkAlt} /></span>
</Button>
</OutputContainer>
</Container>
</ThemeProvider>
);
};

View File

@ -0,0 +1,83 @@
import * as monaco from 'monaco-editor';
import React, { useEffect, useRef, useState } from 'react';
import { Helmet } from 'react-helmet';
import styled, { withTheme } from 'styled-components';
const Container = styled.div`
flex: 2;
`;
export const Editor = withTheme(
(props: {
value: string;
language?: string;
onChange?: (value: string) => void;
theme: { mode: string };
}) => {
let containerRef = useRef(null);
const isLightTheme = props.theme.mode === 'light';
const background = isLightTheme ? "#eff7ff" : "#3b454e40";
const lineHighlightBackground = isLightTheme ? "#cee3ff" : "#63768840";
const lineNumberColor = "#888";
const model = monaco.editor.createModel(props.value, props.language);
monaco.editor.defineTheme("ligoTheme", {
base: "vs",
inherit: true,
rules: [],
colors: {
"editor.background": background,
"editor.lineHighlightBackground": lineHighlightBackground,
"editorLineNumber.foreground": lineNumberColor
}
});
monaco.editor.setTheme("ligoTheme");
useEffect(() => {
const cleanupFunc: Array<() => void> = [];
const htmlElement = (containerRef.current as unknown) as HTMLElement;
const editor = monaco.editor.create(htmlElement, {
readOnly: true,
model: model,
automaticLayout: true,
minimap: {
enabled: false
}
});
const { dispose } = editor.onDidChangeModelContent(() => {
if (props.onChange) {
props.onChange(editor.getValue());
}
});
cleanupFunc.push(dispose);
return function cleanUp() {
cleanupFunc.forEach(f => f());
};
}, []);
return (
<Container ref={containerRef}>
<Helmet>
<style type="text/css">
{`
.monaco-editor .current-line ~ .line-numbers {
color: ${lineNumberColor};
}
.monaco-editor .margin-view-overlays .current-line,
.monaco-editor .view-overlays .current-line {
background-color: ${lineHighlightBackground};
}
`}
</style>
</Helmet>
</Container>
);
}
);

View File

@ -0,0 +1,2 @@
export { CompactLigoIde } from './components/compact-ligo-ide';
export * from './types';

View File

@ -0,0 +1,105 @@
export enum Language {
PascaLigo = 'pascaligo',
CameLigo = 'cameligo',
ReasonLigo = 'reasonligo'
};
export interface ShareParams {
editor: EditorConfig;
compile: CompileConfig;
dryRun: DryRunConfig;
deploy: DeployConfig;
evaluateFunction: EvaluateFunctionConfig;
evaluateValue: EvaluateValueConfig;
}
export interface EditorConfig {
language: Language;
code: string;
dirty: boolean;
title: string;
}
export interface CompileConfig {
entrypoint: string;
}
export interface DryRunConfig {
entrypoint: string;
parameters: string;
storage: string;
}
export interface DeployConfig {
entrypoint: string;
storage: string;
}
export interface EvaluateFunctionConfig {
entrypoint: string;
parameters: string;
}
export interface EvaluateValueConfig {
entrypoint: string;
}
export interface CompactLigoIdeProps {
editor?: Partial<EditorConfig>;
compile?: Partial<CompileConfig>;
dryRun?: Partial<DryRunConfig>;
deploy?: Partial<DeployConfig>;
evaluateFunction?: Partial<EvaluateFunctionConfig>;
evaluateValue?: Partial<EvaluateValueConfig>;
result?: string;
webIdeUrl?: string;
theme?: "dark" | "light";
children?: string;
}
export const DEFAULT_EDITOR_CONFIG: EditorConfig = {
code: "",
language: Language.PascaLigo,
dirty: true,
title: ""
};
export const DEFAULT_COMPILE_CONFIG: CompileConfig = {
entrypoint: ""
};
export const DEFAULT_DRY_RUN_CONFIG: DryRunConfig = {
entrypoint: "",
parameters: "",
storage: ""
};
export const DEFAULT_DEPLOY_CONFIG: DeployConfig = {
entrypoint: "",
storage: ""
};
export const DEFAULT_EVALUATE_FUNCTION_CONFIG: EvaluateFunctionConfig = {
entrypoint: "",
parameters: ""
};
export const DEFAULT_EVALUATE_VALUE_CONFIG: EvaluateValueConfig = {
entrypoint: ""
};
export const DEFAULT_SHARE_PARAMS: ShareParams = {
editor: DEFAULT_EDITOR_CONFIG,
compile: DEFAULT_COMPILE_CONFIG,
dryRun: DEFAULT_DRY_RUN_CONFIG,
deploy: DEFAULT_DEPLOY_CONFIG,
evaluateFunction: DEFAULT_EVALUATE_FUNCTION_CONFIG,
evaluateValue: DEFAULT_EVALUATE_VALUE_CONFIG
};
export const DEFAULT_COMPACT_LIGO_IDE_PROPS: (ShareParams & CompactLigoIdeProps) = {
...DEFAULT_SHARE_PARAMS,
result: '',
webIdeUrl: process.env.NODE_ENV === 'production' ? 'https://ide.ligolang.org' : 'http://localhost:8080',
theme: 'light'
};

View File

@ -0,0 +1,19 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react"
},
"include": ["src"]
}

View File

@ -0,0 +1,5 @@
import { StatelessComponent } from 'react';
declare const Boilerplate: StatelessComponent;
export { Boilerplate };

View File

@ -0,0 +1,29 @@
const path = require('path');
const nodeExternals = require("webpack-node-externals");
module.exports = {
mode: 'production',
entry: './src/index.tsx',
output: {
path: path.resolve('lib'),
filename: 'index.js',
libraryTarget: 'commonjs2'
},
module: {
rules: [
{
test: /\.(t|j)sx?$/,
exclude: /(node_modules)/,
use: 'babel-loader'
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
]
},
externals: [nodeExternals()],
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx']
},
}

File diff suppressed because it is too large Load Diff

View File

@ -650,6 +650,15 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"@types/cors": {
"version": "2.8.6",
"resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.6.tgz",
"integrity": "sha512-invOmosX0DqbpA+cE2yoHGUlF/blyf7nB0OGYBBiH27crcVm5NmFaZkLP4Ta1hGaesckCi5lVLlydNJCxkTOSg==",
"dev": true,
"requires": {
"@types/express": "*"
}
},
"@types/express": { "@types/express": {
"version": "4.17.3", "version": "4.17.3",
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.3.tgz", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.3.tgz",
@ -752,12 +761,14 @@
"@types/node": { "@types/node": {
"version": "10.14.21", "version": "10.14.21",
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.21.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.21.tgz",
"integrity": "sha512-nuFlRdBiqbF+PJIEVxm2jLFcQWN7q7iWEJGsBV4n7v1dbI9qXB8im2pMMKMCUZe092sQb5SQft2DHfuQGK5hqQ==" "integrity": "sha512-nuFlRdBiqbF+PJIEVxm2jLFcQWN7q7iWEJGsBV4n7v1dbI9qXB8im2pMMKMCUZe092sQb5SQft2DHfuQGK5hqQ==",
"dev": true
}, },
"@types/node-fetch": { "@types/node-fetch": {
"version": "2.5.5", "version": "2.5.5",
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.5.tgz", "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.5.tgz",
"integrity": "sha512-IWwjsyYjGw+em3xTvWVQi5MgYKbRs0du57klfTaZkv/B24AEQ/p/IopNeqIYNy3EsfHOpg8ieQSDomPcsYMHpA==", "integrity": "sha512-IWwjsyYjGw+em3xTvWVQi5MgYKbRs0du57klfTaZkv/B24AEQ/p/IopNeqIYNy3EsfHOpg8ieQSDomPcsYMHpA==",
"dev": true,
"requires": { "requires": {
"@types/node": "*", "@types/node": "*",
"form-data": "^3.0.0" "form-data": "^3.0.0"
@ -1056,7 +1067,8 @@
"asynckit": { "asynckit": {
"version": "0.4.0", "version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
"dev": true
}, },
"atob": { "atob": {
"version": "2.1.2", "version": "2.1.2",
@ -1677,6 +1689,7 @@
"version": "1.0.8", "version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"dev": true,
"requires": { "requires": {
"delayed-stream": "~1.0.0" "delayed-stream": "~1.0.0"
} }
@ -1772,6 +1785,15 @@
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
}, },
"cors": {
"version": "2.8.5",
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
"integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
"requires": {
"object-assign": "^4",
"vary": "^1"
}
},
"create-error-class": { "create-error-class": {
"version": "3.0.2", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz",
@ -1970,7 +1992,8 @@
"delayed-stream": { "delayed-stream": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
"dev": true
}, },
"depd": { "depd": {
"version": "1.1.2", "version": "1.1.2",
@ -2662,6 +2685,7 @@
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz",
"integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==",
"dev": true,
"requires": { "requires": {
"asynckit": "^0.4.0", "asynckit": "^0.4.0",
"combined-stream": "^1.0.8", "combined-stream": "^1.0.8",
@ -5181,6 +5205,11 @@
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
"dev": true "dev": true
}, },
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
},
"object-copy": { "object-copy": {
"version": "0.1.0", "version": "0.1.0",
"resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",

View File

@ -19,6 +19,8 @@
"@types/node": "10", "@types/node": "10",
"@types/tmp": "^0.1.0", "@types/tmp": "^0.1.0",
"@types/winston": "^2.4.4", "@types/winston": "^2.4.4",
"@types/cors": "^2.8.6",
"@types/node-fetch": "^2.5.4",
"jest": "^24.9.0", "jest": "^24.9.0",
"nodemon": "^1.19.3", "nodemon": "^1.19.3",
"ts-jest": "^24.1.0", "ts-jest": "^24.1.0",
@ -32,8 +34,8 @@
"@google-cloud/storage": "^4.0.0", "@google-cloud/storage": "^4.0.0",
"@hapi/joi": "^16.1.7", "@hapi/joi": "^16.1.7",
"@taquito/taquito": "^6.1.0-beta.0", "@taquito/taquito": "^6.1.0-beta.0",
"@types/node-fetch": "^2.5.4",
"body-parser": "^1.19.0", "body-parser": "^1.19.0",
"cors": "^2.8.5",
"escape-html": "^1.0.3", "escape-html": "^1.0.3",
"express": "^4.17.1", "express": "^4.17.1",
"express-prometheus-middleware": "^0.8.5", "express-prometheus-middleware": "^0.8.5",

View File

@ -1,3 +1,4 @@
import cors from 'cors';
import express from 'express'; import express from 'express';
import fs from 'fs'; import fs from 'fs';
import { dirname, join } from 'path'; import { dirname, join } from 'path';
@ -25,6 +26,15 @@ const APP_PORT = 8080;
const metrics = express(); const metrics = express();
const METRICS_PORT = 8081; const METRICS_PORT = 8081;
const corsOptions = {
origin: [
'https://ligolang.org',
'http://localhost:3000',
'http://localhost:1234'
],
optionsSuccessStatus: 200
};
const appRootDirectory = const appRootDirectory =
process.env['STATIC_ASSETS'] || process.env['STATIC_ASSETS'] ||
dirname(require.resolve('../../client/package.json')); dirname(require.resolve('../../client/package.json'));
@ -60,6 +70,9 @@ app.use('^/$', async (_, res) =>
res.send(template(JSON.stringify(await loadDefaultState(appBundleDirectory)))) res.send(template(JSON.stringify(await loadDefaultState(appBundleDirectory))))
); );
app.use(express.static(appBundleDirectory)); app.use(express.static(appBundleDirectory));
app.options('/api/share', cors(corsOptions));
app.get( app.get(
`/p/:hash([0-9a-zA-Z\-\_]+)`, `/p/:hash([0-9a-zA-Z\-\_]+)`,
sharedLinkHandler(appBundleDirectory, template) sharedLinkHandler(appBundleDirectory, template)
@ -68,7 +81,7 @@ app.post('/api/compile-contract', compileContractHandler);
app.post('/api/compile-expression', compileExpressionHandler); app.post('/api/compile-expression', compileExpressionHandler);
app.post('/api/compile-storage', compileStorageHandler); app.post('/api/compile-storage', compileStorageHandler);
app.post('/api/dry-run', dryRunHandler); app.post('/api/dry-run', dryRunHandler);
app.post('/api/share', shareHandler); app.post('/api/share', cors(corsOptions), shareHandler);
app.post('/api/evaluate-value', evaluateValueHandler); app.post('/api/evaluate-value', evaluateValueHandler);
app.post('/api/run-function', runFunctionHandler); app.post('/api/run-function', runFunctionHandler);
app.post('/api/deploy', deployHandler); app.post('/api/deploy', deployHandler);

View File

@ -1471,6 +1471,13 @@
dependencies: dependencies:
"@types/node" "*" "@types/node" "*"
"@types/cors@^2.8.6":
version "2.8.6"
resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.6.tgz#cfaab33c49c15b1ded32f235111ce9123009bd02"
integrity sha512-invOmosX0DqbpA+cE2yoHGUlF/blyf7nB0OGYBBiH27crcVm5NmFaZkLP4Ta1hGaesckCi5lVLlydNJCxkTOSg==
dependencies:
"@types/express" "*"
"@types/eslint-visitor-keys@^1.0.0": "@types/eslint-visitor-keys@^1.0.0":
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d"
@ -3496,6 +3503,14 @@ core-util-is@1.0.2, core-util-is@~1.0.0:
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
cors@^2.8.5:
version "2.8.5"
resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29"
integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==
dependencies:
object-assign "^4"
vary "^1"
cosmiconfig@^5.0.0, cosmiconfig@^5.2.0, cosmiconfig@^5.2.1: cosmiconfig@^5.0.0, cosmiconfig@^5.2.0, cosmiconfig@^5.2.1:
version "5.2.1" version "5.2.1"
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a"
@ -8225,7 +8240,7 @@ oauth-sign@~0.9.0:
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
object-assign@4.1.1, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: object-assign@4.1.1, object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
version "4.1.1" version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
@ -11935,7 +11950,7 @@ validate-npm-package-license@^3.0.1:
spdx-correct "^3.0.0" spdx-correct "^3.0.0"
spdx-expression-parse "^3.0.0" spdx-expression-parse "^3.0.0"
vary@~1.1.2: vary@^1, vary@~1.1.2:
version "1.1.2" version "1.1.2"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=