diff --git a/.dockerignore b/.dockerignore index 1454c63..91ecaf4 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,14 +1,11 @@ -.do .github .git .gitignore docker-compose* Dockerfile -render.yaml LICENSE README.md .env.sample node_modules -_fresh data-files bewcloud.config.sample.ts diff --git a/.dvmrc b/.dvmrc index da6b0a8..a04abec 100644 --- a/.dvmrc +++ b/.dvmrc @@ -1 +1 @@ -2.5.6 +2.6.10 diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 539b66b..84ab1b5 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,7 +1,7 @@ github: [bewcloud, BrunoBernardino] custom: [ - 'https://donate.stripe.com/bIYeWBbw00Ape5iaFi', + 'https://payment-links.mollie.com/payment/wUS9dvewvjEPvseZVHEi5', 'https://paypal.me/brunobernardino', 'https://gist.github.com/BrunoBernardino/ff5b54c13dd96ac7f9fee6fbfd825b09', ] diff --git a/.gitignore b/.gitignore index 1b9cac0..c33d7a7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,3 @@ -# Fresh build directory -_fresh/ - # npm dependencies node_modules/ diff --git a/Dockerfile b/Dockerfile index 9498af7..af1a0e6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM denoland/deno:ubuntu-2.5.6 +FROM denoland/deno:ubuntu-2.6.10 EXPOSE 8000 @@ -6,17 +6,19 @@ RUN apt-get update && apt-get install -y make zip coreutils WORKDIR /app -# These steps will be re-run upon each file change in your working directory: ADD . /app -# Build fresh -RUN deno task build +# Prepare for any npm modules required "on the fly" +RUN mkdir -p /app/node_modules/.deno -RUN chown -R deno:deno /app /deno-dir +RUN chown -R deno:deno /app # Prefer not to run as root. USER deno +# Build frontend components and CSS +RUN deno task build + # Compile the main app so that it doesn't need to be compiled each startup/entry. RUN deno cache --reload main.ts diff --git a/FAQ.md b/FAQ.md index f06d204..d5dec5e 100644 --- a/FAQ.md +++ b/FAQ.md @@ -215,3 +215,7 @@ BEWCLOUD_CALENDAR_CALDAV_URL=http://127.0.0.1:5232 ``` + +## Wasn't this made with Fresh? + +Up until [v4.0.0](https://github.com/bewcloud/bewcloud/releases/tag/v4.0.0), bewCloud was made with [Fresh](https://fresh.deno.dev/), but as per [#141](https://github.com/bewcloud/bewcloud/issues/141) it has since been rewritten in standard Deno to use a more web-standards-based backend, easier to maintain and extend, without requiring breaking updates. diff --git a/Makefile b/Makefile index 665a55b..888d5c3 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,21 @@ test: .PHONY: build build: - deno task build + make download-frontend-imports + make build-babel + make build-tailwind + +.PHONY: download-frontend-imports +download-frontend-imports: + deno task download-frontend-imports + +.PHONY: build-babel +build-babel: + deno run --allow-env --allow-ffi --allow-sys --allow-read --allow-write=public/components npm:@babel/cli@7.28.6/babel ./components --out-dir ./public/components --extensions ".ts,.tsx" + +.PHONY: watch-babel +watch-babel: + deno run --allow-env --allow-ffi --allow-sys --allow-read --allow-write=public/components npm:@babel/cli@7.28.6/babel ./components --out-dir ./public/components --extensions ".ts,.tsx" --watch .PHONY: migrate-db migrate-db: @@ -25,6 +39,16 @@ migrate-db: exec-db: docker exec -it -u postgres $(shell basename $(CURDIR))-postgresql-1 psql +.PHONY: build-tailwind +build-tailwind: + deno install --allow-scripts npm:tailwindcss@4.2.0 npm:@tailwindcss/cli@4.2.0 + deno run --allow-env --allow-read --allow-sys --allow-ffi --vendor --unstable-detect-cjs --allow-write=public/css,/var/folders --allow-scripts npm:@tailwindcss/cli@4.2.0 -i ./public/css/tailwind-input.css -o ./public/css/tailwind.css + +.PHONY: watch-tailwind +watch-tailwind: + deno install --allow-scripts npm:tailwindcss@4.2.0 npm:@tailwindcss/cli@4.2.0 + deno run --allow-env --allow-read --allow-sys --allow-ffi --vendor --unstable-detect-cjs --allow-write=public/css,/var/folders --allow-scripts npm:@tailwindcss/cli@4.2.0 -w -i ./public/css/tailwind-input.css -o ./public/css/tailwind.css + .PHONY: preview preview: deno task preview diff --git a/README.md b/README.md index 13c6c85..cc4dcc7 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![](https://github.com/bewcloud/bewcloud/workflows/Run%20Tests/badge.svg)](https://github.com/bewcloud/bewcloud/actions?workflow=Run+Tests) -This is the [bewCloud app](https://bewcloud.com) built using [Fresh](https://fresh.deno.dev) and deployed using [docker compose](https://docs.docker.com/compose/). +This is the [bewCloud app](https://bewcloud.com) built with [Deno](https://deno.land/) and deployed using [docker compose](https://docs.docker.com/compose/). If you're looking for the desktop sync app, it's at [`bewcloud-desktop`](https://github.com/bewcloud/bewcloud-desktop). @@ -10,9 +10,7 @@ If you're looking for the mobile app, it's at [`bewcloud-mobile`](https://github ## Self-host it! -[![Buy managed cloud (1 year)](https://img.shields.io/badge/Buy%20managed%20cloud%20(1%20year)-51a4fb?style=for-the-badge)](https://buy.stripe.com/eVa01HgQk0Ap0eseVz) - -[![Buy managed cloud (1 month)](https://img.shields.io/badge/Buy%20managed%20cloud%20(1%20month)-51a4fb?style=for-the-badge)](https://buy.stripe.com/fZu8wOb5RfIydj56FA1gs0J) +[![Buy managed cloud (1 year)](https://img.shields.io/badge/Buy%20managed%20cloud%20(1%20year)-51a4fb?style=for-the-badge)](https://payment-links.mollie.com/payment/zeLCmenLMLQwTcvqPJMyb) Or, to run on your own machine, start with these commands: @@ -48,7 +46,7 @@ See the [Community Links](#community-links) section for alternative ways of runn ## Sponsors -These are the amazing entities or individuals who are sponsoring this project for this current month. If you'd like to show up here, [check the GitHub Sponsors page](https://github.com/sponsors/bewcloud) or [make a donation](https://donate.stripe.com/bIYeWBbw00Ape5iaFi) above $50 ($100 to show up on the website)! +These are the amazing entities or individuals who are sponsoring this project for this current month. If you'd like to show up here, [check the GitHub Sponsors page](https://github.com/sponsors/bewcloud) or [make a donation](https://payment-links.mollie.com/payment/wUS9dvewvjEPvseZVHEi5) above $50 ($100 to show up on the website)!

@@ -72,9 +70,10 @@ These are the amazing entities or individuals who are sponsoring this project fo ```sh docker compose -f docker-compose.dev.yml up # (optional) runs docker with postgres, locally make migrate-db # runs any missing database migrations -make start # runs the app in development mode (watches for file changes and recompiles the app) +make start # runs the app in development mode (watches for CSS file changes and recompiles the CSS) make format # (optional) formats the code (if you're interested in contributing) make test # (optional) runs tests (if you're interested in contributing) +make build # (optional) generates CSS for production, if you've made changes ``` ### Other less-used commands (mostly for development) @@ -82,15 +81,14 @@ make test # (optional) runs tests (if you're interested in contributing) ```sh make preview # runs the app in production mode (serves the app from the built files) make exec-db # runs psql inside the postgres container, useful for running direct development queries like `DROP DATABASE "bewcloud"; CREATE DATABASE "bewcloud";` -make build # generates all static files for production deploy ``` ## File/Directory Structure -- Routes are defined at `routes/`. -- Static files are defined at `static/`. -- Frontend-only components are defined at `components/`. -- Isomorphic components are defined at `islands/`. +- Backend routes are defined at `routes.ts` +- Publicly-available files are defined at `public/` +- Pages are defined at `pages/`. +- JSX/TSX components are defined at `components/`. - Cron jobs are defined at `crons/`. - Reusable bits of code are defined at `lib/`. - Database migrations are defined at `db-migrations/`. diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 0000000..64923b9 --- /dev/null +++ b/babel.config.js @@ -0,0 +1,56 @@ +// Converts local TSX imports to JS imports, used in the components +const rewriteLocalTsxImports = () => { + const isLocal = (value) => typeof value === 'string' && (value.startsWith('./') || value.startsWith('../')); + const isComponent = (value) => typeof value === 'string' && value.startsWith('/components/'); + + const rewrite = (source) => { + if (source && isLocal(source.value) && source.value.endsWith('.tsx')) { + source.value = source.value.replace('.tsx', '.js'); + } + + if (source && isComponent(source.value) && source.value.endsWith('.tsx')) { + source.value = source.value.replace('/components/', '/public/components/').replace('.tsx', '.js'); + } + }; + + return { + visitor: { + ImportDeclaration(path) { + rewrite(path.node.source); + }, + ExportAllDeclaration(path) { + rewrite(path.node.source); + }, + ExportNamedDeclaration(path) { + if (path.node.source) rewrite(path.node.source); + }, + }, + }; +}; + +const presets = [ + ['@babel/preset-react'], + ['@babel/preset-typescript', { jsxPragma: 'h' }], +]; + +const plugins = [ + rewriteLocalTsxImports, + [ + '@babel/plugin-transform-react-jsx', + { + 'pragma': 'h', + 'pragmaFrag': 'Fragment', + 'jsxImportSource': 'preact', + }, + ], +]; + +export default { + sourceType: 'module', + targets: '> 0.5%, not dead', + presets, + plugins, + comments: false, + compact: false, + minified: false, +}; diff --git a/bewcloud.config.sample.ts b/bewcloud.config.sample.ts index 9d6a05c..b2b86c8 100644 --- a/bewcloud.config.sample.ts +++ b/bewcloud.config.sample.ts @@ -32,8 +32,8 @@ const config: PartialDeep = { // from: 'help@bewcloud.com', // host: 'localhost', // port: 465, - // tlsMode: "auto", // “auto” means “immediate” on port 465, “starttls” otherwise; `null` is legacy behaviour that will be removed in v4: on port 465 it also means “immediate”, otherwise it will use opportunistic StartTLS falling back to plain transmission - // tlsVerify: true, // Whether to verify the TLS certificate. If a string is used the hostname will be verified using that name. + // tlsMode: 'auto', // "auto" means "immediate" on port 465, "starttls" otherwise. + // tlsVerify: true, // Whether to verify the TLS certificate. If a string is used the hostname will be verified using that name. // }, // contacts: { // enableCardDavServer: true, diff --git a/components/Header.tsx b/components/Header.tsx index 1e52f2a..69db8bb 100644 --- a/components/Header.tsx +++ b/components/Header.tsx @@ -1,11 +1,9 @@ -import { Head } from 'fresh/runtime.ts'; - import { OptionalApp, User } from '/lib/types.ts'; -import { capitalizeWord } from '/lib/utils/misc.ts'; +import { capitalizeWord } from '/public/ts/utils/misc.ts'; interface Data { route: string; - user?: User; + user?: User | null; enabledApps: OptionalApp[]; } @@ -58,16 +56,17 @@ export default function Header({ route, user, enabledApps }: Data) { return ( <> - - {pageLabel} - bewCloud -