few fixes + devfrontend v0

This commit is contained in:
Ruben Fiszel
2023-06-08 14:06:23 +02:00
parent aa3c7ef81a
commit e7846cc296
25 changed files with 10492 additions and 29 deletions
+34
View File
@@ -177,6 +177,19 @@
},
"query": "SELECT * from resource_type WHERE name = $1 AND (workspace_id = $2 OR workspace_id = 'admins')"
},
"03e9c9d8dd74c75b4608b49cad79f0a9572c7e8b48d8e373c0342b75b843d123": {
"describe": {
"columns": [],
"nullable": [],
"parameters": {
"Left": [
"Text",
"Text"
]
}
},
"query": "DELETE FROM usr_to_group WHERE usr = $1 AND workspace_id = $2"
},
"04a15674cf66f2822085e65ca33ee42b8e7f3f9d63ffac0585a12368d0322252": {
"describe": {
"columns": [
@@ -2582,6 +2595,27 @@
},
"query": "SELECT EXISTS(SELECT 1 FROM usr WHERE username = $1 AND workspace_id = $2)"
},
"62cd69e3dc0f8757db3481d078921f4722bbc93d52e05656b82cb42ba9803ef6": {
"describe": {
"columns": [
{
"name": "username",
"ordinal": 0,
"type_info": "Varchar"
}
],
"nullable": [
false
],
"parameters": {
"Left": [
"Text",
"Text"
]
}
},
"query": "DELETE FROM usr WHERE email = $1 AND workspace_id = $2 RETURNING username"
},
"637ead7701775609c772c9985450273b942202cdf9017ce6b5ba612e66ce3875": {
"describe": {
"columns": [
+10 -6
View File
@@ -16,16 +16,20 @@ export {
} from "https://deno.land/x/cliffy@v0.25.7/command/upgrade/mod.ts";
export { CompletionsCommand } from "https://deno.land/x/cliffy@v0.25.7/command/completions/mod.ts";
// std
export * as path from "https://deno.land/std@0.176.0/path/mod.ts";
export { ensureDir } from "https://deno.land/std@0.176.0/fs/ensure_dir.ts";
export * as path from "https://deno.land/std@0.184.0/path/mod.ts";
export { ensureDir } from "https://deno.land/std@0.184.0/fs/ensure_dir.ts";
export {
copy,
readAll,
readerFromStreamReader,
} from "https://deno.land/std@0.176.0/streams/mod.ts";
export { DelimiterStream } from "https://deno.land/std@0.176.0/streams/mod.ts";
export { iterateReader } from "https://deno.land/std@0.176.0/streams/iterate_reader.ts";
export { writeAllSync } from "https://deno.land/std@0.176.0/streams/mod.ts";
} from "https://deno.land/std@0.184.0/streams/mod.ts";
export { Application, Router } from "https://deno.land/x/oak@v12.5.0/mod.ts";
export { getPort } from "https://deno.land/x/getport@v2.1.2/mod.ts";
export { DelimiterStream } from "https://deno.land/std@0.184.0/streams/mod.ts";
export { iterateReader } from "https://deno.land/std@0.184.0/streams/iterate_reader.ts";
export { writeAllSync } from "https://deno.land/std@0.184.0/streams/mod.ts";
// other
export { getAvailablePort } from "https://deno.land/x/port@1.0.0/mod.ts";
+133
View File
@@ -0,0 +1,133 @@
import getPort from "https://deno.land/x/getport@v2.1.2/mod.ts";
import { Application, Command, Router, log, path } from "./deps.ts";
import { GlobalOptions } from "./types.ts";
import { ignoreF } from "./sync.ts";
import { requireLogin, resolveWorkspace } from "./context.ts";
async function dev(opts: GlobalOptions & { filter?: string }) {
const workspace = await resolveWorkspace(opts);
await requireLogin(opts);
log.info("Started dev mode");
let currentLastEdit: LastEdit | undefined = undefined;
const watcher = Deno.watchFs(opts.filter ?? ".");
const base = await Deno.realPath(".");
async function watchChanges() {
const ignore = await ignoreF();
for await (const event of watcher) {
log.debug(">>>> event", event);
// Example event: { kind: "create", paths: [ "/home/alice/deno/foo.txt" ] }
const paths = event.paths.filter(
(path) =>
path.endsWith(".go") ||
path.endsWith(".ts") ||
path.endsWith(".py") ||
path.endsWith(".sh")
);
const cpath = (await Deno.realPath(paths[0])).replace(
base + path.sep,
""
);
console.log("Detected change in " + cpath);
if (!ignore(cpath, false)) {
console.log("FOO");
const content = await Deno.readTextFile(cpath);
const splitted = cpath.split(".");
const wmPath = splitted[0];
const ext = splitted[splitted.length - 1];
const lang =
ext == "py"
? "python3"
: ext == "ts"
? "deno"
: ext == "go"
? "go"
: "bash";
currentLastEdit = { content, path: wmPath, language: lang };
broadcast_changes(currentLastEdit);
log.info("Updated " + wmPath);
}
}
}
type LastEdit = { content: string; path: string; language?: string };
const connectedClients = new Set<WebSocket>();
const app = new Application();
const router: Router = new Router();
// send a message to all connected clients
function broadcast_changes(lastEdit: LastEdit) {
for (const client of connectedClients.values()) {
client.send(JSON.stringify(lastEdit));
}
}
async function startApp() {
router.get("/ws", async (ctx) => {
const socket = await ctx.upgrade();
connectedClients.add(socket);
log.info(`New client connected`);
socket.onopen = () => {
if (currentLastEdit) {
broadcast_changes(currentLastEdit);
}
};
socket.onclose = () => {
connectedClients.delete(socket);
};
});
app.use(router.routes());
app.use(async (ctx) => {
const req = ctx.request;
const path = new URL(req.url).pathname;
if (path.startsWith("/api")) {
console.log("Proxying to " + workspace.remote + path);
const proxyRes = await fetch(
workspace.remote.substring(0, workspace.remote.length - 1) + path,
{
headers: {
Authorization: "Bearer " + workspace.token,
},
method: req.method,
body: await req.body().value,
}
);
ctx.response.body = proxyRes.body;
ctx.response.status = proxyRes.status;
} else {
await ctx.send({
root: `${Deno.cwd()}/`,
index: "public/index.html",
});
}
});
const port = getPort(3000);
console.log("Started dev server at http://localhost:" + port);
console.log(
"Dev server will automatically point to the last script edited locally"
);
await app.listen({ port });
}
await Promise.all([startApp(), watchChanges()]);
console.log("Stopped dev mode");
}
const command = new Command()
.description("Launch a dev server that will spawn a webserver with HMR")
.option(
"--filter <filter:string>",
"Filter paths givena glob pattern or path"
)
// deno-lint-ignore no-explicit-any
.action(dev as any);
export default command;
+2
View File
@@ -17,6 +17,7 @@ import pull from "./pull.ts";
import hub from "./hub.ts";
import folder from "./folder.ts";
import sync from "./sync.ts";
import dev from "./dev.ts";
import { tryResolveVersion } from "./context.ts";
import { GlobalOptions } from "./types.ts";
@@ -55,6 +56,7 @@ let command: any = new Command()
.command("variable", variable)
.command("hub", hub)
.command("folder", folder)
.command("dev", dev)
.command("sync", sync)
.command("version", "Show version information")
.action(async (opts) => {
+3 -3
View File
@@ -359,10 +359,10 @@ const isNotWmillFile = (p: string, isDirectory: boolean) => {
}
};
const isWhitelisted = (p: string) => {
export const isWhitelisted = (p: string) => {
return p == "./" || p == "" || p == "u" || p == "f" || p == "g";
};
async function ignoreF() {
export async function ignoreF() {
try {
const ignore: {
accepts(file: string): boolean;
@@ -736,7 +736,7 @@ async function push(
case "folder":
await FolderService.deleteFolder({
workspace: workspaceId,
name: change.path.split("/")[1],
name: change.path.split(path.sep)[1],
});
break;
case "resource":
+24
View File
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
+3
View File
@@ -0,0 +1,3 @@
{
"recommendations": ["svelte.svelte-vscode"]
}
+47
View File
@@ -0,0 +1,47 @@
# Svelte + TS + Vite
This template should help get you started developing with Svelte and TypeScript in Vite.
## Recommended IDE Setup
[VS Code](https://code.visualstudio.com/) + [Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode).
## Need an official Svelte framework?
Check out [SvelteKit](https://github.com/sveltejs/kit#readme), which is also powered by Vite. Deploy anywhere with its serverless-first approach and adapt to various platforms, with out of the box support for TypeScript, SCSS, and Less, and easily-added support for mdsvex, GraphQL, PostCSS, Tailwind CSS, and more.
## Technical considerations
**Why use this over SvelteKit?**
- It brings its own routing solution which might not be preferable for some users.
- It is first and foremost a framework that just happens to use Vite under the hood, not a Vite app.
This template contains as little as possible to get started with Vite + TypeScript + Svelte, while taking into account the developer experience with regards to HMR and intellisense. It demonstrates capabilities on par with the other `create-vite` templates and is a good starting point for beginners dipping their toes into a Vite + Svelte project.
Should you later need the extended capabilities and extensibility provided by SvelteKit, the template has been structured similarly to SvelteKit so that it is easy to migrate.
**Why `global.d.ts` instead of `compilerOptions.types` inside `jsconfig.json` or `tsconfig.json`?**
Setting `compilerOptions.types` shuts out all other types not explicitly listed in the configuration. Using triple-slash references keeps the default TypeScript setting of accepting type information from the entire workspace, while also adding `svelte` and `vite/client` type information.
**Why include `.vscode/extensions.json`?**
Other templates indirectly recommend extensions via the README, but this file allows VS Code to prompt the user to install the recommended extension upon opening the project.
**Why enable `allowJs` in the TS template?**
While `allowJs: false` would indeed prevent the use of `.js` files in the project, it does not prevent the use of JavaScript syntax in `.svelte` files. In addition, it would force `checkJs: false`, bringing the worst of both worlds: not being able to guarantee the entire codebase is TypeScript, and also having worse typechecking for the existing JavaScript. In addition, there are valid use cases in which a mixed codebase may be relevant.
**Why is HMR not preserving my local component state?**
HMR state preservation comes with a number of gotchas! It has been disabled by default in both `svelte-hmr` and `@sveltejs/vite-plugin-svelte` due to its often surprising behavior. You can read the details [here](https://github.com/rixo/svelte-hmr#svelte-hmr).
If you have state that's important to retain within a component, consider creating an external store which would not be replaced by HMR.
```ts
// store.ts
// An extremely simple external store
import { writable } from 'svelte/store'
export default writable(0)
```
+13
View File
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<!-- <link rel="stylesheet" href="/tailwind.css" /> -->
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Local Windmill</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
+3541
View File
File diff suppressed because it is too large Load Diff
+33
View File
@@ -0,0 +1,33 @@
{
"name": "devfrontend",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"check": "svelte-check --tsconfig ./tsconfig.json"
},
"devDependencies": {
"@rgossiaux/svelte-headlessui": "^1.0.2",
"@sveltejs/vite-plugin-svelte": "^2.0.4",
"@tailwindcss/forms": "^0.5.3",
"@tailwindcss/typography": "^0.5.9",
"@tsconfig/svelte": "^4.0.1",
"@zerodevx/svelte-toast": "^0.9.3",
"monaco-editor-workers": "^0.38.0",
"simple-svelte-autocomplete": "^2.5.2",
"svelte": "^3.58.0",
"svelte-awesome": "^3.2.0",
"svelte-check": "^3.3.1",
"svelte-highlight": "^7.3.0",
"svelte-popperjs": "^1.3.2",
"svelte-splitpanes": "^0.7.14",
"tslib": "^2.5.0",
"typescript": "^5.0.2",
"vite": "^4.3.9",
"windmill-components": "^1.109.8",
"windmill-parser-wasm": "file:../backend/parsers/windmill-parser-wasm/pkg"
}
}
+152
View File
@@ -0,0 +1,152 @@
<script lang="ts">
import TestJobLoader from 'windmill-components/components/TestJobLoader.svelte'
import Kbd from 'windmill-components/components/common/kbd/Kbd.svelte'
import LogPanel from 'windmill-components/components/scriptEditor/LogPanel.svelte'
import WindmillIcon from 'windmill-components/components/icons/WindmillIcon.svelte'
import SchemaForm from 'windmill-components/components/SchemaForm.svelte'
import Button from 'windmill-components/components/common/button/Button.svelte'
import { emptySchema, getModifierKey } from 'windmill-components/utils'
import { inferArgs } from 'windmill-components/infer'
import type { CompletedJob, Job, Preview } from 'windmill-components/package/gen';
import { Pane, Splitpanes} from 'svelte-splitpanes'
import { faPlay } from '@fortawesome/free-solid-svg-icons'
let testJobLoader: TestJobLoader
// Test args input
let args: Record<string, any> = {}
let isValid: boolean = true
// Test
let testIsLoading = false
let testJob: Job | undefined
let pastPreviews: CompletedJob[] = []
let lang = 'deno' as Preview.language
let validCode = true
let currentScript: {path: string, content: string} | undefined = undefined
let schema = emptySchema()
const href = window.location.href;
const indexQ = href.indexOf('?')
const searchParams = indexQ > -1 ? new URLSearchParams(href.substring(indexQ)) : undefined;
const port = searchParams?.get('port') || '3000';
const socket = new WebSocket(`ws://localhost:${port}/ws`);
// Connection opened
socket.addEventListener("open", (event) => {
socket.send("Hello Server!");
});
// Listen for messages
socket.addEventListener("message", (event) => {
let data: any | undefined = undefined;
try {
data = JSON.parse(event.data);
} catch {
console.log("Received invalid JSON: " + event.data);
return
}
replaceScript(data);
});
function runTest() {
testJobLoader.runPreview(path, code, lang, args,)
}
async function loadPastTests(): Promise<void> {
pastPreviews = await JobService.listCompletedJobs({
workspace: $workspaceStore!,
jobKinds: 'preview',
createdBy: $userStore?.username,
scriptPathExact: path
})
}
let lastPath = undefined
async function replaceScript({path, content, language}: {path: string, content: string, language: "deno" | "python3" | "go" | "bash"}) {
currentScript = {path, content}
if (lastPath !== path) {
schema = emptySchema()
}
try {
await inferArgs(language, content, schema )
schema = schema
lastPath = path
validCode = true
} catch (e) {
console.error(e)
validCode = false
}
}
</script>
<TestJobLoader
on:done={loadPastTests}
bind:this={testJobLoader}
bind:isLoading={testIsLoading}
bind:job={testJob}
/>
<main class="h-screen w-full">
<div class="flex flex-col h-full">
<div class="text-center w-full text-lg truncate py-1">{currentScript?.path ?? 'Not editing a script'}</div>
{#if !validCode}
<div class="text-center w-full text-lg truncate py-1 text-red-500">Invalid code</div>
{/if}
<div class="flex justify-center pt-1">
{#if testIsLoading}
<Button on:click={testJobLoader?.cancelJob} btnClasses="w-full" color="red" size="xs">
<WindmillIcon
white={true}
class="mr-2 text-white"
height="20px"
width="20px"
spin="fast"
/>
Cancel
</Button>
{:else}
<Button
color="dark"
on:click={() => {
runTest()
}}
btnClasses="w-full"
size="xs"
startIcon={{
icon: faPlay,
classes: 'animate-none'
}}
>
{#if testIsLoading}
Running
{:else}
Test&nbsp;<Kbd small>{getModifierKey()}</Kbd>
<Kbd small><span class="text-lg font-bold"></span></Kbd>
{/if}
</Button>
{/if}
</div>
<Splitpanes horizontal class="h-full">
<Pane size={33}>
<div class="px-2">
<div class="break-words relative font-sans">
<SchemaForm compact {schema} bind:args bind:isValid />
</div>
</div>
</Pane>
<Pane size={67}>
<LogPanel {lang} previewJob={testJob} {pastPreviews} previewIsLoading={testIsLoading} />
</Pane>
</Splitpanes>
</div>
</main>
+10
View File
@@ -0,0 +1,10 @@
<script lang="ts">
let count: number = 0
const increment = () => {
count += 1
}
</script>
<button on:click={increment}>
count is {count}
</button>
+8
View File
@@ -0,0 +1,8 @@
import "./tailwind.css";
import App from "./App.svelte";
const app = new App({
target: document.getElementById("app"),
});
export default app;
File diff suppressed because it is too large Load Diff
+2
View File
@@ -0,0 +1,2 @@
/// <reference types="svelte" />
/// <reference types="vite/client" />
+7
View File
@@ -0,0 +1,7 @@
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
export default {
// Consult https://svelte.dev/docs#compile-time-svelte-preprocess
// for more information about preprocessors
preprocess: vitePreprocess(),
}
+685
View File
@@ -0,0 +1,685 @@
const plugin = require("tailwindcss/plugin");
/** @type {import('tailwindcss').Config} */
const config = {
content: [
"./src/**/*.{html,js,svelte,ts}",
"./node_modules/windmill-components/package/**/*.{html,js,svelte,ts}",
],
safelist: [
"hljs",
"splitpanes__pane",
"splitpanes__splitter",
...(process.env.NODE_ENV === "production"
? [
{ pattern: /^m(\w?)-.*$/ },
{ pattern: /^p(\w?)-.*$/ },
{ pattern: /^rounded-.*$/ },
{ pattern: /^shadow-.*$/, variants: ["hover"] },
{ pattern: /^text-[^/]*$/, variants: ["hover", "active", "focus"] },
{ pattern: /^bg-[^/]*$/, variants: ["hover", "active", "focus"] },
{ pattern: /^border-[^/]*$/, variants: ["hover", "active", "focus"] },
{ pattern: /^ring-[^/]*$/, variants: ["hover", "active", "focus"] },
]
: []),
],
theme: {
colors: {
current: "currentcolor",
transparent: "transparent",
white: "#ffffff",
black: "#000000",
slate: {
50: "#f8fafc",
100: "#f1f5f9",
200: "#e2e8f0",
300: "#cbd5e1",
400: "#94a3b8",
500: "#64748b",
600: "#475569",
700: "#334155",
800: "#1e293b",
900: "#0f172a",
},
zinc: {
50: "#fafafa",
100: "#f4f4f5",
200: "#e4e4e7",
300: "#d4d4d8",
400: "#a1a1aa",
500: "#71717a",
600: "#52525b",
700: "#3f3f46",
800: "#27272a",
900: "#18181b",
},
neutral: {
50: "#fafafa",
100: "#f5f5f5",
200: "#e5e5e5",
300: "#d4d4d4",
400: "#a3a3a3",
500: "#737373",
600: "#525252",
700: "#404040",
800: "#262626",
900: "#171717",
},
stone: {
50: "#fafaf9",
100: "#f5f5f4",
200: "#e7e5e4",
300: "#d6d3d1",
400: "#a8a29e",
500: "#78716c",
600: "#57534e",
700: "#44403c",
800: "#292524",
900: "#1c1917",
},
orange: {
50: "#fff7ed",
100: "#ffedd5",
200: "#fed7aa",
300: "#fdba74",
400: "#fb923c",
500: "#f97316",
600: "#ea580c",
700: "#c2410c",
800: "#9a3412",
900: "#7c2d12",
},
amber: {
50: "#fffbeb",
100: "#fef3c7",
200: "#fde68a",
300: "#fcd34d",
400: "#fbbf24",
500: "#f59e0b",
600: "#d97706",
700: "#b45309",
800: "#92400e",
900: "#78350f",
},
lime: {
50: "#f7fee7",
100: "#ecfccb",
200: "#d9f99d",
300: "#bef264",
400: "#a3e635",
500: "#84cc16",
600: "#65a30d",
700: "#4d7c0f",
800: "#3f6212",
900: "#365314",
},
emerald: {
50: "#ecfdf5",
100: "#d1fae5",
200: "#a7f3d0",
300: "#6ee7b7",
400: "#34d399",
500: "#10b981",
600: "#059669",
700: "#047857",
800: "#065f46",
900: "#064e3b",
},
teal: {
50: "#f0fdfa",
100: "#ccfbf1",
200: "#99f6e4",
300: "#5eead4",
400: "#2dd4bf",
500: "#14b8a6",
600: "#0d9488",
700: "#0f766e",
800: "#115e59",
900: "#134e4a",
},
cyan: {
50: "#ecfeff",
100: "#cffafe",
200: "#a5f3fc",
300: "#67e8f9",
400: "#22d3ee",
500: "#06b6d4",
600: "#0891b2",
700: "#0e7490",
800: "#155e75",
900: "#164e63",
},
sky: {
50: "#f0f9ff",
100: "#e0f2fe",
200: "#bae6fd",
300: "#7dd3fc",
400: "#38bdf8",
500: "#0ea5e9",
600: "#0284c7",
700: "#0369a1",
800: "#075985",
900: "#0c4a6e",
},
violet: {
50: "#f5f3ff",
100: "#ede9fe",
200: "#ddd6fe",
300: "#c4b5fd",
400: "#a78bfa",
500: "#8b5cf6",
600: "#7c3aed",
700: "#6d28d9",
800: "#5b21b6",
900: "#4c1d95",
},
purple: {
50: "#faf5ff",
100: "#f3e8ff",
200: "#e9d5ff",
300: "#d8b4fe",
400: "#c084fc",
500: "#a855f7",
600: "#9333ea",
700: "#7e22ce",
800: "#6b21a8",
900: "#581c87",
},
fuchsia: {
50: "#fdf4ff",
100: "#fae8ff",
200: "#f5d0fe",
300: "#f0abfc",
400: "#e879f9",
500: "#d946ef",
600: "#c026d3",
700: "#a21caf",
800: "#86198f",
900: "#701a75",
},
pink: {
50: "#fdf2f8",
100: "#fce7f3",
200: "#fbcfe8",
300: "#f9a8d4",
400: "#f472b6",
500: "#ec4899",
600: "#db2777",
700: "#be185d",
800: "#9d174d",
900: "#831843",
},
rose: {
50: "#fff1f2",
100: "#ffe4e6",
200: "#fecdd3",
300: "#fda4af",
400: "#fb7185",
500: "#f43f5e",
600: "#e11d48",
700: "#be123c",
800: "#9f1239",
900: "#881337",
},
gray: {
50: "#f9fafb",
100: "#f3f4f6",
200: "#e5e7eb",
300: "#d1d5db",
400: "#9ca3af",
500: "#6b7280",
600: "#4b5563",
700: "#374151",
800: "#1f2937",
900: "#111827",
},
red: {
50: "#fef2f2",
100: "#fee2e2",
200: "#fecaca",
300: "#fca5a5",
400: "#f87171",
500: "#ef4444",
600: "#dc2626",
700: "#b91c1c",
800: "#991b1b",
900: "#7f1d1d",
},
orange: {
100: "#ffedd5",
200: "#ffedd5",
300: "#FDC089",
400: "#fb923c",
500: "#f97316",
600: "#ea580c",
700: "#c2410c",
800: "#c2410c",
},
yellow: {
50: "#fefce8",
100: "#fef9c3",
200: "#fef08a",
300: "#fde047",
400: "#facc15",
500: "#eab308",
600: "#ca8a04",
700: "#a16207",
800: "#854d0e",
900: "#713f12",
},
green: {
50: "#f0fdf4",
100: "#dcfce7",
200: "#bbf7d0",
300: "#86efac",
400: "#4ade80",
500: "#22c55e",
600: "#16a34a",
700: "#15803d",
800: "#166534",
900: "#14532d",
},
blue: {
50: "#eff6ff",
100: "#dbeafe",
200: "#bfdbfe",
300: "#93c5fd",
400: "#60a5fa",
500: "#3b82f6",
600: "#2563eb",
700: "#1d4ed8",
800: "#1e40af",
900: "#1e3a8a",
},
indigo: {
50: "#eef2ff",
100: "#e0e7ff",
200: "#c7d2fe",
300: "#a5b4fc",
400: "#818cf8",
500: "#6366f1",
600: "#4f46e5",
700: "#4338ca",
800: "#3730a3",
900: "#312e81",
},
frost: {
100: "#dfe6ee",
200: "#bfcdde",
300: "#9eb3cd",
400: "#7e9abd",
500: "#5e81ac",
600: "#4b678a",
700: "#384d67",
800: "#263445",
900: "#131a22",
},
},
fontFamily: {
// add double quotes if there is space in font name
main: ["Inter", "sans-serif"],
mono: [
"ui-monospace",
"SFMono-Regular",
"Menlo",
"Monaco",
"Consolas",
'"Liberation Mono"',
'"Courier New"',
"monospace",
],
},
extend: {
maxHeight: {
"1/2": "50vh",
"2/3": "66vh",
"3/4": "75vh",
},
minWidth: {
"1/4": "25%",
"1/3": "33%",
"1/2": "50%",
"2/3": "66%",
"3/4": "75%",
},
minHeight: {
"1/2": "50vh",
},
height: {
"2/3": "66vh",
},
transitionProperty: {
height: "height",
},
fontSize: {
"2xs": "0.7rem",
},
screens: {
fhd: "1900px",
qhd: "2500px",
"4k": "3800px",
},
animation: {
"spin-counter-clockwise": "spin-counter-clockwise 1s linear infinite",
},
keyframes: {
"spin-counter-clockwise": {
to: { transform: "rotate(-360deg)" },
},
},
},
},
plugins: [
require("@tailwindcss/forms"),
require("@tailwindcss/typography"),
plugin(({ addBase, addComponents, addUtilities, theme }) => {
addBase({
html: {
fontFamily: theme("fontFamily.main"),
fontSize: theme("fontSize.base"),
fontWeight: theme("fontWeight.normal"),
color: theme("colors.gray.900"),
[`@media (min-width: ${theme("screens.qhd")})`]: {
fontSize: theme("fontSize.lg"),
},
},
h1: {
fontSize: "24px",
fontWeight: theme("fontWeight.extrabold"),
lineHeight: "1.05",
color: theme("colors.gray.800"),
[`@media (min-width: ${theme("screens.lg")})`]: {
fontSize: "26px",
},
[`@media (min-width: ${theme("screens.fhd")})`]: {
fontSize: "29px",
},
[`@media (min-width: ${theme("screens.qhd")})`]: {
fontSize: "34px",
},
},
h2: {
fontSize: "20px",
fontWeight: theme("fontWeight.extrabold"),
lineHeight: "1.1",
color: theme("colors.gray.700"),
[`@media (min-width: ${theme("screens.fhd")})`]: {
fontSize: "22px",
},
[`@media (min-width: ${theme("screens.qhd")})`]: {
fontSize: "25px",
},
},
mark: {
backgroundColor: theme("colors.yellow.200"),
borderRadius: theme("borderRadius.sm"),
},
h3: {
fontSize: "18px",
fontWeight: theme("fontWeight.bold"),
lineHeight: "1.2",
color: theme("colors.gray.600"),
[`@media (min-width: ${theme("screens.fhd")})`]: {
fontSize: "20px",
},
[`@media (min-width: ${theme("screens.qhd")})`]: {
fontSize: "22px",
},
},
h4: {
fontSize: "18px",
fontWeight: theme("fontWeight.semibold"),
lineHeight: "1.3",
color: theme("colors.gray.600"),
[`@media (min-width: ${theme("screens.qhd")})`]: {
fontSize: "20px",
},
},
h5: {
fontSize: "16px",
fontWeight: theme("fontWeight.semibold"),
lineHeight: "1.5",
color: theme("colors.gray.600"),
[`@media (min-width: ${theme("screens.qhd")})`]: {
fontSize: "18px",
},
},
h6: {
fontSize: "16px",
fontWeight: theme("fontWeight.medium"),
lineHeight: "1.5",
color: theme("colors.gray.600"),
[`@media (min-width: ${theme("screens.qhd")})`]: {
fontSize: "18px",
},
},
button: {
fontWeight: theme("fontWeight.semibold"),
},
a: {
color: theme("colors.blue.500"),
},
'input:not(.windmillapp),input[type="text"]:not(.windmillapp),input[type="email"]:not(.windmillapp),input[type="url"]:not(.windmillapp),input[type="password"]:not(.windmillapp),input[type="number"]:not(.windmillapp),input[type="date"]:not(.windmillapp),input[type="datetime-local"]:not(.windmillapp),input[type="month"]:not(.windmillapp),input[type="search"]:not(.windmillapp),input[type="tel"]:not(.windmillapp),input[type="time"]:not(.windmillapp),input[type="week"]:not(.windmillapp),textarea:not(.windmillapp):not(.monaco-mouse-cursor-text),select:not(.windmillapp)':
{
display: "block",
fontSize: theme("fontSize.sm"),
width: "100%",
padding: `${theme("spacing.1")} ${theme("spacing.2")}`,
border: `1px solid ${theme("colors.gray.300")}`,
borderRadius: theme("borderRadius.md"),
"&:focus": {
"--tw-ring-color": theme("colors.indigo.100"),
"--tw-ring-offset-shadow":
"var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)",
"--tw-ring-shadow":
"var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color)",
boxShadow:
"var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000)",
},
"&:disabled,[disabled]": {
backgroundColor: theme("colors.gray.100") + " !important",
},
},
"button:disabled,button[disabled=true],a:disabled,a[disabled=true]": {
pointerEvents: "none",
cursor: "default",
filter: "grayscale(1)",
},
"pre code.hljs": {
padding: "0px !important",
fontFamily: theme("fontFamily.mono"),
fontSize: theme("fontSize.sm") + " !important",
lineHeight: theme("lineHeight.4") + " !important",
},
".h1-textarea": {
fontSize: "24px !important",
fontWeight: `${theme("fontWeight.extrabold")} !important`,
lineHeight: "1.05 !important",
color: theme("!colors.gray.800"),
[`@media (min-width: ${theme("screens.lg")})`]: {
fontSize: "26px !important",
},
[`@media (min-width: ${theme("screens.fhd")})`]: {
fontSize: "29px !important",
},
[`@media (min-width: ${theme("screens.qhd")})`]: {
fontSize: "34px !important",
},
},
".h3-textarea": {
fontSize: "18px !important",
fontWeight: `${theme("fontWeight.bold")} !important`,
lineHeight: "1.2 !important",
color: theme("!colors.gray.600"),
[`@media (min-width: ${theme("screens.fhd")})`]: {
fontSize: "20px !important",
},
[`@media (min-width: ${theme("screens.qhd")})`]: {
fontSize: "22px !important",
},
},
".p-textarea": {
fontSize: "16px !important",
fontWeight: `${theme("fontWeight.normal")} !important`,
lineHeight: "1.5 !important",
color: theme("!colors.gray.600"),
[`@media (min-width: ${theme("screens.fhd")})`]: {
fontSize: "18px !important",
},
[`@media (min-width: ${theme("screens.qhd")})`]: {
fontSize: "20px !important",
},
},
});
addComponents({
".table-custom": {
"& th": {
paddingTop: theme("spacing.3"),
paddingRight: theme("spacing.1"),
paddingLeft: theme("spacing.1"),
paddingBottom: theme("spacing.3"),
fontSize: theme("fontSize.sm"),
textAlign: "left",
fontWeight: theme("fontWeight.semibold"),
color: theme("colors.gray.900"),
textTransform: "capitalize",
},
"& td": {
paddingLeft: theme("spacing.1"),
paddingRight: theme("spacing.1"),
paddingTop: theme("spacing.2"),
paddingBottom: theme("spacing.2"),
fontSize: theme("fontSize.sm"),
color: theme("colors.gray.700"),
},
"& tbody > :not([hidden]) ~ :not([hidden])": {
borderTop: `1px solid ${theme("colors.gray.200")}`,
},
"& tbody > tr:hover": {
backgroundColor: theme("colors.gray.50"),
},
},
".commit-hash": {
fontSize: theme("fontSize.2xs"),
color: theme("colors.gray.500"),
backgroundColor: theme("colors.gray.200"),
fontFamily: theme("fontFamily.mono"),
},
".input-error": {
borderColor: `${theme("colors.red.500")} !important`,
},
".box": {
borderWidth: "1px",
borderRadius: theme("borderRadius.sm"),
boxShadow: theme("boxShadow.sm"),
padding: theme("spacing.4"),
},
".animate-skeleton": {
animation: theme("animation.pulse"),
backgroundColor: theme("colors.blue.100"),
borderRadius: theme("borderRadius.DEFAULT"),
},
".text-black-gradient": {
color: "transparent",
backgroundClip: "text",
backgroundImage: `linear-gradient(to right, ${theme(
"colors.black"
)}, ${theme("colors.gray.600")})`,
},
".splitpanes__pane": {
backgroundColor: theme("colors.white") + " !important",
overflow: "auto !important",
},
".splitpanes__splitter": {
backgroundColor: theme("colors.gray.300") + " !important",
margin: "0 !important",
border: "none !important",
"&::after": {
backgroundColor: "#3f83f850 !important",
margin: "0 !important",
transform: "none !important",
zIndex: "1001 !important",
transition: "opacity 200ms !important",
opacity: "0",
"--splitter-hover-size": "5px",
"--splitter-hover-adjustment": "-2px",
},
"&:hover::after": {
opacity: "1",
},
},
".splitpanes--vertical>.splitpanes__splitter": {
width: "1px !important",
"&::before": {
left: "1px !important",
width: "0px !important",
marginLeft: "0 !important",
},
"&::after": {
top: "0 !important",
height: "100% !important",
left: "var(--splitter-hover-adjustment) !important",
width: "var(--splitter-hover-size) !important",
},
},
".splitpanes--horizontal>.splitpanes__splitter": {
height: "1px !important",
"&::before": {
top: "1px !important",
height: "0px !important",
marginTop: "0 !important",
},
"&::after": {
top: "var(--splitter-hover-adjustment) !important",
height: "var(--splitter-hover-size) !important",
left: "0 !important",
width: "100% !important",
},
},
});
addUtilities({
".separator": {
backgroundColor: "#ddd !important",
},
".center-center": {
display: "flex",
justifyContent: "center",
alignItems: "center",
},
".ellipsize": {
overflow: "hidden",
whiteSpace: "nowrap",
textOverflow: "ellipsis",
},
/** Set the '-webkit-line-clamp' property to the desired number of lines.
*
* Eg.: `class="ellipsize-multi-line [-webkit-line-clamp:3]"`
*/
".ellipsize-multi-line": {
display: "-webkit-box",
"-webkit-box-orient": "vertical",
overflow: "hidden",
},
".disabled": {
pointerEvents: "none",
cursor: "default",
filter: "grayscale(1)",
},
".scrollbar-hidden": {
"-ms-overflow-style": "none",
"scrollbar-width": "none",
"&::-webkit-scrollbar": {
display: "none",
width: "0px",
},
},
});
}),
],
darkMode: "class",
};
module.exports = config;
+20
View File
@@ -0,0 +1,20 @@
{
"extends": "@tsconfig/svelte/tsconfig.json",
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
"resolveJsonModule": true,
/**
* Typecheck JS in `.svelte` and `.js` files by default.
* Disable checkJs if you'd like to use dynamic types in JS.
* Note that setting allowJs false does not prevent the use
* of JS in `.svelte` files.
*/
"allowJs": true,
"checkJs": true,
"isolatedModules": true
},
"include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.js", "src/**/*.svelte"],
"references": [{ "path": "./tsconfig.node.json" }]
}
+9
View File
@@ -0,0 +1,9 @@
{
"compilerOptions": {
"composite": true,
"skipLibCheck": true,
"module": "ESNext",
"moduleResolution": "bundler"
},
"include": ["vite.config.ts"]
}
+7
View File
@@ -0,0 +1,7 @@
import { defineConfig } from 'vite'
import { svelte } from '@sveltejs/vite-plugin-svelte'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [svelte()],
})
+54
View File
@@ -112,6 +112,21 @@
"svelte": "./dist/index.js"
},
"./assets/app.css": "./package/assets/app.css",
"./components/TestJobLoader.svelte": {
"types": "./package/components/TestJobLoader.svelte.d.ts",
"svelte": "./package/components/TestJobLoader.svelte",
"default": "./package/components/TestJobLoader.svelte"
},
"./components/common/kbd/Kbd.svelte": {
"types": "./package/components/common/kbd/Kbd.svelte.d.ts",
"svelte": "./package/components/common/kbd/Kbd.svelte",
"default": "./package/components/common/kbd/Kbd.svelte"
},
"./components/icons/WindmillIcon.svelte": {
"types": "./package/components/icons/WindmillIcon.d.ts",
"svelte": "./package/components/icons/WindmillIcon.svelte",
"default": "./package/components/icons/WindmillIcon.svelte"
},
"./components/IconedResourceType.svelte": {
"types": "./package/components/IconedResourceType.svelte.d.ts",
"svelte": "./package/components/IconedResourceType.svelte",
@@ -177,15 +192,33 @@
"svelte": "./package/components/SchemaViewer.svelte",
"default": "./package/components/SchemaViewer.svelte"
},
"./components/SchemaForm.svelte": {
"types": "./package/components/SchemaForm.svelte.d.ts",
"svelte": "./package/components/SchemaForm.svelte",
"default": "./package/components/SchemaForm.svelte"
},
"./components/SchemaEditor.svelte": {
"types": "./package/components/SchemaEditor.svelte.d.ts",
"svelte": "./package/components/SchemaEditor.svelte",
"default": "./package/components/SchemaEditor.svelte"
},
"./components/scriptEditor/LogPanel.svelte": {
"types": "./package/components/scriptEditor/LogPanel.svelte.d.ts",
"svelte": "./package/components/scriptEditor/LogPanel.svelte",
"default": "./package/components/scriptEditor/LogPanel.svelte"
},
"./common": {
"types": "./package/common.d.ts",
"default": "./package/common.js"
},
"./utils": {
"types": "./package/utils.d.ts",
"default": "./package/utils.js"
},
"./infer": {
"types": "./package/infer.d.ts",
"default": "./package/infer.js"
},
"./stores": {
"types": "./package/stores.d.ts",
"default": "./package/stores.js"
@@ -219,6 +252,21 @@
"components/IconedResourceType.svelte": [
"./package/components/IconedResourceType.svelte.d.ts"
],
"components/TestJobLoader.svelte": [
"./package/components/TestJobLoader.svelte.d.ts"
],
"components/SchemaForm.svelte": [
"./package/components/SchemaForm.svelte.d.ts"
],
"components/icons/WindmillIcon.svelte": [
"./package/components/icons/WindmillIcon.svelte.d.ts"
],
"components/scriptEditor/LogPanel.svelte": [
"./package/components/scriptEditor/LogPanel.svelte.d.ts"
],
"components/common/kbd/Kbd.svelte": [
"./package/components/common/kbd/Kbd.svelte.d.ts"
],
"components/common/drawer/Drawer.svelte": [
"./package/components/common/drawer/Drawer.svelte.d.ts"
],
@@ -258,6 +306,12 @@
"components/SchemaEditor.svelte": [
"./package/components/SchemaEditor.svelte.d.ts"
],
"utils": [
"./package/utils.d.ts"
],
"infer": [
"./package/infer.d.ts"
],
"common": [
"./package/common.d.ts"
],
@@ -92,6 +92,12 @@
$: computeDefaultValue(value, inputCat, defaultValue)
$: defaultValue != undefined && handleDefaultValueChange()
function handleDefaultValueChange() {
value = defaultValue
}
function evalValueToRaw() {
rawValue = inputCat === 'object' ? JSON.stringify(value, null, 2) : undefined
}
@@ -98,31 +98,15 @@
}
export async function inferSchema(code: string, nlang?: 'go' | 'bash' | 'python3' | 'deno') {
schema = schema ?? emptySchema()
let isDefault: string[] = []
Object.entries(args).forEach(([k, v]) => {
if (schema.properties?.[k]?.default == v) {
isDefault.push(k)
}
})
let nschema = schema ?? emptySchema()
try {
await inferArgs(nlang ?? lang, code, schema)
await inferArgs(nlang ?? lang, code, nschema)
validCode = true
schema = nschema
} catch (e) {
validCode = false
}
schema = schema
isDefault
.filter((key) => schema.properties[key] != undefined)
.forEach((key) => (args[key] = schema.properties[key].default))
for (const key of Object.keys(args)) {
if (schema.properties[key] == undefined) {
delete args[key]
}
}
}
onMount(() => {
@@ -94,7 +94,7 @@
on:change={() => {
outputs?.result.set([...(value ?? [])])
}}
options={items}
options={Array.isArray(items) ? items : []}
placeholder={resolvedConfig.placeholder}
allowUserOptions={resolvedConfig.create}
on:open={() => {