sovrium 0.0.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +67 -185
- package/package.json +26 -17
- package/src/application/use-cases/server/static-content-generators.ts +18 -2
- package/src/domain/models/api/activity.ts +87 -0
- package/src/domain/models/api/comments.ts +131 -0
- package/src/domain/models/api/index.ts +9 -0
- package/src/domain/models/api/params.ts +83 -0
- package/src/infrastructure/server/route-setup/openapi-routes/activity-routes.ts +72 -0
- package/src/infrastructure/server/route-setup/openapi-routes/analytics-routes.ts +176 -0
- package/src/infrastructure/server/route-setup/openapi-routes/batch-routes.ts +215 -0
- package/src/infrastructure/server/route-setup/openapi-routes/health-routes.ts +38 -0
- package/src/infrastructure/server/route-setup/openapi-routes/record-routes.ts +444 -0
- package/src/infrastructure/server/route-setup/openapi-routes/table-routes.ts +100 -0
- package/src/infrastructure/server/route-setup/openapi-routes/view-routes.ts +104 -0
- package/src/infrastructure/server/route-setup/openapi-schema.ts +40 -40
- package/src/presentation/styling/parse-style.ts +17 -9
- package/CHANGELOG.md +0 -3497
- package/schemas/0.0.1/app.openapi.json +0 -70
- package/schemas/0.0.1/app.schema.json +0 -7961
- package/schemas/0.0.2/app.openapi.json +0 -80
- package/schemas/0.0.2/app.schema.json +0 -8829
- package/schemas/development/app.openapi.json +0 -70
- package/schemas/development/app.schema.json +0 -7456
package/README.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<h1 align="center">Sovrium</h1>
|
|
3
|
+
</p>
|
|
4
|
+
|
|
1
5
|
<h3 align="center">Build business apps with config. Own your data forever.</h3>
|
|
2
6
|
|
|
3
7
|
<p align="center">
|
|
@@ -7,27 +11,29 @@
|
|
|
7
11
|
|
|
8
12
|
<p align="center">
|
|
9
13
|
<a href="https://github.com/sovrium/sovrium/blob/main/LICENSE.md"><img src="https://img.shields.io/badge/license-BSL--1.1-blue" alt="License" /></a>
|
|
10
|
-
<a href="SPEC-PROGRESS.md"><img src="https://img.shields.io/badge/specs-99%25_passing-brightgreen" alt="Specs" /></a>
|
|
11
14
|
<a href="https://bun.sh"><img src="https://img.shields.io/badge/runtime-Bun_1.3-f472b6" alt="Bun" /></a>
|
|
12
15
|
<a href="https://www.typescriptlang.org"><img src="https://img.shields.io/badge/TypeScript-5.9-3178c6" alt="TypeScript" /></a>
|
|
16
|
+
<a href="https://www.npmjs.com/package/sovrium"><img src="https://img.shields.io/npm/v/sovrium" alt="npm" /></a>
|
|
17
|
+
<a href="https://www.npmjs.com/package/sovrium"><img src="https://img.shields.io/npm/dm/sovrium" alt="downloads" /></a>
|
|
13
18
|
</p>
|
|
14
19
|
|
|
15
20
|
<p align="center">
|
|
21
|
+
<a href="https://sovrium.com">Website</a> ·
|
|
16
22
|
<a href="VISION.md">Vision</a> ·
|
|
17
23
|
<a href="SPEC-PROGRESS.md">Roadmap</a> ·
|
|
18
24
|
<a href="CLAUDE.md">Docs</a> ·
|
|
19
25
|
<a href="https://github.com/sovrium/sovrium/issues">Issues</a>
|
|
20
26
|
</p>
|
|
21
27
|
|
|
28
|
+
<!-- TODO: Add a product screenshot or demo GIF here (recommended: 1200x800px). -->
|
|
29
|
+
|
|
22
30
|
---
|
|
23
31
|
|
|
24
32
|
## What is Sovrium?
|
|
25
33
|
|
|
26
|
-
Sovrium turns **configuration
|
|
27
|
-
|
|
28
|
-
No code generation. No external services. Just config and `sovrium start`.
|
|
34
|
+
Sovrium turns a **configuration file** into a complete web application — database, authentication, API, and pages included.
|
|
29
35
|
|
|
30
|
-
|
|
36
|
+
No code generation. No external services. Write a config file, run one command, and your app is live.
|
|
31
37
|
|
|
32
38
|
```yaml
|
|
33
39
|
# sovrium.yaml
|
|
@@ -58,11 +64,15 @@ pages:
|
|
|
58
64
|
content: Welcome to My CRM
|
|
59
65
|
```
|
|
60
66
|
|
|
67
|
+
```bash
|
|
68
|
+
sovrium start sovrium.yaml
|
|
69
|
+
# -> http://localhost:3000
|
|
70
|
+
```
|
|
71
|
+
|
|
61
72
|
<details>
|
|
62
|
-
<summary>
|
|
73
|
+
<summary>Prefer TypeScript? Use it for autocompletion and type checking.</summary>
|
|
63
74
|
|
|
64
75
|
```typescript
|
|
65
|
-
// app.ts
|
|
66
76
|
import { start } from 'sovrium'
|
|
67
77
|
|
|
68
78
|
await start({
|
|
@@ -91,229 +101,101 @@ await start({
|
|
|
91
101
|
|
|
92
102
|
</details>
|
|
93
103
|
|
|
94
|
-
```bash
|
|
95
|
-
sovrium start sovrium.yaml # Run with YAML
|
|
96
|
-
bun run app.ts # Or run with TypeScript
|
|
97
|
-
# -> http://localhost:3000
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
---
|
|
101
|
-
|
|
102
|
-
## Why Sovrium?
|
|
103
|
-
|
|
104
|
-
**The problem**: Organizations pay $10k+/month for 20+ SaaS tools, with data scattered everywhere and zero control.
|
|
105
|
-
|
|
106
|
-
**The solution**: One self-hosted platform that does what you need, configured in files you own.
|
|
107
|
-
|
|
108
|
-
| | Sovrium | SaaS Tools |
|
|
109
|
-
| ------------------- | :-------------: | :----------: |
|
|
110
|
-
| **Data ownership** | Your servers | Vendor cloud |
|
|
111
|
-
| **Monthly cost** | $0 (infra only) | $20-50/user |
|
|
112
|
-
| **Vendor lock-in** | None | Complete |
|
|
113
|
-
| **Customization** | Unlimited | Limited |
|
|
114
|
-
| **Version control** | Git-native | None |
|
|
115
|
-
|
|
116
104
|
---
|
|
117
105
|
|
|
118
|
-
## Quick Start
|
|
106
|
+
## 🚀 Quick Start
|
|
119
107
|
|
|
120
|
-
**
|
|
108
|
+
**You need**: [Bun](https://bun.sh) 1.3+ and [PostgreSQL](https://www.postgresql.org/) 15+
|
|
121
109
|
|
|
122
110
|
```bash
|
|
123
|
-
# Install
|
|
124
111
|
bun add sovrium
|
|
125
|
-
|
|
126
|
-
# Create config
|
|
127
|
-
cat > sovrium.yaml << EOF
|
|
128
|
-
name: my-app
|
|
129
|
-
pages:
|
|
130
|
-
- name: home
|
|
131
|
-
path: /
|
|
132
|
-
sections:
|
|
133
|
-
- type: h1
|
|
134
|
-
content: Hello World
|
|
135
|
-
EOF
|
|
136
|
-
|
|
137
|
-
# Run
|
|
138
112
|
sovrium start sovrium.yaml
|
|
139
|
-
|
|
140
|
-
# Or use environment variable (JSON, YAML, or URL)
|
|
141
|
-
APP_SCHEMA='{"name":"my-app"}' sovrium start
|
|
142
|
-
APP_SCHEMA='name: my-app' sovrium start
|
|
143
|
-
APP_SCHEMA='https://example.com/app.yaml' sovrium start
|
|
144
113
|
```
|
|
145
114
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
## Features
|
|
149
|
-
|
|
150
|
-
### Database & Tables
|
|
151
|
-
|
|
152
|
-
Define your data model in config. Sovrium creates PostgreSQL tables, handles migrations, and exposes a full REST API automatically.
|
|
153
|
-
|
|
154
|
-
- **44+ field types** -- text, numeric, date/time, selection, media, relational, user tracking, and advanced types (formula, JSON, geolocation, barcode, autonumber, and more)
|
|
155
|
-
- **Relationships** -- one-to-many and many-to-many with lookup and rollup fields
|
|
156
|
-
- **Views** -- filtered, sorted, and grouped views with field-level visibility
|
|
157
|
-
- **Indexes and constraints** -- primary keys, unique constraints, check constraints
|
|
158
|
-
- **Soft delete** -- built-in trash with restore capability
|
|
159
|
-
- **Permissions** -- role-based table and field-level access control
|
|
160
|
-
- **Schema evolution** -- migration system for safe schema changes
|
|
115
|
+
Your app is running at `http://localhost:3000`.
|
|
161
116
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
Every table gets a full CRUD API with no additional code.
|
|
165
|
-
|
|
166
|
-
- **Records** -- create, read, update, delete with field validation
|
|
167
|
-
- **Batch operations** -- bulk create, update, and upsert
|
|
168
|
-
- **Filtering and sorting** -- query records with field-based filters
|
|
169
|
-
- **Pagination** -- cursor and offset-based pagination
|
|
170
|
-
- **Activity logs** -- audit trail for all record changes
|
|
171
|
-
- **Rate limiting** -- configurable per-endpoint rate limits
|
|
172
|
-
|
|
173
|
-
### Authentication
|
|
174
|
-
|
|
175
|
-
Production-ready auth out of the box.
|
|
176
|
-
|
|
177
|
-
- **Email/password** -- sign up, sign in, email verification, password reset
|
|
178
|
-
- **Magic link** -- passwordless email authentication
|
|
179
|
-
- **Two-factor** -- TOTP-based 2FA
|
|
180
|
-
- **OAuth** -- social login providers
|
|
181
|
-
- **Roles** -- admin, member, viewer with custom roles
|
|
182
|
-
- **Admin plugin** -- user management, banning, impersonation
|
|
183
|
-
- **Session management** -- list, revoke, and manage active sessions
|
|
184
|
-
|
|
185
|
-
### Pages & UI
|
|
186
|
-
|
|
187
|
-
Server-rendered pages with a component-based system.
|
|
188
|
-
|
|
189
|
-
- **Dynamic routing** -- path-based page routing
|
|
190
|
-
- **Sections** -- composable content sections with theming support
|
|
191
|
-
- **Reusable components** -- define once with `$ref`, customize with `$vars`
|
|
192
|
-
- **SEO metadata** -- title, description, Open Graph, structured data
|
|
193
|
-
- **Scripts** -- custom head and body scripts per page
|
|
194
|
-
|
|
195
|
-
### Theming
|
|
117
|
+
---
|
|
196
118
|
|
|
197
|
-
|
|
119
|
+
## ✨ Features
|
|
198
120
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
121
|
+
| | Feature | What you get |
|
|
122
|
+
| :-- | :----------------- | :-------------------------------------------------------------------------------------------------------------------------------------- |
|
|
123
|
+
| 🗄️ | **Tables** | 40 field types including formulas, lookups, and rollups. Views with filtering and sorting. Trash with restore. Granular access control. |
|
|
124
|
+
| 🔌 | **Automatic API** | Every table gets its own API. Filter, sort, paginate, and track changes — no code needed. |
|
|
125
|
+
| 🔐 | **Authentication** | Email/password, magic link, two-factor, social login. Built-in roles (admin, member, viewer) and user management. |
|
|
126
|
+
| 🖥️ | **Pages** | Build pages from reusable sections. Define once, customize with variables. SEO-ready out of the box. |
|
|
127
|
+
| 🎨 | **Theming** | Colors, fonts, spacing, shadows, animations, and responsive breakpoints — all defined in your config file. |
|
|
128
|
+
| 🌐 | **Multi-language** | Built-in translation system with browser language detection and user preference memory. |
|
|
129
|
+
| ⌨️ | **CLI** | `sovrium start` to run your app. `sovrium build` to export a static site. Supports YAML, JSON, and TypeScript. |
|
|
204
130
|
|
|
205
|
-
|
|
131
|
+
---
|
|
206
132
|
|
|
207
|
-
|
|
133
|
+
## 💡 Why Sovrium?
|
|
208
134
|
|
|
209
|
-
|
|
210
|
-
- **Translation tokens** -- `$t:` syntax for referencing translations in pages
|
|
211
|
-
- **Browser detection** -- automatic language detection
|
|
212
|
-
- **Persistence** -- remember user language preference
|
|
135
|
+
Organizations pay **$10k+/month** for 20+ SaaS tools, with data scattered everywhere and zero control.
|
|
213
136
|
|
|
214
|
-
|
|
137
|
+
Sovrium is **one self-hosted platform** that does what you need, configured in files you own.
|
|
215
138
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
139
|
+
| | Sovrium | SaaS Tools |
|
|
140
|
+
| ------------------- | :-------------: | :----------: |
|
|
141
|
+
| **Data ownership** | Your servers | Vendor cloud |
|
|
142
|
+
| **Monthly cost** | $0 (infra only) | $20-50/user |
|
|
143
|
+
| **Vendor lock-in** | None | Complete |
|
|
144
|
+
| **Customization** | Unlimited | Limited |
|
|
145
|
+
| **Version control** | Git-native | None |
|
|
219
146
|
|
|
220
147
|
---
|
|
221
148
|
|
|
222
|
-
##
|
|
149
|
+
## 📊 Status
|
|
223
150
|
|
|
224
|
-
|
|
225
|
-
Config File (YAML/JSON/TS)
|
|
226
|
-
|
|
|
227
|
-
v
|
|
228
|
-
Effect Schema (validation)
|
|
229
|
-
|
|
|
230
|
-
v
|
|
231
|
-
Sovrium Runtime
|
|
232
|
-
|
|
|
233
|
-
+---> PostgreSQL (tables, records, migrations)
|
|
234
|
-
+---> Hono (REST API + SSR)
|
|
235
|
-
+---> Better Auth (sessions, OAuth, 2FA)
|
|
236
|
-
+---> React + Tailwind (server-rendered UI)
|
|
237
|
-
```
|
|
151
|
+
Sovrium is under **active development**. The core feature set — tables, API, authentication, pages, theming, and i18n — is defined and tested across 272 user stories. Implementation is ongoing with automated pipelines.
|
|
238
152
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
| | |
|
|
242
|
-
| :---------------------------------------- | :------------- |
|
|
243
|
-
| [Bun](https://bun.sh) | Runtime |
|
|
244
|
-
| [Hono](https://hono.dev) | Web framework |
|
|
245
|
-
| [Drizzle](https://orm.drizzle.team) | Database ORM |
|
|
246
|
-
| [Effect](https://effect.website) | Type-safe FP |
|
|
247
|
-
| [React 19](https://react.dev) | UI (SSR) |
|
|
248
|
-
| [Tailwind CSS 4](https://tailwindcss.com) | Styling |
|
|
249
|
-
| [Better Auth](https://better-auth.com) | Authentication |
|
|
250
|
-
|
|
251
|
-
### Project Structure
|
|
252
|
-
|
|
253
|
-
```
|
|
254
|
-
src/
|
|
255
|
-
domain/ # Business logic, Effect Schema models
|
|
256
|
-
models/app/ # App configuration schema (tables, auth, pages, theme, ...)
|
|
257
|
-
models/api/ # API contracts (Zod schemas for OpenAPI)
|
|
258
|
-
application/ # Use cases, Effect programs
|
|
259
|
-
infrastructure/ # Database, auth, CSS compiler, email, logging
|
|
260
|
-
presentation/ # API routes, CLI, React components, styling
|
|
261
|
-
specs/ # 2,200+ E2E tests (Playwright)
|
|
262
|
-
docs/ # Architecture and infrastructure documentation
|
|
263
|
-
```
|
|
153
|
+
📋 [See the full roadmap →](SPEC-PROGRESS.md)
|
|
264
154
|
|
|
265
155
|
---
|
|
266
156
|
|
|
267
|
-
##
|
|
157
|
+
## 🤝 Contributing
|
|
268
158
|
|
|
269
|
-
|
|
159
|
+
We welcome contributions of all kinds!
|
|
270
160
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
| App Schema | 131 | 1,398 | 99% |
|
|
277
|
-
| CLI | 9 | 108 | 100% |
|
|
278
|
-
| Migrations | 17 | 139 | 100% |
|
|
279
|
-
| Templates | 1 | 11 | 100% |
|
|
161
|
+
```bash
|
|
162
|
+
git clone https://github.com/sovrium/sovrium
|
|
163
|
+
cd sovrium && bun install
|
|
164
|
+
bun run start
|
|
165
|
+
```
|
|
280
166
|
|
|
281
|
-
|
|
167
|
+
📖 See [CLAUDE.md](CLAUDE.md) for coding standards and architecture details.
|
|
282
168
|
|
|
283
169
|
---
|
|
284
170
|
|
|
285
|
-
##
|
|
171
|
+
## 💬 Community & Support
|
|
286
172
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
bun run quality --skip-e2e # Lint, format, typecheck, unit tests
|
|
291
|
-
bun test:unit # Unit tests only
|
|
292
|
-
bun test:e2e:regression # E2E regression tests
|
|
293
|
-
bun run progress # Spec analysis and progress report
|
|
294
|
-
```
|
|
173
|
+
- [GitHub Issues](https://github.com/sovrium/sovrium/issues) — Bug reports and feature requests
|
|
174
|
+
- [GitHub Discussions](https://github.com/sovrium/sovrium/discussions) — Questions, ideas, and general chat
|
|
175
|
+
- [Vision](VISION.md) — Where Sovrium is headed
|
|
295
176
|
|
|
296
177
|
---
|
|
297
178
|
|
|
298
|
-
|
|
179
|
+
<details>
|
|
180
|
+
<summary>🛠️ Built with</summary>
|
|
181
|
+
<br />
|
|
299
182
|
|
|
300
|
-
|
|
183
|
+
[Bun](https://bun.sh) · [Hono](https://hono.dev) · [Drizzle ORM](https://orm.drizzle.team) · [Effect](https://effect.website) · [React 19](https://react.dev) · [Tailwind CSS 4](https://tailwindcss.com) · [Better Auth](https://better-auth.com)
|
|
301
184
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
```
|
|
185
|
+
See [CLAUDE.md](CLAUDE.md) for the full architecture and project structure.
|
|
186
|
+
|
|
187
|
+
</details>
|
|
306
188
|
|
|
307
189
|
---
|
|
308
190
|
|
|
309
|
-
## License
|
|
191
|
+
## 📄 License
|
|
310
192
|
|
|
311
|
-
[BSL-1.1](LICENSE.md)
|
|
193
|
+
[BSL-1.1](LICENSE.md) — Free for internal and non-commercial use. Automatically converts to **Apache 2.0** on January 1, 2029.
|
|
312
194
|
|
|
313
195
|
---
|
|
314
196
|
|
|
315
197
|
<p align="center">
|
|
316
|
-
<
|
|
198
|
+
<strong>Own your data. Own your tools. Own your future.</strong>
|
|
317
199
|
</p>
|
|
318
200
|
|
|
319
201
|
<p align="center">
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sovrium",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"packageManager": "bun@1.3.10",
|
|
5
5
|
"description": "Configuration-driven web application platform built with Bun, Effect, React, and Tailwind CSS",
|
|
6
6
|
"module": "src/index.ts",
|
|
@@ -12,8 +12,12 @@
|
|
|
12
12
|
"company": "ESSENTIAL SERVICES",
|
|
13
13
|
"email": "support@sovrium.com"
|
|
14
14
|
},
|
|
15
|
-
"license": "
|
|
15
|
+
"license": "BUSL-1.1",
|
|
16
16
|
"type": "module",
|
|
17
|
+
"publishConfig": {
|
|
18
|
+
"provenance": true,
|
|
19
|
+
"access": "public"
|
|
20
|
+
},
|
|
17
21
|
"repository": {
|
|
18
22
|
"type": "git",
|
|
19
23
|
"url": "https://github.com/sovrium/sovrium.git"
|
|
@@ -21,7 +25,16 @@
|
|
|
21
25
|
"bugs": {
|
|
22
26
|
"url": "https://github.com/sovrium/sovrium/issues"
|
|
23
27
|
},
|
|
24
|
-
"homepage": "https://
|
|
28
|
+
"homepage": "https://sovrium.com",
|
|
29
|
+
"engines": {
|
|
30
|
+
"bun": ">=1.3.10"
|
|
31
|
+
},
|
|
32
|
+
"exports": {
|
|
33
|
+
".": {
|
|
34
|
+
"import": "./src/index.ts",
|
|
35
|
+
"types": "./src/index.ts"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
25
38
|
"keywords": [
|
|
26
39
|
"sovrium",
|
|
27
40
|
"bun",
|
|
@@ -34,9 +47,7 @@
|
|
|
34
47
|
"configuration"
|
|
35
48
|
],
|
|
36
49
|
"files": [
|
|
37
|
-
"drizzle
|
|
38
|
-
"drizzle/**/*",
|
|
39
|
-
"schemas/*",
|
|
50
|
+
"drizzle/**",
|
|
40
51
|
"src/**/*.ts",
|
|
41
52
|
"src/**/*.tsx",
|
|
42
53
|
"src/**/*.css",
|
|
@@ -47,7 +58,6 @@
|
|
|
47
58
|
"LICENSE.md",
|
|
48
59
|
"LICENSE_EE.md",
|
|
49
60
|
"README.md",
|
|
50
|
-
"CHANGELOG.md",
|
|
51
61
|
"tsconfig.json"
|
|
52
62
|
],
|
|
53
63
|
"scripts": {
|
|
@@ -88,7 +98,9 @@
|
|
|
88
98
|
"db:check": "drizzle-kit check",
|
|
89
99
|
"website": "bun --watch run website/start.ts",
|
|
90
100
|
"website:build": "bun run website/build.ts",
|
|
91
|
-
"
|
|
101
|
+
"analyze-commits": "bun run scripts/analyze-commits.ts",
|
|
102
|
+
"prepublish-check": "bun run scripts/prepublish-check.ts",
|
|
103
|
+
"release": "bun run scripts/release.ts"
|
|
92
104
|
},
|
|
93
105
|
"devDependencies": {
|
|
94
106
|
"@apidevtools/json-schema-ref-parser": "^15.3.1",
|
|
@@ -97,9 +109,7 @@
|
|
|
97
109
|
"@eslint/compat": "^2.0.2",
|
|
98
110
|
"@eslint/js": "^9.39.3",
|
|
99
111
|
"@playwright/test": "^1.58.2",
|
|
100
|
-
"@
|
|
101
|
-
"@semantic-release/exec": "^7.1.0",
|
|
102
|
-
"@semantic-release/git": "^10.0.1",
|
|
112
|
+
"@tanstack/react-query-devtools": "^5.91.3",
|
|
103
113
|
"@testcontainers/postgresql": "^11.12.0",
|
|
104
114
|
"@types/bun": "^1.3.10",
|
|
105
115
|
"@types/dompurify": "^3.2.0",
|
|
@@ -125,10 +135,10 @@
|
|
|
125
135
|
"globals": "^17.4.0",
|
|
126
136
|
"knip": "^5.85.0",
|
|
127
137
|
"otplib": "^13.3.0",
|
|
138
|
+
"pagefind": "^1.4.0",
|
|
128
139
|
"pg": "^8.19.0",
|
|
129
140
|
"playwright": "^1.58.2",
|
|
130
141
|
"prettier-plugin-tailwindcss": "^0.7.2",
|
|
131
|
-
"semantic-release": "^25.0.3",
|
|
132
142
|
"typescript": "^5.9.3",
|
|
133
143
|
"typescript-eslint": "^8.56.1"
|
|
134
144
|
},
|
|
@@ -136,21 +146,20 @@
|
|
|
136
146
|
"typescript": "^5.9.3"
|
|
137
147
|
},
|
|
138
148
|
"dependencies": {
|
|
149
|
+
"@better-auth/drizzle-adapter": "^1.5.3",
|
|
139
150
|
"@effect/experimental": "^0.58.0",
|
|
140
151
|
"@hono/zod-openapi": "^1.2.2",
|
|
141
152
|
"@hono/zod-validator": "^0.7.6",
|
|
142
153
|
"@hookform/resolvers": "^5.2.2",
|
|
143
|
-
"@scalar/hono-api-reference": "^0.9.
|
|
154
|
+
"@scalar/hono-api-reference": "^0.9.48",
|
|
144
155
|
"@tailwindcss/postcss": "^4.2.1",
|
|
145
156
|
"@tanstack/react-query": "^5.90.21",
|
|
146
|
-
"@tanstack/react-query-devtools": "^5.91.3",
|
|
147
157
|
"@tanstack/react-table": "^8.21.3",
|
|
148
|
-
"better-auth": "^1.5.
|
|
158
|
+
"better-auth": "^1.5.3",
|
|
149
159
|
"dompurify": "^3.3.1",
|
|
150
160
|
"drizzle-orm": "^0.45.1",
|
|
151
161
|
"effect": "^3.19.19",
|
|
152
|
-
"hono": "^4.12.
|
|
153
|
-
"jiti": "^2.6.1",
|
|
162
|
+
"hono": "^4.12.4",
|
|
154
163
|
"js-yaml": "^4.1.1",
|
|
155
164
|
"lucide-react": "^0.575.0",
|
|
156
165
|
"nanoid": "^5.1.6",
|
|
@@ -17,18 +17,34 @@ export interface HreflangConfig {
|
|
|
17
17
|
readonly defaultLanguage: string
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Repair whitespace inside <pre> tags that Prettier's HTML formatter damages.
|
|
22
|
+
*
|
|
23
|
+
* Prettier adds a newline + indentation after the opening `>` of `<pre>` tags.
|
|
24
|
+
* Because `<pre>` renders whitespace literally (CSS `white-space: pre`), this
|
|
25
|
+
* introduces a visible blank first line in code blocks.
|
|
26
|
+
*
|
|
27
|
+
* This function strips the newline and any spaces immediately after `<pre ...>`.
|
|
28
|
+
*/
|
|
29
|
+
const repairPreWhitespace = (html: string): string => html.replace(/(<pre[^>]*>)\n[ ]*/g, '$1')
|
|
30
|
+
|
|
20
31
|
/**
|
|
21
32
|
* Format HTML with Prettier for professional formatting
|
|
22
|
-
* Loads Prettier config and formats HTML using the HTML parser
|
|
33
|
+
* Loads Prettier config and formats HTML using the HTML parser.
|
|
34
|
+
*
|
|
35
|
+
* After formatting, repairs `<pre>` whitespace that Prettier damages
|
|
36
|
+
* (leading newline + indentation, trailing whitespace).
|
|
23
37
|
*/
|
|
24
38
|
export const formatHtmlWithPrettier = async (html: string): Promise<string> => {
|
|
25
39
|
const prettier = await import('prettier')
|
|
26
40
|
const config = await prettier.resolveConfig(process.cwd())
|
|
27
41
|
|
|
28
|
-
|
|
42
|
+
const formatted = await prettier.format(html, {
|
|
29
43
|
...config,
|
|
30
44
|
parser: 'html',
|
|
31
45
|
})
|
|
46
|
+
|
|
47
|
+
return repairPreWhitespace(formatted)
|
|
32
48
|
}
|
|
33
49
|
|
|
34
50
|
/**
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 ESSENTIAL SERVICES
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Business Source License 1.1
|
|
5
|
+
* found in the LICENSE.md file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { z } from 'zod'
|
|
9
|
+
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Activity Log Schemas
|
|
12
|
+
// ============================================================================
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Activity log user reference schema
|
|
16
|
+
*/
|
|
17
|
+
export const activityLogUserSchema = z.object({
|
|
18
|
+
id: z.string().describe('User identifier'),
|
|
19
|
+
name: z.string().describe('User display name'),
|
|
20
|
+
email: z.string().describe('User email address'),
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Activity log entry schema (list view)
|
|
25
|
+
*/
|
|
26
|
+
export const activityLogSchema = z.object({
|
|
27
|
+
id: z.string().describe('Activity log identifier'),
|
|
28
|
+
createdAt: z.string().describe('ISO 8601 timestamp of the activity'),
|
|
29
|
+
userId: z.string().optional().describe('User who performed the action'),
|
|
30
|
+
action: z.enum(['create', 'update', 'delete', 'restore']).describe('Action type'),
|
|
31
|
+
tableName: z.string().describe('Name of the affected table'),
|
|
32
|
+
recordId: z.union([z.string(), z.number()]).describe('ID of the affected record'),
|
|
33
|
+
user: activityLogUserSchema.nullable().describe('User details (null for system activities)'),
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Activity log detail schema (single view, includes changes)
|
|
38
|
+
*/
|
|
39
|
+
export const activityLogDetailSchema = activityLogSchema.extend({
|
|
40
|
+
changes: z
|
|
41
|
+
.record(z.string(), z.unknown())
|
|
42
|
+
.nullable()
|
|
43
|
+
.describe('Field changes (null for delete actions)'),
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Activity log pagination schema
|
|
48
|
+
*/
|
|
49
|
+
export const activityPaginationSchema = z.object({
|
|
50
|
+
total: z.number().int().describe('Total count of activities'),
|
|
51
|
+
page: z.number().int().describe('Current page number'),
|
|
52
|
+
pageSize: z.number().int().describe('Items per page'),
|
|
53
|
+
totalPages: z.number().int().describe('Total number of pages'),
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
// ============================================================================
|
|
57
|
+
// Activity Log Response Schemas
|
|
58
|
+
// ============================================================================
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* List activity logs response schema
|
|
62
|
+
*
|
|
63
|
+
* GET /api/activity
|
|
64
|
+
*/
|
|
65
|
+
export const listActivityLogsResponseSchema = z.object({
|
|
66
|
+
activities: z.array(activityLogSchema).describe('List of activity log entries'),
|
|
67
|
+
pagination: activityPaginationSchema.describe('Pagination metadata'),
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Get activity log detail response schema
|
|
72
|
+
*
|
|
73
|
+
* GET /api/activity/:activityId
|
|
74
|
+
*/
|
|
75
|
+
export const getActivityLogResponseSchema = activityLogDetailSchema.describe(
|
|
76
|
+
'Single activity log entry with change details'
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
// ============================================================================
|
|
80
|
+
// TypeScript Types
|
|
81
|
+
// ============================================================================
|
|
82
|
+
|
|
83
|
+
export type ActivityLogUser = z.infer<typeof activityLogUserSchema>
|
|
84
|
+
export type ActivityLog = z.infer<typeof activityLogSchema>
|
|
85
|
+
export type ActivityLogDetail = z.infer<typeof activityLogDetailSchema>
|
|
86
|
+
export type ListActivityLogsResponse = z.infer<typeof listActivityLogsResponseSchema>
|
|
87
|
+
export type GetActivityLogResponse = z.infer<typeof getActivityLogResponseSchema>
|