diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 40618c5973..b55715e5e2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -235,7 +235,9 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Run frontend lint - run: docker run --rm ${{ needs.build-frontend.outputs.image }} lint + run: | + docker run --rm \ + ${{ needs.build-frontend.outputs.image }} lint dockerfile-lint: name: Dockerfile Lint (hadolint) @@ -693,7 +695,7 @@ jobs: -e PRIVATE_BACKEND_URL=http://backend:8000 \ -e FEATURE_FLAGS="*" \ -p 3000:3000 \ - ${{ needs.build-frontend.outputs.image }} nuxt-local & + ${{ needs.build-frontend.outputs.image }} nuxt-prod & # Wait for all docker run commands to complete wait diff --git a/deploy/all-in-one/Dockerfile b/deploy/all-in-one/Dockerfile index 659ce7f3c1..622803e9b0 100644 --- a/deploy/all-in-one/Dockerfile +++ b/deploy/all-in-one/Dockerfile @@ -93,8 +93,6 @@ ARG GID # Web-frontend COPY --chown=$UID:$GID --from=web_frontend_image /baserow/web-frontend /baserow/web-frontend -COPY --chown=$UID:$GID --from=web_frontend_image /baserow/premium/web-frontend /baserow/premium/web-frontend -COPY --chown=$UID:$GID --from=web_frontend_image /baserow/enterprise/web-frontend /baserow/enterprise/web-frontend # Backend COPY --chown=$UID:$GID --from=backend_image /baserow/backend /baserow/backend @@ -144,8 +142,6 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ # Web-frontend COPY --chown=$UID:$GID --from=web_frontend_image /baserow/web-frontend /baserow/web-frontend -COPY --chown=$UID:$GID --from=web_frontend_image /baserow/premium/web-frontend /baserow/premium/web-frontend -COPY --chown=$UID:$GID --from=web_frontend_image /baserow/enterprise/web-frontend /baserow/enterprise/web-frontend # Backend COPY --chown=$UID:$GID --from=backend_image /baserow/backend /baserow/backend diff --git a/deploy/all-in-one/supervisor/default_baserow_env.sh b/deploy/all-in-one/supervisor/default_baserow_env.sh index 5e4453f10a..0490146632 100755 --- a/deploy/all-in-one/supervisor/default_baserow_env.sh +++ b/deploy/all-in-one/supervisor/default_baserow_env.sh @@ -60,7 +60,7 @@ if [[ "${BASEROW_ALL_IN_ONE_DEV_MODE:-}" == "true" ]]; then DEFAULT_CELERY_BEAT_STARTUP_COMMAND='celery-beat' else DEFAULT_DJANGO_SETTINGS_MODULE='baserow.config.settings.base' - DEFAULT_WEB_FRONTEND_STARTUP_COMMAND='nuxt-local' + DEFAULT_WEB_FRONTEND_STARTUP_COMMAND='nuxt-prod' DEFAULT_BACKEND_STARTUP_COMMAND='gunicorn' DEFAULT_CELERY_WORKER_STARTUP_COMMAND='celery-worker' DEFAULT_CELERY_EXPORT_WORKER_STARTUP_COMMAND='celery-exportworker' diff --git a/deploy/plugins/install_plugin.sh b/deploy/plugins/install_plugin.sh index ad0baffd4a..c5de5bd5d4 100755 --- a/deploy/plugins/install_plugin.sh +++ b/deploy/plugins/install_plugin.sh @@ -245,7 +245,7 @@ if [[ -d "/baserow/web-frontend" && -d "$PLUGIN_WEBFRONTEND_FOLDER" ]]; then run_as_docker_user yarn add "$PLUGIN_WEBFRONTEND_FOLDER" && yarn cache clean # We only load web-frontend modules into nuxt which have a built marker. Touch - # it now so the build-local picks up the newly installed module and builds it. + # it now so the build picks up the newly installed module and builds it. touch "$WEBFRONTEND_BUILT_MARKER" function finish { rm -f "$WEBFRONTEND_BUILT_MARKER" @@ -253,7 +253,7 @@ if [[ -d "/baserow/web-frontend" && -d "$PLUGIN_WEBFRONTEND_FOLDER" ]]; then trap finish EXIT if [[ "$dev" != true ]]; then - run_as_docker_user /baserow/web-frontend/docker/docker-entrypoint.sh build-local + run_as_docker_user /baserow/web-frontend/docker/docker-entrypoint.sh build else log "Installing plugins dev dependencies..." # In dev mode yarn install the plugins own dependencies so they are available diff --git a/deploy/plugins/uninstall_plugin.sh b/deploy/plugins/uninstall_plugin.sh index f6c0f4983d..e49f8346cc 100755 --- a/deploy/plugins/uninstall_plugin.sh +++ b/deploy/plugins/uninstall_plugin.sh @@ -69,11 +69,11 @@ if [[ -d "/baserow/web-frontend" && -d "$PLUGIN_WEBFRONTEND_FOLDER" ]]; then check_and_run_script "$PLUGIN_WEBFRONTEND_FOLDER" uninstall.sh run_as_docker_user yarn remove "$package_name" - # We must delete the web-frontend plugin entirely so the build-local doesn't + # We must delete the web-frontend plugin entirely so the build doesn't # pick it up and build it. rm -rf "$PLUGIN_WEBFRONTEND_FOLDER" # We need to rebuild to ensure nuxt no longer has the plugin. - run_as_docker_user /baserow/web-frontend/docker/docker-entrypoint.sh build-local + run_as_docker_user /baserow/web-frontend/docker/docker-entrypoint.sh build rm -f /baserow/container_markers/"$plugin_name".web-frontend-built rm -f /baserow/container_markers/"$plugin_name".web-frontend-runtime-setup found_sub_module="true" diff --git a/docs/installation/install-using-standalone-images.md b/docs/installation/install-using-standalone-images.md index d962bc3deb..51d0234d13 100644 --- a/docs/installation/install-using-standalone-images.md +++ b/docs/installation/install-using-standalone-images.md @@ -30,7 +30,7 @@ images: * `baserow/backend:2.0.6` (default command is `gunicorn`) * `baserow/backend:2.0.6` with command `celery-worker` * `baserow/backend:2.0.6` with command `celery-export-worker` -* `baserow/web-frontend:2.0.6` (default command is `nuxt-local`) +* `baserow/web-frontend:2.0.6` (default command is `nuxt-prod`) * A postgres database * A redis server diff --git a/e2e-tests/justfile b/e2e-tests/justfile index 6f956fc52b..ef5c83cd75 100644 --- a/e2e-tests/justfile +++ b/e2e-tests/justfile @@ -202,7 +202,7 @@ up: _ensure-images -e PRIVATE_BACKEND_URL=http://e2e-backend:8000 \ -e FEATURE_FLAGS="*" \ -p 3000:3000 \ - {{ frontend_image }} nuxt-local + {{ frontend_image }} nuxt-prod fi echo "" diff --git a/enterprise/web-frontend/eslint.config.mjs b/enterprise/web-frontend/eslint.config.mjs deleted file mode 100644 index 685dc0377e..0000000000 --- a/enterprise/web-frontend/eslint.config.mjs +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -import withNuxt from '../../web-frontend/.nuxt/eslint.config.mjs' -import common from '../../web-frontend/eslint.config.common.mjs' - -export default withNuxt([ - ...common, - { rules: { 'vue/order-in-components': 'off' } }, -]) diff --git a/web-frontend/eslint.config.common.mjs b/eslint.config.mjs similarity index 53% rename from web-frontend/eslint.config.common.mjs rename to eslint.config.mjs index 6b0daaf249..12bd1dd0ec 100644 --- a/web-frontend/eslint.config.common.mjs +++ b/eslint.config.mjs @@ -1,22 +1,30 @@ -// Please keep in sync with the premium/enterprise eslintrc.js -import withNuxt from './.nuxt/eslint.config.mjs' +// @ts-check +import withNuxt from './web-frontend/.nuxt/eslint.config.mjs' +import globals from './web-frontend/node_modules/globals/index.js' +import vitest from './web-frontend/node_modules/eslint-plugin-vitest/dist/index.mjs' +import eslintConfigPrettier from './web-frontend/node_modules/eslint-config-prettier/index.js' -import globals from 'globals' -import vitest from 'eslint-plugin-vitest' -import eslintConfigPrettier from 'eslint-config-prettier' - -export default [ +export default withNuxt([ { ignores: [ - '.nuxt/**', '**/node_modules/**', - 'coverage/**', + '**/.nuxt/**', + '**/coverage/**', '**/generated/**', - '.nuxt-storybook/**', + '**/.nuxt-storybook/**', + '**/dist/**', + '**/.output/**', + '**/.storybook/**', + '**/vitest.setup.ts', ], }, eslintConfigPrettier, // deactivate eslint rules that conflict with prettier { + files: [ + 'web-frontend/**/*.{js,ts,mjs,mts,jsx,tsx,vue}', + 'premium/web-frontend/**/*.{js,ts,mjs,mts,jsx,tsx,vue}', + 'enterprise/web-frontend/**/*.{js,ts,mjs,mts,jsx,tsx,vue}', + ], languageOptions: { globals: { ...globals.browser, @@ -40,7 +48,17 @@ export default [ 'no-empty': 'off', }, }, - + // Premium and Enterprise-specific overrides + { + files: [ + 'premium/web-frontend/**/*.{js,ts,mjs,mts,jsx,tsx,vue}', + 'enterprise/web-frontend/**/*.{js,ts,mjs,mts,jsx,tsx,vue}', + ], + rules: { + 'vue/order-in-components': 'off', + }, + }, + // Test files configuration { files: [ '**/*.{test,spec}.{js,ts,jsx,tsx}', @@ -56,4 +74,4 @@ export default [ ...vitest.configs.recommended.rules, }, }, -] +]) diff --git a/plugin-boilerplate/{{ cookiecutter.project_slug }}/plugins/{{ cookiecutter.project_module }}/web-frontend/package.json b/plugin-boilerplate/{{ cookiecutter.project_slug }}/plugins/{{ cookiecutter.project_module }}/web-frontend/package.json index 66bdc9ece2..fcd6d4fd70 100644 --- a/plugin-boilerplate/{{ cookiecutter.project_slug }}/plugins/{{ cookiecutter.project_module }}/web-frontend/package.json +++ b/plugin-boilerplate/{{ cookiecutter.project_slug }}/plugins/{{ cookiecutter.project_module }}/web-frontend/package.json @@ -10,7 +10,6 @@ "lint": "yarn eslint && yarn stylelint", "dev": "cd /baserow/web-frontend/ && nuxt --hostname 0.0.0.0 --config-file ./config/nuxt.config.dev.js", "build": "cd /baserow/web-frontend/ && nuxt build --config-file ./config/nuxt.config.dev.js", - "build-local": "cd /baserow/web-frontend/ && nuxt build --config-file ./config/nuxt.config.local.ts", "start": "cd /baserow/web-frontend/ && nuxt start --hostname 0.0.0.0 --config-file ./config/nuxt.config.local.ts" }, "dependencies": { diff --git a/premium/web-frontend/eslint.config.mjs b/premium/web-frontend/eslint.config.mjs deleted file mode 100644 index 685dc0377e..0000000000 --- a/premium/web-frontend/eslint.config.mjs +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -import withNuxt from '../../web-frontend/.nuxt/eslint.config.mjs' -import common from '../../web-frontend/eslint.config.common.mjs' - -export default withNuxt([ - ...common, - { rules: { 'vue/order-in-components': 'off' } }, -]) diff --git a/premium/web-frontend/modules/baserow_premium/components/views/grid/fields/GridViewFieldAI.vue b/premium/web-frontend/modules/baserow_premium/components/views/grid/fields/GridViewFieldAI.vue index a68b8866c6..d76c9afb51 100644 --- a/premium/web-frontend/modules/baserow_premium/components/views/grid/fields/GridViewFieldAI.vue +++ b/premium/web-frontend/modules/baserow_premium/components/views/grid/fields/GridViewFieldAI.vue @@ -76,6 +76,7 @@ import gridFieldAI from '@baserow_premium/mixins/gridFieldAI' export default { name: 'GridViewFieldAI', mixins: [gridField, gridFieldAI], + emits: ['update', 'selectBelow', 'add-row-after'], data() { return { editing: false, diff --git a/web-frontend/Dockerfile b/web-frontend/Dockerfile index 0997dc3d79..f65f11200a 100644 --- a/web-frontend/Dockerfile +++ b/web-frontend/Dockerfile @@ -87,8 +87,7 @@ WORKDIR /baserow/web-frontend # Build, then clean reinstall production only RUN --mount=type=cache,target=$YARN_CACHE_FOLDER,uid=$UID,gid=$GID,sharing=locked \ - yarn run build-local \ - && ls .output \ + yarn run build \ && find .output -type f -name "*.map" -delete @@ -107,6 +106,7 @@ ARG GID SHELL ["/bin/bash", "-o", "pipefail", "-c"] ENV DOCKER_USER=baserow_docker_user \ + APP_ENV=test \ BASEROW_IMAGE_TYPE="web-frontend" RUN groupadd --system --gid $GID ${DOCKER_USER} && \ @@ -116,10 +116,11 @@ COPY --from=tool-builder /usr/local/bin/su-exec /usr/local/bin/su-exec COPY --from=tool-builder /usr/bin/tini /usr/bin/tini COPY --from=busybox-helper /bin/wget /usr/local/bin/wget -RUN mkdir -p /baserow/web-frontend/.cache /baserow/reports /baserow/.cache /baserow/.yarn /baserow/web-frontend/reports/coverage && \ +RUN mkdir -p /baserow/reports /baserow/.cache /baserow/.yarn && \ chown -R $UID:$GID /baserow # Copy dependencies and source code +COPY --chown=$UID:$GID ./eslint.config.mjs /baserow/eslint.config.mjs COPY --chown=$UID:$GID web-frontend /baserow/web-frontend COPY --chown=$UID:$GID premium/web-frontend /baserow/premium/web-frontend COPY --chown=$UID:$GID enterprise/web-frontend /baserow/enterprise/web-frontend/ @@ -128,9 +129,11 @@ COPY --chown=$UID:$GID --from=builder-ci /baserow/web-frontend/node_modules /bas COPY --chown=$UID:$GID --from=builder-prod /baserow/web-frontend/.nuxt /baserow/web-frontend/.nuxt COPY --chown=$UID:$GID --from=builder-prod /baserow/web-frontend/.output /baserow/web-frontend/.output -# Create symlinks because premium and enterprise are node packages +# Create symlinks and cache directories (after COPY so they don't get overwritten) RUN ln -s /baserow/web-frontend/node_modules/ /baserow/premium/web-frontend/node_modules \ - && ln -s /baserow/web-frontend/node_modules/ /baserow/enterprise/web-frontend/node_modules + && ln -s /baserow/web-frontend/node_modules/ /baserow/enterprise/web-frontend/node_modules \ + && mkdir -p /baserow/web-frontend/.cache /baserow/web-frontend/reports/coverage \ + && chown -R $UID:$GID /baserow/web-frontend/.cache /baserow/web-frontend/reports COPY --chown=$UID:$GID tests /baserow/tests COPY --chown=$UID:$GID deploy/plugins/*.sh /baserow/plugins/ @@ -140,7 +143,8 @@ WORKDIR /baserow/web-frontend ENTRYPOINT ["/usr/bin/tini", "--", "/bin/bash", "/baserow/web-frontend/docker/docker-entrypoint.sh"] HEALTHCHECK --interval=60s CMD wget -q -O /dev/null http://localhost:3000/_health/ || exit 1 -CMD ["nuxt-local"] + +CMD ["nuxt-prod"] # ============================================================================= @@ -204,6 +208,7 @@ RUN echo "set -g default-command \"\${SHELL}\"" > /baserow/.tmux.conf && \ 'echo " j - See available commands"' \ > /baserow/.bashrc +COPY ./eslint.config.mjs /baserow/eslint.config.mjs COPY --chown=$UID:$GID web-frontend/docker/docker-entrypoint.sh /baserow/web-frontend/docker/docker-entrypoint.sh RUN dos2unix /baserow/web-frontend/docker/docker-entrypoint.sh \ @@ -254,10 +259,11 @@ USER $UID:$GID RUN mkdir -p /baserow/web-frontend WORKDIR /baserow/web-frontend +COPY --chown=$UID:$GID web-frontend/package.json /baserow/web-frontend/package.json +COPY --chown=$UID:$GID web-frontend/yarn.lock /baserow/web-frontend/yarn.lock + # Install dependencies first (cached unless package.json/yarn.lock change) RUN --mount=type=cache,target=$YARN_CACHE_FOLDER,uid=$UID,gid=$GID,sharing=locked \ - --mount=type=bind,source=web-frontend/package.json,target=/baserow/web-frontend/package.json \ - --mount=type=bind,source=web-frontend/yarn.lock,target=/baserow/web-frontend/yarn.lock \ yarn install --production --pure-lockfile --cache-folder $YARN_CACHE_FOLDER \ # Clean up unnecessary files to reduce image size && find node_modules -type f -name "*.map" -delete \ @@ -275,26 +281,20 @@ RUN --mount=type=cache,target=$YARN_CACHE_FOLDER,uid=$UID,gid=$GID,sharing=locke -o -name ".github" \ \) -prune -exec rm -rf {} + -COPY --chown=$UID:$GID web-frontend /baserow/web-frontend -COPY --chown=$UID:$GID premium/web-frontend /baserow/premium/web-frontend -COPY --chown=$UID:$GID enterprise/web-frontend /baserow/enterprise/web-frontend/ +COPY --chown=$UID:$GID ./web-frontend/env-remap.mjs /baserow/web-frontend/env-remap.mjs +COPY --chown=$UID:$GID ./web-frontend/docker/docker-entrypoint.sh /baserow/web-frontend/docker/docker-entrypoint.sh COPY --chown=$UID:$GID ./deploy/plugins/*.sh /baserow/plugins/ -# Create symlinks because premium and enterprise are node packages -RUN ln -s /baserow/web-frontend/node_modules/ /baserow/premium/web-frontend/node_modules \ - && ln -s /baserow/web-frontend/node_modules/ /baserow/enterprise/web-frontend/node_modules - HEALTHCHECK --interval=60s CMD wget -q -O /dev/null http://localhost:3000/_health/ || exit 1 ENTRYPOINT ["/usr/bin/tini", "--", "/bin/bash", "/baserow/web-frontend/docker/docker-entrypoint.sh"] FROM local-base AS local -COPY --chown=$UID:$GID --from=builder-prod /baserow/web-frontend/.nuxt /baserow/web-frontend/.nuxt COPY --chown=$UID:$GID --from=builder-prod /baserow/web-frontend/.output /baserow/web-frontend/.output -CMD ["nuxt-local"] +CMD ["nuxt-prod"] FROM local AS prod -CMD ["nuxt-local"] +CMD ["nuxt-prod"] diff --git a/web-frontend/Makefile b/web-frontend/Makefile index eb035b2bc9..87dc24b2ee 100644 --- a/web-frontend/Makefile +++ b/web-frontend/Makefile @@ -73,7 +73,7 @@ jest: test: jest ci-test-javascript: - $(YARNBIN) test-coverage || exit; + $(YARNBIN) test:coverage || exit; update-snapshots: $(YARNBIN) run jest --updateSnapshot || exit; diff --git a/web-frontend/config/nuxt.config.base.ts b/web-frontend/config/nuxt.config.base.ts index c7ffb48e97..245803093c 100644 --- a/web-frontend/config/nuxt.config.base.ts +++ b/web-frontend/config/nuxt.config.base.ts @@ -56,8 +56,7 @@ export default defineNuxtConfig({ '@baserow': '', }, css: [], - // TODO MIG don't load eslint on production even if it's needed for linting - modules: [...baserow.modules, '@nuxtjs/i18n', '@nuxt/eslint'], + modules: [...baserow.modules, '@nuxtjs/i18n'], i18n: { strategy: 'no_prefix', defaultLocale: 'en', diff --git a/web-frontend/config/nuxt.config.dev.ts b/web-frontend/config/nuxt.config.dev.ts index b2121a9fb8..04cd608c75 100644 --- a/web-frontend/config/nuxt.config.dev.ts +++ b/web-frontend/config/nuxt.config.dev.ts @@ -1,5 +1,8 @@ +import { defineNuxtConfig } from 'nuxt/config' +import baseConfig from './nuxt.config.base.ts' + export default defineNuxtConfig({ - extends: ['./config/nuxt.config.base.ts'], - modules: ['@nuxt/eslint'], + ...baseConfig, + modules: [...(baseConfig.modules || []), '@nuxt/eslint'], devtools: { enabled: true }, }) diff --git a/web-frontend/config/nuxt.config.local.ts b/web-frontend/config/nuxt.config.local.ts deleted file mode 100644 index b2121a9fb8..0000000000 --- a/web-frontend/config/nuxt.config.local.ts +++ /dev/null @@ -1,5 +0,0 @@ -export default defineNuxtConfig({ - extends: ['./config/nuxt.config.base.ts'], - modules: ['@nuxt/eslint'], - devtools: { enabled: true }, -}) diff --git a/web-frontend/config/nuxt.config.test.ts b/web-frontend/config/nuxt.config.test.ts index 138cc19408..27d6f22344 100644 --- a/web-frontend/config/nuxt.config.test.ts +++ b/web-frontend/config/nuxt.config.test.ts @@ -19,7 +19,7 @@ export default defineNuxtConfig( defu( { // Test-specific configuration - modules: ['@nuxt/test-utils/module'], + modules: ['@nuxt/test-utils/module', '@nuxt/eslint'], }, baseConfig ) diff --git a/web-frontend/docker/docker-entrypoint.sh b/web-frontend/docker/docker-entrypoint.sh index 1ebfac25b4..5cc7d49929 100755 --- a/web-frontend/docker/docker-entrypoint.sh +++ b/web-frontend/docker/docker-entrypoint.sh @@ -10,22 +10,21 @@ show_help() { The available Baserow web-frontend related commands and services are shown below: COMMANDS: +nuxt-prepare : Prepare nuxt (generate .nuxt directory) nuxt-dev : Start a normal nuxt development server nuxt-dev-with-storybook : Start nuxt dev + storybook in parallel -nuxt : Start a non-dev prod ready nuxt server -nuxt-local : Start a non-dev prod ready nuxt server using the preset local config -nuxt-prepare : Prepare nuxt (generate .nuxt directory) storybook-dev : Start a storybook dev server +nuxt-prod : Start a production nuxt server bash : Start a bash shell -build-local : Triggers a nuxt re-build of Baserow's web-frontend. +build : Triggers a nuxt re-build of Baserow's web-frontend. DEV COMMANDS: -lint : Run all the linting -lint-fix : Run eslint fix -stylelint : Run stylelint +lint : Run all linters (eslint, stylelint, prettier) +lint-fix : Run all linter fixes eslint : Run eslint -test : Run jest tests -ci-test : Run ci tests with reporting +stylelint : Run stylelint +test : Run vitest tests +ci-test : Run tests with coverage reporting install-plugin : Installs a plugin (append --help for more info). uninstall-plugin: Un-installs a plugin (append --help for more info). list-plugins : Lists currently installed plugins. @@ -87,15 +86,12 @@ case "$1" in setup_additional_modules exec yarn dev ;; - nuxt) - startup_plugin_setup - setup_additional_modules - exec ./node_modules/.bin/nuxt start --hostname "${BASEROW_WEBFRONTEND_BIND_ADDRESS:-0.0.0.0}" --port "$BASEROW_WEBFRONTEND_PORT" "${@:2}" - ;; - nuxt-local) + nuxt-prod) startup_plugin_setup setup_additional_modules - exec ./node_modules/.bin/nuxt start --hostname "${BASEROW_WEBFRONTEND_BIND_ADDRESS:-0.0.0.0}" --port "$BASEROW_WEBFRONTEND_PORT" --config-file ./config/nuxt.config.local.ts "${@:2}" + export NITRO_HOST="${BASEROW_WEBFRONTEND_BIND_ADDRESS:-0.0.0.0}" + export NITRO_PORT="$BASEROW_WEBFRONTEND_PORT" + exec yarn prod "${@:2}" ;; nuxt-prepare) setup_additional_modules @@ -112,7 +108,7 @@ case "$1" in exec yarn lint ;; lint-fix) - attachable_exec yarn eslint --fix + attachable_exec yarn fix ;; eslint) exec yarn eslint @@ -124,14 +120,14 @@ case "$1" in exec yarn test ;; ci-test) - exec yarn test-coverage + exec yarn test:coverage ;; bash) exec /bin/bash -c "${@:2}" ;; - build-local) + build) setup_additional_modules - exec yarn build-local + exec yarn build ;; install-plugin) exec /baserow/plugins/install_plugin.sh "${@:2}" diff --git a/web-frontend/env-remap.mjs b/web-frontend/env-remap.mjs new file mode 100644 index 0000000000..93be129547 --- /dev/null +++ b/web-frontend/env-remap.mjs @@ -0,0 +1,122 @@ +/** + * Environment variable remapping for Nuxt 3 runtime config. + * Remaps legacy env vars to NUXT_ prefixed vars for runtime config support. + * + * This allows existing environment variable names (e.g., PUBLIC_BACKEND_URL) + * to work with Nuxt 3's runtime config system, which expects NUXT_PUBLIC_* + * prefixed variables for runtime overrides. + * + * Import this file before starting Nuxt (dev or prod). + */ + +// Mapping: legacy env var -> NUXT runtime config env var +const envMapping = { + // Private config (server-only) + PRIVATE_BACKEND_URL: 'NUXT_PRIVATE_BACKEND_URL', + + // Public config (available on client via SSR) + PUBLIC_BACKEND_URL: 'NUXT_PUBLIC_PUBLIC_BACKEND_URL', + PUBLIC_WEB_FRONTEND_URL: 'NUXT_PUBLIC_PUBLIC_WEB_FRONTEND_URL', + DOWNLOAD_FILE_VIA_XHR: 'NUXT_PUBLIC_DOWNLOAD_FILE_VIA_XHR', + BASEROW_DISABLE_PUBLIC_URL_CHECK: + 'NUXT_PUBLIC_BASEROW_DISABLE_PUBLIC_URL_CHECK', + INITIAL_TABLE_DATA_LIMIT: 'NUXT_PUBLIC_INITIAL_TABLE_DATA_LIMIT', + HOURS_UNTIL_TRASH_PERMANENTLY_DELETED: + 'NUXT_PUBLIC_HOURS_UNTIL_TRASH_PERMANENTLY_DELETED', + DISABLE_ANONYMOUS_PUBLIC_VIEW_WS_CONNECTIONS: + 'NUXT_PUBLIC_DISABLE_ANONYMOUS_PUBLIC_VIEW_WS_CONNECTIONS', + BASEROW_MAX_IMPORT_FILE_SIZE_MB: + 'NUXT_PUBLIC_BASEROW_MAX_IMPORT_FILE_SIZE_MB', + FEATURE_FLAGS: 'NUXT_PUBLIC_FEATURE_FLAGS', + BASEROW_DISABLE_GOOGLE_DOCS_FILE_PREVIEW: + 'NUXT_PUBLIC_BASEROW_DISABLE_GOOGLE_DOCS_FILE_PREVIEW', + BASEROW_MAX_SNAPSHOTS_PER_GROUP: + 'NUXT_PUBLIC_BASEROW_MAX_SNAPSHOTS_PER_GROUP', + BASEROW_FRONTEND_SAME_SITE_COOKIE: + 'NUXT_PUBLIC_BASEROW_FRONTEND_SAME_SITE_COOKIE', + BASEROW_FRONTEND_JOBS_POLLING_TIMEOUT_MS: + 'NUXT_PUBLIC_BASEROW_FRONTEND_JOBS_POLLING_TIMEOUT_MS', + POSTHOG_PROJECT_API_KEY: 'NUXT_PUBLIC_POSTHOG_PROJECT_API_KEY', + POSTHOG_HOST: 'NUXT_PUBLIC_POSTHOG_HOST', + BASEROW_USE_PG_FULLTEXT_SEARCH: 'NUXT_PUBLIC_BASEROW_USE_PG_FULLTEXT_SEARCH', + BASEROW_INTEGRATION_LOCAL_BASEROW_PAGE_SIZE_LIMIT: + 'NUXT_PUBLIC_INTEGRATION_LOCAL_BASEROW_PAGE_SIZE_LIMIT', + BASEROW_ROW_PAGE_SIZE_LIMIT: 'NUXT_PUBLIC_BASEROW_ROW_PAGE_SIZE_LIMIT', + BASEROW_UNIQUE_ROW_VALUES_SIZE_LIMIT: + 'NUXT_PUBLIC_BASEROW_UNIQUE_ROW_VALUES_SIZE_LIMIT', + BASEROW_DISABLE_SUPPORT: 'NUXT_PUBLIC_BASEROW_DISABLE_SUPPORT', + BASEROW_INTEGRATIONS_PERIODIC_MINUTE_MIN: + 'NUXT_PUBLIC_BASEROW_INTEGRATIONS_PERIODIC_MINUTE_MIN', + + // Additional env vars + SENTRY_DSN: 'NUXT_PUBLIC_SENTRY_CONFIG_DSN', + SENTRY_ENVIRONMENT: 'NUXT_PUBLIC_SENTRY_CONFIG_ENVIRONMENT', + MEDIA_URL: 'NUXT_PUBLIC_MEDIA_URL', +} + +// Remap env vars: only if legacy var exists AND NUXT_ var is not already set +for (const [legacyKey, nuxtKey] of Object.entries(envMapping)) { + if ( + process.env[legacyKey] !== undefined && + process.env[nuxtKey] === undefined + ) { + process.env[nuxtKey] = process.env[legacyKey] + } +} + +// Handle BASEROW_PUBLIC_URL convenience variable (sets both backend and frontend URLs) +if (process.env.BASEROW_PUBLIC_URL) { + if (!process.env.NUXT_PUBLIC_PUBLIC_BACKEND_URL) { + process.env.NUXT_PUBLIC_PUBLIC_BACKEND_URL = process.env.BASEROW_PUBLIC_URL + } + if (!process.env.NUXT_PUBLIC_PUBLIC_WEB_FRONTEND_URL) { + process.env.NUXT_PUBLIC_PUBLIC_WEB_FRONTEND_URL = + process.env.BASEROW_PUBLIC_URL + } +} + +// Handle BASEROW_EMBEDDED_SHARE_URL fallback to PUBLIC_WEB_FRONTEND_URL +if (!process.env.NUXT_PUBLIC_BASEROW_EMBEDDED_SHARE_URL) { + if (process.env.BASEROW_EMBEDDED_SHARE_URL) { + process.env.NUXT_PUBLIC_BASEROW_EMBEDDED_SHARE_URL = + process.env.BASEROW_EMBEDDED_SHARE_URL + } else if (process.env.NUXT_PUBLIC_PUBLIC_WEB_FRONTEND_URL) { + // Use the already-remapped variable (PUBLIC_WEB_FRONTEND_URL -> NUXT_PUBLIC_PUBLIC_WEB_FRONTEND_URL) + process.env.NUXT_PUBLIC_BASEROW_EMBEDDED_SHARE_URL = + process.env.NUXT_PUBLIC_PUBLIC_WEB_FRONTEND_URL + } +} + +// Handle BASEROW_EXTRA_PUBLIC_URLS with hostname extraction transformation +if ( + process.env.BASEROW_EXTRA_PUBLIC_URLS && + !process.env.NUXT_PUBLIC_EXTRA_PUBLIC_WEB_FRONTEND_HOSTNAMES +) { + // Inline parseHostnamesFromUrls to avoid importing from source files + // (source files are not copied to production Docker images) + const hostnames = process.env.BASEROW_EXTRA_PUBLIC_URLS.split(',') + .map((url) => url.trim()) + .filter((url) => url !== '') + .map((url) => { + try { + return new URL(url).hostname + } catch (e) { + console.warn(`Invalid URL in BASEROW_EXTRA_PUBLIC_URLS: ${url}`) + return null + } + }) + .filter((hostname) => hostname !== null) + process.env.NUXT_PUBLIC_EXTRA_PUBLIC_WEB_FRONTEND_HOSTNAMES = + JSON.stringify(hostnames) +} + +// Handle BASEROW_BUILDER_DOMAINS with comma-split transformation +if ( + process.env.BASEROW_BUILDER_DOMAINS && + !process.env.NUXT_PUBLIC_BASEROW_BUILDER_DOMAINS +) { + const domains = process.env.BASEROW_BUILDER_DOMAINS.split(',') + .map((d) => d.trim()) + .filter((d) => d !== '') + process.env.NUXT_PUBLIC_BASEROW_BUILDER_DOMAINS = JSON.stringify(domains) +} diff --git a/web-frontend/eslint.config.mjs b/web-frontend/eslint.config.mjs deleted file mode 100644 index b579e16158..0000000000 --- a/web-frontend/eslint.config.mjs +++ /dev/null @@ -1,5 +0,0 @@ -// @ts-check -import withNuxt from './.nuxt/eslint.config.mjs' -import common from './eslint.config.common.mjs' - -export default withNuxt(...common) diff --git a/web-frontend/justfile b/web-frontend/justfile index b5c6a20926..f2d5e4c291 100644 --- a/web-frontend/justfile +++ b/web-frontend/justfile @@ -88,16 +88,6 @@ lint: fix: yarn run fix -# Check formatting with Prettier -[group('4 - code-quality')] -prettier-check: - yarn run prettier:check - -# Format all files with Prettier -[group('4 - code-quality')] -format: - yarn run format - # ============================================================================= # Testing # ============================================================================= @@ -110,7 +100,7 @@ test *ARGS: # Run tests with coverage (for CI) [group('3 - testing')] ci-test: - yarn test-coverage + yarn test:coverage # Update Jest snapshots [group('3 - testing')] @@ -137,7 +127,7 @@ storybook: # Build Nuxt for production [group('5 - build')] build-nuxt: - yarn run build-local + yarn run build # ============================================================================= # Cleanup diff --git a/web-frontend/modules/core/module.js b/web-frontend/modules/core/module.js index 621197e249..d6f3653b17 100644 --- a/web-frontend/modules/core/module.js +++ b/web-frontend/modules/core/module.js @@ -17,7 +17,6 @@ import _ from 'lodash' import defu from 'defu' import pathe from 'pathe' import page from '../builder/services/page' -import { parseHostnamesFromUrls } from './utils/url' import { readFileSync, writeFileSync, mkdirSync } from 'node:fs' import { createRequire } from 'node:module' @@ -91,122 +90,49 @@ export default defineNuxtModule({ // Alias nuxt.options.alias['@baserow'] = resolve('../../') - // Runtime config - const BASEROW_PUBLIC_URL = process.env.BASEROW_PUBLIC_URL - if (BASEROW_PUBLIC_URL) { - process.env.PUBLIC_BACKEND_URL = BASEROW_PUBLIC_URL - process.env.PUBLIC_WEB_FRONTEND_URL = BASEROW_PUBLIC_URL - } - // Add routes extendPages((pages) => { pages.push(...routes) }) - nuxt.options.runtimeConfig.privateBackendUrl = - process.env.PRIVATE_BACKEND_URL ?? 'http://backend:8000' + // Runtime config defaults - values can be overridden at runtime via NUXT_ prefixed env vars + // See env-remap.mjs for the env var remapping that enables backwards compatibility + nuxt.options.runtimeConfig.privateBackendUrl = 'http://backend:8000' nuxt.options.runtimeConfig.public = defu( nuxt.options.runtimeConfig.public, { - downloadFileViaXhr: process.env.DOWNLOAD_FILE_VIA_XHR ?? '0', - baserowDisablePublicUrlCheck: - process.env.BASEROW_DISABLE_PUBLIC_URL_CHECK ?? false, - publicBackendUrl: - process.env.PUBLIC_BACKEND_URL ?? 'http://localhost:8000', - publicWebFrontendUrl: - process.env.PUBLIC_WEB_FRONTEND_URL ?? 'http://localhost:3000', - initialTableDataLimit: process.env.INITIAL_TABLE_DATA_LIMIT ?? null, - hoursUntilTrashPermanentlyDeleted: - process.env.HOURS_UNTIL_TRASH_PERMANENTLY_DELETED ?? 24 * 3, - disableAnonymousPublicViewWsConnections: - process.env.DISABLE_ANONYMOUS_PUBLIC_VIEW_WS_CONNECTIONS ?? '', - baserowMaxImportFileSizeMb: - process.env.BASEROW_MAX_IMPORT_FILE_SIZE_MB ?? 512, - featureFlags: process.env.FEATURE_FLAGS ?? '', - baserowDisableGoogleDocsFilePreview: - process.env.BASEROW_DISABLE_GOOGLE_DOCS_FILE_PREVIEW ?? '', - baserowMaxSnapshotsPerGroup: - process.env.BASEROW_MAX_SNAPSHOTS_PER_GROUP ?? -1, - baserowFrontendSameSiteCookie: - process.env.BASEROW_FRONTEND_SAME_SITE_COOKIE ?? 'lax', - baserowFrontendJobsPollingTimeoutMs: - process.env.BASEROW_FRONTEND_JOBS_POLLING_TIMEOUT_MS ?? 2000, - posthogProjectApiKey: process.env.POSTHOG_PROJECT_API_KEY ?? '', - posthogHost: process.env.POSTHOG_HOST ?? '', - baserowEmbeddedShareUrl: - process.env.BASEROW_EMBEDDED_SHARE_URL ?? - process.env.PUBLIC_WEB_FRONTEND_URL ?? - 'http://localhost:3000', - baserowUsePgFulltextSearch: - process.env.BASEROW_USE_PG_FULLTEXT_SEARCH ?? 'true', - integrationLocalBaserowPageSizeLimit: parseInt( - process.env.BASEROW_INTEGRATION_LOCAL_BASEROW_PAGE_SIZE_LIMIT ?? 200 - ), - extraPublicWebFrontendHostnames: parseHostnamesFromUrls( - process.env.BASEROW_EXTRA_PUBLIC_URLS ?? '' - ), - baserowBuilderDomains: process.env.BASEROW_BUILDER_DOMAINS - ? process.env.BASEROW_BUILDER_DOMAINS.split(',') - : [], - - baserowRowPageSizeLimit: parseInt( - process.env.BASEROW_ROW_PAGE_SIZE_LIMIT ?? 200 - ), - baserowUniqueRowValuesSizeLimit: - process.env.BASEROW_UNIQUE_ROW_VALUES_SIZE_LIMIT ?? 100, - baserowDisableSupport: process.env.BASEROW_DISABLE_SUPPORT ?? '', - baserowIntegrationsPeriodicMinuteMin: - process.env.BASEROW_INTEGRATIONS_PERIODIC_MINUTE_MIN ?? '1', - - /*sentry: { + downloadFileViaXhr: '0', + baserowDisablePublicUrlCheck: false, + publicBackendUrl: 'http://localhost:8000', + publicWebFrontendUrl: 'http://localhost:3000', + initialTableDataLimit: null, + hoursUntilTrashPermanentlyDeleted: 24 * 3, + disableAnonymousPublicViewWsConnections: '', + baserowMaxImportFileSizeMb: 512, + featureFlags: '', + baserowDisableGoogleDocsFilePreview: '', + baserowMaxSnapshotsPerGroup: -1, + baserowFrontendSameSiteCookie: 'lax', + baserowFrontendJobsPollingTimeoutMs: 2000, + posthogProjectApiKey: '', + posthogHost: '', + baserowEmbeddedShareUrl: 'http://localhost:3000', + baserowUsePgFulltextSearch: 'true', + integrationLocalBaserowPageSizeLimit: 200, + extraPublicWebFrontendHostnames: [], + baserowBuilderDomains: [], + baserowRowPageSizeLimit: 200, + baserowUniqueRowValuesSizeLimit: 100, + baserowDisableSupport: '', + baserowIntegrationsPeriodicMinuteMin: '1', + mediaUrl: 'http://localhost:4000/media/', + sentry: { config: { - dsn: process.env.SENTRY_DSN || '', - environment: process.env.SENTRY_ENVIRONMENT || '', + dsn: '', + environment: '', }, }, - BASEROW_DISABLE_PUBLIC_URL_CHECK: - process.env.BASEROW_DISABLE_PUBLIC_URL_CHECK ?? false, - PUBLIC_BACKEND_URL: - process.env.PUBLIC_BACKEND_URL ?? 'http://localhost:8000', - PUBLIC_WEB_FRONTEND_URL: - process.env.PUBLIC_WEB_FRONTEND_URL ?? 'http://localhost:3000', - MEDIA_URL: process.env.MEDIA_URL ?? 'http://localhost:4000/media/', - INITIAL_TABLE_DATA_LIMIT: process.env.INITIAL_TABLE_DATA_LIMIT ?? null, - DOWNLOAD_FILE_VIA_XHR: process.env.DOWNLOAD_FILE_VIA_XHR ?? '0', - HOURS_UNTIL_TRASH_PERMANENTLY_DELETED: - process.env.HOURS_UNTIL_TRASH_PERMANENTLY_DELETED ?? 24 * 3, - DISABLE_ANONYMOUS_PUBLIC_VIEW_WS_CONNECTIONS: - process.env.DISABLE_ANONYMOUS_PUBLIC_VIEW_WS_CONNECTIONS ?? '', - BASEROW_MAX_IMPORT_FILE_SIZE_MB: - process.env.BASEROW_MAX_IMPORT_FILE_SIZE_MB ?? 512, - FEATURE_FLAGS: process.env.FEATURE_FLAGS ?? '', - BASEROW_DISABLE_GOOGLE_DOCS_FILE_PREVIEW: - process.env.BASEROW_DISABLE_GOOGLE_DOCS_FILE_PREVIEW ?? '', - BASEROW_MAX_SNAPSHOTS_PER_GROUP: - process.env.BASEROW_MAX_SNAPSHOTS_PER_GROUP ?? -1, - BASEROW_FRONTEND_JOBS_POLLING_TIMEOUT_MS: - process.env.BASEROW_FRONTEND_JOBS_POLLING_TIMEOUT_MS ?? 2000, - BASEROW_USE_PG_FULLTEXT_SEARCH: - process.env.BASEROW_USE_PG_FULLTEXT_SEARCH ?? 'true', - POSTHOG_PROJECT_API_KEY: process.env.POSTHOG_PROJECT_API_KEY ?? '', - POSTHOG_HOST: process.env.POSTHOG_HOST ?? '', - BASEROW_UNIQUE_ROW_VALUES_SIZE_LIMIT: - process.env.BASEROW_UNIQUE_ROW_VALUES_SIZE_LIMIT ?? 100, - BASEROW_ROW_PAGE_SIZE_LIMIT: parseInt( - process.env.BASEROW_ROW_PAGE_SIZE_LIMIT ?? 200 - ), - INTEGRATION_LOCAL_BASEROW_PAGE_SIZE_LIMIT: parseInt( - process.env.BASEROW_INTEGRATION_LOCAL_BASEROW_PAGE_SIZE_LIMIT ?? 200 - ), - BASEROW_BUILDER_DOMAINS: process.env.BASEROW_BUILDER_DOMAINS - ? process.env.BASEROW_BUILDER_DOMAINS.split(',') - : [], - BASEROW_FRONTEND_SAME_SITE_COOKIE: - process.env.BASEROW_FRONTEND_SAME_SITE_COOKIE ?? 'lax', - BASEROW_DISABLE_SUPPORT: process.env.BASEROW_DISABLE_SUPPORT ?? '', - BASEROW_INTEGRATIONS_PERIODIC_MINUTE_MIN: - process.env.BASEROW_INTEGRATIONS_PERIODIC_MINUTE_MIN ?? '1',*/ } ) diff --git a/web-frontend/modules/database/components/field/FieldSelectOptionsDropdown.vue b/web-frontend/modules/database/components/field/FieldSelectOptionsDropdown.vue index 42cee05fcd..7d89adb71e 100644 --- a/web-frontend/modules/database/components/field/FieldSelectOptionsDropdown.vue +++ b/web-frontend/modules/database/components/field/FieldSelectOptionsDropdown.vue @@ -145,7 +145,6 @@ export default { return this.allowCreateOption && this.query !== '' && !this.hasItems }, selectedColor() { - // eslint-disable-next-line @typescript-eslint/no-unused-expressions this.selectedColorRefreshKey // Adds a dependency to this variable I guess. Is this the best way??? return this.getSelectedProperty(this.value, 'color') diff --git a/web-frontend/modules/database/components/table/TableJSONImporter.vue b/web-frontend/modules/database/components/table/TableJSONImporter.vue index 922d30a8d4..d77b3bc7a4 100644 --- a/web-frontend/modules/database/components/table/TableJSONImporter.vue +++ b/web-frontend/modules/database/components/table/TableJSONImporter.vue @@ -101,7 +101,6 @@ export default { components: { CharsetDropdown }, mixins: [form, importer], emits: ['changed', 'data', 'getData'], - emits: ['changed', 'data', 'getData'], setup() { const config = useRuntimeConfig() return { v$: useVuelidate({ $lazy: true }), config } diff --git a/web-frontend/nuxt.config.ts b/web-frontend/nuxt.config.ts index 4e3b82efe2..4ce686bced 100644 --- a/web-frontend/nuxt.config.ts +++ b/web-frontend/nuxt.config.ts @@ -1,5 +1,8 @@ -const isTest = process.env.VITEST +const isTest = process.env.VITEST || process.env.APP_ENV === 'test' +const isDev = process.env.APP_ENV === 'dev' export default isTest ? (await import('./config/nuxt.config.test.ts')).default - : (await import('./config/nuxt.config.prod.ts')).default + : isDev + ? (await import('./config/nuxt.config.dev.ts')).default + : (await import('./config/nuxt.config.prod.ts')).default diff --git a/web-frontend/package.json b/web-frontend/package.json index d389b94df3..696e8762f2 100644 --- a/web-frontend/package.json +++ b/web-frontend/package.json @@ -4,35 +4,22 @@ "private": true, "type": "module", "scripts": { + "postinstall": "APP_ENV=dev nuxt prepare", + "dev": "APP_ENV=dev node --import ./env-remap.mjs ./node_modules/.bin/nuxt dev", "build": "APP_ENV=production nuxt build", - "build-local": "APP_ENV=production nuxt build --config-file ./config/nuxt.config.local.ts", - "dev": "APP_ENV=dev nuxt dev", "preview": "nuxt preview", + "prod": "node --import ./env-remap.mjs .output/server/index.mjs", "storybook": "storybook dev -p 6006 --host 0.0.0.0 --no-open", - "test": "yarn test:core", - "test:coverage": "yarn test:core:coverage", - "test-coverage": "yarn test:coverage", - "test:core": "TZ=UTC NODE_OPTIONS=\"--max-old-space-size=8192\" vitest $EXTRA_VITEST_PARAMS", - "test:core:coverage": "TZ=UTC NODE_OPTIONS=\"--max-old-space-size=8192\" vitest $EXTRA_VITEST_PARAMS --coverage", - "test:premium": "TZ=UTC NODE_OPTIONS=\"--max-old-space-size=8192\" vitest $EXTRA_VITEST_PARAMS --config ../premium/web-frontend/vitest.config.ts", - "test:premium:coverage": "TZ=UTC NODE_OPTIONS=\"--max-old-space-size=8192\" vitest $EXTRA_VITEST_PARAMS --config ../premium/web-frontend/vitest.config.ts --coverage", - "test:enterprise": "TZ=UTC NODE_OPTIONS=\"--max-old-space-size=8192\" vitest $EXTRA_VITEST_PARAMS --config ../enterprise/web-frontend/vitest.config.ts", - "test:enterprise:coverage": "TZ=UTC NODE_OPTIONS=\"--max-old-space-size=8192\" vitest $EXTRA_VITEST_PARAMS --config ../enterprise/web-frontend/vitest.config.ts --coverage", - "postinstall": "nuxt prepare", - "lint": "yarn eslint && yarn stylelint && yarn prettier:check", - "prettier:check": "prettier --check . ../premium/web-frontend ../enterprise/web-frontend", - "eslint": "yarn postinstall && yarn eslint:core && yarn eslint:premium && yarn eslint:enterprise", - "stylelint": "stylelint --cache --cache-location=.cache/stylelint **/*.scss ../premium/web-frontend/modules/**/*.scss ../enterprise/web-frontend/modules/**/*.scss", - "eslint:fix": "yarn eslint:core --fix && yarn eslint:premium --fix && yarn eslint:enterprise --fix", - "eslint:core": "eslint --cache --cache-location=.cache/eslint .", - "eslint:premium": "./rootNode.sh eslint --cache --cache-location=web-frontend/.cache/eslint --config premium/web-frontend/eslint.config.mjs premium/web-frontend", - "eslint:enterprise": "./rootNode.sh eslint --cache --cache-location=web-frontend/.cache/eslint --config enterprise/web-frontend/eslint.config.mjs enterprise/web-frontend", - "format": "yarn format:all", - "fix": "yarn format:all && yarn eslint:fix", - "format:core": "prettier . --write", - "format:premium": "prettier ../premium/web-frontend --write", - "format:enterprise": "prettier ../enterprise/web-frontend --write", - "format:all": "prettier . ../premium/web-frontend ../enterprise/web-frontend --write" + "test": "TZ=UTC NODE_OPTIONS=\"--max-old-space-size=8192\" vitest --run $EXTRA_VITEST_PARAMS && vitest --run $EXTRA_VITEST_PARAMS --config ../premium/web-frontend/vitest.config.ts && vitest --run $EXTRA_VITEST_PARAMS --config ../enterprise/web-frontend/vitest.config.ts", + "test:coverage": "EXTRA_VITEST_PARAMS=\"$EXTRA_VITEST_PARAMS --coverage\" yarn test", + "lint": "yarn eslint && yarn stylelint && yarn prettier", + "fix": "yarn eslint:fix && yarn stylelint:fix && yarn prettier:fix", + "eslint": "[ -f .nuxt/eslint.config.mjs ] || yarn postinstall && cd .. && web-frontend/node_modules/.bin/eslint --cache --cache-location=web-frontend/.cache/eslint web-frontend premium/web-frontend enterprise/web-frontend", + "eslint:fix": "cd .. && web-frontend/node_modules/.bin/eslint --cache --cache-location=web-frontend/.cache/eslint --fix web-frontend premium/web-frontend enterprise/web-frontend", + "stylelint": "stylelint --cache --cache-location=.cache/stylelint **/*.scss ../premium/web-frontend/modules/**/*.scss ../enterprise/web-frontend/modules/**/*.scss", + "stylelint:fix": "stylelint --cache --cache-location=.cache/stylelint --fix **/*.scss ../premium/web-frontend/modules/**/*.scss ../enterprise/web-frontend/modules/**/*.scss", + "prettier": "prettier --check --log-level=warn --cache --cache-location=.cache/prettier . ../premium/web-frontend ../enterprise/web-frontend", + "prettier:fix": "prettier --write --log-level=warn --cache --cache-location=.cache/prettier . ../premium/web-frontend ../enterprise/web-frontend" }, "resolutions": { "sass": "~1.70.0", diff --git a/web-frontend/rootNode.sh b/web-frontend/rootNode.sh deleted file mode 100755 index 92beeccd23..0000000000 --- a/web-frontend/rootNode.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env sh - -# Execute the node command like if we were a level up. -# needed for some commands like eslint that don't -# want to go out of current root directory - -set -e - -# Resolve the directory of this script (portable) -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" - -# Repo root is two levels up from web-frontend/ -REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" - -cd "$REPO_ROOT" - -# Forward all arguments -exec "$@"