OneDrive
Lightweight, dependency-free Microsoft Graph OneDrive emulator for parlel-pool.
Default port: 4622
Quick Start
Start the server in-process:
import { OnedriveServer } from "./services/onedrive/src/server.js";
const server = new OnedriveServer(4622);
await server.start();
Connect with the real @microsoft/microsoft-graph-client client by pointing its Graph base URL at the emulator:
import { Client } from "@microsoft/microsoft-graph-client";
const client = Client.init({
baseUrl: "http://127.0.0.1:4622/v1.0",
authProvider: (done) => done(null, "parlel-token"),
});
const root = await client.api("/me/drive/root").get();
await client.api("/me/drive/root:/hello.txt:/content").put("hello");
Health and reset endpoints:
curl http://127.0.0.1:4622/_parlel/health
curl -X POST http://127.0.0.1:4622/_parlel/reset
Implemented Operations
Discovery and users:
GET /,GET /v1.0,GET /betaGET /meGET /users/{user-id}GET /me/drive,GET /users/{user-id}/driveGET /me/drives,GET /drives,GET /drives/{drive-id}
Drive item CRUD and addressing:
GET /me/drive/rootGET /me/drive/items/{item-id}PATCH /me/drive/items/{item-id}DELETE /me/drive/items/{item-id}GET /me/drive/special/{name}GET /me/drive/root:/{path}:GET /me/drive/items/{item-id}:/{path}:
Children and OData collection options:
GET /me/drive/root/childrenPOST /me/drive/root/childrenGET /me/drive/items/{item-id}/childrenPOST /me/drive/items/{item-id}/childrenGET /me/drive/items/{item-id}/children/{child-id-or-name}- Supports
$top,$skip,$count,$orderby,$select,$filter,$search,$expand=children, and$expand=permissionswhere applicable.
Content and uploads:
GET /me/drive/items/{item-id}/contentPUT /me/drive/items/{item-id}/contentGET /me/drive/root:/{path}:/contentPUT /me/drive/root:/{path}:/contentPOST /me/drive/items/{item-id}/createUploadSessionPUT {uploadUrl}withContent-RangeDELETE {uploadUrl}
Actions and collections:
POST /me/drive/items/{item-id}/copyGET /me/drive/operations/{operation-id}GET /me/drive/items/{item-id}/search(q='term')GET /me/drive/items/{item-id}/deltaGET /me/drive/recentGET /me/drive/sharedWithMeGET /me/drive/followingPOST /me/drive/items/{item-id}/followPOST /me/drive/items/{item-id}/unfollowPOST /me/drive/items/{item-id}/previewPOST /me/drive/items/{item-id}/restore
Permissions and sharing:
GET /me/drive/items/{item-id}/permissionsPOST /me/drive/items/{item-id}/permissionsGET /me/drive/items/{item-id}/permissions/{permission-id}PATCH /me/drive/items/{item-id}/permissions/{permission-id}DELETE /me/drive/items/{item-id}/permissions/{permission-id}POST /me/drive/items/{item-id}/invitePOST /me/drive/items/{item-id}/createLinkGET /shares/{share-id}GET /shares/{share-id}/driveItem
Thumbnails:
GET /me/drive/items/{item-id}/thumbnailsGET /me/drive/items/{item-id}/thumbnails/{set-id}GET /me/drive/items/{item-id}/thumbnails/{set-id}/{size}GET /me/drive/items/{item-id}/thumbnails/{set-id}/{size}/content
Subscriptions and batch:
GET /subscriptionsPOST /subscriptionsGET /subscriptions/{subscription-id}PATCH /subscriptions/{subscription-id}DELETE /subscriptions/{subscription-id}POST /$batch
Parlel control endpoints:
GET /_parlel/healthPOST /_parlel/reset
The same routes are accepted under /beta and under /drives/{drive-id} where Graph exposes drive-scoped item routes.
Support Matrix
| Feature | Status | Notes |
|---|---|---|
| Microsoft Graph REST shape | Supported | JSON resources, OData collections, Graph error envelopes. |
@microsoft/microsoft-graph-client request builders | Supported | Use Client.init({ baseUrl: "http://127.0.0.1:4622/v1.0" }). |
| In-memory drive/items/permissions/subscriptions | Supported | Ephemeral; reset with POST /_parlel/reset. |
| Small file upload/download | Supported | PUT/GET .../content. |
| Path-addressed upload/download | Supported | root:/path:/content. |
| Resumable upload sessions | Supported | Local upload URL, Content-Range, partial 202, final item response. |
| Async copy operation | Supported | Completes immediately and can be polled. |
| OData query options | Supported | Minimal $top, $skip, $count, $orderby, $select, $filter, $search. |
| Thumbnails | Supported | Deterministic fake metadata/content. |
| Webhook subscriptions | Supported | Stored only; no outbound webhook delivery. |
| Authentication/authorization | Intentionally unsupported | Tokens are ignored for zero-cost local testing. |
| Real Microsoft storage, sharing emails, virus scanning, Office conversion | Intentionally unsupported | No external side effects. |
| Multi-tenant persistence | Intentionally unsupported | Single local user and drive only. |
Error Shapes
Errors use Microsoft Graph-style envelopes:
{
"error": {
"code": "itemNotFound",
"message": "Item not found",
"innerError": {
"date": "2026-06-11T00:00:00.000Z",
"request-id": "req_...",
"client-request-id": "..."
}
}
}
Common returned errors:
| Status | Code | When |
|---|---|---|
400 | invalidRequest | Invalid JSON, missing name, folder content download, root rename/delete, missing Content-Range. |
404 | itemNotFound | Missing drive item, permission, share, operation, upload session, or special folder. |
404 | Request_ResourceNotFound | Unknown route or user. |
405 | Request_BadRequest | Unsupported method for an existing route. |
409 | nameAlreadyExists | Child create conflict without @microsoft.graph.conflictBehavior. |
500 | InternalServerError | Unexpected emulator failures. |
Configuration — test.env
Copy these into your test.env (used by the bridge sidecar flow). Tokens are Parlel's seeded test credentials — any non-empty value is accepted by the emulator, so you rarely need to change them. Swap in real credentials only when pointing at the live service in prod.env.
ONEDRIVE_EMULATOR_HOST=http://parlel-bridge:4622
MICROSOFT_GRAPH_BASE_URL=http://parlel-bridge:4622/v1.0
AZURE_TENANT_ID=parlel
AZURE_CLIENT_ID=parlel
AZURE_CLIENT_SECRET=parlel
<!-- parlel:testenv:end -->