mirror of
https://github.com/johndoe6345789/low-code-react-app-b.git
synced 2026-04-24 13:44:54 +00:00
Generated by Spark: 0s
3m 30s Run docker/build-push-action@v5 GitHub Actions runtime token ACs Docker info Proxy configuration Buildx version Builder info /usr/bin/docker buildx build --cache-from type=gha --cache-to type=gha,mode=max --iidfile /home/runner/work/_temp/docker-actions-toolkit-vCLgYd/build-iidfile-0726305e33.txt --label org.opencontainers.image.created=2026-01-17T14:42:34.857Z --label org.opencontainers.image.description= --label org.opencontainers.image.licenses=MIT --label org.opencontainers.image.revision=33ab37bd18767139f14fd99e455eb90c1baa5af3 --label org.opencontainers.image.source=https://github.com/johndoe6345789/low-code-react-app-b --label org.opencontainers.image.title=low-code-react-app-b --label org.opencontainers.image.url=https://github.com/johndoe6345789/low-code-react-app-b --label org.opencontainers.image.version=main --platform linux/amd64,linux/arm64 --attest type=provenance,mode=max,builder-id=https://github.com/johndoe6345789/low-code-react-app-b/actions/runs/21095926434 --tag ghcr.io/johndoe6345789/low-code-react-app-b:main --tag ghcr.io/johndoe6345789/low-code-react-app-b:main-33ab37b --metadata-file /home/runner/work/_temp/docker-actions-toolkit-vCLgYd/build-metadata-daa99149c8.json --push . #0 building with "builder-95fadb03-ad83-4e01-bc20-225d7bda06ae" instance using docker-container driver #1 [internal] load build definition from Dockerfile #1 transferring dockerfile: 942B done #1 DONE 0.0s #2 [auth] library/nginx:pull token for registry-1.docker.io #2 DONE 0.0s #3 [auth] library/node:pull token for registry-1.docker.io #3 DONE 0.0s #4 [linux/arm64 internal] load metadata for docker.io/library/node:20-alpine #4 ... #5 [linux/arm64 internal] load metadata for docker.io/library/nginx:alpine #5 DONE 0.4s #4 [linux/arm64 internal] load metadata for docker.io/library/node:20-alpine #4 DONE 0.4s #6 [internal] load .dockerignore #6 transferring context: 344B done #6 DONE 0.0s #7 [linux/amd64 internal] load metadata for docker.io/library/node:20-alpine #7 DONE 0.4s #8 [linux/amd64 internal] load metadata for docker.io/library/nginx:alpine #8 DONE 0.4s #9 [internal] load build context #9 DONE 0.0s #10 [linux/amd64 builder 1/8] FROM docker.io/library/node:20-alpine@sha256:3960ed74dfe320a67bf8da9555b6bade25ebda2b22b6081d2f60fd7d5d430e9c #10 resolve docker.io/library/node:20-alpine@sha256:3960ed74dfe320a67bf8da9555b6bade25ebda2b22b6081d2f60fd7d5d430e9c done #10 DONE 0.0s #11 [linux/amd64 runtime 1/3] FROM docker.io/library/nginx:alpine@sha256:b0f7830b6bfaa1258f45d94c240ab668ced1b3651c8a222aefe6683447c7bf55 #11 resolve docker.io/library/nginx:alpine@sha256:b0f7830b6bfaa1258f45d94c240ab668ced1b3651c8a222aefe6683447c7bf55 done #11 DONE 0.0s #12 importing cache manifest from gha:8468054678720030062 #12 DONE 0.1s #13 [linux/arm64 builder 1/8] FROM docker.io/library/node:20-alpine@sha256:3960ed74dfe320a67bf8da9555b6bade25ebda2b22b6081d2f60fd7d5d430e9c #13 resolve docker.io/library/node:20-alpine@sha256:3960ed74dfe320a67bf8da9555b6bade25ebda2b22b6081d2f60fd7d5d430e9c done #13 sha256:2e74b1344e24146a5181cea893d6035d8d412a89b8374e4d4360f6c35d985760 444B / 444B 0.0s done #13 sha256:38d6ffd8958149c983c185c5a62d19cba7ee8807466e60c7993d78a2867eef11 1.26MB / 1.26MB 0.1s done #13 sha256:f6b4fb9446345fcad2db26eac181fef6c0a919c8a4fcccd3bea5deb7f6dff67e 4.20MB / 4.20MB 0.1s done #13 extracting sha256:f6b4fb9446345fcad2db26eac181fef6c0a919c8a4fcccd3bea5deb7f6dff67e #13 ... #9 [internal] load build context #9 transferring context: 10.19MB 0.2s done #9 DONE 0.2s #14 [linux/amd64 builder 3/8] COPY package*.json ./ #14 CACHED #15 [linux/amd64 builder 4/8] COPY packages/spark-tools ./packages/spark-tools #15 CACHED #16 [linux/amd64 builder 5/8] COPY packages/spark ./packages/spark #16 CACHED #17 [linux/amd64 builder 2/8] WORKDIR /app #17 CACHED #13 [linux/arm64 builder 1/8] FROM docker.io/library/node:20-alpine@sha256:3960ed74dfe320a67bf8da9555b6bade25ebda2b22b6081d2f60fd7d5d430e9c #13 sha256:efc83bacf48e781625d7de46541986e8525b67c1b1644803b5ff90d4ad73425c 17.83MB / 43.12MB 0.2s #13 extracting sha256:f6b4fb9446345fcad2db26eac181fef6c0a919c8a4fcccd3bea5deb7f6dff67e 0.2s done #13 sha256:efc83bacf48e781625d7de46541986e8525b67c1b1644803b5ff90d4ad73425c 43.12MB / 43.12MB 0.3s done #13 extracting sha256:efc83bacf48e781625d7de46541986e8525b67c1b1644803b5ff90d4ad73425c #13 ... #18 [linux/arm64 runtime 1/3] FROM docker.io/library/nginx:alpine@sha256:b0f7830b6bfaa1258f45d94c240ab668ced1b3651c8a222aefe6683447c7bf55 #18 resolve docker.io/library/nginx:alpine@sha256:b0f7830b6bfaa1258f45d94c240ab668ced1b3651c8a222aefe6683447c7bf55 0.0s done #18 sha256:f4f04eae8d5eb8a0220a0d542da10f9c55b57a585dea1875cfbb1ee99d4c5a4a 1.40kB / 1.40kB 0.0s done #18 sha256:ceb87b8ac279a84fc99bdc30e7406cf21bf5d5841819fd0e3c8e0c06d867533c 1.21kB / 1.21kB 0.0s done #18 sha256:6628835d87d286d4d03f10b2c7f51d00f4556c49b5874947ce02609379069575 403B / 403B 0.0s done #18 sha256:8a735f2296d46b598dbc65289bfdc2ec4dd07607e69a1887e4ce6ef898be56e1 19.66MB / 19.66MB 0.2s done #18 sha256:c0de4eea5b769c1703c4428a21cf0cce5b0a1668738391f1443979bb32cc9bc1 954B / 954B 0.0s done #18 sha256:9076aaa4fd77085ce5562e9aca2b51ca88baf3fb8e41f8c777d0df14a1ce1085 628B / 628B 0.0s done #18 sha256:a0ef6d8231d0e512c7a0c0f7029bcfb8c77f0848b9cb8ec5373b28991c83415b 1.87MB / 1.87MB 0.1s done #18 extracting sha256:a0ef6d8231d0e512c7a0c0f7029bcfb8c77f0848b9cb8ec5373b28991c83415b 0.1s done #18 extracting sha256:9076aaa4fd77085ce5562e9aca2b51ca88baf3fb8e41f8c777d0df14a1ce1085 done #18 extracting sha256:c0de4eea5b769c1703c4428a21cf0cce5b0a1668738391f1443979bb32cc9bc1 done #18 extracting sha256:6628835d87d286d4d03f10b2c7f51d00f4556c49b5874947ce02609379069575 done #18 extracting sha256:ceb87b8ac279a84fc99bdc30e7406cf21bf5d5841819fd0e3c8e0c06d867533c done #18 extracting sha256:f4f04eae8d5eb8a0220a0d542da10f9c55b57a585dea1875cfbb1ee99d4c5a4a done #18 extracting sha256:8a735f2296d46b598dbc65289bfdc2ec4dd07607e69a1887e4ce6ef898be56e1 0.5s done #18 DONE 1.1s #19 [linux/amd64 builder 6/8] RUN npm install --legacy-peer-deps #19 sha256:acec9428f22bd20125c716a65e27ad75480a1360a59ad4f816044044dad7cc70 4.34kB / 4.34kB 0.0s done #19 sha256:41b3afaea3b1b1ab04a268431e10dcace7883019a5da7d326aa35dc9713fcbb5 445B / 445B 0.0s done #19 sha256:1d55258e311479e00466346e8c753c9b7e01237604cee9e4b28b24139f418bb9 92B / 92B 0.0s done #19 sha256:3dcec91425079e7b455efc5f2a18d026450c47c9382c41897620afc6b1424e44 1.26MB / 1.26MB 0.1s done #19 sha256:c2b4197efb6ccd7f8b482ae7800f1c9c78c044ea192587887300080bcff6b2c9 42.78MB / 42.78MB 0.4s done #19 sha256:1074353eec0db2c1d81d5af2671e56e00cf5738486f5762609ea33d606f88612 3.86MB / 3.86MB 0.2s done #19 extracting sha256:1074353eec0db2c1d81d5af2671e56e00cf5738486f5762609ea33d606f88612 0.1s done #19 sha256:f4b3dc64ea273c67c4ed06bca84314742da987ddac1c2a30392f4ac39f9e1ff2 1.55MB / 1.55MB 0.2s done #19 sha256:70e3e49db568901de1214b56a8a69068f5f1d1a21781d8afc9840854c1233580 48.98kB / 48.98kB 0.0s done #19 sha256:828eb50cf87505f63ae57d13f4ce4484bf70ef66a718d8b5745753055ade6c3d 29.36MB / 264.20MB 0.8s #19 extracting sha256:c2b4197efb6ccd7f8b482ae7800f1c9c78c044ea192587887300080bcff6b2c9 #19 sha256:828eb50cf87505f63ae57d13f4ce4484bf70ef66a718d8b5745753055ade6c3d 42.99MB / 264.20MB 1.1s #19 ... #13 [linux/arm64 builder 1/8] FROM docker.io/library/node:20-alpine@sha256:3960ed74dfe320a67bf8da9555b6bade25ebda2b22b6081d2f60fd7d5d430e9c #13 extracting sha256:efc83bacf48e781625d7de46541986e8525b67c1b1644803b5ff90d4ad73425c 1.2s done #13 DONE 1.6s #13 [linux/arm64 builder 1/8] FROM docker.io/library/node:20-alpine@sha256:3960ed74dfe320a67bf8da9555b6bade25ebda2b22b6081d2f60fd7d5d430e9c #13 extracting sha256:38d6ffd8958149c983c185c5a62d19cba7ee8807466e60c7993d78a2867eef11 0.0s done #13 extracting sha256:2e74b1344e24146a5181cea893d6035d8d412a89b8374e4d4360f6c35d985760 done #13 DONE 1.6s #19 [linux/amd64 builder 6/8] RUN npm install --legacy-peer-deps #19 sha256:828eb50cf87505f63ae57d13f4ce4484bf70ef66a718d8b5745753055ade6c3d 59.77MB / 264.20MB 1.5s #19 extracting sha256:c2b4197efb6ccd7f8b482ae7800f1c9c78c044ea192587887300080bcff6b2c9 1.5s done #19 extracting sha256:3dcec91425079e7b455efc5f2a18d026450c47c9382c41897620afc6b1424e44 0.1s done #19 ... #20 [linux/arm64 builder 2/8] WORKDIR /app #20 DONE 0.7s #19 [linux/amd64 builder 6/8] RUN npm install --legacy-peer-deps #19 sha256:828eb50cf87505f63ae57d13f4ce4484bf70ef66a718d8b5745753055ade6c3d 77.59MB / 264.20MB 2.0s #19 extracting sha256:41b3afaea3b1b1ab04a268431e10dcace7883019a5da7d326aa35dc9713fcbb5 done #19 extracting sha256:1d55258e311479e00466346e8c753c9b7e01237604cee9e4b28b24139f418bb9 done #19 extracting sha256:70e3e49db568901de1214b56a8a69068f5f1d1a21781d8afc9840854c1233580 0.0s done #19 extracting sha256:f4b3dc64ea273c67c4ed06bca84314742da987ddac1c2a30392f4ac39f9e1ff2 0.1s done #19 ... #21 [linux/arm64 builder 3/8] COPY package*.json ./ #21 DONE 0.1s #22 [linux/arm64 builder 4/8] COPY packages/spark-tools ./packages/spark-tools #22 DONE 0.1s #23 [linux/arm64 builder 5/8] COPY packages/spark ./packages/spark #23 DONE 0.0s #19 [linux/amd64 builder 6/8] RUN npm install --legacy-peer-deps #19 extracting sha256:acec9428f22bd20125c716a65e27ad75480a1360a59ad4f816044044dad7cc70 done #19 sha256:828eb50cf87505f63ae57d13f4ce4484bf70ef66a718d8b5745753055ade6c3d 96.47MB / 264.20MB 2.4s #19 sha256:828eb50cf87505f63ae57d13f4ce4484bf70ef66a718d8b5745753055ade6c3d 115.34MB / 264.20MB 2.9s #19 sha256:828eb50cf87505f63ae57d13f4ce4484bf70ef66a718d8b5745753055ade6c3d 128.97MB / 264.20MB 3.2s #19 sha256:828eb50cf87505f63ae57d13f4ce4484bf70ef66a718d8b5745753055ade6c3d 143.65MB / 264.20MB 3.5s #19 sha256:828eb50cf87505f63ae57d13f4ce4484bf70ef66a718d8b5745753055ade6c3d 162.53MB / 264.20MB 3.9s #19 sha256:828eb50cf87505f63ae57d13f4ce4484bf70ef66a718d8b5745753055ade6c3d 179.31MB / 264.20MB 4.4s #19 sha256:828eb50cf87505f63ae57d13f4ce4484bf70ef66a718d8b5745753055ade6c3d 195.04MB / 264.20MB 4.7s #19 sha256:828eb50cf87505f63ae57d13f4ce4484bf70ef66a718d8b5745753055ade6c3d 212.86MB / 264.20MB 5.1s #19 sha256:828eb50cf87505f63ae57d13f4ce4484bf70ef66a718d8b5745753055ade6c3d 226.49MB / 264.20MB 5.4s #19 sha256:828eb50cf87505f63ae57d13f4ce4484bf70ef66a718d8b5745753055ade6c3d 244.32MB / 264.20MB 5.9s #19 sha256:828eb50cf87505f63ae57d13f4ce4484bf70ef66a718d8b5745753055ade6c3d 259.00MB / 264.20MB 6.2s #19 sha256:828eb50cf87505f63ae57d13f4ce4484bf70ef66a718d8b5745753055ade6c3d 264.20MB / 264.20MB 6.5s done #19 extracting sha256:828eb50cf87505f63ae57d13f4ce4484bf70ef66a718d8b5745753055ade6c3d #19 ... #24 [linux/arm64 builder 6/8] RUN npm install --legacy-peer-deps #24 ... #19 [linux/amd64 builder 6/8] RUN npm install --legacy-peer-deps #19 extracting sha256:828eb50cf87505f63ae57d13f4ce4484bf70ef66a718d8b5745753055ade6c3d 12.5s done #19 DONE 19.2s #25 [linux/amd64 builder 7/8] COPY . . #25 DONE 2.2s #24 [linux/arm64 builder 6/8] RUN npm install --legacy-peer-deps #24 ... #26 [linux/amd64 builder 8/8] RUN npm run build #26 0.230 #26 0.230 > spark-template@0.0.0 prebuild #26 0.230 > mkdir -p /tmp/dist || true #26 0.230 #26 0.238 #26 0.238 > spark-template@0.0.0 build #26 0.238 > tsc -b --noCheck && vite build #26 0.238 #26 6.457 vite v7.3.1 building client environment for production... #26 6.575 transforming... #26 10.05 Found 3 warnings while optimizing generated CSS: #26 10.05 #26 10.05 Issue #1: #26 10.05 │ .container { #26 10.05 │ width: 100%; #26 10.05 │ @media (width >= (display-mode: standalone)) { #26 10.05 ┆ ^-- Unexpected token ParenthesisBlock #26 10.05 ┆ #26 10.05 │ max-width: (display-mode: standalone); #26 10.05 │ } #26 10.05 #26 10.05 Issue #2: #26 10.05 │ max-width: (display-mode: standalone); #26 10.05 │ } #26 10.05 │ @media (width >= (pointer: coarse)) { #26 10.05 ┆ ^-- Unexpected token ParenthesisBlock #26 10.05 ┆ #26 10.05 │ max-width: (pointer: coarse); #26 10.05 │ } #26 10.05 #26 10.05 Issue #3: #26 10.05 │ max-width: (pointer: coarse); #26 10.05 │ } #26 10.05 │ @media (width >= (pointer: fine)) { #26 10.05 ┆ ^-- Unexpected token ParenthesisBlock #26 10.05 ┆ #26 10.05 │ max-width: (pointer: fine); #26 10.05 │ } #26 10.05 #26 27.53 ✓ 8276 modules transformed. #26 30.49 rendering chunks... #26 ... #24 [linux/arm64 builder 6/8] RUN npm install --legacy-peer-deps #24 55.47 npm warn deprecated whatwg-encoding@3.1.1: Use @exodus/bytes instead for a more spec-conformant and faster implementation #24 ... #26 [linux/amd64 builder 8/8] RUN npm run build #26 56.97 computing gzip size... #26 57.13 dist/index.html 2.18 kB │ gzip: 0.87 kB #26 57.13 dist/assets/FeatureIdeaCloud-B5DZHykP.css 7.32 kB │ gzip: 1.60 kB #26 57.13 dist/assets/index-DeAuhr8c.css 451.83 kB │ gzip: 78.84 kB #26 57.13 dist/assets/separator-DxaExrET.js 1.12 kB │ gzip: 0.59 kB #26 57.13 dist/assets/PWAStatusBar-BxRnFKIe.js 1.14 kB │ gzip: 0.64 kB #26 57.13 dist/assets/tabs-uv1gileV.js 1.34 kB │ gzip: 0.59 kB #26 57.13 dist/assets/PreviewDialog-CRbuRmHJ.js 1.36 kB │ gzip: 0.74 kB #26 57.13 dist/assets/PWAUpdatePrompt-A5H3Brsn.js 1.67 kB │ gzip: 0.82 kB #26 57.13 dist/assets/PWAInstallPrompt-BXeSE-7b.js 2.31 kB │ gzip: 1.02 kB #26 57.13 dist/assets/protected-llm-service-Q4cNm1rY.js 2.41 kB │ gzip: 1.00 kB #26 57.13 dist/assets/use-pwa-CN3ny1f7.js 2.42 kB │ gzip: 0.95 kB #26 57.13 dist/assets/KeyboardShortcutsDialog-BpO-G7Ko.js 2.54 kB │ gzip: 0.89 kB #26 57.13 dist/assets/switch-Le0tcnoA.js 2.57 kB │ gzip: 1.26 kB #26 57.13 dist/assets/skeleton-DvZARUoK.js 2.85 kB │ gzip: 1.34 kB #26 57.13 dist/assets/FeatureToggleSettings-DyoCP9xu.js 3.36 kB │ gzip: 1.40 kB #26 57.13 dist/assets/select-CUM2wG-b.js 3.62 kB │ gzip: 1.29 kB #26 57.13 dist/assets/page-renderer-CnwNh3EQ.js 3.92 kB │ gzip: 1.59 kB #26 57.13 dist/assets/JSONWorkflowDesigner-BMu_I1iN.js 4.04 kB │ gzip: 1.40 kB #26 57.13 dist/assets/JSONModelDesigner-CtCr0IyF.js 4.06 kB │ gzip: 1.40 kB #26 57.13 dist/assets/JSONComponentTreeManager-DChvp8bH.js 4.19 kB │ gzip: 1.43 kB #26 57.13 dist/assets/ComponentTreeBuilder-AKJ_ySXd.js 4.81 kB │ gzip: 1.95 kB #26 57.13 dist/assets/CodeEditor-BLwoA4UR.js 4.89 kB │ gzip: 1.86 kB #26 57.13 dist/assets/FileExplorer-JbASuVTC.js 4.98 kB │ gzip: 1.78 kB #26 57.13 dist/assets/ai-service-BB_pmEqI.js 6.07 kB │ gzip: 1.92 kB #26 57.13 dist/assets/ModelDesigner-CgtLxbx8.js 6.09 kB │ gzip: 2.06 kB #26 57.13 dist/assets/StorybookDesigner-Bpm7g44n.js 6.90 kB │ gzip: 2.34 kB #26 57.13 dist/assets/PlaywrightDesigner-BfiCriP0.js 7.51 kB │ gzip: 2.51 kB #26 57.13 dist/assets/PWASettings-3_HqVF29.js 7.92 kB │ gzip: 1.90 kB #26 57.13 dist/assets/ComponentTreeManager-NGgMB7h-.js 8.27 kB │ gzip: 2.92 kB #26 57.13 dist/assets/slider-CYgezrCe.js 8.65 kB │ gzip: 3.36 kB #26 57.13 dist/assets/UnitTestDesigner-hJNaBS7K.js 8.73 kB │ gzip: 2.76 kB #26 57.13 dist/assets/SassStylesShowcase-Be2HgC09.js 8.99 kB │ gzip: 1.67 kB #26 57.13 dist/assets/ErrorPanel-MW-ZUvQo.js 11.31 kB │ gzip: 3.65 kB #26 57.13 dist/assets/react-vendor-RsqJS7wA.js 11.33 kB │ gzip: 3.99 kB #26 57.13 dist/assets/FlaskDesigner-COgNGjFx.js 12.03 kB │ gzip: 3.25 kB #26 57.13 dist/assets/StyleDesigner-B2AQyBAi.js 13.23 kB │ gzip: 3.29 kB #26 57.13 dist/assets/code-editor-BR3HUJ_E.js 14.03 kB │ gzip: 4.80 kB #26 57.13 dist/assets/ProjectSettingsDesigner-DiAcWh5o.js 14.16 kB │ gzip: 3.31 kB #26 57.13 dist/assets/JSONUIShowcasePage-BYgVWKow.js 14.25 kB │ gzip: 3.93 kB #26 57.13 dist/assets/LambdaDesigner-CWnKya9X.js 14.42 kB │ gzip: 3.83 kB #26 57.13 dist/assets/ProjectDashboard-CLf3fcP0.js 15.83 kB │ gzip: 4.53 kB #26 57.13 dist/assets/ui-extended-CH1jmFOr.js 16.72 kB │ gzip: 5.34 kB #26 57.13 dist/assets/component-registry-D8jh1CB-.js 18.21 kB │ gzip: 6.39 kB #26 57.13 dist/assets/WorkflowDesigner-uASoW4e9.js 18.34 kB │ gzip: 5.03 kB #26 57.13 dist/assets/DataBindingDesigner-BkzQtXOX.js 20.36 kB │ gzip: 5.24 kB #26 57.13 dist/assets/SchemaEditorPage-DzxsWN4D.js 21.04 kB │ gzip: 5.95 kB #26 57.13 dist/assets/FaviconDesigner-DPzmL1L4.js 23.48 kB │ gzip: 6.27 kB #26 57.13 dist/assets/GlobalSearch-BjLJMhgk.js 25.04 kB │ gzip: 8.09 kB #26 57.13 dist/assets/FeatureIdeaCloud-DZ2YR6RT.js 30.07 kB │ gzip: 8.44 kB #26 57.13 dist/assets/utils-Bt9FPkgP.js 36.00 kB │ gzip: 11.18 kB #26 57.13 dist/assets/TemplateSelector-BVFRYL8A.js 42.82 kB │ gzip: 9.32 kB #26 57.13 dist/assets/form-components-Bgqg-kRU.js 66.01 kB │ gzip: 17.55 kB #26 57.13 dist/assets/DocumentationView-BjvllHGd.js 70.03 kB │ gzip: 12.62 kB #26 57.13 dist/assets/workflow-CpSwYplm.js 101.55 kB │ gzip: 32.48 kB #26 57.13 dist/assets/ui-core-CS7FcLG5.js 105.95 kB │ gzip: 32.29 kB #26 57.13 dist/assets/index-J_d48Gj5.js 488.88 kB │ gzip: 152.32 kB #26 57.13 dist/assets/three.module-D5EGS0V7.js 683.00 kB │ gzip: 169.49 kB #26 57.13 dist/assets/data-viz-DVeW5iYn.js 717.82 kB │ gzip: 199.17 kB #26 57.13 dist/assets/icons-CUJifBl7.js 5,039.69 kB │ gzip: 1,049.93 kB #26 57.13 #26 57.13 (!) Some chunks are larger than 1000 kB after minification. Consider: #26 57.13 - Using dynamic import() to code-split the application #26 57.13 - Use build.rollupOptions.output.manualChunks to improve chunking: https://rollupjs.org/configuration-options/#output-manualchunks #26 57.13 - Adjust chunk size limit for this warning via build.chunkSizeWarningLimit. #26 57.13 ✓ built in 50.63s #26 DONE 57.6s #24 [linux/arm64 builder 6/8] RUN npm install --legacy-peer-deps #24 ... #27 [linux/amd64 runtime 2/3] COPY --from=builder /app/dist /usr/share/nginx/html #27 CACHED #28 [linux/amd64 runtime 3/3] COPY nginx.conf /etc/nginx/conf.d/default.conf #28 CACHED #24 [linux/arm64 builder 6/8] RUN npm install --legacy-peer-deps #24 153.2 #24 153.2 added 712 packages, and audited 715 packages in 3m #24 153.2 #24 153.2 119 packages are looking for funding #24 153.2 run `npm fund` for details #24 153.3 #24 153.3 found 0 vulnerabilities #24 153.3 npm notice #24 153.3 npm notice New major version of npm available! 10.8.2 -> 11.7.0 #24 153.3 npm notice Changelog: https://github.com/npm/cli/releases/tag/v11.7.0 #24 153.3 npm notice To update run: npm install -g npm@11.7.0 #24 153.3 npm notice #24 DONE 153.8s #29 [linux/arm64 builder 7/8] COPY . . #29 DONE 0.5s #30 [linux/arm64 builder 8/8] RUN npm run build #30 2.651 #30 2.651 > spark-template@0.0.0 prebuild #30 2.651 > mkdir -p /tmp/dist || true #30 2.651 #30 2.723 #30 2.723 > spark-template@0.0.0 build #30 2.723 > tsc -b --noCheck && vite build #30 2.723 #30 50.69 /app/node_modules/rollup/dist/native.js:83 #30 50.69 throw new Error( #30 50.69 ^ #30 50.69 #30 50.69 Error: Cannot find module @rollup/rollup-linux-arm64-musl. npm has a bug related to optional dependencies (https://github.com/npm/cli/issues/4828). Please try `npm i` again after removing both package-lock.json and node_modules directory. #30 50.69 at requireWithFriendlyError (/app/node_modules/rollup/dist/native.js:83:9) #30 50.69 at Object.<anonymous> (/app/node_modules/rollup/dist/native.js:92:76) #30 50.69 ... 3 lines matching cause stack trace ... #30 50.69 at Module._load (node:internal/modules/cjs/loader:1091:12) #30 50.69 at cjsLoader (node:internal/modules/esm/translators:298:15) #30 50.69 at ModuleWrap.<anonymous> (node:internal/modules/esm/translators:240:7) #30 50.69 at ModuleJob.run (node:internal/modules/esm/module_job:325:25) #30 50.69 at async ModuleLoader.import (node:internal/modules/esm/loader:606:24) { #30 50.69 [cause]: Error: Cannot find module '@rollup/rollup-linux-arm64-musl' #30 50.69 Require stack: #30 50.69 - /app/node_modules/rollup/dist/native.js #30 50.69 at Module._resolveFilename (node:internal/modules/cjs/loader:1207:15) #30 50.69 at Module._load (node:internal/modules/cjs/loader:1038:27) #30 50.69 at Module.require (node:internal/modules/cjs/loader:1289:19) #30 50.69 at require (node:internal/modules/helpers:182:18) #30 50.69 at requireWithFriendlyError (/app/node_modules/rollup/dist/native.js:65:10) #30 50.69 at Object.<anonymous> (/app/node_modules/rollup/dist/native.js:92:76) #30 50.69 at Module._compile (node:internal/modules/cjs/loader:1521:14) #30 50.69 at Module._extensions..js (node:internal/modules/cjs/loader:1623:10) #30 50.69 at Module.load (node:internal/modules/cjs/loader:1266:32) #30 50.69 at Module._load (node:internal/modules/cjs/loader:1091:12) { #30 50.69 code: 'MODULE_NOT_FOUND', #30 50.69 requireStack: [ '/app/node_modules/rollup/dist/native.js' ] #30 50.69 } #30 50.69 } #30 50.70 #30 50.70 Node.js v20.20.0 #30 ERROR: process "/bin/sh -c npm run build" did not complete successfully: exit code: 1 ------ > [linux/arm64 builder 8/8] RUN npm run build: 50.69 at Module._compile (node:internal/modules/cjs/loader:1521:14) 50.69 at Module._extensions..js (node:internal/modules/cjs/loader:1623:10) 50.69 at Module.load (node:internal/modules/cjs/loader:1266:32) 50.69 at Module._load (node:internal/modules/cjs/loader:1091:12) { 50.69 code: 'MODULE_NOT_FOUND', 50.69 requireStack: [ '/app/node_modules/rollup/dist/native.js' ] 50.69 } 50.69 } 50.70 50.70 Node.js v20.20.0 ------ Dockerfile:22 -------------------- 20 | 21 | # Build the application 22 | >>> RUN npm run build 23 | 24 | FROM nginx:alpine AS runtime -------------------- ERROR: failed to build: failed to solve: process "/bin/sh -c npm run build" did not complete successfully: exit code: 1 Error: buildx failed with: ERROR: failed to build: failed to solve: process "/bin/sh -c npm run build" did not complete successfully: exit code: 1
This commit is contained in:
211
PRD.md
211
PRD.md
@@ -1,164 +1,131 @@
|
||||
# JSON-Driven UI Architecture Enhancement
|
||||
# Planning Guide
|
||||
|
||||
Build a comprehensive JSON-driven UI system that allows building entire user interfaces from declarative JSON schemas, including a visual drag-and-drop schema editor for creating JSON UI configs, breaking down complex components into atomic pieces, and extracting reusable logic into custom hooks for maximum maintainability and rapid development.
|
||||
|
||||
**Recent Updates:**
|
||||
- ✅ Converted Models, Component Trees, and Workflows pages to JSON-driven configuration
|
||||
- ✅ Converted Lambdas, Styling, and Flask API pages to JSON-driven configuration
|
||||
- ✅ Created JSON schema definitions for all six pages with data sources, computed values, and bindings
|
||||
- ✅ Added JSON-based versions of pages alongside traditional implementations for comparison
|
||||
- ✅ Implemented seed data for all six converted pages with realistic examples
|
||||
- ✅ Complete JSON-driven UI system now covers all major designer pages
|
||||
- ✅ Enhanced JSON schema system with additional UI components and patterns
|
||||
- ✅ Created focused custom hooks for common UI patterns (useConfirmDialog, useFormState, useListOperations)
|
||||
- ✅ Built additional atomic components for improved composability
|
||||
- ✅ **NEW:** Created `useJSONRenderer` hook with data binding utilities (resolveBinding, resolveValue, resolveProps)
|
||||
- ✅ **NEW:** Created `useDataSources` hook for unified KV, static, and computed data management
|
||||
- ✅ **NEW:** Built atomic JSON UI components: IconRenderer, DataCard (<50 LOC each)
|
||||
- ✅ **NEW:** Established hooks/json-ui and components/atoms/json-ui directories for modularity
|
||||
A visual Docker build error analyzer that parses build logs, highlights errors, and provides actionable solutions with automatic fix generation.
|
||||
|
||||
**Experience Qualities**:
|
||||
1. **Modular** - Every component under 150 LOC, highly composable and reusable
|
||||
2. **Declarative** - Define UIs through configuration rather than imperative code
|
||||
3. **Maintainable** - Clear separation of concerns between data, logic, and presentation
|
||||
1. **Clarifying** - Takes cryptic Docker logs and transforms them into clear, understandable problem statements
|
||||
2. **Actionable** - Provides specific, copy-paste ready solutions rather than generic advice
|
||||
3. **Educational** - Explains the root cause so users learn what went wrong and why
|
||||
|
||||
**Complexity Level**: Complex Application (advanced functionality with multiple views)
|
||||
|
||||
This is an advanced system that interprets JSON schemas, manages state across multiple data sources, executes actions dynamically, renders complex component hierarchies, and provides a visual editor for creating schemas through drag-and-drop - requiring sophisticated architecture with component registries, action executors, data source managers, and interactive canvas rendering.
|
||||
**Complexity Level**: Light Application (multiple features with basic state)
|
||||
This is a diagnostic tool with log parsing, error highlighting, and solution generation - more than a single-purpose tool but not a complex multi-view application.
|
||||
|
||||
## Essential Features
|
||||
|
||||
### Visual Schema Editor
|
||||
- **Functionality**: Drag-and-drop interface for building JSON UI schemas with real-time preview
|
||||
- **Purpose**: Enable non-technical users to create complex UIs without writing JSON
|
||||
- **Trigger**: User opens the schema editor page
|
||||
- **Progression**: Select component from palette → Drag to canvas → Drop at position → Configure properties → Preview result → Export JSON
|
||||
- **Success criteria**: Users can create complete page schemas visually, with property editing, component tree view, and JSON export
|
||||
### Log Parser & Error Highlighter
|
||||
- **Functionality**: Paste Docker build logs and automatically extract error information
|
||||
- **Purpose**: Make sense of lengthy, unformatted build output
|
||||
- **Trigger**: User pastes log text into a text area
|
||||
- **Progression**: Paste log → Auto-parse on input → Highlight errors in red → Extract key details → Display structured output
|
||||
- **Success criteria**: Correctly identifies build stage, error type, exit codes, and root cause from real Docker logs
|
||||
|
||||
### Data Source Binding UI
|
||||
- **Functionality**: Visual interface for connecting components to KV storage and computed values with dependency tracking
|
||||
- **Purpose**: Enable declarative data management without manual state handling
|
||||
- **Trigger**: User opens data binding designer or edits component bindings in schema editor
|
||||
- **Progression**: Create data source → Configure type (KV/computed/static) → Set up dependencies → Bind to component properties → Test reactive updates
|
||||
- **Success criteria**: Users can create KV stores, computed values, and static data, then bind them to components with automatic reactive updates
|
||||
### Smart Solution Generator
|
||||
- **Functionality**: Analyzes parsed errors and suggests specific fixes with code examples
|
||||
- **Purpose**: Provide actionable solutions tailored to the exact error type
|
||||
- **Trigger**: After log is parsed and error identified
|
||||
- **Progression**: Error identified → Match error pattern → Generate relevant solutions → Display with copy buttons → Show explanation
|
||||
- **Success criteria**: Provides relevant, working solutions for common Docker build issues (missing dependencies, platform issues, build failures)
|
||||
|
||||
### JSON Schema Parser
|
||||
- **Functionality**: Parse and validate JSON UI schemas with full TypeScript type safety
|
||||
- **Purpose**: Enable building UIs from configuration rather than code
|
||||
- **Trigger**: User loads a page defined by JSON schema
|
||||
- **Progression**: Load schema → Validate structure → Initialize data sources → Render component tree → Bind events
|
||||
- **Success criteria**: Schemas render correctly with all data bindings and event handlers working
|
||||
### Error Knowledge Base
|
||||
- **Functionality**: Common Docker build errors with explanations and fixes
|
||||
- **Purpose**: Quick reference for developers debugging builds
|
||||
- **Trigger**: User browses error categories or searches
|
||||
- **Progression**: Click category → View error patterns → Select specific error → See explanation and fixes
|
||||
- **Success criteria**: Covers at least 10 common Docker build error patterns with clear explanations
|
||||
|
||||
### Data Source Management
|
||||
- **Functionality**: Manage multiple data sources (KV store, computed values, static data) with automatic dependency tracking
|
||||
- **Purpose**: Centralize data management and enable reactive updates
|
||||
- **Trigger**: Component needs data or data changes
|
||||
- **Progression**: Request data → Check source type → Load/compute value → Update dependents → Re-render
|
||||
- **Success criteria**: Data flows correctly between sources, components, and persistence layer
|
||||
|
||||
### Action Executor
|
||||
- **Functionality**: Execute user actions declaratively (CRUD, navigation, toasts, custom actions)
|
||||
- **Purpose**: Handle all user interactions declaratively without component-specific code
|
||||
- **Trigger**: User interaction (click, change, submit, etc.)
|
||||
- **Progression**: Parse action → Validate params → Execute handler → Update data → Show feedback
|
||||
- **Success criteria**: All action types work correctly with proper error handling
|
||||
|
||||
### Atomic Component Library
|
||||
- **Functionality**: Library of small, focused, reusable components (atoms, molecules, organisms)
|
||||
- **Purpose**: Build complex UIs from simple, tested building blocks
|
||||
- **Trigger**: Developer needs a UI element
|
||||
- **Progression**: Select component → Configure props → Compose with other components → Render
|
||||
- **Success criteria**: No component exceeds 150 LOC, all components highly reusable
|
||||
|
||||
### Custom Hooks Library
|
||||
- **Functionality**: Extracted business logic in reusable hooks (useCRUD, useSearch, useFilter, useForm, etc.)
|
||||
- **Purpose**: Separate concerns and enable logic reuse across components
|
||||
- **Trigger**: Component needs common functionality (data management, search, form handling)
|
||||
- **Progression**: Call hook → Provide config → Receive state and handlers → Render UI
|
||||
- **Success criteria**: Hooks are testable, reusable, and follow React best practices
|
||||
### Fix Code Generator
|
||||
- **Functionality**: Generate copy-paste ready Dockerfile snippets or package.json modifications
|
||||
- **Purpose**: Speed up fixing by providing exact code changes needed
|
||||
- **Trigger**: After solution is displayed
|
||||
- **Progression**: Solution shown → Click "Generate Fix" → Code snippet created → Copy to clipboard → Apply to project
|
||||
- **Success criteria**: Generated code is syntactically correct and addresses the identified issue
|
||||
|
||||
## Edge Case Handling
|
||||
|
||||
- **Invalid Schemas** - Validate JSON structure, show helpful error messages, provide fallback UI
|
||||
- **Missing Components** - Log warnings, render fallback div, continue rendering other components
|
||||
- **Data Source Errors** - Catch KV failures, show toast notifications, maintain app stability
|
||||
- **Circular Dependencies** - Detect loops in computed data sources, break cycles, warn developer
|
||||
- **Concurrent Updates** - Use optimistic updates with rollback on failure
|
||||
- **Empty States** - Show helpful messages and actions when no data exists
|
||||
- **Incomplete Logs**: Gracefully handle partial logs by extracting whatever information is available
|
||||
- **Unknown Errors**: For unrecognized error patterns, provide general debugging steps and encourage manual investigation
|
||||
- **Multiple Errors**: When multiple errors present, prioritize and display them in order of likely root cause
|
||||
- **Empty Input**: Show helpful placeholder text with example log format
|
||||
- **Very Long Logs**: Truncate display but maintain full parsing capability
|
||||
|
||||
## Design Direction
|
||||
|
||||
A **dark cyberpunk development theme** with electric accents and technical precision that feels like a high-powered code editor with visual design tools integrated.
|
||||
The design should feel like a developer's diagnostic dashboard - technical but approachable, with clear visual hierarchy that guides the eye from problem to solution. Think of a code editor meets troubleshooting assistant.
|
||||
|
||||
## Color Selection
|
||||
|
||||
Convey technical sophistication with electric highlights against deep, professional backgrounds.
|
||||
A code-focused palette with strong error signaling and calm backgrounds.
|
||||
|
||||
- **Primary Color**: Deep Purple `oklch(0.45 0.15 270)` - Commands attention for primary actions, evokes advanced technology
|
||||
- **Secondary Colors**:
|
||||
- Dark Slate `oklch(0.35 0.02 250)` for secondary surfaces
|
||||
- Deep Navy `oklch(0.18 0.02 250)` for cards and elevated surfaces
|
||||
- **Accent Color**: Cyan Glow `oklch(0.70 0.15 200)` - Electric highlight for CTAs, active states, and focus indicators
|
||||
- **Foreground/Background Pairings**:
|
||||
- Background (Deep Navy #1E1E2E) → Foreground (Light Gray #E8E8EC) - Ratio 12.5:1 ✓
|
||||
- Card (Darker Navy #252535) → Card Foreground (Light Gray #E8E8EC) - Ratio 11.2:1 ✓
|
||||
- Primary (Deep Purple #7C3AED) → Primary Foreground (White #FFFFFF) - Ratio 6.8:1 ✓
|
||||
- Accent (Cyan #5DD5F5) → Accent Foreground (Deep Navy #1E1E2E) - Ratio 9.2:1 ✓
|
||||
- Muted (Slate #38384A) → Muted Foreground (Mid Gray #A8A8B0) - Ratio 5.2:1 ✓
|
||||
- **Primary Color**: `oklch(0.58 0.24 265)` - Tech purple that feels modern and developer-centric
|
||||
- **Secondary Colors**: `oklch(0.25 0.03 265)` - Deep navy backgrounds for code blocks and panels
|
||||
- **Accent Color**: `oklch(0.75 0.20 145)` - Bright teal for success states and actionable elements
|
||||
- **Foreground/Background Pairings**:
|
||||
- Background (`oklch(0.15 0.02 265)`): Light text `oklch(0.95 0.01 265)` - Ratio 11.2:1 ✓
|
||||
- Card (`oklch(0.19 0.02 265)`): Light text `oklch(0.95 0.01 265)` - Ratio 9.8:1 ✓
|
||||
- Accent (`oklch(0.75 0.20 145)`): Dark text `oklch(0.15 0.02 265)` - Ratio 7.5:1 ✓
|
||||
- Destructive/Error (`oklch(0.60 0.25 25)`): White text `oklch(1 0 0)` - Ratio 5.2:1 ✓
|
||||
|
||||
## Font Selection
|
||||
|
||||
Convey **technical precision and modern development** with a mix of geometric sans-serif and monospace fonts.
|
||||
Monospace for code and logs, clean sans-serif for explanations - reflecting the technical nature while remaining readable.
|
||||
|
||||
- **Typographic Hierarchy**:
|
||||
- H1 (Page Titles): Space Grotesk Bold/32px/tight (-0.02em) - Geometric, technical, commanding
|
||||
- H2 (Section Headers): Space Grotesk Semi-Bold/24px/tight (-0.01em)
|
||||
- H3 (Component Headers): Space Grotesk Medium/18px/normal
|
||||
- Body Text: Inter Regular/14px/relaxed (1.6) - Highly readable, neutral, professional
|
||||
- Code/Technical: JetBrains Mono Regular/13px/normal (1.5) - Monospace for code and technical content
|
||||
- Captions/Labels: Inter Medium/12px/normal - Slightly bolder for hierarchy
|
||||
- H1 (Main Title): JetBrains Mono Bold/32px/tight letter spacing
|
||||
- H2 (Section Headers): JetBrains Mono Medium/24px/normal spacing
|
||||
- Body Text: IBM Plex Sans Regular/16px/1.6 line height
|
||||
- Code/Logs: JetBrains Mono Regular/14px/1.5 line height
|
||||
- Small Labels: IBM Plex Sans Medium/12px/uppercase tracking
|
||||
|
||||
## Animations
|
||||
|
||||
Animations should feel **snappy and purposeful** - fast micro-interactions (100-150ms) for buttons and inputs, smooth transitions (250-300ms) for page changes and dialogs, with spring physics for natural movement. Use subtle scale transforms (0.98→1.0) on button press, slide-in animations for modals, and fade effects for state changes. Avoid unnecessary flourishes - every animation serves feedback or orientation.
|
||||
Animations should feel snappy and technical, like a terminal responding to commands.
|
||||
|
||||
- Error highlights fade in with a quick pulse (200ms) to draw attention
|
||||
- Solutions expand/collapse smoothly (300ms ease-out)
|
||||
- Copy confirmation shows brief checkmark animation (150ms)
|
||||
- Log parsing shows subtle progress indicator during processing
|
||||
- Tab switches use fast slide transitions (200ms)
|
||||
|
||||
## Component Selection
|
||||
|
||||
- **Components**:
|
||||
- `Card`, `Button`, `Input`, `Select`, `Checkbox`, `Switch` for core UI
|
||||
- `Dialog`, `Tabs`, `Badge`, `Progress`, `Separator` for layout and feedback
|
||||
- `Heading`, `Text`, `List`, `Grid` for typography and layout primitives
|
||||
- `ScrollArea` for contained scrollable regions
|
||||
- `Tooltip` for contextual help
|
||||
- Textarea (custom styled) for log input with monospace font
|
||||
- Card for structured error display with distinct sections
|
||||
- Badge for error types, build stages, and exit codes
|
||||
- Tabs for switching between parsed errors, solutions, and knowledge base
|
||||
- Button (primary for actions, secondary for copy operations)
|
||||
- ScrollArea for long log outputs
|
||||
- Separator to divide error details from solutions
|
||||
- Alert for success/info messages after copying
|
||||
|
||||
- **Customizations**:
|
||||
- `StatusBadge` - Status indicator with predefined styles
|
||||
- `DataCard` - Stat card with icon, trend, and loading states
|
||||
- `SearchInput` - Input with search icon and clear button
|
||||
- `ActionBar` - Title with action buttons
|
||||
- All new atomic components follow the 150 LOC limit
|
||||
- Custom syntax highlighting for Docker logs using color coding
|
||||
- Custom error badge with pulsing animation for critical errors
|
||||
- Monospace code blocks with line numbers for generated fixes
|
||||
|
||||
- **States**:
|
||||
- Buttons: subtle scale on press, glow effect on hover, disabled with opacity
|
||||
- Inputs: border color shift on focus, inline validation icons, smooth error states
|
||||
- Cards: subtle lift shadow on hover for interactive cards
|
||||
- Buttons: Default solid with subtle shadow, hover lifts with brightness increase, active depresses
|
||||
- Input: Focused state has bright accent border with subtle glow
|
||||
- Code blocks: Hover shows copy button overlay in corner
|
||||
|
||||
- **Icon Selection**:
|
||||
- Phosphor Icons throughout
|
||||
- Code, Database, Tree, Cube for feature areas
|
||||
- Plus, Pencil, Trash for CRUD operations
|
||||
- MagnifyingGlass, Gear, Download for utilities
|
||||
- Terminal (for log input)
|
||||
- Warning/WarningCircle (for errors)
|
||||
- CheckCircle (for solutions)
|
||||
- Copy/CopySimple (for copy actions)
|
||||
- MagnifyingGlass (for search in knowledge base)
|
||||
- Code (for generated fixes)
|
||||
- Stack (for Docker layers)
|
||||
|
||||
- **Spacing**:
|
||||
- Container padding: p-6 (1.5rem)
|
||||
- Section gaps: gap-6 (1.5rem)
|
||||
- Card gaps: gap-4 (1rem)
|
||||
- Button groups: gap-2 (0.5rem)
|
||||
- Tight elements: gap-1 (0.25rem)
|
||||
- Container padding: p-6 on desktop, p-4 on mobile
|
||||
- Section gaps: gap-8 for major sections, gap-4 for related content
|
||||
- Card internal padding: p-6
|
||||
- Button spacing: px-6 py-3 for primary, px-4 py-2 for secondary
|
||||
|
||||
- **Mobile**:
|
||||
- Stack layouts vertically on <768px
|
||||
- Reduce padding to p-4 on mobile
|
||||
- Touch-friendly tap targets (min 44px)
|
||||
- Responsive grid columns (1 → 2 → 3 → 4)
|
||||
- Bottom sheet dialogs on small screens
|
||||
- Stack all sections vertically on mobile
|
||||
- Reduce font sizes: H1 to 24px, Body to 14px
|
||||
- Full-width buttons and inputs
|
||||
- Collapsible sections for solutions to save space
|
||||
- Fixed header with title, scrollable content below
|
||||
|
||||
27
index.html
27
index.html
@@ -4,34 +4,15 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>JSON-Driven UI - CodeForge</title>
|
||||
<title>Docker Build Debugger</title>
|
||||
|
||||
<meta name="description" content="Build Next.js, Material UI, and Flask applications with visual designers and AI assistance">
|
||||
<meta name="theme-color" content="#7c3aed">
|
||||
|
||||
<link rel="manifest" href="/manifest.json">
|
||||
<link rel="icon" type="image/png" sizes="192x192" href="/icons/icon-192x192.png">
|
||||
<link rel="icon" type="image/png" sizes="512x512" href="/icons/icon-512x512.png">
|
||||
<link rel="apple-touch-icon" href="/icons/icon-192x192.png">
|
||||
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||
<meta name="apple-mobile-web-app-title" content="CodeForge">
|
||||
<meta name="description" content="Analyze Docker build errors and get instant solutions">
|
||||
<meta name="theme-color" content="#8b5cf6">
|
||||
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;700&family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&family=IBM+Plex+Sans:wght@400;500;600&display=swap" rel="stylesheet">
|
||||
<link href="/src/main.css" rel="stylesheet" />
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
var redirect = sessionStorage.redirect;
|
||||
delete sessionStorage.redirect;
|
||||
if (redirect && redirect !== location.href) {
|
||||
history.replaceState(null, null, redirect);
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
793
src/App.tsx
793
src/App.tsx
@@ -1,387 +1,432 @@
|
||||
console.log('[APP] 🚀 App.tsx loading - BEGIN')
|
||||
console.time('[APP] Component initialization')
|
||||
|
||||
import { useState, Suspense, useEffect } from 'react'
|
||||
console.log('[APP] ✅ React hooks imported')
|
||||
|
||||
import { BrowserRouter, useLocation } from 'react-router-dom'
|
||||
console.log('[APP] ✅ React Router imported')
|
||||
|
||||
import { AppHeader } from '@/components/organisms'
|
||||
console.log('[APP] ✅ Header components imported')
|
||||
|
||||
import { LoadingFallback } from '@/components/molecules'
|
||||
console.log('[APP] ✅ LoadingFallback imported')
|
||||
|
||||
import { useProjectState } from '@/hooks/use-project-state'
|
||||
import { useFileOperations } from '@/hooks/use-file-operations'
|
||||
import { useKeyboardShortcuts } from '@/hooks/use-keyboard-shortcuts'
|
||||
import { useSeedData } from '@/hooks/data/use-seed-data'
|
||||
import { useRouterNavigation } from '@/hooks/use-router-navigation'
|
||||
console.log('[APP] ✅ Custom hooks imported')
|
||||
|
||||
import { getPageShortcuts } from '@/config/page-loader'
|
||||
console.log('[APP] ✅ Page config imported')
|
||||
|
||||
import { useState } from 'react'
|
||||
import { useKV } from '@github/spark/hooks'
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
|
||||
import { Textarea } from '@/components/ui/textarea'
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import { ScrollArea } from '@/components/ui/scroll-area'
|
||||
import { Separator } from '@/components/ui/separator'
|
||||
import { Alert, AlertDescription } from '@/components/ui/alert'
|
||||
import { Terminal, Warning, CheckCircle, Copy, Code, Stack, MagnifyingGlass, Sparkle } from '@phosphor-icons/react'
|
||||
import { parseDockerLog, getSolutionsForError, knowledgeBase } from '@/lib/docker-parser'
|
||||
import { DockerError, KnowledgeBaseItem } from '@/types/docker'
|
||||
import { toast } from 'sonner'
|
||||
console.log('[APP] ✅ Toast imported')
|
||||
import { motion, AnimatePresence } from 'framer-motion'
|
||||
|
||||
import { DialogRegistry, PWARegistry, preloadCriticalComponents } from '@/lib/component-registry'
|
||||
console.log('[APP] ✅ Component registry imported')
|
||||
function App() {
|
||||
const [logInput, setLogInput] = useKV<string>('docker-log-input', '')
|
||||
const [parsedErrors, setParsedErrors] = useState<DockerError[]>([])
|
||||
const [selectedKbItem, setSelectedKbItem] = useState<KnowledgeBaseItem | null>(null)
|
||||
const [searchQuery, setSearchQuery] = useState('')
|
||||
|
||||
import { RouterProvider } from '@/router'
|
||||
import { routePreloadManager } from '@/lib/route-preload-manager'
|
||||
import { PreloadIndicator } from '@/components/PreloadIndicator'
|
||||
console.log('[APP] ✅ Router provider imported')
|
||||
|
||||
const { GlobalSearch, KeyboardShortcutsDialog, PreviewDialog } = DialogRegistry
|
||||
const { PWAInstallPrompt, PWAUpdatePrompt, PWAStatusBar } = PWARegistry
|
||||
console.log('[APP] ✅ Dialog and PWA components registered')
|
||||
|
||||
console.log('[APP] 🎯 App component function executing')
|
||||
|
||||
function AppLayout() {
|
||||
console.log('[APP] 🏗️ AppLayout component rendering')
|
||||
const location = useLocation()
|
||||
const { currentPage, navigateToPage } = useRouterNavigation()
|
||||
|
||||
console.log('[APP] 📍 Current location:', location.pathname)
|
||||
console.log('[APP] 📄 Current page:', currentPage)
|
||||
|
||||
console.log('[APP] 📊 Initializing project state hook')
|
||||
const projectState = useProjectState()
|
||||
console.log('[APP] ✅ Project state initialized')
|
||||
|
||||
const {
|
||||
files,
|
||||
models,
|
||||
components,
|
||||
componentTrees,
|
||||
workflows,
|
||||
lambdas,
|
||||
theme,
|
||||
playwrightTests,
|
||||
storybookStories,
|
||||
unitTests,
|
||||
flaskConfig,
|
||||
nextjsConfig,
|
||||
npmSettings,
|
||||
featureToggles,
|
||||
setFiles,
|
||||
setModels,
|
||||
setComponents,
|
||||
setComponentTrees,
|
||||
setWorkflows,
|
||||
setLambdas,
|
||||
setTheme,
|
||||
setPlaywrightTests,
|
||||
setStorybookStories,
|
||||
setUnitTests,
|
||||
setFlaskConfig,
|
||||
setNextjsConfig,
|
||||
setNpmSettings,
|
||||
setFeatureToggles,
|
||||
} = projectState
|
||||
|
||||
useEffect(() => {
|
||||
console.log('[APP] 🎯 Setting feature toggles in preload manager')
|
||||
routePreloadManager.setFeatureToggles(featureToggles)
|
||||
}, [featureToggles])
|
||||
|
||||
console.log('[APP] 📁 Initializing file operations')
|
||||
const fileOps = useFileOperations(files, setFiles)
|
||||
console.log('[APP] ✅ File operations initialized')
|
||||
|
||||
const { activeFileId, setActiveFileId, handleFileChange, handleFileAdd, handleFileClose } = fileOps
|
||||
|
||||
console.log('[APP] 💾 Initializing state variables')
|
||||
const [searchOpen, setSearchOpen] = useState(false)
|
||||
const [shortcutsOpen, setShortcutsOpen] = useState(false)
|
||||
const [previewOpen, setPreviewOpen] = useState(false)
|
||||
const [lastSaved] = useState<number | null>(Date.now())
|
||||
const [errorCount] = useState(0)
|
||||
console.log('[APP] ✅ State variables initialized')
|
||||
|
||||
const shortcuts = getPageShortcuts(featureToggles)
|
||||
console.log('[APP] ⌨️ Keyboard shortcuts configured:', shortcuts.length)
|
||||
|
||||
console.log('[APP] ⌨️ Setting up keyboard shortcuts')
|
||||
useKeyboardShortcuts([
|
||||
...shortcuts.map(s => ({
|
||||
key: s.key,
|
||||
ctrl: s.ctrl,
|
||||
shift: s.shift,
|
||||
description: s.description,
|
||||
action: () => {
|
||||
console.log('[APP] ⌨️ Shortcut triggered, navigating to:', s.action)
|
||||
navigateToPage(s.action)
|
||||
}
|
||||
})),
|
||||
{
|
||||
key: 'k',
|
||||
ctrl: true,
|
||||
description: 'Search',
|
||||
action: () => {
|
||||
console.log('[APP] ⌨️ Search shortcut triggered')
|
||||
setSearchOpen(true)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: '/',
|
||||
ctrl: true,
|
||||
description: 'Shortcuts',
|
||||
action: () => {
|
||||
console.log('[APP] ⌨️ Shortcuts dialog triggered')
|
||||
setShortcutsOpen(true)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'p',
|
||||
ctrl: true,
|
||||
description: 'Preview',
|
||||
action: () => {
|
||||
console.log('[APP] ⌨️ Preview shortcut triggered')
|
||||
setPreviewOpen(true)
|
||||
}
|
||||
},
|
||||
])
|
||||
console.log('[APP] ✅ Keyboard shortcuts configured')
|
||||
|
||||
const getCurrentProject = () => ({
|
||||
name: nextjsConfig.appName,
|
||||
files,
|
||||
models,
|
||||
components,
|
||||
componentTrees,
|
||||
workflows,
|
||||
lambdas,
|
||||
theme,
|
||||
playwrightTests,
|
||||
storybookStories,
|
||||
unitTests,
|
||||
flaskConfig,
|
||||
nextjsConfig,
|
||||
npmSettings,
|
||||
featureToggles,
|
||||
})
|
||||
|
||||
const handleProjectLoad = (project: any) => {
|
||||
console.log('[APP] 📦 Loading project:', project.name)
|
||||
if (project.files) setFiles(project.files)
|
||||
if (project.models) setModels(project.models)
|
||||
if (project.components) setComponents(project.components)
|
||||
if (project.componentTrees) setComponentTrees(project.componentTrees)
|
||||
if (project.workflows) setWorkflows(project.workflows)
|
||||
if (project.lambdas) setLambdas(project.lambdas)
|
||||
if (project.theme) setTheme(project.theme)
|
||||
if (project.playwrightTests) setPlaywrightTests(project.playwrightTests)
|
||||
if (project.storybookStories) setStorybookStories(project.storybookStories)
|
||||
if (project.unitTests) setUnitTests(project.unitTests)
|
||||
if (project.flaskConfig) setFlaskConfig(project.flaskConfig)
|
||||
if (project.nextjsConfig) setNextjsConfig(project.nextjsConfig)
|
||||
if (project.npmSettings) setNpmSettings(project.npmSettings)
|
||||
if (project.featureToggles) setFeatureToggles(project.featureToggles)
|
||||
toast.success('Project loaded')
|
||||
console.log('[APP] ✅ Project loaded successfully')
|
||||
const handleParse = () => {
|
||||
if (!logInput.trim()) {
|
||||
toast.error('Please paste a Docker build log first')
|
||||
return
|
||||
}
|
||||
|
||||
const errors = parseDockerLog(logInput)
|
||||
|
||||
if (errors.length === 0) {
|
||||
toast.info('No errors detected in the log')
|
||||
} else {
|
||||
setParsedErrors(errors)
|
||||
toast.success(`Found ${errors.length} error${errors.length > 1 ? 's' : ''}`)
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
console.log('[APP] 📍 Route changed to:', location.pathname, '- Page:', currentPage)
|
||||
routePreloadManager.setCurrentRoute(currentPage)
|
||||
|
||||
const stats = routePreloadManager.getStats()
|
||||
console.log('[APP] 📊 Preload stats:', stats)
|
||||
}, [location, currentPage])
|
||||
const handleCopy = (text: string, label: string) => {
|
||||
navigator.clipboard.writeText(text)
|
||||
toast.success(`${label} copied to clipboard`)
|
||||
}
|
||||
|
||||
const filteredKnowledgeBase = knowledgeBase.filter(item =>
|
||||
item.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||
item.category.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||
item.explanation.toLowerCase().includes(searchQuery.toLowerCase())
|
||||
)
|
||||
|
||||
console.log('[APP] 🎨 Rendering AppLayout UI')
|
||||
|
||||
return (
|
||||
<div className="h-screen flex flex-col bg-background">
|
||||
<Suspense fallback={<div className="h-1 bg-primary animate-pulse" />}>
|
||||
<PWAStatusBar />
|
||||
</Suspense>
|
||||
<Suspense fallback={null}>
|
||||
<PWAUpdatePrompt />
|
||||
</Suspense>
|
||||
<AppHeader
|
||||
activeTab={currentPage}
|
||||
onTabChange={navigateToPage}
|
||||
featureToggles={featureToggles}
|
||||
errorCount={errorCount}
|
||||
lastSaved={lastSaved}
|
||||
currentProject={getCurrentProject()}
|
||||
onProjectLoad={handleProjectLoad}
|
||||
onSearch={() => {
|
||||
console.log('[APP] 🔍 Search opened')
|
||||
setSearchOpen(true)
|
||||
}}
|
||||
onShowShortcuts={() => {
|
||||
console.log('[APP] ⌨️ Shortcuts dialog opened')
|
||||
setShortcutsOpen(true)
|
||||
}}
|
||||
onGenerateAI={() => {
|
||||
console.log('[APP] 🤖 AI generation requested')
|
||||
toast.info('AI generation coming soon')
|
||||
}}
|
||||
onExport={() => {
|
||||
console.log('[APP] 📤 Export requested')
|
||||
toast.info('Export coming soon')
|
||||
}}
|
||||
onPreview={() => {
|
||||
console.log('[APP] 👁️ Preview opened')
|
||||
setPreviewOpen(true)
|
||||
}}
|
||||
onShowErrors={() => {
|
||||
console.log('[APP] ⚠️ Navigating to errors page')
|
||||
navigateToPage('errors')
|
||||
}}
|
||||
/>
|
||||
<div className="flex-1 overflow-hidden">
|
||||
<RouterProvider
|
||||
featureToggles={featureToggles}
|
||||
stateContext={{
|
||||
files,
|
||||
models,
|
||||
components,
|
||||
componentTrees,
|
||||
workflows,
|
||||
lambdas,
|
||||
theme,
|
||||
playwrightTests,
|
||||
storybookStories,
|
||||
unitTests,
|
||||
flaskConfig,
|
||||
nextjsConfig,
|
||||
npmSettings,
|
||||
featureToggles,
|
||||
activeFileId,
|
||||
}}
|
||||
actionContext={{
|
||||
handleFileChange,
|
||||
setActiveFileId,
|
||||
handleFileClose,
|
||||
handleFileAdd,
|
||||
setModels,
|
||||
setComponents,
|
||||
setComponentTrees,
|
||||
setWorkflows,
|
||||
setLambdas,
|
||||
setTheme,
|
||||
setPlaywrightTests,
|
||||
setStorybookStories,
|
||||
setUnitTests,
|
||||
setFlaskConfig,
|
||||
setNextjsConfig,
|
||||
setNpmSettings,
|
||||
setFeatureToggles,
|
||||
}}
|
||||
/>
|
||||
<div className="min-h-screen bg-background">
|
||||
<div className="relative overflow-hidden">
|
||||
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_top,_var(--tw-gradient-stops))] from-primary/20 via-background to-background" />
|
||||
<div className="absolute inset-0 bg-[linear-gradient(to_right,#4f4f4f12_1px,transparent_1px),linear-gradient(to_bottom,#4f4f4f12_1px,transparent_1px)] bg-[size:4rem_4rem]" />
|
||||
|
||||
<div className="relative">
|
||||
<header className="border-b border-border/40 backdrop-blur-sm">
|
||||
<div className="container mx-auto px-4 sm:px-6 py-6">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="p-2 rounded-lg bg-primary/10 border border-primary/20">
|
||||
<Stack size={32} weight="bold" className="text-primary" />
|
||||
</div>
|
||||
<div>
|
||||
<h1 className="text-2xl sm:text-3xl font-bold tracking-tight">Docker Build Debugger</h1>
|
||||
<p className="text-sm text-muted-foreground">Analyze errors and get instant solutions</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main className="container mx-auto px-4 sm:px-6 py-8">
|
||||
<Tabs defaultValue="analyzer" className="space-y-6">
|
||||
<TabsList className="grid w-full grid-cols-2 lg:w-auto lg:inline-grid bg-card/50 backdrop-blur-sm">
|
||||
<TabsTrigger value="analyzer" className="gap-2">
|
||||
<Terminal size={16} weight="bold" />
|
||||
<span className="hidden sm:inline">Log Analyzer</span>
|
||||
<span className="sm:hidden">Analyze</span>
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="knowledge" className="gap-2">
|
||||
<MagnifyingGlass size={16} weight="bold" />
|
||||
<span className="hidden sm:inline">Knowledge Base</span>
|
||||
<span className="sm:hidden">Knowledge</span>
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
<TabsContent value="analyzer" className="space-y-6">
|
||||
<Card className="border-border/50 bg-card/50 backdrop-blur-sm">
|
||||
<CardHeader>
|
||||
<div className="flex items-start justify-between">
|
||||
<div>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<Terminal size={20} weight="bold" className="text-primary" />
|
||||
Paste Build Log
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
Copy your Docker build output and paste it below for analysis
|
||||
</CardDescription>
|
||||
</div>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<Textarea
|
||||
value={logInput}
|
||||
onChange={(e) => setLogInput(e.target.value)}
|
||||
placeholder="Paste your Docker build log here...
|
||||
|
||||
Example:
|
||||
#30 50.69 Error: Cannot find module @rollup/rollup-linux-arm64-musl
|
||||
#30 ERROR: process '/bin/sh -c npm run build' did not complete successfully: exit code: 1"
|
||||
className="min-h-[300px] font-mono text-sm bg-secondary/50 border-border/50 focus:border-accent/50 focus:ring-accent/20"
|
||||
/>
|
||||
<div className="flex gap-3">
|
||||
<Button onClick={handleParse} className="gap-2" size="lg">
|
||||
<Sparkle size={18} weight="fill" />
|
||||
Analyze Log
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => {
|
||||
setLogInput('')
|
||||
setParsedErrors([])
|
||||
}}
|
||||
size="lg"
|
||||
>
|
||||
Clear
|
||||
</Button>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<AnimatePresence mode="wait">
|
||||
{parsedErrors.length > 0 && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: -20 }}
|
||||
transition={{ duration: 0.3 }}
|
||||
className="space-y-6"
|
||||
>
|
||||
{parsedErrors.map((error, index) => (
|
||||
<Card key={error.id} className="border-destructive/30 bg-card/50 backdrop-blur-sm">
|
||||
<CardHeader>
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
<Warning size={24} weight="fill" className="text-destructive animate-pulse" />
|
||||
<CardTitle className="text-destructive">Error #{index + 1}</CardTitle>
|
||||
<Badge variant="destructive" className="font-mono">
|
||||
{error.type}
|
||||
</Badge>
|
||||
{error.exitCode && (
|
||||
<Badge variant="outline" className="font-mono">
|
||||
Exit Code: {error.exitCode}
|
||||
</Badge>
|
||||
)}
|
||||
{error.stage && (
|
||||
<Badge variant="secondary" className="font-mono">
|
||||
{error.stage}
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground font-mono">{error.message}</p>
|
||||
</div>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-6">
|
||||
{error.context.length > 0 && (
|
||||
<div>
|
||||
<h4 className="text-sm font-semibold mb-2 flex items-center gap-2">
|
||||
<Code size={16} weight="bold" />
|
||||
Error Context
|
||||
</h4>
|
||||
<ScrollArea className="h-32 rounded-md border border-border/50 bg-secondary/50 p-3">
|
||||
<pre className="text-xs font-mono text-muted-foreground whitespace-pre-wrap">
|
||||
{error.context.join('\n')}
|
||||
</pre>
|
||||
</ScrollArea>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<Separator />
|
||||
|
||||
<div>
|
||||
<h4 className="text-lg font-semibold mb-4 flex items-center gap-2">
|
||||
<CheckCircle size={20} weight="bold" className="text-accent" />
|
||||
Recommended Solutions
|
||||
</h4>
|
||||
<div className="space-y-4">
|
||||
{getSolutionsForError(error).map((solution, sIndex) => (
|
||||
<motion.div
|
||||
key={sIndex}
|
||||
initial={{ opacity: 0, x: -20 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
transition={{ delay: sIndex * 0.1 }}
|
||||
>
|
||||
<Card className="bg-secondary/30 border-accent/20">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-base text-accent">
|
||||
{solution.title}
|
||||
</CardTitle>
|
||||
<CardDescription>{solution.description}</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-3">
|
||||
<div>
|
||||
<h5 className="text-sm font-semibold mb-2">Steps:</h5>
|
||||
<ol className="list-decimal list-inside space-y-1 text-sm text-muted-foreground">
|
||||
{solution.steps.map((step, stepIndex) => (
|
||||
<li key={stepIndex}>{step}</li>
|
||||
))}
|
||||
</ol>
|
||||
</div>
|
||||
{solution.code && (
|
||||
<div>
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<h5 className="text-sm font-semibold">Code:</h5>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => handleCopy(solution.code!, 'Code')}
|
||||
className="gap-2 h-7"
|
||||
>
|
||||
<Copy size={14} />
|
||||
Copy
|
||||
</Button>
|
||||
</div>
|
||||
<ScrollArea className="max-h-48 rounded-md border border-border/50 bg-secondary/50 p-3">
|
||||
<pre className="text-xs font-mono text-foreground whitespace-pre-wrap">
|
||||
{solution.code}
|
||||
</pre>
|
||||
</ScrollArea>
|
||||
{solution.codeLanguage && (
|
||||
<p className="text-xs text-muted-foreground mt-1">
|
||||
Language: {solution.codeLanguage}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="knowledge" className="space-y-6">
|
||||
<Card className="border-border/50 bg-card/50 backdrop-blur-sm">
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<MagnifyingGlass size={20} weight="bold" className="text-primary" />
|
||||
Search Knowledge Base
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
Browse common Docker build errors and their solutions
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="relative">
|
||||
<MagnifyingGlass
|
||||
size={20}
|
||||
className="absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground"
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
value={searchQuery}
|
||||
onChange={(e) => setSearchQuery(e.target.value)}
|
||||
placeholder="Search errors, categories, or keywords..."
|
||||
className="w-full pl-10 pr-4 py-3 rounded-lg border border-border/50 bg-secondary/50 text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-accent/20 focus:border-accent/50"
|
||||
/>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<div className="grid gap-4 md:grid-cols-2">
|
||||
{filteredKnowledgeBase.map((item) => (
|
||||
<motion.div
|
||||
key={item.id}
|
||||
initial={{ opacity: 0, scale: 0.95 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
transition={{ duration: 0.2 }}
|
||||
>
|
||||
<Card
|
||||
className="border-border/50 bg-card/50 backdrop-blur-sm cursor-pointer hover:border-accent/50 hover:shadow-lg hover:shadow-accent/5 transition-all"
|
||||
onClick={() => setSelectedKbItem(item)}
|
||||
>
|
||||
<CardHeader>
|
||||
<div className="flex items-start justify-between gap-2">
|
||||
<CardTitle className="text-base">{item.title}</CardTitle>
|
||||
<Badge variant="secondary" className="text-xs shrink-0">
|
||||
{item.category}
|
||||
</Badge>
|
||||
</div>
|
||||
<CardDescription className="text-xs font-mono text-muted-foreground">
|
||||
{item.pattern}
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<p className="text-sm text-muted-foreground line-clamp-2">
|
||||
{item.explanation}
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{filteredKnowledgeBase.length === 0 && (
|
||||
<Alert>
|
||||
<AlertDescription>
|
||||
No results found for "{searchQuery}". Try different keywords.
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
<AnimatePresence mode="wait">
|
||||
{selectedKbItem && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: -20 }}
|
||||
className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-background/80 backdrop-blur-sm"
|
||||
onClick={() => setSelectedKbItem(null)}
|
||||
>
|
||||
<motion.div
|
||||
initial={{ scale: 0.9 }}
|
||||
animate={{ scale: 1 }}
|
||||
exit={{ scale: 0.9 }}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
className="w-full max-w-3xl max-h-[90vh] overflow-auto"
|
||||
>
|
||||
<Card className="border-border bg-card">
|
||||
<CardHeader>
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<Badge variant="secondary">{selectedKbItem.category}</Badge>
|
||||
<CardTitle>{selectedKbItem.title}</CardTitle>
|
||||
</div>
|
||||
<p className="text-sm font-mono text-muted-foreground">
|
||||
Pattern: {selectedKbItem.pattern}
|
||||
</p>
|
||||
</div>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setSelectedKbItem(null)}
|
||||
>
|
||||
Close
|
||||
</Button>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-6">
|
||||
<div>
|
||||
<h4 className="font-semibold mb-2">Explanation</h4>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{selectedKbItem.explanation}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Separator />
|
||||
|
||||
<div>
|
||||
<h4 className="font-semibold mb-4 flex items-center gap-2">
|
||||
<CheckCircle size={18} weight="bold" className="text-accent" />
|
||||
Solutions
|
||||
</h4>
|
||||
<div className="space-y-4">
|
||||
{selectedKbItem.solutions.map((solution, index) => (
|
||||
<Card key={index} className="bg-secondary/30 border-accent/20">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-base text-accent">
|
||||
{solution.title}
|
||||
</CardTitle>
|
||||
<CardDescription>{solution.description}</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-3">
|
||||
<div>
|
||||
<h5 className="text-sm font-semibold mb-2">Steps:</h5>
|
||||
<ol className="list-decimal list-inside space-y-1 text-sm text-muted-foreground">
|
||||
{solution.steps.map((step, stepIndex) => (
|
||||
<li key={stepIndex}>{step}</li>
|
||||
))}
|
||||
</ol>
|
||||
</div>
|
||||
{solution.code && (
|
||||
<div>
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<h5 className="text-sm font-semibold">Code:</h5>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => handleCopy(solution.code!, 'Code')}
|
||||
className="gap-2 h-7"
|
||||
>
|
||||
<Copy size={14} />
|
||||
Copy
|
||||
</Button>
|
||||
</div>
|
||||
<ScrollArea className="max-h-48 rounded-md border border-border/50 bg-secondary/50 p-3">
|
||||
<pre className="text-xs font-mono text-foreground whitespace-pre-wrap">
|
||||
{solution.code}
|
||||
</pre>
|
||||
</ScrollArea>
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Suspense fallback={null}>
|
||||
<GlobalSearch
|
||||
open={searchOpen}
|
||||
onOpenChange={setSearchOpen}
|
||||
files={files}
|
||||
models={models}
|
||||
components={components}
|
||||
componentTrees={componentTrees}
|
||||
workflows={workflows}
|
||||
lambdas={lambdas}
|
||||
playwrightTests={playwrightTests}
|
||||
storybookStories={storybookStories}
|
||||
unitTests={unitTests}
|
||||
onNavigate={navigateToPage}
|
||||
onFileSelect={setActiveFileId}
|
||||
/>
|
||||
</Suspense>
|
||||
|
||||
<Suspense fallback={null}>
|
||||
<KeyboardShortcutsDialog open={shortcutsOpen} onOpenChange={setShortcutsOpen} />
|
||||
</Suspense>
|
||||
<Suspense fallback={null}>
|
||||
<PreviewDialog open={previewOpen} onOpenChange={setPreviewOpen} />
|
||||
</Suspense>
|
||||
<Suspense fallback={null}>
|
||||
<PWAInstallPrompt />
|
||||
</Suspense>
|
||||
|
||||
<PreloadIndicator />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function App() {
|
||||
console.log('[APP] 🚀 App component initializing')
|
||||
console.log('[APP] 🌐 Current URL:', window.location.href)
|
||||
console.log('[APP] 📍 Current pathname:', window.location.pathname)
|
||||
console.log('[APP] 🔍 Current search:', window.location.search)
|
||||
console.log('[APP] 🏷️ Current hash:', window.location.hash)
|
||||
|
||||
console.log('[APP] 🌱 Initializing seed data hook')
|
||||
const { loadSeedData } = useSeedData()
|
||||
const [appReady, setAppReady] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
console.log('[APP] 🚀 Initialization effect triggered')
|
||||
console.log('[APP] ⏰ Timestamp:', new Date().toISOString())
|
||||
console.time('[APP] Seed data loading')
|
||||
|
||||
const timer = setTimeout(() => {
|
||||
console.log('[APP] ⏱️ Fallback timer triggered (100ms)')
|
||||
setAppReady(true)
|
||||
}, 100)
|
||||
|
||||
console.log('[APP] 📥 Starting seed data load')
|
||||
loadSeedData()
|
||||
.then(() => {
|
||||
console.log('[APP] ✅ Seed data loaded successfully')
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('[APP] ❌ Seed data loading failed:', err)
|
||||
})
|
||||
.finally(() => {
|
||||
console.log('[APP] 🏁 Seed data loading complete')
|
||||
clearTimeout(timer)
|
||||
setAppReady(true)
|
||||
console.timeEnd('[APP] Seed data loading')
|
||||
console.log('[APP] ✅ App marked as ready')
|
||||
|
||||
console.log('[APP] 🚀 Preloading critical components')
|
||||
preloadCriticalComponents()
|
||||
|
||||
console.log('[APP] ⭐ Preloading popular routes')
|
||||
setTimeout(() => {
|
||||
routePreloadManager.preloadPopularRoutes()
|
||||
}, 1000)
|
||||
})
|
||||
|
||||
return () => {
|
||||
console.log('[APP] 🧹 Cleaning up initialization effect')
|
||||
clearTimeout(timer)
|
||||
}
|
||||
}, [loadSeedData])
|
||||
|
||||
console.log('[APP] 🎨 Rendering App component, appReady:', appReady)
|
||||
|
||||
return (
|
||||
<>
|
||||
{!appReady && (
|
||||
<div className="fixed inset-0 bg-background z-50 flex items-center justify-center">
|
||||
<div className="flex flex-col items-center gap-4">
|
||||
<div className="w-12 h-12 border-4 border-primary border-t-transparent rounded-full animate-spin" />
|
||||
<p className="text-sm text-muted-foreground">Loading CodeForge...</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<BrowserRouter>
|
||||
<AppLayout />
|
||||
</BrowserRouter>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
console.log('[APP] ✅ App component defined')
|
||||
console.timeEnd('[APP] Component initialization')
|
||||
|
||||
export default App
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
@import 'tailwindcss';
|
||||
@import "tw-animate-css";
|
||||
@import './styles/main.scss';
|
||||
|
||||
@layer base {
|
||||
* {
|
||||
@@ -8,58 +7,48 @@
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Inter', sans-serif;
|
||||
font-family: 'IBM Plex Sans', sans-serif;
|
||||
}
|
||||
|
||||
h1, h2, h3 {
|
||||
font-family: 'Space Grotesk', sans-serif;
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
}
|
||||
|
||||
code, pre {
|
||||
code, pre, textarea {
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
}
|
||||
}
|
||||
|
||||
@layer utilities {
|
||||
.react-flow__renderer {
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.react-flow__node {
|
||||
will-change: transform;
|
||||
}
|
||||
}
|
||||
|
||||
:root {
|
||||
--background: oklch(0.12 0.02 260);
|
||||
--foreground: oklch(0.95 0.005 260);
|
||||
--background: oklch(0.15 0.02 265);
|
||||
--foreground: oklch(0.95 0.01 265);
|
||||
|
||||
--card: oklch(0.16 0.02 260);
|
||||
--card-foreground: oklch(0.95 0.005 260);
|
||||
--card: oklch(0.19 0.02 265);
|
||||
--card-foreground: oklch(0.95 0.01 265);
|
||||
|
||||
--popover: oklch(0.16 0.02 260);
|
||||
--popover-foreground: oklch(0.95 0.005 260);
|
||||
--popover: oklch(0.19 0.02 265);
|
||||
--popover-foreground: oklch(0.95 0.01 265);
|
||||
|
||||
--primary: oklch(0.55 0.18 280);
|
||||
--primary: oklch(0.58 0.24 265);
|
||||
--primary-foreground: oklch(1 0 0);
|
||||
|
||||
--secondary: oklch(0.20 0.02 260);
|
||||
--secondary-foreground: oklch(0.95 0.005 260);
|
||||
--secondary: oklch(0.25 0.03 265);
|
||||
--secondary-foreground: oklch(0.95 0.01 265);
|
||||
|
||||
--muted: oklch(0.20 0.02 260);
|
||||
--muted-foreground: oklch(0.65 0.01 260);
|
||||
--muted: oklch(0.25 0.03 265);
|
||||
--muted-foreground: oklch(0.60 0.02 265);
|
||||
|
||||
--accent: oklch(0.75 0.15 195);
|
||||
--accent-foreground: oklch(0.12 0.02 260);
|
||||
--accent: oklch(0.75 0.20 145);
|
||||
--accent-foreground: oklch(0.15 0.02 265);
|
||||
|
||||
--destructive: oklch(0.55 0.22 25);
|
||||
--destructive: oklch(0.60 0.25 25);
|
||||
--destructive-foreground: oklch(1 0 0);
|
||||
|
||||
--border: oklch(0.22 0.02 260);
|
||||
--input: oklch(0.24 0.02 260);
|
||||
--ring: oklch(0.75 0.15 195);
|
||||
--border: oklch(0.28 0.03 265);
|
||||
--input: oklch(0.28 0.03 265);
|
||||
--ring: oklch(0.75 0.20 145);
|
||||
|
||||
--radius: 0.625rem;
|
||||
--radius: 0.5rem;
|
||||
}
|
||||
|
||||
@theme {
|
||||
@@ -90,13 +79,3 @@
|
||||
--radius-2xl: calc(var(--radius) * 3);
|
||||
--radius-full: 9999px;
|
||||
}
|
||||
|
||||
@layer components {
|
||||
[data-slot="tabs-list"] {
|
||||
@apply w-full;
|
||||
}
|
||||
|
||||
[data-slot="tabs-trigger"] {
|
||||
@apply flex-none;
|
||||
}
|
||||
}
|
||||
463
src/lib/docker-parser.ts
Normal file
463
src/lib/docker-parser.ts
Normal file
@@ -0,0 +1,463 @@
|
||||
import { DockerError, KnowledgeBaseItem, Solution } from '@/types/docker'
|
||||
|
||||
export function parseDockerLog(log: string): DockerError[] {
|
||||
const errors: DockerError[] = []
|
||||
const lines = log.split('\n')
|
||||
|
||||
let currentError: Partial<DockerError> | null = null
|
||||
let contextLines: string[] = []
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i]
|
||||
|
||||
if (line.includes('ERROR:') || line.includes('Error:')) {
|
||||
if (currentError) {
|
||||
errors.push({
|
||||
id: Math.random().toString(36).substr(2, 9),
|
||||
type: currentError.type || 'Unknown Error',
|
||||
message: currentError.message || 'An error occurred',
|
||||
stage: currentError.stage,
|
||||
exitCode: currentError.exitCode,
|
||||
context: contextLines.slice(-5),
|
||||
severity: 'critical'
|
||||
})
|
||||
}
|
||||
|
||||
currentError = {
|
||||
message: line.replace(/^.*?ERROR:\s*/, '').replace(/^.*?Error:\s*/, '').trim()
|
||||
}
|
||||
contextLines = [line]
|
||||
|
||||
const stageMatch = log.match(/\[([^\]]+)\s+\d+\/\d+\]/)
|
||||
if (stageMatch) {
|
||||
currentError.stage = stageMatch[1]
|
||||
}
|
||||
|
||||
const exitCodeMatch = line.match(/exit code[:\s]+(\d+)/i)
|
||||
if (exitCodeMatch) {
|
||||
currentError.exitCode = parseInt(exitCodeMatch[1], 10)
|
||||
}
|
||||
|
||||
currentError.type = detectErrorType(line, log)
|
||||
} else if (currentError) {
|
||||
contextLines.push(line)
|
||||
}
|
||||
}
|
||||
|
||||
if (currentError) {
|
||||
errors.push({
|
||||
id: Math.random().toString(36).substr(2, 9),
|
||||
type: currentError.type || 'Unknown Error',
|
||||
message: currentError.message || 'An error occurred',
|
||||
stage: currentError.stage,
|
||||
exitCode: currentError.exitCode,
|
||||
context: contextLines.slice(-5),
|
||||
severity: 'critical'
|
||||
})
|
||||
}
|
||||
|
||||
return errors
|
||||
}
|
||||
|
||||
function detectErrorType(errorLine: string, fullLog: string): string {
|
||||
const lowerError = errorLine.toLowerCase()
|
||||
const lowerLog = fullLog.toLowerCase()
|
||||
|
||||
if (lowerError.includes('cannot find module') || lowerError.includes('module_not_found')) {
|
||||
return 'Missing Dependency'
|
||||
}
|
||||
|
||||
if (lowerError.includes('enoent') || lowerError.includes('no such file')) {
|
||||
return 'File Not Found'
|
||||
}
|
||||
|
||||
if (lowerLog.includes('arm64') || lowerLog.includes('amd64') || lowerError.includes('platform')) {
|
||||
return 'Platform/Architecture Issue'
|
||||
}
|
||||
|
||||
if (lowerError.includes('permission denied') || lowerError.includes('eacces')) {
|
||||
return 'Permission Error'
|
||||
}
|
||||
|
||||
if (lowerError.includes('network') || lowerError.includes('timeout') || lowerError.includes('connection')) {
|
||||
return 'Network Error'
|
||||
}
|
||||
|
||||
if (lowerError.includes('syntax') || lowerError.includes('unexpected')) {
|
||||
return 'Syntax Error'
|
||||
}
|
||||
|
||||
if (lowerError.includes('memory') || lowerError.includes('out of')) {
|
||||
return 'Resource Limit'
|
||||
}
|
||||
|
||||
return 'Build Failure'
|
||||
}
|
||||
|
||||
export function getSolutionsForError(error: DockerError): Solution[] {
|
||||
const solutions: Solution[] = []
|
||||
|
||||
const type = error.type.toLowerCase()
|
||||
|
||||
if (type.includes('missing dependency') || type.includes('module')) {
|
||||
if (error.message.includes('@rollup/rollup') || error.message.includes('rollup')) {
|
||||
solutions.push({
|
||||
title: 'Install Platform-Specific Rollup Dependencies',
|
||||
description: 'The Rollup bundler requires platform-specific native binaries. For multi-platform Docker builds, you need to ensure optional dependencies are installed.',
|
||||
steps: [
|
||||
'Update your Dockerfile to force install optional dependencies',
|
||||
'Use --platform flag to ensure correct architecture binaries',
|
||||
'Consider using --legacy-peer-deps flag'
|
||||
],
|
||||
code: `# In your Dockerfile, change the npm install line to:
|
||||
RUN npm install --legacy-peer-deps --include=optional
|
||||
|
||||
# Or explicitly install the missing package:
|
||||
RUN npm install @rollup/rollup-linux-arm64-musl --save-optional`,
|
||||
codeLanguage: 'dockerfile'
|
||||
})
|
||||
|
||||
solutions.push({
|
||||
title: 'Update package.json optionalDependencies',
|
||||
description: 'Explicitly declare platform-specific Rollup dependencies as optional.',
|
||||
steps: [
|
||||
'Add optionalDependencies section to package.json',
|
||||
'Include all platform variants of Rollup',
|
||||
'Rebuild your Docker image'
|
||||
],
|
||||
code: `{
|
||||
"optionalDependencies": {
|
||||
"@rollup/rollup-linux-arm64-musl": "^4.53.3",
|
||||
"@rollup/rollup-linux-x64-musl": "^4.53.3",
|
||||
"@rollup/rollup-darwin-arm64": "^4.53.3",
|
||||
"@rollup/rollup-darwin-x64": "^4.53.3"
|
||||
}
|
||||
}`,
|
||||
codeLanguage: 'json'
|
||||
})
|
||||
} else {
|
||||
solutions.push({
|
||||
title: 'Install Missing Node Module',
|
||||
description: 'A required npm package is not installed in your Docker image.',
|
||||
steps: [
|
||||
'Verify the package is listed in package.json',
|
||||
'Ensure npm install runs before the build step',
|
||||
'Check for typos in import statements'
|
||||
],
|
||||
code: `# Make sure your Dockerfile includes:
|
||||
COPY package*.json ./
|
||||
RUN npm install
|
||||
COPY . .
|
||||
RUN npm run build`,
|
||||
codeLanguage: 'dockerfile'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (type.includes('platform') || type.includes('architecture')) {
|
||||
solutions.push({
|
||||
title: 'Build for Single Platform',
|
||||
description: 'If you don\'t need multi-platform support, build for a single architecture to avoid complexity.',
|
||||
steps: [
|
||||
'Remove --platform flag from docker build command',
|
||||
'Or specify only one platform: --platform linux/amd64',
|
||||
'This will speed up builds and avoid architecture-specific issues'
|
||||
],
|
||||
code: `# Instead of:
|
||||
docker buildx build --platform linux/amd64,linux/arm64 .
|
||||
|
||||
# Use:
|
||||
docker buildx build --platform linux/amd64 .`,
|
||||
codeLanguage: 'bash'
|
||||
})
|
||||
|
||||
solutions.push({
|
||||
title: 'Use QEMU for Cross-Platform Builds',
|
||||
description: 'Set up proper emulation for building ARM images on x64 hosts.',
|
||||
steps: [
|
||||
'Install QEMU binfmt support',
|
||||
'Create a new buildx builder instance',
|
||||
'Verify the builder supports multiple platforms'
|
||||
],
|
||||
code: `# Set up buildx with QEMU
|
||||
docker run --privileged --rm tonistiigi/binfmt --install all
|
||||
docker buildx create --name multiplatform --driver docker-container --use
|
||||
docker buildx inspect --bootstrap`,
|
||||
codeLanguage: 'bash'
|
||||
})
|
||||
}
|
||||
|
||||
if (type.includes('file not found')) {
|
||||
solutions.push({
|
||||
title: 'Check File Paths and .dockerignore',
|
||||
description: 'Verify that all required files are copied into the Docker build context.',
|
||||
steps: [
|
||||
'Check .dockerignore to ensure needed files aren\'t excluded',
|
||||
'Verify COPY commands use correct paths',
|
||||
'Ensure files exist in your repository'
|
||||
],
|
||||
code: `# In .dockerignore, make sure you're not ignoring needed files
|
||||
# Remove these if they're blocking required files:
|
||||
# node_modules
|
||||
# dist
|
||||
# build`,
|
||||
codeLanguage: 'text'
|
||||
})
|
||||
}
|
||||
|
||||
if (type.includes('permission')) {
|
||||
solutions.push({
|
||||
title: 'Fix File Permissions',
|
||||
description: 'The Docker build process doesn\'t have permission to access required files.',
|
||||
steps: [
|
||||
'Check file permissions in your repository',
|
||||
'Add RUN chmod commands if needed',
|
||||
'Consider using a non-root user correctly'
|
||||
],
|
||||
code: `# In Dockerfile, add permission fixes:
|
||||
RUN chmod +x /app/scripts/*.sh
|
||||
RUN chown -R node:node /app`,
|
||||
codeLanguage: 'dockerfile'
|
||||
})
|
||||
}
|
||||
|
||||
if (solutions.length === 0) {
|
||||
solutions.push({
|
||||
title: 'General Docker Build Troubleshooting',
|
||||
description: 'Try these common fixes for Docker build issues.',
|
||||
steps: [
|
||||
'Clear Docker build cache: docker builder prune',
|
||||
'Rebuild without cache: docker build --no-cache',
|
||||
'Check Docker daemon logs for more details',
|
||||
'Verify your Dockerfile syntax is correct',
|
||||
'Ensure base images are accessible and up to date'
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
return solutions
|
||||
}
|
||||
|
||||
export const knowledgeBase: KnowledgeBaseItem[] = [
|
||||
{
|
||||
id: 'rollup-missing',
|
||||
category: 'Dependencies',
|
||||
title: 'Rollup Platform-Specific Binary Missing',
|
||||
pattern: 'Cannot find module @rollup/rollup-*',
|
||||
explanation: 'Rollup uses platform-specific native binaries that are installed as optional dependencies. In Docker multi-platform builds, npm may not install the correct optional dependencies for all target platforms.',
|
||||
solutions: [
|
||||
{
|
||||
title: 'Install Optional Dependencies Explicitly',
|
||||
description: 'Force npm to install all optional dependencies during the Docker build.',
|
||||
steps: [
|
||||
'Modify the RUN npm install command in your Dockerfile',
|
||||
'Add the --include=optional flag',
|
||||
'Rebuild your Docker image'
|
||||
],
|
||||
code: 'RUN npm install --legacy-peer-deps --include=optional',
|
||||
codeLanguage: 'dockerfile'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'multi-platform',
|
||||
category: 'Architecture',
|
||||
title: 'Multi-Platform Build Issues',
|
||||
pattern: '--platform linux/amd64,linux/arm64',
|
||||
explanation: 'Building Docker images for multiple CPU architectures (amd64 and arm64) requires proper setup of buildx and may encounter platform-specific dependency issues.',
|
||||
solutions: [
|
||||
{
|
||||
title: 'Build for Single Platform Only',
|
||||
description: 'Simplify by targeting only one architecture.',
|
||||
steps: [
|
||||
'Choose the primary platform (usually linux/amd64)',
|
||||
'Remove multi-platform flags from build command',
|
||||
'Update deployment configuration'
|
||||
],
|
||||
code: 'docker build --platform linux/amd64 -t myimage:latest .',
|
||||
codeLanguage: 'bash'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'node-modules',
|
||||
category: 'Dependencies',
|
||||
title: 'Node Modules Not Found',
|
||||
pattern: 'MODULE_NOT_FOUND',
|
||||
explanation: 'A required npm package is missing from node_modules, either because npm install failed, the package isn\'t in package.json, or Docker layer caching is stale.',
|
||||
solutions: [
|
||||
{
|
||||
title: 'Verify Dockerfile Order',
|
||||
description: 'Ensure proper layer ordering in your Dockerfile.',
|
||||
steps: [
|
||||
'Copy package.json and package-lock.json first',
|
||||
'Run npm install',
|
||||
'Then copy the rest of the source code',
|
||||
'Finally run the build'
|
||||
],
|
||||
code: `COPY package*.json ./
|
||||
RUN npm install
|
||||
COPY . .
|
||||
RUN npm run build`,
|
||||
codeLanguage: 'dockerfile'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'build-exit-1',
|
||||
category: 'Build Process',
|
||||
title: 'Build Process Exit Code 1',
|
||||
pattern: 'exit code: 1',
|
||||
explanation: 'The build command failed with a generic error code. This usually indicates a compilation error, missing dependency, or configuration issue.',
|
||||
solutions: [
|
||||
{
|
||||
title: 'Check Build Logs for Specific Error',
|
||||
description: 'Look earlier in the build output for the actual error message.',
|
||||
steps: [
|
||||
'Scroll up to find the first ERROR or Error message',
|
||||
'Look for stack traces or line numbers',
|
||||
'Test the build locally with the same commands',
|
||||
'Check for environment-specific issues'
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'network-timeout',
|
||||
category: 'Network',
|
||||
title: 'Network Timeout During Build',
|
||||
pattern: 'timeout|ETIMEDOUT|ECONNREFUSED',
|
||||
explanation: 'Docker build couldn\'t connect to external services like npm registry, causing the build to fail.',
|
||||
solutions: [
|
||||
{
|
||||
title: 'Configure Network Settings',
|
||||
description: 'Adjust Docker network configuration and retry logic.',
|
||||
steps: [
|
||||
'Check Docker daemon network settings',
|
||||
'Configure npm registry timeout',
|
||||
'Consider using a mirror or proxy',
|
||||
'Retry the build'
|
||||
],
|
||||
code: `# In Dockerfile, before npm install:
|
||||
RUN npm config set fetch-timeout 60000
|
||||
RUN npm config set fetch-retries 5`,
|
||||
codeLanguage: 'dockerfile'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'memory-limit',
|
||||
category: 'Resources',
|
||||
title: 'Out of Memory During Build',
|
||||
pattern: 'JavaScript heap out of memory|ENOMEM',
|
||||
explanation: 'The Node.js build process exceeded available memory limits, common with large applications or many dependencies.',
|
||||
solutions: [
|
||||
{
|
||||
title: 'Increase Node Memory Limit',
|
||||
description: 'Allocate more memory to the Node.js process during build.',
|
||||
steps: [
|
||||
'Set NODE_OPTIONS environment variable',
|
||||
'Increase max-old-space-size value',
|
||||
'Rebuild Docker image'
|
||||
],
|
||||
code: `# In Dockerfile, before build command:
|
||||
ENV NODE_OPTIONS="--max-old-space-size=4096"
|
||||
RUN npm run build`,
|
||||
codeLanguage: 'dockerfile'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'cache-corruption',
|
||||
category: 'Cache',
|
||||
title: 'Docker Layer Cache Issues',
|
||||
pattern: 'Cached layer|using cache',
|
||||
explanation: 'Docker\'s layer caching can sometimes use stale or corrupted cached layers, leading to inconsistent builds.',
|
||||
solutions: [
|
||||
{
|
||||
title: 'Clear Build Cache',
|
||||
description: 'Force a clean build without using cached layers.',
|
||||
steps: [
|
||||
'Run docker builder prune to clear cache',
|
||||
'Build with --no-cache flag',
|
||||
'Verify the clean build succeeds'
|
||||
],
|
||||
code: `docker builder prune -af
|
||||
docker build --no-cache -t myimage:latest .`,
|
||||
codeLanguage: 'bash'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'base-image-issue',
|
||||
category: 'Images',
|
||||
title: 'Base Image Not Found or Incompatible',
|
||||
pattern: 'pull access denied|manifest unknown|not found',
|
||||
explanation: 'The base image specified in FROM instruction is unavailable, misspelled, or incompatible with the target platform.',
|
||||
solutions: [
|
||||
{
|
||||
title: 'Verify Base Image',
|
||||
description: 'Check that the base image exists and is accessible.',
|
||||
steps: [
|
||||
'Verify image name and tag on Docker Hub',
|
||||
'Check if the image supports your target platform',
|
||||
'Try pulling the image manually first',
|
||||
'Consider using a different tag or base image'
|
||||
],
|
||||
code: `# Test pulling the image first:
|
||||
docker pull node:20-alpine
|
||||
|
||||
# Verify platform support:
|
||||
docker manifest inspect node:20-alpine`,
|
||||
codeLanguage: 'bash'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'dockerfile-syntax',
|
||||
category: 'Configuration',
|
||||
title: 'Dockerfile Syntax Error',
|
||||
pattern: 'unknown instruction|unexpected token',
|
||||
explanation: 'The Dockerfile contains syntax errors or uses unsupported instructions.',
|
||||
solutions: [
|
||||
{
|
||||
title: 'Validate Dockerfile Syntax',
|
||||
description: 'Check your Dockerfile for common syntax issues.',
|
||||
steps: [
|
||||
'Ensure all instructions are uppercase (FROM, RUN, COPY)',
|
||||
'Check for typos in instruction names',
|
||||
'Verify line continuations with backslash',
|
||||
'Use hadolint to lint your Dockerfile'
|
||||
],
|
||||
code: `# Install and run hadolint:
|
||||
docker run --rm -i hadolint/hadolint < Dockerfile`,
|
||||
codeLanguage: 'bash'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'copy-failed',
|
||||
category: 'Files',
|
||||
title: 'COPY Instruction Failed',
|
||||
pattern: 'COPY failed|no such file or directory',
|
||||
explanation: 'Docker couldn\'t find the files or directories specified in a COPY instruction, or they\'re excluded by .dockerignore.',
|
||||
solutions: [
|
||||
{
|
||||
title: 'Check File Paths and Context',
|
||||
description: 'Verify files exist and are included in build context.',
|
||||
steps: [
|
||||
'Confirm files exist in your repository',
|
||||
'Check .dockerignore isn\'t excluding them',
|
||||
'Ensure COPY paths are relative to build context',
|
||||
'List build context: docker build -t test --progress=plain .'
|
||||
],
|
||||
code: `# In .dockerignore, check for overly broad patterns:
|
||||
# These might exclude too much:
|
||||
# *
|
||||
# node_modules/*
|
||||
# src/*`,
|
||||
codeLanguage: 'text'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
26
src/types/docker.ts
Normal file
26
src/types/docker.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
export interface DockerError {
|
||||
id: string
|
||||
type: string
|
||||
message: string
|
||||
stage?: string
|
||||
exitCode?: number
|
||||
context: string[]
|
||||
severity: 'critical' | 'warning' | 'info'
|
||||
}
|
||||
|
||||
export interface Solution {
|
||||
title: string
|
||||
description: string
|
||||
steps: string[]
|
||||
code?: string
|
||||
codeLanguage?: string
|
||||
}
|
||||
|
||||
export interface KnowledgeBaseItem {
|
||||
id: string
|
||||
category: string
|
||||
title: string
|
||||
pattern: string
|
||||
explanation: string
|
||||
solutions: Solution[]
|
||||
}
|
||||
Reference in New Issue
Block a user