microsoft-onedrive-mock 1.0.2 → 1.0.3
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/dist/index.js +2 -0
- package/dist/routes/v1.js +157 -0
- package/dist/store.d.ts +13 -0
- package/dist/store.js +35 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -85,6 +85,8 @@ const createApp = (config = {}) => {
|
|
|
85
85
|
// Auth Middleware
|
|
86
86
|
const validTokens = ['valid-token', 'another-valid-token'];
|
|
87
87
|
app.use((req, res, next) => {
|
|
88
|
+
if (req.path.startsWith('/v1.0/upload-sessions'))
|
|
89
|
+
return next();
|
|
88
90
|
const authHeaderVal = req.headers.authorization;
|
|
89
91
|
const authHeader = Array.isArray(authHeaderVal) ? authHeaderVal[0] : authHeaderVal;
|
|
90
92
|
if (!authHeader) {
|
package/dist/routes/v1.js
CHANGED
|
@@ -224,6 +224,36 @@ const createV1Router = () => {
|
|
|
224
224
|
res.send(file.content);
|
|
225
225
|
}
|
|
226
226
|
});
|
|
227
|
+
// Path-based Addressing
|
|
228
|
+
app.get('/v1.0/me/drive/items/:parentId\\:/:filename', (req, res) => {
|
|
229
|
+
const params = req.params;
|
|
230
|
+
const parentId = params.parentId;
|
|
231
|
+
let filename = params.filename;
|
|
232
|
+
if (filename.endsWith(':'))
|
|
233
|
+
filename = filename.slice(0, -1);
|
|
234
|
+
filename = decodeURIComponent(filename);
|
|
235
|
+
const parentObj = store_1.driveStore.getItem(parentId) || (parentId === 'root' ? store_1.driveStore.getItem('root') : null);
|
|
236
|
+
if (!parentObj) {
|
|
237
|
+
return res.status(404).json({ error: { code: "itemNotFound", message: "Parent not found" } });
|
|
238
|
+
}
|
|
239
|
+
const child = store_1.driveStore.getItemByName(parentId, filename);
|
|
240
|
+
if (!child) {
|
|
241
|
+
return res.status(404).json({ error: { code: "itemNotFound", message: "Item not found" } });
|
|
242
|
+
}
|
|
243
|
+
res.status(200).json(applySelect(child, req.query.$select));
|
|
244
|
+
});
|
|
245
|
+
app.get('/v1.0/me/drive/root\\:/:filename', (req, res) => {
|
|
246
|
+
const params = req.params;
|
|
247
|
+
let filename = params.filename;
|
|
248
|
+
if (filename.endsWith(':'))
|
|
249
|
+
filename = filename.slice(0, -1);
|
|
250
|
+
filename = decodeURIComponent(filename);
|
|
251
|
+
const child = store_1.driveStore.getItemByName('root', filename);
|
|
252
|
+
if (!child) {
|
|
253
|
+
return res.status(404).json({ error: { code: "itemNotFound", message: "Item not found" } });
|
|
254
|
+
}
|
|
255
|
+
res.status(200).json(applySelect(child, req.query.$select));
|
|
256
|
+
});
|
|
227
257
|
// PUT /me/drive/items/{parent-id}:/{filename}:/content
|
|
228
258
|
app.put('/v1.0/me/drive/items/:parentId\\:/:filename\\:/content', (req, res) => {
|
|
229
259
|
const parentId = req.params.parentId;
|
|
@@ -295,6 +325,133 @@ const createV1Router = () => {
|
|
|
295
325
|
value: result.items
|
|
296
326
|
});
|
|
297
327
|
});
|
|
328
|
+
// ==========================================
|
|
329
|
+
// MISSING ENDPOINTS IMPLEMENTATION
|
|
330
|
+
// ==========================================
|
|
331
|
+
// --- Drives & Shared Content ---
|
|
332
|
+
const defaultDrive = {
|
|
333
|
+
id: "b!default-mock-drive-id",
|
|
334
|
+
driveType: "personal",
|
|
335
|
+
name: "OneDrive",
|
|
336
|
+
owner: { user: { id: "user1", displayName: "Mock User" } }
|
|
337
|
+
};
|
|
338
|
+
app.get('/v1.0/me/drives', (req, res) => {
|
|
339
|
+
res.json({ value: [defaultDrive] });
|
|
340
|
+
});
|
|
341
|
+
app.get('/v1.0/drives/:driveId', (req, res) => {
|
|
342
|
+
res.json(defaultDrive);
|
|
343
|
+
});
|
|
344
|
+
app.get('/v1.0/me/drive/sharedWithMe', (req, res) => {
|
|
345
|
+
res.json({ value: [] });
|
|
346
|
+
});
|
|
347
|
+
app.get('/v1.0/me/drive/recent', (req, res) => {
|
|
348
|
+
res.json({ value: [] });
|
|
349
|
+
});
|
|
350
|
+
app.get('/v1.0/me/drive/following', (req, res) => {
|
|
351
|
+
res.json({ value: [] });
|
|
352
|
+
});
|
|
353
|
+
// --- Special Folders ---
|
|
354
|
+
app.get('/v1.0/me/drive/special/:folderName', (req, res) => {
|
|
355
|
+
const root = store_1.driveStore.getItem('root');
|
|
356
|
+
if (!root)
|
|
357
|
+
return res.status(404).json({ error: { message: "Not found" } });
|
|
358
|
+
res.json(root);
|
|
359
|
+
});
|
|
360
|
+
// --- Advanced Item Operations ---
|
|
361
|
+
app.post('/v1.0/me/drive/items/:itemId/copy', (req, res) => {
|
|
362
|
+
const itemId = req.params.itemId;
|
|
363
|
+
const item = store_1.driveStore.getItem(itemId);
|
|
364
|
+
if (!item)
|
|
365
|
+
return res.status(404).json({ error: { message: "Not found" } });
|
|
366
|
+
const host = req.headers.host || 'localhost';
|
|
367
|
+
const protocol = req.protocol || 'http';
|
|
368
|
+
const baseUrl = `${protocol}://${host}`;
|
|
369
|
+
res.setHeader('Location', `${baseUrl}/v1.0/monitor/mock-copy-job-12345`);
|
|
370
|
+
res.status(202).json({});
|
|
371
|
+
});
|
|
372
|
+
app.post('/v1.0/me/drive/items/:itemId/createLink', (req, res) => {
|
|
373
|
+
const item = store_1.driveStore.getItem(req.params.itemId);
|
|
374
|
+
if (!item)
|
|
375
|
+
return res.status(404).json({ error: { message: "Not found" } });
|
|
376
|
+
res.json({
|
|
377
|
+
id: "mock-link-id",
|
|
378
|
+
roles: ["write"],
|
|
379
|
+
link: { webUrl: "https://mock-onedrive-link/123" }
|
|
380
|
+
});
|
|
381
|
+
});
|
|
382
|
+
app.get('/v1.0/me/drive/items/:itemId/permissions', (req, res) => {
|
|
383
|
+
res.json({ value: [{ id: "perm1", roles: ["write"] }] });
|
|
384
|
+
});
|
|
385
|
+
app.post('/v1.0/me/drive/items/:itemId/invite', (req, res) => {
|
|
386
|
+
res.json({ value: [{ id: "perm1", roles: ["write"] }] });
|
|
387
|
+
});
|
|
388
|
+
app.delete('/v1.0/me/drive/items/:itemId/permissions/:permId', (req, res) => {
|
|
389
|
+
res.status(204).send();
|
|
390
|
+
});
|
|
391
|
+
app.get('/v1.0/me/drive/items/:itemId/versions', (req, res) => {
|
|
392
|
+
res.json({ value: [] });
|
|
393
|
+
});
|
|
394
|
+
app.post('/v1.0/me/drive/items/:itemId/versions/:versionId/restoreVersion', (req, res) => {
|
|
395
|
+
res.status(204).send();
|
|
396
|
+
});
|
|
397
|
+
app.post('/v1.0/me/drive/items/:itemId/checkout', (req, res) => {
|
|
398
|
+
res.status(204).send();
|
|
399
|
+
});
|
|
400
|
+
app.post('/v1.0/me/drive/items/:itemId/checkin', (req, res) => {
|
|
401
|
+
res.status(204).send();
|
|
402
|
+
});
|
|
403
|
+
app.get('/v1.0/me/drive/items/:itemId/thumbnails', (req, res) => {
|
|
404
|
+
res.json({
|
|
405
|
+
value: [
|
|
406
|
+
{ id: "0", large: { url: "https://mock-thumbnail-url/large" } }
|
|
407
|
+
]
|
|
408
|
+
});
|
|
409
|
+
});
|
|
410
|
+
app.get('/v1.0/me/drive/items/:itemId/activities', (req, res) => {
|
|
411
|
+
res.json({ value: [] });
|
|
412
|
+
});
|
|
413
|
+
// --- Upload Sessions ---
|
|
414
|
+
const handleCreateUploadSession = (parentId, filename, req, res) => {
|
|
415
|
+
const parentObj = store_1.driveStore.getItem(parentId) || (parentId === 'root' ? store_1.driveStore.getItem('root') : null);
|
|
416
|
+
if (!parentObj) {
|
|
417
|
+
return res.status(404).json({ error: { code: "itemNotFound", message: "Parent not found" } });
|
|
418
|
+
}
|
|
419
|
+
const session = store_1.driveStore.createUploadSession(parentId, filename);
|
|
420
|
+
const host = req.headers.host || 'localhost';
|
|
421
|
+
const protocol = req.protocol || 'http';
|
|
422
|
+
const baseUrl = `${protocol}://${host}`;
|
|
423
|
+
res.status(200).json({
|
|
424
|
+
uploadUrl: `${baseUrl}/v1.0${session.uploadUrl}`,
|
|
425
|
+
expirationDateTime: session.expirationDateTime
|
|
426
|
+
});
|
|
427
|
+
};
|
|
428
|
+
app.post('/v1.0/me/drive/items/:parentId\\:/:filename\\:/createUploadSession', (req, res) => {
|
|
429
|
+
const params = req.params;
|
|
430
|
+
handleCreateUploadSession(params.parentId, decodeURIComponent(params.filename), req, res);
|
|
431
|
+
});
|
|
432
|
+
app.post('/v1.0/me/drive/root\\:/:filename\\:/createUploadSession', (req, res) => {
|
|
433
|
+
const params = req.params;
|
|
434
|
+
handleCreateUploadSession('root', decodeURIComponent(params.filename), req, res);
|
|
435
|
+
});
|
|
436
|
+
// --- Subscriptions ---
|
|
437
|
+
app.post('/v1.0/subscriptions', (req, res) => {
|
|
438
|
+
res.status(201).json({
|
|
439
|
+
id: "mock-subscription-123",
|
|
440
|
+
expirationDateTime: new Date(Date.now() + 2 * 24 * 3600 * 1000).toISOString(),
|
|
441
|
+
clientState: req.body.clientState || "mock-secret"
|
|
442
|
+
});
|
|
443
|
+
});
|
|
444
|
+
app.get('/v1.0/subscriptions', (req, res) => {
|
|
445
|
+
res.json({ value: [] });
|
|
446
|
+
});
|
|
447
|
+
app.put('/v1.0/upload-sessions/:sessionId', express_1.default.raw({ type: '*/*', limit: '50mb' }), (req, res) => {
|
|
448
|
+
const sessionId = req.params.sessionId;
|
|
449
|
+
const session = store_1.driveStore.getUploadSession(sessionId);
|
|
450
|
+
if (!session)
|
|
451
|
+
return res.status(404).json({ error: { message: "Session not found" } });
|
|
452
|
+
const item = store_1.driveStore.completeUploadSession(sessionId);
|
|
453
|
+
res.status(200).json(item);
|
|
454
|
+
});
|
|
298
455
|
return app;
|
|
299
456
|
};
|
|
300
457
|
exports.createV1Router = createV1Router;
|
package/dist/store.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { DriveItem } from './types';
|
|
|
2
2
|
export declare class DriveStore {
|
|
3
3
|
private items;
|
|
4
4
|
private deltaHistory;
|
|
5
|
+
private uploadSessions;
|
|
5
6
|
constructor();
|
|
6
7
|
private calculateStats;
|
|
7
8
|
createItem(item: Partial<DriveItem> & {
|
|
@@ -9,10 +10,22 @@ export declare class DriveStore {
|
|
|
9
10
|
}, isFolder?: boolean): DriveItem;
|
|
10
11
|
updateItem(id: string, updates: Partial<DriveItem>): DriveItem | null;
|
|
11
12
|
getItem(id: string): DriveItem | null;
|
|
13
|
+
getItemByName(parentId: string, name: string): DriveItem | null;
|
|
12
14
|
deleteItem(id: string): boolean;
|
|
13
15
|
listItems(parentId?: string): DriveItem[];
|
|
14
16
|
getAllItems(): DriveItem[];
|
|
15
17
|
clear(): void;
|
|
18
|
+
createUploadSession(parentId: string, filename: string): {
|
|
19
|
+
uploadUrl: string;
|
|
20
|
+
expirationDateTime: string;
|
|
21
|
+
};
|
|
22
|
+
completeUploadSession(sessionId: string): DriveItem | null;
|
|
23
|
+
getUploadSession(sessionId: string): {
|
|
24
|
+
parentId: string;
|
|
25
|
+
filename: string;
|
|
26
|
+
expirationDateTime: string;
|
|
27
|
+
} | null;
|
|
28
|
+
deleteUploadSession(sessionId: string): void;
|
|
16
29
|
private addDeltaHistory;
|
|
17
30
|
getDeltaToken(): string;
|
|
18
31
|
getDelta(token?: string): {
|
package/dist/store.js
CHANGED
|
@@ -39,6 +39,7 @@ class DriveStore {
|
|
|
39
39
|
constructor() {
|
|
40
40
|
this.items = new Map();
|
|
41
41
|
this.deltaHistory = [];
|
|
42
|
+
this.uploadSessions = new Map();
|
|
42
43
|
}
|
|
43
44
|
calculateStats(content) {
|
|
44
45
|
let buffer;
|
|
@@ -107,6 +108,10 @@ class DriveStore {
|
|
|
107
108
|
getItem(id) {
|
|
108
109
|
return this.items.get(id) || null;
|
|
109
110
|
}
|
|
111
|
+
getItemByName(parentId, name) {
|
|
112
|
+
const children = this.listItems(parentId);
|
|
113
|
+
return children.find(c => c.name === name && !c.deleted) || null;
|
|
114
|
+
}
|
|
110
115
|
deleteItem(id) {
|
|
111
116
|
const item = this.items.get(id);
|
|
112
117
|
if (!item)
|
|
@@ -134,9 +139,39 @@ class DriveStore {
|
|
|
134
139
|
clear() {
|
|
135
140
|
this.items.clear();
|
|
136
141
|
this.deltaHistory = [];
|
|
142
|
+
this.uploadSessions.clear();
|
|
137
143
|
// Always recreate a standard root folder
|
|
138
144
|
this.createItem({ id: 'root', name: 'root' }, true);
|
|
139
145
|
}
|
|
146
|
+
// Upload Sessions
|
|
147
|
+
createUploadSession(parentId, filename) {
|
|
148
|
+
const sessionId = Math.random().toString(36).substring(7);
|
|
149
|
+
const expirationDateTime = new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(); // 1 day
|
|
150
|
+
this.uploadSessions.set(sessionId, { parentId, filename, expirationDateTime });
|
|
151
|
+
// Return a relative URL path to be prefixed by the router
|
|
152
|
+
return {
|
|
153
|
+
uploadUrl: `/upload-sessions/${sessionId}`,
|
|
154
|
+
expirationDateTime
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
completeUploadSession(sessionId) {
|
|
158
|
+
const session = this.uploadSessions.get(sessionId);
|
|
159
|
+
if (!session)
|
|
160
|
+
return null;
|
|
161
|
+
this.uploadSessions.delete(sessionId);
|
|
162
|
+
const item = this.createItem({
|
|
163
|
+
name: session.filename,
|
|
164
|
+
file: { mimeType: 'application/octet-stream' },
|
|
165
|
+
parentReference: { id: session.parentId }
|
|
166
|
+
});
|
|
167
|
+
return item;
|
|
168
|
+
}
|
|
169
|
+
getUploadSession(sessionId) {
|
|
170
|
+
return this.uploadSessions.get(sessionId) || null;
|
|
171
|
+
}
|
|
172
|
+
deleteUploadSession(sessionId) {
|
|
173
|
+
this.uploadSessions.delete(sessionId);
|
|
174
|
+
}
|
|
140
175
|
// Delta History (simulated changes API)
|
|
141
176
|
addDeltaHistory(item) {
|
|
142
177
|
this.deltaHistory.push(JSON.parse(JSON.stringify(item)));
|