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 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)));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "microsoft-onedrive-mock",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Mock-Server that simulates being Microsoft OneDrive. Used for testing.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",