diff --git a/.taskfiles/desktop.yml b/.taskfiles/desktop.yml index 4615c977a..46a06abd8 100644 --- a/.taskfiles/desktop.yml +++ b/.taskfiles/desktop.yml @@ -31,52 +31,60 @@ tasks: provisioner: desc: "Build installer provisioner" platforms: [windows] + dir: editor cmds: - - node editor/scripts/build-provisioner.mjs + - node scripts/build-provisioner.mjs dev: desc: "Start Tauri desktop dev mode" deps: [prepare] ignore_error: true + dir: editor cmds: - - cd editor && npx tauri dev --no-watch + - npx tauri dev --no-watch build: desc: "Build Tauri desktop app (production)" deps: [prepare] + dir: editor cmds: - - cd editor && npx tauri build + - npx tauri build build:dev: desc: "Build Tauri desktop app (dev, no bundling)" deps: [prepare] + dir: editor cmds: - - cd editor && npx tauri build --no-bundle + - npx tauri build --no-bundle build:dev:mac: desc: "Build Tauri desktop .app bundle (macOS)" deps: [prepare] + dir: editor cmds: - - cd editor && npx tauri build --bundles app + - npx tauri build --bundles app build:dev:windows: desc: "Build Tauri desktop NSIS installer (Windows)" deps: [prepare] + dir: editor cmds: - - cd editor && npx tauri build --bundles nsis + - npx tauri build --bundles nsis build:dev:linux: desc: "Build Tauri desktop AppImage (Linux)" deps: [prepare] + dir: editor cmds: - - cd editor && npx tauri build --bundles appimage + - npx tauri build --bundles appimage clean: desc: "Clean Tauri/Cargo build artifacts" + dir: editor cmds: - task: jlink:clean - - cd editor/src-tauri && cargo clean - - rm -rf editor/dist editor/build + - cd src-tauri && cargo clean + - rm -rf dist build # ============================================================ # JLink — Build bundled Java runtime for Tauri @@ -106,9 +114,10 @@ tasks: jlink:runtime: desc: "Create custom JRE with jlink" deps: [jlink:jar] + dir: editor/src-tauri cmds: - - rm -rf editor/src-tauri/runtime/jre - - mkdir -p editor/src-tauri/runtime + - rm -rf runtime/jre + - mkdir -p runtime - >- jlink --add-modules {{.JLINK_MODULES}} @@ -116,14 +125,15 @@ tasks: --compress=zip-6 --no-header-files --no-man-pages - --output editor/src-tauri/runtime/jre + --output runtime/jre status: - test -d editor/src-tauri/runtime/jre jlink:clean: desc: "Remove JLink runtime and bundled JARs" + dir: editor/src-tauri cmds: - - rm -rf editor/src-tauri/libs editor/src-tauri/runtime + - rm -rf libs runtime # macOS-only. Replaces jlink:runtime's single-arch JRE with a universal # (arm64 + x86_64) one for the universal Tauri shell. Runs the x86_64 @@ -134,8 +144,9 @@ tasks: desc: "Create universal (arm64+x86_64) JRE for the macOS Tauri build" deps: [jlink:jar] platforms: [darwin] + dir: editor env: JLINK_MODULES: "{{.JLINK_MODULES}}" - OUTPUT_DIR: editor/src-tauri/runtime/jre + OUTPUT_DIR: src-tauri/runtime/jre cmds: - - editor/scripts/build-universal-mac-jre.sh + - scripts/build-universal-mac-jre.sh diff --git a/app/core/build.gradle b/app/core/build.gradle index b85b4544f..54bdd7bd7 100644 --- a/app/core/build.gradle +++ b/app/core/build.gradle @@ -196,9 +196,13 @@ if (buildPrototypes) { } def frontendBuildTask = "frontend:build:${frontendMode}" +// Workspace root holds package.json and node_modules (shared across editor / +// future portal). Editor-specific paths (src, public, dist, tauri) live one +// level deeper under frontend/editor/. When the portal lands as an embedded +// app, add a sibling frontendPortalDir / frontendPortalDistDir alongside. def frontendDir = file('../../frontend') def frontendEditorDir = file('../../frontend/editor') -def frontendDistDir = file('../../frontend/editor/dist') +def frontendEditorDistDir = file('../../frontend/editor/dist') def resourcesStaticDir = file('src/main/resources/static') def generatedFrontendPaths = [ 'assets', @@ -263,13 +267,13 @@ tasks.register('npmBuild', Exec) { doNotTrackState("Frontend build depends on untracked npmInstall task") enabled = buildWithFrontend group = 'frontend' - description = 'Build frontend application' + description = 'Build editor frontend application' workingDir file('../..') commandLine = ['task', frontendBuildTask] inputs.dir(new File(frontendEditorDir, 'src')) inputs.dir(new File(frontendEditorDir, 'public')) inputs.file(new File(frontendDir, 'package.json')) - outputs.dir(frontendDistDir) + outputs.dir(frontendEditorDistDir) // Show live output standardOutput = System.out @@ -280,17 +284,17 @@ tasks.register('npmBuild', Exec) { environment 'VITE_API_BASE_URL', '/' doFirst { - println "Building frontend application for production (mode=${frontendMode}, VITE_API_BASE_URL=/)" + println "Building editor frontend application for production (mode=${frontendMode}, VITE_API_BASE_URL=/)" } } tasks.register('copyFrontendAssets', Copy) { enabled = buildWithFrontend group = 'frontend' - description = 'Copy frontend build to static resources' + description = 'Copy editor frontend build to static resources' dependsOn npmBuild dependsOn cleanFrontendAssets - from(frontendDistDir) { + from(frontendEditorDistDir) { // Exclude files that conflict with backend static resources exclude 'robots.txt' // Backend already has this exclude 'favicon.ico' // Backend already has this @@ -298,7 +302,7 @@ tasks.register('copyFrontendAssets', Copy) { into resourcesStaticDir duplicatesStrategy = DuplicatesStrategy.INCLUDE // Let frontend overwrite when needed doFirst { - println "Copying frontend build from ${frontendDistDir} to ${resourcesStaticDir}..." + println "Copying frontend build from ${frontendEditorDistDir} to ${resourcesStaticDir}..." println "Backend static resources will be preserved" } doLast { @@ -330,7 +334,7 @@ tasks.named('copyFrontendAssets').configure { } if (buildWithFrontend) { - println "Frontend build enabled - JAR will include React frontend (mode=${frontendMode})" + println "Editor frontend build enabled - JAR will include React frontend (mode=${frontendMode})" processResources.dependsOn copyFrontendAssets } else { println "Frontend build disabled - JAR will be backend-only with API landing page" diff --git a/frontend/.prettierignore b/frontend/.prettierignore index 6bada9283..c8240371d 100644 --- a/frontend/.prettierignore +++ b/frontend/.prettierignore @@ -1,8 +1,10 @@ dist/ dist-portal/ editor/dist/ -# Tauri/Cargo build output (binary assets named *.js etc. confuse Prettier) -editor/src-tauri/target/ +# Tauri/Cargo build output (binary assets named *.js etc. confuse Prettier). +# Match nested target/ dirs too — provisioner/ and thumbnail-handler/ each +# have their own Cargo workspace under src-tauri/. +editor/src-tauri/**/target/ editor/src-tauri/gen/ node_modules/ editor/public/vendor/ diff --git a/frontend/editor/scripts/setup-env.mts b/frontend/editor/scripts/setup-env.mts index c955ba3ae..553ba181e 100644 --- a/frontend/editor/scripts/setup-env.mts +++ b/frontend/editor/scripts/setup-env.mts @@ -6,9 +6,18 @@ * Vite automatically layers these `.local` files on top of the committed ones. * * Usage: - * tsx scripts/setup-env.ts # ensures .env.local - * tsx scripts/setup-env.ts --desktop # also ensures .env.desktop.local - * tsx scripts/setup-env.ts --saas # also ensures .env.saas.local + * tsx scripts/setup-env.mts # ensures .env.local + * tsx scripts/setup-env.mts --desktop # also ensures .env.desktop.local + * tsx scripts/setup-env.mts --saas # also ensures .env.saas.local + * + * Why .mts (and not .ts)? + * This script needs `import.meta.url` to resolve paths relative to itself, + * because Task invokes it from the workspace root (frontend/) but the .env + * files live one level deeper at frontend/editor/. `import.meta` is only + * valid in ESM output; `editor/scripts/tsconfig.json` extends the editor + * tsconfig which uses `module: node16`, treating plain .ts as CommonJS + * (TS1470 error on `import.meta`). The .mts extension explicitly marks + * the file as ESM, which tsx already runs at runtime anyway. */ import { existsSync, writeFileSync } from "fs"; @@ -17,8 +26,6 @@ import { fileURLToPath } from "url"; // .env files live next to the editor's vite.config.ts (frontend/editor/). // Resolve relative to this script regardless of where the build was invoked. -// `import.meta.dirname` would be tidier but isn't available under tsx's CJS -// transpilation today, so go via fileURLToPath for portability. const scriptDir = dirname(fileURLToPath(import.meta.url)); const root = resolve(scriptDir, ".."); const args = process.argv.slice(2); diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index 6b42ad585..8641e4120 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -7,7 +7,8 @@ import tseslint from "typescript-eslint"; const srcGlobs = ["editor/src/**/*.{js,mjs,jsx,ts,tsx}"]; const nodeGlobs = [ - "editor/scripts/**/*.{js,ts,mjs}", + "scripts/**/*.{js,ts,mjs,mts}", + "editor/scripts/**/*.{js,ts,mjs,mts}", "editor/*.config.{js,ts,mjs}", "*.config.{js,ts,mjs}", ]; diff --git a/frontend/package.json b/frontend/package.json index 3567411f2..a23ee45d3 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -82,7 +82,7 @@ "web-vitals": "^5.1.0" }, "scripts": { - "update:minor": "node editor/scripts/update-minor.js", + "update:minor": "node scripts/update-minor.js", "update:major": "npx npm-check-updates -u && npm install", "update:interactive": "npx npm-check-updates -i", "update:minor-strict": "npx npm-check-updates -u --target minor && npm install" diff --git a/frontend/editor/scripts/update-minor.js b/frontend/scripts/update-minor.js similarity index 100% rename from frontend/editor/scripts/update-minor.js rename to frontend/scripts/update-minor.js