@slorenzot/memento-core 2.0.0 → 2.0.1

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.
Files changed (55) hide show
  1. package/dist/ConfigManager.d.ts +44 -59
  2. package/dist/ConfigManager.d.ts.map +1 -1
  3. package/dist/ConfigManager.js +78 -279
  4. package/dist/ConfigManager.js.map +1 -1
  5. package/dist/MemoryEngine.d.ts +30 -0
  6. package/dist/MemoryEngine.d.ts.map +1 -1
  7. package/dist/MemoryEngine.js +136 -11
  8. package/dist/MemoryEngine.js.map +1 -1
  9. package/dist/auth/device-flow-client.d.ts +48 -0
  10. package/dist/auth/device-flow-client.d.ts.map +1 -0
  11. package/dist/auth/device-flow-client.js +143 -0
  12. package/dist/auth/device-flow-client.js.map +1 -0
  13. package/dist/auth/index.d.ts +4 -0
  14. package/dist/auth/index.d.ts.map +1 -0
  15. package/dist/auth/index.js +9 -0
  16. package/dist/auth/index.js.map +1 -0
  17. package/dist/auth/token-store.d.ts +46 -0
  18. package/dist/auth/token-store.d.ts.map +1 -0
  19. package/dist/auth/token-store.js +117 -0
  20. package/dist/auth/token-store.js.map +1 -0
  21. package/dist/auth/types.d.ts +83 -0
  22. package/dist/auth/types.d.ts.map +1 -0
  23. package/dist/auth/types.js +4 -0
  24. package/dist/auth/types.js.map +1 -0
  25. package/dist/index.d.ts +2 -0
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +2 -0
  28. package/dist/index.js.map +1 -1
  29. package/dist/sync/conflict-resolution.d.ts +26 -0
  30. package/dist/sync/conflict-resolution.d.ts.map +1 -0
  31. package/dist/sync/conflict-resolution.js +64 -0
  32. package/dist/sync/conflict-resolution.js.map +1 -0
  33. package/dist/sync/index.d.ts +5 -0
  34. package/dist/sync/index.d.ts.map +1 -0
  35. package/dist/sync/index.js +12 -0
  36. package/dist/sync/index.js.map +1 -0
  37. package/dist/sync/sync-client.d.ts +41 -0
  38. package/dist/sync/sync-client.d.ts.map +1 -0
  39. package/dist/sync/sync-client.js +101 -0
  40. package/dist/sync/sync-client.js.map +1 -0
  41. package/dist/sync/sync-engine.d.ts +58 -0
  42. package/dist/sync/sync-engine.d.ts.map +1 -0
  43. package/dist/sync/sync-engine.js +370 -0
  44. package/dist/sync/sync-engine.js.map +1 -0
  45. package/dist/sync/types.d.ts +107 -0
  46. package/dist/sync/types.d.ts.map +1 -0
  47. package/dist/sync/types.js +20 -0
  48. package/dist/sync/types.js.map +1 -0
  49. package/dist/token-savings.d.ts +42 -0
  50. package/dist/token-savings.d.ts.map +1 -0
  51. package/dist/token-savings.js +104 -0
  52. package/dist/token-savings.js.map +1 -0
  53. package/dist/types.d.ts +3 -0
  54. package/dist/types.d.ts.map +1 -1
  55. package/package.json +1 -1
@@ -0,0 +1,4 @@
1
+ export { DeviceFlowClient, DeviceFlowError } from './device-flow-client.js';
2
+ export { TokenStore } from './token-store.js';
3
+ export type { OAuthClientConfig, DeviceCodeResponse, TokenResponse, TokenErrorResponse, TokenUserInfo, StoredAuth, DeviceFlowResult, DeviceFlowError as DeviceFlowErrorType, FetchFunction, } from './types.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EACV,iBAAiB,EACjB,kBAAkB,EAClB,aAAa,EACb,kBAAkB,EAClB,aAAa,EACb,UAAU,EACV,gBAAgB,EAChB,eAAe,IAAI,mBAAmB,EACtC,aAAa,GACd,MAAM,YAAY,CAAC"}
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TokenStore = exports.DeviceFlowError = exports.DeviceFlowClient = void 0;
4
+ var device_flow_client_js_1 = require("./device-flow-client.js");
5
+ Object.defineProperty(exports, "DeviceFlowClient", { enumerable: true, get: function () { return device_flow_client_js_1.DeviceFlowClient; } });
6
+ Object.defineProperty(exports, "DeviceFlowError", { enumerable: true, get: function () { return device_flow_client_js_1.DeviceFlowError; } });
7
+ var token_store_js_1 = require("./token-store.js");
8
+ Object.defineProperty(exports, "TokenStore", { enumerable: true, get: function () { return token_store_js_1.TokenStore; } });
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":";;;AAAA,iEAA4E;AAAnE,yHAAA,gBAAgB,OAAA;AAAE,wHAAA,eAAe,OAAA;AAC1C,mDAA8C;AAArC,4GAAA,UAAU,OAAA"}
@@ -0,0 +1,46 @@
1
+ import type { StoredAuth, TokenResponse, TokenUserInfo } from './types.js';
2
+ /**
3
+ * Manages OAuth token persistence in ~/.memento/auth.json.
4
+ *
5
+ * This is SEPARATE from the main config (~/.memento/config.json)
6
+ * because auth tokens are sensitive and shouldn't be in project config.
7
+ */
8
+ export declare class TokenStore {
9
+ private readonly filePath;
10
+ constructor(filePath?: string);
11
+ /**
12
+ * Get the stored auth token, if any.
13
+ * Returns null if no token is stored or if it's expired.
14
+ */
15
+ getToken(): StoredAuth | null;
16
+ /**
17
+ * Check if the user is currently authenticated with a valid (non-expired) token.
18
+ */
19
+ isAuthenticated(): boolean;
20
+ /**
21
+ * Get user info from the stored token, if available.
22
+ */
23
+ getUser(): TokenUserInfo | null;
24
+ /**
25
+ * Get the server URL from the stored token.
26
+ */
27
+ getServerUrl(): string | null;
28
+ /**
29
+ * Save a token response as the stored auth.
30
+ */
31
+ setToken(token: TokenResponse, serverUrl: string): StoredAuth;
32
+ /**
33
+ * Clear the stored token (logout).
34
+ */
35
+ clearToken(): boolean;
36
+ /**
37
+ * Get time remaining until token expires, in seconds.
38
+ * Returns 0 if no token or already expired.
39
+ */
40
+ getTimeUntilExpiry(): number;
41
+ /**
42
+ * Get the file path where auth is stored (useful for display).
43
+ */
44
+ getFilePath(): string;
45
+ }
46
+ //# sourceMappingURL=token-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-store.d.ts","sourceRoot":"","sources":["../../src/auth/token-store.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAK3E;;;;;GAKG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;gBAEtB,QAAQ,CAAC,EAAE,MAAM;IAI7B;;;OAGG;IACH,QAAQ,IAAI,UAAU,GAAG,IAAI;IAqB7B;;OAEG;IACH,eAAe,IAAI,OAAO;IAM1B;;OAEG;IACH,OAAO,IAAI,aAAa,GAAG,IAAI;IAK/B;;OAEG;IACH,YAAY,IAAI,MAAM,GAAG,IAAI;IAK7B;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,GAAG,UAAU;IAsB7D;;OAEG;IACH,UAAU,IAAI,OAAO;IAUrB;;;OAGG;IACH,kBAAkB,IAAI,MAAM;IAO5B;;OAEG;IACH,WAAW,IAAI,MAAM;CAGtB"}
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TokenStore = void 0;
4
+ const fs_1 = require("fs");
5
+ const path_1 = require("path");
6
+ const os_1 = require("os");
7
+ const AUTH_DIR = (0, path_1.join)((0, os_1.homedir)(), '.memento');
8
+ const AUTH_FILE = 'auth.json';
9
+ /**
10
+ * Manages OAuth token persistence in ~/.memento/auth.json.
11
+ *
12
+ * This is SEPARATE from the main config (~/.memento/config.json)
13
+ * because auth tokens are sensitive and shouldn't be in project config.
14
+ */
15
+ class TokenStore {
16
+ filePath;
17
+ constructor(filePath) {
18
+ this.filePath = filePath ?? (0, path_1.join)(AUTH_DIR, AUTH_FILE);
19
+ }
20
+ /**
21
+ * Get the stored auth token, if any.
22
+ * Returns null if no token is stored or if it's expired.
23
+ */
24
+ getToken() {
25
+ if (!(0, fs_1.existsSync)(this.filePath)) {
26
+ return null;
27
+ }
28
+ try {
29
+ const raw = (0, fs_1.readFileSync)(this.filePath, 'utf-8');
30
+ const auth = JSON.parse(raw);
31
+ // Validate structure
32
+ if (!auth.accessToken || !auth.expiresAt || !auth.serverUrl) {
33
+ return null;
34
+ }
35
+ return auth;
36
+ }
37
+ catch {
38
+ // Corrupted file — treat as no auth
39
+ return null;
40
+ }
41
+ }
42
+ /**
43
+ * Check if the user is currently authenticated with a valid (non-expired) token.
44
+ */
45
+ isAuthenticated() {
46
+ const auth = this.getToken();
47
+ if (!auth)
48
+ return false;
49
+ return Date.now() < auth.expiresAt;
50
+ }
51
+ /**
52
+ * Get user info from the stored token, if available.
53
+ */
54
+ getUser() {
55
+ const auth = this.getToken();
56
+ return auth?.user ?? null;
57
+ }
58
+ /**
59
+ * Get the server URL from the stored token.
60
+ */
61
+ getServerUrl() {
62
+ const auth = this.getToken();
63
+ return auth?.serverUrl ?? null;
64
+ }
65
+ /**
66
+ * Save a token response as the stored auth.
67
+ */
68
+ setToken(token, serverUrl) {
69
+ const dir = (0, path_1.dirname)(this.filePath);
70
+ if (!(0, fs_1.existsSync)(dir)) {
71
+ (0, fs_1.mkdirSync)(dir, { recursive: true });
72
+ }
73
+ const auth = {
74
+ accessToken: token.access_token,
75
+ refreshToken: token.refresh_token,
76
+ tokenType: (token.token_type || 'Bearer'),
77
+ expiresAt: token.expires_in
78
+ ? Date.now() + token.expires_in * 1000
79
+ : Date.now() + 365 * 24 * 60 * 60 * 1000, // Default 1 year if no expiry
80
+ user: token.user,
81
+ serverUrl,
82
+ storedAt: Date.now(),
83
+ };
84
+ (0, fs_1.writeFileSync)(this.filePath, JSON.stringify(auth, null, 2), 'utf-8');
85
+ return auth;
86
+ }
87
+ /**
88
+ * Clear the stored token (logout).
89
+ */
90
+ clearToken() {
91
+ if (!(0, fs_1.existsSync)(this.filePath)) {
92
+ return false;
93
+ }
94
+ const raw = (0, fs_1.readFileSync)(this.filePath, 'utf-8');
95
+ (0, fs_1.writeFileSync)(this.filePath, JSON.stringify({}, null, 2), 'utf-8');
96
+ return raw.trim().length > 2; // Was there actual data?
97
+ }
98
+ /**
99
+ * Get time remaining until token expires, in seconds.
100
+ * Returns 0 if no token or already expired.
101
+ */
102
+ getTimeUntilExpiry() {
103
+ const auth = this.getToken();
104
+ if (!auth)
105
+ return 0;
106
+ const remaining = Math.max(0, Math.floor((auth.expiresAt - Date.now()) / 1000));
107
+ return remaining;
108
+ }
109
+ /**
110
+ * Get the file path where auth is stored (useful for display).
111
+ */
112
+ getFilePath() {
113
+ return this.filePath;
114
+ }
115
+ }
116
+ exports.TokenStore = TokenStore;
117
+ //# sourceMappingURL=token-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-store.js","sourceRoot":"","sources":["../../src/auth/token-store.ts"],"names":[],"mappings":";;;AAAA,2BAAwE;AACxE,+BAAqC;AACrC,2BAA6B;AAG7B,MAAM,QAAQ,GAAG,IAAA,WAAI,EAAC,IAAA,YAAO,GAAE,EAAE,UAAU,CAAC,CAAC;AAC7C,MAAM,SAAS,GAAG,WAAW,CAAC;AAE9B;;;;;GAKG;AACH,MAAa,UAAU;IACJ,QAAQ,CAAS;IAElC,YAAY,QAAiB;QAC3B,IAAI,CAAC,QAAQ,GAAG,QAAQ,IAAI,IAAA,WAAI,EAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IACxD,CAAC;IAED;;;OAGG;IACH,QAAQ;QACN,IAAI,CAAC,IAAA,eAAU,EAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC/B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAA,iBAAY,EAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACjD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAe,CAAC;YAE3C,qBAAqB;YACrB,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;gBAC5D,OAAO,IAAI,CAAC;YACd,CAAC;YAED,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,oCAAoC;YACpC,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACH,eAAe;QACb,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC7B,IAAI,CAAC,IAAI;YAAE,OAAO,KAAK,CAAC;QACxB,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC;IACrC,CAAC;IAED;;OAEG;IACH,OAAO;QACL,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC7B,OAAO,IAAI,EAAE,IAAI,IAAI,IAAI,CAAC;IAC5B,CAAC;IAED;;OAEG;IACH,YAAY;QACV,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC7B,OAAO,IAAI,EAAE,SAAS,IAAI,IAAI,CAAC;IACjC,CAAC;IAED;;OAEG;IACH,QAAQ,CAAC,KAAoB,EAAE,SAAiB;QAC9C,MAAM,GAAG,GAAG,IAAA,cAAO,EAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnC,IAAI,CAAC,IAAA,eAAU,EAAC,GAAG,CAAC,EAAE,CAAC;YACrB,IAAA,cAAS,EAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtC,CAAC;QAED,MAAM,IAAI,GAAe;YACvB,WAAW,EAAE,KAAK,CAAC,YAAY;YAC/B,YAAY,EAAE,KAAK,CAAC,aAAa;YACjC,SAAS,EAAE,CAAC,KAAK,CAAC,UAAU,IAAI,QAAQ,CAAa;YACrD,SAAS,EAAE,KAAK,CAAC,UAAU;gBACzB,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,UAAU,GAAG,IAAI;gBACtC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,8BAA8B;YAC1E,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,SAAS;YACT,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE;SACrB,CAAC;QAEF,IAAA,kBAAa,EAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACrE,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACH,UAAU;QACR,IAAI,CAAC,IAAA,eAAU,EAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC/B,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,GAAG,GAAG,IAAA,iBAAY,EAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACjD,IAAA,kBAAa,EAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACnE,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,yBAAyB;IACzD,CAAC;IAED;;;OAGG;IACH,kBAAkB;QAChB,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC7B,IAAI,CAAC,IAAI;YAAE,OAAO,CAAC,CAAC;QACpB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;QAChF,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;OAEG;IACH,WAAW;QACT,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;CACF;AAhHD,gCAgHC"}
@@ -0,0 +1,83 @@
1
+ /** Configuration for the OAuth device flow client */
2
+ export interface OAuthClientConfig {
3
+ /** Base URL of the memento-web server (e.g. 'https://memento-web.app') */
4
+ serverUrl: string;
5
+ /** OAuth client identifier */
6
+ clientId?: string;
7
+ /** Polling interval in seconds (server may override via slow_down) */
8
+ pollInterval?: number;
9
+ /** Device code lifetime in seconds (default: 900 = 15 min) */
10
+ deviceCodeLifetime?: number;
11
+ /** Custom fetch function — useful for testing with mocks */
12
+ fetchFunction?: FetchFunction;
13
+ /** Custom sleep function — useful for testing (default: real setTimeout) */
14
+ sleepFunction?: SleepFunction;
15
+ }
16
+ /** Response from POST /api/oauth/device — RFC 8628 §3.1 */
17
+ export interface DeviceCodeResponse {
18
+ /** The device verification code */
19
+ device_code: string;
20
+ /** The code the user should enter at the verification URI */
21
+ user_code: string;
22
+ /** The URI where the user should go to authorize */
23
+ verification_uri: string;
24
+ /** Full URI with user_code pre-embedded (optional convenience) */
25
+ verification_uri_complete?: string;
26
+ /** Lifetime in seconds of the device_code */
27
+ expires_in: number;
28
+ /** Minimum polling interval in seconds */
29
+ interval: number;
30
+ }
31
+ /** Response from POST /api/v1/auth/device/token */
32
+ export interface TokenResponse {
33
+ access_token: string;
34
+ token_type: string;
35
+ /** Seconds until expiry (optional — device flow tokens may not expire) */
36
+ expires_in?: number;
37
+ refresh_token?: string;
38
+ scope?: string;
39
+ /** User info included in token response */
40
+ user?: TokenUserInfo;
41
+ }
42
+ /** User info returned with the token */
43
+ export interface TokenUserInfo {
44
+ email: string;
45
+ name?: string;
46
+ image?: string;
47
+ }
48
+ /** Error response from the token endpoint — RFC 8628 §3.5 */
49
+ export interface TokenErrorResponse {
50
+ error: DeviceFlowError;
51
+ error_description?: string;
52
+ }
53
+ /** RFC 8628 error codes */
54
+ export type DeviceFlowError = 'authorization_pending' | 'slow_down' | 'expired_token' | 'access_denied' | 'invalid_client' | 'invalid_grant' | 'server_error';
55
+ /** Stored auth token with metadata */
56
+ export interface StoredAuth {
57
+ /** The access token */
58
+ accessToken: string;
59
+ /** Refresh token (for renewing access) */
60
+ refreshToken?: string;
61
+ /** Token type (always 'Bearer') */
62
+ tokenType: 'Bearer';
63
+ /** Absolute expiry timestamp (ms since epoch) */
64
+ expiresAt: number;
65
+ /** User info at time of auth */
66
+ user?: TokenUserInfo;
67
+ /** Server URL that issued this token */
68
+ serverUrl: string;
69
+ /** When this auth was stored */
70
+ storedAt: number;
71
+ }
72
+ /** Result of a device flow authorization attempt */
73
+ export interface DeviceFlowResult {
74
+ success: boolean;
75
+ token?: TokenResponse;
76
+ error?: DeviceFlowError;
77
+ errorDescription?: string;
78
+ }
79
+ /** Configurable fetch function — allows mocking in tests */
80
+ export type FetchFunction = typeof fetch;
81
+ /** Configurable sleep function — allows mocking in tests (default: real setTimeout) */
82
+ export type SleepFunction = (ms: number) => Promise<void>;
83
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"AAEA,qDAAqD;AACrD,MAAM,WAAW,iBAAiB;IAChC,0EAA0E;IAC1E,SAAS,EAAE,MAAM,CAAC;IAClB,8BAA8B;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,8DAA8D;IAC9D,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,4DAA4D;IAC5D,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,4EAA4E;IAC5E,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAED,2DAA2D;AAC3D,MAAM,WAAW,kBAAkB;IACjC,mCAAmC;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,6DAA6D;IAC7D,SAAS,EAAE,MAAM,CAAC;IAClB,oDAAoD;IACpD,gBAAgB,EAAE,MAAM,CAAC;IACzB,kEAAkE;IAClE,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,6CAA6C;IAC7C,UAAU,EAAE,MAAM,CAAC;IACnB,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,mDAAmD;AACnD,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,IAAI,CAAC,EAAE,aAAa,CAAC;CACtB;AAED,wCAAwC;AACxC,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,6DAA6D;AAC7D,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,eAAe,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,2BAA2B;AAC3B,MAAM,MAAM,eAAe,GACvB,uBAAuB,GACvB,WAAW,GACX,eAAe,GACf,eAAe,GACf,gBAAgB,GAChB,eAAe,GACf,cAAc,CAAC;AAEnB,sCAAsC;AACtC,MAAM,WAAW,UAAU;IACzB,uBAAuB;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,0CAA0C;IAC1C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mCAAmC;IACnC,SAAS,EAAE,QAAQ,CAAC;IACpB,iDAAiD;IACjD,SAAS,EAAE,MAAM,CAAC;IAClB,gCAAgC;IAChC,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,gCAAgC;IAChC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,oDAAoD;AACpD,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,4DAA4D;AAC5D,MAAM,MAAM,aAAa,GAAG,OAAO,KAAK,CAAC;AAEzC,uFAAuF;AACvF,MAAM,MAAM,aAAa,GAAG,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ // ─── OAuth 2.0 Device Flow Types (RFC 8628) ─────────────────
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":";AAAA,+DAA+D"}
package/dist/index.d.ts CHANGED
@@ -2,4 +2,6 @@ export * from './MemoryEngine.js';
2
2
  export * from './types.js';
3
3
  export * from './ConfigManager.js';
4
4
  export * from './EmbeddingService.js';
5
+ export * from './auth/index.js';
6
+ export * from './sync/index.js';
5
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC"}
package/dist/index.js CHANGED
@@ -18,4 +18,6 @@ __exportStar(require("./MemoryEngine.js"), exports);
18
18
  __exportStar(require("./types.js"), exports);
19
19
  __exportStar(require("./ConfigManager.js"), exports);
20
20
  __exportStar(require("./EmbeddingService.js"), exports);
21
+ __exportStar(require("./auth/index.js"), exports);
22
+ __exportStar(require("./sync/index.js"), exports);
21
23
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,oDAAkC;AAClC,6CAA2B;AAC3B,qDAAmC;AACnC,wDAAsC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,oDAAkC;AAClC,6CAA2B;AAC3B,qDAAmC;AACnC,wDAAsC;AACtC,kDAAgC;AAChC,kDAAgC"}
@@ -0,0 +1,26 @@
1
+ import type { SyncMemento, SyncConflict } from './types.js';
2
+ /**
3
+ * Conflict resolution for sync — last-write-wins strategy.
4
+ *
5
+ * Compares localUpdatedAt timestamps to determine winner.
6
+ */
7
+ export declare function resolveConflict(local: SyncMemento, remote: SyncMemento): SyncConflict;
8
+ /**
9
+ * Detect which remote mementos conflict with local ones.
10
+ */
11
+ export declare function detectConflicts(remoteMementos: SyncMemento[], localByUuid: Map<string, SyncMemento>): {
12
+ conflicts: Array<{
13
+ local: SyncMemento;
14
+ remote: SyncMemento;
15
+ }>;
16
+ newRemote: SyncMemento[];
17
+ unchanged: SyncMemento[];
18
+ };
19
+ /**
20
+ * Resolve all conflicts and return results.
21
+ */
22
+ export declare function resolveAllConflicts(conflicts: Array<{
23
+ local: SyncMemento;
24
+ remote: SyncMemento;
25
+ }>): SyncConflict[];
26
+ //# sourceMappingURL=conflict-resolution.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conflict-resolution.d.ts","sourceRoot":"","sources":["../../src/sync/conflict-resolution.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE5D;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,WAAW,EAClB,MAAM,EAAE,WAAW,GAClB,YAAY,CAoBd;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,cAAc,EAAE,WAAW,EAAE,EAC7B,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,GACpC;IACD,SAAS,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,WAAW,CAAC;QAAC,MAAM,EAAE,WAAW,CAAA;KAAE,CAAC,CAAC;IAC9D,SAAS,EAAE,WAAW,EAAE,CAAC;IACzB,SAAS,EAAE,WAAW,EAAE,CAAC;CAC1B,CA+BA;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,CAAC,GAC5D,YAAY,EAAE,CAEhB"}
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveConflict = resolveConflict;
4
+ exports.detectConflicts = detectConflicts;
5
+ exports.resolveAllConflicts = resolveAllConflicts;
6
+ /**
7
+ * Conflict resolution for sync — last-write-wins strategy.
8
+ *
9
+ * Compares localUpdatedAt timestamps to determine winner.
10
+ */
11
+ function resolveConflict(local, remote) {
12
+ const localTime = new Date(local.localUpdatedAt).getTime();
13
+ const remoteTime = new Date(remote.localUpdatedAt).getTime();
14
+ if (localTime >= remoteTime) {
15
+ return {
16
+ uuid: local.uuid,
17
+ localVersion: local.version,
18
+ serverVersion: remote.version,
19
+ resolution: 'client_wins',
20
+ };
21
+ }
22
+ return {
23
+ uuid: remote.uuid,
24
+ localVersion: local.version,
25
+ serverVersion: remote.version,
26
+ resolution: 'server_wins',
27
+ serverData: remote,
28
+ };
29
+ }
30
+ /**
31
+ * Detect which remote mementos conflict with local ones.
32
+ */
33
+ function detectConflicts(remoteMementos, localByUuid) {
34
+ const conflicts = [];
35
+ const newRemote = [];
36
+ const unchanged = [];
37
+ for (const remote of remoteMementos) {
38
+ const local = localByUuid.get(remote.uuid);
39
+ if (!local) {
40
+ newRemote.push(remote);
41
+ continue;
42
+ }
43
+ // Check if content is identical
44
+ if (local.title === remote.title &&
45
+ local.content === remote.content &&
46
+ local.type === remote.type &&
47
+ local.topicKey === remote.topicKey &&
48
+ local.pinned === remote.pinned &&
49
+ local.readOnly === remote.readOnly &&
50
+ local.version === remote.version) {
51
+ unchanged.push(remote);
52
+ continue;
53
+ }
54
+ conflicts.push({ local, remote });
55
+ }
56
+ return { conflicts, newRemote, unchanged };
57
+ }
58
+ /**
59
+ * Resolve all conflicts and return results.
60
+ */
61
+ function resolveAllConflicts(conflicts) {
62
+ return conflicts.map(({ local, remote }) => resolveConflict(local, remote));
63
+ }
64
+ //# sourceMappingURL=conflict-resolution.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conflict-resolution.js","sourceRoot":"","sources":["../../src/sync/conflict-resolution.ts"],"names":[],"mappings":";;AAOA,0CAuBC;AAKD,0CAsCC;AAKD,kDAIC;AAhFD;;;;GAIG;AACH,SAAgB,eAAe,CAC7B,KAAkB,EAClB,MAAmB;IAEnB,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE,CAAC;IAC3D,MAAM,UAAU,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE,CAAC;IAE7D,IAAI,SAAS,IAAI,UAAU,EAAE,CAAC;QAC5B,OAAO;YACL,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,YAAY,EAAE,KAAK,CAAC,OAAO;YAC3B,aAAa,EAAE,MAAM,CAAC,OAAO;YAC7B,UAAU,EAAE,aAAa;SAC1B,CAAC;IACJ,CAAC;IAED,OAAO;QACL,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,YAAY,EAAE,KAAK,CAAC,OAAO;QAC3B,aAAa,EAAE,MAAM,CAAC,OAAO;QAC7B,UAAU,EAAE,aAAa;QACzB,UAAU,EAAE,MAAM;KACnB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAgB,eAAe,CAC7B,cAA6B,EAC7B,WAAqC;IAMrC,MAAM,SAAS,GAAuD,EAAE,CAAC;IACzE,MAAM,SAAS,GAAkB,EAAE,CAAC;IACpC,MAAM,SAAS,GAAkB,EAAE,CAAC;IAEpC,KAAK,MAAM,MAAM,IAAI,cAAc,EAAE,CAAC;QACpC,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAE3C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACvB,SAAS;QACX,CAAC;QAED,gCAAgC;QAChC,IACE,KAAK,CAAC,KAAK,KAAK,MAAM,CAAC,KAAK;YAC5B,KAAK,CAAC,OAAO,KAAK,MAAM,CAAC,OAAO;YAChC,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI;YAC1B,KAAK,CAAC,QAAQ,KAAK,MAAM,CAAC,QAAQ;YAClC,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM;YAC9B,KAAK,CAAC,QAAQ,KAAK,MAAM,CAAC,QAAQ;YAClC,KAAK,CAAC,OAAO,KAAK,MAAM,CAAC,OAAO,EAChC,CAAC;YACD,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACvB,SAAS;QACX,CAAC;QAED,SAAS,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IACpC,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;AAC7C,CAAC;AAED;;GAEG;AACH,SAAgB,mBAAmB,CACjC,SAA6D;IAE7D,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,eAAe,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;AAC9E,CAAC"}
@@ -0,0 +1,5 @@
1
+ export { SyncEngine } from './sync-engine.js';
2
+ export { SyncClient } from './sync-client.js';
3
+ export { resolveConflict, detectConflicts, resolveAllConflicts } from './conflict-resolution.js';
4
+ export type { SyncDirection, SyncMemento, SyncPushRequest, SyncPushResponse, SyncPullResponse, SyncPullParams, SyncConflict, SyncStatusResponse, SyncMeta, SyncResult, SyncConfig, SyncApiError, } from './types.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sync/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACjG,YAAY,EACV,aAAa,EACb,WAAW,EACX,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,YAAY,EACZ,kBAAkB,EAClB,QAAQ,EACR,UAAU,EACV,UAAU,EACV,YAAY,GACb,MAAM,YAAY,CAAC"}
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveAllConflicts = exports.detectConflicts = exports.resolveConflict = exports.SyncClient = exports.SyncEngine = void 0;
4
+ var sync_engine_js_1 = require("./sync-engine.js");
5
+ Object.defineProperty(exports, "SyncEngine", { enumerable: true, get: function () { return sync_engine_js_1.SyncEngine; } });
6
+ var sync_client_js_1 = require("./sync-client.js");
7
+ Object.defineProperty(exports, "SyncClient", { enumerable: true, get: function () { return sync_client_js_1.SyncClient; } });
8
+ var conflict_resolution_js_1 = require("./conflict-resolution.js");
9
+ Object.defineProperty(exports, "resolveConflict", { enumerable: true, get: function () { return conflict_resolution_js_1.resolveConflict; } });
10
+ Object.defineProperty(exports, "detectConflicts", { enumerable: true, get: function () { return conflict_resolution_js_1.detectConflicts; } });
11
+ Object.defineProperty(exports, "resolveAllConflicts", { enumerable: true, get: function () { return conflict_resolution_js_1.resolveAllConflicts; } });
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sync/index.ts"],"names":[],"mappings":";;;AAAA,mDAA8C;AAArC,4GAAA,UAAU,OAAA;AACnB,mDAA8C;AAArC,4GAAA,UAAU,OAAA;AACnB,mEAAiG;AAAxF,yHAAA,eAAe,OAAA;AAAE,yHAAA,eAAe,OAAA;AAAE,6HAAA,mBAAmB,OAAA"}
@@ -0,0 +1,41 @@
1
+ import type { SyncPullResponse, SyncPushRequest, SyncPushResponse, SyncStatusResponse } from './types.js';
2
+ /**
3
+ * HTTP client for the Memento v1 Sync API.
4
+ *
5
+ * Communicates with memento-web server at /api/v1/sync/*
6
+ * Authentication via Bearer token from DeviceFlowClient.
7
+ */
8
+ export declare class SyncClient {
9
+ private baseUrl;
10
+ private getToken;
11
+ private fetchFn;
12
+ constructor(options: {
13
+ serverUrl: string;
14
+ getToken: () => Promise<string | null>;
15
+ fetchFunction?: typeof fetch;
16
+ });
17
+ /**
18
+ * Pull changes from server since cursor.
19
+ * GET /api/v1/sync/pull?projectId=<slug>&cursor=<iso>&limit=<n>
20
+ */
21
+ pull(params: {
22
+ projectId: string;
23
+ cursor: string | null;
24
+ limit?: number;
25
+ }): Promise<SyncPullResponse>;
26
+ /**
27
+ * Push local mementos to server.
28
+ * POST /api/v1/sync/push
29
+ */
30
+ push(data: SyncPushRequest): Promise<SyncPushResponse>;
31
+ /**
32
+ * Get sync status for a project.
33
+ * GET /api/v1/sync/status?projectId=<slug>
34
+ */
35
+ status(projectId: string): Promise<SyncStatusResponse>;
36
+ /**
37
+ * Make an authenticated request to the sync API.
38
+ */
39
+ private request;
40
+ }
41
+ //# sourceMappingURL=sync-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-client.d.ts","sourceRoot":"","sources":["../../src/sync/sync-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAGpB;;;;;GAKG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAA+B;IAC/C,OAAO,CAAC,OAAO,CAAe;gBAElB,OAAO,EAAE;QACnB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;QACvC,aAAa,CAAC,EAAE,OAAO,KAAK,CAAC;KAC9B;IAMD;;;OAGG;IACG,IAAI,CAAC,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAa3G;;;OAGG;IACG,IAAI,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAU5D;;;OAGG;IACG,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAS5D;;OAEG;YACW,OAAO;CAgFtB"}
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SyncClient = void 0;
4
+ const types_js_1 = require("./types.js");
5
+ /**
6
+ * HTTP client for the Memento v1 Sync API.
7
+ *
8
+ * Communicates with memento-web server at /api/v1/sync/*
9
+ * Authentication via Bearer token from DeviceFlowClient.
10
+ */
11
+ class SyncClient {
12
+ baseUrl;
13
+ getToken;
14
+ fetchFn;
15
+ constructor(options) {
16
+ this.baseUrl = options.serverUrl.replace(/\/+$/, '');
17
+ this.getToken = options.getToken;
18
+ this.fetchFn = options.fetchFunction || fetch;
19
+ }
20
+ /**
21
+ * Pull changes from server since cursor.
22
+ * GET /api/v1/sync/pull?projectId=<slug>&cursor=<iso>&limit=<n>
23
+ */
24
+ async pull(params) {
25
+ const qp = new URLSearchParams({ projectId: params.projectId });
26
+ if (params.cursor)
27
+ qp.set('cursor', params.cursor);
28
+ if (params.limit)
29
+ qp.set('limit', String(params.limit));
30
+ const response = await this.request('GET', `/api/v1/sync/pull?${qp.toString()}`);
31
+ return response.data;
32
+ }
33
+ /**
34
+ * Push local mementos to server.
35
+ * POST /api/v1/sync/push
36
+ */
37
+ async push(data) {
38
+ const response = await this.request('POST', '/api/v1/sync/push', data);
39
+ return response.data;
40
+ }
41
+ /**
42
+ * Get sync status for a project.
43
+ * GET /api/v1/sync/status?projectId=<slug>
44
+ */
45
+ async status(projectId) {
46
+ const response = await this.request('GET', `/api/v1/sync/status?projectId=${encodeURIComponent(projectId)}`);
47
+ return response.data;
48
+ }
49
+ /**
50
+ * Make an authenticated request to the sync API.
51
+ */
52
+ async request(method, path, body) {
53
+ const token = await this.getToken();
54
+ if (!token) {
55
+ throw new types_js_1.SyncApiError('Not authenticated. Run `memento login` first.', 401, 'UNAUTHORIZED');
56
+ }
57
+ const headers = {
58
+ 'Authorization': `Bearer ${token}`,
59
+ 'Content-Type': 'application/json',
60
+ };
61
+ const response = await this.fetchFn(`${this.baseUrl}${path}`, {
62
+ method,
63
+ headers,
64
+ body: body ? JSON.stringify(body) : undefined,
65
+ });
66
+ if (response.status === 401) {
67
+ throw new types_js_1.SyncApiError('Authentication failed. Run `memento login` again.', 401, 'UNAUTHORIZED');
68
+ }
69
+ if (response.status === 403) {
70
+ throw new types_js_1.SyncApiError('Access denied. Check your project permissions.', 403, 'FORBIDDEN');
71
+ }
72
+ if (response.status === 429) {
73
+ throw new types_js_1.SyncApiError('Rate limited. Please wait before retrying.', 429, 'RATE_LIMITED');
74
+ }
75
+ if (!response.ok) {
76
+ const text = await response.text().catch(() => 'Unknown error');
77
+ // Try to extract a more specific error message from the response body.
78
+ // The memento-hub API returns { error: { code, message } } for validation errors.
79
+ let detail = '';
80
+ try {
81
+ const parsed = JSON.parse(text);
82
+ if (parsed?.error?.message) {
83
+ detail = ` — ${parsed.error.message}`;
84
+ }
85
+ else if (parsed?.message) {
86
+ detail = ` — ${parsed.message}`;
87
+ }
88
+ }
89
+ catch {
90
+ // Not JSON — use raw text if it's short enough
91
+ if (text && text.length < 500) {
92
+ detail = ` — ${text}`;
93
+ }
94
+ }
95
+ throw new types_js_1.SyncApiError(`Sync API error: ${response.status} ${response.statusText}${detail}`, response.status, undefined, text);
96
+ }
97
+ return response.json();
98
+ }
99
+ }
100
+ exports.SyncClient = SyncClient;
101
+ //# sourceMappingURL=sync-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-client.js","sourceRoot":"","sources":["../../src/sync/sync-client.ts"],"names":[],"mappings":"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"}