Skip to content

Commit

Permalink
Support serverless Function datasource (#641)
Browse files Browse the repository at this point in the history
* WIP

* Update NOTES.md

* fwefwr

* proto

* cleany

* typo

* remove comment

* Update server.ts

* wip

* Wip

* console

* lint

* wip

* params types

* params

* better default

* Add secrets

* response headers

* Add timeout

* cancel logic

* Move types

* Move Console to components

* Console theming

* fix parameter view

* Move toolbar

* tweakztweaky

* header

* network

* remove legacy

* theme spacing

* dense tabs

* fix build
  • Loading branch information
Janpot authored Jul 14, 2022
1 parent e6c2dc4 commit 9bdb7ec
Show file tree
Hide file tree
Showing 23 changed files with 994 additions and 8 deletions.
4 changes: 3 additions & 1 deletion packages/toolpad-app/next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { createRequire } from 'module';
import * as path from 'path';

const require = createRequire(import.meta.url);
const pkgJson = require('./package.json');

/**
* @param {string} input
Expand All @@ -23,7 +24,8 @@ function parseBuidEnvVars(env) {

return {
TOOLPAD_TARGET: target,
TOOLPAD_DEMO: env.TOOLPAD_DEMO,
TOOLPAD_DEMO: env.TOOLPAD_DEMO || '',
TOOLPAD_VERSION: pkgJson.version,
};
}

Expand Down
14 changes: 11 additions & 3 deletions packages/toolpad-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
"@emotion/react": "^11.9.3",
"@emotion/server": "^11.4.0",
"@emotion/styled": "^11.9.3",
"@googleapis/drive": "^2.3.0",
"@googleapis/sheets": "^2.0.1",
"@mui/icons-material": "^5.8.4",
"@mui/lab": "^5.0.0-alpha.88",
"@mui/material": "^5.8.6",
Expand All @@ -54,16 +56,19 @@
"cuid": "^2.1.8",
"es-module-shims": "^1.5.4",
"esbuild": "^0.14.48",
"fastestsmallesttextencoderdecoder": "^1.0.22",
"find-up": "^6.2.0",
"fractional-indexing": "^3.0.1",
"@googleapis/drive": "^2.3.0",
"@googleapis/sheets": "^2.0.1",
"headers-polyfill": "^3.0.10",
"isolated-vm": "^4.4.1",
"json-to-ts": "^1.7.0",
"json5": "^2.2.1",
"lodash-es": "^4.17.21",
"next": "12.2.0",
"node-fetch": "^3.2.6",
"node-fetch-har": "^1.0.1",
"path-to-regexp": "^6.2.0",
"perf-cascade": "^2.11.0",
"prettier": "^2.6.2",
"pretty-bytes": "^6.0.0",
"prisma": "^4.0.0",
Expand All @@ -79,15 +84,18 @@
"react-router-dom": "^6.3.0",
"react-split-pane": "^0.1.92",
"serialize-javascript": "^6.0.0",
"ses": "^0.15.17",
"sucrase": "^3.23.0",
"superjson": "^1.8.1",
"ts-node": "^10.8.2",
"typescript": "^4.7.4"
"typescript": "^4.7.4",
"whatwg-url": "^11.0.0"
},
"devDependencies": {
"@types/babel__code-frame": "^7.0.3",
"@types/crypto-js": "^4.1.1",
"@types/glob": "^7.2.0",
"@types/har-format": "^1.2.8",
"@types/lodash-es": "^4.17.6",
"@types/node-fetch": "^2.6.2",
"@types/react": "^18.0.14",
Expand Down
10 changes: 9 additions & 1 deletion packages/toolpad-app/src/components/AppEditor/BindingEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,15 @@ export function JsBindingEditor({ value, onChange }: JsBindingEditorProps) {
<Stack direction="row" sx={{ height: 400, gap: 2 }}>
<GlobalScopeExplorer value={globalScope} />

<Box sx={{ height: '100%', display: 'flex', flex: 1, flexDirection: 'column' }}>
<Box
sx={{
height: '100%',
display: 'flex',
flex: 1,
flexDirection: 'column',
overflow: 'hidden',
}}
>
<Typography sx={{ mb: 2 }}>
Make the &quot;{label}&quot; property dynamic with a JavaScript expression. This property
expects a type: <code>{propType?.type || 'any'}</code>.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ function QueryNodeEditorDialog<Q, P>({
</Stack>
</DialogTitle>
<Divider />

{dataSourceId && dataSource ? (
<DialogContent sx={{ overflow: 'hidden', display: 'flex', flexDirection: 'column', p: 0 }}>
<Box sx={{ display: 'flex', flexDirection: 'row', minHeight: 0 }}>
Expand Down
141 changes: 141 additions & 0 deletions packages/toolpad-app/src/components/Console.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import { darken, IconButton, lighten, styled, SxProps } from '@mui/material';
import clsx from 'clsx';
import * as React from 'react';
import DoDisturbIcon from '@mui/icons-material/DoDisturb';
import Inspector, { InspectorProps } from 'react-inspector';
import inspectorTheme from '../inspectorTheme';
import { interleave } from '../utils/react';

export interface LogEntry {
timestamp: number;
level: string;
args: any[];
}

const classes = {
header: 'Toolpad_ConsoleHeader',
logEntriesContainer: 'Toolpad_ConsoleLogEntriesContainer',
logEntries: 'Toolpad_ConsoleLogEntries',
logEntry: 'Toolpad_ConsoleLogEntry',
logEntryText: 'Toolpad_ConsoleLogEntryTExt',
};

const ConsoleRoot = styled('div')(({ theme }) => {
const getColor = (color: string) => {
const modify = theme.palette.mode === 'light' ? darken : lighten;
return modify(color, 0.6);
};

const getBackgroundColor = (color: string) => {
const modify = theme.palette.mode === 'light' ? lighten : darken;
return modify(color, 0.9);
};

return {
width: '100%',
height: '100%',
display: 'flex',
flexDirection: 'column',
alignItems: 'stretch',

[`& .${classes.header}`]: {
padding: theme.spacing('2px', 1),
borderBottom: `1px solid ${theme.palette.divider}`,
},

[`& .${classes.logEntriesContainer}`]: {
flex: 1,

// This container has only a single item, but the column-reverse has the effect that it
// keeps the scroll position at the bottom when the content grows
display: 'flex',
flexDirection: 'column-reverse',
overflow: 'auto',

fontSize: 12,
lineHeight: 1.2,
fontFamily: 'Consolas, Menlo, Monaco, "Andale Mono", "Ubuntu Mono", monospace',
},

[`& .${classes.logEntry}`]: {
'&:first-of-type': {
borderTop: `1px solid ${theme.palette.divider}`,
},
borderBottom: `1px solid ${theme.palette.divider}`,
paddingLeft: theme.spacing(1),
paddingRight: theme.spacing(1),
paddingTop: 3,
paddingBottom: 1,
},

[`& .${classes.logEntry}.error`]: {
color: getColor(theme.palette.error.light),
background: getBackgroundColor(theme.palette.error.light),
},

[`& .${classes.logEntry}.warn`]: {
color: getColor(theme.palette.warning.light),
background: getBackgroundColor(theme.palette.warning.light),
},

[`& .${classes.logEntry}.info`]: {
color: getColor(theme.palette.info.light),
background: getBackgroundColor(theme.palette.info.light),
},

[`& .${classes.logEntryText} > *`]: {
display: 'inline-block',
verticalAlign: 'top',
},
};
});

function ConsoleInpector(props: InspectorProps) {
return <Inspector {...props} theme={inspectorTheme} />;
}

interface ConsoleEntryProps {
entry: LogEntry;
}

function ConsoleEntry({ entry }: ConsoleEntryProps) {
return (
<div className={clsx(classes.logEntry, entry.level)}>
<div className={classes.logEntryText}>
{interleave(
entry.args.map((arg, i) =>
typeof arg === 'string' ? arg : <ConsoleInpector key={i} data={arg} />,
),
' ',
)}
</div>
</div>
);
}

interface ConsoleProps {
sx?: SxProps;
value?: LogEntry[];
onChange?: (logEntries: LogEntry[]) => void;
}

export default function Console({ value = [], onChange, sx }: ConsoleProps) {
return (
<ConsoleRoot sx={sx}>
<div className={classes.header}>
{onChange ? (
<IconButton disabled={value.length <= 0} onClick={() => onChange([])}>
<DoDisturbIcon />
</IconButton>
) : null}
</div>
<div className={classes.logEntriesContainer}>
<div className={classes.logEntries}>
{value.map((entry, i) => (
<ConsoleEntry key={i} entry={entry} />
))}
</div>
</div>
</ConsoleRoot>
);
}
52 changes: 52 additions & 0 deletions packages/toolpad-app/src/components/HarViewer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { fromHar } from 'perf-cascade';
import * as React from 'react';
import { Har } from 'har-format';
import { styled, SxProps } from '@mui/material';
import 'perf-cascade/dist/perf-cascade.css';

const HarViewerRoot = styled('div')({});

function fixLinks(elm: Element) {
elm.querySelectorAll('a').forEach((link) => link.setAttribute('target', '_blank'));
}

export interface HarViewerProps {
har?: Har;
sx?: SxProps;
}

export default function HarViewer({ har, sx }: HarViewerProps) {
const rootRef = React.useRef<HTMLDivElement>(null);

React.useEffect(() => {
const root = rootRef.current;
if (har && root) {
const svg = fromHar(har);
fixLinks(svg);

const observer = new MutationObserver((entries) => {
for (const entry of entries) {
for (const node of entry.addedNodes) {
if (node instanceof Element) {
fixLinks(node);
}
}
}
});

observer.observe(svg, {
subtree: true,
childList: true,
});

root.append(svg);
return () => {
observer.disconnect();
svg.remove();
};
}
return () => {};
}, [har]);

return <HarViewerRoot ref={rootRef} sx={sx} />;
}
6 changes: 6 additions & 0 deletions packages/toolpad-app/src/components/JsonView.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as React from 'react';
import { SxProps, styled } from '@mui/material';
import { ObjectInspector, ObjectInspectorProps, ObjectValue, ObjectLabel } from 'react-inspector';
import inspectorTheme from '../inspectorTheme';

const nodeRenderer: ObjectInspectorProps['nodeRenderer'] = ({
depth,
Expand All @@ -17,6 +18,10 @@ const nodeRenderer: ObjectInspectorProps['nodeRenderer'] = ({

const JsonViewRoot = styled('div')({
whiteSpace: 'nowrap',

fontSize: 12,
lineHeight: 1.2,
fontFamily: 'Consolas, Menlo, Monaco, "Andale Mono", "Ubuntu Mono", monospace',
});

export interface JsonViewProps {
Expand All @@ -34,6 +39,7 @@ export default function JsonView({ src, sx }: JsonViewProps) {
expandLevel={1}
expandPaths={expandPaths}
data={src}
theme={inspectorTheme}
/>
</JsonViewRoot>
);
Expand Down
2 changes: 2 additions & 0 deletions packages/toolpad-app/src/components/MonacoEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import * as monaco from 'monaco-editor';
import { styled, SxProps } from '@mui/material';
import clsx from 'clsx';
import cuid from 'cuid';
import monacoEditorTheme from '../monacoEditorTheme';

function getExtension(language: string): string {
switch (language) {
Expand Down Expand Up @@ -189,6 +190,7 @@ export default React.forwardRef<MonacoEditorHandle, MonacoEditorProps>(function
accessibilitySupport: 'off',
tabSize: 2,
automaticLayout: true,
theme: monacoEditorTheme,
...extraOptions,
});

Expand Down
8 changes: 7 additions & 1 deletion packages/toolpad-app/src/components/SplitPane.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,13 @@ const WrappedSplitPane = React.forwardRef<
// Some sensible defaults
minSize={20}
maxSize={-20}
paneStyle={{ display: 'block', ...props.paneStyle }}
paneStyle={{
display: 'block',
// Prevent the content from stretching the Panel out
minWidth: 0,
minHeight: 0,
...props.paneStyle,
}}
{...props}
/>
);
Expand Down
2 changes: 1 addition & 1 deletion packages/toolpad-app/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { RUNTIME_CONFIG_WINDOW_PROPERTY } from './constants';
*/

// These are inlined at build time
export type BuildEnvVars = Partial<Record<'TOOLPAD_TARGET' | 'TOOLPAD_DEMO', string>>;
export type BuildEnvVars = Record<'TOOLPAD_TARGET' | 'TOOLPAD_DEMO' | 'TOOLPAD_VERSION', string>;

// These are set at runtime and passed to the browser.
// Do not add secrets
Expand Down
15 changes: 15 additions & 0 deletions packages/toolpad-app/src/inspectorTheme.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { chromeDark, chromeLight, InspectorTheme } from 'react-inspector';

import theme from './theme';

const inspectorTheme: InspectorTheme = {
...(theme.palette.mode === 'dark' ? chromeDark : chromeLight),

BASE_BACKGROUND_COLOR: 'inherit',
TREENODE_FONT_FAMILY: 'inherit',
TREENODE_FONT_SIZE: 'inherit',
ARROW_FONT_SIZE: 'inherit',
TREENODE_LINE_HEIGHT: 'inherit',
};

export default inspectorTheme;
5 changes: 5 additions & 0 deletions packages/toolpad-app/src/monacoEditorTheme.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import theme from './theme';

const monacoEditorTheme: string = theme.palette.mode === 'dark' ? 'vs-dark' : 'vs';

export default monacoEditorTheme;
2 changes: 1 addition & 1 deletion packages/toolpad-app/src/server/evalExpression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export type Serializable =
| { [key: string]: Serializable }
| ((...args: Serializable[]) => Serializable);

function newJson(ctx: QuickJSContext, json: Serializable): QuickJSHandle {
export function newJson(ctx: QuickJSContext, json: Serializable): QuickJSHandle {
switch (typeof json) {
case 'string':
return ctx.newString(json);
Expand Down
Loading

0 comments on commit 9bdb7ec

Please sign in to comment.