@awolve/myoffice 1.6.1 → 1.6.2

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.
@@ -5,6 +5,7 @@ import { ICachePlugin, TokenCacheContext } from '@azure/msal-node';
5
5
  */
6
6
  export declare class FileCachePlugin implements ICachePlugin {
7
7
  private cachePath;
8
+ private writeLock;
8
9
  constructor(cachePath: string);
9
10
  /**
10
11
  * Called before MSAL accesses the cache.
@@ -13,8 +14,9 @@ export declare class FileCachePlugin implements ICachePlugin {
13
14
  beforeCacheAccess(cacheContext: TokenCacheContext): Promise<void>;
14
15
  /**
15
16
  * Called after MSAL accesses the cache.
16
- * If the cache changed, persist it to disk.
17
+ * If the cache changed, persist it to disk using atomic write.
17
18
  */
18
19
  afterCacheAccess(cacheContext: TokenCacheContext): Promise<void>;
20
+ private writeCache;
19
21
  }
20
22
  //# sourceMappingURL=cache-plugin.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cache-plugin.d.ts","sourceRoot":"","sources":["../../src/auth/cache-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAInE;;;GAGG;AACH,qBAAa,eAAgB,YAAW,YAAY;IAClD,OAAO,CAAC,SAAS,CAAS;gBAEd,SAAS,EAAE,MAAM;IAI7B;;;OAGG;IACG,iBAAiB,CAAC,YAAY,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAavE;;;OAGG;IACG,gBAAgB,CAAC,YAAY,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;CAcvE"}
1
+ {"version":3,"file":"cache-plugin.d.ts","sourceRoot":"","sources":["../../src/auth/cache-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAInE;;;GAGG;AACH,qBAAa,eAAgB,YAAW,YAAY;IAClD,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAAoC;gBAEzC,SAAS,EAAE,MAAM;IAI7B;;;OAGG;IACG,iBAAiB,CAAC,YAAY,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAavE;;;OAGG;IACG,gBAAgB,CAAC,YAAY,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;YAQxD,UAAU;CA0BzB"}
@@ -1,4 +1,4 @@
1
- import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
1
+ import { existsSync, readFileSync, writeFileSync, mkdirSync, renameSync, unlinkSync } from 'fs';
2
2
  import { dirname } from 'path';
3
3
  /**
4
4
  * MSAL Cache Plugin that persists the full token cache (including refresh tokens)
@@ -6,6 +6,7 @@ import { dirname } from 'path';
6
6
  */
7
7
  export class FileCachePlugin {
8
8
  cachePath;
9
+ writeLock = Promise.resolve();
9
10
  constructor(cachePath) {
10
11
  this.cachePath = cachePath;
11
12
  }
@@ -28,20 +29,39 @@ export class FileCachePlugin {
28
29
  }
29
30
  /**
30
31
  * Called after MSAL accesses the cache.
31
- * If the cache changed, persist it to disk.
32
+ * If the cache changed, persist it to disk using atomic write.
32
33
  */
33
34
  async afterCacheAccess(cacheContext) {
34
35
  if (cacheContext.cacheHasChanged) {
36
+ // Queue writes to prevent concurrent file operations
37
+ this.writeLock = this.writeLock.then(() => this.writeCache(cacheContext));
38
+ await this.writeLock;
39
+ }
40
+ }
41
+ async writeCache(cacheContext) {
42
+ try {
43
+ const dir = dirname(this.cachePath);
44
+ if (!existsSync(dir)) {
45
+ mkdirSync(dir, { recursive: true });
46
+ }
47
+ const serialized = cacheContext.tokenCache.serialize();
48
+ // Atomic write: write to temp file, then rename
49
+ // This prevents corruption from concurrent writes
50
+ const tempPath = `${this.cachePath}.tmp.${process.pid}`;
51
+ writeFileSync(tempPath, serialized, { mode: 0o600 });
52
+ renameSync(tempPath, this.cachePath);
53
+ }
54
+ catch (error) {
55
+ console.error('[Cache] Failed to save cache:', error instanceof Error ? error.message : error);
56
+ // Clean up temp file if it exists
35
57
  try {
36
- const dir = dirname(this.cachePath);
37
- if (!existsSync(dir)) {
38
- mkdirSync(dir, { recursive: true });
58
+ const tempPath = `${this.cachePath}.tmp.${process.pid}`;
59
+ if (existsSync(tempPath)) {
60
+ unlinkSync(tempPath);
39
61
  }
40
- const serialized = cacheContext.tokenCache.serialize();
41
- writeFileSync(this.cachePath, serialized, { mode: 0o600 });
42
62
  }
43
- catch (error) {
44
- console.error('[Cache] Failed to save cache:', error instanceof Error ? error.message : error);
63
+ catch {
64
+ // Ignore cleanup errors
45
65
  }
46
66
  }
47
67
  }
@@ -1 +1 @@
1
- {"version":3,"file":"cache-plugin.js","sourceRoot":"","sources":["../../src/auth/cache-plugin.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACxE,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAE/B;;;GAGG;AACH,MAAM,OAAO,eAAe;IAClB,SAAS,CAAS;IAE1B,YAAY,SAAiB;QAC3B,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,iBAAiB,CAAC,YAA+B;QACrD,IAAI,CAAC;YACH,IAAI,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC/B,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;gBACxD,IAAI,SAAS,IAAI,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC;oBAClC,YAAY,CAAC,UAAU,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;gBACjD,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACjG,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,gBAAgB,CAAC,YAA+B;QACpD,IAAI,YAAY,CAAC,eAAe,EAAE,CAAC;YACjC,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBACpC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;oBACrB,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBACtC,CAAC;gBACD,MAAM,UAAU,GAAG,YAAY,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC;gBACvD,aAAa,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YAC7D,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YACjG,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
1
+ {"version":3,"file":"cache-plugin.js","sourceRoot":"","sources":["../../src/auth/cache-plugin.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChG,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAE/B;;;GAGG;AACH,MAAM,OAAO,eAAe;IAClB,SAAS,CAAS;IAClB,SAAS,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAC;IAErD,YAAY,SAAiB;QAC3B,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,iBAAiB,CAAC,YAA+B;QACrD,IAAI,CAAC;YACH,IAAI,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC/B,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;gBACxD,IAAI,SAAS,IAAI,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC;oBAClC,YAAY,CAAC,UAAU,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;gBACjD,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACjG,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,gBAAgB,CAAC,YAA+B;QACpD,IAAI,YAAY,CAAC,eAAe,EAAE,CAAC;YACjC,qDAAqD;YACrD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC;YAC1E,MAAM,IAAI,CAAC,SAAS,CAAC;QACvB,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,UAAU,CAAC,YAA+B;QACtD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACpC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACrB,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACtC,CAAC;YACD,MAAM,UAAU,GAAG,YAAY,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC;YAEvD,gDAAgD;YAChD,kDAAkD;YAClD,MAAM,QAAQ,GAAG,GAAG,IAAI,CAAC,SAAS,QAAQ,OAAO,CAAC,GAAG,EAAE,CAAC;YACxD,aAAa,CAAC,QAAQ,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YACrD,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QACvC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YAC/F,kCAAkC;YAClC,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,GAAG,IAAI,CAAC,SAAS,QAAQ,OAAO,CAAC,GAAG,EAAE,CAAC;gBACxD,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACzB,UAAU,CAAC,QAAQ,CAAC,CAAC;gBACvB,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,wBAAwB;YAC1B,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@awolve/myoffice",
3
- "version": "1.6.1",
3
+ "version": "1.6.2",
4
4
  "description": "CLI and MCP server for personal Microsoft 365 access - email, calendar, tasks, OneDrive, Teams, Planner",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",