@edgebasejs/react-native 0.1.0
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/client-core/src/auth/auth-manager.d.ts +73 -0
- package/dist/client-core/src/auth/auth-manager.d.ts.map +1 -0
- package/dist/client-core/src/auth/auth-manager.js +226 -0
- package/dist/client-core/src/auth/auth-manager.js.map +1 -0
- package/dist/client-core/src/auth/index.d.ts +2 -0
- package/dist/client-core/src/auth/index.d.ts.map +1 -0
- package/dist/client-core/src/auth/index.js +2 -0
- package/dist/client-core/src/auth/index.js.map +1 -0
- package/dist/client-core/src/conflict/conflict-resolver.d.ts +62 -0
- package/dist/client-core/src/conflict/conflict-resolver.d.ts.map +1 -0
- package/dist/client-core/src/conflict/conflict-resolver.js +102 -0
- package/dist/client-core/src/conflict/conflict-resolver.js.map +1 -0
- package/dist/client-core/src/conflict/index.d.ts +2 -0
- package/dist/client-core/src/conflict/index.d.ts.map +1 -0
- package/dist/client-core/src/conflict/index.js +2 -0
- package/dist/client-core/src/conflict/index.js.map +1 -0
- package/dist/client-core/src/index.d.ts +6 -0
- package/dist/client-core/src/index.d.ts.map +1 -0
- package/dist/client-core/src/index.js +6 -0
- package/dist/client-core/src/index.js.map +1 -0
- package/dist/client-core/src/outbox/index.d.ts +2 -0
- package/dist/client-core/src/outbox/index.d.ts.map +1 -0
- package/dist/client-core/src/outbox/index.js +2 -0
- package/dist/client-core/src/outbox/index.js.map +1 -0
- package/dist/client-core/src/outbox/outbox-manager.d.ts +82 -0
- package/dist/client-core/src/outbox/outbox-manager.d.ts.map +1 -0
- package/dist/client-core/src/outbox/outbox-manager.js +143 -0
- package/dist/client-core/src/outbox/outbox-manager.js.map +1 -0
- package/dist/client-core/src/storage/index.d.ts +2 -0
- package/dist/client-core/src/storage/index.d.ts.map +1 -0
- package/dist/client-core/src/storage/index.js +2 -0
- package/dist/client-core/src/storage/index.js.map +1 -0
- package/dist/client-core/src/storage/storage-adapter.d.ts +54 -0
- package/dist/client-core/src/storage/storage-adapter.d.ts.map +1 -0
- package/dist/client-core/src/storage/storage-adapter.js +38 -0
- package/dist/client-core/src/storage/storage-adapter.js.map +1 -0
- package/dist/client-core/src/sync/index.d.ts +2 -0
- package/dist/client-core/src/sync/index.d.ts.map +1 -0
- package/dist/client-core/src/sync/index.js +2 -0
- package/dist/client-core/src/sync/index.js.map +1 -0
- package/dist/client-core/src/sync/sync-engine.d.ts +65 -0
- package/dist/client-core/src/sync/sync-engine.d.ts.map +1 -0
- package/dist/client-core/src/sync/sync-engine.js +190 -0
- package/dist/client-core/src/sync/sync-engine.js.map +1 -0
- package/dist/client-react-native/src/hooks/index.d.ts +5 -0
- package/dist/client-react-native/src/hooks/index.d.ts.map +1 -0
- package/dist/client-react-native/src/hooks/index.js +5 -0
- package/dist/client-react-native/src/hooks/index.js.map +1 -0
- package/dist/client-react-native/src/hooks/use-auth.d.ts +17 -0
- package/dist/client-react-native/src/hooks/use-auth.d.ts.map +1 -0
- package/dist/client-react-native/src/hooks/use-auth.js +78 -0
- package/dist/client-react-native/src/hooks/use-auth.js.map +1 -0
- package/dist/client-react-native/src/hooks/use-mutation.d.ts +14 -0
- package/dist/client-react-native/src/hooks/use-mutation.d.ts.map +1 -0
- package/dist/client-react-native/src/hooks/use-mutation.js +95 -0
- package/dist/client-react-native/src/hooks/use-mutation.js.map +1 -0
- package/dist/client-react-native/src/hooks/use-query.d.ts +14 -0
- package/dist/client-react-native/src/hooks/use-query.d.ts.map +1 -0
- package/dist/client-react-native/src/hooks/use-query.js +77 -0
- package/dist/client-react-native/src/hooks/use-query.js.map +1 -0
- package/dist/client-react-native/src/hooks/use-sync.d.ts +14 -0
- package/dist/client-react-native/src/hooks/use-sync.d.ts.map +1 -0
- package/dist/client-react-native/src/hooks/use-sync.js +67 -0
- package/dist/client-react-native/src/hooks/use-sync.js.map +1 -0
- package/dist/client-react-native/src/index.d.ts +9 -0
- package/dist/client-react-native/src/index.d.ts.map +1 -0
- package/dist/client-react-native/src/index.js +9 -0
- package/dist/client-react-native/src/index.js.map +1 -0
- package/dist/client-react-native/src/provider.d.ts +21 -0
- package/dist/client-react-native/src/provider.d.ts.map +1 -0
- package/dist/client-react-native/src/provider.js +92 -0
- package/dist/client-react-native/src/provider.js.map +1 -0
- package/dist/client-react-native/src/storage/async-storage-adapter.d.ts +16 -0
- package/dist/client-react-native/src/storage/async-storage-adapter.d.ts.map +1 -0
- package/dist/client-react-native/src/storage/async-storage-adapter.js +78 -0
- package/dist/client-react-native/src/storage/async-storage-adapter.js.map +1 -0
- package/dist/client-react-native/src/storage/index.d.ts +2 -0
- package/dist/client-react-native/src/storage/index.d.ts.map +1 -0
- package/dist/client-react-native/src/storage/index.js +2 -0
- package/dist/client-react-native/src/storage/index.js.map +1 -0
- package/dist/shared-types/src/admin.d.ts +101 -0
- package/dist/shared-types/src/admin.d.ts.map +1 -0
- package/dist/shared-types/src/admin.js +3 -0
- package/dist/shared-types/src/admin.js.map +1 -0
- package/dist/shared-types/src/auth.d.ts +27 -0
- package/dist/shared-types/src/auth.d.ts.map +1 -0
- package/dist/shared-types/src/auth.js +2 -0
- package/dist/shared-types/src/auth.js.map +1 -0
- package/dist/shared-types/src/index.d.ts +5 -0
- package/dist/shared-types/src/index.d.ts.map +1 -0
- package/dist/shared-types/src/index.js +5 -0
- package/dist/shared-types/src/index.js.map +1 -0
- package/dist/shared-types/src/schema.d.ts +34 -0
- package/dist/shared-types/src/schema.d.ts.map +1 -0
- package/dist/shared-types/src/schema.js +2 -0
- package/dist/shared-types/src/schema.js.map +1 -0
- package/dist/shared-types/src/sync.d.ts +37 -0
- package/dist/shared-types/src/sync.d.ts.map +1 -0
- package/dist/shared-types/src/sync.js +2 -0
- package/dist/shared-types/src/sync.js.map +1 -0
- package/package.json +36 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { LoginRequest, RegisterRequest, User } from '@edgebasejs/types';
|
|
2
|
+
import type { IStorageAdapter } from '../storage/storage-adapter';
|
|
3
|
+
export interface AuthManagerOptions {
|
|
4
|
+
apiUrl: string;
|
|
5
|
+
storage: IStorageAdapter;
|
|
6
|
+
}
|
|
7
|
+
export interface AuthState {
|
|
8
|
+
user: User | null;
|
|
9
|
+
accessToken: string | null;
|
|
10
|
+
refreshToken: string | null;
|
|
11
|
+
isAuthenticated: boolean;
|
|
12
|
+
isLoading: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Client-side authentication manager
|
|
16
|
+
*/
|
|
17
|
+
export declare class AuthManager {
|
|
18
|
+
private apiUrl;
|
|
19
|
+
private storage;
|
|
20
|
+
private state;
|
|
21
|
+
private listeners;
|
|
22
|
+
constructor(options: AuthManagerOptions);
|
|
23
|
+
/**
|
|
24
|
+
* Initialize auth manager from storage
|
|
25
|
+
*/
|
|
26
|
+
init(): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* Register a new user
|
|
29
|
+
*/
|
|
30
|
+
register(request: RegisterRequest): Promise<User>;
|
|
31
|
+
/**
|
|
32
|
+
* Login with email and password
|
|
33
|
+
*/
|
|
34
|
+
login(request: LoginRequest): Promise<User>;
|
|
35
|
+
/**
|
|
36
|
+
* Refresh access token
|
|
37
|
+
*/
|
|
38
|
+
refreshAccessToken(): Promise<string>;
|
|
39
|
+
/**
|
|
40
|
+
* Logout
|
|
41
|
+
*/
|
|
42
|
+
logout(): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Get current auth state
|
|
45
|
+
*/
|
|
46
|
+
getState(): AuthState;
|
|
47
|
+
/**
|
|
48
|
+
* Get access token
|
|
49
|
+
*/
|
|
50
|
+
getAccessToken(): string | null;
|
|
51
|
+
/**
|
|
52
|
+
* Get current user
|
|
53
|
+
*/
|
|
54
|
+
getUser(): User | null;
|
|
55
|
+
/**
|
|
56
|
+
* Check if user is authenticated
|
|
57
|
+
*/
|
|
58
|
+
isAuthenticated(): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Subscribe to auth state changes
|
|
61
|
+
*/
|
|
62
|
+
subscribe(listener: (state: AuthState) => void): () => void;
|
|
63
|
+
/**
|
|
64
|
+
* Set tokens and update state
|
|
65
|
+
*/
|
|
66
|
+
private setTokens;
|
|
67
|
+
/**
|
|
68
|
+
* Notify all listeners of state change
|
|
69
|
+
*/
|
|
70
|
+
private notifyListeners;
|
|
71
|
+
}
|
|
72
|
+
export default AuthManager;
|
|
73
|
+
//# sourceMappingURL=auth-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-manager.d.ts","sourceRoot":"","sources":["../../../../../client-core/src/auth/auth-manager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAc,YAAY,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAMlE,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,eAAe,CAAC;CAC1B;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,eAAe,EAAE,OAAO,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,KAAK,CAAY;IACzB,OAAO,CAAC,SAAS,CAA8C;gBAEnD,OAAO,EAAE,kBAAkB;IAYvC;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAsB3B;;OAEG;IACG,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BvD;;OAEG;IACG,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BjD;;OAEG;IACG,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC;IAgC3C;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAoC7B;;OAEG;IACH,QAAQ,IAAI,SAAS;IAIrB;;OAEG;IACH,cAAc,IAAI,MAAM,GAAG,IAAI;IAI/B;;OAEG;IACH,OAAO,IAAI,IAAI,GAAG,IAAI;IAItB;;OAEG;IACH,eAAe,IAAI,OAAO;IAI1B;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,GAAG,MAAM,IAAI;IAK3D;;OAEG;YACW,SAAS;IAkBvB;;OAEG;IACH,OAAO,CAAC,eAAe;CAUxB;AAED,eAAe,WAAW,CAAC"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
// Client-side authentication manager
|
|
2
|
+
const ACCESS_TOKEN_KEY = 'auth:token';
|
|
3
|
+
const REFRESH_TOKEN_KEY = 'auth:refreshToken';
|
|
4
|
+
const USER_KEY = 'auth:user';
|
|
5
|
+
/**
|
|
6
|
+
* Client-side authentication manager
|
|
7
|
+
*/
|
|
8
|
+
export class AuthManager {
|
|
9
|
+
constructor(options) {
|
|
10
|
+
this.listeners = new Set();
|
|
11
|
+
this.apiUrl = options.apiUrl;
|
|
12
|
+
this.storage = options.storage;
|
|
13
|
+
this.state = {
|
|
14
|
+
user: null,
|
|
15
|
+
accessToken: null,
|
|
16
|
+
refreshToken: null,
|
|
17
|
+
isAuthenticated: false,
|
|
18
|
+
isLoading: false,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Initialize auth manager from storage
|
|
23
|
+
*/
|
|
24
|
+
async init() {
|
|
25
|
+
try {
|
|
26
|
+
const [user, accessToken, refreshToken] = await Promise.all([
|
|
27
|
+
this.storage.getItem(USER_KEY),
|
|
28
|
+
this.storage.getItem(ACCESS_TOKEN_KEY),
|
|
29
|
+
this.storage.getItem(REFRESH_TOKEN_KEY),
|
|
30
|
+
]);
|
|
31
|
+
this.state = {
|
|
32
|
+
user: user ? JSON.parse(user) : null,
|
|
33
|
+
accessToken: accessToken,
|
|
34
|
+
refreshToken: refreshToken,
|
|
35
|
+
isAuthenticated: !!accessToken && !!user,
|
|
36
|
+
isLoading: false,
|
|
37
|
+
};
|
|
38
|
+
this.notifyListeners();
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
console.error('Auth init error:', error);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Register a new user
|
|
46
|
+
*/
|
|
47
|
+
async register(request) {
|
|
48
|
+
this.state.isLoading = true;
|
|
49
|
+
this.notifyListeners();
|
|
50
|
+
try {
|
|
51
|
+
const response = await fetch(`${this.apiUrl}/auth/register`, {
|
|
52
|
+
method: 'POST',
|
|
53
|
+
headers: { 'Content-Type': 'application/json' },
|
|
54
|
+
body: JSON.stringify(request),
|
|
55
|
+
});
|
|
56
|
+
if (!response.ok) {
|
|
57
|
+
const error = await response.json();
|
|
58
|
+
throw new Error(error.error || 'Registration failed');
|
|
59
|
+
}
|
|
60
|
+
const data = await response.json();
|
|
61
|
+
await this.setTokens(data.user, data.tokens);
|
|
62
|
+
return data.user;
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
this.state.isLoading = false;
|
|
66
|
+
this.notifyListeners();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Login with email and password
|
|
71
|
+
*/
|
|
72
|
+
async login(request) {
|
|
73
|
+
this.state.isLoading = true;
|
|
74
|
+
this.notifyListeners();
|
|
75
|
+
try {
|
|
76
|
+
const response = await fetch(`${this.apiUrl}/auth/login`, {
|
|
77
|
+
method: 'POST',
|
|
78
|
+
headers: { 'Content-Type': 'application/json' },
|
|
79
|
+
body: JSON.stringify(request),
|
|
80
|
+
});
|
|
81
|
+
if (!response.ok) {
|
|
82
|
+
const error = await response.json();
|
|
83
|
+
throw new Error(error.error || 'Login failed');
|
|
84
|
+
}
|
|
85
|
+
const data = await response.json();
|
|
86
|
+
await this.setTokens(data.user, data.tokens);
|
|
87
|
+
return data.user;
|
|
88
|
+
}
|
|
89
|
+
finally {
|
|
90
|
+
this.state.isLoading = false;
|
|
91
|
+
this.notifyListeners();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Refresh access token
|
|
96
|
+
*/
|
|
97
|
+
async refreshAccessToken() {
|
|
98
|
+
if (!this.state.refreshToken) {
|
|
99
|
+
throw new Error('No refresh token available');
|
|
100
|
+
}
|
|
101
|
+
this.state.isLoading = true;
|
|
102
|
+
this.notifyListeners();
|
|
103
|
+
try {
|
|
104
|
+
const response = await fetch(`${this.apiUrl}/auth/refresh`, {
|
|
105
|
+
method: 'POST',
|
|
106
|
+
headers: { 'Content-Type': 'application/json' },
|
|
107
|
+
body: JSON.stringify({ refreshToken: this.state.refreshToken }),
|
|
108
|
+
});
|
|
109
|
+
if (!response.ok) {
|
|
110
|
+
await this.logout();
|
|
111
|
+
throw new Error('Token refresh failed');
|
|
112
|
+
}
|
|
113
|
+
const data = await response.json();
|
|
114
|
+
this.state.accessToken = data.accessToken;
|
|
115
|
+
await this.storage.setItem(ACCESS_TOKEN_KEY, data.accessToken);
|
|
116
|
+
this.notifyListeners();
|
|
117
|
+
return data.accessToken;
|
|
118
|
+
}
|
|
119
|
+
finally {
|
|
120
|
+
this.state.isLoading = false;
|
|
121
|
+
this.notifyListeners();
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Logout
|
|
126
|
+
*/
|
|
127
|
+
async logout() {
|
|
128
|
+
this.state.isLoading = true;
|
|
129
|
+
this.notifyListeners();
|
|
130
|
+
try {
|
|
131
|
+
if (this.state.accessToken) {
|
|
132
|
+
await fetch(`${this.apiUrl}/auth/logout`, {
|
|
133
|
+
method: 'POST',
|
|
134
|
+
headers: {
|
|
135
|
+
'Content-Type': 'application/json',
|
|
136
|
+
Authorization: `Bearer ${this.state.accessToken}`,
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
console.error('Logout error:', error);
|
|
143
|
+
}
|
|
144
|
+
finally {
|
|
145
|
+
// Clear local state
|
|
146
|
+
this.state = {
|
|
147
|
+
user: null,
|
|
148
|
+
accessToken: null,
|
|
149
|
+
refreshToken: null,
|
|
150
|
+
isAuthenticated: false,
|
|
151
|
+
isLoading: false,
|
|
152
|
+
};
|
|
153
|
+
await Promise.all([
|
|
154
|
+
this.storage.removeItem(USER_KEY),
|
|
155
|
+
this.storage.removeItem(ACCESS_TOKEN_KEY),
|
|
156
|
+
this.storage.removeItem(REFRESH_TOKEN_KEY),
|
|
157
|
+
]);
|
|
158
|
+
this.notifyListeners();
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Get current auth state
|
|
163
|
+
*/
|
|
164
|
+
getState() {
|
|
165
|
+
return { ...this.state };
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Get access token
|
|
169
|
+
*/
|
|
170
|
+
getAccessToken() {
|
|
171
|
+
return this.state.accessToken;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Get current user
|
|
175
|
+
*/
|
|
176
|
+
getUser() {
|
|
177
|
+
return this.state.user;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Check if user is authenticated
|
|
181
|
+
*/
|
|
182
|
+
isAuthenticated() {
|
|
183
|
+
return this.state.isAuthenticated;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Subscribe to auth state changes
|
|
187
|
+
*/
|
|
188
|
+
subscribe(listener) {
|
|
189
|
+
this.listeners.add(listener);
|
|
190
|
+
return () => this.listeners.delete(listener);
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Set tokens and update state
|
|
194
|
+
*/
|
|
195
|
+
async setTokens(user, tokens) {
|
|
196
|
+
this.state = {
|
|
197
|
+
user,
|
|
198
|
+
accessToken: tokens.accessToken,
|
|
199
|
+
refreshToken: tokens.refreshToken,
|
|
200
|
+
isAuthenticated: true,
|
|
201
|
+
isLoading: false,
|
|
202
|
+
};
|
|
203
|
+
await Promise.all([
|
|
204
|
+
this.storage.setItem(USER_KEY, JSON.stringify(user)),
|
|
205
|
+
this.storage.setItem(ACCESS_TOKEN_KEY, tokens.accessToken),
|
|
206
|
+
this.storage.setItem(REFRESH_TOKEN_KEY, tokens.refreshToken),
|
|
207
|
+
]);
|
|
208
|
+
this.notifyListeners();
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Notify all listeners of state change
|
|
212
|
+
*/
|
|
213
|
+
notifyListeners() {
|
|
214
|
+
const state = this.getState();
|
|
215
|
+
for (const listener of this.listeners) {
|
|
216
|
+
try {
|
|
217
|
+
listener(state);
|
|
218
|
+
}
|
|
219
|
+
catch (error) {
|
|
220
|
+
console.error('Listener error:', error);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
export default AuthManager;
|
|
226
|
+
//# sourceMappingURL=auth-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-manager.js","sourceRoot":"","sources":["../../../../../client-core/src/auth/auth-manager.ts"],"names":[],"mappings":"AAAA,qCAAqC;AAKrC,MAAM,gBAAgB,GAAG,YAAY,CAAC;AACtC,MAAM,iBAAiB,GAAG,mBAAmB,CAAC;AAC9C,MAAM,QAAQ,GAAG,WAAW,CAAC;AAe7B;;GAEG;AACH,MAAM,OAAO,WAAW;IAMtB,YAAY,OAA2B;QAF/B,cAAS,GAAoC,IAAI,GAAG,EAAE,CAAC;QAG7D,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAC/B,IAAI,CAAC,KAAK,GAAG;YACX,IAAI,EAAE,IAAI;YACV,WAAW,EAAE,IAAI;YACjB,YAAY,EAAE,IAAI;YAClB,eAAe,EAAE,KAAK;YACtB,SAAS,EAAE,KAAK;SACjB,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,IAAI;QACR,IAAI,CAAC;YACH,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,YAAY,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;gBAC1D,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC;gBAC9B,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC;gBACtC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC;aACxC,CAAC,CAAC;YAEH,IAAI,CAAC,KAAK,GAAG;gBACX,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI;gBACpC,WAAW,EAAE,WAAW;gBACxB,YAAY,EAAE,YAAY;gBAC1B,eAAe,EAAE,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,IAAI;gBACxC,SAAS,EAAE,KAAK;aACjB,CAAC;YAEF,IAAI,CAAC,eAAe,EAAE,CAAC;QACzB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,QAAQ,CAAC,OAAwB;QACrC,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC;QAC5B,IAAI,CAAC,eAAe,EAAE,CAAC;QAEvB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,gBAAgB,EAAE;gBAC3D,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;aAC9B,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACpC,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,IAAI,qBAAqB,CAAC,CAAC;YACxD,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;YAE7C,OAAO,IAAI,CAAC,IAAI,CAAC;QACnB,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC;YAC7B,IAAI,CAAC,eAAe,EAAE,CAAC;QACzB,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,KAAK,CAAC,OAAqB;QAC/B,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC;QAC5B,IAAI,CAAC,eAAe,EAAE,CAAC;QAEvB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,aAAa,EAAE;gBACxD,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;aAC9B,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACpC,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,IAAI,cAAc,CAAC,CAAC;YACjD,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;YAE7C,OAAO,IAAI,CAAC,IAAI,CAAC;QACnB,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC;YAC7B,IAAI,CAAC,eAAe,EAAE,CAAC;QACzB,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,kBAAkB;QACtB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAChD,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC;QAC5B,IAAI,CAAC,eAAe,EAAE,CAAC;QAEvB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,eAAe,EAAE;gBAC1D,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC;aAChE,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;gBACpB,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;YAC1C,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;YAC1C,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,gBAAgB,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;YAC/D,IAAI,CAAC,eAAe,EAAE,CAAC;YAEvB,OAAO,IAAI,CAAC,WAAW,CAAC;QAC1B,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC;YAC7B,IAAI,CAAC,eAAe,EAAE,CAAC;QACzB,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,MAAM;QACV,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC;QAC5B,IAAI,CAAC,eAAe,EAAE,CAAC;QAEvB,IAAI,CAAC;YACH,IAAI,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;gBAC3B,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,cAAc,EAAE;oBACxC,MAAM,EAAE,MAAM;oBACd,OAAO,EAAE;wBACP,cAAc,EAAE,kBAAkB;wBAClC,aAAa,EAAE,UAAU,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE;qBAClD;iBACF,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;QACxC,CAAC;gBAAS,CAAC;YACT,oBAAoB;YACpB,IAAI,CAAC,KAAK,GAAG;gBACX,IAAI,EAAE,IAAI;gBACV,WAAW,EAAE,IAAI;gBACjB,YAAY,EAAE,IAAI;gBAClB,eAAe,EAAE,KAAK;gBACtB,SAAS,EAAE,KAAK;aACjB,CAAC;YAEF,MAAM,OAAO,CAAC,GAAG,CAAC;gBAChB,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC;gBACjC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,gBAAgB,CAAC;gBACzC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,iBAAiB,CAAC;aAC3C,CAAC,CAAC;YAEH,IAAI,CAAC,eAAe,EAAE,CAAC;QACzB,CAAC;IACH,CAAC;IAED;;OAEG;IACH,QAAQ;QACN,OAAO,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,cAAc;QACZ,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,OAAO;QACL,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACzB,CAAC;IAED;;OAEG;IACH,eAAe;QACb,OAAO,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC;IACpC,CAAC;IAED;;OAEG;IACH,SAAS,CAAC,QAAoC;QAC5C,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC7B,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC/C,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,SAAS,CAAC,IAAU,EAAE,MAAkB;QACpD,IAAI,CAAC,KAAK,GAAG;YACX,IAAI;YACJ,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,YAAY,EAAE,MAAM,CAAC,YAAY;YACjC,eAAe,EAAE,IAAI;YACrB,SAAS,EAAE,KAAK;SACjB,CAAC;QAEF,MAAM,OAAO,CAAC,GAAG,CAAC;YAChB,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YACpD,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,gBAAgB,EAAE,MAAM,CAAC,WAAW,CAAC;YAC1D,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,iBAAiB,EAAE,MAAM,CAAC,YAAY,CAAC;SAC7D,CAAC,CAAC;QAEH,IAAI,CAAC,eAAe,EAAE,CAAC;IACzB,CAAC;IAED;;OAEG;IACK,eAAe;QACrB,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC9B,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACtC,IAAI,CAAC;gBACH,QAAQ,CAAC,KAAK,CAAC,CAAC;YAClB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;IACH,CAAC;CACF;AAED,eAAe,WAAW,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../client-core/src/auth/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../client-core/src/auth/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conflict resolution strategies
|
|
3
|
+
*/
|
|
4
|
+
export type ConflictResolutionStrategy = 'last-write-wins' | 'client-wins' | 'server-wins' | 'manual';
|
|
5
|
+
/**
|
|
6
|
+
* Conflict information
|
|
7
|
+
*/
|
|
8
|
+
export interface Conflict {
|
|
9
|
+
entity: string;
|
|
10
|
+
recordId: string;
|
|
11
|
+
clientVersion: number;
|
|
12
|
+
serverVersion: number;
|
|
13
|
+
clientData: Record<string, any>;
|
|
14
|
+
serverData: Record<string, any>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Resolution result
|
|
18
|
+
*/
|
|
19
|
+
export interface ResolutionResult {
|
|
20
|
+
conflict: Conflict;
|
|
21
|
+
strategy: ConflictResolutionStrategy;
|
|
22
|
+
resolvedData: Record<string, any>;
|
|
23
|
+
keepLocal: boolean;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Conflict resolver - handles merge strategy for conflicting changes
|
|
27
|
+
*/
|
|
28
|
+
export declare class ConflictResolver {
|
|
29
|
+
/**
|
|
30
|
+
* Resolve conflict using Last-Write-Wins strategy
|
|
31
|
+
* Server timestamp is considered the "last write" since it's authoritative
|
|
32
|
+
*/
|
|
33
|
+
static resolveLWW(conflict: Conflict): ResolutionResult;
|
|
34
|
+
/**
|
|
35
|
+
* Resolve by keeping client version
|
|
36
|
+
* Useful for optimistic UI updates where client has latest info
|
|
37
|
+
*/
|
|
38
|
+
static resolveClientWins(conflict: Conflict): ResolutionResult;
|
|
39
|
+
/**
|
|
40
|
+
* Resolve by keeping server version
|
|
41
|
+
*/
|
|
42
|
+
static resolveServerWins(conflict: Conflict): ResolutionResult;
|
|
43
|
+
/**
|
|
44
|
+
* Auto-resolve conflicts with a strategy
|
|
45
|
+
*/
|
|
46
|
+
static autoResolve(conflict: Conflict, strategy?: ConflictResolutionStrategy): ResolutionResult;
|
|
47
|
+
/**
|
|
48
|
+
* Merge changes using field-level conflict resolution
|
|
49
|
+
* Takes changes from both sides and merges them intelligently
|
|
50
|
+
*/
|
|
51
|
+
static merge(clientData: Record<string, any>, serverData: Record<string, any>, strategy?: 'client-wins' | 'server-wins'): Record<string, any>;
|
|
52
|
+
/**
|
|
53
|
+
* Detect conflicts between two versions
|
|
54
|
+
*/
|
|
55
|
+
static detectConflict(clientVersion: number, serverVersion: number): boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Get changed fields between two objects
|
|
58
|
+
*/
|
|
59
|
+
static getChangedFields(before: Record<string, any>, after: Record<string, any>): string[];
|
|
60
|
+
}
|
|
61
|
+
export default ConflictResolver;
|
|
62
|
+
//# sourceMappingURL=conflict-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conflict-resolver.d.ts","sourceRoot":"","sources":["../../../../../client-core/src/conflict/conflict-resolver.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,MAAM,0BAA0B,GAClC,iBAAiB,GACjB,aAAa,GACb,aAAa,GACb,QAAQ,CAAC;AAEb;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAChC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,EAAE,0BAA0B,CAAC;IACrC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAClC,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,qBAAa,gBAAgB;IAC3B;;;OAGG;IACH,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,gBAAgB;IAWvD;;;OAGG;IACH,MAAM,CAAC,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,GAAG,gBAAgB;IAS9D;;OAEG;IACH,MAAM,CAAC,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,GAAG,gBAAgB;IAS9D;;OAEG;IACH,MAAM,CAAC,WAAW,CAChB,QAAQ,EAAE,QAAQ,EAClB,QAAQ,GAAE,0BAA8C,GACvD,gBAAgB;IAenB;;;OAGG;IACH,MAAM,CAAC,KAAK,CACV,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC/B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC/B,QAAQ,GAAE,aAAa,GAAG,aAA6B,GACtD,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAgBtB;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,aAAa,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO;IAI5E;;OAEG;IACH,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,EAAE;CAiB3F;AAED,eAAe,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// Conflict resolution engine
|
|
2
|
+
/**
|
|
3
|
+
* Conflict resolver - handles merge strategy for conflicting changes
|
|
4
|
+
*/
|
|
5
|
+
export class ConflictResolver {
|
|
6
|
+
/**
|
|
7
|
+
* Resolve conflict using Last-Write-Wins strategy
|
|
8
|
+
* Server timestamp is considered the "last write" since it's authoritative
|
|
9
|
+
*/
|
|
10
|
+
static resolveLWW(conflict) {
|
|
11
|
+
// Server always wins in Last-Write-Wins
|
|
12
|
+
// Client should discard local version and use server data
|
|
13
|
+
return {
|
|
14
|
+
conflict,
|
|
15
|
+
strategy: 'last-write-wins',
|
|
16
|
+
resolvedData: conflict.serverData,
|
|
17
|
+
keepLocal: false, // Discard local version
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Resolve by keeping client version
|
|
22
|
+
* Useful for optimistic UI updates where client has latest info
|
|
23
|
+
*/
|
|
24
|
+
static resolveClientWins(conflict) {
|
|
25
|
+
return {
|
|
26
|
+
conflict,
|
|
27
|
+
strategy: 'client-wins',
|
|
28
|
+
resolvedData: conflict.clientData,
|
|
29
|
+
keepLocal: true,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Resolve by keeping server version
|
|
34
|
+
*/
|
|
35
|
+
static resolveServerWins(conflict) {
|
|
36
|
+
return {
|
|
37
|
+
conflict,
|
|
38
|
+
strategy: 'server-wins',
|
|
39
|
+
resolvedData: conflict.serverData,
|
|
40
|
+
keepLocal: false,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Auto-resolve conflicts with a strategy
|
|
45
|
+
*/
|
|
46
|
+
static autoResolve(conflict, strategy = 'last-write-wins') {
|
|
47
|
+
switch (strategy) {
|
|
48
|
+
case 'last-write-wins':
|
|
49
|
+
return this.resolveLWW(conflict);
|
|
50
|
+
case 'client-wins':
|
|
51
|
+
return this.resolveClientWins(conflict);
|
|
52
|
+
case 'server-wins':
|
|
53
|
+
return this.resolveServerWins(conflict);
|
|
54
|
+
case 'manual':
|
|
55
|
+
throw new Error('Manual resolution not supported in autoResolve');
|
|
56
|
+
default:
|
|
57
|
+
return this.resolveLWW(conflict);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Merge changes using field-level conflict resolution
|
|
62
|
+
* Takes changes from both sides and merges them intelligently
|
|
63
|
+
*/
|
|
64
|
+
static merge(clientData, serverData, strategy = 'server-wins') {
|
|
65
|
+
const merged = { ...serverData };
|
|
66
|
+
if (strategy === 'client-wins') {
|
|
67
|
+
// Client overwrites server for changed fields
|
|
68
|
+
for (const key in clientData) {
|
|
69
|
+
if (clientData[key] !== serverData[key]) {
|
|
70
|
+
merged[key] = clientData[key];
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// For server-wins, we already have serverData as base
|
|
75
|
+
return merged;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Detect conflicts between two versions
|
|
79
|
+
*/
|
|
80
|
+
static detectConflict(clientVersion, serverVersion) {
|
|
81
|
+
return clientVersion !== serverVersion;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Get changed fields between two objects
|
|
85
|
+
*/
|
|
86
|
+
static getChangedFields(before, after) {
|
|
87
|
+
const changed = [];
|
|
88
|
+
for (const key in after) {
|
|
89
|
+
if (after[key] !== before[key]) {
|
|
90
|
+
changed.push(key);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
for (const key in before) {
|
|
94
|
+
if (!(key in after)) {
|
|
95
|
+
changed.push(key);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return changed;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
export default ConflictResolver;
|
|
102
|
+
//# sourceMappingURL=conflict-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conflict-resolver.js","sourceRoot":"","sources":["../../../../../client-core/src/conflict/conflict-resolver.ts"],"names":[],"mappings":"AAAA,6BAA6B;AAiC7B;;GAEG;AACH,MAAM,OAAO,gBAAgB;IAC3B;;;OAGG;IACH,MAAM,CAAC,UAAU,CAAC,QAAkB;QAClC,wCAAwC;QACxC,0DAA0D;QAC1D,OAAO;YACL,QAAQ;YACR,QAAQ,EAAE,iBAAiB;YAC3B,YAAY,EAAE,QAAQ,CAAC,UAAU;YACjC,SAAS,EAAE,KAAK,EAAE,wBAAwB;SAC3C,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,iBAAiB,CAAC,QAAkB;QACzC,OAAO;YACL,QAAQ;YACR,QAAQ,EAAE,aAAa;YACvB,YAAY,EAAE,QAAQ,CAAC,UAAU;YACjC,SAAS,EAAE,IAAI;SAChB,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,iBAAiB,CAAC,QAAkB;QACzC,OAAO;YACL,QAAQ;YACR,QAAQ,EAAE,aAAa;YACvB,YAAY,EAAE,QAAQ,CAAC,UAAU;YACjC,SAAS,EAAE,KAAK;SACjB,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,WAAW,CAChB,QAAkB,EAClB,WAAuC,iBAAiB;QAExD,QAAQ,QAAQ,EAAE,CAAC;YACjB,KAAK,iBAAiB;gBACpB,OAAO,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;YACnC,KAAK,aAAa;gBAChB,OAAO,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;YAC1C,KAAK,aAAa;gBAChB,OAAO,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;YAC1C,KAAK,QAAQ;gBACX,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;YACpE;gBACE,OAAO,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,KAAK,CACV,UAA+B,EAC/B,UAA+B,EAC/B,WAA0C,aAAa;QAEvD,MAAM,MAAM,GAAG,EAAE,GAAG,UAAU,EAAE,CAAC;QAEjC,IAAI,QAAQ,KAAK,aAAa,EAAE,CAAC;YAC/B,8CAA8C;YAC9C,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;gBAC7B,IAAI,UAAU,CAAC,GAAG,CAAC,KAAK,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;oBACxC,MAAM,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;gBAChC,CAAC;YACH,CAAC;QACH,CAAC;QACD,sDAAsD;QAEtD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,aAAqB,EAAE,aAAqB;QAChE,OAAO,aAAa,KAAK,aAAa,CAAC;IACzC,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,gBAAgB,CAAC,MAA2B,EAAE,KAA0B;QAC7E,MAAM,OAAO,GAAa,EAAE,CAAC;QAE7B,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;YACxB,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC/B,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACpB,CAAC;QACH,CAAC;QAED,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;YACzB,IAAI,CAAC,CAAC,GAAG,IAAI,KAAK,CAAC,EAAE,CAAC;gBACpB,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACpB,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;CACF;AAED,eAAe,gBAAgB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../client-core/src/conflict/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../client-core/src/conflict/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../client-core/src/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../client-core/src/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../client-core/src/outbox/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../client-core/src/outbox/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { IStorageAdapter } from '../storage/storage-adapter';
|
|
2
|
+
export interface OutboxEntry {
|
|
3
|
+
id: string;
|
|
4
|
+
entity: string;
|
|
5
|
+
operation: 'create' | 'update' | 'delete';
|
|
6
|
+
recordId: string;
|
|
7
|
+
data: Record<string, any>;
|
|
8
|
+
clientTimestamp: number;
|
|
9
|
+
version: number;
|
|
10
|
+
attempts: number;
|
|
11
|
+
lastError?: string;
|
|
12
|
+
lastAttempt?: number;
|
|
13
|
+
}
|
|
14
|
+
export interface OutboxOptions {
|
|
15
|
+
maxRetries?: number;
|
|
16
|
+
retryDelayMs?: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Outbox manager - tracks offline changes waiting to be synced
|
|
20
|
+
*/
|
|
21
|
+
export declare class OutboxManager {
|
|
22
|
+
private storage;
|
|
23
|
+
private outboxKey;
|
|
24
|
+
private maxRetries;
|
|
25
|
+
private retryDelayMs;
|
|
26
|
+
private entries;
|
|
27
|
+
constructor(storage: IStorageAdapter, options?: OutboxOptions);
|
|
28
|
+
/**
|
|
29
|
+
* Initialize outbox from storage
|
|
30
|
+
*/
|
|
31
|
+
init(): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Add entry to outbox
|
|
34
|
+
*/
|
|
35
|
+
add(entry: Omit<OutboxEntry, 'id' | 'attempts'>): Promise<OutboxEntry>;
|
|
36
|
+
/**
|
|
37
|
+
* Get all pending entries
|
|
38
|
+
*/
|
|
39
|
+
getPending(): Promise<OutboxEntry[]>;
|
|
40
|
+
/**
|
|
41
|
+
* Get pending entries for an entity
|
|
42
|
+
*/
|
|
43
|
+
getPendingForEntity(entity: string): Promise<OutboxEntry[]>;
|
|
44
|
+
/**
|
|
45
|
+
* Mark entry as synced (remove from outbox)
|
|
46
|
+
*/
|
|
47
|
+
markSynced(entryId: string): Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* Mark multiple entries as synced
|
|
50
|
+
*/
|
|
51
|
+
markSyncedBatch(entryIds: string[]): Promise<void>;
|
|
52
|
+
/**
|
|
53
|
+
* Record failed sync attempt
|
|
54
|
+
*/
|
|
55
|
+
recordFailure(entryId: string, error: string): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Check if entry is ready to retry (exponential backoff)
|
|
58
|
+
*/
|
|
59
|
+
isReadyToRetry(entryId: string): Promise<boolean>;
|
|
60
|
+
/**
|
|
61
|
+
* Get entries ready for retry
|
|
62
|
+
*/
|
|
63
|
+
getReadyForRetry(): Promise<OutboxEntry[]>;
|
|
64
|
+
/**
|
|
65
|
+
* Clear outbox
|
|
66
|
+
*/
|
|
67
|
+
clear(): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Get entry by ID
|
|
70
|
+
*/
|
|
71
|
+
getEntry(id: string): Promise<OutboxEntry | null>;
|
|
72
|
+
/**
|
|
73
|
+
* Get all entries (for debugging)
|
|
74
|
+
*/
|
|
75
|
+
getAll(): Promise<OutboxEntry[]>;
|
|
76
|
+
/**
|
|
77
|
+
* Persist entries to storage
|
|
78
|
+
*/
|
|
79
|
+
private persist;
|
|
80
|
+
}
|
|
81
|
+
export default OutboxManager;
|
|
82
|
+
//# sourceMappingURL=outbox-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outbox-manager.d.ts","sourceRoot":"","sources":["../../../../../client-core/src/outbox/outbox-manager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAElE,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,OAAO,CAAuC;gBAE1C,OAAO,EAAE,eAAe,EAAE,OAAO,GAAE,aAAkB;IAMjE;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAc3B;;OAEG;IACG,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,GAAG,UAAU,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC;IAc5E;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAI1C;;OAEG;IACG,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAIjE;;OAEG;IACG,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKhD;;OAEG;IACG,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAOxD;;OAEG;IACG,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUlE;;OAEG;IACG,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAavD;;OAEG;IACG,gBAAgB,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAahD;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAK5B;;OAEG;IACG,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAIvD;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAItC;;OAEG;YACW,OAAO;CAQtB;AAED,eAAe,aAAa,CAAC"}
|