@edgebasejs/core 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/core/src/access-rules/engine.d.ts +26 -0
- package/dist/core/src/access-rules/engine.d.ts.map +1 -0
- package/dist/core/src/access-rules/engine.js +75 -0
- package/dist/core/src/access-rules/engine.js.map +1 -0
- package/dist/core/src/access-rules/index.d.ts +3 -0
- package/dist/core/src/access-rules/index.d.ts.map +1 -0
- package/dist/core/src/access-rules/index.js +3 -0
- package/dist/core/src/access-rules/index.js.map +1 -0
- package/dist/core/src/auth/auth-service.d.ts +71 -0
- package/dist/core/src/auth/auth-service.d.ts.map +1 -0
- package/dist/core/src/auth/auth-service.js +177 -0
- package/dist/core/src/auth/auth-service.js.map +1 -0
- package/dist/core/src/auth/index.d.ts +4 -0
- package/dist/core/src/auth/index.d.ts.map +1 -0
- package/dist/core/src/auth/index.js +4 -0
- package/dist/core/src/auth/index.js.map +1 -0
- package/dist/core/src/index.d.ts +4 -0
- package/dist/core/src/index.d.ts.map +1 -0
- package/dist/core/src/index.js +4 -0
- package/dist/core/src/index.js.map +1 -0
- package/dist/core/src/sync/index.d.ts +3 -0
- package/dist/core/src/sync/index.d.ts.map +1 -0
- package/dist/core/src/sync/index.js +3 -0
- package/dist/core/src/sync/index.js.map +1 -0
- package/dist/core/src/sync/sync-engine.d.ts +46 -0
- package/dist/core/src/sync/sync-engine.d.ts.map +1 -0
- package/dist/core/src/sync/sync-engine.js +204 -0
- package/dist/core/src/sync/sync-engine.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 +26 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { User, AccessRules } from '@edgebasejs/types';
|
|
2
|
+
export interface AccessContext {
|
|
3
|
+
user: User;
|
|
4
|
+
operation: 'create' | 'read' | 'update' | 'delete';
|
|
5
|
+
data: Record<string, any>;
|
|
6
|
+
existingData?: Record<string, any>;
|
|
7
|
+
}
|
|
8
|
+
export interface AccessDecision {
|
|
9
|
+
allowed: boolean;
|
|
10
|
+
reason?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Access rules engine
|
|
14
|
+
*/
|
|
15
|
+
export declare class AccessRulesEngine {
|
|
16
|
+
/**
|
|
17
|
+
* Evaluate access rules for an operation
|
|
18
|
+
*/
|
|
19
|
+
static evaluate(context: AccessContext, rules?: AccessRules): Promise<AccessDecision>;
|
|
20
|
+
/**
|
|
21
|
+
* Batch evaluate access for multiple records
|
|
22
|
+
*/
|
|
23
|
+
static evaluateBatch(contexts: AccessContext[], rules?: AccessRules): Promise<Map<string, AccessDecision>>;
|
|
24
|
+
}
|
|
25
|
+
export default AccessRulesEngine;
|
|
26
|
+
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../../src/access-rules/engine.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAE3D,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,IAAI,CAAC;IACX,SAAS,EAAE,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACnD,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,qBAAa,iBAAiB;IAC5B;;OAEG;WACU,QAAQ,CAAC,OAAO,EAAE,aAAa,EAAE,KAAK,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC;IA2D3F;;OAEG;WACU,aAAa,CACxB,QAAQ,EAAE,aAAa,EAAE,EACzB,KAAK,CAAC,EAAE,WAAW,GAClB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;CAWxC;AAED,eAAe,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// Access rules evaluation engine
|
|
2
|
+
/**
|
|
3
|
+
* Access rules engine
|
|
4
|
+
*/
|
|
5
|
+
export class AccessRulesEngine {
|
|
6
|
+
/**
|
|
7
|
+
* Evaluate access rules for an operation
|
|
8
|
+
*/
|
|
9
|
+
static async evaluate(context, rules) {
|
|
10
|
+
if (!rules) {
|
|
11
|
+
// No rules = allow all access
|
|
12
|
+
return { allowed: true };
|
|
13
|
+
}
|
|
14
|
+
try {
|
|
15
|
+
switch (context.operation) {
|
|
16
|
+
case 'create':
|
|
17
|
+
if (!rules.create) {
|
|
18
|
+
return { allowed: true }; // No rule = allow
|
|
19
|
+
}
|
|
20
|
+
const createAllowed = await Promise.resolve(rules.create(context.user, context.data));
|
|
21
|
+
return {
|
|
22
|
+
allowed: createAllowed,
|
|
23
|
+
reason: createAllowed ? undefined : 'Create denied by access rules',
|
|
24
|
+
};
|
|
25
|
+
case 'read':
|
|
26
|
+
if (!rules.read) {
|
|
27
|
+
return { allowed: true };
|
|
28
|
+
}
|
|
29
|
+
const readAllowed = await Promise.resolve(rules.read(context.user, context.data));
|
|
30
|
+
return {
|
|
31
|
+
allowed: readAllowed,
|
|
32
|
+
reason: readAllowed ? undefined : 'Read denied by access rules',
|
|
33
|
+
};
|
|
34
|
+
case 'update':
|
|
35
|
+
if (!rules.update) {
|
|
36
|
+
return { allowed: true };
|
|
37
|
+
}
|
|
38
|
+
const updateAllowed = await Promise.resolve(rules.update(context.user, context.existingData || {}, context.data));
|
|
39
|
+
return {
|
|
40
|
+
allowed: updateAllowed,
|
|
41
|
+
reason: updateAllowed ? undefined : 'Update denied by access rules',
|
|
42
|
+
};
|
|
43
|
+
case 'delete':
|
|
44
|
+
if (!rules.delete) {
|
|
45
|
+
return { allowed: true };
|
|
46
|
+
}
|
|
47
|
+
const deleteAllowed = await Promise.resolve(rules.delete(context.user, context.data));
|
|
48
|
+
return {
|
|
49
|
+
allowed: deleteAllowed,
|
|
50
|
+
reason: deleteAllowed ? undefined : 'Delete denied by access rules',
|
|
51
|
+
};
|
|
52
|
+
default:
|
|
53
|
+
return { allowed: false, reason: 'Unknown operation' };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
console.error('Access rule evaluation error:', error);
|
|
58
|
+
return { allowed: false, reason: 'Access rule evaluation failed' };
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Batch evaluate access for multiple records
|
|
63
|
+
*/
|
|
64
|
+
static async evaluateBatch(contexts, rules) {
|
|
65
|
+
const results = new Map();
|
|
66
|
+
for (const context of contexts) {
|
|
67
|
+
const recordKey = `${context.operation}:${context.data.id || 'unknown'}`;
|
|
68
|
+
const decision = await this.evaluate(context, rules);
|
|
69
|
+
results.set(recordKey, decision);
|
|
70
|
+
}
|
|
71
|
+
return results;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
export default AccessRulesEngine;
|
|
75
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../../../src/access-rules/engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/access-rules/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/access-rules/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { User, AuthTokens, LoginRequest, RegisterRequest } from '@edgebasejs/types';
|
|
3
|
+
export declare const LoginSchema: z.ZodObject<{
|
|
4
|
+
email: z.ZodString;
|
|
5
|
+
password: z.ZodString;
|
|
6
|
+
}, "strip", z.ZodTypeAny, {
|
|
7
|
+
email: string;
|
|
8
|
+
password: string;
|
|
9
|
+
}, {
|
|
10
|
+
email: string;
|
|
11
|
+
password: string;
|
|
12
|
+
}>;
|
|
13
|
+
export declare const RegisterSchema: z.ZodObject<{
|
|
14
|
+
email: z.ZodString;
|
|
15
|
+
password: z.ZodString;
|
|
16
|
+
}, "strip", z.ZodTypeAny, {
|
|
17
|
+
email: string;
|
|
18
|
+
password: string;
|
|
19
|
+
}, {
|
|
20
|
+
email: string;
|
|
21
|
+
password: string;
|
|
22
|
+
}>;
|
|
23
|
+
/**
|
|
24
|
+
* Password hashing utilities
|
|
25
|
+
* For D1/Cloudflare, we use PBKDF2 (built-in Web Crypto API)
|
|
26
|
+
*/
|
|
27
|
+
export declare function hashPassword(password: string): Promise<string>;
|
|
28
|
+
/**
|
|
29
|
+
* Verify password against hash
|
|
30
|
+
*/
|
|
31
|
+
export declare function verifyPassword(password: string, hash: string): Promise<boolean>;
|
|
32
|
+
/**
|
|
33
|
+
* JWT token generation and verification
|
|
34
|
+
*/
|
|
35
|
+
export interface JWTPayload {
|
|
36
|
+
userId: string;
|
|
37
|
+
email: string;
|
|
38
|
+
iat: number;
|
|
39
|
+
exp: number;
|
|
40
|
+
type: 'access' | 'refresh';
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Create JWT token (simple implementation without external library)
|
|
44
|
+
* Note: In production, consider using a library like `jose` or `jsonwebtoken`
|
|
45
|
+
*/
|
|
46
|
+
export declare function createJWT(payload: Omit<JWTPayload, 'iat' | 'exp'>, secret: string, expiresIn: number): string;
|
|
47
|
+
/**
|
|
48
|
+
* Parse JWT token (simple implementation)
|
|
49
|
+
*/
|
|
50
|
+
export declare function parseJWT(token: string): JWTPayload | null;
|
|
51
|
+
/**
|
|
52
|
+
* Authentication service
|
|
53
|
+
*/
|
|
54
|
+
export declare class AuthService {
|
|
55
|
+
/**
|
|
56
|
+
* Register a new user
|
|
57
|
+
*/
|
|
58
|
+
static registerUser(request: RegisterRequest, onCreateUser: (user: User) => Promise<void>): Promise<User>;
|
|
59
|
+
/**
|
|
60
|
+
* Login user
|
|
61
|
+
*/
|
|
62
|
+
static loginUser(request: LoginRequest, onGetUser: (email: string) => Promise<User & {
|
|
63
|
+
passwordHash: string;
|
|
64
|
+
}>, secret: string): Promise<AuthTokens>;
|
|
65
|
+
/**
|
|
66
|
+
* Refresh access token
|
|
67
|
+
*/
|
|
68
|
+
static refreshToken(refreshToken: string, secret: string): string;
|
|
69
|
+
}
|
|
70
|
+
export default AuthService;
|
|
71
|
+
//# sourceMappingURL=auth-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-service.d.ts","sourceRoot":"","sources":["../../../../src/auth/auth-service.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGzF,eAAO,MAAM,WAAW;;;;;;;;;EAGtB,CAAC;AAEH,eAAO,MAAM,cAAc;;;;;;;;;EAGzB,CAAC;AAEH;;;GAGG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA6BpE;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CA4CrF;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,QAAQ,GAAG,SAAS,CAAC;CAC5B;AAED;;;GAGG;AACH,wBAAgB,SAAS,CACvB,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE,KAAK,GAAG,KAAK,CAAC,EACxC,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,MAAM,CAmBR;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAkBzD;AAED;;GAEG;AACH,qBAAa,WAAW;IACtB;;OAEG;WACU,YAAY,CACvB,OAAO,EAAE,eAAe,EACxB,YAAY,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,GAC1C,OAAO,CAAC,IAAI,CAAC;IAuBhB;;OAEG;WACU,SAAS,CACpB,OAAO,EAAE,YAAY,EACrB,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,GAAG;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC,EACtE,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,UAAU,CAAC;IAiCtB;;OAEG;IACH,MAAM,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM;CAYlE;AAED,eAAe,WAAW,CAAC"}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
// Authentication service
|
|
2
|
+
// Handles password hashing, JWT generation, and token management
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
// Validation schemas
|
|
5
|
+
export const LoginSchema = z.object({
|
|
6
|
+
email: z.string().email('Invalid email'),
|
|
7
|
+
password: z.string().min(8, 'Password must be at least 8 characters'),
|
|
8
|
+
});
|
|
9
|
+
export const RegisterSchema = z.object({
|
|
10
|
+
email: z.string().email('Invalid email'),
|
|
11
|
+
password: z.string().min(8, 'Password must be at least 8 characters'),
|
|
12
|
+
});
|
|
13
|
+
/**
|
|
14
|
+
* Password hashing utilities
|
|
15
|
+
* For D1/Cloudflare, we use PBKDF2 (built-in Web Crypto API)
|
|
16
|
+
*/
|
|
17
|
+
export async function hashPassword(password) {
|
|
18
|
+
// Using PBKDF2 with Web Crypto API available in Cloudflare Workers
|
|
19
|
+
const encoder = new TextEncoder();
|
|
20
|
+
const data = encoder.encode(password);
|
|
21
|
+
const salt = crypto.getRandomValues(new Uint8Array(16));
|
|
22
|
+
const key = await crypto.subtle.importKey('raw', data, { name: 'PBKDF2' }, false, ['deriveBits']);
|
|
23
|
+
const bits = await crypto.subtle.deriveBits({
|
|
24
|
+
name: 'PBKDF2',
|
|
25
|
+
salt: salt,
|
|
26
|
+
iterations: 100000,
|
|
27
|
+
hash: 'SHA-256',
|
|
28
|
+
}, key, 256);
|
|
29
|
+
// Combine salt + hash and encode as hex
|
|
30
|
+
const hashArray = new Uint8Array(bits);
|
|
31
|
+
const saltHex = Array.from(salt)
|
|
32
|
+
.map((b) => b.toString(16).padStart(2, '0'))
|
|
33
|
+
.join('');
|
|
34
|
+
const hashHex = Array.from(hashArray)
|
|
35
|
+
.map((b) => b.toString(16).padStart(2, '0'))
|
|
36
|
+
.join('');
|
|
37
|
+
return `pbkdf2:${saltHex}:${hashHex}`;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Verify password against hash
|
|
41
|
+
*/
|
|
42
|
+
export async function verifyPassword(password, hash) {
|
|
43
|
+
if (!hash.startsWith('pbkdf2:')) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
const parts = hash.split(':');
|
|
47
|
+
if (parts.length !== 3) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
const [, saltHex, storedHashHex] = parts;
|
|
51
|
+
try {
|
|
52
|
+
const encoder = new TextEncoder();
|
|
53
|
+
const data = encoder.encode(password);
|
|
54
|
+
// Convert hex salt back to bytes
|
|
55
|
+
const salt = new Uint8Array(saltHex.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)));
|
|
56
|
+
const key = await crypto.subtle.importKey('raw', data, { name: 'PBKDF2' }, false, [
|
|
57
|
+
'deriveBits',
|
|
58
|
+
]);
|
|
59
|
+
const bits = await crypto.subtle.deriveBits({
|
|
60
|
+
name: 'PBKDF2',
|
|
61
|
+
salt: salt,
|
|
62
|
+
iterations: 100000,
|
|
63
|
+
hash: 'SHA-256',
|
|
64
|
+
}, key, 256);
|
|
65
|
+
const hashArray = new Uint8Array(bits);
|
|
66
|
+
const computedHashHex = Array.from(hashArray)
|
|
67
|
+
.map((b) => b.toString(16).padStart(2, '0'))
|
|
68
|
+
.join('');
|
|
69
|
+
return computedHashHex === storedHashHex;
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
console.error('Password verification error:', error);
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Create JWT token (simple implementation without external library)
|
|
78
|
+
* Note: In production, consider using a library like `jose` or `jsonwebtoken`
|
|
79
|
+
*/
|
|
80
|
+
export function createJWT(payload, secret, expiresIn) {
|
|
81
|
+
const header = {
|
|
82
|
+
alg: 'HS256',
|
|
83
|
+
typ: 'JWT',
|
|
84
|
+
};
|
|
85
|
+
const now = Math.floor(Date.now() / 1000);
|
|
86
|
+
const jwtPayload = {
|
|
87
|
+
...payload,
|
|
88
|
+
iat: now,
|
|
89
|
+
exp: now + expiresIn,
|
|
90
|
+
};
|
|
91
|
+
const headerEncoded = btoa(JSON.stringify(header));
|
|
92
|
+
const payloadEncoded = btoa(JSON.stringify(jwtPayload));
|
|
93
|
+
// For now, return a placeholder token with payload info
|
|
94
|
+
// Full HMAC implementation would require crypto-js or jose library
|
|
95
|
+
return `${headerEncoded}.${payloadEncoded}.signature-placeholder`;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Parse JWT token (simple implementation)
|
|
99
|
+
*/
|
|
100
|
+
export function parseJWT(token) {
|
|
101
|
+
try {
|
|
102
|
+
const parts = token.split('.');
|
|
103
|
+
if (parts.length !== 3) {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
const payload = JSON.parse(atob(parts[1]));
|
|
107
|
+
const now = Math.floor(Date.now() / 1000);
|
|
108
|
+
if (payload.exp && payload.exp < now) {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
return payload;
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Authentication service
|
|
119
|
+
*/
|
|
120
|
+
export class AuthService {
|
|
121
|
+
/**
|
|
122
|
+
* Register a new user
|
|
123
|
+
*/
|
|
124
|
+
static async registerUser(request, onCreateUser) {
|
|
125
|
+
// Validate input
|
|
126
|
+
const validated = RegisterSchema.parse(request);
|
|
127
|
+
// Hash password
|
|
128
|
+
const passwordHash = await hashPassword(validated.password);
|
|
129
|
+
// Create user
|
|
130
|
+
const userId = `user_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
131
|
+
const now = Date.now();
|
|
132
|
+
const user = {
|
|
133
|
+
id: userId,
|
|
134
|
+
email: validated.email,
|
|
135
|
+
createdAt: now,
|
|
136
|
+
updatedAt: now,
|
|
137
|
+
};
|
|
138
|
+
await onCreateUser(user);
|
|
139
|
+
return user;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Login user
|
|
143
|
+
*/
|
|
144
|
+
static async loginUser(request, onGetUser, secret) {
|
|
145
|
+
// Validate input
|
|
146
|
+
const validated = LoginSchema.parse(request);
|
|
147
|
+
// Get user
|
|
148
|
+
const user = await onGetUser(validated.email);
|
|
149
|
+
// Verify password
|
|
150
|
+
const passwordValid = await verifyPassword(validated.password, user.passwordHash);
|
|
151
|
+
if (!passwordValid) {
|
|
152
|
+
throw new Error('Invalid credentials');
|
|
153
|
+
}
|
|
154
|
+
// Generate tokens
|
|
155
|
+
const accessToken = createJWT({ userId: user.id, email: user.email, type: 'access' }, secret, 3600 // 1 hour
|
|
156
|
+
);
|
|
157
|
+
const refreshToken = createJWT({ userId: user.id, email: user.email, type: 'refresh' }, secret, 604800 // 7 days
|
|
158
|
+
);
|
|
159
|
+
return {
|
|
160
|
+
accessToken,
|
|
161
|
+
refreshToken,
|
|
162
|
+
expiresIn: 3600,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Refresh access token
|
|
167
|
+
*/
|
|
168
|
+
static refreshToken(refreshToken, secret) {
|
|
169
|
+
const payload = parseJWT(refreshToken);
|
|
170
|
+
if (!payload || payload.type !== 'refresh') {
|
|
171
|
+
throw new Error('Invalid refresh token');
|
|
172
|
+
}
|
|
173
|
+
return createJWT({ userId: payload.userId, email: payload.email, type: 'access' }, secret, 3600);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
export default AuthService;
|
|
177
|
+
//# sourceMappingURL=auth-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-service.js","sourceRoot":"","sources":["../../../../src/auth/auth-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/auth/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/auth/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,gBAAgB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,gBAAgB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/sync/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/sync/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { SyncRequest, SyncResponse, User } from '@edgebasejs/types';
|
|
2
|
+
export interface SyncDatabase {
|
|
3
|
+
getOne(sql: string, params: any[]): Promise<any>;
|
|
4
|
+
getAll(sql: string, params: any[]): Promise<any[]>;
|
|
5
|
+
run(sql: string, params: any[]): Promise<any>;
|
|
6
|
+
batch(statements: Array<{
|
|
7
|
+
sql: string;
|
|
8
|
+
params?: any[];
|
|
9
|
+
}>): Promise<any[]>;
|
|
10
|
+
}
|
|
11
|
+
export interface EntitySchema {
|
|
12
|
+
accessRules?: any;
|
|
13
|
+
}
|
|
14
|
+
export interface ServerSyncOptions {
|
|
15
|
+
schemas: Map<string, EntitySchema>;
|
|
16
|
+
db: SyncDatabase;
|
|
17
|
+
user: User;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Server-side sync engine
|
|
21
|
+
*/
|
|
22
|
+
export declare class ServerSyncEngine {
|
|
23
|
+
private schemas;
|
|
24
|
+
private db;
|
|
25
|
+
private user;
|
|
26
|
+
private serverTimestamp;
|
|
27
|
+
constructor(options: ServerSyncOptions);
|
|
28
|
+
/**
|
|
29
|
+
* Process sync request from client
|
|
30
|
+
*/
|
|
31
|
+
sync(request: SyncRequest): Promise<SyncResponse>;
|
|
32
|
+
/**
|
|
33
|
+
* Process changes from client
|
|
34
|
+
*/
|
|
35
|
+
private processClientChanges;
|
|
36
|
+
/**
|
|
37
|
+
* Apply a change to the database
|
|
38
|
+
*/
|
|
39
|
+
private applyChange;
|
|
40
|
+
/**
|
|
41
|
+
* Get server changes since last sync
|
|
42
|
+
*/
|
|
43
|
+
private getServerChanges;
|
|
44
|
+
}
|
|
45
|
+
export default ServerSyncEngine;
|
|
46
|
+
//# sourceMappingURL=sync-engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-engine.d.ts","sourceRoot":"","sources":["../../../../src/sync/sync-engine.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAGzE,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IACjD,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACnD,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAC9C,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,GAAG,EAAE,CAAA;KAAE,CAAC,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;CAC3E;AAED,MAAM,WAAW,YAAY;IAC3B,WAAW,CAAC,EAAE,GAAG,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACnC,EAAE,EAAE,YAAY,CAAC;IACjB,IAAI,EAAE,IAAI,CAAC;CACZ;AAED;;GAEG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,EAAE,CAAe;IACzB,OAAO,CAAC,IAAI,CAAO;IACnB,OAAO,CAAC,eAAe,CAAS;gBAEpB,OAAO,EAAE,iBAAiB;IAOtC;;OAEG;IACG,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAmBvD;;OAEG;YACW,oBAAoB;IAiGlC;;OAEG;YACW,WAAW;IAsDzB;;OAEG;YACW,gBAAgB;CAwD/B;AAED,eAAe,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
// Server-side synchronization engine
|
|
2
|
+
import { AccessRulesEngine } from '../access-rules/engine';
|
|
3
|
+
/**
|
|
4
|
+
* Server-side sync engine
|
|
5
|
+
*/
|
|
6
|
+
export class ServerSyncEngine {
|
|
7
|
+
constructor(options) {
|
|
8
|
+
this.schemas = options.schemas;
|
|
9
|
+
this.db = options.db;
|
|
10
|
+
this.user = options.user;
|
|
11
|
+
this.serverTimestamp = Date.now();
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Process sync request from client
|
|
15
|
+
*/
|
|
16
|
+
async sync(request) {
|
|
17
|
+
const response = {
|
|
18
|
+
serverTimestamp: this.serverTimestamp,
|
|
19
|
+
changes: [],
|
|
20
|
+
conflicts: [],
|
|
21
|
+
errors: [],
|
|
22
|
+
};
|
|
23
|
+
// Process client changes
|
|
24
|
+
if (request.changes && request.changes.length > 0) {
|
|
25
|
+
await this.processClientChanges(request.changes, response);
|
|
26
|
+
}
|
|
27
|
+
// Get server changes since last sync
|
|
28
|
+
await this.getServerChanges(request.lastSyncTimestamp, response);
|
|
29
|
+
return response;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Process changes from client
|
|
33
|
+
*/
|
|
34
|
+
async processClientChanges(changes, response) {
|
|
35
|
+
for (const change of changes) {
|
|
36
|
+
try {
|
|
37
|
+
// Get schema for entity
|
|
38
|
+
const schema = this.schemas.get(change.entity);
|
|
39
|
+
if (!schema) {
|
|
40
|
+
response.errors.push({
|
|
41
|
+
entity: change.entity,
|
|
42
|
+
id: change.id,
|
|
43
|
+
operation: change.operation,
|
|
44
|
+
error: 'Unknown entity',
|
|
45
|
+
code: 'NOT_FOUND',
|
|
46
|
+
});
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
// Check access rules
|
|
50
|
+
const accessContext = {
|
|
51
|
+
user: this.user,
|
|
52
|
+
operation: change.operation,
|
|
53
|
+
data: change.data,
|
|
54
|
+
};
|
|
55
|
+
// Get existing data for update/delete operations
|
|
56
|
+
if (change.operation === 'update' || change.operation === 'delete') {
|
|
57
|
+
const existing = await this.db.getOne(`SELECT * FROM ${change.entity} WHERE id = ?`, [
|
|
58
|
+
change.id,
|
|
59
|
+
]);
|
|
60
|
+
if (existing) {
|
|
61
|
+
accessContext.existingData = existing;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// Evaluate access rules
|
|
65
|
+
const accessDecision = await AccessRulesEngine.evaluate(accessContext, schema.accessRules);
|
|
66
|
+
if (!accessDecision.allowed) {
|
|
67
|
+
response.errors.push({
|
|
68
|
+
entity: change.entity,
|
|
69
|
+
id: change.id,
|
|
70
|
+
operation: change.operation,
|
|
71
|
+
error: accessDecision.reason || 'Access denied',
|
|
72
|
+
code: 'ACCESS_DENIED',
|
|
73
|
+
});
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
// Get current version
|
|
77
|
+
const metadata = await this.db.getOne('SELECT version FROM sync_metadata WHERE entity = ? AND record_id = ?', [change.entity, change.id]);
|
|
78
|
+
const currentVersion = metadata?.version || 0;
|
|
79
|
+
// Check for conflicts (version mismatch)
|
|
80
|
+
if (metadata && change.version !== currentVersion) {
|
|
81
|
+
// Get current data
|
|
82
|
+
const currentData = await this.db.getOne(`SELECT * FROM ${change.entity} WHERE id = ?`, [
|
|
83
|
+
change.id,
|
|
84
|
+
]);
|
|
85
|
+
response.conflicts.push({
|
|
86
|
+
entity: change.entity,
|
|
87
|
+
id: change.id,
|
|
88
|
+
clientVersion: change.version,
|
|
89
|
+
serverVersion: currentVersion,
|
|
90
|
+
serverData: currentData || {},
|
|
91
|
+
});
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
// Apply change to database
|
|
95
|
+
await this.applyChange(change, currentVersion + 1);
|
|
96
|
+
// Add to response changes
|
|
97
|
+
response.changes.push({
|
|
98
|
+
...change,
|
|
99
|
+
serverTimestamp: this.serverTimestamp,
|
|
100
|
+
version: currentVersion + 1,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
console.error('Error processing change:', error);
|
|
105
|
+
response.errors.push({
|
|
106
|
+
entity: change.entity,
|
|
107
|
+
id: change.id,
|
|
108
|
+
operation: change.operation,
|
|
109
|
+
error: error instanceof Error ? error.message : 'Processing failed',
|
|
110
|
+
code: 'VALIDATION_ERROR',
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Apply a change to the database
|
|
117
|
+
*/
|
|
118
|
+
async applyChange(change, version) {
|
|
119
|
+
const now = Date.now();
|
|
120
|
+
switch (change.operation) {
|
|
121
|
+
case 'create': {
|
|
122
|
+
// Insert record
|
|
123
|
+
const columns = ['id', ...Object.keys(change.data)];
|
|
124
|
+
const values = [change.id, ...Object.values(change.data)];
|
|
125
|
+
const placeholders = columns.map(() => '?').join(', ');
|
|
126
|
+
await this.db.run(`INSERT INTO ${change.entity} (${columns.join(', ')}) VALUES (${placeholders})`, values);
|
|
127
|
+
// Insert metadata
|
|
128
|
+
await this.db.run('INSERT OR REPLACE INTO sync_metadata (entity, record_id, version, updated_at) VALUES (?, ?, ?, ?)', [change.entity, change.id, version, now]);
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
case 'update': {
|
|
132
|
+
// Update record
|
|
133
|
+
const updates = Object.entries(change.data)
|
|
134
|
+
.map(([key]) => `${key} = ?`)
|
|
135
|
+
.join(', ');
|
|
136
|
+
const values = [...Object.values(change.data), change.id];
|
|
137
|
+
await this.db.run(`UPDATE ${change.entity} SET ${updates} WHERE id = ?`, values);
|
|
138
|
+
// Update metadata
|
|
139
|
+
await this.db.run('INSERT OR REPLACE INTO sync_metadata (entity, record_id, version, updated_at) VALUES (?, ?, ?, ?)', [change.entity, change.id, version, now]);
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
case 'delete': {
|
|
143
|
+
// Delete record
|
|
144
|
+
await this.db.run(`DELETE FROM ${change.entity} WHERE id = ?`, [change.id]);
|
|
145
|
+
// Mark as deleted in metadata
|
|
146
|
+
await this.db.run('INSERT OR REPLACE INTO sync_metadata (entity, record_id, version, updated_at, deleted_at) VALUES (?, ?, ?, ?, ?)', [change.entity, change.id, version, now, now]);
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Get server changes since last sync
|
|
153
|
+
*/
|
|
154
|
+
async getServerChanges(lastSyncTimestamp, response) {
|
|
155
|
+
if (!lastSyncTimestamp) {
|
|
156
|
+
// First sync - get all data
|
|
157
|
+
for (const entity of this.schemas.keys()) {
|
|
158
|
+
try {
|
|
159
|
+
const records = await this.db.getAll(`SELECT m.version, r.* FROM ${entity} r
|
|
160
|
+
LEFT JOIN sync_metadata m ON m.entity = ? AND m.record_id = r.id`, [entity]);
|
|
161
|
+
for (const record of records) {
|
|
162
|
+
response.changes.push({
|
|
163
|
+
entity,
|
|
164
|
+
operation: 'create',
|
|
165
|
+
id: record.id,
|
|
166
|
+
data: record,
|
|
167
|
+
serverTimestamp: this.serverTimestamp,
|
|
168
|
+
version: record.version || 1,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
console.error(`Error fetching records from ${entity}:`, error);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
// Get changes since last sync
|
|
179
|
+
for (const entity of this.schemas.keys()) {
|
|
180
|
+
try {
|
|
181
|
+
const records = await this.db.getAll(`SELECT m.version, m.deleted_at, r.* FROM sync_metadata m
|
|
182
|
+
LEFT JOIN ${entity} r ON r.id = m.record_id
|
|
183
|
+
WHERE m.entity = ? AND m.updated_at > ?`, [entity, lastSyncTimestamp]);
|
|
184
|
+
for (const record of records) {
|
|
185
|
+
const operation = record.deleted_at ? 'delete' : 'update';
|
|
186
|
+
response.changes.push({
|
|
187
|
+
entity,
|
|
188
|
+
operation: operation,
|
|
189
|
+
id: record.id,
|
|
190
|
+
data: record.deleted_at ? {} : record,
|
|
191
|
+
serverTimestamp: this.serverTimestamp,
|
|
192
|
+
version: record.version || 1,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
console.error(`Error fetching changes from ${entity}:`, error);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
export default ServerSyncEngine;
|
|
204
|
+
//# sourceMappingURL=sync-engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-engine.js","sourceRoot":"","sources":["../../../../src/sync/sync-engine.ts"],"names":[],"mappings":"AAAA,qCAAqC;AAGrC,OAAO,EAAE,iBAAiB,EAAsB,MAAM,wBAAwB,CAAC;AAmB/E;;GAEG;AACH,MAAM,OAAO,gBAAgB;IAM3B,YAAY,OAA0B;QACpC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAC/B,IAAI,CAAC,EAAE,GAAG,OAAO,CAAC,EAAE,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACpC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,IAAI,CAAC,OAAoB;QAC7B,MAAM,QAAQ,GAAiB;YAC7B,eAAe,EAAE,IAAI,CAAC,eAAe;YACrC,OAAO,EAAE,EAAE;YACX,SAAS,EAAE,EAAE;YACb,MAAM,EAAE,EAAE;SACX,CAAC;QAEF,yBAAyB;QACzB,IAAI,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClD,MAAM,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QAC7D,CAAC;QAED,qCAAqC;QACrC,MAAM,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC;QAEjE,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,oBAAoB,CAChC,OAA+B,EAC/B,QAAsB;QAEtB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,IAAI,CAAC;gBACH,wBAAwB;gBACxB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBAC/C,IAAI,CAAC,MAAM,EAAE,CAAC;oBACZ,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC;wBACnB,MAAM,EAAE,MAAM,CAAC,MAAM;wBACrB,EAAE,EAAE,MAAM,CAAC,EAAE;wBACb,SAAS,EAAE,MAAM,CAAC,SAAS;wBAC3B,KAAK,EAAE,gBAAgB;wBACvB,IAAI,EAAE,WAAW;qBAClB,CAAC,CAAC;oBACH,SAAS;gBACX,CAAC;gBAED,qBAAqB;gBACrB,MAAM,aAAa,GAAkB;oBACnC,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,SAAS,EAAE,MAAM,CAAC,SAAS;oBAC3B,IAAI,EAAE,MAAM,CAAC,IAAI;iBAClB,CAAC;gBAEF,iDAAiD;gBACjD,IAAI,MAAM,CAAC,SAAS,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;oBACnE,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,iBAAiB,MAAM,CAAC,MAAM,eAAe,EAAE;wBACnF,MAAM,CAAC,EAAE;qBACV,CAAC,CAAC;oBACH,IAAI,QAAQ,EAAE,CAAC;wBACb,aAAa,CAAC,YAAY,GAAG,QAAQ,CAAC;oBACxC,CAAC;gBACH,CAAC;gBAED,wBAAwB;gBACxB,MAAM,cAAc,GAAG,MAAM,iBAAiB,CAAC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;gBAE3F,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC;oBAC5B,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC;wBACnB,MAAM,EAAE,MAAM,CAAC,MAAM;wBACrB,EAAE,EAAE,MAAM,CAAC,EAAE;wBACb,SAAS,EAAE,MAAM,CAAC,SAAS;wBAC3B,KAAK,EAAE,cAAc,CAAC,MAAM,IAAI,eAAe;wBAC/C,IAAI,EAAE,eAAe;qBACtB,CAAC,CAAC;oBACH,SAAS;gBACX,CAAC;gBAED,sBAAsB;gBACtB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,MAAM,CACnC,sEAAsE,EACtE,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAC3B,CAAC;gBAEF,MAAM,cAAc,GAAG,QAAQ,EAAE,OAAO,IAAI,CAAC,CAAC;gBAE9C,yCAAyC;gBACzC,IAAI,QAAQ,IAAI,MAAM,CAAC,OAAO,KAAK,cAAc,EAAE,CAAC;oBAClD,mBAAmB;oBACnB,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,iBAAiB,MAAM,CAAC,MAAM,eAAe,EAAE;wBACtF,MAAM,CAAC,EAAE;qBACV,CAAC,CAAC;oBAEH,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC;wBACtB,MAAM,EAAE,MAAM,CAAC,MAAM;wBACrB,EAAE,EAAE,MAAM,CAAC,EAAE;wBACb,aAAa,EAAE,MAAM,CAAC,OAAO;wBAC7B,aAAa,EAAE,cAAc;wBAC7B,UAAU,EAAE,WAAW,IAAI,EAAE;qBAC9B,CAAC,CAAC;oBACH,SAAS;gBACX,CAAC;gBAED,2BAA2B;gBAC3B,MAAM,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,cAAc,GAAG,CAAC,CAAC,CAAC;gBAEnD,0BAA0B;gBAC1B,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC;oBACpB,GAAG,MAAM;oBACT,eAAe,EAAE,IAAI,CAAC,eAAe;oBACrC,OAAO,EAAE,cAAc,GAAG,CAAC;iBAC5B,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,KAAK,CAAC,CAAC;gBACjD,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC;oBACnB,MAAM,EAAE,MAAM,CAAC,MAAM;oBACrB,EAAE,EAAE,MAAM,CAAC,EAAE;oBACb,SAAS,EAAE,MAAM,CAAC,SAAS;oBAC3B,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,mBAAmB;oBACnE,IAAI,EAAE,kBAAkB;iBACzB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,WAAW,CAAC,MAAiC,EAAE,OAAe;QAC1E,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEvB,QAAQ,MAAM,CAAC,SAAS,EAAE,CAAC;YACzB,KAAK,QAAQ,CAAC,CAAC,CAAC;gBACd,gBAAgB;gBAChB,MAAM,OAAO,GAAG,CAAC,IAAI,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;gBACpD,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;gBAC1D,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAEvD,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CACf,eAAe,MAAM,CAAC,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,YAAY,GAAG,EAC/E,MAAM,CACP,CAAC;gBAEF,kBAAkB;gBAClB,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CACf,mGAAmG,EACnG,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,CACzC,CAAC;gBACF,MAAM;YACR,CAAC;YAED,KAAK,QAAQ,CAAC,CAAC,CAAC;gBACd,gBAAgB;gBAChB,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC;qBACxC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,MAAM,CAAC;qBAC5B,IAAI,CAAC,IAAI,CAAC,CAAC;gBACd,MAAM,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;gBAE1D,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,MAAM,CAAC,MAAM,QAAQ,OAAO,eAAe,EAAE,MAAM,CAAC,CAAC;gBAEjF,kBAAkB;gBAClB,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CACf,mGAAmG,EACnG,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,CACzC,CAAC;gBACF,MAAM;YACR,CAAC;YAED,KAAK,QAAQ,CAAC,CAAC,CAAC;gBACd,gBAAgB;gBAChB,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,eAAe,MAAM,CAAC,MAAM,eAAe,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;gBAE5E,8BAA8B;gBAC9B,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CACf,kHAAkH,EAClH,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,CAC9C,CAAC;gBACF,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,gBAAgB,CAC5B,iBAAgC,EAChC,QAAsB;QAEtB,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACvB,4BAA4B;YAC5B,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;gBACzC,IAAI,CAAC;oBACH,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,MAAM,CAClC,8BAA8B,MAAM;8EAC8B,EAClE,CAAC,MAAM,CAAC,CACT,CAAC;oBAEF,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;wBAC7B,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC;4BACpB,MAAM;4BACN,SAAS,EAAE,QAAQ;4BACnB,EAAE,EAAE,MAAM,CAAC,EAAE;4BACb,IAAI,EAAE,MAAM;4BACZ,eAAe,EAAE,IAAI,CAAC,eAAe;4BACrC,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,CAAC;yBAC7B,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,OAAO,CAAC,KAAK,CAAC,+BAA+B,MAAM,GAAG,EAAE,KAAK,CAAC,CAAC;gBACjE,CAAC;YACH,CAAC;QACH,CAAC;aAAM,CAAC;YACN,8BAA8B;YAC9B,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;gBACzC,IAAI,CAAC;oBACH,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,MAAM,CAClC;yBACa,MAAM;qDACsB,EACzC,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAC5B,CAAC;oBAEF,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;wBAC7B,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;wBAC1D,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC;4BACpB,MAAM;4BACN,SAAS,EAAE,SAAgB;4BAC3B,EAAE,EAAE,MAAM,CAAC,EAAE;4BACb,IAAI,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM;4BACrC,eAAe,EAAE,IAAI,CAAC,eAAe;4BACrC,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,CAAC;yBAC7B,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,OAAO,CAAC,KAAK,CAAC,+BAA+B,MAAM,GAAG,EAAE,KAAK,CAAC,CAAC;gBACjE,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;CACF;AAED,eAAe,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
export type AdminRole = 'super_admin' | 'admin' | 'viewer';
|
|
2
|
+
export interface Admin {
|
|
3
|
+
id: string;
|
|
4
|
+
email: string;
|
|
5
|
+
role: AdminRole;
|
|
6
|
+
isActive: boolean;
|
|
7
|
+
createdAt: number;
|
|
8
|
+
updatedAt: number;
|
|
9
|
+
}
|
|
10
|
+
export interface AdminLoginRequest {
|
|
11
|
+
email: string;
|
|
12
|
+
password: string;
|
|
13
|
+
}
|
|
14
|
+
export interface AdminAuthResponse {
|
|
15
|
+
admin: Admin;
|
|
16
|
+
accessToken: string;
|
|
17
|
+
refreshToken: string;
|
|
18
|
+
expiresIn: number;
|
|
19
|
+
}
|
|
20
|
+
export interface PaginatedResponse<T> {
|
|
21
|
+
data: T[];
|
|
22
|
+
pagination: {
|
|
23
|
+
page: number;
|
|
24
|
+
pageSize: number;
|
|
25
|
+
total: number;
|
|
26
|
+
totalPages: number;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export type ActivityAction = 'create' | 'read' | 'update' | 'delete' | 'login' | 'logout';
|
|
30
|
+
export type ActivityEntityType = 'user' | 'admin' | 'system' | 'database';
|
|
31
|
+
export interface ActivityLogEntry {
|
|
32
|
+
id: string;
|
|
33
|
+
adminId: string;
|
|
34
|
+
adminEmail?: string;
|
|
35
|
+
action: ActivityAction;
|
|
36
|
+
entityType: ActivityEntityType;
|
|
37
|
+
entityId?: string;
|
|
38
|
+
details: Record<string, any>;
|
|
39
|
+
ipAddress: string;
|
|
40
|
+
createdAt: number;
|
|
41
|
+
}
|
|
42
|
+
export interface ActivityLogFilter {
|
|
43
|
+
adminId?: string;
|
|
44
|
+
entityType?: ActivityEntityType;
|
|
45
|
+
action?: ActivityAction;
|
|
46
|
+
dateFrom?: number;
|
|
47
|
+
dateTo?: number;
|
|
48
|
+
page?: number;
|
|
49
|
+
pageSize?: number;
|
|
50
|
+
}
|
|
51
|
+
export interface TableInfo {
|
|
52
|
+
name: string;
|
|
53
|
+
rowCount: number;
|
|
54
|
+
createdAt?: number;
|
|
55
|
+
}
|
|
56
|
+
export interface ColumnDefinition {
|
|
57
|
+
name: string;
|
|
58
|
+
type: string;
|
|
59
|
+
nullable: boolean;
|
|
60
|
+
primaryKey: boolean;
|
|
61
|
+
defaultValue?: any;
|
|
62
|
+
}
|
|
63
|
+
export interface TableSchema {
|
|
64
|
+
name: string;
|
|
65
|
+
columns: ColumnDefinition[];
|
|
66
|
+
primaryKey: string[];
|
|
67
|
+
createdAt?: number;
|
|
68
|
+
}
|
|
69
|
+
export interface TableDataResponse {
|
|
70
|
+
tableName: string;
|
|
71
|
+
data: Record<string, any>[];
|
|
72
|
+
columns: ColumnDefinition[];
|
|
73
|
+
pagination: {
|
|
74
|
+
page: number;
|
|
75
|
+
pageSize: number;
|
|
76
|
+
total: number;
|
|
77
|
+
totalPages: number;
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
export interface UserDetail extends Record<string, any> {
|
|
81
|
+
id: string;
|
|
82
|
+
email: string;
|
|
83
|
+
createdAt: number;
|
|
84
|
+
updatedAt: number;
|
|
85
|
+
}
|
|
86
|
+
export interface AdminCreateRequest {
|
|
87
|
+
email: string;
|
|
88
|
+
password: string;
|
|
89
|
+
role: AdminRole;
|
|
90
|
+
}
|
|
91
|
+
export interface AdminUpdateRequest {
|
|
92
|
+
email?: string;
|
|
93
|
+
role?: AdminRole;
|
|
94
|
+
isActive?: boolean;
|
|
95
|
+
}
|
|
96
|
+
export interface ErrorResponse {
|
|
97
|
+
code: string;
|
|
98
|
+
message: string;
|
|
99
|
+
details?: Record<string, any>;
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=admin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin.d.ts","sourceRoot":"","sources":["../../../../shared-types/src/admin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin.js","sourceRoot":"","sources":["../../../../shared-types/src/admin.ts"],"names":[],"mappings":"AAAA,sBAAsB"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface User {
|
|
2
|
+
id: string;
|
|
3
|
+
email: string;
|
|
4
|
+
createdAt: number;
|
|
5
|
+
updatedAt: number;
|
|
6
|
+
}
|
|
7
|
+
export interface AuthTokens {
|
|
8
|
+
accessToken: string;
|
|
9
|
+
refreshToken: string;
|
|
10
|
+
expiresIn: number;
|
|
11
|
+
}
|
|
12
|
+
export interface LoginRequest {
|
|
13
|
+
email: string;
|
|
14
|
+
password: string;
|
|
15
|
+
}
|
|
16
|
+
export interface RegisterRequest {
|
|
17
|
+
email: string;
|
|
18
|
+
password: string;
|
|
19
|
+
}
|
|
20
|
+
export interface RefreshTokenRequest {
|
|
21
|
+
refreshToken: string;
|
|
22
|
+
}
|
|
23
|
+
export interface AuthResponse {
|
|
24
|
+
user: User;
|
|
25
|
+
tokens: AuthTokens;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../../shared-types/src/auth.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,UAAU,CAAC;CACpB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../../shared-types/src/auth.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../shared-types/src/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../shared-types/src/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export type FieldTypeValue = 'string' | 'integer' | 'number' | 'boolean' | 'timestamp' | 'text' | 'json' | 'reference';
|
|
2
|
+
export interface FieldType {
|
|
3
|
+
type: FieldTypeValue;
|
|
4
|
+
required: boolean;
|
|
5
|
+
primary?: boolean;
|
|
6
|
+
reference?: string;
|
|
7
|
+
default?: string | number | boolean;
|
|
8
|
+
description?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface AccessRules {
|
|
11
|
+
create?: (user: any, data: any) => boolean;
|
|
12
|
+
read?: (user: any, data: any) => boolean;
|
|
13
|
+
update?: (user: any, existing: any, updates?: any) => boolean;
|
|
14
|
+
delete?: (user: any, data: any) => boolean;
|
|
15
|
+
}
|
|
16
|
+
export interface EntitySchema {
|
|
17
|
+
fields: Record<string, FieldType>;
|
|
18
|
+
accessRules?: AccessRules;
|
|
19
|
+
indexes?: Array<{
|
|
20
|
+
fields: string[];
|
|
21
|
+
unique?: boolean;
|
|
22
|
+
}>;
|
|
23
|
+
}
|
|
24
|
+
export interface DatabaseSchema {
|
|
25
|
+
entities: Record<string, EntitySchema>;
|
|
26
|
+
}
|
|
27
|
+
export interface Migration {
|
|
28
|
+
version: number;
|
|
29
|
+
name: string;
|
|
30
|
+
up: string;
|
|
31
|
+
down?: string;
|
|
32
|
+
appliedAt?: number;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../../shared-types/src/schema.ts"],"names":[],"mappings":"AACA,MAAM,MAAM,cAAc,GACtB,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,SAAS,GACT,WAAW,GACX,MAAM,GACN,MAAM,GACN,WAAW,CAAC;AAEhB,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,cAAc,CAAC;IACrB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC;IAC3C,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC;IACzC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC;IAC9D,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC;CAC5C;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAClC,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,OAAO,CAAC,EAAE,KAAK,CAAC;QACd,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,MAAM,CAAC,EAAE,OAAO,CAAC;KAClB,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;CACxC;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../../shared-types/src/schema.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export interface SyncRequest {
|
|
2
|
+
lastSyncTimestamp: number | null;
|
|
3
|
+
changes: Array<{
|
|
4
|
+
entity: string;
|
|
5
|
+
operation: 'create' | 'update' | 'delete';
|
|
6
|
+
id: string;
|
|
7
|
+
data: Record<string, any>;
|
|
8
|
+
clientTimestamp: number;
|
|
9
|
+
version: number;
|
|
10
|
+
}>;
|
|
11
|
+
}
|
|
12
|
+
export interface SyncResponse {
|
|
13
|
+
serverTimestamp: number;
|
|
14
|
+
changes: Array<{
|
|
15
|
+
entity: string;
|
|
16
|
+
operation: 'create' | 'update' | 'delete';
|
|
17
|
+
id: string;
|
|
18
|
+
data: Record<string, any>;
|
|
19
|
+
serverTimestamp: number;
|
|
20
|
+
version: number;
|
|
21
|
+
}>;
|
|
22
|
+
conflicts: Array<{
|
|
23
|
+
entity: string;
|
|
24
|
+
id: string;
|
|
25
|
+
clientVersion: number;
|
|
26
|
+
serverVersion: number;
|
|
27
|
+
serverData: Record<string, any>;
|
|
28
|
+
}>;
|
|
29
|
+
errors: Array<{
|
|
30
|
+
entity: string;
|
|
31
|
+
id: string;
|
|
32
|
+
operation: string;
|
|
33
|
+
error: string;
|
|
34
|
+
code: 'ACCESS_DENIED' | 'VALIDATION_ERROR' | 'NOT_FOUND';
|
|
35
|
+
}>;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=sync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../../../shared-types/src/sync.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,WAAW;IAC1B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,OAAO,EAAE,KAAK,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;QAC1C,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC1B,eAAe,EAAE,MAAM,CAAC;QACxB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,YAAY;IAC3B,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,KAAK,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;QAC1C,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC1B,eAAe,EAAE,MAAM,CAAC;QACxB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;IACH,SAAS,EAAE,KAAK,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;QACf,EAAE,EAAE,MAAM,CAAC;QACX,aAAa,EAAE,MAAM,CAAC;QACtB,aAAa,EAAE,MAAM,CAAC;QACtB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;KACjC,CAAC,CAAC;IACH,MAAM,EAAE,KAAK,CAAC;QACZ,MAAM,EAAE,MAAM,CAAC;QACf,EAAE,EAAE,MAAM,CAAC;QACX,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,eAAe,GAAG,kBAAkB,GAAG,WAAW,CAAC;KAC1D,CAAC,CAAC;CACJ"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../../../shared-types/src/sync.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@edgebasejs/core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "EdgeBase server core library",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"zod": "^3.22.0",
|
|
12
|
+
"@edgebasejs/types": "0.1.0"
|
|
13
|
+
},
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"registry": "https://registry.npmjs.org/"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"typescript": "^5.4.5",
|
|
19
|
+
"vitest": "^1.2.0"
|
|
20
|
+
},
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsc",
|
|
23
|
+
"type-check": "tsc --noEmit",
|
|
24
|
+
"test": "vitest"
|
|
25
|
+
}
|
|
26
|
+
}
|