javascript-solid-server 0.0.111 → 0.0.112

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.
@@ -327,7 +327,8 @@
327
327
  "Bash(gh label:*)",
328
328
  "Bash(mongosh --eval \"db.runCommand\\({ ping: 1 }\\)\" 2>&1 | head -5)",
329
329
  "Bash(which jss && jss --version 2>&1)",
330
- "Bash(jss start --help 2>&1 | grep -i mongo)"
330
+ "Bash(jss start --help 2>&1 | grep -i mongo)",
331
+ "Bash(grep -A5 '\"\"files\"\"' package.json)"
331
332
  ]
332
333
  }
333
334
  }
package/README.md CHANGED
@@ -91,23 +91,28 @@ Full options: [docs/configuration.md](docs/configuration.md)
91
91
  |-------|------|
92
92
  | Configuration & Options | [docs/configuration.md](docs/configuration.md) |
93
93
  | Authentication | [docs/authentication.md](docs/authentication.md) |
94
+ | Mashlib / SolidOS UI | [docs/mashlib.md](docs/mashlib.md) |
95
+ | WebSocket Notifications | [docs/notifications.md](docs/notifications.md) |
94
96
  | Git Support | [docs/git-support.md](docs/git-support.md) |
97
+ | Nostr Relay | [docs/nostr.md](docs/nostr.md) |
95
98
  | ActivityPub & Mastodon API | [docs/activitypub.md](docs/activitypub.md) |
96
99
  | remoteStorage | [docs/remotestorage.md](docs/remotestorage.md) |
97
- | Security & Subdomain Mode | [docs/security.md](docs/security.md) |
98
- | HTTP 402 Payments | [docs/payments.md](docs/payments.md) |
99
100
  | WebRTC & Tunnel | [docs/webrtc.md](docs/webrtc.md) |
100
101
  | MongoDB `/db/` Route | [docs/mongodb.md](docs/mongodb.md) |
102
+ | HTTP 402 Payments | [docs/payments.md](docs/payments.md) |
103
+ | Storage Quotas | [docs/quotas.md](docs/quotas.md) |
104
+ | Invite-Only Registration | [docs/invites.md](docs/invites.md) |
105
+ | Security & Subdomain Mode | [docs/security.md](docs/security.md) |
101
106
  | Architecture & Structure | [docs/architecture.md](docs/architecture.md) |
102
107
 
103
108
  ## Comparison
104
109
 
105
110
  | Server | Size | Deps | Notes |
106
111
  |--------|------|------|-------|
107
- | [JSS](https://github.com/JavaScriptSolidServer/JavaScriptSolidServer) | ~14K LoC | 14 | Minimal, JSON-LD native |
108
- | [NSS](https://github.com/nodeSolidServer/node-solid-server) | 777 KB | 58 | Original Solid server |
109
- | [CSS](https://github.com/CommunitySolidServer/CommunitySolidServer) | 5.8 MB | 70 | Modular, configurable |
110
- | [Pivot](https://github.com/solid-contrib/pivot) | ~6 MB | 70+ | Built on CSS |
112
+ | [JSS](https://github.com/JavaScriptSolidServer/JavaScriptSolidServer) | ~18K LoC | 15 | Minimal, JSON-LD native |
113
+ | [NSS](https://github.com/nodeSolidServer/node-solid-server) | ~25K LoC | 58 | Original Solid server |
114
+ | [CSS](https://github.com/CommunitySolidServer/CommunitySolidServer) | ~65K LoC | 70 | Modular, configurable |
115
+ | [Pivot](https://github.com/solid-contrib/pivot) | ~70K LoC | 70+ | Built on CSS |
111
116
 
112
117
  ## Performance
113
118
 
package/bin/jss.js CHANGED
@@ -53,12 +53,10 @@ program
53
53
  .option('--subdomains', 'Enable subdomain-based pods (XSS protection)')
54
54
  .option('--no-subdomains', 'Disable subdomain-based pods')
55
55
  .option('--base-domain <domain>', 'Base domain for subdomain pods (e.g., "example.com")')
56
- .option('--mashlib', 'Enable Mashlib data browser (local mode, requires mashlib in node_modules)')
57
- .option('--mashlib-cdn', 'Enable Mashlib data browser (CDN mode, no local files needed)')
56
+ .option('--mashlib-cdn', 'Enable Mashlib data browser (CDN mode)')
58
57
  .option('--mashlib-module <url>', 'Enable ES module data browser from a URL')
59
58
  .option('--no-mashlib', 'Disable Mashlib data browser')
60
59
  .option('--mashlib-version <version>', 'Mashlib version for CDN mode (default: 2.0.0)')
61
- .option('--solidos-ui', 'Enable modern Nextcloud-style UI (requires --mashlib)')
62
60
  .option('--git', 'Enable Git HTTP backend (clone/push support)')
63
61
  .option('--no-git', 'Disable Git HTTP backend')
64
62
  .option('--nostr', 'Enable Nostr relay')
@@ -143,7 +141,6 @@ program
143
141
  mashlibCdn: config.mashlibCdn,
144
142
  mashlibVersion: config.mashlibVersion,
145
143
  mashlibModule: config.mashlibModule,
146
- solidosUi: config.solidosUi,
147
144
  git: config.git,
148
145
  nostr: config.nostr,
149
146
  nostrPath: config.nostrPath,
@@ -193,7 +190,6 @@ program
193
190
  console.log(` Mashlib: local (data browser enabled)`);
194
191
  }
195
192
  if (config.mashlibModule) console.log(` Mashlib module: ${config.mashlibModule}`);
196
- if (config.solidosUi) console.log(' SolidOS UI: enabled (modern interface)');
197
193
  if (config.git) console.log(' Git: enabled (clone/push support)');
198
194
  if (config.nostr) console.log(` Nostr: enabled (${config.nostrPath})`);
199
195
  if (config.webrtc) console.log(` WebRTC: enabled (${config.webrtcPath || '/.webrtc'})`);
@@ -355,43 +355,6 @@ jss quota reconcile alice
355
355
 
356
356
  Supported formats: `50MB`, `1GB`, `500KB`, `1TB`
357
357
 
358
- ## Storage Quotas
359
-
360
- Limit storage per pod to prevent abuse and manage resources:
361
-
362
- ```bash
363
- jss start --default-quota 50MB
364
- ```
365
-
366
- ### Managing Quotas
367
-
368
- ```bash
369
- # Set quota for a user (overrides default)
370
- jss quota set alice 100MB
371
-
372
- # Show quota info
373
- jss quota show alice
374
- # alice:
375
- # Used: 12.5 MB
376
- # Limit: 100 MB
377
- # Free: 87.5 MB
378
- # Usage: 12%
379
-
380
- # Recalculate from actual disk usage
381
- jss quota reconcile alice
382
- ```
383
-
384
- ### How It Works
385
-
386
- - Quotas are tracked incrementally on PUT, POST, and DELETE operations
387
- - When quota is exceeded, the server returns HTTP 507 Insufficient Storage
388
- - Each pod stores its quota in `/{pod}/.quota.json`
389
- - Use `reconcile` to fix quota drift from manual file changes
390
-
391
- ### Size Formats
392
-
393
- Supported formats: `50MB`, `1GB`, `500KB`, `1TB`
394
-
395
358
  ### Mashlib Data Browser
396
359
 
397
360
  Enable the [SolidOS Mashlib](https://github.com/SolidOS/mashlib) data browser for RDF resources. Two modes are available:
@@ -0,0 +1,43 @@
1
+ # Invite-Only Registration
2
+
3
+ Control who can create accounts by requiring invite codes.
4
+
5
+ ```bash
6
+ jss start --idp --invite-only
7
+ ```
8
+
9
+ ## Managing Invite Codes
10
+
11
+ ```bash
12
+ # Create a single-use invite
13
+ jss invite create
14
+ # Created invite code: ABCD1234
15
+
16
+ # Create multi-use invite with note
17
+ jss invite create -u 5 -n "For team members"
18
+
19
+ # List all active invites
20
+ jss invite list
21
+ # CODE USES CREATED NOTE
22
+ # -------------------------------------------------------
23
+ # ABCD1234 0/1 2026-01-03
24
+ # EFGH5678 2/5 2026-01-03 For team members
25
+
26
+ # Revoke an invite
27
+ jss invite revoke ABCD1234
28
+ ```
29
+
30
+ ## How It Works
31
+
32
+ | Mode | Registration | Pod Creation |
33
+ |------|--------------|--------------|
34
+ | Open (default) | Anyone can register | Anyone can create pods |
35
+ | Invite-only | Requires valid invite code | Via registration only |
36
+
37
+ When `--invite-only` is enabled:
38
+ - The registration page shows an "Invite Code" field
39
+ - Invalid or expired codes are rejected with an error
40
+ - Each use decrements the invite's remaining uses
41
+ - Depleted invites are automatically removed
42
+
43
+ Invite codes are stored in `.server/invites.json` in your data directory.
@@ -0,0 +1,58 @@
1
+ # Mashlib Data Browser
2
+
3
+ Enable the [SolidOS Mashlib](https://github.com/SolidOS/mashlib) data browser for RDF resources.
4
+
5
+ ## Modes
6
+
7
+ **CDN Mode** (recommended for getting started):
8
+ ```bash
9
+ jss start --mashlib-cdn --conneg
10
+ ```
11
+ Loads mashlib from unpkg.com CDN. Zero footprint — no local files needed.
12
+
13
+ **Local Mode** (for production/offline):
14
+ ```bash
15
+ jss start --mashlib --conneg
16
+ ```
17
+ Serves mashlib from `src/mashlib-local/dist/`. Requires building mashlib locally:
18
+ ```bash
19
+ cd src/mashlib-local
20
+ npm install && npm run build
21
+ ```
22
+
23
+ **ES Module Mode** (for custom or next-gen mashlib builds):
24
+ ```bash
25
+ jss start --mashlib-module https://example.com/mashlib.js
26
+ ```
27
+ Loads an ES module-based data browser from any URL. Uses `<script type="module">` and `<div id="mashlib">` (self-initializing). CSS is auto-derived by replacing `.js` with `.css`. Content negotiation is auto-enabled.
28
+
29
+ ## How It Works
30
+
31
+ 1. Browser requests `/alice/public/data.ttl` with `Accept: text/html`
32
+ 2. Server returns Mashlib HTML wrapper
33
+ 3. Mashlib fetches the actual data via content negotiation
34
+ 4. Mashlib renders an interactive, editable view
35
+
36
+ **Note:** Mashlib works best with `--conneg` enabled for Turtle support.
37
+
38
+ ## Modern UI (SolidOS UI)
39
+
40
+ ```bash
41
+ jss start --mashlib --solidos-ui --conneg
42
+ ```
43
+
44
+ Serves a modern Nextcloud-style UI shell while reusing mashlib's data layer:
45
+ - Modern file browser with breadcrumb navigation
46
+ - Profile, Contacts, Sharing, and Settings views
47
+ - Path-based URLs (browser URL reflects current resource)
48
+ - Responsive design for mobile devices
49
+
50
+ Requires solidos-ui dist files in `src/mashlib-local/dist/solidos-ui/`. See [solidos-ui](https://github.com/solidos/solidos/tree/main/workspaces/solidos-ui) for details.
51
+
52
+ ## Profile Pages
53
+
54
+ Pod profiles (`/alice/`) use HTML with embedded JSON-LD data islands and are rendered using:
55
+ - [mashlib-jss](https://github.com/JavaScriptSolidServer/mashlib-jss) — A fork of mashlib with `getPod()` fix for path-based pods
56
+ - [solidos-lite](https://github.com/SolidOS/solidos-lite) — Parses JSON-LD data islands into the RDF store
57
+
58
+ This allows profiles to work without server-side content negotiation while still providing full SolidOS editing capabilities.
package/docs/nostr.md ADDED
@@ -0,0 +1,56 @@
1
+ # Nostr Relay
2
+
3
+ Integrated NIP-01/NIP-11/NIP-16 Nostr relay running on the same port as the Solid server.
4
+
5
+ ```bash
6
+ jss start --nostr
7
+ ```
8
+
9
+ ## Endpoint
10
+
11
+ `wss://your.pod/relay` (configurable via `--nostr-path`)
12
+
13
+ ## Supported NIPs
14
+
15
+ - **NIP-01** — Basic protocol flow (EVENT, REQ, CLOSE)
16
+ - **NIP-11** — Relay information document (`GET /relay` with `Accept: application/nostr+json`)
17
+ - **NIP-16** — Event treatment (regular, replaceable, ephemeral)
18
+
19
+ ## Options
20
+
21
+ | Option | Description | Default |
22
+ |--------|-------------|---------|
23
+ | `--nostr` | Enable Nostr relay | false |
24
+ | `--nostr-path <path>` | WebSocket path | /relay |
25
+ | `--nostr-max-events <n>` | Max events in memory | 1000 |
26
+
27
+ ## How It Works
28
+
29
+ - Events are stored in memory (up to `--nostr-max-events`)
30
+ - Replaceable events (kinds 0, 3, 10000-19999) replace previous events by the same pubkey
31
+ - Ephemeral events (kinds 20000-29999) are broadcast but not stored
32
+ - Parameterized replaceable events (kinds 30000-39999) use the `d` tag for deduplication
33
+ - Rate limiting: 60 events per socket per minute
34
+
35
+ ## Client Usage
36
+
37
+ ```javascript
38
+ import { Relay } from 'nostr-tools';
39
+
40
+ const relay = await Relay.connect('wss://your.pod/relay');
41
+
42
+ // Subscribe
43
+ const sub = relay.subscribe([{ kinds: [1], limit: 10 }], {
44
+ onevent(event) { console.log(event); }
45
+ });
46
+
47
+ // Publish
48
+ await relay.publish(signedEvent);
49
+ ```
50
+
51
+ ## Nostr Authentication (NIP-98)
52
+
53
+ JSS also supports NIP-98 HTTP Auth for Solid operations. See [docs/authentication.md](authentication.md) for details on:
54
+ - NIP-98 Schnorr signature authentication
55
+ - `did:nostr` → WebID resolution
56
+ - Linking Nostr identity to your WebID profile
@@ -0,0 +1,50 @@
1
+ # WebSocket Notifications
2
+
3
+ Real-time notifications for resource changes using the solid-0.1 protocol (SolidOS compatible).
4
+
5
+ ```bash
6
+ jss start --notifications
7
+ ```
8
+
9
+ ## Discovery
10
+
11
+ Clients discover the WebSocket URL via the `Updates-Via` header:
12
+
13
+ ```bash
14
+ curl -I http://localhost:3000/alice/public/
15
+ # Updates-Via: ws://localhost:3000/.notifications
16
+ ```
17
+
18
+ ## Protocol
19
+
20
+ ```
21
+ Server: protocol solid-0.1
22
+ Client: sub http://localhost:3000/alice/public/data.json
23
+ Server: ack http://localhost:3000/alice/public/data.json
24
+ Server: pub http://localhost:3000/alice/public/data.json (on change)
25
+ ```
26
+
27
+ ## How It Works
28
+
29
+ 1. Client connects to the WebSocket URL from `Updates-Via`
30
+ 2. Server sends `protocol solid-0.1` greeting
31
+ 3. Client subscribes: `sub <resource-url>`
32
+ 4. Server acknowledges: `ack <resource-url>`
33
+ 5. On any change (PUT, PATCH, DELETE), server broadcasts: `pub <resource-url>`
34
+ 6. Container subscriptions also fire when child resources change
35
+
36
+ ## ACL Enforcement
37
+
38
+ - Anonymous clients can subscribe to public resources
39
+ - Private resource subscriptions require authentication
40
+ - Cross-origin subscriptions are rejected
41
+
42
+ ## Live Reload
43
+
44
+ For development, `--live-reload` injects a script that auto-refreshes the browser when files change on disk:
45
+
46
+ ```bash
47
+ jss start --live-reload --notifications
48
+ ```
49
+
50
+ File system changes (editing files directly) also trigger WebSocket notifications.
package/docs/quotas.md ADDED
@@ -0,0 +1,36 @@
1
+ # Storage Quotas
2
+
3
+ Limit storage per pod to prevent abuse and manage resources.
4
+
5
+ ```bash
6
+ jss start --default-quota 50MB
7
+ ```
8
+
9
+ ## Managing Quotas
10
+
11
+ ```bash
12
+ # Set quota for a user (overrides default)
13
+ jss quota set alice 100MB
14
+
15
+ # Show quota info
16
+ jss quota show alice
17
+ # alice:
18
+ # Used: 12.5 MB
19
+ # Limit: 100 MB
20
+ # Free: 87.5 MB
21
+ # Usage: 12%
22
+
23
+ # Recalculate from actual disk usage
24
+ jss quota reconcile alice
25
+ ```
26
+
27
+ ## How It Works
28
+
29
+ - Quotas are tracked incrementally on PUT, POST, and DELETE operations
30
+ - When quota is exceeded, the server returns HTTP 507 Insufficient Storage
31
+ - Each pod stores its quota in `/{pod}/.quota.json`
32
+ - Use `reconcile` to fix quota drift from manual file changes
33
+
34
+ ## Size Formats
35
+
36
+ Supported formats: `50MB`, `1GB`, `500KB`, `1TB`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "javascript-solid-server",
3
- "version": "0.0.111",
3
+ "version": "0.0.112",
4
4
  "description": "A minimal, fast Solid server",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -9,7 +9,7 @@ import { checkAccess, getRequiredMode } from '../wac/checker.js';
9
9
  import { AccessMode } from '../wac/parser.js';
10
10
  import * as storage from '../storage/filesystem.js';
11
11
  import { getEffectiveUrlPath } from '../utils/url.js';
12
- import { generateDatabrowserHtml, generateModuleDatabrowserHtml, generateSolidosUiHtml } from '../mashlib/index.js';
12
+ import { generateDatabrowserHtml, generateModuleDatabrowserHtml } from '../mashlib/index.js';
13
13
 
14
14
  /**
15
15
  * Build a resource URL for WAC checking, normalizing path-based pod access
@@ -148,12 +148,9 @@ export function handleUnauthorized(request, reply, isAuthenticated, wacAllow, au
148
148
  // If mashlib is enabled, serve mashlib instead of static error page
149
149
  // Mashlib has built-in login functionality via panes.runDataBrowser()
150
150
  if (request.mashlibEnabled) {
151
- // Use SolidOS UI if enabled, ES module if configured, otherwise classic mashlib
152
- const html = request.solidosUiEnabled
153
- ? generateSolidosUiHtml()
154
- : request.mashlibModule
155
- ? generateModuleDatabrowserHtml(request.mashlibModule)
156
- : generateDatabrowserHtml(request.url, request.mashlibCdn ? request.mashlibVersion : null);
151
+ const html = request.mashlibModule
152
+ ? generateModuleDatabrowserHtml(request.mashlibModule)
153
+ : generateDatabrowserHtml(request.url, request.mashlibCdn ? request.mashlibVersion : null);
157
154
  return reply.code(statusCode).type('text/html').send(html);
158
155
  }
159
156
  return reply.code(statusCode).type('text/html').send(getErrorPage(statusCode, isAuthenticated, request));
package/src/config.js CHANGED
@@ -43,9 +43,6 @@ export const defaults = {
43
43
  mashlibVersion: '2.0.0',
44
44
  mashlibModule: false,
45
45
 
46
- // SolidOS UI (modern Nextcloud-style interface)
47
- solidosUi: false,
48
-
49
46
  // Git HTTP backend
50
47
  git: false,
51
48
 
@@ -137,7 +134,6 @@ const envMap = {
137
134
  JSS_MASHLIB_CDN: 'mashlibCdn',
138
135
  JSS_MASHLIB_VERSION: 'mashlibVersion',
139
136
  JSS_MASHLIB_MODULE: 'mashlibModule',
140
- JSS_SOLIDOS_UI: 'solidosUi',
141
137
  JSS_GIT: 'git',
142
138
  JSS_NOSTR: 'nostr',
143
139
  JSS_NOSTR_PATH: 'nostrPath',
@@ -331,8 +327,7 @@ export function printConfig(config) {
331
327
  console.log(` Notifications: ${config.notifications}`);
332
328
  console.log(` IdP: ${config.idp ? (config.idpIssuer || 'enabled') : 'disabled'}`);
333
329
  console.log(` Subdomains: ${config.subdomains ? (config.baseDomain || 'enabled') : 'disabled'}`);
334
- console.log(` Mashlib: ${config.mashlibModule ? `module (${config.mashlibModule})` : config.mashlibCdn ? `CDN v${config.mashlibVersion}` : config.mashlib ? 'local' : 'disabled'}`);
335
- console.log(` SolidOS UI: ${config.solidosUi ? 'enabled' : 'disabled'}`);
330
+ console.log(` Mashlib: ${config.mashlibModule ? `module (${config.mashlibModule})` : config.mashlibCdn ? `CDN v${config.mashlibVersion}` : 'disabled'}`);
336
331
  if (config.pay) {
337
332
  console.log(` Pay: ${config.payCost} sat/req`);
338
333
  if (config.payToken) console.log(` Token: ${config.payToken} @ ${config.payRate} sat/token`);
@@ -15,7 +15,7 @@ import {
15
15
  } from '../rdf/conneg.js';
16
16
  import { emitChange } from '../notifications/events.js';
17
17
  import { checkIfMatch, checkIfNoneMatchForGet, checkIfNoneMatchForWrite } from '../utils/conditional.js';
18
- import { generateDatabrowserHtml, generateModuleDatabrowserHtml, generateSolidosUiHtml, shouldServeMashlib } from '../mashlib/index.js';
18
+ import { generateDatabrowserHtml, generateModuleDatabrowserHtml, shouldServeMashlib } from '../mashlib/index.js';
19
19
 
20
20
  /**
21
21
  * Live reload script - injected into HTML when --live-reload is enabled
@@ -230,12 +230,9 @@ export async function handleGet(request, reply) {
230
230
 
231
231
  // Check if we should serve Mashlib data browser for containers
232
232
  if (shouldServeMashlib(request, request.mashlibEnabled, 'application/ld+json')) {
233
- // Use SolidOS UI if enabled, ES module if configured, otherwise classic mashlib
234
- const html = request.solidosUiEnabled
235
- ? generateSolidosUiHtml()
236
- : request.mashlibModule
237
- ? generateModuleDatabrowserHtml(request.mashlibModule)
238
- : generateDatabrowserHtml(resourceUrl, request.mashlibCdn ? request.mashlibVersion : null);
233
+ const html = request.mashlibModule
234
+ ? generateModuleDatabrowserHtml(request.mashlibModule)
235
+ : generateDatabrowserHtml(resourceUrl, request.mashlibCdn ? request.mashlibVersion : null);
239
236
  const headers = getAllHeaders({
240
237
  isContainer: true,
241
238
  etag: stats.etag,
@@ -309,12 +306,9 @@ export async function handleGet(request, reply) {
309
306
  // Check if we should serve Mashlib data browser
310
307
  // Only for RDF resources when Accept: text/html is requested
311
308
  if (shouldServeMashlib(request, request.mashlibEnabled, storedContentType)) {
312
- // Use SolidOS UI if enabled, ES module if configured, otherwise classic mashlib
313
- const html = request.solidosUiEnabled
314
- ? generateSolidosUiHtml()
315
- : request.mashlibModule
316
- ? generateModuleDatabrowserHtml(request.mashlibModule)
317
- : generateDatabrowserHtml(resourceUrl, request.mashlibCdn ? request.mashlibVersion : null);
309
+ const html = request.mashlibModule
310
+ ? generateModuleDatabrowserHtml(request.mashlibModule)
311
+ : generateDatabrowserHtml(resourceUrl, request.mashlibCdn ? request.mashlibVersion : null);
318
312
  const headers = getAllHeaders({
319
313
  isContainer: false,
320
314
  etag: stats.etag,
package/src/server.js CHANGED
@@ -62,14 +62,11 @@ export function createServer(options = {}) {
62
62
  const subdomainsEnabled = options.subdomains ?? false;
63
63
  const baseDomain = options.baseDomain || null;
64
64
  // Mashlib data browser is OFF by default
65
- // mashlibCdn: if true, load from CDN; if false, serve locally
66
- // mashlibModule: URL to ES module entry point (alternative to classic mashlib)
65
+ // mashlibCdn: load from CDN; mashlibModule: URL to ES module entry point
67
66
  const mashlibModule = options.mashlibModule ?? false;
68
- const mashlibEnabled = options.mashlib || !!mashlibModule;
69
67
  const mashlibCdn = options.mashlibCdn ?? false;
68
+ const mashlibEnabled = mashlibCdn || !!mashlibModule;
70
69
  const mashlibVersion = options.mashlibVersion ?? '2.0.0';
71
- // SolidOS UI (modern Nextcloud-style interface) - requires mashlib
72
- const solidosUiEnabled = options.solidosUi ?? false;
73
70
  // Git HTTP backend is OFF by default - enables clone/push via git protocol
74
71
  const gitEnabled = options.git ?? false;
75
72
  // Nostr relay is OFF by default
@@ -179,7 +176,6 @@ export function createServer(options = {}) {
179
176
  fastify.decorateRequest('mashlibCdn', null);
180
177
  fastify.decorateRequest('mashlibVersion', null);
181
178
  fastify.decorateRequest('mashlibModule', null);
182
- fastify.decorateRequest('solidosUiEnabled', null);
183
179
  fastify.decorateRequest('defaultQuota', null);
184
180
  fastify.decorateRequest('config', null);
185
181
  fastify.decorateRequest('liveReloadEnabled', null);
@@ -193,7 +189,6 @@ export function createServer(options = {}) {
193
189
  request.mashlibCdn = mashlibCdn;
194
190
  request.mashlibVersion = mashlibVersion;
195
191
  request.mashlibModule = mashlibModule;
196
- request.solidosUiEnabled = solidosUiEnabled;
197
192
  request.defaultQuota = defaultQuota;
198
193
  request.config = { public: options.public, readOnly: options.readOnly };
199
194
  request.liveReloadEnabled = liveReloadEnabled;
@@ -410,7 +405,7 @@ export function createServer(options = {}) {
410
405
  // Authorization hook - check WAC permissions
411
406
  // Skip for pod creation endpoint (needs special handling)
412
407
  fastify.addHook('preHandler', async (request, reply) => {
413
- // Skip auth for pod creation, OPTIONS, IdP routes, mashlib, solidos-ui, well-known, notifications, nostr, git, and AP
408
+ // Skip auth for pod creation, OPTIONS, IdP routes, mashlib, well-known, notifications, nostr, git, and AP
414
409
  const mashlibPaths = ['/mashlib.min.js', '/mash.css', '/841.mashlib.min.js'];
415
410
  const apPaths = ['/inbox', '/profile/card/inbox', '/profile/card/outbox', '/profile/card/followers', '/profile/card/following',
416
411
  '/api/v1/apps', '/api/v1/instance', '/api/v1/accounts/verify_credentials',
@@ -424,7 +419,6 @@ export function createServer(options = {}) {
424
419
  request.method === 'OPTIONS' ||
425
420
  request.url.startsWith('/idp/') ||
426
421
  request.url.startsWith('/.well-known/') ||
427
- request.url.startsWith('/solidos-ui/') ||
428
422
  (nostrEnabled && request.url.startsWith(nostrPath)) ||
429
423
  (gitEnabled && isGitRequest(request.url)) ||
430
424
  (activitypubEnabled && apPaths.some(p => request.url === p || request.url.startsWith(p + '?'))) ||
@@ -464,72 +458,15 @@ export function createServer(options = {}) {
464
458
  }
465
459
  }, handleCreatePod);
466
460
 
467
- // Mashlib static files (served from root like NSS does)
468
- if (mashlibEnabled) {
469
- if (mashlibCdn) {
470
- // CDN mode: redirect chunk requests to CDN
471
- // Mashlib uses code splitting, so it loads chunks like 789.mashlib.min.js
472
- const cdnBase = `https://unpkg.com/mashlib@${mashlibVersion}/dist`;
473
- const chunkPattern = /^\/\d+\.mashlib\.min\.js(\.map)?$/;
474
-
475
- fastify.addHook('onRequest', async (request, reply) => {
476
- if (chunkPattern.test(request.url)) {
477
- const filename = request.url.split('/').pop();
478
- return reply.redirect(302, `${cdnBase}/${filename}`);
479
- }
480
- });
481
- } else {
482
- // Local mode: serve from local files
483
- const mashlibDir = join(__dirname, 'mashlib-local', 'dist');
484
- const mashlibFiles = {
485
- '/mashlib.min.js': { file: 'mashlib.min.js', type: 'application/javascript' },
486
- '/mashlib.min.js.map': { file: 'mashlib.min.js.map', type: 'application/json' },
487
- '/mash.css': { file: 'mash.css', type: 'text/css' },
488
- '/mash.css.map': { file: 'mash.css.map', type: 'application/json' },
489
- '/841.mashlib.min.js': { file: '841.mashlib.min.js', type: 'application/javascript' },
490
- '/841.mashlib.min.js.map': { file: '841.mashlib.min.js.map', type: 'application/json' }
491
- };
492
-
493
- for (const [path, config] of Object.entries(mashlibFiles)) {
494
- fastify.get(path, async (request, reply) => {
495
- try {
496
- const content = await readFile(join(mashlibDir, config.file));
497
- return reply.type(config.type).send(content);
498
- } catch {
499
- return reply.code(404).send({ error: 'Not Found' });
500
- }
501
- });
502
- }
503
- }
504
- }
461
+ // Mashlib CDN mode: redirect chunk requests to CDN
462
+ if (mashlibEnabled && mashlibCdn) {
463
+ const cdnBase = `https://unpkg.com/mashlib@${mashlibVersion}/dist`;
464
+ const chunkPattern = /^\/\d+\.mashlib\.min\.js(\.map)?$/;
505
465
 
506
- // SolidOS UI static files (modern Nextcloud-style interface)
507
- // Serves from /solidos-ui/* - requires mashlib to be enabled as well
508
- if (solidosUiEnabled && mashlibEnabled) {
509
- const solidosUiDir = join(__dirname, 'mashlib-local', 'dist', 'solidos-ui');
510
-
511
- // Serve all files under /solidos-ui/* path
512
- fastify.get('/solidos-ui/*', async (request, reply) => {
513
- try {
514
- // Get the path after /solidos-ui/
515
- const filePath = request.url.replace('/solidos-ui/', '').split('?')[0];
516
- const fullPath = join(solidosUiDir, filePath);
517
-
518
- // Determine content type based on extension
519
- const ext = filePath.split('.').pop()?.toLowerCase();
520
- const contentTypes = {
521
- 'js': 'application/javascript',
522
- 'css': 'text/css',
523
- 'map': 'application/json',
524
- 'html': 'text/html'
525
- };
526
- const contentType = contentTypes[ext] || 'application/octet-stream';
527
-
528
- const content = await readFile(fullPath);
529
- return reply.type(contentType).send(content);
530
- } catch (err) {
531
- request.log.error(err, 'Failed to serve solidos-ui file');
532
- return reply.code(404).send({ error: 'Not Found' });
466
+ fastify.addHook('onRequest', async (request, reply) => {
467
+ if (chunkPattern.test(request.url)) {
468
+ const filename = request.url.split('/').pop();
469
+ return reply.redirect(302, `${cdnBase}/${filename}`);
533
470
  }
534
471
  });
535
472
  }