2024-03-16 08:40:24 +00:00
export interface User {
id : string ;
email : string ;
hashed_password : string ;
subscription : {
external : Record < never , never > ;
expires_at : string ;
updated_at : string ;
} ;
status : 'trial' | 'active' | 'inactive' ;
extra : {
is_email_verified : boolean ;
is_admin? : boolean ;
dav_hashed_password? : string ;
2025-02-26 17:43:53 +00:00
expenses_currency? : SupportedCurrencySymbol ;
2025-05-29 16:30:28 +00:00
multi_factor_auth_methods? : MultiFactorAuthMethod [ ] ;
Basic CalDav UI (Calendar)
This implements a basic CalDav UI, titled "Calendar". It allows creating new calendars and events with a start and end date, URL, location, and description.
You can also import and export ICS (VCALENDAR + VEVENT) files.
It allows editing the ICS directly, for power users.
Additionally, you can hide/display events from certain calendars, change their names and their colors. If there's no calendar created yet in your CalDav server (first-time setup), it'll automatically create one, titled "Calendar".
You can also change the display timezone for the calendar from the settings.
Finally, there's some minor documentation fixes and some other minor tweaks.
Closes #56
Closes #89
2025-09-06 11:46:13 +00:00
hidden_calendar_ids? : string [ ] ;
timezone ? : {
id : string ;
utcOffset : number ;
} ;
2024-03-16 08:40:24 +00:00
} ;
created_at : Date ;
}
export interface UserSession {
id : string ;
user_id : string ;
expires_at : Date ;
last_seen_at : Date ;
created_at : Date ;
}
export interface VerificationCode {
id : string ;
user_id : string ;
code : string ;
verification : {
type : 'email' ;
id : string ;
} ;
expires_at : Date ;
created_at : Date ;
}
export interface DashboardLink {
url : string ;
name : string ;
}
export interface Dashboard {
id : string ;
user_id : string ;
data : {
links : DashboardLink [ ] ;
notes : string ;
} ;
created_at : Date ;
}
export type NewsFeedType = 'rss' | 'atom' | 'json' ;
export type NewsFeedCrawlType = 'direct' | 'googlebot' | 'proxy' ;
export interface NewsFeed {
id : string ;
user_id : string ;
feed_url : string ;
last_crawled_at : Date | null ;
extra : {
title? : string ;
feed_type? : NewsFeedType ;
crawl_type? : NewsFeedCrawlType ;
} ;
created_at : Date ;
}
export interface NewsFeedArticle {
id : string ;
user_id : string ;
feed_id : string ;
article_url : string ;
article_title : string ;
article_summary : string ;
article_date : Date ;
is_read : boolean ;
2025-02-26 17:43:53 +00:00
extra : Record < never , never > ; // NOTE: Here for potential future fields
2024-03-16 08:40:24 +00:00
created_at : Date ;
}
2024-04-03 13:02:04 +00:00
export interface Directory {
2024-04-04 16:55:47 +00:00
user_id : string ;
2024-04-03 13:02:04 +00:00
parent_path : string ;
directory_name : string ;
has_write_access : boolean ;
size_in_bytes : number ;
2025-06-20 11:04:16 +00:00
file_share_id : string | null ;
2024-03-17 11:43:58 +00:00
updated_at : Date ;
created_at : Date ;
}
2024-03-17 17:00:05 +00:00
2024-04-03 13:02:04 +00:00
export interface DirectoryFile {
2024-04-04 16:55:47 +00:00
user_id : string ;
2024-04-03 13:02:04 +00:00
parent_path : string ;
file_name : string ;
has_write_access : boolean ;
size_in_bytes : number ;
2025-06-20 11:04:16 +00:00
file_share_id : string | null ;
2024-04-03 13:02:04 +00:00
updated_at : Date ;
created_at : Date ;
2024-03-18 19:18:29 +00:00
}
2025-02-26 17:43:53 +00:00
export interface Budget {
id : string ;
user_id : string ;
name : string ;
month : string ;
value : number ;
extra : {
usedValue : number ;
availableValue : number ;
} ;
created_at : Date ;
}
export interface Expense {
id : string ;
user_id : string ;
cost : number ;
description : string ;
budget : string ;
date : string ;
is_recurring : boolean ;
extra : Record < never , never > ; // NOTE: Here for potential future fields
created_at : Date ;
}
export type SupportedCurrencySymbol = '$' | '€' | '£' | '¥' | '₹' ;
Remove fresh
This implements a huge change, where Fresh is removed as a framework and serving files, allowing more control over importing, bundling, and serving files and components.
The biggest challenge was to continue making sure that there weren't too many places to look into for import versions, and `PasswordlessPasskeyLogin.tsx` became a prototype in migrating a component to fully SSR, no need for frontend parsing (via Babel) or bundling (via a custom-script, downloading frontend dependencies from esm.sh). Still, there are too many components to migrate like that, and it's all working, so I likely won't even attempt it unless there's some bug, new feature, or security vulnerability to address that warrants a rewrite of those.
This also updates all dependencies (except `@libs/xml` because that still causes some breaking in DAV endpoints), including Deno!
All other advantages can be seen in the related issues, and the breaking change this (v4.0.0) introduces is related simply to `config.email.tlsMode` (which had a deprecation warning throughout v3), and because, while I tested many things exhaustively, it's not impossible something broke that I didn't see.
Closes #141
Closes #132
2026-02-20 10:54:31 +00:00
export type SupportedCurrency = 'USD' | 'EUR' | 'GBP' | 'JPY' | 'INR' ;
2025-05-25 14:48:53 +00:00
export type PartialDeep < T > = ( T extends ( infer U ) [ ] ? PartialDeep < U > [ ] : { [ P in keyof T ] ? : PartialDeep < T [ P ] > } ) | T ;
2025-12-01 12:25:21 +00:00
export type OptionalApp = 'dashboard' | 'files' | 'news' | 'notes' | 'photos' | 'expenses' | 'contacts' | 'calendar' ;
2025-05-25 14:48:53 +00:00
export interface Config {
auth : {
2025-09-27 18:39:09 +00:00
/** The base URL of the application you use to access the app, i.e. "http://localhost:8000" or "https://cloud.example.com" (note authentication won't work without https:// except for localhost; SSO redirect, if enabled, will be this + /oidc/callback, so "https://cloud.example.com/oidc/callback") */
2025-05-25 14:48:53 +00:00
baseUrl : string ;
/** If true, anyone can sign up for an account. Note that it's always possible to sign up for the first user, and they will be an admin */
allowSignups : boolean ;
Migrate email provider (from Brevo to generic SMTP) (#67)
This means we now need to have the text and HTML content set in the code, which is arguably better.
In order to avoid allowing legacy Brevo API Key support, this will also introduce breaking changes and will be released as v2.0.0.
I took the opportunity to remove a few deprecated things (like legacy ENV-based config), upgrade PostgreSQL, and pin a specific version in `docker-compose.yml`, since I don't plan to do breaking releases anytime soon, and upgrading PostgreSQL should be fine from now on if the version is pinned.
If you were using Brevo with an API Key, they support SMTP as well, just update your config.
If you were using ENV-based config, check `bewcloud.config.sample.ts`to create your `bewcloud.config.ts`.
If you need help upgrading you PostgreSQL container, I've written a simple guide [step-by-step guide](https://news.onbrn.com/step-by-step-guide-upgrading-postgresql-docker-containers/).
2025-06-10 09:28:13 +00:00
/** If true, email verification will be required for signups (using SMTP settings below) */
2025-05-25 14:48:53 +00:00
enableEmailVerification : boolean ;
/** If true, all signups become active for 100 years */
enableForeverSignup : boolean ;
2025-06-11 14:53:39 +00:00
/** If true, users can enable multi-factor authentication (TOTP, Passkeys, or Email if the SMTP settings below are set) */
2025-05-29 16:30:28 +00:00
enableMultiFactor : boolean ;
2025-05-25 14:48:53 +00:00
/** Can be set to allow more than the baseUrl's domain for session cookies */
allowedCookieDomains : string [ ] ;
/** If true, the cookie domain will not be strictly set and checked against. This skipping slightly reduces security, but is usually necessary for reverse proxies like Cloudflare Tunnel. */
skipCookieDomainSecurity : boolean ;
2025-06-05 17:10:40 +00:00
/** If true, single sign-on will be enabled */
enableSingleSignOn : boolean ;
2026-02-25 16:06:20 +00:00
/** If true, single sign-on signups will be enabled overriding allowSignups */
enableSingleSignOnSignUp : boolean ;
2025-06-05 17:10:40 +00:00
/** The Discovery URL (AKA Issuer) of the identity/single sign-on provider */
singleSignOnUrl : string ;
/** The attribute to prefer as email of the identity/single sign-on provider */
singleSignOnEmailAttribute : string ;
/** The scopes to request from the identity/single sign-on provider */
singleSignOnScopes : string [ ] ;
2025-05-25 14:48:53 +00:00
} ;
files : {
/** The root-relative root path for files, i.e. "data-files" */
rootPath : string ;
2025-06-20 11:04:16 +00:00
/** If true, public file sharing will be allowed (still requires a user to enable sharing for a given file or directory) */
allowPublicSharing : boolean ;
2025-10-08 13:32:45 +00:00
/** If true, directories can be downloaded as zip files */
allowDirectoryDownloads : boolean ;
2025-05-25 14:48:53 +00:00
} ;
core : {
2025-12-01 12:25:21 +00:00
/** The apps to show, in order of appearance in the header. The first app will be the default one shown after logging in. At least one is required. */
2025-05-25 14:48:53 +00:00
enabledApps : OptionalApp [ ] ;
} ;
visuals : {
/** An override title of the application. Empty shows the default title. */
title : string ;
/** An override description of the application. Empty shows the default description. */
description : string ;
/** The email address to contact for help. Empty will disable/hide the "need help" sections. */
helpEmail : string ;
} ;
Migrate email provider (from Brevo to generic SMTP) (#67)
This means we now need to have the text and HTML content set in the code, which is arguably better.
In order to avoid allowing legacy Brevo API Key support, this will also introduce breaking changes and will be released as v2.0.0.
I took the opportunity to remove a few deprecated things (like legacy ENV-based config), upgrade PostgreSQL, and pin a specific version in `docker-compose.yml`, since I don't plan to do breaking releases anytime soon, and upgrading PostgreSQL should be fine from now on if the version is pinned.
If you were using Brevo with an API Key, they support SMTP as well, just update your config.
If you were using ENV-based config, check `bewcloud.config.sample.ts`to create your `bewcloud.config.ts`.
If you need help upgrading you PostgreSQL container, I've written a simple guide [step-by-step guide](https://news.onbrn.com/step-by-step-guide-upgrading-postgresql-docker-containers/).
2025-06-10 09:28:13 +00:00
email : {
/** The email address to send emails from */
from : string ;
/** The SMTP host to send emails from */
host : string ;
/** The SMTP port to send emails from */
port : number ;
Remove fresh
This implements a huge change, where Fresh is removed as a framework and serving files, allowing more control over importing, bundling, and serving files and components.
The biggest challenge was to continue making sure that there weren't too many places to look into for import versions, and `PasswordlessPasskeyLogin.tsx` became a prototype in migrating a component to fully SSR, no need for frontend parsing (via Babel) or bundling (via a custom-script, downloading frontend dependencies from esm.sh). Still, there are too many components to migrate like that, and it's all working, so I likely won't even attempt it unless there's some bug, new feature, or security vulnerability to address that warrants a rewrite of those.
This also updates all dependencies (except `@libs/xml` because that still causes some breaking in DAV endpoints), including Deno!
All other advantages can be seen in the related issues, and the breaking change this (v4.0.0) introduces is related simply to `config.email.tlsMode` (which had a deprecation warning throughout v3), and because, while I tested many things exhaustively, it's not impossible something broke that I didn't see.
Closes #141
Closes #132
2026-02-20 10:54:31 +00:00
/** "auto" means "immediate" on port 465, "starttls" otherwise. */
tlsMode : 'auto' | 'immediate' | 'starttls' | 'none' ;
2025-12-20 11:50:15 +00:00
/** Whether to verify the TLS certificate. If a string is used the hostname will be verified using that name. */
tlsVerify : boolean | string ;
Migrate email provider (from Brevo to generic SMTP) (#67)
This means we now need to have the text and HTML content set in the code, which is arguably better.
In order to avoid allowing legacy Brevo API Key support, this will also introduce breaking changes and will be released as v2.0.0.
I took the opportunity to remove a few deprecated things (like legacy ENV-based config), upgrade PostgreSQL, and pin a specific version in `docker-compose.yml`, since I don't plan to do breaking releases anytime soon, and upgrading PostgreSQL should be fine from now on if the version is pinned.
If you were using Brevo with an API Key, they support SMTP as well, just update your config.
If you were using ENV-based config, check `bewcloud.config.sample.ts`to create your `bewcloud.config.ts`.
If you need help upgrading you PostgreSQL container, I've written a simple guide [step-by-step guide](https://news.onbrn.com/step-by-step-guide-upgrading-postgresql-docker-containers/).
2025-06-10 09:28:13 +00:00
} ;
2025-07-20 09:35:32 +00:00
contacts : {
/** If true, the CardDAV server will be enabled (proxied) */
enableCardDavServer : boolean ;
/** The CardDAV server URL to proxy to */
cardDavUrl : string ;
} ;
calendar : {
/** If true, the CalDAV server will be enabled (proxied) */
enableCalDavServer : boolean ;
/** The CalDAV server URL to proxy to */
calDavUrl : string ;
} ;
2025-05-25 14:48:53 +00:00
}
2025-05-29 16:30:28 +00:00
2025-06-11 14:53:39 +00:00
export type MultiFactorAuthMethodType = 'totp' | 'passkey' | 'email' ;
2025-05-29 16:30:28 +00:00
export interface MultiFactorAuthMethod {
type : MultiFactorAuthMethodType ;
id : string ;
name : string ;
enabled : boolean ;
created_at : Date ;
metadata : {
totp ? : {
hashed_secret : string ;
hashed_backup_codes : string [ ] ;
} ;
passkey ? : {
credential_id : string ;
public_key : string ;
counter? : number ;
device_type? : string ;
backed_up? : boolean ;
transports? : AuthenticatorTransport [ ] ;
} ;
} ;
}
2025-06-20 11:04:16 +00:00
export interface FileShare {
id : string ;
user_id : string ;
file_path : string ;
extra : {
hashed_password? : string ;
} ;
created_at : Date ;
}