SQLite-backed (Microsoft.Data.Sqlite, WAL) minimal API storing NestRecord
metadata plus the .nest archive as a BLOB. Endpoints: GET/POST /api/nests,
GET /api/nests/{id}[/file], PUT /api/nests/{id}/file, PUT
/api/nests/{id}/metadata, DELETE /api/nests/{id}, GET /healthz. Multipart
upload contract matches RemoteNestRepository (metadata JSON part + file
part). Added to OpenNest.sln, builds standalone on Linux. Dockerfile
publishes to a runtime image listening on :8090 with a /app/data volume
for the SQLite file. docs/nest-storage.md documents the wire contract,
endpoints and deployment.
Full curl round trip verified manually against a running instance:
upload (server-assigned id + computed fileSize), list, get, byte-exact
file download, metadata-only update (archive unchanged), file update
(new archive persisted), 404s for unknown ids, delete, post-delete 404.
3.6 KiB
Nest storage: File mode vs. Database mode
The desktop app can save nests two ways:
- File mode (default, unchanged behavior): Save/Save As write a
.nestZIP archive to disk via the normal file dialog. See nest-file-format.md. - Database mode: Save uploads the nest to a central
OpenNest.Serverinstance shared by every shop PC, instead of writing a local file. A separate File > Export .nest... command is always available (in both modes) for producing a local file to share or back up.
The mode and server address are stored per-PC at %APPDATA%\OpenNest\storage.json
(OpenNest.Data.NestStorageSettings), defaulting to File mode so existing
installs are unaffected until an operator opts in via File > Storage Mode....
Wire contract
OpenNest.Data.NestRecord is the metadata DTO shared by the client
(RemoteNestRepository) and the server (OpenNest.Server). JSON is camelCase
with enums serialized as strings (JsonSerializerDefaults.Web +
JsonStringEnumConverter(JsonNamingPolicy.CamelCase)), matching the rest of
OpenNest.Data's local JSON stores.
| Field | Type | Notes |
|---|---|---|
id |
guid | Client-generated on first save; kept on updates. |
name |
string | |
customer |
string | |
dateCreated / dateModified |
datetime | Set by the client from the nest's own metadata. |
material |
string | |
thickness |
number | |
status |
"quote" | "toBeCut" | "hasBeenCut" |
Default quote. |
plateCount / partCount |
integer | Computed client-side at save time (non-cutoff parts only). |
comments |
string | |
madeBy |
string | |
fileSize |
integer | Server-computed; ignored on upload. |
savedAt |
datetime | Server-computed; ignored on upload. |
Endpoints
| Method | Path | Body | Response |
|---|---|---|---|
| GET | /healthz |
— | { "status": "ok" } |
| GET | /api/nests |
— | NestRecord[], newest savedAt first |
| GET | /api/nests/{id} |
— | NestRecord or 404 |
| GET | /api/nests/{id}/file |
— | .nest archive bytes (application/zip) or 404 |
| POST | /api/nests |
multipart: metadata (JSON NestRecord) + file (.nest bytes) |
NestRecord with server-assigned id when the client sends an empty guid |
| PUT | /api/nests/{id}/file |
multipart: metadata + file |
Updated NestRecord, or 404 if id is unknown |
| PUT | /api/nests/{id}/metadata |
JSON NestRecord |
Updated NestRecord (archive untouched), or 404 |
| DELETE | /api/nests/{id} |
— | 204, or 404 |
There is no authentication; this is a LAN-only service. Do not expose it outside the shop network without adding one.
Storage
OpenNest.Server.NestDatabase uses SQLite (Microsoft.Data.Sqlite) with
journal_mode=WAL. Each row holds the metadata columns plus the .nest
archive as a BLOB. The database file path comes from --database=<path>,
then OPENNEST_DB, defaulting to ./data/nests.db.
Running
Locally:
dotnet run --project OpenNest.Server/OpenNest.Server.csproj
Listens on ASPNETCORE_URLS (default Kestrel ports) unless overridden.
Docker (built from the repository root so it can see OpenNest.Data):
docker build -f OpenNest.Server/Dockerfile -t opennest-server .
docker run -d -p 8090:8090 -v opennest-data:/app/data opennest-server
The image listens on :8090 and stores nests.db under /app/data, which
should be a named volume or bind mount so nests survive container recreation.
Point the desktop app's File > Storage Mode... server URL at
http://<host>:8090 (no trailing slash required; RemoteNestRepository
trims it).