mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-17 16:02:25 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
39f0752525 | ||
|
|
1ee78da4bf | ||
|
|
451b6bb22d | ||
|
|
0a336467d8 | ||
|
|
250237793b | ||
|
|
632bd18a2e | ||
|
|
de4f5e3015 | ||
|
|
99f7828ebb | ||
|
|
5a8fa1d724 | ||
|
|
49835ca6ca | ||
|
|
43459ce03a | ||
|
|
e23c3fad62 | ||
|
|
dffd5f7f7d | ||
|
|
55340029db | ||
|
|
c9ef2c8e97 | ||
|
|
3cf4f00dca | ||
|
|
2afdb66e75 | ||
|
|
6705b6706f | ||
|
|
c4282a0656 | ||
|
|
6c9e32af10 | ||
|
|
5416254aa1 | ||
|
|
11b81e3d9d | ||
|
|
0cce27636d | ||
|
|
e0857c7178 | ||
|
|
0eb96ded5f | ||
|
|
be90b3e219 | ||
|
|
fbd9b87c0f | ||
|
|
75d96baf50 | ||
|
|
58adf6ad2d | ||
|
|
ad698768e8 | ||
|
|
ecea507670 | ||
|
|
acfe6325a1 | ||
|
|
3bd461ffa1 | ||
|
|
c09f078928 | ||
|
|
f88efc2380 | ||
|
|
2aa40c413e | ||
|
|
9363e6d05f | ||
|
|
0be8982ddc | ||
|
|
969699ce47 | ||
|
|
b9924d01d5 | ||
|
|
35fed96cd3 | ||
|
|
bcc94badbd | ||
|
|
2021b8f86a | ||
|
|
b626e52324 | ||
|
|
7a68cc76c2 | ||
|
|
b424c61e95 | ||
|
|
41bf933fb7 | ||
|
|
f00545f169 | ||
|
|
95a898a5d5 | ||
|
|
1d0807f542 | ||
|
|
527183874c | ||
|
|
0d5c2e5dd7 | ||
|
|
599399870f | ||
|
|
955a980703 | ||
|
|
7eccebf5da | ||
|
|
1719c2689e | ||
|
|
2b99789077 | ||
|
|
fd1c456fad | ||
|
|
3c4b8377ed | ||
|
|
36129fb470 | ||
|
|
e779f96386 | ||
|
|
df33b281e8 |
@@ -1,5 +1,100 @@
|
||||
# Changelog
|
||||
|
||||
## [1.381.0](https://github.com/windmill-labs/windmill/compare/v1.380.0...v1.381.0) (2024-08-16)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add env to refresh cgroup readings ([#4250](https://github.com/windmill-labs/windmill/issues/4250)) ([e23c3fa](https://github.com/windmill-labs/windmill/commit/e23c3fad628cc718314472f3cb53c0f257c4c9e5))
|
||||
* cache common hub scripts in image ([#4249](https://github.com/windmill-labs/windmill/issues/4249)) ([99f7828](https://github.com/windmill-labs/windmill/commit/99f7828ebb5fddf799afb52af7214ba4119e57b9))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **cli:** add inject and define options ([dffd5f7](https://github.com/windmill-labs/windmill/commit/dffd5f7f7d5c84624953bf8c778b14586a14e2d4))
|
||||
* **frontend:** improve UI for email triggers ([#4243](https://github.com/windmill-labs/windmill/issues/4243)) ([6c9e32a](https://github.com/windmill-labs/windmill/commit/6c9e32af104a897e5c2a5b41867d2ffbbacc8acb))
|
||||
* improve password field lifetime incorrectly recycled too early ([5a8fa1d](https://github.com/windmill-labs/windmill/commit/5a8fa1d72487ac2a29dca8833b8c92b8cac3726e))
|
||||
* improve row update of aggrid table actions II ([3cf4f00](https://github.com/windmill-labs/windmill/commit/3cf4f00dca677fc592d5dde8a7b8fdcac5f08e0a))
|
||||
* **typescript-client:** add runFlow and runFlowAsync ([c9ef2c8](https://github.com/windmill-labs/windmill/commit/c9ef2c8e97bdecb16b9a54805f1c90523e3b406f))
|
||||
* workspace specific default tags do not override step level custom tags ([49835ca](https://github.com/windmill-labs/windmill/commit/49835ca6ca65e569ea2915b2ef4f7ce1c4988cae))
|
||||
|
||||
## [1.380.0](https://github.com/windmill-labs/windmill/compare/v1.379.4...v1.380.0) (2024-08-14)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* opt-in job args in audit logs ([#4241](https://github.com/windmill-labs/windmill/issues/4241)) ([0cce276](https://github.com/windmill-labs/windmill/commit/0cce27636d128972730427a33b7be954d00210dc))
|
||||
* recoverable error handlers ([e0857c7](https://github.com/windmill-labs/windmill/commit/e0857c7178ac9657173e9ed597d072130e41fe47))
|
||||
* togglable continue on disapproval/timeout of approvals ([be90b3e](https://github.com/windmill-labs/windmill/commit/be90b3e2192cdae88e38fd7e269ad8abc8f7c054))
|
||||
|
||||
## [1.379.4](https://github.com/windmill-labs/windmill/compare/v1.379.3...v1.379.4) (2024-08-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add missing change for better key renewal ([#4237](https://github.com/windmill-labs/windmill/issues/4237)) ([f88efc2](https://github.com/windmill-labs/windmill/commit/f88efc2380bf5b055b2633b24cb94fc46e6cdca5))
|
||||
* fix transformer issue after proxy change for apps ([ad69876](https://github.com/windmill-labs/windmill/commit/ad698768e8fdbcc4a90f138f74ceee20d2d68a9b))
|
||||
* handle time with tz col type in pg ([#4239](https://github.com/windmill-labs/windmill/issues/4239)) ([c09f078](https://github.com/windmill-labs/windmill/commit/c09f078928fb9f4b52df641580505d98bb728aa0))
|
||||
* use job timeout for snowflake timeout ([#4240](https://github.com/windmill-labs/windmill/issues/4240)) ([3bd461f](https://github.com/windmill-labs/windmill/commit/3bd461ffa1fcbe19c9007b1b15970be21cff08ef))
|
||||
|
||||
## [1.379.3](https://github.com/windmill-labs/windmill/compare/v1.379.2...v1.379.3) (2024-08-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* improve scrolling performance of the runs page ([0be8982](https://github.com/windmill-labs/windmill/commit/0be8982ddc263b76dab2c87cb6fa63e21effd58c))
|
||||
|
||||
## [1.379.2](https://github.com/windmill-labs/windmill/compare/v1.379.1...v1.379.2) (2024-08-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add fetch connection limits to bun type fetcher ([b9924d0](https://github.com/windmill-labs/windmill/commit/b9924d01d54f6dfaf5d719c13a38bb3dccbfe3b9))
|
||||
* extend step_id being returned as part of the error of every languages ([bcc94ba](https://github.com/windmill-labs/windmill/commit/bcc94badbd848b6838dd0e353c3a30e7a1889ff8))
|
||||
* **frontend:** date input is more flexible and accept default html format as a fallback ([b424c61](https://github.com/windmill-labs/windmill/commit/b424c61e95e3cc9213d4d3efbe4173857d4e80fd))
|
||||
* improve logviewer behavior when job is loading ([7a68cc7](https://github.com/windmill-labs/windmill/commit/7a68cc76c2d5d7a66f080afdfcb6c5cd09fc25b5))
|
||||
|
||||
## [1.379.1](https://github.com/windmill-labs/windmill/compare/v1.379.0...v1.379.1) (2024-08-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add an option to disable bundling globally ([f00545f](https://github.com/windmill-labs/windmill/commit/f00545f1691c5107d1103f89bf68fdc3915ddd82))
|
||||
* **apps:** improve tanstack table handling of objects ([1d0807f](https://github.com/windmill-labs/windmill/commit/1d0807f54238c8d8d242e3e5534c6d0868b3172b))
|
||||
|
||||
## [1.379.0](https://github.com/windmill-labs/windmill/compare/v1.378.0...v1.379.0) (2024-08-13)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* embeddable apps using jwt ([#4229](https://github.com/windmill-labs/windmill/issues/4229)) ([fd1c456](https://github.com/windmill-labs/windmill/commit/fd1c456fad16229112d9329e7c7eb9d60561efc0))
|
||||
* **frontend:** group fields are mutable ([955a980](https://github.com/windmill-labs/windmill/commit/955a980703362b78bf24a47ec348878d7aac94e3))
|
||||
* **frontend:** improve display of waiting jobs + schedule filter + suspended jobs on runs page ([2b99789](https://github.com/windmill-labs/windmill/commit/2b99789077b66991902819b26b140e2681a51344))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **apps:** type hints for results are automatically widened ([1719c26](https://github.com/windmill-labs/windmill/commit/1719c2689e2cdcbf4e88a5133e0d6c5626c8d6d9))
|
||||
* support NODE_PATH ([3c4b837](https://github.com/windmill-labs/windmill/commit/3c4b8377ed4689704cb7baaee13e8acaa91e8611))
|
||||
|
||||
## [1.378.0](https://github.com/windmill-labs/windmill/compare/v1.377.1...v1.378.0) (2024-08-12)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **cli:** add customerBundler support ([70d1e6c](https://github.com/windmill-labs/windmill/commit/70d1e6c7208b59890ad4d15cad28b1f32d7970d2))
|
||||
* windmill embed ([d56a956](https://github.com/windmill-labs/windmill/commit/d56a956b9a471cca4042f43ba4e3922e42f121f1))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* allow user resources in app to work within iframes ([6272c9f](https://github.com/windmill-labs/windmill/commit/6272c9ff41e5359f38ae13e879aa615da0fb0d09))
|
||||
* **frontend:** improve default id of the components of the topbar ([#4222](https://github.com/windmill-labs/windmill/issues/4222)) ([7115a35](https://github.com/windmill-labs/windmill/commit/7115a3577947c52aa72edcc134dcb8e739208df0))
|
||||
* **frontend:** support plus sign in emails format fields [#4223](https://github.com/windmill-labs/windmill/issues/4223) ([c0853ea](https://github.com/windmill-labs/windmill/commit/c0853eafc9f9bf6d454c6a70800c98c75c9d8ba3))
|
||||
* **frontend:** user resource picker for app use lightweight component ([c03c0f6](https://github.com/windmill-labs/windmill/commit/c03c0f61726e7b6196fe5222c44d4d635e907b20))
|
||||
* improve default value handling for date & date-time in apps ([e779f96](https://github.com/windmill-labs/windmill/commit/e779f963869fcb22d73f02b6a806e3fdac978959))
|
||||
* improve license key ui ([#4220](https://github.com/windmill-labs/windmill/issues/4220)) ([0655803](https://github.com/windmill-labs/windmill/commit/06558038601d6f78b234519d4b48f229a2bf9fc8))
|
||||
|
||||
## [1.377.1](https://github.com/windmill-labs/windmill/compare/v1.377.0...v1.377.1) (2024-08-08)
|
||||
|
||||
|
||||
|
||||
+15
-5
@@ -59,7 +59,9 @@ ARG features=""
|
||||
|
||||
COPY --from=planner /windmill/recipe.json recipe.json
|
||||
|
||||
RUN apt-get update && apt-get install -y libxml2-dev libxmlsec1-dev clang libclang-dev cmake
|
||||
RUN apt-get update && apt-get install -y libxml2-dev=2.9.* libxmlsec1-dev=1.2.* clang=1:14.0-55.* libclang-dev=1:14.0-55.* cmake=3.25.* && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN --mount=type=cache,target=/usr/local/cargo/registry \
|
||||
--mount=type=cache,target=$SCCACHE_DIR,sharing=locked \
|
||||
@@ -92,14 +94,17 @@ ARG WITH_HELM=true
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y ca-certificates wget curl git jq unzip build-essential unixodbc xmlsec1 software-properties-common \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
|
||||
RUN if [ "$WITH_POWERSHELL" = "true" ]; then \
|
||||
if [ "$TARGETPLATFORM" = "linux/amd64" ]; then apt-get update -y && apt install libicu-dev -y && wget -O 'pwsh.deb' "https://github.com/PowerShell/PowerShell/releases/download/v${POWERSHELL_VERSION}/powershell_${POWERSHELL_DEB_VERSION}.deb_amd64.deb" && \
|
||||
if [ "$TARGETPLATFORM" = "linux/amd64" ]; then apt-get update -y && apt install libicu-dev -y && wget -O 'pwsh.deb' "https://github.com/PowerShell/PowerShell/releases/download/v${POWERSHELL_VERSION}/powershell_${POWERSHELL_DEB_VERSION}.deb_amd64.deb" && apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/* && \
|
||||
dpkg --install 'pwsh.deb' && \
|
||||
rm 'pwsh.deb'; \
|
||||
elif [ "$TARGETPLATFORM" = "linux/arm64" ]; then apt-get update -y && apt install libicu-dev -y && wget -O powershell.tar.gz "https://github.com/PowerShell/PowerShell/releases/download/v${POWERSHELL_VERSION}/powershell-${POWERSHELL_VERSION}-linux-arm64.tar.gz" && \
|
||||
elif [ "$TARGETPLATFORM" = "linux/arm64" ]; then apt-get update -y && apt install libicu-dev -y && wget -O powershell.tar.gz "https://github.com/PowerShell/PowerShell/releases/download/v${POWERSHELL_VERSION}/powershell-${POWERSHELL_VERSION}-linux-arm64.tar.gz" && apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/* && \
|
||||
mkdir -p /opt/microsoft/powershell/7 && \
|
||||
tar zxf powershell.tar.gz -C /opt/microsoft/powershell/7 && \
|
||||
chmod +x /opt/microsoft/powershell/7/pwsh && \
|
||||
@@ -143,7 +148,8 @@ ENV PATH="${PATH}:/usr/local/go/bin"
|
||||
ENV GO_PATH=/usr/local/go/bin/go
|
||||
|
||||
RUN curl -sL https://deb.nodesource.com/setup_20.x | bash -
|
||||
RUN apt-get -y update && apt-get install -y curl nodejs awscli
|
||||
RUN apt-get -y update && apt-get install -y curl nodejs awscli && apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# go build is slower the first time it is ran, so we prewarm it in the build
|
||||
RUN mkdir -p /tmp/gobuildwarm && cd /tmp/gobuildwarm && go mod init gobuildwarm && printf "package foo\nimport (\"fmt\")\nfunc main() { fmt.Println(42) }" > warm.go && go mod tidy && go build -x && rm -rf /tmp/gobuildwarm
|
||||
@@ -169,7 +175,11 @@ WORKDIR ${APP}
|
||||
|
||||
RUN ln -s ${APP}/windmill /usr/local/bin/windmill
|
||||
|
||||
RUN windmill cache
|
||||
COPY ./frontend/src/lib/hubPaths.json ${APP}/hubPaths.json
|
||||
|
||||
RUN windmill cache ${APP}/hubPaths.json
|
||||
|
||||
RUN rm ${APP}/hubPaths.json
|
||||
|
||||
EXPOSE 8000
|
||||
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
export default {
|
||||
plugins: {
|
||||
"postcss-import": {},
|
||||
"tailwindcss/nesting": "postcss-nesting",
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
};
|
||||
@@ -1,950 +0,0 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
export default {
|
||||
content: [],
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: [],
|
||||
};
|
||||
|
||||
const plugin = require("tailwindcss/plugin");
|
||||
|
||||
const lightTheme = {
|
||||
surface: "#ffffff",
|
||||
surfaceSecondary: "#f3f4f6",
|
||||
surfaceHover: "#e5e7eb",
|
||||
surfaceDisabled: "#f9fafb",
|
||||
surfaceSelected: "#d1d5db",
|
||||
|
||||
textPrimary: "#2d3748",
|
||||
textSecondary: "#4a5568",
|
||||
textTertiary: "#505c70",
|
||||
textDisabled: "#a0aec0",
|
||||
|
||||
border: "#ddd",
|
||||
borderHover: "#ccc",
|
||||
};
|
||||
|
||||
const lightThemeRgb = makeRgb(lightTheme);
|
||||
|
||||
const darkTheme = {
|
||||
surface: "#2e3440",
|
||||
surfaceSecondary: "#3b4252",
|
||||
surfaceHover: "#454F64",
|
||||
surfaceDisabled: "#212732",
|
||||
surfaceSelected: "#434c5e",
|
||||
|
||||
textPrimary: "#EEEEEE",
|
||||
textSecondary: "#C2C9D1",
|
||||
textTertiary: "#A8AEB7",
|
||||
textDisabled: "#989DA5",
|
||||
|
||||
border: "#3e4c60",
|
||||
borderHover: "#3e4c60",
|
||||
};
|
||||
|
||||
const darkThemeRgb = makeRgb(darkTheme);
|
||||
|
||||
function makeRgb(theme) {
|
||||
return Object.fromEntries(
|
||||
Object.entries(theme).map(([key, value]) => {
|
||||
if (typeof value === "string" && value.startsWith("#")) {
|
||||
return [key, hexToRgb(value)];
|
||||
}
|
||||
|
||||
return [key, value];
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
function hexToRgb(hex) {
|
||||
// Remove '#' symbol from the beginning of the hex value
|
||||
hex = hex.replace("#", "");
|
||||
|
||||
// Convert the hex value to decimal
|
||||
const r = parseInt(hex.substring(0, 2), 16);
|
||||
const g = parseInt(hex.substring(2, 4), 16);
|
||||
const b = parseInt(hex.substring(4, 6), 16);
|
||||
|
||||
// Return the RGB string format
|
||||
return `${r} ${g} ${b}`;
|
||||
}
|
||||
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
const config = {
|
||||
content: [
|
||||
"./src/**/*.{html,js,svelte,ts}",
|
||||
"./node_modules/windmill-components/**/*.{html,js,svelte,ts}",
|
||||
],
|
||||
safelist: [
|
||||
"hljs",
|
||||
"splitpanes__pane",
|
||||
"splitpanes__splitter",
|
||||
"wm-tab",
|
||||
"autocomplete-list",
|
||||
"autocomplete-list-item",
|
||||
"autocomplete-list-item-create",
|
||||
"selected",
|
||||
"wm-tab-selected",
|
||||
...(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: {
|
||||
50: "#f5f7fa",
|
||||
100: "#eaeef4",
|
||||
200: "#cfd9e8",
|
||||
300: "#a6bad3",
|
||||
400: "#7594bb",
|
||||
500: "#5e81ac",
|
||||
600: "#415f88",
|
||||
700: "#364d6e",
|
||||
800: "#2f425d",
|
||||
900: "#2b394f",
|
||||
950: "#1d2534",
|
||||
},
|
||||
marine: {
|
||||
50: "#E9E9F4",
|
||||
100: "#859AC7",
|
||||
200: "#586F9E",
|
||||
300: "#4A5F8A",
|
||||
400: "#394A6D",
|
||||
500: "#323F5B",
|
||||
},
|
||||
surface: "rgb(var(--color-surface) / <alpha-value>)",
|
||||
"surface-secondary":
|
||||
"rgb(var(--color-surface-secondary) / <alpha-value>)",
|
||||
"surface-hover": "rgb(var(--color-surface-hover) / <alpha-value>)",
|
||||
"surface-disabled": "rgb(var(--color-surface-disabled) / <alpha-value>)",
|
||||
"surface-selected": "rgb(var(--color-surface-selected) / <alpha-value>)",
|
||||
|
||||
primary: "rgb(var(--color-text-primary) / <alpha-value>)",
|
||||
secondary: "rgb(var(--color-text-secondary) / <alpha-value>)",
|
||||
tertiary: "rgb(var(--color-text-tertiary) / <alpha-value>)",
|
||||
disabled: "rgb(var(--color-text-disabled) / <alpha-value>)",
|
||||
|
||||
"surface-inverse": "rgb(var(--color-surface-inverse) / <alpha-value>)",
|
||||
"surface-secondary-inverse":
|
||||
"rgb(var(--color-surface-secondary-inverse) / <alpha-value>)",
|
||||
"surface-hover-inverse":
|
||||
"rgb(var(--color-surface-hover-inverse) / <alpha-value>)",
|
||||
"surface-disabled-inverse":
|
||||
"rgb(var(--color-surface-disabled-inverse) / <alpha-value>)",
|
||||
"surface-selected-inverse":
|
||||
"rgb(var(--color-surface-selected-inverse) / <alpha-value>)",
|
||||
|
||||
"primary-inverse":
|
||||
"rgb(var(--color-text-primary-inverse) / <alpha-value>)",
|
||||
"secondary-inverse":
|
||||
"rgb(var(--color-text-secondary-inverse) / <alpha-value>)",
|
||||
"tertiary-inverse":
|
||||
"rgb(var(--color-text-tertiary-inverse) / <alpha-value>)",
|
||||
"disabled-inverse":
|
||||
"rgb(var(--color-text-disabled-inverse) / <alpha-value>)",
|
||||
},
|
||||
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: {
|
||||
border: {
|
||||
color: "red",
|
||||
},
|
||||
borderRadius: {
|
||||
component: "0.250rem",
|
||||
},
|
||||
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"),
|
||||
// scopedPreflightStyles({
|
||||
// isolationStrategy: isolateInsideOfContainer("#windmill-app"),
|
||||
// }),
|
||||
plugin(({ addBase, addComponents, addUtilities, theme }) => {
|
||||
addBase({
|
||||
fontFamily: theme("fontFamily.main"),
|
||||
fontSize: theme("fontSize.base"),
|
||||
fontWeight: theme("fontWeight.normal"),
|
||||
|
||||
backgroundColor: "rgb(var(--color-surface) / <alpha-value>)",
|
||||
color: lightTheme.textPrimary,
|
||||
"--color-surface": lightThemeRgb.surface,
|
||||
"--color-surface-secondary": lightThemeRgb.surfaceSecondary,
|
||||
"--color-surface-hover": lightThemeRgb.surfaceHover,
|
||||
"--color-surface-disabled": lightThemeRgb.surfaceDisabled,
|
||||
"--color-surface-selected": lightThemeRgb.surfaceSelected,
|
||||
|
||||
"--color-text-primary": lightThemeRgb.textPrimary,
|
||||
"--color-text-secondary": lightThemeRgb.textSecondary,
|
||||
"--color-text-tertiary": lightThemeRgb.textTertiary,
|
||||
"--color-text-disabled": lightThemeRgb.textDisabled,
|
||||
|
||||
"--color-surface-inverse": darkThemeRgb.surface,
|
||||
"--color-surface-secondary-inverse": darkThemeRgb.surfaceSecondary,
|
||||
"--color-surface-hover-inverse": darkThemeRgb.surfaceHover,
|
||||
"--color-surface-disabled-inverse": darkThemeRgb.surfaceDisabled,
|
||||
"--color-surface-selected-inverse": darkThemeRgb.surfaceSelected,
|
||||
|
||||
"--color-text-primary-inverse": darkThemeRgb.textPrimary,
|
||||
"--color-text-secondary-inverse": darkThemeRgb.textSecondary,
|
||||
"--color-text-tertiary-inverse": darkThemeRgb.textTertiary,
|
||||
"--color-text-disabled-inverse": darkThemeRgb.textDisabled,
|
||||
|
||||
"--color-border": lightThemeRgb.border,
|
||||
"--color-border-hover": lightThemeRgb.borderHover,
|
||||
|
||||
"--vscode-editorSuggestWidget-background": "#f3f3f3",
|
||||
"--vscode-editorHoverWidget-foreground": "#616161",
|
||||
"--vscode-editorHoverWidget-border": "#c8c8c8",
|
||||
"--vscode-editorHoverWidget-statusBarBackground": "#e7e7e7",
|
||||
"--vscode-editorSuggestWidget-foreground": "#eeffff",
|
||||
"--vscode-editorSuggestWidget-highlightForeground": "#80cbc4",
|
||||
"--vscode-editorSuggestWidget-selectedBackground":
|
||||
"rgba(0, 0, 0, 0.31)",
|
||||
|
||||
[`@media (min-width: ${theme("screens.qhd")})`]: {
|
||||
fontSize: theme("fontSize.lg"),
|
||||
},
|
||||
|
||||
"&.dark": {
|
||||
backgroundColor: darkTheme.surface,
|
||||
color: darkTheme.textPrimary,
|
||||
|
||||
"--color-surface": darkThemeRgb.surface,
|
||||
"--color-surface-secondary": darkThemeRgb.surfaceSecondary,
|
||||
"--color-surface-hover": darkThemeRgb.surfaceHover,
|
||||
"--color-surface-disabled": darkThemeRgb.surfaceDisabled,
|
||||
"--color-surface-selected": darkThemeRgb.surfaceSelected,
|
||||
|
||||
"--color-text-primary": darkThemeRgb.textPrimary,
|
||||
"--color-text-secondary": darkThemeRgb.textSecondary,
|
||||
"--color-text-tertiary": darkThemeRgb.textTertiary,
|
||||
"--color-text-disabled": darkThemeRgb.textDisabled,
|
||||
|
||||
"--color-surface-inverse": lightThemeRgb.surface,
|
||||
"--color-surface-secondary-inverse": lightThemeRgb.surfaceSecondary,
|
||||
"--color-surface-hover-inverse": lightThemeRgb.surfaceHover,
|
||||
"--color-surface-disabled-inverse": lightThemeRgb.surfaceDisabled,
|
||||
"--color-surface-selected-inverse": lightThemeRgb.surfaceSelected,
|
||||
|
||||
"--color-text-primary-inverse": lightThemeRgb.textPrimary,
|
||||
"--color-text-secondary-inverse": lightThemeRgb.textSecondary,
|
||||
"--color-text-tertiary-inverse": lightThemeRgb.textTertiary,
|
||||
"--color-text-disabled-inverse": lightThemeRgb.textDisabled,
|
||||
|
||||
"--color-border": darkThemeRgb.border,
|
||||
"--color-border-hover": darkThemeRgb.borderHover,
|
||||
|
||||
"--vscode-editorSuggestWidget-background": "#252526",
|
||||
"--vscode-editorHoverWidget-foreground": "#cccccc",
|
||||
"--vscode-editorHoverWidget-border": "#454545",
|
||||
"--vscode-editorHoverWidget-statusBarBackground": "#2c2c2d",
|
||||
},
|
||||
|
||||
h1: {
|
||||
fontSize: "24px",
|
||||
fontWeight: theme("fontWeight.extrabold"),
|
||||
lineHeight: "1.05",
|
||||
[`@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",
|
||||
[`@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",
|
||||
[`@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",
|
||||
[`@media (min-width: ${theme("screens.qhd")})`]: {
|
||||
fontSize: "20px",
|
||||
},
|
||||
},
|
||||
h5: {
|
||||
fontSize: "16px",
|
||||
fontWeight: theme("fontWeight.semibold"),
|
||||
lineHeight: "1.5",
|
||||
[`@media (min-width: ${theme("screens.qhd")})`]: {
|
||||
fontSize: "18px",
|
||||
},
|
||||
},
|
||||
h6: {
|
||||
fontSize: "16px",
|
||||
fontWeight: theme("fontWeight.medium"),
|
||||
lineHeight: "1.5",
|
||||
[`@media (min-width: ${theme("screens.qhd")})`]: {
|
||||
fontSize: "18px",
|
||||
},
|
||||
},
|
||||
button: {
|
||||
fontWeight: theme("fontWeight.semibold"),
|
||||
},
|
||||
a: {
|
||||
color: theme("colors.blue.500"),
|
||||
},
|
||||
".dark input::placeholder": {
|
||||
color: theme("colors.gray.400"),
|
||||
},
|
||||
"[type='checkbox']:checked": {
|
||||
backgroundImage: `url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='black' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");`,
|
||||
},
|
||||
".dark [type='checkbox']:checked": {
|
||||
backgroundImage: `url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");`,
|
||||
},
|
||||
'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"),
|
||||
boxShadow: theme("boxShadow.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.frost.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",
|
||||
".dark &": {
|
||||
backgroundColor: theme("colors.gray.700") + " !important",
|
||||
},
|
||||
},
|
||||
},
|
||||
'.dark input:not(.windmillapp),.dark input[type="text"]:not(.windmillapp),.dark input[type="email"]:not(.windmillapp),.dark input[type="url"]:not(.windmillapp),.dark input[type="password"]:not(.windmillapp),.dark input[type="number"]:not(.windmillapp),.dark input[type="date"]:not(.windmillapp),.dark input[type="datetime-local"]:not(.windmillapp),.dark input[type="month"]:not(.windmillapp),.dark input[type="search"]:not(.windmillapp),.dark input[type="tel"]:not(.windmillapp),.dark input[type="time"]:not(.windmillapp),.dark input[type="week"]:not(.windmillapp),.dark textarea:not(.windmillapp):not(.monaco-mouse-cursor-text),.dark select:not(.windmillapp)':
|
||||
{
|
||||
backgroundColor: theme("colors.gray.700"),
|
||||
color: theme("colors.gray.200"),
|
||||
borderColor: theme("colors.gray.600"),
|
||||
"&:focus": {
|
||||
"--tw-ring-color": theme("colors.frost.700"),
|
||||
},
|
||||
},
|
||||
|
||||
"button:disabled,button[disabled=true],a:disabled,a[disabled=true]": {
|
||||
pointerEvents: "none",
|
||||
cursor: "default",
|
||||
opacity: "0.90",
|
||||
},
|
||||
"pre code.hljs": {
|
||||
padding: "0px !important",
|
||||
fontFamily: theme("fontFamily.mono"),
|
||||
fontSize: theme("fontSize.xs") + " !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",
|
||||
},
|
||||
},
|
||||
input: {
|
||||
backgroundColor: theme("colors.surface-secondary") + " !important",
|
||||
},
|
||||
textarea: {
|
||||
backgroundColor: theme("colors.surface-secondary") + " !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",
|
||||
},
|
||||
".dark & th": {
|
||||
color: theme("colors.gray.200"),
|
||||
},
|
||||
"& 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"),
|
||||
},
|
||||
".dark & td ": {
|
||||
color: theme("colors.gray.200"),
|
||||
},
|
||||
"& tbody > :not([hidden]) ~ :not([hidden])": {
|
||||
borderTop: `1px solid ${theme("colors.gray.200")}`,
|
||||
},
|
||||
".dark & tbody > :not([hidden]) ~ :not([hidden])": {
|
||||
borderTop: `1px solid ${theme("colors.gray.700")}`,
|
||||
},
|
||||
"& tbody > tr:hover": {
|
||||
backgroundColor: theme("colors.gray.50"),
|
||||
},
|
||||
".dark & tbody > tr:hover": {
|
||||
backgroundColor: theme("colors.gray.800"),
|
||||
},
|
||||
},
|
||||
".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: lightTheme.surface + " !important",
|
||||
overflow: "auto !important",
|
||||
},
|
||||
".dark .splitpanes__pane": {
|
||||
backgroundColor: darkTheme.surface + " !important",
|
||||
overflow: "auto !important",
|
||||
},
|
||||
".splitpanes__splitter": {
|
||||
backgroundColor: lightTheme.border + " !important",
|
||||
margin: "0 !important",
|
||||
border: "none !important",
|
||||
"&::after": {
|
||||
backgroundColor: lightTheme.border + " !important",
|
||||
margin: "0 !important",
|
||||
transform: "none !important",
|
||||
transition: "opacity 200ms !important",
|
||||
opacity: "0",
|
||||
"--splitter-hover-size": "5px",
|
||||
"--splitter-hover-adjustment": "-2px",
|
||||
},
|
||||
"&:hover::after": {
|
||||
opacity: "1",
|
||||
zIndex: "1001 !important",
|
||||
},
|
||||
},
|
||||
".dark .splitpanes__splitter": {
|
||||
backgroundColor: darkTheme.border + " !important",
|
||||
"&::after": {
|
||||
backgroundColor: darkTheme.border + " !important",
|
||||
},
|
||||
},
|
||||
".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",
|
||||
},
|
||||
},
|
||||
// Windmill Tab classes
|
||||
|
||||
".wm-tab-active": {
|
||||
borderColor: darkTheme.border,
|
||||
color: lightTheme.textPrimary,
|
||||
},
|
||||
|
||||
".dark .wm-tab-active": {
|
||||
borderColor: lightTheme.border,
|
||||
color: darkTheme.textPrimary,
|
||||
},
|
||||
});
|
||||
|
||||
addUtilities({
|
||||
".separator": {
|
||||
backgroundColor: `${lightTheme.border} !important`,
|
||||
},
|
||||
".dark .separator": {
|
||||
backgroundColor: `${darkTheme.border} !important`,
|
||||
},
|
||||
".center-center": {
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
},
|
||||
".inner-border": {
|
||||
boxShadow: `inset 0 0 0 1px ${lightTheme.border}`,
|
||||
},
|
||||
".dark .inner-border": {
|
||||
boxShadow: `inset 0 0 0 1px ${darkTheme.border}`,
|
||||
},
|
||||
".z5000": {
|
||||
zIndex: "5000 !important",
|
||||
},
|
||||
".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",
|
||||
important: ".windmill-app",
|
||||
};
|
||||
|
||||
module.exports = config;
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT coalesce(COUNT(*) FILTER(WHERE suspend = 0 AND running = false), 0) as \"database_length!\", coalesce(COUNT(*) FILTER(WHERE suspend > 0), 0) as \"suspended!\" FROM queue WHERE (workspace_id = $1 OR $2) AND scheduled_for <= now()",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "database_length!",
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "suspended!",
|
||||
"type_info": "Int8"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Bool"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
null,
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "28a878c59b6d52f42d315eabb34c96133b69542b01232295c26cc9e093c372f9"
|
||||
}
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "bool",
|
||||
"name": "?column?",
|
||||
"type_info": "Bool"
|
||||
}
|
||||
],
|
||||
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT coalesce(COUNT(*), 0) as \"database_length!\" FROM queue WHERE (workspace_id = $1 OR $2) AND scheduled_for <= now() AND running = false",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "database_length!",
|
||||
"type_info": "Int8"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Bool"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "8481d1bd91b7d23f946b4cf0d312acfc0ed4973309b4860e93882a37a21a0bd0"
|
||||
}
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "DELETE FROM variable WHERE expires_at IS NOT NULL AND expires_at > now() RETURNING path",
|
||||
"query": "DELETE FROM variable WHERE expires_at IS NOT NULL AND expires_at < now() RETURNING path",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -16,5 +16,5 @@
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "bac12eff366f6b76f97d1a44041e0c1b5fdcb2c4205c1c1c0026b71ce404f089"
|
||||
"hash": "b0c2f470f7d2df567eca550db1ae638fcb554622b61a5f4fb6b6696f6283516a"
|
||||
}
|
||||
+2
-2
@@ -18,8 +18,8 @@
|
||||
"Left": []
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
true
|
||||
true,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "b3dbdfb50ee8118bdaed3164b210cb549a34b96554ae1872355b90304f5dcb76"
|
||||
|
||||
+8
-2
@@ -1,12 +1,17 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT coalesce(COUNT(*), 0) as \"database_length!\" FROM completed_job WHERE workspace_id = $1",
|
||||
"query": "SELECT coalesce(COUNT(*), 0) as \"database_length!\", null::bigint as suspended FROM completed_job WHERE workspace_id = $1",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "database_length!",
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "suspended",
|
||||
"type_info": "Int8"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
@@ -15,8 +20,9 @@
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
null,
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "f5681df5935ec753f4a6d9ab8b927bbf890f0b4fe2de16dc764b24f24d7bbdca"
|
||||
"hash": "bf04a017bc55f6e1f5f25f697b3c4828611591c76dd32541735095c010d6cdf2"
|
||||
}
|
||||
+5
-3
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE worker_ping SET ping_at = now(), jobs_executed = $1, custom_tags = $2, occupancy_rate = $3, memory_usage = $4, wm_memory_usage = $5, current_job_id = NULL, current_job_workspace_id = NULL WHERE worker = $6",
|
||||
"query": "UPDATE worker_ping SET ping_at = now(), jobs_executed = $1, custom_tags = $2, occupancy_rate = $3, memory_usage = $4, wm_memory_usage = $5, current_job_id = NULL, current_job_workspace_id = NULL, vcpus = COALESCE($7, vcpus), memory = COALESCE($8, memory) WHERE worker = $6",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
@@ -10,10 +10,12 @@
|
||||
"Float4",
|
||||
"Int8",
|
||||
"Int8",
|
||||
"Text"
|
||||
"Text",
|
||||
"Int8",
|
||||
"Int8"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "4398bc6f701dcba647a259ec2d091a70938a3ecd7ff8a89277cc35d119e2bad4"
|
||||
"hash": "c1de24c68933ab35934395d74c5d2747b3da80c96e255ccf0c4e053206a9ad1b"
|
||||
}
|
||||
Generated
+139
-131
@@ -377,7 +377,7 @@ dependencies = [
|
||||
"arrow-schema",
|
||||
"chrono",
|
||||
"half",
|
||||
"indexmap 2.3.0",
|
||||
"indexmap 2.4.0",
|
||||
"lexical-core",
|
||||
"num",
|
||||
"serde",
|
||||
@@ -845,9 +845,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aws-sdk-sso"
|
||||
version = "1.37.0"
|
||||
version = "1.38.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1074e818fbe4f9169242d78448b15be8916a79daa38ea1231f2e2e10d993fcd2"
|
||||
checksum = "fca5e0b9fb285638f1007e9d961d963b9e504ab968fe5a3807cce94070bd0ce3"
|
||||
dependencies = [
|
||||
"aws-credential-types",
|
||||
"aws-runtime",
|
||||
@@ -867,9 +867,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aws-sdk-ssooidc"
|
||||
version = "1.38.0"
|
||||
version = "1.39.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29755c51e33fa3f678598f64324a169cf4b7d3c4865d2709d4308f53366a92a4"
|
||||
checksum = "bc3e48ec239bb734db029ceef83599f4c9b3ce5d25c961b5bcd3f031c15bed54"
|
||||
dependencies = [
|
||||
"aws-credential-types",
|
||||
"aws-runtime",
|
||||
@@ -889,9 +889,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aws-sdk-sts"
|
||||
version = "1.37.0"
|
||||
version = "1.38.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e52dc3fd7dfa6c01a69cf3903e00aa467261639138a05b06cd92314d2c8fb07"
|
||||
checksum = "ede095dfcc5c92b224813c24a82b65005a475c98d737e2726a898cf583e2e8bd"
|
||||
dependencies = [
|
||||
"aws-credential-types",
|
||||
"aws-runtime",
|
||||
@@ -985,9 +985,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aws-smithy-runtime"
|
||||
version = "1.6.2"
|
||||
version = "1.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce87155eba55e11768b8c1afa607f3e864ae82f03caf63258b37455b0ad02537"
|
||||
checksum = "0abbf454960d0db2ad12684a1640120e7557294b0ff8e2f11236290a1b293225"
|
||||
dependencies = [
|
||||
"aws-smithy-async",
|
||||
"aws-smithy-http",
|
||||
@@ -1029,9 +1029,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aws-smithy-types"
|
||||
version = "1.2.0"
|
||||
version = "1.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfe321a6b21f5d8eabd0ade9c55d3d0335f3c3157fc2b3e87f05f34b539e4df5"
|
||||
checksum = "6cee7cadb433c781d3299b916fbf620fea813bf38f49db282fb6858141a05cc8"
|
||||
dependencies = [
|
||||
"base64-simd 0.8.0",
|
||||
"bytes",
|
||||
@@ -1105,7 +1105,7 @@ dependencies = [
|
||||
"serde_urlencoded",
|
||||
"sync_wrapper 1.0.1",
|
||||
"tokio",
|
||||
"tower",
|
||||
"tower 0.4.13",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
@@ -1483,18 +1483,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.16.3"
|
||||
version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "102087e286b4677862ea56cf8fc58bb2cdfa8725c40ffb80fe3a008eb7f2fc83"
|
||||
checksum = "6fd4c6dcc3b0aea2f5c0b4b82c2b15fe39ddbc76041a310848f4706edf76bb31"
|
||||
dependencies = [
|
||||
"bytemuck_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck_derive"
|
||||
version = "1.7.0"
|
||||
version = "1.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ee891b04274a59bd38b412188e24b849617b2e45a0fd8d057deb63e7403761b"
|
||||
checksum = "0cc8b54b395f2fcfbb3d90c47b01c7f444d94d05bdeb775811dec868ac3bbc26"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1613,12 +1613,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.1.10"
|
||||
version = "1.1.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e9e8aabfac534be767c909e0690571677d49f41bd8465ae876fe043d52ba5292"
|
||||
checksum = "72db2f7947ecee9b03b510377e8bb9077afa27176fdbff55c51027e976fdcc48"
|
||||
dependencies = [
|
||||
"jobserver",
|
||||
"libc",
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1717,9 +1718,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.15"
|
||||
version = "4.5.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11d8838454fda655dafd3accb2b6e2bea645b9e4078abe84a22ceb947235c5cc"
|
||||
checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
@@ -1757,9 +1758,9 @@ checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
|
||||
|
||||
[[package]]
|
||||
name = "cmake"
|
||||
version = "0.1.50"
|
||||
version = "0.1.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130"
|
||||
checksum = "fb1e43aa7fd152b1f968787f7dbcdeb306d1867ff373c69955211876c053f91a"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
@@ -1952,9 +1953,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.12"
|
||||
version = "0.2.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"
|
||||
checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
@@ -2264,7 +2265,7 @@ dependencies = [
|
||||
"glob",
|
||||
"half",
|
||||
"hashbrown 0.14.5",
|
||||
"indexmap 2.3.0",
|
||||
"indexmap 2.4.0",
|
||||
"itertools 0.12.1",
|
||||
"log",
|
||||
"num_cpus",
|
||||
@@ -2433,7 +2434,7 @@ dependencies = [
|
||||
"datafusion-expr",
|
||||
"datafusion-physical-expr",
|
||||
"hashbrown 0.14.5",
|
||||
"indexmap 2.3.0",
|
||||
"indexmap 2.4.0",
|
||||
"itertools 0.12.1",
|
||||
"log",
|
||||
"regex-syntax 0.8.4",
|
||||
@@ -2462,7 +2463,7 @@ dependencies = [
|
||||
"half",
|
||||
"hashbrown 0.14.5",
|
||||
"hex",
|
||||
"indexmap 2.3.0",
|
||||
"indexmap 2.4.0",
|
||||
"itertools 0.12.1",
|
||||
"log",
|
||||
"paste",
|
||||
@@ -2506,7 +2507,7 @@ dependencies = [
|
||||
"futures",
|
||||
"half",
|
||||
"hashbrown 0.14.5",
|
||||
"indexmap 2.3.0",
|
||||
"indexmap 2.4.0",
|
||||
"itertools 0.12.1",
|
||||
"log",
|
||||
"once_cell",
|
||||
@@ -2664,7 +2665,7 @@ dependencies = [
|
||||
"tokio-rustls 0.26.0",
|
||||
"tokio-socks",
|
||||
"tokio-util",
|
||||
"tower",
|
||||
"tower 0.4.13",
|
||||
"tower-http",
|
||||
"tower-service",
|
||||
]
|
||||
@@ -3884,7 +3885,7 @@ dependencies = [
|
||||
"futures-sink",
|
||||
"futures-util",
|
||||
"http 0.2.12",
|
||||
"indexmap 2.3.0",
|
||||
"indexmap 2.4.0",
|
||||
"slab",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
@@ -3903,7 +3904,7 @@ dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"http 1.1.0",
|
||||
"indexmap 2.3.0",
|
||||
"indexmap 2.4.0",
|
||||
"slab",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
@@ -4284,7 +4285,7 @@ dependencies = [
|
||||
"pin-project-lite",
|
||||
"socket2 0.5.7",
|
||||
"tokio",
|
||||
"tower",
|
||||
"tower 0.4.13",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
]
|
||||
@@ -4357,9 +4358,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.3.0"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0"
|
||||
checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.14.5",
|
||||
@@ -4512,9 +4513,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.69"
|
||||
version = "0.3.70"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
|
||||
checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
@@ -4539,7 +4540,7 @@ version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ee7893dab2e44ae5f9d0173f26ff4aa327c10b01b06a72b52dd9405b628640d"
|
||||
dependencies = [
|
||||
"indexmap 2.3.0",
|
||||
"indexmap 2.4.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4659,9 +4660,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.155"
|
||||
version = "0.2.156"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
||||
checksum = "a5f43f184355eefb8d17fc948dbecf6c13be3c141f20d834ae842193a448c72a"
|
||||
|
||||
[[package]]
|
||||
name = "libgit2-sys"
|
||||
@@ -4726,9 +4727,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libz-sys"
|
||||
version = "1.1.18"
|
||||
version = "1.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c15da26e5af7e25c90b37a2d75cdbf940cf4a55316de9d84c679c9b8bfabf82e"
|
||||
checksum = "fdc53a7799a7496ebc9fd29f31f7df80e83c9bda5299768af5f9e59eeea74647"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
@@ -5053,6 +5054,16 @@ dependencies = [
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "minicov"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c71e683cd655513b99affab7d317deb690528255a0d5f717f1024093c12b169"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
@@ -5068,18 +5079,6 @@ dependencies = [
|
||||
"adler",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "1.0.2"
|
||||
@@ -5156,9 +5155,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mysql_async"
|
||||
version = "0.34.1"
|
||||
version = "0.34.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fbfe87d7e35cb72363326216cc1712b865d8d4f70abf3b2d2e6b251fb6b2f427"
|
||||
checksum = "a0b66e411c31265e879d9814d03721f2daa7ad07337b6308cb4bb0cde7e6fd47"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"crossbeam",
|
||||
@@ -5167,12 +5166,9 @@ dependencies = [
|
||||
"futures-sink",
|
||||
"futures-util",
|
||||
"keyed_priority_queue",
|
||||
"lazy_static",
|
||||
"lru",
|
||||
"mio 0.8.11",
|
||||
"mysql_common",
|
||||
"native-tls",
|
||||
"once_cell",
|
||||
"pem 3.0.4",
|
||||
"percent-encoding",
|
||||
"pin-project",
|
||||
@@ -5819,7 +5815,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db"
|
||||
dependencies = [
|
||||
"fixedbitset",
|
||||
"indexmap 2.3.0",
|
||||
"indexmap 2.4.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7470,9 +7466,9 @@ checksum = "a3f0bf26fd526d2a95683cd0f87bf103b8539e2ca1ef48ce002d67aad59aa0b4"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.206"
|
||||
version = "1.0.208"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b3e4cd94123dd520a128bcd11e34d9e9e423e7e3e50425cb1b4b1e3549d0284"
|
||||
checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
@@ -7511,9 +7507,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.206"
|
||||
version = "1.0.208"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fabfb6138d2383ea8208cf98ccf69cdfb1aff4088460681d84189aa259762f97"
|
||||
checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -7533,11 +7529,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.124"
|
||||
version = "1.0.125"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "66ad62847a56b3dba58cc891acd13884b9c61138d330c0d7b6181713d4fce38d"
|
||||
checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed"
|
||||
dependencies = [
|
||||
"indexmap 2.3.0",
|
||||
"indexmap 2.4.0",
|
||||
"itoa",
|
||||
"memchr",
|
||||
"ryu",
|
||||
@@ -7596,9 +7592,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_tokenstream"
|
||||
version = "0.2.1"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8790a7c3fe883e443eaa2af6f705952bc5d6e8671a220b9335c8cae92c037e74"
|
||||
checksum = "64060d864397305347a78851c51588fd283767e7e7589829e8121d65512340f1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -7641,7 +7637,7 @@ dependencies = [
|
||||
"chrono",
|
||||
"hex",
|
||||
"indexmap 1.9.3",
|
||||
"indexmap 2.3.0",
|
||||
"indexmap 2.4.0",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
@@ -7667,7 +7663,7 @@ version = "0.9.34+deprecated"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
|
||||
dependencies = [
|
||||
"indexmap 2.3.0",
|
||||
"indexmap 2.4.0",
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
@@ -8047,7 +8043,7 @@ dependencies = [
|
||||
"hashbrown 0.14.5",
|
||||
"hashlink",
|
||||
"hex",
|
||||
"indexmap 2.3.0",
|
||||
"indexmap 2.4.0",
|
||||
"log",
|
||||
"memchr",
|
||||
"once_cell",
|
||||
@@ -8424,7 +8420,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84b67e115ab136fe0eb03558bb0508ca7782eeb446a96d165508c48617e3fd94"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"indexmap 2.3.0",
|
||||
"indexmap 2.4.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"swc_cached",
|
||||
@@ -8575,7 +8571,7 @@ checksum = "d37dc505c92af56d0f77cf6f31a6ccd37ac40cad1e01ff77277e0b1c70e8f8ff"
|
||||
dependencies = [
|
||||
"better_scoped_tls",
|
||||
"bitflags 2.6.0",
|
||||
"indexmap 2.3.0",
|
||||
"indexmap 2.4.0",
|
||||
"once_cell",
|
||||
"phf",
|
||||
"rustc-hash 1.1.0",
|
||||
@@ -8644,7 +8640,7 @@ checksum = "446da32cac8299973aaf1d37496562bfd0c1e4f3c3ab5d0af6f07f42e8184102"
|
||||
dependencies = [
|
||||
"base64 0.21.7",
|
||||
"dashmap",
|
||||
"indexmap 2.3.0",
|
||||
"indexmap 2.4.0",
|
||||
"once_cell",
|
||||
"serde",
|
||||
"sha1",
|
||||
@@ -8683,7 +8679,7 @@ version = "0.130.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13e62b199454a576c5fdbd7e1bef8ab88a395427456d8a713d994b7d469833aa"
|
||||
dependencies = [
|
||||
"indexmap 2.3.0",
|
||||
"indexmap 2.4.0",
|
||||
"num_cpus",
|
||||
"once_cell",
|
||||
"rustc-hash 1.1.0",
|
||||
@@ -9273,7 +9269,7 @@ dependencies = [
|
||||
"backtrace",
|
||||
"bytes",
|
||||
"libc",
|
||||
"mio 1.0.2",
|
||||
"mio",
|
||||
"parking_lot",
|
||||
"pin-project-lite",
|
||||
"signal-hook-registry",
|
||||
@@ -9442,7 +9438,7 @@ version = "0.19.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
|
||||
dependencies = [
|
||||
"indexmap 2.3.0",
|
||||
"indexmap 2.4.0",
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
@@ -9455,7 +9451,7 @@ version = "0.21.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1"
|
||||
dependencies = [
|
||||
"indexmap 2.3.0",
|
||||
"indexmap 2.4.0",
|
||||
"toml_datetime",
|
||||
"winnow 0.5.40",
|
||||
]
|
||||
@@ -9466,7 +9462,7 @@ version = "0.22.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d"
|
||||
dependencies = [
|
||||
"indexmap 2.3.0",
|
||||
"indexmap 2.4.0",
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
@@ -9502,6 +9498,16 @@ dependencies = [
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "36b837f86b25d7c0d7988f00a54e74739be6477f2aac6201b8f429a7569991b7"
|
||||
dependencies = [
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower-cookies"
|
||||
version = "0.10.0"
|
||||
@@ -9542,15 +9548,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tower-layer"
|
||||
version = "0.3.2"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
|
||||
checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e"
|
||||
|
||||
[[package]]
|
||||
name = "tower-service"
|
||||
version = "0.3.2"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
|
||||
checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
@@ -10181,19 +10187,20 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.92"
|
||||
version = "0.2.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
|
||||
checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.92"
|
||||
version = "0.2.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
|
||||
checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
@@ -10206,9 +10213,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-futures"
|
||||
version = "0.4.42"
|
||||
version = "0.4.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0"
|
||||
checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
@@ -10218,9 +10225,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.92"
|
||||
version = "0.2.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
|
||||
checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
@@ -10228,9 +10235,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.92"
|
||||
version = "0.2.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
|
||||
checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -10241,18 +10248,19 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.92"
|
||||
version = "0.2.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
|
||||
checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-test"
|
||||
version = "0.3.42"
|
||||
version = "0.3.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9bf62a58e0780af3e852044583deee40983e5886da43a271dd772379987667b"
|
||||
checksum = "68497a05fb21143a08a7d24fc81763384a3072ee43c44e86aad1744d6adef9d9"
|
||||
dependencies = [
|
||||
"console_error_panic_hook",
|
||||
"js-sys",
|
||||
"minicov",
|
||||
"scoped-tls",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
@@ -10261,9 +10269,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-test-macro"
|
||||
version = "0.3.42"
|
||||
version = "0.3.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7f89739351a2e03cb94beb799d47fb2cac01759b40ec441f7de39b00cbf7ef0"
|
||||
checksum = "4b8220be1fa9e4c889b30fd207d4906657e7e90b12e0e6b0c8b8d8709f5de021"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -10294,9 +10302,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.69"
|
||||
version = "0.3.70"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef"
|
||||
checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
@@ -10401,7 +10409,7 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windmill"
|
||||
version = "1.377.1"
|
||||
version = "1.381.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum",
|
||||
@@ -10441,7 +10449,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-api"
|
||||
version = "1.377.1"
|
||||
version = "1.381.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"argon2",
|
||||
@@ -10470,7 +10478,7 @@ dependencies = [
|
||||
"hmac",
|
||||
"http 1.1.0",
|
||||
"hyper 1.4.1",
|
||||
"itertools 0.10.5",
|
||||
"itertools 0.13.0",
|
||||
"jsonwebtoken",
|
||||
"lazy_static",
|
||||
"magic-crypt",
|
||||
@@ -10504,7 +10512,7 @@ dependencies = [
|
||||
"tokio-native-tls",
|
||||
"tokio-tar",
|
||||
"tokio-util",
|
||||
"tower",
|
||||
"tower 0.5.0",
|
||||
"tower-cookies",
|
||||
"tower-http",
|
||||
"tracing",
|
||||
@@ -10525,7 +10533,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-api-client"
|
||||
version = "1.377.1"
|
||||
version = "1.381.0"
|
||||
dependencies = [
|
||||
"base64 0.21.7",
|
||||
"chrono",
|
||||
@@ -10543,7 +10551,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-audit"
|
||||
version = "1.377.1"
|
||||
version = "1.381.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"serde",
|
||||
@@ -10556,7 +10564,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-common"
|
||||
version = "1.377.1"
|
||||
version = "1.381.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-stream",
|
||||
@@ -10571,8 +10579,8 @@ dependencies = [
|
||||
"hex",
|
||||
"hmac",
|
||||
"hyper 1.4.1",
|
||||
"indexmap 2.3.0",
|
||||
"itertools 0.10.5",
|
||||
"indexmap 2.4.0",
|
||||
"itertools 0.13.0",
|
||||
"lazy_static",
|
||||
"magic-crypt",
|
||||
"mail-send",
|
||||
@@ -10597,7 +10605,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-git-sync"
|
||||
version = "1.377.1"
|
||||
version = "1.381.0"
|
||||
dependencies = [
|
||||
"regex",
|
||||
"rsmq_async",
|
||||
@@ -10612,7 +10620,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-indexer"
|
||||
version = "1.377.1"
|
||||
version = "1.381.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
@@ -10633,7 +10641,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser"
|
||||
version = "1.377.1"
|
||||
version = "1.381.0"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -10641,7 +10649,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-bash"
|
||||
version = "1.377.1"
|
||||
version = "1.381.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"lazy_static",
|
||||
@@ -10652,11 +10660,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-go"
|
||||
version = "1.377.1"
|
||||
version = "1.381.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"gosyn",
|
||||
"itertools 0.10.5",
|
||||
"itertools 0.13.0",
|
||||
"lazy_static",
|
||||
"regex",
|
||||
"windmill-parser",
|
||||
@@ -10664,7 +10672,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-graphql"
|
||||
version = "1.377.1"
|
||||
version = "1.381.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"lazy_static",
|
||||
@@ -10675,11 +10683,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-php"
|
||||
version = "1.377.1"
|
||||
version = "1.381.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"convert_case 0.6.0",
|
||||
"itertools 0.10.5",
|
||||
"itertools 0.13.0",
|
||||
"lazy_static",
|
||||
"php-parser-rs",
|
||||
"regex",
|
||||
@@ -10689,10 +10697,10 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-py"
|
||||
version = "1.377.1"
|
||||
version = "1.381.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"itertools 0.10.5",
|
||||
"itertools 0.13.0",
|
||||
"rustpython-parser",
|
||||
"serde_json",
|
||||
"windmill-parser",
|
||||
@@ -10700,11 +10708,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-py-imports"
|
||||
version = "1.377.1"
|
||||
version = "1.381.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-recursion",
|
||||
"itertools 0.10.5",
|
||||
"itertools 0.13.0",
|
||||
"lazy_static",
|
||||
"phf",
|
||||
"regex",
|
||||
@@ -10717,7 +10725,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-sql"
|
||||
version = "1.377.1"
|
||||
version = "1.381.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"lazy_static",
|
||||
@@ -10728,7 +10736,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-ts"
|
||||
version = "1.377.1"
|
||||
version = "1.381.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"convert_case 0.6.0",
|
||||
@@ -10747,7 +10755,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-wasm"
|
||||
version = "1.377.1"
|
||||
version = "1.381.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"getrandom 0.2.15",
|
||||
@@ -10766,7 +10774,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-queue"
|
||||
version = "1.377.1"
|
||||
version = "1.381.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-recursion",
|
||||
@@ -10778,7 +10786,7 @@ dependencies = [
|
||||
"futures-core",
|
||||
"hex",
|
||||
"hmac",
|
||||
"itertools 0.10.5",
|
||||
"itertools 0.13.0",
|
||||
"lazy_static",
|
||||
"prometheus",
|
||||
"regex",
|
||||
@@ -10799,7 +10807,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-sql-datatype-parser-wasm"
|
||||
version = "1.377.1"
|
||||
version = "1.381.0"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-test",
|
||||
@@ -10809,7 +10817,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-worker"
|
||||
version = "1.377.1"
|
||||
version = "1.381.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-recursion",
|
||||
@@ -10834,7 +10842,7 @@ dependencies = [
|
||||
"gcp_auth",
|
||||
"git-version",
|
||||
"hex",
|
||||
"itertools 0.10.5",
|
||||
"itertools 0.13.0",
|
||||
"jsonwebtoken",
|
||||
"lazy_static",
|
||||
"mappable-rc",
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "windmill"
|
||||
version = "1.377.1"
|
||||
version = "1.381.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
@@ -25,7 +25,7 @@ members = [
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
version = "1.377.1"
|
||||
version = "1.381.0"
|
||||
authors = ["Ruben Fiszel <ruben@windmill.dev>"]
|
||||
edition = "2021"
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
80d9e507977b55d0b76272905c969c3d6e830083
|
||||
7cf76a8c6694b59f4615b0c8fa61fb02411326a7
|
||||
+35
-4
@@ -6,15 +6,20 @@
|
||||
* LICENSE-AGPL for a copy of the license.
|
||||
*/
|
||||
|
||||
use anyhow::Context;
|
||||
use gethostname::gethostname;
|
||||
use git_version::git_version;
|
||||
use rand::Rng;
|
||||
use sqlx::{postgres::PgListener, Pool, Postgres};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
net::{IpAddr, Ipv4Addr, SocketAddr},
|
||||
time::Duration,
|
||||
};
|
||||
use tokio::fs::DirBuilder;
|
||||
use tokio::{
|
||||
fs::{create_dir_all, DirBuilder, File},
|
||||
io::AsyncReadExt,
|
||||
};
|
||||
use windmill_api::HTTP_CLIENT;
|
||||
|
||||
#[cfg(feature = "enterprise")]
|
||||
@@ -54,9 +59,10 @@ use windmill_common::METRICS_ADDR;
|
||||
use windmill_common::global_settings::OBJECT_STORE_CACHE_CONFIG_SETTING;
|
||||
|
||||
use windmill_worker::{
|
||||
BUN_BUNDLE_CACHE_DIR, BUN_CACHE_DIR, BUN_DEPSTAR_CACHE_DIR, DENO_CACHE_DIR,
|
||||
DENO_CACHE_DIR_DEPS, DENO_CACHE_DIR_NPM, GO_BIN_CACHE_DIR, GO_CACHE_DIR, HUB_CACHE_DIR,
|
||||
LOCK_CACHE_DIR, PIP_CACHE_DIR, POWERSHELL_CACHE_DIR, TAR_PIP_CACHE_DIR, TMP_LOGS_DIR,
|
||||
get_hub_script_content_and_requirements, BUN_BUNDLE_CACHE_DIR, BUN_CACHE_DIR,
|
||||
BUN_DEPSTAR_CACHE_DIR, DENO_CACHE_DIR, DENO_CACHE_DIR_DEPS, DENO_CACHE_DIR_NPM,
|
||||
GO_BIN_CACHE_DIR, GO_CACHE_DIR, HUB_CACHE_DIR, LOCK_CACHE_DIR, PIP_CACHE_DIR,
|
||||
POWERSHELL_CACHE_DIR, TAR_PIP_CACHE_DIR, TMP_LOGS_DIR,
|
||||
};
|
||||
|
||||
use crate::monitor::{
|
||||
@@ -111,6 +117,28 @@ pub fn main() -> anyhow::Result<()> {
|
||||
create_and_run_current_thread_inner(windmill_main())
|
||||
}
|
||||
|
||||
async fn cache_hub_scripts(file_path: Option<String>) -> anyhow::Result<()> {
|
||||
let file_path = file_path.unwrap_or("./hubPaths.json".to_string());
|
||||
let mut file = File::open(&file_path)
|
||||
.await
|
||||
.with_context(|| format!("Could not open {}, make sure it exists", &file_path))?;
|
||||
let mut contents = String::new();
|
||||
file.read_to_string(&mut contents).await?;
|
||||
let paths = serde_json::from_str::<HashMap<String, String>>(&contents).with_context(|| {
|
||||
format!(
|
||||
"Could not parse {}, make sure it is a valid JSON object with string keys and values",
|
||||
&file_path
|
||||
)
|
||||
})?;
|
||||
|
||||
create_dir_all(HUB_CACHE_DIR).await?;
|
||||
|
||||
for path in paths.values() {
|
||||
get_hub_script_content_and_requirements(Some(path.to_string()), None).await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn windmill_main() -> anyhow::Result<()> {
|
||||
dotenv::dotenv().ok();
|
||||
|
||||
@@ -141,6 +169,9 @@ async fn windmill_main() -> anyhow::Result<()> {
|
||||
{
|
||||
tracing::warn!("Embeddings are not enabled, ignoring...");
|
||||
}
|
||||
|
||||
cache_hub_scripts(std::env::args().nth(2)).await?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
"-v" | "--version" | "version" => {
|
||||
|
||||
@@ -407,7 +407,7 @@ pub async fn delete_expired_items(db: &DB) -> () {
|
||||
}
|
||||
|
||||
let deleted_expired_variables = sqlx::query_scalar!(
|
||||
"DELETE FROM variable WHERE expires_at IS NOT NULL AND expires_at > now() RETURNING path",
|
||||
"DELETE FROM variable WHERE expires_at IS NOT NULL AND expires_at < now() RETURNING path",
|
||||
)
|
||||
.fetch_all(db)
|
||||
.await;
|
||||
|
||||
@@ -372,7 +372,7 @@ mod suspend_resume {
|
||||
server.close().await.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
json!( {"error": {"name": "SuspendedDisapproved", "message": "Disapproved by Some(\"ruben\")"}}),
|
||||
json!( {"error": {"name": "SuspendedDisapproved", "message": "Disapproved by ruben"}}),
|
||||
result
|
||||
);
|
||||
}
|
||||
@@ -433,7 +433,7 @@ mod suspend_resume {
|
||||
let result = completed_job(flow, &db).await.json_result().unwrap();
|
||||
|
||||
assert_eq!(
|
||||
json!( {"error": {"name": "SuspendedDisapproved", "message": "Disapproved by None"}}),
|
||||
json!( {"error": {"name": "SuspendedDisapproved", "message": "Disapproved by unknown"}}),
|
||||
result
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
openapi: "3.0.3"
|
||||
|
||||
info:
|
||||
version: 1.377.1
|
||||
version: 1.381.0
|
||||
title: Windmill API
|
||||
|
||||
contact:
|
||||
@@ -5631,6 +5631,8 @@ paths:
|
||||
properties:
|
||||
database_length:
|
||||
type: integer
|
||||
suspended:
|
||||
type: integer
|
||||
required:
|
||||
- database_length
|
||||
|
||||
@@ -5812,6 +5814,7 @@ paths:
|
||||
- $ref: "#/components/parameters/CreatedOrStartedAfter"
|
||||
- $ref: "#/components/parameters/CreatedOrStartedAfterCompletedJob"
|
||||
- $ref: "#/components/parameters/JobKinds"
|
||||
- $ref: "#/components/parameters/Suspended"
|
||||
- $ref: "#/components/parameters/ArgsFilter"
|
||||
- $ref: "#/components/parameters/Tag"
|
||||
- $ref: "#/components/parameters/ResultFilter"
|
||||
|
||||
@@ -29,7 +29,6 @@ use sha2::{Digest, Sha256};
|
||||
use sql_builder::{bind::Bind, SqlBuilder};
|
||||
use sqlx::{types::Uuid, FromRow};
|
||||
use std::str;
|
||||
use tower_http::cors::{Any, CorsLayer};
|
||||
use windmill_audit::audit_ee::audit_log;
|
||||
use windmill_audit::ActionKind;
|
||||
use windmill_common::{
|
||||
@@ -66,24 +65,10 @@ pub fn workspaced_service() -> Router {
|
||||
}
|
||||
|
||||
pub fn unauthed_service() -> Router {
|
||||
let cors = CorsLayer::new()
|
||||
.allow_methods([http::Method::GET])
|
||||
.allow_headers([http::header::CONTENT_TYPE, http::header::AUTHORIZATION])
|
||||
.allow_origin(Any);
|
||||
|
||||
Router::new()
|
||||
.route(
|
||||
"/execute_component/*path",
|
||||
post(execute_component).layer(cors.clone()),
|
||||
)
|
||||
.route(
|
||||
"/public_app/:secret",
|
||||
get(get_public_app_by_secret).layer(cors.clone()),
|
||||
)
|
||||
.route(
|
||||
"/public_resource/*path",
|
||||
get(get_public_resource).layer(cors.clone()),
|
||||
)
|
||||
.route("/execute_component/*path", post(execute_component))
|
||||
.route("/public_app/:secret", get(get_public_app_by_secret))
|
||||
.route("/public_resource/*path", get(get_public_resource))
|
||||
}
|
||||
|
||||
pub fn global_service() -> Router {
|
||||
@@ -720,7 +705,7 @@ pub async fn get_hub_app_by_id(
|
||||
&format!("{}/apps/{}/json", *HUB_BASE_URL.read().await, id),
|
||||
false,
|
||||
None,
|
||||
&db,
|
||||
Some(&db),
|
||||
)
|
||||
.await?
|
||||
.json()
|
||||
|
||||
@@ -313,7 +313,7 @@ impl EmbeddingsDb {
|
||||
&format!("{}/scripts/embeddings", hub_base_url),
|
||||
false,
|
||||
None,
|
||||
pg_db,
|
||||
Some(pg_db),
|
||||
)
|
||||
.await?
|
||||
} else {
|
||||
@@ -326,7 +326,7 @@ impl EmbeddingsDb {
|
||||
&format!("{}/scripts/embeddings", hub_base_url),
|
||||
false,
|
||||
None,
|
||||
pg_db,
|
||||
Some(pg_db),
|
||||
)
|
||||
.await?
|
||||
}
|
||||
@@ -375,7 +375,7 @@ impl EmbeddingsDb {
|
||||
&format!("{}/resource_types/embeddings", hub_base_url),
|
||||
false,
|
||||
None,
|
||||
pg_db,
|
||||
Some(pg_db),
|
||||
)
|
||||
.await?
|
||||
} else {
|
||||
@@ -388,7 +388,7 @@ impl EmbeddingsDb {
|
||||
&format!("{}/resource_types/embeddings", hub_base_url),
|
||||
false,
|
||||
None,
|
||||
pg_db,
|
||||
Some(pg_db),
|
||||
)
|
||||
.await?
|
||||
}
|
||||
|
||||
@@ -230,7 +230,7 @@ pub async fn get_hub_flow_by_id(
|
||||
&format!("{}/flows/{}/json", *HUB_BASE_URL.read().await, id),
|
||||
false,
|
||||
None,
|
||||
&db,
|
||||
Some(&db),
|
||||
)
|
||||
.await?
|
||||
.json()
|
||||
|
||||
@@ -1462,7 +1462,6 @@ async fn cancel_selection(
|
||||
Path(w_id): Path<String>,
|
||||
Json(jobs): Json<Vec<Uuid>>,
|
||||
) -> error::JsonResult<Vec<Uuid>> {
|
||||
|
||||
let mut tx = user_db.begin(&authed).await?;
|
||||
let jobs_to_cancel = sqlx::query_scalar!(
|
||||
"SELECT id FROM queue WHERE id = ANY($1) AND schedule_path IS NULL",
|
||||
@@ -1508,6 +1507,7 @@ async fn list_filtered_uuids(
|
||||
#[derive(Serialize, Debug, FromRow)]
|
||||
struct QueueStats {
|
||||
database_length: i64,
|
||||
suspended: Option<i64>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
@@ -1523,7 +1523,7 @@ async fn count_queue_jobs(
|
||||
Ok(Json(
|
||||
sqlx::query_as!(
|
||||
QueueStats,
|
||||
"SELECT coalesce(COUNT(*), 0) as \"database_length!\" FROM queue WHERE (workspace_id = $1 OR $2) AND scheduled_for <= now() AND running = false",
|
||||
"SELECT coalesce(COUNT(*) FILTER(WHERE suspend = 0 AND running = false), 0) as \"database_length!\", coalesce(COUNT(*) FILTER(WHERE suspend > 0), 0) as \"suspended!\" FROM queue WHERE (workspace_id = $1 OR $2) AND scheduled_for <= now()",
|
||||
w_id,
|
||||
w_id == "admins" && cq.all_workspaces.unwrap_or(false),
|
||||
)
|
||||
@@ -1539,7 +1539,7 @@ async fn count_completed_jobs(
|
||||
Ok(Json(
|
||||
sqlx::query_as!(
|
||||
QueueStats,
|
||||
"SELECT coalesce(COUNT(*), 0) as \"database_length!\" FROM completed_job WHERE workspace_id = $1",
|
||||
"SELECT coalesce(COUNT(*), 0) as \"database_length!\", null::bigint as suspended FROM completed_job WHERE workspace_id = $1",
|
||||
w_id
|
||||
)
|
||||
.fetch_one(&db)
|
||||
|
||||
@@ -334,7 +334,7 @@ pub async fn run_server(
|
||||
)
|
||||
.nest(
|
||||
"/w/:workspace_id/capture_u",
|
||||
capture::global_service().layer(cors.clone()),
|
||||
capture::global_service().layer(cors),
|
||||
)
|
||||
.nest(
|
||||
"/auth",
|
||||
@@ -346,7 +346,7 @@ pub async fn run_server(
|
||||
)
|
||||
.route("/version", get(git_v))
|
||||
.route("/uptodate", get(is_up_to_date))
|
||||
.route("/ee_license", get(ee_license).layer(cors.clone()))
|
||||
.route("/ee_license", get(ee_license))
|
||||
.route("/openapi.yaml", get(openapi))
|
||||
.route("/openapi.json", get(openapi_json)),
|
||||
)
|
||||
|
||||
@@ -817,7 +817,8 @@ pub async fn get_full_hub_script_by_path(
|
||||
Extension(db): Extension<DB>,
|
||||
) -> JsonResult<HubScript> {
|
||||
Ok(Json(
|
||||
windmill_common::scripts::get_full_hub_script_by_path(path, &HTTP_CLIENT, &db).await?,
|
||||
windmill_common::scripts::get_full_hub_script_by_path(path, &HTTP_CLIENT, Some(&db))
|
||||
.await?,
|
||||
))
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,9 @@ use axum::{
|
||||
Json, Router,
|
||||
};
|
||||
|
||||
#[cfg(feature = "enterprise")]
|
||||
use axum::extract::Query;
|
||||
|
||||
use serde::Deserialize;
|
||||
use windmill_common::{
|
||||
error::{self, JsonResult, Result},
|
||||
@@ -237,12 +240,12 @@ pub async fn set_global_setting_internal(
|
||||
}
|
||||
v => {
|
||||
sqlx::query!(
|
||||
"INSERT INTO global_settings (name, value) VALUES ($1, $2) ON CONFLICT (name) DO UPDATE SET value = $2, updated_at = now()",
|
||||
key,
|
||||
v
|
||||
)
|
||||
.execute(db)
|
||||
.await?;
|
||||
"INSERT INTO global_settings (name, value) VALUES ($1, $2) ON CONFLICT (name) DO UPDATE SET value = $2, updated_at = now()",
|
||||
key,
|
||||
v
|
||||
)
|
||||
.execute(db)
|
||||
.await?;
|
||||
tracing::info!("Set global setting {} to {}", key, v);
|
||||
}
|
||||
};
|
||||
@@ -339,6 +342,12 @@ pub async fn get_latest_key_renewal_attempt(
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "enterprise")]
|
||||
#[derive(Deserialize)]
|
||||
pub struct LicenseQuery {
|
||||
license_key: Option<String>,
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "enterprise"))]
|
||||
pub async fn renew_license_key() -> Result<String> {
|
||||
return Err(error::Error::BadRequest(
|
||||
@@ -347,15 +356,23 @@ pub async fn renew_license_key() -> Result<String> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "enterprise")]
|
||||
pub async fn renew_license_key(Extension(db): Extension<DB>, authed: ApiAuthed) -> Result<String> {
|
||||
pub async fn renew_license_key(
|
||||
Extension(db): Extension<DB>,
|
||||
Query(LicenseQuery { license_key }): Query<LicenseQuery>,
|
||||
authed: ApiAuthed,
|
||||
) -> Result<String> {
|
||||
require_super_admin(&db, &authed.email).await?;
|
||||
windmill_common::stats_ee::send_stats(&"manual".to_string(), &HTTP_CLIENT, &db).await?;
|
||||
let result = windmill_common::ee::renew_license_key(&HTTP_CLIENT, &db, None).await;
|
||||
let result = windmill_common::ee::renew_license_key(&HTTP_CLIENT, &db, license_key).await;
|
||||
|
||||
if result != "success" {
|
||||
return Err(error::Error::BadRequest(format!(
|
||||
"Failed to renew license key: {}",
|
||||
result
|
||||
if result == "Unauthorized" {
|
||||
"Invalid key".to_string()
|
||||
} else {
|
||||
result
|
||||
}
|
||||
)));
|
||||
} else {
|
||||
return Ok("Renewed license key".to_string());
|
||||
@@ -370,8 +387,11 @@ pub async fn create_customer_portal_session() -> Result<String> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "enterprise")]
|
||||
pub async fn create_customer_portal_session() -> Result<String> {
|
||||
let url = windmill_common::ee::create_customer_portal_session(&HTTP_CLIENT, None).await?;
|
||||
pub async fn create_customer_portal_session(
|
||||
Query(LicenseQuery { license_key }): Query<LicenseQuery>,
|
||||
) -> Result<String> {
|
||||
let url =
|
||||
windmill_common::ee::create_customer_portal_session(&HTTP_CLIENT, license_key).await?;
|
||||
|
||||
return Ok(url);
|
||||
}
|
||||
|
||||
@@ -44,7 +44,6 @@ use time::OffsetDateTime;
|
||||
#[cfg(feature = "enterprise")]
|
||||
use tokio::sync::RwLock;
|
||||
use tower_cookies::{Cookie, Cookies};
|
||||
use tower_http::cors::{Any, CorsLayer};
|
||||
use tracing::{Instrument, Span};
|
||||
use windmill_audit::audit_ee::{audit_log, AuditAuthor};
|
||||
use windmill_audit::ActionKind;
|
||||
@@ -67,11 +66,6 @@ const COOKIE_NAME: &str = "token";
|
||||
const COOKIE_PATH: &str = "/";
|
||||
|
||||
pub fn workspaced_service() -> Router {
|
||||
let cors = CorsLayer::new()
|
||||
.allow_methods([http::Method::GET])
|
||||
.allow_headers([http::header::CONTENT_TYPE, http::header::AUTHORIZATION])
|
||||
.allow_origin(Any);
|
||||
|
||||
Router::new()
|
||||
.route("/list", get(list_users))
|
||||
.route("/list_usage", get(list_user_usage))
|
||||
@@ -82,21 +76,16 @@ pub fn workspaced_service() -> Router {
|
||||
.route("/delete/:user", delete(delete_workspace_user))
|
||||
.route("/is_owner/*path", get(is_owner_of_path))
|
||||
.route("/whois/:username", get(whois))
|
||||
.route("/whoami", get(whoami).layer(cors))
|
||||
.route("/whoami", get(whoami))
|
||||
.route("/leave", post(leave_workspace))
|
||||
.route("/username_to_email/:username", get(username_to_email))
|
||||
}
|
||||
|
||||
pub fn global_service() -> Router {
|
||||
let cors = CorsLayer::new()
|
||||
.allow_methods([http::Method::GET])
|
||||
.allow_headers([http::header::CONTENT_TYPE, http::header::AUTHORIZATION])
|
||||
.allow_origin(Any);
|
||||
|
||||
Router::new()
|
||||
.route("/exists/:email", get(exists_email))
|
||||
.route("/email", get(get_email))
|
||||
.route("/whoami", get(global_whoami).layer(cors))
|
||||
.route("/whoami", get(global_whoami))
|
||||
.route("/list_invites", get(list_invites))
|
||||
.route("/decline_invite", post(decline_invite))
|
||||
.route("/accept_invite", post(accept_invite))
|
||||
@@ -129,13 +118,8 @@ pub fn global_service() -> Router {
|
||||
}
|
||||
|
||||
pub fn make_unauthed_service() -> Router {
|
||||
let cors = CorsLayer::new()
|
||||
.allow_methods([http::Method::POST])
|
||||
.allow_headers([http::header::CONTENT_TYPE, http::header::AUTHORIZATION])
|
||||
.allow_origin(Any);
|
||||
|
||||
Router::new()
|
||||
.route("/login", post(login).layer(cors))
|
||||
.route("/login", post(login))
|
||||
.route("/logout", post(logout))
|
||||
.route("/logout", get(logout))
|
||||
}
|
||||
|
||||
@@ -21,8 +21,6 @@ use crate::{
|
||||
webhook_util::WebhookShared,
|
||||
};
|
||||
|
||||
use tower_http::cors::{Any, CorsLayer};
|
||||
|
||||
use axum::{
|
||||
extract::{Extension, Path, Query},
|
||||
response::IntoResponse,
|
||||
@@ -126,15 +124,10 @@ pub fn workspaced_service() -> Router {
|
||||
router
|
||||
}
|
||||
pub fn global_service() -> Router {
|
||||
let cors = CorsLayer::new()
|
||||
.allow_methods([http::Method::GET])
|
||||
.allow_headers([http::header::CONTENT_TYPE, http::header::AUTHORIZATION])
|
||||
.allow_origin(Any);
|
||||
|
||||
Router::new()
|
||||
.route("/list_as_superadmin", get(list_workspaces_as_super_admin))
|
||||
.route("/list", get(list_workspaces))
|
||||
.route("/users", get(user_workspaces).layer(cors.clone()))
|
||||
.route("/users", get(user_workspaces))
|
||||
.route("/create", post(create_workspace))
|
||||
.route("/exists", post(exists_workspace))
|
||||
.route("/exists_username", post(exists_username))
|
||||
@@ -175,9 +168,9 @@ pub struct WorkspaceSettings {
|
||||
pub error_handler: Option<String>,
|
||||
pub error_handler_extra_args: Option<serde_json::Value>,
|
||||
pub error_handler_muted_on_cancel: Option<bool>,
|
||||
pub large_file_storage: Option<serde_json::Value>, // effectively: DatasetsStorage
|
||||
pub git_sync: Option<serde_json::Value>, // effectively: WorkspaceGitSyncSettings
|
||||
pub deploy_ui: Option<serde_json::Value>, // effectively: WorkspaceDeploymentUISettings
|
||||
pub large_file_storage: Option<serde_json::Value>, // effectively: DatasetsStorage
|
||||
pub git_sync: Option<serde_json::Value>, // effectively: WorkspaceGitSyncSettings
|
||||
pub deploy_ui: Option<serde_json::Value>, // effectively: WorkspaceDeploymentUISettings
|
||||
pub default_app: Option<String>,
|
||||
pub automatic_billing: bool,
|
||||
pub default_scripts: Option<serde_json::Value>,
|
||||
@@ -1078,6 +1071,7 @@ async fn edit_deploy_ui_config(
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
#[cfg(feature = "enterprise")]
|
||||
async fn edit_deploy_ui_config(
|
||||
authed: ApiAuthed,
|
||||
@@ -1103,9 +1097,8 @@ async fn edit_deploy_ui_config(
|
||||
.await?;
|
||||
|
||||
if let Some(deploy_ui_settings) = new_config.deploy_ui_settings {
|
||||
let serialized_config =
|
||||
serde_json::to_value::<WorkspaceDeploymentUISettings>(deploy_ui_settings)
|
||||
.map_err(|err| Error::InternalErr(err.to_string()))?;
|
||||
let serialized_config = serde_json::to_value::<WorkspaceDeploymentUISettings>(deploy_ui_settings)
|
||||
.map_err(|err| Error::InternalErr(err.to_string()))?;
|
||||
|
||||
sqlx::query!(
|
||||
"UPDATE workspace_settings SET deploy_ui = $1 WHERE workspace_id = $2",
|
||||
@@ -1127,6 +1120,8 @@ async fn edit_deploy_ui_config(
|
||||
Ok(format!("Edit deployment UI config for workspace {}", &w_id))
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct EditDefaultApp {
|
||||
pub default_app_path: Option<String>,
|
||||
|
||||
@@ -213,6 +213,12 @@ pub struct Suspend {
|
||||
pub self_approval_disabled: Option<bool>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub hide_cancel: Option<bool>,
|
||||
#[serde(skip_serializing_if = "false_or_empty")]
|
||||
pub continue_on_disapprove_timeout: Option<bool>,
|
||||
}
|
||||
|
||||
fn false_or_empty(v: &Option<bool>) -> bool {
|
||||
v.is_none() || v.as_ref().is_some_and(|x| !x)
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||
|
||||
@@ -30,7 +30,7 @@ pub const DEV_INSTANCE_SETTING: &str = "dev_instance";
|
||||
pub const JWT_SECRET_SETTING: &str = "jwt_secret";
|
||||
pub const EMAIL_DOMAIN_SETTING: &str = "email_domain";
|
||||
|
||||
pub const ENV_SETTINGS: [&str; 50] = [
|
||||
pub const ENV_SETTINGS: [&str; 51] = [
|
||||
"DISABLE_NSJAIL",
|
||||
"MODE",
|
||||
"NUM_WORKERS",
|
||||
@@ -81,4 +81,5 @@ pub const ENV_SETTINGS: [&str; 50] = [
|
||||
"MAX_WAIT_FOR_SIGTERM",
|
||||
"WORKER_GROUP",
|
||||
"SAML_METADATA",
|
||||
"INSTANCE_IS_DEV",
|
||||
];
|
||||
|
||||
@@ -384,7 +384,7 @@ pub async fn get_hub_script_by_path(
|
||||
&format!("{}/raw/{}.ts", hub_base_url, path),
|
||||
true,
|
||||
None,
|
||||
db,
|
||||
Some(db),
|
||||
)
|
||||
.await?
|
||||
.text()
|
||||
@@ -409,7 +409,7 @@ pub async fn get_hub_script_by_path(
|
||||
&format!("{}/raw/{}.ts", DEFAULT_HUB_BASE_URL, path),
|
||||
true,
|
||||
None,
|
||||
db,
|
||||
Some(db),
|
||||
)
|
||||
.await?
|
||||
.text()
|
||||
@@ -427,7 +427,7 @@ pub async fn get_hub_script_by_path(
|
||||
pub async fn get_full_hub_script_by_path(
|
||||
path: StripPath,
|
||||
http_client: &reqwest::Client,
|
||||
db: &DB,
|
||||
db: Option<&DB>,
|
||||
) -> crate::error::Result<HubScript> {
|
||||
let path = path
|
||||
.to_path()
|
||||
|
||||
@@ -96,7 +96,7 @@ pub async fn query_elems_from_hub(
|
||||
reqwest::header::HeaderMap,
|
||||
axum::body::Body,
|
||||
)> {
|
||||
let response = http_get_from_hub(http_client, url, false, query_params, db).await?;
|
||||
let response = http_get_from_hub(http_client, url, false, query_params, Some(db)).await?;
|
||||
|
||||
let status = response.status();
|
||||
|
||||
@@ -112,9 +112,18 @@ pub async fn http_get_from_hub(
|
||||
url: &str,
|
||||
plain: bool,
|
||||
query_params: Option<Vec<(&str, String)>>,
|
||||
db: &Pool<Postgres>,
|
||||
db: Option<&Pool<Postgres>>,
|
||||
) -> Result<reqwest::Response> {
|
||||
let uid = get_uid(db).await;
|
||||
let uid = match db {
|
||||
Some(db) => match get_uid(db).await {
|
||||
Ok(uid) => Some(uid),
|
||||
Err(err) => {
|
||||
tracing::info!("No valid uid found: {}", err);
|
||||
None
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
|
||||
let mut request = http_client.get(url).header(
|
||||
"Accept",
|
||||
@@ -125,10 +134,8 @@ pub async fn http_get_from_hub(
|
||||
},
|
||||
);
|
||||
|
||||
if let Ok(uid) = uid {
|
||||
if let Some(uid) = uid {
|
||||
request = request.header("X-uid", uid);
|
||||
} else {
|
||||
tracing::info!("No valid uid found: {}", uid.err().unwrap())
|
||||
}
|
||||
|
||||
if let Some(query_params) = query_params {
|
||||
|
||||
@@ -78,6 +78,11 @@ lazy_static::lazy_static! {
|
||||
|
||||
static ref CUSTOM_TAG_REGEX: Regex = Regex::new(r"^(\w+)\(((?:\w+)\+?)+\)$").unwrap();
|
||||
|
||||
pub static ref DISABLE_BUNDLING: bool = std::env::var("DISABLE_BUNDLING")
|
||||
.ok()
|
||||
.and_then(|x| x.parse::<bool>().ok())
|
||||
.unwrap_or(false);
|
||||
|
||||
}
|
||||
|
||||
pub async fn make_suspended_pull_query(wc: &WorkerConfig) {
|
||||
@@ -232,7 +237,8 @@ pub fn get_annotation(inner_content: &str) -> Annotations {
|
||||
let native_mode: bool = annotations.contains(&"native".to_string());
|
||||
|
||||
//TODO: remove || npm_mode when bun build is more powerful
|
||||
let nobundling: bool = annotations.contains(&"nobundling".to_string()) || nodejs_mode;
|
||||
let nobundling: bool =
|
||||
annotations.contains(&"nobundling".to_string()) || nodejs_mode || *DISABLE_BUNDLING;
|
||||
|
||||
Annotations { npm_mode, nodejs_mode, native_mode, nobundling }
|
||||
}
|
||||
|
||||
@@ -53,7 +53,6 @@ use windmill_common::{
|
||||
jobs::{
|
||||
get_payload_tag_from_prefixed_path, CompletedJob, JobKind, JobPayload, QueuedJob, RawCode,
|
||||
},
|
||||
oauth2::WORKSPACE_SLACK_BOT_TOKEN_PATH,
|
||||
schedule::Schedule,
|
||||
scripts::{get_full_hub_script_by_path, ScriptHash, ScriptLang},
|
||||
users::{SUPERADMIN_NOTIFICATION_EMAIL, SUPERADMIN_SECRET_EMAIL},
|
||||
@@ -111,6 +110,11 @@ lazy_static::lazy_static! {
|
||||
|
||||
|
||||
pub static ref JOB_TOKEN: Option<String> = std::env::var("JOB_TOKEN").ok();
|
||||
|
||||
static ref JOB_ARGS_AUDIT_LOGS: bool = std::env::var("JOB_ARGS_AUDIT_LOGS")
|
||||
.ok()
|
||||
.and_then(|x| x.parse().ok())
|
||||
.unwrap_or(false);
|
||||
}
|
||||
|
||||
#[cfg(feature = "cloud")]
|
||||
@@ -1474,16 +1478,6 @@ pub async fn push_error_handler<
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(gbouv): REMOVE THIS after December 1st 2023 and ping users to re-save their error handlers
|
||||
if on_failure_path
|
||||
.to_string()
|
||||
.eq("script/hub/5792/workspace-or-schedule-error-handler-slack")
|
||||
{
|
||||
// default slack error handler being used -> we need to inject the slack token
|
||||
let slack_resource = format!("$res:{WORKSPACE_SLACK_BOT_TOKEN_PATH}");
|
||||
extra.insert("slack".to_string(), to_raw_value(&slack_resource));
|
||||
}
|
||||
|
||||
let result = sanitize_result(result);
|
||||
|
||||
let tx = PushIsolationLevel::IsolatedRoot(db.clone(), rsmq);
|
||||
@@ -1597,15 +1591,6 @@ async fn handle_recovered_schedule<
|
||||
));
|
||||
}
|
||||
}
|
||||
// TODO(gbouv): REMOVE THIS after December 1st 2023 and ping users to re-save their error handlers
|
||||
if on_recovery_path
|
||||
.to_string()
|
||||
.eq("script/hub/2430/slack/schedule-recovery-handler-slack")
|
||||
{
|
||||
// default slack error handler being used -> we need to inject the slack token
|
||||
let slack_resource = format!("$res:{WORKSPACE_SLACK_BOT_TOKEN_PATH}");
|
||||
extra.insert("slack".to_string(), to_raw_value(&slack_resource));
|
||||
}
|
||||
|
||||
let args = error_job
|
||||
.result
|
||||
@@ -3132,7 +3117,8 @@ pub async fn push<'c, 'd, R: rsmq_async::RsmqConnection + Send + 'c>(
|
||||
}
|
||||
|
||||
let hub_script =
|
||||
get_full_hub_script_by_path(StripPath(path.clone()), &HTTP_CLIENT, _db).await?;
|
||||
get_full_hub_script_by_path(StripPath(path.clone()), &HTTP_CLIENT, Some(_db))
|
||||
.await?;
|
||||
|
||||
(
|
||||
None,
|
||||
@@ -3690,6 +3676,16 @@ pub async fn push<'c, 'd, R: rsmq_async::RsmqConnection + Send + 'c>(
|
||||
.map_err(|e| Error::InternalErr(format!("Could not insert concurrency_key={concurrency_key} for job_id={job_id} script_path={script_path:?} workspace_id={workspace_id}: {e:#}")))?;
|
||||
}
|
||||
|
||||
let stringified_args = if *JOB_ARGS_AUDIT_LOGS {
|
||||
Some(serde_json::to_string(&args).map_err(|e| {
|
||||
Error::InternalErr(format!(
|
||||
"Could not serialize args for audit log of job {job_id}: {e:#}"
|
||||
))
|
||||
})?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
tracing::debug!("Pushing job {job_id} with tag {tag}, schedule_path {schedule_path:?}, script_path: {script_path:?}, email {email}, workspace_id {workspace_id}");
|
||||
let uuid = sqlx::query_scalar!(
|
||||
"INSERT INTO queue
|
||||
@@ -3831,6 +3827,10 @@ pub async fn push<'c, 'd, R: rsmq_async::RsmqConnection + Send + 'c>(
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(ref stringified_args) = stringified_args {
|
||||
hm.insert("args", stringified_args);
|
||||
}
|
||||
|
||||
audit_log(
|
||||
&mut tx,
|
||||
&audit_author,
|
||||
|
||||
@@ -18,8 +18,8 @@ use crate::{
|
||||
write_file_binary,
|
||||
},
|
||||
AuthedClientBackgroundTask, BUNFIG_INSTALL_SCOPES, BUN_BUNDLE_CACHE_DIR, BUN_CACHE_DIR,
|
||||
BUN_DEPSTAR_CACHE_DIR, BUN_PATH, DISABLE_NSJAIL, DISABLE_NUSER, HOME_ENV, NODE_PATH,
|
||||
NPM_CONFIG_REGISTRY, NPM_PATH, NSJAIL_PATH, PATH_ENV, TZ_ENV,
|
||||
BUN_DEPSTAR_CACHE_DIR, BUN_PATH, DISABLE_NSJAIL, DISABLE_NUSER, HOME_ENV, NODE_BIN_PATH,
|
||||
NODE_PATH, NPM_CONFIG_REGISTRY, NPM_PATH, NSJAIL_PATH, PATH_ENV, TZ_ENV,
|
||||
};
|
||||
|
||||
use tokio::{fs::File, process::Command};
|
||||
@@ -1165,7 +1165,7 @@ try {{
|
||||
"--config",
|
||||
"run.config.proto",
|
||||
"--",
|
||||
&NODE_PATH,
|
||||
&NODE_BIN_PATH,
|
||||
"/tmp/nodejs/wrapper.mjs",
|
||||
]
|
||||
} else if codebase.is_some() || has_bundle_cache {
|
||||
@@ -1207,7 +1207,7 @@ try {{
|
||||
let cmd = if annotation.nodejs_mode {
|
||||
let script_path = format!("{job_dir}/wrapper.mjs");
|
||||
|
||||
let mut bun_cmd = Command::new(&*NODE_PATH);
|
||||
let mut bun_cmd = Command::new(&*NODE_BIN_PATH);
|
||||
bun_cmd
|
||||
.current_dir(job_dir)
|
||||
.env_clear()
|
||||
@@ -1248,7 +1248,7 @@ try {{
|
||||
start_child_process(
|
||||
cmd,
|
||||
if annotation.nodejs_mode {
|
||||
&*NODE_PATH
|
||||
&*NODE_BIN_PATH
|
||||
} else {
|
||||
&*BUN_PATH
|
||||
},
|
||||
@@ -1274,7 +1274,7 @@ try {{
|
||||
}
|
||||
|
||||
pub async fn get_common_bun_proc_envs(base_internal_url: &str) -> HashMap<String, String> {
|
||||
let bun_envs: HashMap<String, String> = HashMap::from([
|
||||
let mut bun_envs: HashMap<String, String> = HashMap::from([
|
||||
(String::from("PATH"), PATH_ENV.clone()),
|
||||
(String::from("HOME"), HOME_ENV.clone()),
|
||||
(String::from("TZ"), TZ_ENV.clone()),
|
||||
@@ -1291,6 +1291,11 @@ pub async fn get_common_bun_proc_envs(base_internal_url: &str) -> HashMap<String
|
||||
BUN_CACHE_DIR.to_string(),
|
||||
),
|
||||
]);
|
||||
|
||||
if let Some(ref node_path) = NODE_PATH.as_ref() {
|
||||
bun_envs.insert(String::from("NODE_PATH"), node_path.to_string());
|
||||
}
|
||||
|
||||
return bun_envs;
|
||||
}
|
||||
|
||||
@@ -1507,7 +1512,7 @@ for await (const line of Readline.createInterface({{ input: process.stdin }})) {
|
||||
let script_path = format!("{job_dir}/wrapper.mjs");
|
||||
|
||||
handle_dedicated_process(
|
||||
&*NODE_PATH,
|
||||
&*NODE_BIN_PATH,
|
||||
job_dir,
|
||||
context_envs,
|
||||
envs,
|
||||
|
||||
@@ -561,6 +561,9 @@ pub fn pg_cell_to_json_value(
|
||||
Type::TIME => get_basic(row, column, column_i, |a: chrono::NaiveTime| {
|
||||
Ok(JSONValue::String(a.to_string()))
|
||||
})?,
|
||||
Type::TIMETZ => get_basic(row, column, column_i, |a: TimeTZStr| {
|
||||
Ok(JSONValue::String(a.0))
|
||||
})?,
|
||||
Type::TIMESTAMPTZ => get_basic(row, column, column_i, |a: chrono::DateTime<Utc>| {
|
||||
Ok(JSONValue::String(a.to_string()))
|
||||
})?,
|
||||
@@ -633,6 +636,9 @@ pub fn pg_cell_to_json_value(
|
||||
Type::TIME_ARRAY => get_array(row, column, column_i, |a: chrono::NaiveTime| {
|
||||
Ok(JSONValue::String(a.to_string()))
|
||||
})?,
|
||||
Type::TIMETZ_ARRAY => get_array(row, column, column_i, |a: TimeTZStr| {
|
||||
Ok(JSONValue::String(a.0))
|
||||
})?,
|
||||
Type::TIMESTAMPTZ_ARRAY => get_array(row, column, column_i, |a: chrono::DateTime<Utc>| {
|
||||
Ok(JSONValue::String(a.to_string()))
|
||||
})?,
|
||||
@@ -699,6 +705,28 @@ impl<'a> FromSql<'a> for IntervalStr {
|
||||
}
|
||||
}
|
||||
|
||||
struct TimeTZStr(String);
|
||||
impl<'a> FromSql<'a> for TimeTZStr {
|
||||
fn from_sql(
|
||||
_: &Type,
|
||||
mut raw: &'a [u8],
|
||||
) -> Result<Self, Box<dyn std::error::Error + Sync + Send>> {
|
||||
let microsecond = raw.get_i64();
|
||||
let offset = raw.get_i32();
|
||||
let utc_sec = (microsecond / 1_000_000) + offset as i64;
|
||||
let utc = chrono::NaiveTime::from_num_seconds_from_midnight_opt(
|
||||
((utc_sec + 3600 * 24) % (3600 * 24)) as u32,
|
||||
((microsecond % 1_000_000) * 1_000) as u32,
|
||||
)
|
||||
.ok_or_else(|| anyhow::anyhow!("Invalid time value"))?;
|
||||
Ok(TimeTZStr(format!("{:?} UTC", utc)))
|
||||
}
|
||||
|
||||
fn accepts(ty: &Type) -> bool {
|
||||
matches!(ty, &Type::TIMETZ)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_array<'a, T: FromSql<'a>>(
|
||||
row: &'a Row,
|
||||
column: &Column,
|
||||
|
||||
@@ -17,7 +17,7 @@ use windmill_queue::{CanceledBy, HTTP_CLIENT};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::common::run_future_with_polling_update_job_poller;
|
||||
use crate::common::{resolve_job_timeout, run_future_with_polling_update_job_poller};
|
||||
use crate::{common::build_args_values, AuthedClientBackgroundTask};
|
||||
|
||||
#[derive(Serialize)]
|
||||
@@ -304,7 +304,11 @@ pub async fn do_snowflake(
|
||||
json!(database.database.unwrap().to_uppercase()),
|
||||
);
|
||||
}
|
||||
body.insert("timeout".to_string(), json!(10)); // in seconds
|
||||
let timeout = resolve_job_timeout(&db, &job.workspace_id, job.id, job.timeout)
|
||||
.await
|
||||
.0
|
||||
.as_secs();
|
||||
body.insert("timeout".to_string(), json!(timeout));
|
||||
|
||||
let queries = parse_sql_blocks(query);
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
use windmill_common::{
|
||||
auth::{fetch_authed_from_permissioned_as, JWTAuthClaims, JobPerms, JWT_SECRET}, scripts::PREVIEW_IS_TAR_CODEBASE_HASH, worker::{get_windmill_memory_usage, get_worker_memory_usage, TMP_DIR}
|
||||
auth::{fetch_authed_from_permissioned_as, JWTAuthClaims, JobPerms, JWT_SECRET}, scripts::PREVIEW_IS_TAR_CODEBASE_HASH, worker::{get_memory, get_vcpus, get_windmill_memory_usage, get_worker_memory_usage, TMP_DIR}
|
||||
};
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
@@ -245,6 +245,7 @@ pub const POWERSHELL_CACHE_DIR: &str = concatcp!(ROOT_CACHE_DIR, "powershell");
|
||||
pub const COMPOSER_CACHE_DIR: &str = concatcp!(ROOT_CACHE_DIR, "composer");
|
||||
|
||||
const NUM_SECS_PING: u64 = 5;
|
||||
const NUM_SECS_READINGS: u64 = 60;
|
||||
|
||||
const INCLUDE_DEPS_PY_SH_CONTENT: &str = include_str!("../nsjail/download_deps.py.sh");
|
||||
|
||||
@@ -317,13 +318,15 @@ lazy_static::lazy_static! {
|
||||
pub static ref DENO_PATH: String = std::env::var("DENO_PATH").unwrap_or_else(|_| "/usr/bin/deno".to_string());
|
||||
pub static ref BUN_PATH: String = std::env::var("BUN_PATH").unwrap_or_else(|_| "/usr/bin/bun".to_string());
|
||||
pub static ref NPM_PATH: String = std::env::var("NPM_PATH").unwrap_or_else(|_| "/usr/bin/npm".to_string());
|
||||
pub static ref NODE_PATH: String = std::env::var("NODE_PATH").unwrap_or_else(|_| "/usr/bin/node".to_string());
|
||||
pub static ref NODE_BIN_PATH: String = std::env::var("NODE_BIN_PATH").unwrap_or_else(|_| "/usr/bin/node".to_string());
|
||||
pub static ref POWERSHELL_PATH: String = std::env::var("POWERSHELL_PATH").unwrap_or_else(|_| "/usr/bin/pwsh".to_string());
|
||||
pub static ref PHP_PATH: String = std::env::var("PHP_PATH").unwrap_or_else(|_| "/usr/bin/php".to_string());
|
||||
pub static ref COMPOSER_PATH: String = std::env::var("COMPOSER_PATH").unwrap_or_else(|_| "/usr/bin/composer".to_string());
|
||||
pub static ref NSJAIL_PATH: String = std::env::var("NSJAIL_PATH").unwrap_or_else(|_| "nsjail".to_string());
|
||||
pub static ref PATH_ENV: String = std::env::var("PATH").unwrap_or_else(|_| String::new());
|
||||
pub static ref HOME_ENV: String = std::env::var("HOME").unwrap_or_else(|_| "/tmp".to_string());
|
||||
pub static ref NODE_PATH: Option<String> = std::env::var("NODE_PATH").ok();
|
||||
|
||||
pub static ref TZ_ENV: String = std::env::var("TZ").unwrap_or_else(|_| String::new());
|
||||
pub static ref GOPRIVATE: Option<String> = std::env::var("GOPRIVATE").ok();
|
||||
pub static ref GOPROXY: Option<String> = std::env::var("GOPROXY").ok();
|
||||
@@ -371,6 +374,12 @@ lazy_static::lazy_static! {
|
||||
.and_then(|x| x.parse::<u64>().ok());
|
||||
|
||||
|
||||
pub static ref REFRESH_CGROUP_READINGS: bool = std::env::var("REFRESH_CGROUP_READINGS")
|
||||
.ok()
|
||||
.and_then(|x| x.parse().ok())
|
||||
.unwrap_or(false);
|
||||
|
||||
|
||||
}
|
||||
//only matter if CLOUD_HOSTED
|
||||
pub const MAX_RESULT_SIZE: usize = 1024 * 1024 * 2; // 2MB
|
||||
@@ -1354,6 +1363,7 @@ pub async fn run_worker<R: rsmq_async::RsmqConnection + Send + Sync + Clone + 's
|
||||
}
|
||||
};
|
||||
let mut suspend_first_success = false;
|
||||
let mut last_reading = Instant::now() - Duration::from_secs(NUM_SECS_READINGS + 1);
|
||||
|
||||
loop {
|
||||
#[cfg(feature = "benchmark")]
|
||||
@@ -1383,15 +1393,23 @@ pub async fn run_worker<R: rsmq_async::RsmqConnection + Send + Sync + Clone + 's
|
||||
|
||||
let memory_usage = get_worker_memory_usage();
|
||||
let wm_memory_usage = get_windmill_memory_usage();
|
||||
let (vcpus, memory) = if *REFRESH_CGROUP_READINGS && last_reading.elapsed().as_secs() > NUM_SECS_READINGS {
|
||||
last_reading = Instant::now();
|
||||
(get_vcpus(), get_memory())
|
||||
} else {
|
||||
(None, None)
|
||||
};
|
||||
|
||||
if let Err(e) = sqlx::query!(
|
||||
"UPDATE worker_ping SET ping_at = now(), jobs_executed = $1, custom_tags = $2, occupancy_rate = $3, memory_usage = $4, wm_memory_usage = $5, current_job_id = NULL, current_job_workspace_id = NULL WHERE worker = $6",
|
||||
"UPDATE worker_ping SET ping_at = now(), jobs_executed = $1, custom_tags = $2, occupancy_rate = $3, memory_usage = $4, wm_memory_usage = $5, current_job_id = NULL, current_job_workspace_id = NULL, vcpus = COALESCE($7, vcpus), memory = COALESCE($8, memory) WHERE worker = $6",
|
||||
jobs_executed,
|
||||
tags.as_slice(),
|
||||
worker_code_execution_metric / start_time.elapsed().as_secs_f32(),
|
||||
memory_usage,
|
||||
wm_memory_usage,
|
||||
&worker_name
|
||||
&worker_name,
|
||||
vcpus,
|
||||
memory
|
||||
).execute(db).await {
|
||||
tracing::error!("failed to update worker ping, exiting: {}", e);
|
||||
killpill_tx.send(()).unwrap_or_default();
|
||||
@@ -2168,9 +2186,20 @@ pub async fn handle_job_error<R: rsmq_async::RsmqConnection + Send + Sync + Clon
|
||||
tracing::error!(job_id = %job.id, "error handling job: {err:?} {} {} {}", job.id, job.workspace_id, job.created_by);
|
||||
}
|
||||
|
||||
fn extract_error_value(log_lines: &str, i: i32) -> Box<RawValue> {
|
||||
#[derive(Debug, Serialize)]
|
||||
struct SerializedError {
|
||||
message: String,
|
||||
name: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
step_id: Option<String>,
|
||||
}
|
||||
fn extract_error_value(log_lines: &str, i: i32, step_id: Option<String>) -> Box<RawValue> {
|
||||
return to_raw_value(
|
||||
&json!({"message": format!("ExitCode: {i}, last log lines:\n{}", ANSI_ESCAPE_RE.replace_all(log_lines.trim(), "").to_string()), "name": "ExecutionErr"}),
|
||||
&SerializedError {
|
||||
message: format!("ExitCode: {i}, last log lines:\n{}", ANSI_ESCAPE_RE.replace_all(log_lines.trim(), "").to_string()),
|
||||
name: "ExecutionErr".to_string(),
|
||||
step_id,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2638,11 +2667,15 @@ async fn process_result(
|
||||
.last()
|
||||
.unwrap_or(&last_10_log_lines);
|
||||
|
||||
extract_error_value(log_lines, i)
|
||||
extract_error_value(log_lines, i, job.flow_step_id.clone())
|
||||
}
|
||||
}
|
||||
err @ _ => to_raw_value(
|
||||
&json!({"message": format!("error during execution of the script:\n{}", err), "name": "ExecutionErr"}),
|
||||
&SerializedError {
|
||||
message: format!("error during execution of the script:\n{}", err),
|
||||
name: "ExecutionErr".to_string(),
|
||||
step_id: job.flow_step_id.clone(),
|
||||
},
|
||||
),
|
||||
};
|
||||
|
||||
@@ -2703,9 +2736,9 @@ pub struct ContentReqLangEnvs {
|
||||
pub codebase: Option<String>,
|
||||
}
|
||||
|
||||
async fn get_hub_script_content_and_requirements(
|
||||
pub async fn get_hub_script_content_and_requirements(
|
||||
script_path: Option<String>,
|
||||
db: &DB,
|
||||
db: Option<&DB>,
|
||||
) -> error::Result<ContentReqLangEnvs> {
|
||||
let script_path = script_path
|
||||
.clone()
|
||||
@@ -2750,7 +2783,7 @@ async fn get_script_content_by_path(
|
||||
.clone()
|
||||
.ok_or_else(|| Error::InternalErr(format!("expected script path")))?;
|
||||
return if script_path.starts_with("hub/") {
|
||||
get_hub_script_content_and_requirements(Some(script_path), db).await
|
||||
get_hub_script_content_and_requirements(Some(script_path), Some(db)).await
|
||||
} else {
|
||||
let (script_hash, ..) =
|
||||
get_latest_deployed_hash_for_path(db, w_id, script_path.as_str()).await?;
|
||||
@@ -2837,7 +2870,7 @@ async fn handle_code_execution_job(
|
||||
codebase
|
||||
}},
|
||||
JobKind::Script_Hub => {
|
||||
get_hub_script_content_and_requirements(job.script_path.clone(), db).await?
|
||||
get_hub_script_content_and_requirements(job.script_path.clone(), Some(db)).await?
|
||||
}
|
||||
JobKind::Script => {
|
||||
get_script_content_by_hash(
|
||||
|
||||
@@ -162,6 +162,11 @@ pub struct SkipIfStopped {
|
||||
pub args: Option<Json<HashMap<String, Box<RawValue>>>>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct RecoveryObject {
|
||||
recover: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(sqlx::FromRow, Deserialize)]
|
||||
pub struct RowFlowStatus {
|
||||
pub flow_status: sqlx::types::Json<Box<serde_json::value::RawValue>>,
|
||||
@@ -758,8 +763,9 @@ pub async fn update_flow_status_after_job_completion_internal<
|
||||
let module = get_module(&flow_job, module_index);
|
||||
|
||||
// tracing::error!(
|
||||
// "UPDATE FLOW STATUS 3: {module:#?} {unrecoverable} {} {is_last_step} {success} {skip_error_handler}", flow_job.canceled
|
||||
// "UPDATE FLOW STATUS 3: {module:#?} {unrecoverable} {} {is_last_step} {success} {skip_error_handler} is_failure_step {is_failure_step}", flow_job.canceled
|
||||
// );
|
||||
|
||||
let should_continue_flow = match success {
|
||||
_ if stop_early => false,
|
||||
_ if flow_job.canceled => false,
|
||||
@@ -873,7 +879,13 @@ pub async fn update_flow_status_after_job_completion_internal<
|
||||
|
||||
save_in_cache(db, client, &flow_job, cached_res_path, &nresult).await;
|
||||
}
|
||||
let success = success && !is_failure_step && !skip_error_handler;
|
||||
fn result_has_recover_true(nresult: Arc<Box<RawValue>>) -> bool {
|
||||
let recover = serde_json::from_str::<RecoveryObject>(nresult.get());
|
||||
return recover.map(|r| r.recover.unwrap_or(false)).unwrap_or(false);
|
||||
}
|
||||
let success = success
|
||||
&& (!is_failure_step || result_has_recover_true(nresult.clone()))
|
||||
&& !skip_error_handler;
|
||||
if success {
|
||||
add_completed_job(
|
||||
db,
|
||||
@@ -1715,7 +1727,26 @@ async fn push_next_flow_job<R: rsmq_async::RsmqConnection + Send + Sync + Clone>
|
||||
}
|
||||
|
||||
let is_disapproved = resumes.iter().find(|x| !x.approved);
|
||||
if is_disapproved.is_none() && resume_messages.len() >= required_events as usize {
|
||||
let can_be_resumed =
|
||||
is_disapproved.is_none() && resume_messages.len() >= required_events as usize;
|
||||
let disapproved_or_timeout_but_continue = !can_be_resumed
|
||||
&& (is_disapproved.is_some()
|
||||
|| !matches!(
|
||||
&status_module,
|
||||
FlowStatusModule::WaitingForPriorSteps { .. }
|
||||
))
|
||||
&& suspend.continue_on_disapprove_timeout.unwrap_or(false);
|
||||
|
||||
if can_be_resumed || disapproved_or_timeout_but_continue {
|
||||
if disapproved_or_timeout_but_continue {
|
||||
let js = if let Some(disapproved) = is_disapproved.as_ref() {
|
||||
json!({"error": {"message": format!("Disapproved by {}", disapproved.approver.clone().unwrap_or_else( || "unknown".to_string())), "name": "SuspendedDisapproved"}})
|
||||
} else {
|
||||
json!({"error": {"message": "Timed out waiting to be resumed", "name": "SuspendedTimedOut"}})
|
||||
};
|
||||
|
||||
resume_messages.push(to_raw_value(&js));
|
||||
}
|
||||
sqlx::query(
|
||||
"UPDATE queue
|
||||
SET flow_status = JSONB_SET(flow_status, ARRAY['modules', $1::TEXT, 'approvers'], $2)
|
||||
@@ -1787,7 +1818,13 @@ async fn push_next_flow_job<R: rsmq_async::RsmqConnection + Send + Sync + Clone>
|
||||
|
||||
let (logs, error_name) = if let Some(disapprover) = is_disapproved {
|
||||
(
|
||||
format!("Disapproved by {:?}", disapprover.approver),
|
||||
format!(
|
||||
"Disapproved by {}",
|
||||
disapprover
|
||||
.approver
|
||||
.clone()
|
||||
.unwrap_or_else(|| "unknown".to_string())
|
||||
),
|
||||
"SuspendedDisapproved",
|
||||
)
|
||||
} else {
|
||||
@@ -2342,7 +2379,7 @@ async fn push_next_flow_job<R: rsmq_async::RsmqConnection + Send + Sync + Clone>
|
||||
continue_on_same_worker,
|
||||
err,
|
||||
flow_job.visible_to_owner,
|
||||
if flow_job.tag == "flow" {
|
||||
if flow_job.tag == "flow" || flow_job.tag == format!("flow-{}", flow_job.workspace_id) {
|
||||
payload_tag.tag
|
||||
} else {
|
||||
Some(flow_job.tag.clone())
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ import { sleep } from "https://deno.land/x/sleep@v1.2.1/mod.ts";
|
||||
import * as windmill from "https://deno.land/x/windmill@v1.174.0/mod.ts";
|
||||
import * as api from "https://deno.land/x/windmill@v1.174.0/windmill-api/index.ts";
|
||||
|
||||
export const VERSION = "v1.377.1";
|
||||
export const VERSION = "v1.381.0";
|
||||
|
||||
export async function login(email: string, password: string): Promise<string> {
|
||||
return await windmill.UserService.login({
|
||||
|
||||
@@ -34,6 +34,8 @@ export interface Codebase {
|
||||
}[];
|
||||
customBundler?: string;
|
||||
external?: string[];
|
||||
define?: { [key: string]: string };
|
||||
inject?: string[];
|
||||
}
|
||||
|
||||
export async function readConfigFile(): Promise<SyncOptions> {
|
||||
|
||||
+25
-4
@@ -12,7 +12,7 @@ import {
|
||||
yamlParse,
|
||||
} from "./deps.ts";
|
||||
import { requireLogin, resolveWorkspace, validatePath } from "./context.ts";
|
||||
import { resolve, track_job } from "./script.ts";
|
||||
import { findGlobalDeps, resolve, track_job } from "./script.ts";
|
||||
import { defaultFlowDefinition } from "./bootstrap/flow_bootstrap.ts";
|
||||
import { generateFlowLockInternal } from "./metadata.ts";
|
||||
import { SyncOptions, mergeConfigWithConfigFile } from "./conf.ts";
|
||||
@@ -237,8 +237,15 @@ async function generateLocks(
|
||||
await requireLogin(opts);
|
||||
opts = await mergeConfigWithConfigFile(opts);
|
||||
if (folder) {
|
||||
const globalDeps = await findGlobalDeps();
|
||||
// read script metadata file
|
||||
await generateFlowLockInternal(folder, false, workspace);
|
||||
await generateFlowLockInternal(
|
||||
folder,
|
||||
false,
|
||||
workspace,
|
||||
globalDeps,
|
||||
opts.defaultTs
|
||||
);
|
||||
} else {
|
||||
const ignore = await ignoreF(opts);
|
||||
const elems = Object.keys(
|
||||
@@ -258,8 +265,16 @@ async function generateLocks(
|
||||
).map((x) => x.substring(0, x.lastIndexOf(SEP)));
|
||||
let hasAny = false;
|
||||
|
||||
const globalDeps = await findGlobalDeps();
|
||||
|
||||
for (const folder of elems) {
|
||||
const candidate = await generateFlowLockInternal(folder, true, workspace);
|
||||
const candidate = await generateFlowLockInternal(
|
||||
folder,
|
||||
true,
|
||||
workspace,
|
||||
globalDeps,
|
||||
opts.defaultTs
|
||||
);
|
||||
if (candidate) {
|
||||
hasAny = true;
|
||||
log.info(colors.green(`+ ${candidate}`));
|
||||
@@ -281,7 +296,13 @@ async function generateLocks(
|
||||
return;
|
||||
}
|
||||
for (const folder of elems) {
|
||||
await generateFlowLockInternal(folder, false, workspace);
|
||||
await generateFlowLockInternal(
|
||||
folder,
|
||||
false,
|
||||
workspace,
|
||||
globalDeps,
|
||||
opts.defaultTs
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ addEventListener("error", (event) => {
|
||||
}
|
||||
});
|
||||
|
||||
export const VERSION = "v1.377.1";
|
||||
export const VERSION = "v1.381.0";
|
||||
|
||||
let command: any = new Command()
|
||||
.name("wmill")
|
||||
|
||||
+115
-44
@@ -46,7 +46,7 @@ import { FlowFile, replaceInlineScripts } from "./flow.ts";
|
||||
export async function generateAllMetadata() {}
|
||||
|
||||
function findClosestRawReqs(
|
||||
lang: "bun" | "python3" | "php" | undefined,
|
||||
lang: "bun" | "python3" | "php" | string | undefined,
|
||||
remotePath: string,
|
||||
globalDeps: GlobalDeps
|
||||
): string | undefined {
|
||||
@@ -84,20 +84,56 @@ function findClosestRawReqs(
|
||||
}
|
||||
|
||||
const TOP_HASH = "__flow_hash";
|
||||
async function generateFlowHash(folder: string) {
|
||||
async function generateFlowHash(
|
||||
folder: string,
|
||||
globalDeps: GlobalDeps,
|
||||
defaultTs: "bun" | "deno" | undefined
|
||||
): Promise<{
|
||||
hashes: Record<string, string>;
|
||||
pathsWithRawReqs: string[];
|
||||
}> {
|
||||
const elems = await FSFSElement(path.join(Deno.cwd(), folder), []);
|
||||
const hashes: Record<string, string> = {};
|
||||
const pathsWithRawReqs: string[] = [];
|
||||
|
||||
for await (const f of elems.getChildren()) {
|
||||
if (exts.some((e) => f.path.endsWith(e))) {
|
||||
hashes[f.path] = await generateHash(await f.getContentText());
|
||||
const found_ext = exts.find((e) => f.path.endsWith(e));
|
||||
|
||||
if (found_ext) {
|
||||
const lang = inferContentTypeFromFilePath(f.path, defaultTs);
|
||||
// log.info(remote_path + "/script" + ext);
|
||||
const raw = findClosestRawReqs(
|
||||
lang as "bun" | "php" | "python3" | undefined,
|
||||
path.join(folder, f.path),
|
||||
globalDeps
|
||||
);
|
||||
// if (raw) {
|
||||
// rawReqs[ext] = raw;
|
||||
// }
|
||||
|
||||
let text = await f.getContentText();
|
||||
if (raw) {
|
||||
text = raw + text;
|
||||
pathsWithRawReqs.push(f.path);
|
||||
}
|
||||
hashes[f.path] = await generateHash(text);
|
||||
}
|
||||
}
|
||||
return { ...hashes, [TOP_HASH]: await generateHash(JSON.stringify(hashes)) };
|
||||
return {
|
||||
hashes: {
|
||||
...hashes,
|
||||
[TOP_HASH]: await generateHash(JSON.stringify(hashes)),
|
||||
},
|
||||
pathsWithRawReqs,
|
||||
};
|
||||
}
|
||||
|
||||
export async function generateFlowLockInternal(
|
||||
folder: string,
|
||||
dryRun: boolean,
|
||||
workspace: Workspace,
|
||||
globalDeps: GlobalDeps,
|
||||
defaultTs: "bun" | "deno" | undefined,
|
||||
justUpdateMetadataLock?: boolean
|
||||
): Promise<string | undefined> {
|
||||
if (folder.endsWith(SEP)) {
|
||||
@@ -110,7 +146,11 @@ export async function generateFlowLockInternal(
|
||||
log.info(`Generating lock for flow ${folder} at ${remote_path}`);
|
||||
}
|
||||
|
||||
let hashes = await generateFlowHash(folder);
|
||||
let { hashes, pathsWithRawReqs } = await generateFlowHash(
|
||||
folder,
|
||||
globalDeps,
|
||||
defaultTs
|
||||
);
|
||||
|
||||
const conf = await readLockfile();
|
||||
if (await checkifMetadataUptodate(folder, hashes[TOP_HASH], conf, TOP_HASH)) {
|
||||
@@ -126,6 +166,7 @@ export async function generateFlowLockInternal(
|
||||
await Deno.readTextFile(folder! + SEP + "flow.yaml")
|
||||
) as FlowFile;
|
||||
|
||||
const fullReqs: Partial<Record<ScriptLanguage, string>> = {};
|
||||
if (!justUpdateMetadataLock) {
|
||||
const changedScripts = [];
|
||||
//find hashes that do not correspond to previous hashes
|
||||
@@ -139,6 +180,19 @@ export async function generateFlowLockInternal(
|
||||
}
|
||||
|
||||
log.info(`Recomputing locks of ${changedScripts.join(", ")} in ${folder}`);
|
||||
|
||||
for (const script of changedScripts) {
|
||||
if (pathsWithRawReqs.includes(script)) {
|
||||
const lang = inferContentTypeFromFilePath(script, defaultTs);
|
||||
log.info(`Inline script ${script} has raw requirements`);
|
||||
let req = fullReqs[lang];
|
||||
if (!req) {
|
||||
const rawReq = findClosestRawReqs(lang, script, globalDeps) ?? "";
|
||||
const fullReq = await getLockfileFromWindmill();
|
||||
fullReqs[lang] = req;
|
||||
}
|
||||
}
|
||||
}
|
||||
replaceInlineScripts(
|
||||
flowValue.value.modules,
|
||||
folder + SEP!,
|
||||
@@ -161,7 +215,7 @@ export async function generateFlowLockInternal(
|
||||
});
|
||||
}
|
||||
|
||||
hashes = await generateFlowHash(folder);
|
||||
hashes = (await generateFlowHash(folder, globalDeps, defaultTs)).hashes;
|
||||
|
||||
for (const [path, hash] of Object.entries(hashes)) {
|
||||
await updateMetadataGlobalLock(folder, hash, path);
|
||||
@@ -308,27 +362,13 @@ export async function updateScriptSchema(
|
||||
metadataContent.schema = newSchema;
|
||||
}
|
||||
|
||||
async function updateScriptLock(
|
||||
async function getLockfileFromWindmill(
|
||||
workspace: Workspace,
|
||||
scriptContent: string,
|
||||
language: ScriptLanguage,
|
||||
remotePath: string,
|
||||
metadataContent: Record<string, any>,
|
||||
rawDeps: string | undefined
|
||||
): Promise<void> {
|
||||
if (
|
||||
!(
|
||||
language == "bun" ||
|
||||
language == "python3" ||
|
||||
language == "go" ||
|
||||
language == "deno" ||
|
||||
language == "php"
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
// generate the script lock running a dependency job in Windmill and update it inplace
|
||||
// TODO: update this once the client is released
|
||||
): Promise<{ lock: string | undefined }> {
|
||||
const rawResponse = await fetch(
|
||||
`${workspace.remote}api/w/${workspace.workspaceId}/jobs/run/dependencies`,
|
||||
{
|
||||
@@ -354,27 +394,7 @@ async function updateScriptLock(
|
||||
let responseText = "reading response failed";
|
||||
try {
|
||||
responseText = await rawResponse.text();
|
||||
const response = JSON.parse(responseText);
|
||||
const lock = response.lock;
|
||||
if (lock === undefined) {
|
||||
throw new Error(
|
||||
`Failed to generate lockfile. Full response was: ${JSON.stringify(
|
||||
response
|
||||
)}`
|
||||
);
|
||||
}
|
||||
const lockPath = remotePath + ".script.lock";
|
||||
if (lock != "") {
|
||||
await Deno.writeTextFile(lockPath, lock);
|
||||
metadataContent.lock = "!inline " + lockPath.replaceAll(SEP, "/");
|
||||
} else {
|
||||
try {
|
||||
if (await Deno.stat(lockPath)) {
|
||||
await Deno.remove(lockPath);
|
||||
}
|
||||
} catch {}
|
||||
metadataContent.lock = "";
|
||||
}
|
||||
return JSON.parse(responseText);
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
`Failed to generate lockfile. Status was: ${rawResponse.statusText}, ${responseText}, ${e}`
|
||||
@@ -382,6 +402,57 @@ async function updateScriptLock(
|
||||
}
|
||||
}
|
||||
|
||||
async function updateScriptLock(
|
||||
workspace: Workspace,
|
||||
scriptContent: string,
|
||||
language: ScriptLanguage,
|
||||
remotePath: string,
|
||||
metadataContent: Record<string, any>,
|
||||
rawDeps: string | undefined
|
||||
): Promise<void> {
|
||||
if (
|
||||
!(
|
||||
language == "bun" ||
|
||||
language == "python3" ||
|
||||
language == "go" ||
|
||||
language == "deno" ||
|
||||
language == "php"
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
// generate the script lock running a dependency job in Windmill and update it inplace
|
||||
// TODO: update this once the client is released
|
||||
|
||||
const response = getLockfileFromWindmill(
|
||||
workspace,
|
||||
scriptContent,
|
||||
language,
|
||||
remotePath,
|
||||
rawDeps
|
||||
);
|
||||
const lock = response.lock;
|
||||
if (lock === undefined) {
|
||||
throw new Error(
|
||||
`Failed to generate lockfile. Full response was: ${JSON.stringify(
|
||||
response
|
||||
)}`
|
||||
);
|
||||
}
|
||||
const lockPath = remotePath + ".script.lock";
|
||||
if (lock != "") {
|
||||
await Deno.writeTextFile(lockPath, lock);
|
||||
metadataContent.lock = "!inline " + lockPath.replaceAll(SEP, "/");
|
||||
} else {
|
||||
try {
|
||||
if (await Deno.stat(lockPath)) {
|
||||
await Deno.remove(lockPath);
|
||||
}
|
||||
} catch {}
|
||||
metadataContent.lock = "";
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateFlow(
|
||||
workspace: Workspace,
|
||||
flow_value: FlowValue,
|
||||
|
||||
@@ -173,6 +173,8 @@ export async function handleFile(
|
||||
bundle: true,
|
||||
write: false,
|
||||
external: codebase.external,
|
||||
inject: codebase.inject,
|
||||
define: codebase.define,
|
||||
platform: "node",
|
||||
packages: "bundle",
|
||||
target: "node20.15.1",
|
||||
|
||||
+8
-1
@@ -1070,7 +1070,14 @@ export async function pull(opts: GlobalOptions & SyncOptions) {
|
||||
}
|
||||
for (const change of changedFlows) {
|
||||
log.info(`Updating lock for flow ${change}`);
|
||||
await generateFlowLockInternal(change, false, workspace, true);
|
||||
await generateFlowLockInternal(
|
||||
change,
|
||||
false,
|
||||
workspace,
|
||||
globalDeps,
|
||||
opts.defaultTs,
|
||||
true
|
||||
);
|
||||
}
|
||||
log.info(
|
||||
colors.bold.green.underline(
|
||||
|
||||
@@ -27,7 +27,11 @@ COPY --from=denoland/deno:1.44.4 --chmod=755 /usr/bin/deno /usr/bin/deno
|
||||
|
||||
RUN ln -s ${APP}/windmill /usr/local/bin/windmill
|
||||
|
||||
RUN windmill cache
|
||||
COPY ./frontend/src/lib/hubPaths.json ${APP}/hubPaths.json
|
||||
|
||||
RUN windmill cache ${APP}/hubPaths.json
|
||||
|
||||
RUN rm ${APP}/hubPaths.json
|
||||
|
||||
EXPOSE 8000
|
||||
|
||||
|
||||
Generated
+106
-76
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "windmill-components",
|
||||
"version": "1.377.3",
|
||||
"version": "1.381.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "windmill-components",
|
||||
"version": "1.377.3",
|
||||
"version": "1.381.0",
|
||||
"license": "AGPL-3.0",
|
||||
"dependencies": {
|
||||
"@aws-crypto/sha256-js": "^4.0.0",
|
||||
@@ -16,6 +16,7 @@
|
||||
"@redocly/json-to-json-schema": "^0.0.1",
|
||||
"@tanstack/svelte-table": "^8.9.9",
|
||||
"@windmill-labs/svelte-dnd-action": "latest",
|
||||
"@xyflow/svelte": "^0.1.14",
|
||||
"ag-charts-community": "^9.0.1",
|
||||
"ag-charts-enterprise": "^9.0.1",
|
||||
"ag-grid-community": "^31.0.0",
|
||||
@@ -40,6 +41,7 @@
|
||||
"monaco-languageclient": "~7.0.1",
|
||||
"ol": "^7.4.0",
|
||||
"openai": "^4.47.1",
|
||||
"p-limit": "^6.1.0",
|
||||
"pdfjs-dist": "^3.8.162",
|
||||
"quill": "^1.3.7",
|
||||
"rfc4648": "^1.5.3",
|
||||
@@ -1777,6 +1779,14 @@
|
||||
"resolved": "https://registry.npmjs.org/@streamparser/json/-/json-0.0.20.tgz",
|
||||
"integrity": "sha512-VqAAkydywPpkw63WQhPVKCD3SdwXuihCUVZbbiY3SfSTGQyHmwRoq27y4dmJdZuJwd5JIlQoMPyGvMbUPY0RKQ=="
|
||||
},
|
||||
"node_modules/@svelte-put/shortcut": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@svelte-put/shortcut/-/shortcut-3.1.1.tgz",
|
||||
"integrity": "sha512-2L5EYTZXiaKvbEelVkg5znxqvfZGZai3m97+cAiUBhLZwXnGtviTDpHxOoZBsqz41szlfRMcamW/8o0+fbW3ZQ==",
|
||||
"peerDependencies": {
|
||||
"svelte": "^3.55.0 || ^4.0.0 || ^5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@sveltejs/adapter-static": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@sveltejs/adapter-static/-/adapter-static-3.0.1.tgz",
|
||||
@@ -2022,8 +2032,7 @@
|
||||
"node_modules/@types/d3-color": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz",
|
||||
"integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==",
|
||||
"dev": true
|
||||
"integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A=="
|
||||
},
|
||||
"node_modules/@types/d3-contour": {
|
||||
"version": "3.0.6",
|
||||
@@ -2051,7 +2060,6 @@
|
||||
"version": "3.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz",
|
||||
"integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/d3-selection": "*"
|
||||
}
|
||||
@@ -2108,7 +2116,6 @@
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz",
|
||||
"integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/d3-color": "*"
|
||||
}
|
||||
@@ -2155,8 +2162,7 @@
|
||||
"node_modules/@types/d3-selection": {
|
||||
"version": "3.0.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.10.tgz",
|
||||
"integrity": "sha512-cuHoUgS/V3hLdjJOLTT691+G2QoqAjCVLmr4kJXR4ha56w1Zdu8UUQ5TxLRqudgNjwXeQxKMq4j+lyf9sWuslg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-cuHoUgS/V3hLdjJOLTT691+G2QoqAjCVLmr4kJXR4ha56w1Zdu8UUQ5TxLRqudgNjwXeQxKMq4j+lyf9sWuslg=="
|
||||
},
|
||||
"node_modules/@types/d3-shape": {
|
||||
"version": "3.1.5",
|
||||
@@ -2189,7 +2195,6 @@
|
||||
"version": "3.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.8.tgz",
|
||||
"integrity": "sha512-ew63aJfQ/ms7QQ4X7pk5NxQ9fZH/z+i24ZfJ6tJSfqxJMrYLiK01EAs2/Rtw/JreGUsS3pLPNV644qXFGnoZNQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/d3-selection": "*"
|
||||
}
|
||||
@@ -2198,7 +2203,6 @@
|
||||
"version": "3.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz",
|
||||
"integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/d3-interpolate": "*",
|
||||
"@types/d3-selection": "*"
|
||||
@@ -2290,8 +2294,7 @@
|
||||
"node_modules/@types/pug": {
|
||||
"version": "2.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.9.tgz",
|
||||
"integrity": "sha512-Yg4LkgFYvn1faISbDNWmcAC1XoDT8IoMUFspp5mnagKk+UvD2N0IWt5A7GRdMubsNWqgCLmrkf8rXkzNqb4szA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-Yg4LkgFYvn1faISbDNWmcAC1XoDT8IoMUFspp5mnagKk+UvD2N0IWt5A7GRdMubsNWqgCLmrkf8rXkzNqb4szA=="
|
||||
},
|
||||
"node_modules/@types/semver": {
|
||||
"version": "7.5.5",
|
||||
@@ -2511,6 +2514,34 @@
|
||||
"svelte": ">=3.23.0 || ^5.0.0-next.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@xyflow/svelte": {
|
||||
"version": "0.1.14",
|
||||
"resolved": "https://registry.npmjs.org/@xyflow/svelte/-/svelte-0.1.14.tgz",
|
||||
"integrity": "sha512-DdlFz+JKW1sQt8Q8O1DoSsroTvFk1RzmpcEZcGARt1REbnLy4BYG/03piaiclaC4iHK6feaPDvxpF057CkMCTw==",
|
||||
"dependencies": {
|
||||
"@svelte-put/shortcut": "^3.1.0",
|
||||
"@xyflow/system": "0.0.37",
|
||||
"classcat": "^5.0.4",
|
||||
"svelte-preprocess": "^5.1.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"svelte": "^3.0.0 || ^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@xyflow/system": {
|
||||
"version": "0.0.37",
|
||||
"resolved": "https://registry.npmjs.org/@xyflow/system/-/system-0.0.37.tgz",
|
||||
"integrity": "sha512-hSIhezhxgftPUpC+xiQVIorcRILZUOWlLjpYPTyGWRu8s4RJvM4GqvrsFmD5OnMKXLgpU7/PqqUibDVO67oWQQ==",
|
||||
"dependencies": {
|
||||
"@types/d3-drag": "^3.0.7",
|
||||
"@types/d3-selection": "^3.0.10",
|
||||
"@types/d3-transition": "^3.0.8",
|
||||
"@types/d3-zoom": "^3.0.8",
|
||||
"d3-drag": "^3.0.0",
|
||||
"d3-selection": "^3.0.0",
|
||||
"d3-zoom": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@zerodevx/svelte-toast": {
|
||||
"version": "0.9.5",
|
||||
"resolved": "https://registry.npmjs.org/@zerodevx/svelte-toast/-/svelte-toast-0.9.5.tgz",
|
||||
@@ -2973,7 +3004,6 @@
|
||||
"version": "0.2.13",
|
||||
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
|
||||
"integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
@@ -3241,6 +3271,11 @@
|
||||
"consola": "^3.2.3"
|
||||
}
|
||||
},
|
||||
"node_modules/classcat": {
|
||||
"version": "5.0.5",
|
||||
"resolved": "https://registry.npmjs.org/classcat/-/classcat-5.0.5.tgz",
|
||||
"integrity": "sha512-JhZUT7JFcQy/EzW605k/ktHtncoo9vnyW/2GspNYwFlN1C/WmjuV/xtS04e9SOkL2sTdw0VAZ2UGCcQ9lR6p6w=="
|
||||
},
|
||||
"node_modules/clone": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
|
||||
@@ -3308,8 +3343,7 @@
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
||||
"devOptional": true
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
|
||||
},
|
||||
"node_modules/confbox": {
|
||||
"version": "0.1.6",
|
||||
@@ -3921,7 +3955,6 @@
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz",
|
||||
"integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
@@ -4148,8 +4181,7 @@
|
||||
"node_modules/es6-promise": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz",
|
||||
"integrity": "sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg=="
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.21.5",
|
||||
@@ -4843,8 +4875,7 @@
|
||||
"node_modules/fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
|
||||
"devOptional": true
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.3",
|
||||
@@ -4962,7 +4993,6 @@
|
||||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
@@ -4994,7 +5024,6 @@
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
@@ -5004,7 +5033,6 @@
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
@@ -5121,8 +5149,7 @@
|
||||
"node_modules/graceful-fs": {
|
||||
"version": "4.2.11",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
||||
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
|
||||
},
|
||||
"node_modules/graphemer": {
|
||||
"version": "1.4.0",
|
||||
@@ -5430,7 +5457,6 @@
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
@@ -5439,8 +5465,7 @@
|
||||
"node_modules/inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"devOptional": true
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"node_modules/ini": {
|
||||
"version": "1.3.8",
|
||||
@@ -5920,7 +5945,7 @@
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
|
||||
"integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
@@ -6999,7 +7024,6 @@
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
|
||||
"integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
@@ -7088,7 +7112,6 @@
|
||||
"version": "0.5.6",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
|
||||
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"minimist": "^1.2.6"
|
||||
},
|
||||
@@ -7201,7 +7224,7 @@
|
||||
"version": "3.3.7",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
|
||||
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@@ -7510,7 +7533,6 @@
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
@@ -7574,15 +7596,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/p-limit": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
|
||||
"integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
|
||||
"dev": true,
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-6.1.0.tgz",
|
||||
"integrity": "sha512-H0jc0q1vOzlEk0TqAKXKZxdl7kX3OFUzCnNVUnq5Pc3DGo0kpeaMuPqxQn235HibwBEb0/pm9dgKTjXy66fBkg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"yocto-queue": "^0.1.0"
|
||||
"yocto-queue": "^1.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
@@ -7603,6 +7625,35 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/p-locate/node_modules/p-limit": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
|
||||
"integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"yocto-queue": "^0.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/p-locate/node_modules/yocto-queue": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
||||
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/pako": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz",
|
||||
@@ -7678,7 +7729,6 @@
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
|
||||
"devOptional": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@@ -7766,8 +7816,7 @@
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz",
|
||||
"integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
"devOptional": true
|
||||
},
|
||||
"node_modules/picomatch-browser": {
|
||||
"version": "2.2.6",
|
||||
@@ -7857,7 +7906,7 @@
|
||||
"version": "8.4.41",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz",
|
||||
"integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@@ -7872,7 +7921,6 @@
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"nanoid": "^3.3.7",
|
||||
"picocolors": "^1.0.1",
|
||||
@@ -8033,7 +8081,7 @@
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.1.tgz",
|
||||
"integrity": "sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"lilconfig": "^2.0.5",
|
||||
"yaml": "^2.1.1"
|
||||
@@ -9000,7 +9048,6 @@
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/sander/-/sander-0.5.1.tgz",
|
||||
"integrity": "sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"es6-promise": "^3.1.2",
|
||||
"graceful-fs": "^4.1.3",
|
||||
@@ -9012,7 +9059,6 @@
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
|
||||
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"glob": "^7.1.3"
|
||||
},
|
||||
@@ -9182,7 +9228,6 @@
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.11.0.tgz",
|
||||
"integrity": "sha512-J69LQ22xrQB1cIFJhPfgtLuI6BpWRiWu1Y3vSsIwK/eAScqJxd/+CJlUuHQRdX2C9NGFamq+KqNywGgaThwfHw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@jridgewell/sourcemap-codec": "^1.4.14",
|
||||
"buffer-crc32": "^0.2.5",
|
||||
@@ -9837,27 +9882,26 @@
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-preprocess": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-5.1.0.tgz",
|
||||
"integrity": "sha512-EkErPiDzHAc0k2MF5m6vBNmRUh338h2myhinUw/xaqsLs7/ZvsgREiLGj03VrSzbY/TB5ZXgBOsKraFee5yceA==",
|
||||
"dev": true,
|
||||
"version": "5.1.4",
|
||||
"resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-5.1.4.tgz",
|
||||
"integrity": "sha512-IvnbQ6D6Ao3Gg6ftiM5tdbR6aAETwjhHV+UKGf5bHGYR69RQvF1ho0JKPcbUON4vy4R7zom13jPjgdOWCQ5hDA==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@types/pug": "^2.0.6",
|
||||
"detect-indent": "^6.1.0",
|
||||
"magic-string": "^0.27.0",
|
||||
"magic-string": "^0.30.5",
|
||||
"sorcery": "^0.11.0",
|
||||
"strip-indent": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14.10.0"
|
||||
"node": ">= 16.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.10.2",
|
||||
"coffeescript": "^2.5.1",
|
||||
"less": "^3.11.3 || ^4.0.0",
|
||||
"postcss": "^7 || ^8",
|
||||
"postcss-load-config": "^2.1.0 || ^3.0.0 || ^4.0.0",
|
||||
"postcss-load-config": "^2.1.0 || ^3.0.0 || ^4.0.0 || ^5.0.0",
|
||||
"pug": "^3.0.0",
|
||||
"sass": "^1.26.8",
|
||||
"stylus": "^0.55.0",
|
||||
@@ -9898,23 +9942,10 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-preprocess/node_modules/magic-string": {
|
||||
"version": "0.27.0",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz",
|
||||
"integrity": "sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@jridgewell/sourcemap-codec": "^1.4.13"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-preprocess/node_modules/strip-indent": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",
|
||||
"integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"min-indent": "^1.0.0"
|
||||
},
|
||||
@@ -10294,7 +10325,7 @@
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
|
||||
"integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
@@ -10757,8 +10788,7 @@
|
||||
"node_modules/wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||
"devOptional": true
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||
},
|
||||
"node_modules/write-file-atomic": {
|
||||
"version": "5.0.1",
|
||||
@@ -10927,12 +10957,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/yocto-queue": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
||||
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
|
||||
"dev": true,
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz",
|
||||
"integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
"node": ">=12.20"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "windmill-components",
|
||||
"version": "1.377.8",
|
||||
"version": "1.381.0",
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"build": "vite build",
|
||||
@@ -97,6 +97,7 @@
|
||||
"@redocly/json-to-json-schema": "^0.0.1",
|
||||
"@tanstack/svelte-table": "^8.9.9",
|
||||
"@windmill-labs/svelte-dnd-action": "latest",
|
||||
"@xyflow/svelte": "^0.1.14",
|
||||
"ag-charts-community": "^9.0.1",
|
||||
"ag-charts-enterprise": "^9.0.1",
|
||||
"ag-grid-community": "^31.0.0",
|
||||
@@ -121,6 +122,7 @@
|
||||
"monaco-languageclient": "~7.0.1",
|
||||
"ol": "^7.4.0",
|
||||
"openai": "^4.47.1",
|
||||
"p-limit": "^6.1.0",
|
||||
"pdfjs-dist": "^3.8.162",
|
||||
"quill": "^1.3.7",
|
||||
"rfc4648": "^1.5.3",
|
||||
@@ -325,11 +327,6 @@
|
||||
"types": "./package/components/DropdownV2.svelte.d.ts",
|
||||
"svelte": "./package/components/DropdownV2.svelte",
|
||||
"default": "./package/components/DropdownV2.svelte"
|
||||
},
|
||||
"./components/AppEmbed.svelte": {
|
||||
"types": "./package/components/AppEmbed.svelte.d.ts",
|
||||
"svelte": "./package/components/AppEmbed.svelte",
|
||||
"default": "./package/components/AppEmbed.svelte"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
@@ -447,9 +444,6 @@
|
||||
],
|
||||
"components/DropdownV2.svelte": [
|
||||
"./package/components/DropdownV2.svelte.d.ts"
|
||||
],
|
||||
"components/AppEmbed.svelte": [
|
||||
"./package/components/AppEmbed.svelte.d.ts"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// https://github.com/jsdelivr/data.jsdelivr.com
|
||||
|
||||
import pLimit from 'p-limit'
|
||||
|
||||
export const getNPMVersionsForModule = (moduleName: string, resLimit: ResLimit) => {
|
||||
const url = `https://data.jsdelivr.com/v1/package/npm/${moduleName}`
|
||||
return api<{ tags: Record<string, string>; versions: string[] }>(url, resLimit, {
|
||||
@@ -51,7 +53,7 @@ export const getDTSFileForModuleWithVersion = async (
|
||||
) => {
|
||||
// file comes with a prefix /
|
||||
const url = `https://cdn.jsdelivr.net/npm/${moduleName}@${version}${file}`
|
||||
const res = await fetch(url)
|
||||
const res = await limit(() => fetch(url))
|
||||
if (res.ok) {
|
||||
return res.text()
|
||||
} else {
|
||||
@@ -67,6 +69,8 @@ export function isOverlimit(resLimit: ResLimit) {
|
||||
return resLimit.usage > 5000000
|
||||
}
|
||||
|
||||
export const limit = pLimit(6)
|
||||
|
||||
function api<T>(url: string, resLimit: ResLimit, init?: RequestInit): Promise<T | Error> {
|
||||
if (isOverlimit(resLimit)) {
|
||||
console.warn(
|
||||
@@ -75,16 +79,18 @@ function api<T>(url: string, resLimit: ResLimit, init?: RequestInit): Promise<T
|
||||
return new Promise(() => new Error('Exceeded limit of 100MB of data downloaded.'))
|
||||
}
|
||||
|
||||
return fetch(url, init).then((res) => {
|
||||
if (res.ok) {
|
||||
return res.text().then((text) => {
|
||||
resLimit.usage += text.length
|
||||
console.log('resLimit', url, resLimit.usage)
|
||||
return limit(() =>
|
||||
fetch(url, init).then((res) => {
|
||||
if (res.ok) {
|
||||
return res.text().then((text) => {
|
||||
resLimit.usage += text.length
|
||||
console.log('resLimit', url, resLimit.usage)
|
||||
|
||||
return JSON.parse(text) as T
|
||||
}) as Promise<T | Error>
|
||||
} else {
|
||||
return new Error('OK')
|
||||
}
|
||||
})
|
||||
return JSON.parse(text) as T
|
||||
}) as Promise<T | Error>
|
||||
} else {
|
||||
return new Error('OK')
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
getNPMVersionForModuleReference,
|
||||
getNPMVersionsForModule,
|
||||
isOverlimit,
|
||||
limit,
|
||||
type NPMTreeMeta,
|
||||
type ResLimit
|
||||
} from './apis'
|
||||
@@ -49,6 +50,7 @@ export const setupTypeAcquisition = (config: ATABootstrapConfig) => {
|
||||
const moduleMap = new Map<string, ModuleMeta>()
|
||||
const fsMap = new Map<string, string>()
|
||||
|
||||
limit.clearQueue()
|
||||
let estimatedToDownload = 0
|
||||
let estimatedDownloaded = 0
|
||||
|
||||
|
||||
@@ -1,167 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { BROWSER } from 'esm-env'
|
||||
import { base } from '$lib/base'
|
||||
import AppPreview from '$lib/components/apps/editor/AppPreview.svelte'
|
||||
import { IS_APP_PUBLIC_CONTEXT_KEY, type EditorBreakpoint } from '$lib/components/apps/types'
|
||||
|
||||
import { Alert, Skeleton } from '$lib/components/common'
|
||||
import { WindmillIcon } from '$lib/components/icons'
|
||||
import { AppService, type AppWithLastVersion } from '$lib/gen'
|
||||
import { enterpriseLicense, userStore } from '$lib/stores'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
|
||||
import { setContext } from 'svelte'
|
||||
import { writable } from 'svelte/store'
|
||||
import { setLicense } from '$lib/enterpriseUtils'
|
||||
import { isCloudHosted } from '$lib/cloud'
|
||||
import Login from '$lib/components/Login.svelte'
|
||||
import { getUserExt } from '$lib/user'
|
||||
import { User, UserRoundX } from 'lucide-svelte'
|
||||
|
||||
export let workspace: string
|
||||
export let secret: string | undefined = undefined
|
||||
export let path: string | undefined = undefined
|
||||
export let replaceStateFn: (path: string) => void = (path: string) =>
|
||||
window.history.replaceState(null, '', path)
|
||||
export let gotoFn: (path: string, opt?: Record<string, any> | undefined) => void = (
|
||||
path: string,
|
||||
opt?: Record<string, any>
|
||||
) => window.history.pushState(null, '', path)
|
||||
|
||||
export let hideUser = false
|
||||
|
||||
let app: (AppWithLastVersion & { value: any }) | undefined = undefined
|
||||
let notExists = false
|
||||
let noPermission = false
|
||||
let neitherSecretNorPath = !secret && !path
|
||||
setContext(IS_APP_PUBLIC_CONTEXT_KEY, true)
|
||||
|
||||
async function loadApp() {
|
||||
try {
|
||||
neitherSecretNorPath = !secret && !path
|
||||
if (neitherSecretNorPath) {
|
||||
throw new Error('No secret or path provided')
|
||||
}
|
||||
app = secret
|
||||
? await AppService.getPublicAppBySecret({
|
||||
workspace: workspace,
|
||||
path: secret
|
||||
})
|
||||
: await AppService.getAppByPath({
|
||||
workspace: workspace,
|
||||
path: path!
|
||||
})
|
||||
noPermission = false
|
||||
notExists = false
|
||||
} catch (e) {
|
||||
if (e.status == 401) {
|
||||
noPermission = true
|
||||
} else {
|
||||
notExists = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (BROWSER) {
|
||||
setLicense()
|
||||
loadUser().then(() => {
|
||||
loadApp()
|
||||
})
|
||||
}
|
||||
|
||||
async function loadUser() {
|
||||
try {
|
||||
userStore.set(await getUserExt(workspace))
|
||||
} catch (e) {
|
||||
console.warn('Anonymous user')
|
||||
}
|
||||
}
|
||||
|
||||
const breakpoint = writable<EditorBreakpoint>('lg')
|
||||
|
||||
const darkMode =
|
||||
window.localStorage.getItem('dark-mode') ??
|
||||
(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')
|
||||
|
||||
if (darkMode === 'dark') {
|
||||
document.documentElement.classList.add('dark')
|
||||
} else {
|
||||
document.documentElement.classList.remove('dark')
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="windmil-app relative h-full w-full">
|
||||
<div
|
||||
class="z-50 text-xs fixed bottom-1 right-2 {$enterpriseLicense && !isCloudHosted()
|
||||
? 'transition-opacity delay-1000 duration-1000 opacity-20 hover:delay-0 hover:opacity-100'
|
||||
: ''}"
|
||||
>
|
||||
<a href="https://windmill.dev" class="whitespace-nowrap text-tertiary inline-flex items-center"
|
||||
>Powered by <WindmillIcon /> Windmill</a
|
||||
>
|
||||
</div>
|
||||
|
||||
{#if !hideUser}
|
||||
<div class="z-50 text-2xs text-tertiary absolute top-3 left-2"
|
||||
>{#if $userStore}
|
||||
<div class="flex gap-1 items-center"><User size={14} />{$userStore.username}</div>
|
||||
{:else}<UserRoundX size={14} />{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if notExists}
|
||||
<div class="px-4 mt-20"
|
||||
><Alert type="error" title="Not found"
|
||||
>There was an error loading the app, is the url correct? <a href={base}>Go to Windmill</a>
|
||||
</Alert></div
|
||||
>
|
||||
{:else if noPermission}
|
||||
<div class="px-4 mt-20 w-full text-center font-bold text-xl"
|
||||
>{#if $userStore}You are logged in but have no read access for this app{:else}You must be
|
||||
logged in and have read access for this app{/if}</div
|
||||
>
|
||||
<div class="px-2 mx-auto mt-20 max-w-xl w-full">
|
||||
<Login
|
||||
loginPasswordRequireEEOnPublicApps
|
||||
on:login={() => {
|
||||
// window.location.reload()
|
||||
loadUser().then(() => {
|
||||
loadApp()
|
||||
})
|
||||
app = app
|
||||
}}
|
||||
popup
|
||||
rd={window.location.href}
|
||||
/>
|
||||
</div>
|
||||
{:else if app}
|
||||
{#key app}
|
||||
<div
|
||||
class={twMerge(
|
||||
'min-h-screen h-full w-full',
|
||||
app?.value?.['css']?.['app']?.['viewer']?.class,
|
||||
'wm-app-viewer'
|
||||
)}
|
||||
style={app?.value?.['css']?.['app']?.['viewer']?.style}
|
||||
>
|
||||
<AppPreview
|
||||
noBackend={false}
|
||||
username={$userStore?.username ?? 'anonymous'}
|
||||
email={$userStore?.email ?? 'anonymous'}
|
||||
groups={$userStore?.groups ?? []}
|
||||
{workspace}
|
||||
summary={app.summary}
|
||||
app={app.value}
|
||||
appPath={app.path}
|
||||
{breakpoint}
|
||||
author={app.policy.on_behalf_of_email ?? ''}
|
||||
isEditor={false}
|
||||
{replaceStateFn}
|
||||
{gotoFn}
|
||||
/>
|
||||
</div>
|
||||
{/key}
|
||||
{:else}
|
||||
<Skeleton layout={[[4], 0.5, [50]]} />
|
||||
{/if}
|
||||
</div>
|
||||
@@ -407,8 +407,24 @@
|
||||
enum_={itemsType?.enum ?? []}
|
||||
enumLabels={extra['enumLabels']}
|
||||
/>
|
||||
{:else if itemsType?.type == 'resource' && itemsType?.resourceType}
|
||||
<ResourcePicker bind:value={v} resourceType={itemsType?.resourceType} />
|
||||
{:else if itemsType?.type == 'resource' && itemsType?.resourceType && resourceTypes?.includes(itemsType.resourceType)}
|
||||
<ObjectResourceInput
|
||||
bind:value={v}
|
||||
format={'resource-' + itemsType?.resourceType}
|
||||
defaultValue={undefined}
|
||||
/>
|
||||
{:else if itemsType?.type == 'resource'}
|
||||
<JsonEditor
|
||||
bind:editor
|
||||
on:focus={(e) => {
|
||||
dispatch('focus')
|
||||
}}
|
||||
on:blur={(e) => {
|
||||
dispatch('blur')
|
||||
}}
|
||||
code={JSON.stringify(v, null, 2)}
|
||||
bind:value={v}
|
||||
/>
|
||||
{:else if itemsType?.type === 'object' && itemsType?.properties}
|
||||
<div class="p-8 border rounded-md w-full">
|
||||
<SchemaForm
|
||||
@@ -455,7 +471,20 @@
|
||||
if (value == undefined || !Array.isArray(value)) {
|
||||
value = []
|
||||
}
|
||||
value = value.concat('')
|
||||
if (itemsType?.type == 'number') {
|
||||
value = value.concat(0)
|
||||
} else if (
|
||||
itemsType?.type == 'object' ||
|
||||
(itemsType?.type == 'resource' &&
|
||||
!(
|
||||
itemsType?.resourceType &&
|
||||
resourceTypes?.includes(itemsType?.resourceType)
|
||||
))
|
||||
) {
|
||||
value = value.concat({})
|
||||
} else {
|
||||
value = value.concat('')
|
||||
}
|
||||
}}
|
||||
id="arg-input-add-item"
|
||||
startIcon={{ icon: Plus }}
|
||||
@@ -495,6 +524,7 @@
|
||||
{disablePortal}
|
||||
{format}
|
||||
bind:value
|
||||
bind:editor
|
||||
{showSchemaExplorer}
|
||||
/>
|
||||
{:else if inputCat == 'resource-object' && format.split('-').length > 1 && format
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { format, isValid } from 'date-fns'
|
||||
import { format, isValid, parse } from 'date-fns'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
|
||||
export let value: string | undefined = undefined
|
||||
export let autofocus: boolean | null = false
|
||||
@@ -8,14 +9,42 @@
|
||||
export let maxDate: string | undefined = undefined
|
||||
export let dateFormat: string | undefined = 'dd-MM-yyyy'
|
||||
|
||||
let date: string | undefined = undefined
|
||||
let date: string | undefined = computeDate(value)
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
const defaultDateFormat = 'dd-MM-yyyy'
|
||||
const defaultHtmlDateFormat = 'yyyy-MM-dd'
|
||||
function computeDate(value: string | undefined) {
|
||||
if (dateFormat === undefined) {
|
||||
dateFormat = defaultDateFormat
|
||||
}
|
||||
if (value && value.length > 0) {
|
||||
try {
|
||||
let date = parse(value, dateFormat, new Date())
|
||||
if (date.toString() === 'Invalid Date') {
|
||||
console.debug('falling back to default html date format')
|
||||
date = parse(value, defaultHtmlDateFormat, new Date())
|
||||
}
|
||||
const res = format(date, defaultHtmlDateFormat)
|
||||
return res
|
||||
} catch (error) {
|
||||
sendUserToast(
|
||||
`Failed to parse date: ${value} with format ${dateFormat} and ${defaultHtmlDateFormat}`,
|
||||
true
|
||||
)
|
||||
console.error(`Failed to parse date: ${value}`, error)
|
||||
return undefined
|
||||
}
|
||||
} else {
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
function updateValue(newDate: string | undefined) {
|
||||
if (newDate && isValid(new Date(newDate))) {
|
||||
if (dateFormat === undefined) {
|
||||
dateFormat = 'dd-MM-yyyy'
|
||||
dateFormat = defaultDateFormat
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
ArrowDownFromLine
|
||||
} from 'lucide-svelte'
|
||||
import Portal from '$lib/components/Portal.svelte'
|
||||
|
||||
import ObjectViewer from './propertyPicker/ObjectViewer.svelte'
|
||||
import S3FilePicker from './S3FilePicker.svelte'
|
||||
import Alert from './common/alert/Alert.svelte'
|
||||
@@ -44,6 +45,7 @@
|
||||
export let noControls: boolean = false
|
||||
export let drawerOpen = false
|
||||
export let nodeId: string | undefined = undefined
|
||||
export let language: string | undefined = undefined
|
||||
|
||||
const IMG_MAX_SIZE = 10000000
|
||||
const TABLE_MAX_SIZE = 5000000
|
||||
@@ -68,6 +70,7 @@
|
||||
| 'plain'
|
||||
| 'markdown'
|
||||
| 'map'
|
||||
| 'nondisplayable'
|
||||
| undefined
|
||||
|
||||
$: resultKind = inferResultKind(result)
|
||||
@@ -119,9 +122,13 @@
|
||||
let is_render_all = false
|
||||
let download_as_csv = false
|
||||
function inferResultKind(result: any) {
|
||||
if (result == 'WINDMILL_TOO_BIG') {
|
||||
largeObject = true
|
||||
return 'json'
|
||||
try {
|
||||
if (result == 'WINDMILL_TOO_BIG') {
|
||||
largeObject = true
|
||||
return 'json'
|
||||
}
|
||||
} catch (err) {
|
||||
return 'nondisplayable'
|
||||
}
|
||||
|
||||
if (result !== undefined) {
|
||||
@@ -243,7 +250,12 @@
|
||||
let s3FileViewer: S3FilePicker
|
||||
|
||||
function toJsonStr(result: any) {
|
||||
return JSON.stringify(result ?? null, null, 4) ?? 'null'
|
||||
try {
|
||||
// console.log(result)
|
||||
return JSON.stringify(result ?? null, null, 4) ?? 'null'
|
||||
} catch (e) {
|
||||
return 'error stringifying object: ' + e.toString()
|
||||
}
|
||||
}
|
||||
|
||||
function contentOrRootString(obj: string | { filename: string; content: string }) {
|
||||
@@ -377,17 +389,15 @@
|
||||
/>
|
||||
{/each}</div
|
||||
>
|
||||
{:else}
|
||||
<div
|
||||
{:else if resultKind == 'nondisplayable'}<div class="text-red-400">Non displayable object</div
|
||||
>{:else}<div
|
||||
class="inline-highlight relative grow {['plain', 'markdown'].includes(resultKind ?? '')
|
||||
? ''
|
||||
: 'min-h-[200px]'}"
|
||||
>
|
||||
{#if result != undefined && length != undefined && largeObject != undefined}
|
||||
<div class="flex justify-between items-center w-full">
|
||||
<div class="text-tertiary text-sm">
|
||||
{#if !hideAsJson && !['json', 's3object'].includes(resultKind ?? '') && typeof result === 'object'}
|
||||
<ToggleButtonGroup
|
||||
>{#if result != undefined && length != undefined && largeObject != undefined}<div
|
||||
class="flex justify-between items-center w-full"
|
||||
><div class="text-tertiary text-sm">
|
||||
{#if !hideAsJson && !['json', 's3object'].includes(resultKind ?? '') && typeof result === 'object'}<ToggleButtonGroup
|
||||
class="h-6"
|
||||
selected={forceJson ? 'json' : resultKind?.startsWith('table-') ? 'table' : 'pretty'}
|
||||
on:selected={(ev) => {
|
||||
@@ -537,13 +547,24 @@
|
||||
</div>
|
||||
{:else if !forceJson && resultKind == 'error' && result?.error}
|
||||
<div class="flex flex-col items-start">
|
||||
<span class="text-red-500 font-semibold text-sm whitespace-pre-wrap"
|
||||
<span class="text-red-500 pt-2 font-semibold !text-xs whitespace-pre-wrap"
|
||||
>{#if result.error.name || result.error.message}{result.error.name}: {result.error
|
||||
.message}{:else}{JSON.stringify(result.error, null, 4)}{/if}</span
|
||||
>
|
||||
<pre class="text-sm whitespace-pre-wrap text-primary">{result.error.stack ?? ''}</pre>
|
||||
<pre class="text-xs pt-2 whitespace-pre-wrap text-primary"
|
||||
>{result.error.stack ?? ''}</pre
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
{#if language == 'bun'}
|
||||
<div class="pt-20" />
|
||||
<Alert size="xs" type="info" title="Seeing an odd error?">
|
||||
Bun script are bundled for performance reasons. If you see an odd error that doesn't
|
||||
appear when testing (which doesn't use bundling), try putting <code>//nobundling</code
|
||||
> at the top of your script to disable bundling and feel free to mention it to the Windmill's
|
||||
team.
|
||||
</Alert>
|
||||
{/if}
|
||||
{:else if !forceJson && resultKind == 'approval'}<div class="flex flex-col gap-3 mt-2 mx-4">
|
||||
<Button
|
||||
color="green"
|
||||
|
||||
@@ -19,9 +19,10 @@
|
||||
import { hubBaseUrlStore } from '$lib/stores'
|
||||
|
||||
import { CheckCircle2, Loader2, RotateCw, XCircle } from 'lucide-svelte'
|
||||
import { hubPaths } from '$lib/hub'
|
||||
|
||||
const slackRecoveryHandler = 'hub/2430/slack/schedule-recovery-handler-slack'
|
||||
const slackHandlerScriptPath = 'hub/6512/workspace-or-schedule-error-handler-slack'
|
||||
const slackRecoveryHandler = hubPaths.slackRecoveryHandler
|
||||
const slackHandlerScriptPath = hubPaths.slackErrorHandler
|
||||
|
||||
export let errorOrRecovery: 'error' | 'recovery'
|
||||
export let isEditable: boolean
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<script lang="ts">
|
||||
import { FlowGraph } from './graph'
|
||||
|
||||
import type { FlowModule, FlowValue } from '$lib/gen'
|
||||
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
|
||||
import FlowGraphViewerStep from './FlowGraphViewerStep.svelte'
|
||||
import FlowGraphV2 from './graph/FlowGraphV2.svelte'
|
||||
|
||||
export let flow: {
|
||||
summary: string
|
||||
@@ -30,7 +29,7 @@
|
||||
class="{noSide ? 'col-span-3' : 'sm:col-span-2 col-span-3'} w-full border max-h-full"
|
||||
class:overflow-auto={overflowAuto}
|
||||
>
|
||||
<FlowGraph
|
||||
<FlowGraphV2
|
||||
{download}
|
||||
minHeight={400}
|
||||
modules={flow?.value?.modules}
|
||||
@@ -39,7 +38,6 @@
|
||||
stepDetail = e.detail
|
||||
dispatch('select', stepDetail)
|
||||
}}
|
||||
rebuildOnChange={flow}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
import type { DurationStatus } from './graph'
|
||||
import type { Writable } from 'svelte/store'
|
||||
|
||||
export let waitingForExecutor: boolean = false
|
||||
export let result: any
|
||||
export let logs: string | undefined
|
||||
export let col: boolean = false
|
||||
@@ -17,6 +18,7 @@
|
||||
export let loading: boolean
|
||||
export let filename: string | undefined = undefined
|
||||
export let jobId: string | undefined = undefined
|
||||
export let tag: string | undefined = undefined
|
||||
export let workspaceId: string | undefined = undefined
|
||||
export let refreshLog: boolean = false
|
||||
export let durationStates: Writable<Record<string, DurationStatus>> | undefined
|
||||
@@ -79,9 +81,9 @@
|
||||
{/if}
|
||||
</div>
|
||||
<div class="overflow-auto {col ? '' : 'max-h-80'} relative">
|
||||
<div class="absolute z-40 text-sm top-1.5 left-2"
|
||||
<div class="absolute z-40 text-xs top-0 left-1"
|
||||
><button class="" on:click={drawer.openDrawer}>explore all steps' logs</button></div
|
||||
>
|
||||
<LogViewer content={logs ?? ''} {jobId} isLoading={false} tag={undefined} />
|
||||
<LogViewer content={logs ?? ''} {jobId} isLoading={waitingForExecutor} {tag} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
export let workspaceId: string | undefined = undefined
|
||||
export let flowStateStore: Writable<FlowState> = writable({})
|
||||
export let selectedJobStep: string | undefined = undefined
|
||||
export let hideFlowResult = false
|
||||
|
||||
export let isOwner = false
|
||||
export let wideResults = false
|
||||
@@ -45,6 +46,7 @@
|
||||
</script>
|
||||
|
||||
<FlowStatusViewerInner
|
||||
{hideFlowResult}
|
||||
on:jobsLoaded={({ detail }) => {
|
||||
let { job } = detail
|
||||
if (job.script_path != lastScriptPath && job.script_path) {
|
||||
|
||||
@@ -16,12 +16,7 @@
|
||||
import { Badge, Button, Tab } from './common'
|
||||
import DisplayResult from './DisplayResult.svelte'
|
||||
import Tabs from './common/tabs/Tabs.svelte'
|
||||
import {
|
||||
FlowGraph,
|
||||
type DurationStatus,
|
||||
type FlowStatusViewerContext,
|
||||
type GraphModuleState
|
||||
} from './graph'
|
||||
import { type DurationStatus, type FlowStatusViewerContext, type GraphModuleState } from './graph'
|
||||
import ModuleStatus from './ModuleStatus.svelte'
|
||||
import { emptyString, msToSec, truncateRev } from '$lib/utils'
|
||||
import JobArgs from './JobArgs.svelte'
|
||||
@@ -33,6 +28,7 @@
|
||||
import { writable, type Writable } from 'svelte/store'
|
||||
import Alert from './common/alert/Alert.svelte'
|
||||
import FlowGraphViewerStep from './FlowGraphViewerStep.svelte'
|
||||
import FlowGraphV2 from './graph/FlowGraphV2.svelte'
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
@@ -69,6 +65,7 @@
|
||||
export let reducedPolling = false
|
||||
|
||||
export let wideResults = false
|
||||
export let hideFlowResult = false
|
||||
|
||||
let jobResults: any[] =
|
||||
flowJobIds?.flowJobs?.map((x, id) => `iter #${id + 1} not loaded by frontend yet`) ?? []
|
||||
@@ -170,7 +167,7 @@
|
||||
mod.type === 'WaitingForEvents' &&
|
||||
$localModuleStates?.[innerModules?.[i - 1]?.id ?? '']?.type == 'Success'
|
||||
) {
|
||||
setModuleState(mod.id ?? '', { type: mod.type, args: job?.args })
|
||||
setModuleState(mod.id ?? '', { type: mod.type, args: job?.args, tag: job?.tag })
|
||||
} else if (
|
||||
mod.type === 'WaitingForExecutor' &&
|
||||
$localModuleStates[mod.id ?? '']?.scheduled_for == undefined
|
||||
@@ -186,7 +183,8 @@
|
||||
scheduled_for: job?.['scheduled_for'],
|
||||
job_id: job?.id,
|
||||
parent_module: mod['parent_module'],
|
||||
args: job?.args
|
||||
args: job?.args,
|
||||
tag: job?.tag
|
||||
}
|
||||
setModuleState(mod.id ?? '', newState)
|
||||
})
|
||||
@@ -398,6 +396,7 @@
|
||||
job_id: job.id,
|
||||
logs: job.logs,
|
||||
args: job.args,
|
||||
tag: job.tag,
|
||||
started_at,
|
||||
parent_module: mod['parent_module']
|
||||
},
|
||||
@@ -416,6 +415,7 @@
|
||||
logs: job.logs,
|
||||
result: job['result'],
|
||||
job_id: job.id,
|
||||
tag: job.tag,
|
||||
parent_module: mod['parent_module'],
|
||||
duration_ms: job['duration_ms'],
|
||||
started_at: started_at,
|
||||
@@ -590,6 +590,7 @@
|
||||
let stepDetail: FlowModule | string | undefined = undefined
|
||||
|
||||
let storedListJobs: Record<number, Job> = {}
|
||||
let wrapperHeight: number = 0
|
||||
</script>
|
||||
|
||||
{#if notAnonynmous}
|
||||
@@ -642,16 +643,19 @@
|
||||
<Loader2 class="animate-spin" />
|
||||
</div>
|
||||
{:else if `result` in job}
|
||||
<div class="w-full h-full">
|
||||
<FlowJobResult
|
||||
workspaceId={job?.workspace_id}
|
||||
jobId={job?.id}
|
||||
loading={job['running'] == true}
|
||||
result={job.result}
|
||||
logs={job.logs}
|
||||
durationStates={localDurationStatuses}
|
||||
/>
|
||||
</div>
|
||||
{#if !hideFlowResult}
|
||||
<div class="w-full h-full">
|
||||
<FlowJobResult
|
||||
workspaceId={job?.workspace_id}
|
||||
jobId={job?.id}
|
||||
tag={job?.tag}
|
||||
loading={job['running'] == true}
|
||||
result={job.result}
|
||||
logs={job.logs}
|
||||
durationStates={localDurationStatuses}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
{:else if job.flow_status?.modules?.[job?.flow_status?.step]?.type === 'WaitingForEvents'}
|
||||
<FlowStatusWaitingForEvents {workspaceId} {job} {isOwner} />
|
||||
{:else if $suspendStatus && Object.keys($suspendStatus).length > 0}
|
||||
@@ -898,7 +902,7 @@
|
||||
{#if render}
|
||||
{#if job.raw_flow && !isListJob}
|
||||
<div class="{selected != 'graph' ? 'hidden' : ''} grow mt-4">
|
||||
<div class="grid grid-cols-3 border h-full">
|
||||
<div class="grid grid-cols-3 border h-full" bind:clientHeight={wrapperHeight}>
|
||||
<div class="col-span-2 bg-surface-secondary">
|
||||
<div class="flex flex-col">
|
||||
{#each Object.values($retryStatus) as count}
|
||||
@@ -917,8 +921,9 @@
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<FlowGraph
|
||||
<FlowGraphV2
|
||||
download
|
||||
minHeight={wrapperHeight}
|
||||
success={jobId != undefined && isSuccess(job?.['success'])}
|
||||
flowModuleStates={$localModuleStates}
|
||||
on:select={(e) => {
|
||||
@@ -943,6 +948,7 @@
|
||||
}}
|
||||
on:selectedIteration={(e) => {
|
||||
let detail = e.detail
|
||||
|
||||
setModuleState(detail.moduleId, {
|
||||
selectedForloop: detail.id,
|
||||
selectedForloopIndex: detail.index
|
||||
@@ -950,7 +956,6 @@
|
||||
globalRefreshes[detail.moduleId]?.({ job: detail.id, index: detail.index })
|
||||
}}
|
||||
modules={job.raw_flow?.modules ?? []}
|
||||
failureModule={job.raw_flow?.failure_module}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
@@ -984,6 +989,7 @@
|
||||
jobId={job?.id}
|
||||
filename={job.id}
|
||||
loading={job['running']}
|
||||
tag={job?.tag}
|
||||
noBorder
|
||||
col
|
||||
result={job['result']}
|
||||
@@ -1047,14 +1053,17 @@
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<FlowJobResult
|
||||
workspaceId={job?.workspace_id}
|
||||
jobId={node.job_id}
|
||||
noBorder
|
||||
loading={node.type != 'Success' && node.type != 'Failure'}
|
||||
waitingForExecutor={node.type == 'WaitingForExecutor'}
|
||||
refreshLog={node.type == 'InProgress'}
|
||||
col
|
||||
result={node.result}
|
||||
tag={node.tag}
|
||||
logs={node.logs}
|
||||
durationStates={localDurationStatuses}
|
||||
/>
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
}}
|
||||
iconOnly
|
||||
/>
|
||||
{#if code?.length < 5000}
|
||||
{#if code?.length < 10000}
|
||||
{#if !lines}
|
||||
<Highlight class="nowrap {$$props.class}" language={lang} {code} />
|
||||
{:else}
|
||||
@@ -82,7 +82,7 @@
|
||||
</Highlight>
|
||||
{/if}
|
||||
{:else}
|
||||
<pre class="overflow-auto max-h-screen {$$props.class}"
|
||||
<pre class="overflow-auto max-h-screen text-xs {$$props.class}"
|
||||
><code class="language-{language}">{code}</code></pre
|
||||
>
|
||||
{/if}
|
||||
|
||||
@@ -718,6 +718,7 @@
|
||||
/>
|
||||
{:else if setting.fieldType == 'password'}
|
||||
<input
|
||||
autocomplete="new-password"
|
||||
type="password"
|
||||
placeholder={setting.placeholder}
|
||||
bind:value={values[setting.key]}
|
||||
|
||||
@@ -181,9 +181,17 @@
|
||||
}
|
||||
|
||||
let prevDefaultValue: any = undefined
|
||||
let defaultChange = 0
|
||||
|
||||
async function changeDefaultValue(inputCat, defaultValue) {
|
||||
if (value == null || value == undefined || deepEqual(value, prevDefaultValue)) {
|
||||
if (
|
||||
value == null ||
|
||||
value == undefined ||
|
||||
deepEqual(value, prevDefaultValue) ||
|
||||
(prevDefaultValue != undefined && !deepEqual(defaultValue, prevDefaultValue))
|
||||
) {
|
||||
value = defaultValue
|
||||
defaultChange += 1
|
||||
}
|
||||
prevDefaultValue = structuredClone(defaultValue)
|
||||
|
||||
@@ -498,11 +506,13 @@
|
||||
{/each}
|
||||
</select>
|
||||
{:else if inputCat == 'date'}
|
||||
{#if format === 'date'}
|
||||
<DateInput bind:value dateFormat={extra['dateFormat']} />
|
||||
{:else}
|
||||
<DateTimeInput useDropdown bind:value />
|
||||
{/if}
|
||||
{#key defaultChange}
|
||||
{#if format === 'date'}
|
||||
<DateInput bind:value dateFormat={extra['dateFormat']} />
|
||||
{:else}
|
||||
<DateTimeInput useDropdown bind:value />
|
||||
{/if}
|
||||
{/key}
|
||||
{:else if inputCat == 'base64'}
|
||||
<div class="flex flex-col my-6 w-full">
|
||||
<input
|
||||
|
||||
@@ -71,7 +71,10 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class={twMerge('w-full flex flex-col px-0.5 pb-2', largeGap ? 'gap-8' : 'gap-2')}>
|
||||
<div
|
||||
class={twMerge('w-full flex flex-col px-0.5 pb-2', largeGap ? 'gap-8' : 'gap-2')}
|
||||
on:pointerdown
|
||||
>
|
||||
{#each keys as argName (argName)}
|
||||
{#if typeof args == 'object' && schema?.properties[argName] && args}
|
||||
<LightweightArgInput
|
||||
|
||||
@@ -96,10 +96,6 @@
|
||||
return content
|
||||
}
|
||||
|
||||
$: if (content != undefined && isLoading) {
|
||||
isLoading = false
|
||||
}
|
||||
|
||||
$: truncatedContent && scrollToBottom()
|
||||
|
||||
$: html = ansi_up.ansi_to_html(
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$lib/navigation'
|
||||
import Github from '$lib/components/icons/brands/Github.svelte'
|
||||
import Gitlab from '$lib/components/icons/brands/Gitlab.svelte'
|
||||
import Google from '$lib/components/icons/brands/Google.svelte'
|
||||
@@ -6,7 +7,7 @@
|
||||
import Okta from '$lib/components/icons/brands/Okta.svelte'
|
||||
|
||||
import { OauthService, UserService, WorkspaceService } from '$lib/gen'
|
||||
import { usersWorkspaceStore, workspaceStore, userStore, enterpriseLicense } from '$lib/stores'
|
||||
import { usersWorkspaceStore, workspaceStore, userStore } from '$lib/stores'
|
||||
import { classNames, emptyString, parseQueryParams } from '$lib/utils'
|
||||
import { base } from '$lib/base'
|
||||
import { getUserExt } from '$lib/user'
|
||||
@@ -21,10 +22,6 @@
|
||||
export let password: string | undefined = undefined
|
||||
export let error: string | undefined = undefined
|
||||
export let popup: boolean = false
|
||||
export let loginPasswordRequireEEOnPublicApps: boolean = false
|
||||
export let gotoFn: ((path: string, opt?: Record<string, any> | undefined) => void) | undefined =
|
||||
undefined
|
||||
export let baseApiUrl: string | undefined = undefined
|
||||
|
||||
const providers = [
|
||||
{
|
||||
@@ -86,19 +83,15 @@
|
||||
}
|
||||
|
||||
// Finally, we check whether the user is a superadmin
|
||||
refreshSuperadmin(gotoFn)
|
||||
if (gotoFn) {
|
||||
redirectUser()
|
||||
} else {
|
||||
dispatch('login')
|
||||
}
|
||||
refreshSuperadmin()
|
||||
redirectUser()
|
||||
}
|
||||
|
||||
async function redirectUser() {
|
||||
const firstTimeCookie =
|
||||
document.cookie.match('(^|;)\\s*first_time\\s*=\\s*([^;]+)')?.pop() || '0'
|
||||
if (Number(firstTimeCookie) > 0 && email === 'admin@windmill.dev') {
|
||||
gotoFn?.('/user/first-time')
|
||||
goto('/user/first-time')
|
||||
return
|
||||
}
|
||||
|
||||
@@ -107,12 +100,12 @@
|
||||
return
|
||||
}
|
||||
if ($workspaceStore) {
|
||||
gotoFn?.(rd ?? '/')
|
||||
goto(rd ?? '/')
|
||||
} else {
|
||||
let workspaceTarget = parseQueryParams(rd ?? undefined)['workspace']
|
||||
if (rd && workspaceTarget) {
|
||||
$workspaceStore = workspaceTarget
|
||||
gotoFn?.(rd)
|
||||
goto(rd)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -133,19 +126,19 @@
|
||||
workspace: $workspaceStore!
|
||||
})
|
||||
if (!emptyString(defaultApp.default_app_path)) {
|
||||
gotoFn?.(`/apps/get/${defaultApp.default_app_path}`)
|
||||
goto(`/apps/get/${defaultApp.default_app_path}`)
|
||||
} else {
|
||||
gotoFn?.(rd ?? '/')
|
||||
goto(rd ?? '/')
|
||||
}
|
||||
} else {
|
||||
gotoFn?.(rd ?? '/')
|
||||
goto(rd ?? '/')
|
||||
}
|
||||
} else if (rd?.startsWith('/user/workspaces')) {
|
||||
gotoFn?.(rd)
|
||||
goto(rd)
|
||||
} else if (rd == '/#user-settings') {
|
||||
gotoFn?.(`/user/workspaces#user-settings`)
|
||||
goto(`/user/workspaces#user-settings`)
|
||||
} else {
|
||||
gotoFn?.(`/user/workspaces${rd ? `?rd=${encodeURIComponent(rd)}` : ''}`)
|
||||
goto(`/user/workspaces${rd ? `?rd=${encodeURIComponent(rd)}` : ''}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -269,74 +262,68 @@
|
||||
{/if}
|
||||
|
||||
{#if showPassword}
|
||||
{#if loginPasswordRequireEEOnPublicApps && !$enterpriseLicense}
|
||||
<p class="text-xs text-red-400 italic p-6">
|
||||
To log in with email and password on a public app, Windmill requires an enterprise license
|
||||
</p>
|
||||
{:else}
|
||||
<div>
|
||||
<div class="space-y-6">
|
||||
{#if isCloudHosted()}
|
||||
<p class="text-xs text-tertiary italic pb-6">
|
||||
To get credentials without the OAuth providers above, send an email at
|
||||
contact@windmill.dev
|
||||
</p>
|
||||
{/if}
|
||||
<div>
|
||||
<div class="space-y-6">
|
||||
{#if isCloudHosted()}
|
||||
<p class="text-xs text-tertiary italic pb-6">
|
||||
To get credentials without the OAuth providers above, send an email at
|
||||
contact@windmill.dev
|
||||
</p>
|
||||
{/if}
|
||||
<div>
|
||||
<label for="email" class="block text-sm font-medium leading-6 text-primary">
|
||||
Email
|
||||
</label>
|
||||
<div>
|
||||
<label for="email" class="block text-sm font-medium leading-6 text-primary">
|
||||
Email
|
||||
</label>
|
||||
<div>
|
||||
<input
|
||||
type="email"
|
||||
bind:value={email}
|
||||
id="email"
|
||||
autocomplete="email"
|
||||
class="block w-full rounded-md border-0 py-1.5 text-primary shadow-sm ring-1 ring-inset placeholder:text-secondary focus:ring-2 focus:ring-inset focus:ring-frost-600 sm:text-sm sm:leading-6"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="password" class="block text-sm font-medium leading-6 text-primary">
|
||||
Password
|
||||
</label>
|
||||
<div>
|
||||
<input
|
||||
on:keyup={handleKeyUp}
|
||||
bind:value={password}
|
||||
id="password"
|
||||
type="password"
|
||||
autocomplete="current-password"
|
||||
class="block w-full rounded-md border-0 py-1.5 text-shadow shadow-sm ring-1 ring-inset placeholder:text-secondary focus:ring-2 focus:ring-inset focus:ring-frost-600 sm:text-sm sm:leading-6"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pt-2">
|
||||
<button
|
||||
on:click={login}
|
||||
disabled={!email || !password}
|
||||
class="flex w-full justify-center rounded-md bg-frost-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-frost-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-frost-600"
|
||||
>
|
||||
Sign in
|
||||
</button>
|
||||
<input
|
||||
type="email"
|
||||
bind:value={email}
|
||||
id="email"
|
||||
autocomplete="email"
|
||||
class="block w-full rounded-md border-0 py-1.5 text-primary shadow-sm ring-1 ring-inset placeholder:text-secondary focus:ring-2 focus:ring-inset focus:ring-frost-600 sm:text-sm sm:leading-6"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
{#if isCloudHosted()}
|
||||
<p class="text-2xs text-tertiary italic mt-10 text-center">
|
||||
By logging in, you agree to our
|
||||
<a href="https://windmill.dev/terms_of_service" target="_blank" rel="noreferrer">
|
||||
Terms of Service
|
||||
</a>
|
||||
and
|
||||
<a href="https://windmill.dev/privacy_policy" target="_blank" rel="noreferrer">
|
||||
Privacy Policy
|
||||
</a>
|
||||
</p>
|
||||
<div>
|
||||
<label for="password" class="block text-sm font-medium leading-6 text-primary">
|
||||
Password
|
||||
</label>
|
||||
<div>
|
||||
<input
|
||||
on:keyup={handleKeyUp}
|
||||
bind:value={password}
|
||||
id="password"
|
||||
type="password"
|
||||
autocomplete="current-password"
|
||||
class="block w-full rounded-md border-0 py-1.5 text-shadow shadow-sm ring-1 ring-inset placeholder:text-secondary focus:ring-2 focus:ring-inset focus:ring-frost-600 sm:text-sm sm:leading-6"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pt-2">
|
||||
<button
|
||||
on:click={login}
|
||||
disabled={!email || !password}
|
||||
class="flex w-full justify-center rounded-md bg-frost-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-frost-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-frost-600"
|
||||
>
|
||||
Sign in
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if isCloudHosted()}
|
||||
<p class="text-2xs text-tertiary italic mt-10 text-center">
|
||||
By logging in, you agree to our
|
||||
<a href="https://windmill.dev/terms_of_service" target="_blank" rel="noreferrer">
|
||||
Terms of Service
|
||||
</a>
|
||||
and
|
||||
<a href="https://windmill.dev/privacy_policy" target="_blank" rel="noreferrer">
|
||||
Privacy Policy
|
||||
</a>
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { createPopperActions } from 'svelte-popperjs'
|
||||
import type { PopoverPlacement } from './Popover.model'
|
||||
import Portal from '$lib/components/Portal.svelte'
|
||||
|
||||
import { fade } from 'svelte/transition'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
|
||||
|
||||
@@ -138,7 +138,7 @@
|
||||
duration={testJob?.['duration_ms']}
|
||||
mem={testJob?.['mem_peak']}
|
||||
content={testJob?.logs}
|
||||
isLoading={testIsLoading}
|
||||
isLoading={testIsLoading && testJob?.['running'] == false}
|
||||
tag={testJob?.tag}
|
||||
/>
|
||||
</Pane>
|
||||
|
||||
@@ -50,7 +50,9 @@
|
||||
}
|
||||
|
||||
function plugIt(argName: string) {
|
||||
args[argName] = evalValue(argName, mod, testStepStore, pickableProperties, true)
|
||||
args[argName] = structuredClone(
|
||||
evalValue(argName, mod, testStepStore, pickableProperties, true)
|
||||
)
|
||||
try {
|
||||
editor?.[argName]?.setCode(JSON.stringify(args[argName], null, 4))
|
||||
} catch {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<script lang="ts">
|
||||
import JsonEditor from './apps/editor/settingsPanel/inputEditor/JsonEditor.svelte'
|
||||
import ResourcePicker from './ResourcePicker.svelte'
|
||||
import S3ObjectPicker from './S3ObjectPicker.svelte'
|
||||
import SimpleEditor from './SimpleEditor.svelte'
|
||||
|
||||
export let format: string
|
||||
export let value: any
|
||||
@@ -8,6 +10,7 @@
|
||||
export let showSchemaExplorer = false
|
||||
export let selectFirst = false
|
||||
export let defaultValue: any
|
||||
export let editor: SimpleEditor | undefined = undefined
|
||||
|
||||
function isString(value: any) {
|
||||
return typeof value === 'string' || value instanceof String
|
||||
@@ -39,7 +42,7 @@
|
||||
<div class="flex flex-row w-full flex-wrap gap-x-2 gap-y-0.5">
|
||||
{#if format === 'resource-s3_object'}
|
||||
<S3ObjectPicker bind:value />
|
||||
{:else}
|
||||
{:else if value == undefined || typeof value === 'string'}
|
||||
<ResourcePicker
|
||||
{selectFirst}
|
||||
{disablePortal}
|
||||
@@ -52,5 +55,7 @@
|
||||
resourceType={format.split('-').length > 1 ? format.substring('resource-'.length) : undefined}
|
||||
{showSchemaExplorer}
|
||||
/>
|
||||
{:else}
|
||||
<JsonEditor bind:editor code={JSON.stringify(value, null, 2)} bind:value />
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -148,7 +148,7 @@
|
||||
<span class="text-tertiary text-2xs"
|
||||
>If left empty, will be derived automatically from $AWS_SECRET_KEY, pod or ec2 profile</span
|
||||
>
|
||||
<input type="password" bind:value={bucket_config.secret_key} />
|
||||
<input type="password" autocomplete="new-password" bind:value={bucket_config.secret_key} />
|
||||
</label>
|
||||
<label class="block pb-2">
|
||||
<span class="text-primary font-semibold text-sm">Endpoint</span>
|
||||
@@ -174,7 +174,7 @@
|
||||
</label>
|
||||
<label class="block pb-2">
|
||||
<span class="text-primary font-semibold text-sm">Access Key</span>
|
||||
<input type="password" bind:value={bucket_config.accessKey} />
|
||||
<input type="password" autocomplete="new-password" bind:value={bucket_config.accessKey} />
|
||||
</label>
|
||||
<label class="block pb-2">
|
||||
<span class="text-primary font-semibold text-sm"
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
type="password"
|
||||
bind:value={password}
|
||||
on:keydown
|
||||
autocomplete="off"
|
||||
autocomplete="new-password"
|
||||
{placeholder}
|
||||
{disabled}
|
||||
/>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { createPopperActions, type PopperOptions } from 'svelte-popperjs'
|
||||
import type { PopoverPlacement } from './Popover.model'
|
||||
import Portal from '$lib/components/Portal.svelte'
|
||||
|
||||
import { ExternalLink } from 'lucide-svelte'
|
||||
|
||||
export let placement: PopoverPlacement = 'bottom-end'
|
||||
|
||||
@@ -29,11 +29,11 @@
|
||||
}. Allowed types: string (CSS selector) or HTMLElement.`
|
||||
)
|
||||
}
|
||||
targetEl.appendChild(el)
|
||||
el.hidden = false
|
||||
if (!el.classList.contains('windmill-app')) {
|
||||
el.classList.add('windmill-app')
|
||||
}
|
||||
targetEl.appendChild(el)
|
||||
el.hidden = false
|
||||
}
|
||||
|
||||
function destroy() {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
import DarkModeObserver from './DarkModeObserver.svelte'
|
||||
import { Pen, Plus, RotateCw } from 'lucide-svelte'
|
||||
import ResourceEditorDrawer from './ResourceEditorDrawer.svelte'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
@@ -42,30 +43,38 @@
|
||||
appConnect?.open?.(resourceType, expressOAuthSetup)
|
||||
}
|
||||
|
||||
let loading = true
|
||||
async function loadResources(resourceType: string | undefined) {
|
||||
const nc = (
|
||||
await ResourceService.listResource({
|
||||
workspace: $workspaceStore!,
|
||||
resourceType
|
||||
})
|
||||
)
|
||||
.filter((x) => x.resource_type != 'state' && x.resource_type != 'cache')
|
||||
.map((x) => ({
|
||||
value: x.path,
|
||||
label: x.path,
|
||||
type: x.resource_type
|
||||
}))
|
||||
loading = true
|
||||
try {
|
||||
const nc = (
|
||||
await ResourceService.listResource({
|
||||
workspace: $workspaceStore!,
|
||||
resourceType
|
||||
})
|
||||
)
|
||||
.filter((x) => x.resource_type != 'state' && x.resource_type != 'cache')
|
||||
.map((x) => ({
|
||||
value: x.path,
|
||||
label: x.path,
|
||||
type: x.resource_type
|
||||
}))
|
||||
|
||||
// TODO check if this is needed
|
||||
if (!nc.find((x) => x.value == value) && (initialValue || value)) {
|
||||
nc.push({ value: value ?? initialValue!, label: value ?? initialValue!, type: '' })
|
||||
}
|
||||
collection = nc
|
||||
if (collection.length == 1 && selectFirst && valueSelect == undefined) {
|
||||
value = collection[0].value
|
||||
valueType = collection[0].type
|
||||
valueSelect = collection[0]
|
||||
// TODO check if this is needed
|
||||
if (!nc.find((x) => x.value == value) && (initialValue || value)) {
|
||||
nc.push({ value: value ?? initialValue!, label: value ?? initialValue!, type: '' })
|
||||
}
|
||||
collection = nc
|
||||
if (collection.length == 1 && selectFirst && valueSelect == undefined) {
|
||||
value = collection[0].value
|
||||
valueType = collection[0].type
|
||||
valueSelect = collection[0]
|
||||
}
|
||||
} catch (e) {
|
||||
sendUserToast('Failed to load resource types', true)
|
||||
console.error(e)
|
||||
}
|
||||
loading = false
|
||||
}
|
||||
|
||||
$: $workspaceStore && loadResources(resourceType)
|
||||
@@ -131,46 +140,48 @@
|
||||
? SELECT_INPUT_DEFAULT_STYLE.containerStylesDark
|
||||
: SELECT_INPUT_DEFAULT_STYLE.containerStyles}
|
||||
/>
|
||||
{:else}
|
||||
{:else if !loading}
|
||||
<div class="text-2xs text-tertiary mr-2">0 found</div>
|
||||
{/if}
|
||||
|
||||
{#if value && value != ''}
|
||||
<Button
|
||||
{disabled}
|
||||
color="light"
|
||||
variant="border"
|
||||
size="xs"
|
||||
on:click={() => resourceEditor?.initEdit?.(value ?? '')}
|
||||
startIcon={{ icon: Pen }}
|
||||
iconOnly
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if resourceType?.includes(',')}
|
||||
{#each resourceType.split(',') as rt}
|
||||
{#if !loading}
|
||||
{#if value && value != ''}
|
||||
<Button
|
||||
{disabled}
|
||||
color="light"
|
||||
variant="border"
|
||||
size="xs"
|
||||
on:click={() => appConnect?.open?.(rt)}
|
||||
startIcon={{ icon: Plus }}>{rt}</Button
|
||||
on:click={() => resourceEditor?.initEdit?.(value ?? '')}
|
||||
startIcon={{ icon: Pen }}
|
||||
iconOnly
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if resourceType?.includes(',')}
|
||||
{#each resourceType.split(',') as rt}
|
||||
<Button
|
||||
{disabled}
|
||||
color="light"
|
||||
variant="border"
|
||||
size="xs"
|
||||
on:click={() => appConnect?.open?.(rt)}
|
||||
startIcon={{ icon: Plus }}>{rt}</Button
|
||||
>
|
||||
{/each}
|
||||
{:else}
|
||||
<Button
|
||||
{disabled}
|
||||
color="light"
|
||||
variant="border"
|
||||
size="xs"
|
||||
on:click={() => appConnect?.open?.(resourceType, expressOAuthSetup)}
|
||||
startIcon={{ icon: Plus }}
|
||||
iconOnly={collection?.length > 0}
|
||||
>{#if collection?.length == 0}
|
||||
Add a {resourceType} resource
|
||||
{/if}</Button
|
||||
>
|
||||
{/each}
|
||||
{:else}
|
||||
<Button
|
||||
{disabled}
|
||||
color="light"
|
||||
variant="border"
|
||||
size="xs"
|
||||
on:click={() => appConnect?.open?.(resourceType, expressOAuthSetup)}
|
||||
startIcon={{ icon: Plus }}
|
||||
iconOnly={collection?.length > 0}
|
||||
>{#if collection?.length == 0}
|
||||
Add a {resourceType} resource
|
||||
{/if}</Button
|
||||
>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
<Button
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
import type { Writable } from 'svelte/store'
|
||||
import type { GroupContext } from '../types'
|
||||
|
||||
export let groupContext: Writable<Record<string, any>>
|
||||
export let context: Writable<Record<string, any>>
|
||||
export let id: string
|
||||
|
||||
setContext<GroupContext>('GroupContext', groupContext)
|
||||
setContext<GroupContext>('GroupContext', { id, context })
|
||||
</script>
|
||||
|
||||
<slot />
|
||||
|
||||
@@ -126,20 +126,23 @@
|
||||
<div
|
||||
class={twMerge('p-2 overflow-auto h-full', css?.container?.class, 'wm-schema-form')}
|
||||
style={css?.container?.style}
|
||||
on:pointerdown|stopPropagation={(e) =>
|
||||
!$connectingInput.opened && selectId(e, id, selectedComponent, $app)}
|
||||
>
|
||||
<LightweightSchemaForm
|
||||
defaultValues={resolvedConfig.defaultValues}
|
||||
dynamicEnums={resolvedConfig.dynamicEnums}
|
||||
schema={result}
|
||||
bind:isValid={valid}
|
||||
bind:args
|
||||
bind:this={schemaForm}
|
||||
displayType={Boolean(resolvedConfig.displayType)}
|
||||
largeGap={Boolean(resolvedConfig.largeGap)}
|
||||
{css}
|
||||
/>
|
||||
<div
|
||||
on:pointerdown|stopPropagation={(e) =>
|
||||
!$connectingInput.opened && selectId(e, id, selectedComponent, $app)}
|
||||
>
|
||||
<LightweightSchemaForm
|
||||
defaultValues={resolvedConfig.defaultValues}
|
||||
dynamicEnums={resolvedConfig.dynamicEnums}
|
||||
schema={result}
|
||||
bind:isValid={valid}
|
||||
bind:args
|
||||
bind:this={schemaForm}
|
||||
displayType={Boolean(resolvedConfig.displayType)}
|
||||
largeGap={Boolean(resolvedConfig.largeGap)}
|
||||
{css}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<p class="m-2 italic">Empty form (no property)</p>
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
duration={testJob?.['duration_ms']}
|
||||
mem={testJob?.['mem_peak']}
|
||||
content={testJob?.logs}
|
||||
isLoading={testIsLoading}
|
||||
isLoading={testIsLoading && testJob?.['running'] == false}
|
||||
tag={testJob?.tag}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
export let render: boolean
|
||||
export let horizontalAlignment: 'left' | 'center' | 'right' | undefined = undefined
|
||||
|
||||
const { app, worldStore } = getContext<AppViewerContext>('AppViewerContext')
|
||||
const { app, worldStore, policy } = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
let resolvedConfig = initConfig(
|
||||
components['recomputeallcomponent'].initialData.configuration,
|
||||
@@ -59,7 +59,7 @@
|
||||
<InitializeComponent {id} />
|
||||
|
||||
<AlignWrapper {horizontalAlignment}>
|
||||
{#if render}
|
||||
{#if render && policy}
|
||||
<RecomputeAllWrapper
|
||||
containerClass={css?.container?.class}
|
||||
containerStyle={css?.container?.style}
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
import { Drawer, DrawerContent } from '$lib/components/common'
|
||||
import InsertRow from './InsertRow.svelte'
|
||||
import Portal from '$lib/components/Portal.svelte'
|
||||
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import type { AppInput, StaticInput } from '$lib/components/apps/inputType'
|
||||
import DbExplorerCount from './DbExplorerCount.svelte'
|
||||
|
||||
+22
-5
@@ -126,20 +126,21 @@
|
||||
['ContextPanel', contextPanel]
|
||||
])
|
||||
|
||||
new AppAggridTableActions({
|
||||
const ta = new AppAggridTableActions({
|
||||
target: c.eGui,
|
||||
props: {
|
||||
p,
|
||||
id: id,
|
||||
actions,
|
||||
rowIndex,
|
||||
row,
|
||||
render: true,
|
||||
wrapActions: resolvedConfig.wrapActions,
|
||||
selectRow: () => {
|
||||
selectRow: (p) => {
|
||||
toggleRow(p)
|
||||
p.node.setSelected(true)
|
||||
},
|
||||
onSet: (id, value) => {
|
||||
onSet: (id, value, rowIndex) => {
|
||||
if (!inputs[id]) {
|
||||
inputs[id] = { [rowIndex]: value }
|
||||
} else {
|
||||
@@ -148,7 +149,7 @@
|
||||
|
||||
outputs?.inputs.set(inputs, true)
|
||||
},
|
||||
onRemove: (id) => {
|
||||
onRemove: (id, rowIndex) => {
|
||||
if (inputs?.[id] == undefined) {
|
||||
return
|
||||
}
|
||||
@@ -163,6 +164,14 @@
|
||||
},
|
||||
context: componentContext
|
||||
})
|
||||
return {
|
||||
destroy: () => {
|
||||
ta.$destroy()
|
||||
},
|
||||
refresh(params) {
|
||||
ta.$set({ rowIndex: params.node.rowIndex ?? 0, row: params.data, p: params })
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
function transformColumnDefs(columnDefs: any[] | undefined) {
|
||||
@@ -184,7 +193,7 @@
|
||||
field: 'delete',
|
||||
headerName: 'Delete',
|
||||
cellRenderer: cellRendererFactory((c, p) => {
|
||||
new Button({
|
||||
let ta = new Button({
|
||||
target: c.eGui,
|
||||
props: {
|
||||
btnClasses: 'w-12',
|
||||
@@ -197,6 +206,14 @@
|
||||
nonCaptureEvent: true
|
||||
}
|
||||
})
|
||||
return {
|
||||
destroy: () => {
|
||||
ta.$destroy()
|
||||
},
|
||||
refresh(params) {
|
||||
//
|
||||
}
|
||||
}
|
||||
}),
|
||||
cellRendererParams: {
|
||||
onClick: (e) => {
|
||||
|
||||
@@ -123,7 +123,7 @@
|
||||
}
|
||||
|
||||
if (!deepEqual(outputs?.selectedRow?.peak(), data)) {
|
||||
outputs?.selectedRow.set(data)
|
||||
outputs?.selectedRow?.set(data)
|
||||
}
|
||||
|
||||
if (iterContext && listInputs) {
|
||||
@@ -202,20 +202,21 @@
|
||||
['ContextPanel', contextPanel]
|
||||
])
|
||||
|
||||
new AppAggridTableActions({
|
||||
let ta = new AppAggridTableActions({
|
||||
target: c.eGui,
|
||||
props: {
|
||||
p,
|
||||
id: id,
|
||||
actions,
|
||||
rowIndex,
|
||||
row,
|
||||
render,
|
||||
wrapActions: resolvedConfig.wrapActions,
|
||||
selectRow: () => {
|
||||
selectRow: (p) => {
|
||||
toggleRow(p)
|
||||
p.node.setSelected(true)
|
||||
},
|
||||
onSet: (id, value) => {
|
||||
onSet: (id, value, rowIndex) => {
|
||||
if (!inputs[id]) {
|
||||
inputs[id] = { [rowIndex]: value }
|
||||
} else {
|
||||
@@ -224,7 +225,7 @@
|
||||
|
||||
outputs?.inputs.set(inputs, true)
|
||||
},
|
||||
onRemove: (id) => {
|
||||
onRemove: (id, rowIndex) => {
|
||||
if (inputs?.[id] == undefined) {
|
||||
return
|
||||
}
|
||||
@@ -239,6 +240,15 @@
|
||||
},
|
||||
context: componentContext
|
||||
})
|
||||
|
||||
return {
|
||||
destroy: () => {
|
||||
ta.$destroy()
|
||||
},
|
||||
refresh(params) {
|
||||
ta.$set({ rowIndex: params.node.rowIndex ?? 0, row: params.data, p: params })
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
function mountGrid() {
|
||||
|
||||
+26
-11
@@ -16,16 +16,18 @@
|
||||
import ComponentOutputViewer from '$lib/components/apps/editor/contextPanel/ComponentOutputViewer.svelte'
|
||||
import { connectOutput } from '$lib/components/apps/editor/appUtils'
|
||||
import RowWrapper from '../../layout/RowWrapper.svelte'
|
||||
import type { ICellRendererParams } from 'ag-grid-community'
|
||||
|
||||
export let p: ICellRendererParams<any>
|
||||
export let id: string
|
||||
export let render: boolean
|
||||
export let actions: TableAction[] = []
|
||||
export let rowIndex: number
|
||||
export let row: { original: Record<string, any> }
|
||||
export let onSet: (id: string, value: any) => void
|
||||
export let onRemove: (id: string) => void
|
||||
export let onSet: (id: string, value: any, rowIndex: number) => void
|
||||
export let onRemove: (id: string, rowIndex: number) => void
|
||||
export let wrapActions: boolean | undefined = undefined
|
||||
export let selectRow: () => void
|
||||
export let selectRow: (params: ICellRendererParams<any>) => void
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
const { selectedComponent, hoverStore, mode, connectingInput } =
|
||||
@@ -39,12 +41,25 @@
|
||||
const parent = rowDiv.parentElement?.parentElement?.parentElement
|
||||
if (parent) {
|
||||
parent.classList.add('w-full')
|
||||
} else {
|
||||
//sometimes the parent is not available immediately
|
||||
setTimeout(() => {
|
||||
const parent = rowDiv?.parentElement?.parentElement?.parentElement
|
||||
if (parent) {
|
||||
parent.classList.add('w-full')
|
||||
}
|
||||
}, 10)
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<RowWrapper value={row} index={rowIndex} {onSet} {onRemove}>
|
||||
<RowWrapper
|
||||
value={row}
|
||||
index={rowIndex}
|
||||
onSet={(id, value) => onSet(id, value, rowIndex)}
|
||||
onRemove={(id) => onRemove(id, rowIndex)}
|
||||
>
|
||||
<div
|
||||
class={twMerge(
|
||||
'flex flex-row justify-center items-center gap-4 h-full px-4 py-1 w-full',
|
||||
@@ -68,7 +83,7 @@
|
||||
}
|
||||
}}
|
||||
on:pointerdown|stopPropagation={(e) => {
|
||||
selectRow()
|
||||
selectRow(p)
|
||||
|
||||
if (!$connectingInput.opened) {
|
||||
$selectedComponent = [action.id]
|
||||
@@ -170,7 +185,7 @@
|
||||
noWFull
|
||||
preclickAction={async () => {
|
||||
dispatch('toggleRow')
|
||||
selectRow()
|
||||
selectRow(p)
|
||||
}}
|
||||
id={action.id}
|
||||
customCss={action.customCss}
|
||||
@@ -196,7 +211,7 @@
|
||||
onToggle={action.onToggle}
|
||||
preclickAction={async () => {
|
||||
dispatch('toggleRow')
|
||||
selectRow()
|
||||
selectRow(p)
|
||||
}}
|
||||
verticalAlignment="center"
|
||||
{controls}
|
||||
@@ -215,7 +230,7 @@
|
||||
onSelect={action.onSelect}
|
||||
preclickAction={async () => {
|
||||
dispatch('toggleRow')
|
||||
selectRow()
|
||||
selectRow(p)
|
||||
}}
|
||||
{controls}
|
||||
/>
|
||||
@@ -227,7 +242,7 @@
|
||||
{render}
|
||||
preclickAction={async () => {
|
||||
dispatch('toggleRow')
|
||||
selectRow()
|
||||
selectRow(p)
|
||||
}}
|
||||
noWFull
|
||||
id={action.id}
|
||||
@@ -252,7 +267,7 @@
|
||||
onToggle={action.onToggle}
|
||||
preclickAction={async () => {
|
||||
dispatch('toggleRow')
|
||||
selectRow()
|
||||
selectRow(p)
|
||||
}}
|
||||
/>
|
||||
{:else if action.type == 'selectcomponent'}
|
||||
@@ -269,7 +284,7 @@
|
||||
onSelect={action.onSelect}
|
||||
preclickAction={async () => {
|
||||
dispatch('toggleRow')
|
||||
selectRow()
|
||||
selectRow(p)
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
@@ -80,7 +80,11 @@
|
||||
{:else}
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div on:dblclick={toggleEdit}>
|
||||
{value}
|
||||
{#if typeof value == 'object'}
|
||||
{JSON.stringify(value)}
|
||||
{:else}
|
||||
{value}
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</td>
|
||||
|
||||
@@ -28,8 +28,11 @@
|
||||
for (let i = 0; i < objArray.length; i++) {
|
||||
let line = ''
|
||||
for (let j = 0; j < headers.length; j++) {
|
||||
const value = objArray[i][headers[j]]
|
||||
let value = objArray[i][headers[j]]
|
||||
line += j ? ',' : ''
|
||||
if (typeof value != 'string') {
|
||||
value = JSON.stringify(value)
|
||||
}
|
||||
line += /[\",\n]/.test(value) ? '"' + value.replace(/"/g, '""') + '"' : value
|
||||
}
|
||||
str += line + '\r\n'
|
||||
|
||||
@@ -11,18 +11,21 @@ import type { ICellRendererComp, ICellRendererParams } from 'ag-grid-community'
|
||||
*/
|
||||
export abstract class AbstractCellRenderer implements ICellRendererComp {
|
||||
eGui: any
|
||||
protected value: any
|
||||
protected params: any
|
||||
protected component:
|
||||
| {
|
||||
refresh: (params: ICellRendererParams) => void
|
||||
destroy: () => void
|
||||
}
|
||||
| undefined
|
||||
constructor(parentElement = 'span') {
|
||||
// create empty span (or other element) to place svelte component in
|
||||
this.component = undefined
|
||||
this.eGui = document.createElement(parentElement)
|
||||
}
|
||||
|
||||
init(params: ICellRendererParams & { onClick?: (data: any) => void }) {
|
||||
this.value = params.value
|
||||
this.createComponent(params)
|
||||
this.component = this.createComponent(params)
|
||||
this.eGui.addEventListener('click', () => params.onClick?.(params.data))
|
||||
this.params = params
|
||||
}
|
||||
|
||||
getGui() {
|
||||
@@ -30,11 +33,13 @@ export abstract class AbstractCellRenderer implements ICellRendererComp {
|
||||
}
|
||||
|
||||
refresh(params: ICellRendererParams) {
|
||||
this.value = params.value
|
||||
|
||||
this.component?.refresh?.(params)
|
||||
return true
|
||||
}
|
||||
|
||||
destroy(): void {
|
||||
this.component?.destroy?.()
|
||||
}
|
||||
/**
|
||||
* Define and create the svelte component to use in the cell
|
||||
* @example
|
||||
@@ -48,7 +53,10 @@ export abstract class AbstractCellRenderer implements ICellRendererComp {
|
||||
* }
|
||||
* @param params params for rendering the call, including the value for the cell
|
||||
*/
|
||||
abstract createComponent(params: ICellRendererParams): void
|
||||
abstract createComponent(params: ICellRendererParams): {
|
||||
refresh: (params: ICellRendererParams) => void
|
||||
destroy: () => void
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,11 +66,20 @@ export abstract class AbstractCellRenderer implements ICellRendererComp {
|
||||
* @returns
|
||||
*/
|
||||
export function cellRendererFactory(
|
||||
svelteComponent: (cell: AbstractCellRenderer, params: ICellRendererParams) => void
|
||||
svelteComponent: (
|
||||
cell: AbstractCellRenderer,
|
||||
params: ICellRendererParams
|
||||
) => {
|
||||
refresh: (params: ICellRendererParams) => void
|
||||
destroy: () => void
|
||||
}
|
||||
) {
|
||||
class Renderer extends AbstractCellRenderer {
|
||||
createComponent(params: ICellRendererParams<any, any>): void {
|
||||
svelteComponent(this, params)
|
||||
createComponent(params: ICellRendererParams<any, any>): {
|
||||
refresh: (params: ICellRendererParams) => void
|
||||
destroy: () => void
|
||||
} {
|
||||
return svelteComponent(this, params)
|
||||
}
|
||||
}
|
||||
return Renderer
|
||||
|
||||
@@ -43,10 +43,12 @@
|
||||
|
||||
let previousConnectedValues: Record<string, any> = {}
|
||||
|
||||
let groupStore = groupContext?.context
|
||||
|
||||
$: fullContext = {
|
||||
iter: iterContext ? $iterContext : undefined,
|
||||
row: rowContext ? $rowContext : undefined,
|
||||
group: groupContext ? $groupContext : undefined
|
||||
group: groupStore ? $groupStore : undefined
|
||||
}
|
||||
|
||||
$: lastInput?.type == 'evalv2' &&
|
||||
@@ -272,7 +274,8 @@
|
||||
$componentControl,
|
||||
$worldStore,
|
||||
$runnableComponents,
|
||||
false
|
||||
false,
|
||||
groupContext?.id
|
||||
)
|
||||
error = ''
|
||||
return r
|
||||
@@ -297,7 +300,8 @@
|
||||
$componentControl,
|
||||
$worldStore,
|
||||
$runnableComponents,
|
||||
false
|
||||
false,
|
||||
groupContext?.id
|
||||
)
|
||||
error = ''
|
||||
return r
|
||||
|
||||
@@ -279,14 +279,15 @@
|
||||
computeGlobalContext($worldStore, {
|
||||
iter: iterContext ? $iterContext : undefined,
|
||||
row: rowContext ? $rowContext : undefined,
|
||||
group: groupContext ? $groupContext : undefined
|
||||
group: groupContext ? get(groupContext.context) : undefined
|
||||
}),
|
||||
$state,
|
||||
isEditor,
|
||||
$componentControl,
|
||||
$worldStore,
|
||||
$runnableComponents,
|
||||
true
|
||||
true,
|
||||
groupContext?.id
|
||||
)
|
||||
|
||||
await setResult(r, job)
|
||||
@@ -504,6 +505,7 @@
|
||||
computeGlobalContext($worldStore, {
|
||||
iter: iterContext ? $iterContext : undefined,
|
||||
row: rowContext ? $rowContext : undefined,
|
||||
group: groupContext ? get(groupContext.context) : undefined,
|
||||
result: res
|
||||
}),
|
||||
$state,
|
||||
@@ -511,7 +513,8 @@
|
||||
$componentControl,
|
||||
$worldStore,
|
||||
$runnableComponents,
|
||||
true
|
||||
true,
|
||||
groupContext?.id
|
||||
)
|
||||
return transformerResult
|
||||
} catch (err) {
|
||||
@@ -656,6 +659,18 @@
|
||||
bgRuns.update((runs) => runs.filter((r) => r !== id))
|
||||
}
|
||||
}
|
||||
|
||||
function getError(obj: any) {
|
||||
try {
|
||||
if (obj?.error) {
|
||||
return obj.error
|
||||
}
|
||||
return undefined
|
||||
} catch (e) {
|
||||
console.error('Error accessing error from result', e)
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{#each Object.entries(fields ?? {}) as [key, v] (key)}
|
||||
@@ -750,7 +765,7 @@
|
||||
<Alert type="warning" size="xs" class="mt-2 px-1" title="Missing runnable">
|
||||
Please select a runnable
|
||||
</Alert>
|
||||
{:else if result?.error && $mode === 'preview' && !errorHandledByComponent}
|
||||
{:else if getError(result) && $mode === 'preview' && !errorHandledByComponent}
|
||||
<div
|
||||
title="Error"
|
||||
class={classNames(
|
||||
|
||||
@@ -25,11 +25,11 @@ function create_context_function_template(
|
||||
) {
|
||||
let hasReturnAsLastLine = noReturn || eval_string.split('\n').some((x) => x.startsWith('return '))
|
||||
return `
|
||||
return async function (context, state, goto, setTab, recompute, getAgGrid, setValue, setSelectedIndex, openModal, closeModal, open, close, validate, invalidate, validateAll, clearFiles, showToast, waitJob, askNewResource) {
|
||||
return async function (context, state, createProxy, goto, setTab, recompute, getAgGrid, setValue, setSelectedIndex, openModal, closeModal, open, close, validate, invalidate, validateAll, clearFiles, showToast, waitJob, askNewResource) {
|
||||
"use strict";
|
||||
${
|
||||
contextKeys && contextKeys.length > 0
|
||||
? `let ${contextKeys.map((key) => ` ${key} = context['${key}']`)};`
|
||||
? `let ${contextKeys.map((key) => ` ${key} = createProxy('${key}', context['${key}'])`)};`
|
||||
: ``
|
||||
}
|
||||
${
|
||||
@@ -46,6 +46,7 @@ return ${eval_string.startsWith('return ') ? eval_string.substring(7) : eval_str
|
||||
type WmFunctor = (
|
||||
context,
|
||||
state,
|
||||
createProxy,
|
||||
goto,
|
||||
setTab,
|
||||
recompute,
|
||||
@@ -113,30 +114,72 @@ export async function eval_like(
|
||||
showToast?: (message: string, error?: boolean) => void
|
||||
waitJob?: (jobId: string) => void
|
||||
askNewResource?: () => void
|
||||
setGroupValue?: (key: string, value: any) => void
|
||||
}
|
||||
>,
|
||||
worldStore: World | undefined,
|
||||
runnableComponents: Record<string, { cb?: (() => void)[] }>,
|
||||
noReturn: boolean
|
||||
noReturn: boolean,
|
||||
groupContextId: string | undefined
|
||||
) {
|
||||
const proxiedState = new Proxy(state, {
|
||||
set(target, key, value) {
|
||||
if (typeof key !== 'string') {
|
||||
throw new Error('Invalid key')
|
||||
const createProxy = (name: string, obj: any) => {
|
||||
// console.log('Creating proxy', name, obj)
|
||||
if (obj != null && obj != undefined && typeof obj == 'object') {
|
||||
if (name == 'group' && groupContextId) {
|
||||
return createGroupProxy(groupContextId, obj)
|
||||
}
|
||||
target[key] = value
|
||||
let o = worldStore?.newOutput('state', key, value)
|
||||
o?.set(value, true)
|
||||
return new Proxy(obj, {
|
||||
set(target, key, value) {
|
||||
if (name != 'state') {
|
||||
throw new Error(
|
||||
'Cannot set value on objects that are neither the global state or a container group field'
|
||||
)
|
||||
}
|
||||
if (typeof key !== 'string') {
|
||||
throw new Error('Invalid key')
|
||||
}
|
||||
target[key] = value
|
||||
let o = worldStore?.newOutput(name, key, value)
|
||||
o?.set(value, true)
|
||||
|
||||
return true
|
||||
return true
|
||||
},
|
||||
get(obj, prop) {
|
||||
if (name != 'state' && prop == 'group') {
|
||||
return createGroupProxy(name, obj[prop])
|
||||
} else {
|
||||
return obj[prop]
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
return obj
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const createGroupProxy = (name: string, obj: any) => {
|
||||
return new Proxy(obj, {
|
||||
set(target, key, value) {
|
||||
target[key] = value
|
||||
let o = worldStore?.newOutput(name, 'group', target)
|
||||
o?.set(target, true)
|
||||
if (typeof key !== 'string') {
|
||||
throw new Error('Invalid key')
|
||||
}
|
||||
controlComponents[name]?.setGroupValue?.(key, value)
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const proxiedState = createProxy('state', state)
|
||||
|
||||
let evaluator = make_context_evaluator(text, Object.keys(context ?? {}), noReturn)
|
||||
// console.log(i, j)
|
||||
return await evaluator(
|
||||
context,
|
||||
proxiedState,
|
||||
createProxy,
|
||||
async (x, newTab) => {
|
||||
if (newTab || editor) {
|
||||
if (!newTab) {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
// @ts-ignore
|
||||
import MultiSelect from 'svelte-multiselect'
|
||||
import Portal from '$lib/components/Portal.svelte'
|
||||
|
||||
import { createFloatingActions } from 'svelte-floating-ui'
|
||||
import { extractCustomProperties } from '$lib/utils'
|
||||
import { tick } from 'svelte'
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
import ResolveConfig from '../helpers/ResolveConfig.svelte'
|
||||
// @ts-ignore
|
||||
import Portal from '$lib/components/Portal.svelte'
|
||||
|
||||
import { createFloatingActions } from 'svelte-floating-ui'
|
||||
import { extractCustomProperties } from '$lib/utils'
|
||||
import { tick } from 'svelte'
|
||||
|
||||
@@ -173,6 +173,7 @@
|
||||
!$connectingInput.opened && selectId(e, id, selectedComponent, $app)}
|
||||
on:keydown|stopPropagation
|
||||
type="password"
|
||||
autocomplete="new-password"
|
||||
bind:value
|
||||
placeholder={resolvedConfig.placeholder}
|
||||
disabled={resolvedConfig.disabled}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { getContext } from 'svelte'
|
||||
import { getContext, onMount } from 'svelte'
|
||||
import { initOutput } from '../../editor/appUtils'
|
||||
import SubGridEditor from '../../editor/SubGridEditor.svelte'
|
||||
import type { AppViewerContext, ComponentCustomCSS, RichConfigurations } from '../../types'
|
||||
@@ -18,7 +18,7 @@
|
||||
export let render: boolean
|
||||
export let groupFields: RichConfigurations | undefined = undefined
|
||||
|
||||
const { app, focusedGrid, selectedComponent, worldStore, connectingInput } =
|
||||
const { app, focusedGrid, selectedComponent, worldStore, connectingInput, componentControl } =
|
||||
getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
let groupContext = writable({})
|
||||
@@ -34,6 +34,17 @@
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
$componentControl[id] = {
|
||||
setGroupValue: (field: string, value: any) => {
|
||||
groupContext.update((group) => {
|
||||
group[field] = value
|
||||
return group
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
let css = initCss($app.css?.containercomponent, customCss)
|
||||
</script>
|
||||
|
||||
@@ -57,7 +68,7 @@
|
||||
|
||||
<div class="w-full h-full">
|
||||
{#if $app.subgrids?.[`${id}-0`]}
|
||||
<GroupWrapper {groupContext}>
|
||||
<GroupWrapper {id} context={groupContext}>
|
||||
<SubGridEditor
|
||||
visible={render}
|
||||
{id}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import SubGridEditor from '../../editor/SubGridEditor.svelte'
|
||||
import type { AppViewerContext, ComponentCustomCSS, RichConfigurations } from '../../types'
|
||||
import Portal from '$lib/components/Portal.svelte'
|
||||
|
||||
import { initCss } from '../../utils'
|
||||
import { Button, Drawer, DrawerContent } from '$lib/components/common'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
import { initConfig, initOutput, maxHeight, ROW_GAP_Y, ROW_HEIGHT } from '../../editor/appUtils'
|
||||
import InitializeComponent from '../helpers/InitializeComponent.svelte'
|
||||
import Portal from '$lib/components/Portal.svelte'
|
||||
|
||||
import { clickOutside } from '$lib/utils'
|
||||
import { X } from 'lucide-svelte'
|
||||
import { components } from '../../editor/component'
|
||||
|
||||
@@ -119,8 +119,8 @@
|
||||
email: $userStore?.email,
|
||||
groups: $userStore?.groups,
|
||||
username: $userStore?.username,
|
||||
query: Object.fromEntries(new URLSearchParams(window.location.search).entries()),
|
||||
hash: window.location.hash,
|
||||
query: Object.fromEntries($page.url.searchParams.entries()),
|
||||
hash: $page.url.hash,
|
||||
workspace: $workspaceStore,
|
||||
mode: 'editor',
|
||||
summary: $summaryStore,
|
||||
@@ -168,6 +168,7 @@
|
||||
previewTheme,
|
||||
debuggingComponents: writable({}),
|
||||
replaceStateFn: (path) => replaceState(path, $page.state),
|
||||
policy: policy,
|
||||
recomputeAllContext: writable({
|
||||
loading: false,
|
||||
componentNumber: 0,
|
||||
@@ -217,10 +218,6 @@
|
||||
function hashchange(e: HashChangeEvent) {
|
||||
context.hash = e.newURL.split('#')[1]
|
||||
context = context
|
||||
worldStore.update((x) => {
|
||||
x.outputsById?.['ctx']?.['hash'].set(context.hash, true)
|
||||
return x
|
||||
})
|
||||
}
|
||||
|
||||
$: context.mode = $mode == 'dnd' ? 'editor' : 'viewer'
|
||||
@@ -573,7 +570,7 @@
|
||||
app={$appStore}
|
||||
appPath={path}
|
||||
{breakpoint}
|
||||
author={policy.on_behalf_of_email ?? ''}
|
||||
{policy}
|
||||
isEditor
|
||||
{context}
|
||||
noBackend={false}
|
||||
|
||||
@@ -938,17 +938,19 @@
|
||||
<h2>Public URL</h2>
|
||||
<div class="mt-4" />
|
||||
|
||||
<Toggle
|
||||
options={{
|
||||
left: `Require login and read-access`,
|
||||
right: `No login required`
|
||||
}}
|
||||
checked={policy.execution_mode == 'anonymous'}
|
||||
on:change={(e) => {
|
||||
policy.execution_mode = e.detail ? 'anonymous' : 'publisher'
|
||||
setPublishState()
|
||||
}}
|
||||
/>
|
||||
<div class="flex gap-2 items-center">
|
||||
<Toggle
|
||||
options={{
|
||||
left: `Require login and read-access`,
|
||||
right: `No login required`
|
||||
}}
|
||||
checked={policy.execution_mode == 'anonymous'}
|
||||
on:change={(e) => {
|
||||
policy.execution_mode = e.detail ? 'anonymous' : 'publisher'
|
||||
setPublishState()
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="my-6 box">
|
||||
Public url:
|
||||
@@ -975,10 +977,14 @@
|
||||
of embedding app must be the same as the one of Windmill)</div
|
||||
>
|
||||
</div>
|
||||
|
||||
<Alert type="info" title="Only latest deployed app is publicly available">
|
||||
You will still need to deploy the app to make visible the latest changes
|
||||
</Alert>
|
||||
|
||||
<a
|
||||
href="https://www.windmill.dev/docs/advanced/external_auth_with_jwt#embed-public-apps-using-your-own-authentification"
|
||||
class="mt-4 text-2xs">Embed this app in your own product to be used by your own users</a
|
||||
>
|
||||
{/if}
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
@@ -1147,14 +1153,14 @@
|
||||
duration={job?.['duration_ms']}
|
||||
jobId={job?.id}
|
||||
content={job?.logs}
|
||||
isLoading={testIsLoading}
|
||||
isLoading={testIsLoading && job?.['running'] == false}
|
||||
tag={job?.tag}
|
||||
/>
|
||||
</Pane>
|
||||
<Pane size={50} minSize={10} class="text-sm text-secondary">
|
||||
{#if job != undefined && 'result' in job && job.result != undefined}
|
||||
<div class="relative h-full px-2">
|
||||
<DisplayResult
|
||||
{#if job != undefined && 'result' in job && job.result != undefined}<div
|
||||
class="relative h-full px-2"
|
||||
><DisplayResult
|
||||
workspaceId={$workspaceStore}
|
||||
jobId={selectedJobId}
|
||||
result={job.result}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
EditorBreakpoint,
|
||||
EditorMode
|
||||
} from '../types'
|
||||
import type { Policy } from '$lib/gen'
|
||||
import Button from '../../common/button/Button.svelte'
|
||||
import { Unlock } from 'lucide-svelte'
|
||||
import GridViewer from './GridViewer.svelte'
|
||||
@@ -18,7 +19,7 @@
|
||||
import { deepEqual } from 'fast-equals'
|
||||
import { dfs, maxHeight } from './appUtils'
|
||||
import { BG_PREFIX, migrateApp } from '../utils'
|
||||
import { workspaceStore, enterpriseLicense, userStore } from '$lib/stores'
|
||||
import { workspaceStore, enterpriseLicense } from '$lib/stores'
|
||||
import DarkModeObserver from '$lib/components/DarkModeObserver.svelte'
|
||||
import { getTheme } from './componentsPanel/themeUtils'
|
||||
import HiddenComponent from '../components/helpers/HiddenComponent.svelte'
|
||||
@@ -27,11 +28,11 @@
|
||||
export let app: App
|
||||
export let appPath: string = ''
|
||||
export let breakpoint: Writable<EditorBreakpoint> = writable('lg')
|
||||
export let author: string
|
||||
export let policy: Policy = {}
|
||||
export let summary: string = ''
|
||||
export let workspace: string = $workspaceStore!
|
||||
export let isEditor: boolean = false
|
||||
|
||||
export let context: Record<string, any>
|
||||
export let noBackend: boolean = false
|
||||
export let isLocked = false
|
||||
export let hideRefreshBar = false
|
||||
@@ -45,10 +46,6 @@
|
||||
|
||||
migrateApp(app)
|
||||
|
||||
let email: string = $userStore?.email ?? 'anonymous'
|
||||
let groups: string[] = $userStore?.groups ?? []
|
||||
let username: string = $userStore?.username ?? 'anonymous'
|
||||
|
||||
const appStore = writable<App>(app)
|
||||
const selectedComponent = writable<string[] | undefined>(undefined)
|
||||
const mode = writable<EditorMode>('preview')
|
||||
@@ -62,15 +59,11 @@
|
||||
const allIdsInPath = writable<string[]>([])
|
||||
|
||||
let ncontext: any = {
|
||||
email,
|
||||
groups,
|
||||
username,
|
||||
query: Object.fromEntries(new URLSearchParams(window.location.search).entries()),
|
||||
hash: window.location.hash,
|
||||
...context,
|
||||
workspace,
|
||||
mode: 'viewer',
|
||||
summary: summary,
|
||||
author
|
||||
author: policy.on_behalf_of_email
|
||||
}
|
||||
|
||||
function resizeWindow() {
|
||||
@@ -87,15 +80,7 @@
|
||||
let parentContext = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
let worldStore = buildWorld(ncontext)
|
||||
|
||||
$: onContextChange({
|
||||
email,
|
||||
groups,
|
||||
username,
|
||||
workspace,
|
||||
summary: summary,
|
||||
author
|
||||
})
|
||||
$: onContextChange(context)
|
||||
|
||||
function onContextChange(context: any) {
|
||||
Object.assign(ncontext, context)
|
||||
@@ -151,6 +136,7 @@
|
||||
debuggingComponents: writable({}),
|
||||
replaceStateFn,
|
||||
gotoFn,
|
||||
policy,
|
||||
recomputeAllContext: writable({
|
||||
loading: false,
|
||||
componentNumber: 0,
|
||||
@@ -253,7 +239,7 @@
|
||||
<h2 class="truncate">{summary}</h2>
|
||||
<RecomputeAllComponents />
|
||||
<div class="text-2xs text-secondary">
|
||||
{author != '' ? `on behalf of ${author}` : ''}
|
||||
{policy.on_behalf_of ? `on behalf of ${policy.on_behalf_of_email}` : ''}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
import { RotateCw, Save } from 'lucide-svelte'
|
||||
import { CUSTOM_TAGS_SETTING, WORKSPACE_SLACK_BOT_TOKEN_PATH } from '$lib/consts'
|
||||
import { loadSchemaFromPath } from '$lib/infer'
|
||||
import { hubPaths } from '$lib/hub'
|
||||
export let appPath: string
|
||||
export let open = false
|
||||
|
||||
@@ -187,7 +188,7 @@ export async function main(app_path: string, startup_duration = 5, kind: 'pdf' |
|
||||
|
||||
const notificationScripts = {
|
||||
discord: {
|
||||
path: 'hub/7838/discord',
|
||||
path: hubPaths.discordReport,
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
@@ -203,7 +204,7 @@ export async function main(app_path: string, startup_duration = 5, kind: 'pdf' |
|
||||
}
|
||||
},
|
||||
slack: {
|
||||
path: 'hub/7836/slack', // if to be updated, also update it in in backend/windmill-queue/src/jobs.rs
|
||||
path: hubPaths.slackReport, // if to be updated, also update it in in backend/windmill-queue/src/jobs.rs
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
@@ -216,7 +217,7 @@ export async function main(app_path: string, startup_duration = 5, kind: 'pdf' |
|
||||
}
|
||||
},
|
||||
email: {
|
||||
path: 'hub/7837/smtp',
|
||||
path: hubPaths.smtpReport,
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
|
||||
@@ -179,7 +179,7 @@
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<AppPreview author="" noBackend app={selected.value} />
|
||||
<AppPreview noBackend app={selected.value} context={{}} />
|
||||
{:else}
|
||||
<Skeleton layout={[[40]]} />
|
||||
{/if}
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
import { secondaryMenuLeft } from './settingsPanel/secondaryMenu'
|
||||
import { clickOutside } from '$lib/utils'
|
||||
import Portal from '$lib/components/Portal.svelte'
|
||||
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
|
||||
let contextMenuVisible = false
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user