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:
2026-01-17 14:56:40 +00:00
committed by GitHub
parent 57e9507fe7
commit d388a9a075
6 changed files with 1022 additions and 561 deletions

211
PRD.md
View File

@@ -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

View File

@@ -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>

View File

@@ -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

View File

@@ -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
View 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
View 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[]
}