javascript-solid-server 0.0.9 → 0.0.11
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/.claude/settings.local.json +6 -1
- package/README.md +159 -11
- package/benchmark.js +145 -249
- package/bin/jss.js +208 -0
- package/package.json +21 -5
- package/src/config.js +185 -0
- package/src/handlers/resource.js +103 -34
- package/src/patch/sparql-update.js +401 -0
- package/src/server.js +21 -10
- package/src/utils/conditional.js +153 -0
- package/test/conditional.test.js +250 -0
- package/test/conformance.test.js +349 -0
- package/test/sparql-update.test.js +219 -0
|
@@ -15,7 +15,12 @@
|
|
|
15
15
|
"Bash(npm test:*)",
|
|
16
16
|
"Bash(git add:*)",
|
|
17
17
|
"WebFetch(domain:solid.github.io)",
|
|
18
|
-
"Bash(node:*)"
|
|
18
|
+
"Bash(node:*)",
|
|
19
|
+
"WebFetch(domain:solidservers.org)",
|
|
20
|
+
"WebFetch(domain:solid-contrib.github.io)",
|
|
21
|
+
"Bash(git clone:*)",
|
|
22
|
+
"Bash(chmod:*)",
|
|
23
|
+
"Bash(JSS_PORT=4000 JSS_CONNEG=true node bin/jss.js:*)"
|
|
19
24
|
]
|
|
20
25
|
}
|
|
21
26
|
}
|
package/README.md
CHANGED
|
@@ -35,12 +35,34 @@ const server = createServer();
|
|
|
35
35
|
const serverWithConneg = createServer({ conneg: true });
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
+
## Performance
|
|
39
|
+
|
|
40
|
+
This server is designed for speed. Benchmark results on a typical development machine:
|
|
41
|
+
|
|
42
|
+
| Operation | Requests/sec | Avg Latency | p99 Latency |
|
|
43
|
+
|-----------|-------------|-------------|-------------|
|
|
44
|
+
| GET resource | 5,400+ | 1.2ms | 3ms |
|
|
45
|
+
| GET container | 4,700+ | 1.6ms | 3ms |
|
|
46
|
+
| PUT (write) | 5,700+ | 1.1ms | 2ms |
|
|
47
|
+
| POST (create) | 5,200+ | 1.3ms | 3ms |
|
|
48
|
+
| OPTIONS | 10,000+ | 0.4ms | 1ms |
|
|
49
|
+
|
|
50
|
+
Run benchmarks yourself:
|
|
51
|
+
```bash
|
|
52
|
+
npm run benchmark
|
|
53
|
+
```
|
|
54
|
+
|
|
38
55
|
## Features
|
|
39
56
|
|
|
40
|
-
### Implemented (v0.0.
|
|
57
|
+
### Implemented (v0.0.11)
|
|
41
58
|
|
|
42
59
|
- **LDP CRUD Operations** - GET, PUT, POST, DELETE, HEAD
|
|
43
60
|
- **N3 Patch** - Solid's native patch format for RDF updates
|
|
61
|
+
- **SPARQL Update** - Standard SPARQL UPDATE protocol for PATCH
|
|
62
|
+
- **Conditional Requests** - If-Match/If-None-Match headers (304, 412)
|
|
63
|
+
- **CLI & Config** - `jss` command with config file/env var support
|
|
64
|
+
- **SSL/TLS** - HTTPS support with certificate configuration
|
|
65
|
+
- **WebSocket Notifications** - Real-time updates via solid-0.1 protocol (SolidOS compatible)
|
|
44
66
|
- **Container Management** - Create, list, and manage containers
|
|
45
67
|
- **Multi-user Pods** - Create pods at `/<username>/`
|
|
46
68
|
- **WebID Profiles** - JSON-LD structured data in HTML at pod root
|
|
@@ -72,18 +94,75 @@ const serverWithConneg = createServer({ conneg: true });
|
|
|
72
94
|
|
|
73
95
|
```bash
|
|
74
96
|
npm install
|
|
97
|
+
|
|
98
|
+
# Or install globally
|
|
99
|
+
npm install -g javascript-solid-server
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Quick Start
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
# Initialize configuration (interactive)
|
|
106
|
+
jss init
|
|
107
|
+
|
|
108
|
+
# Start server
|
|
109
|
+
jss start
|
|
110
|
+
|
|
111
|
+
# Or with options
|
|
112
|
+
jss start --port 8443 --ssl-key ./key.pem --ssl-cert ./cert.pem
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### CLI Commands
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
jss start [options] # Start the server
|
|
119
|
+
jss init [options] # Initialize configuration
|
|
120
|
+
jss --help # Show help
|
|
75
121
|
```
|
|
76
122
|
|
|
77
|
-
###
|
|
123
|
+
### Start Options
|
|
124
|
+
|
|
125
|
+
| Option | Description | Default |
|
|
126
|
+
|--------|-------------|---------|
|
|
127
|
+
| `-p, --port <n>` | Port to listen on | 3000 |
|
|
128
|
+
| `-h, --host <addr>` | Host to bind to | 0.0.0.0 |
|
|
129
|
+
| `-r, --root <path>` | Data directory | ./data |
|
|
130
|
+
| `-c, --config <file>` | Config file path | - |
|
|
131
|
+
| `--ssl-key <path>` | SSL private key (PEM) | - |
|
|
132
|
+
| `--ssl-cert <path>` | SSL certificate (PEM) | - |
|
|
133
|
+
| `--conneg` | Enable Turtle support | false |
|
|
134
|
+
| `--notifications` | Enable WebSocket | false |
|
|
135
|
+
| `-q, --quiet` | Suppress logs | false |
|
|
136
|
+
|
|
137
|
+
### Environment Variables
|
|
138
|
+
|
|
139
|
+
All options can be set via environment variables with `JSS_` prefix:
|
|
78
140
|
|
|
79
141
|
```bash
|
|
80
|
-
|
|
81
|
-
|
|
142
|
+
export JSS_PORT=8443
|
|
143
|
+
export JSS_SSL_KEY=/path/to/key.pem
|
|
144
|
+
export JSS_SSL_CERT=/path/to/cert.pem
|
|
145
|
+
export JSS_CONNEG=true
|
|
146
|
+
jss start
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Config File
|
|
150
|
+
|
|
151
|
+
Create `config.json`:
|
|
82
152
|
|
|
83
|
-
|
|
84
|
-
|
|
153
|
+
```json
|
|
154
|
+
{
|
|
155
|
+
"port": 8443,
|
|
156
|
+
"root": "./data",
|
|
157
|
+
"sslKey": "./ssl/key.pem",
|
|
158
|
+
"sslCert": "./ssl/cert.pem",
|
|
159
|
+
"conneg": true,
|
|
160
|
+
"notifications": true
|
|
161
|
+
}
|
|
85
162
|
```
|
|
86
163
|
|
|
164
|
+
Then: `jss start --config config.json`
|
|
165
|
+
|
|
87
166
|
### Creating a Pod
|
|
88
167
|
|
|
89
168
|
```bash
|
|
@@ -129,6 +208,44 @@ curl -X PATCH http://localhost:3000/alice/public/data.json \
|
|
|
129
208
|
solid:inserts { <#data> <http://example.org/name> "Updated" }.'
|
|
130
209
|
```
|
|
131
210
|
|
|
211
|
+
### PATCH with SPARQL Update
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
curl -X PATCH http://localhost:3000/alice/public/data.json \
|
|
215
|
+
-H "Authorization: Bearer YOUR_TOKEN" \
|
|
216
|
+
-H "Content-Type: application/sparql-update" \
|
|
217
|
+
-d 'PREFIX ex: <http://example.org/>
|
|
218
|
+
DELETE DATA { <#data> ex:value 42 } ;
|
|
219
|
+
INSERT DATA { <#data> ex:value 43 }'
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Conditional Requests
|
|
223
|
+
|
|
224
|
+
Use `If-Match` for safe updates (optimistic concurrency):
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
# Get current ETag
|
|
228
|
+
ETAG=$(curl -sI http://localhost:3000/alice/public/data.json | grep -i etag | awk '{print $2}')
|
|
229
|
+
|
|
230
|
+
# Update only if ETag matches
|
|
231
|
+
curl -X PUT http://localhost:3000/alice/public/data.json \
|
|
232
|
+
-H "Authorization: Bearer YOUR_TOKEN" \
|
|
233
|
+
-H "Content-Type: application/ld+json" \
|
|
234
|
+
-H "If-Match: $ETAG" \
|
|
235
|
+
-d '{"@id": "#data", "http://example.org/value": 100}'
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Use `If-None-Match: *` for create-only semantics:
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
# Create only if resource doesn't exist (returns 412 if it does)
|
|
242
|
+
curl -X PUT http://localhost:3000/alice/public/new-resource.json \
|
|
243
|
+
-H "Authorization: Bearer YOUR_TOKEN" \
|
|
244
|
+
-H "Content-Type: application/ld+json" \
|
|
245
|
+
-H "If-None-Match: *" \
|
|
246
|
+
-d '{"@id": "#new"}'
|
|
247
|
+
```
|
|
248
|
+
|
|
132
249
|
## Pod Structure
|
|
133
250
|
|
|
134
251
|
```
|
|
@@ -171,18 +288,42 @@ curl -H "Authorization: DPoP ACCESS_TOKEN" \
|
|
|
171
288
|
|
|
172
289
|
```javascript
|
|
173
290
|
createServer({
|
|
174
|
-
logger: true,
|
|
175
|
-
conneg: false
|
|
291
|
+
logger: true, // Enable Fastify logging (default: true)
|
|
292
|
+
conneg: false, // Enable content negotiation (default: false)
|
|
293
|
+
notifications: false // Enable WebSocket notifications (default: false)
|
|
176
294
|
});
|
|
177
295
|
```
|
|
178
296
|
|
|
297
|
+
### WebSocket Notifications
|
|
298
|
+
|
|
299
|
+
Enable real-time notifications for resource changes:
|
|
300
|
+
|
|
301
|
+
```javascript
|
|
302
|
+
const server = createServer({ notifications: true });
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
Clients discover the WebSocket URL via the `Updates-Via` header:
|
|
306
|
+
|
|
307
|
+
```bash
|
|
308
|
+
curl -I http://localhost:3000/alice/public/
|
|
309
|
+
# Updates-Via: ws://localhost:3000/.notifications
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
Protocol (solid-0.1, compatible with SolidOS):
|
|
313
|
+
```
|
|
314
|
+
Server: protocol solid-0.1
|
|
315
|
+
Client: sub http://localhost:3000/alice/public/data.json
|
|
316
|
+
Server: ack http://localhost:3000/alice/public/data.json
|
|
317
|
+
Server: pub http://localhost:3000/alice/public/data.json (on change)
|
|
318
|
+
```
|
|
319
|
+
|
|
179
320
|
## Running Tests
|
|
180
321
|
|
|
181
322
|
```bash
|
|
182
323
|
npm test
|
|
183
324
|
```
|
|
184
325
|
|
|
185
|
-
Currently passing: **
|
|
326
|
+
Currently passing: **163 tests** (including 27 conformance tests)
|
|
186
327
|
|
|
187
328
|
## Project Structure
|
|
188
329
|
|
|
@@ -208,12 +349,18 @@ src/
|
|
|
208
349
|
├── webid/
|
|
209
350
|
│ └── profile.js # WebID generation
|
|
210
351
|
├── patch/
|
|
211
|
-
│
|
|
352
|
+
│ ├── n3-patch.js # N3 Patch support
|
|
353
|
+
│ └── sparql-update.js # SPARQL Update support
|
|
354
|
+
├── notifications/
|
|
355
|
+
│ ├── index.js # WebSocket plugin
|
|
356
|
+
│ ├── events.js # Event emitter
|
|
357
|
+
│ └── websocket.js # solid-0.1 protocol
|
|
212
358
|
├── rdf/
|
|
213
359
|
│ ├── turtle.js # Turtle <-> JSON-LD
|
|
214
360
|
│ └── conneg.js # Content negotiation
|
|
215
361
|
└── utils/
|
|
216
|
-
|
|
362
|
+
├── url.js # URL utilities
|
|
363
|
+
└── conditional.js # If-Match/If-None-Match
|
|
217
364
|
```
|
|
218
365
|
|
|
219
366
|
## Dependencies
|
|
@@ -221,6 +368,7 @@ src/
|
|
|
221
368
|
Minimal dependencies for a fast, secure server:
|
|
222
369
|
|
|
223
370
|
- **fastify** - High-performance HTTP server
|
|
371
|
+
- **@fastify/websocket** - WebSocket support for notifications
|
|
224
372
|
- **fs-extra** - Enhanced file operations
|
|
225
373
|
- **jose** - JWT/JWK handling for Solid-OIDC
|
|
226
374
|
- **n3** - Turtle parsing (only used when conneg enabled)
|