@prmichaelsen/agentbase-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/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/auth/guards.d.ts +15 -0
- package/dist/lib/auth/guards.d.ts.map +1 -0
- package/dist/lib/auth/guards.js +48 -0
- package/dist/lib/auth/guards.js.map +1 -0
- package/dist/lib/auth/helpers.d.ts +8 -0
- package/dist/lib/auth/helpers.d.ts.map +1 -0
- package/dist/lib/auth/helpers.js +9 -0
- package/dist/lib/auth/helpers.js.map +1 -0
- package/dist/lib/auth/index.d.ts +4 -0
- package/dist/lib/auth/index.d.ts.map +1 -0
- package/dist/lib/auth/index.js +4 -0
- package/dist/lib/auth/index.js.map +1 -0
- package/dist/lib/auth/session.d.ts +23 -0
- package/dist/lib/auth/session.d.ts.map +1 -0
- package/dist/lib/auth/session.js +104 -0
- package/dist/lib/auth/session.js.map +1 -0
- package/dist/lib/firebase-admin.d.ts +2 -0
- package/dist/lib/firebase-admin.d.ts.map +1 -0
- package/dist/lib/firebase-admin.js +8 -0
- package/dist/lib/firebase-admin.js.map +1 -0
- package/dist/lib/firebase-client.d.ts +29 -0
- package/dist/lib/firebase-client.d.ts.map +1 -0
- package/dist/lib/firebase-client.js +65 -0
- package/dist/lib/firebase-client.js.map +1 -0
- package/dist/lib/format-time.d.ts +6 -0
- package/dist/lib/format-time.d.ts.map +1 -0
- package/dist/lib/format-time.js +34 -0
- package/dist/lib/format-time.js.map +1 -0
- package/dist/lib/index.d.ts +11 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +13 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/linkify.d.ts +10 -0
- package/dist/lib/linkify.d.ts.map +1 -0
- package/dist/lib/linkify.js +51 -0
- package/dist/lib/linkify.js.map +1 -0
- package/dist/lib/logger.d.ts +42 -0
- package/dist/lib/logger.d.ts.map +1 -0
- package/dist/lib/logger.js +112 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/rate-limiter.d.ts +31 -0
- package/dist/lib/rate-limiter.d.ts.map +1 -0
- package/dist/lib/rate-limiter.js +65 -0
- package/dist/lib/rate-limiter.js.map +1 -0
- package/dist/lib/uuid.d.ts +12 -0
- package/dist/lib/uuid.d.ts.map +1 -0
- package/dist/lib/uuid.js +23 -0
- package/dist/lib/uuid.js.map +1 -0
- package/dist/services/base.service.d.ts +46 -0
- package/dist/services/base.service.d.ts.map +1 -0
- package/dist/services/base.service.js +46 -0
- package/dist/services/base.service.js.map +1 -0
- package/dist/services/confirmation-token.service.d.ts +40 -0
- package/dist/services/confirmation-token.service.d.ts.map +1 -0
- package/dist/services/confirmation-token.service.js +60 -0
- package/dist/services/confirmation-token.service.js.map +1 -0
- package/dist/services/index.d.ts +5 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +3 -0
- package/dist/services/index.js.map +1 -0
- package/dist/types/index.d.ts +19 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +70 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
interface LogContext {
|
|
2
|
+
[key: string]: any;
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* Sanitization utilities for secure logging
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Sanitize tokens by returning only a hash prefix
|
|
9
|
+
* Prevents token exposure while maintaining debuggability
|
|
10
|
+
*/
|
|
11
|
+
export declare function sanitizeToken(token: string | undefined | null): string;
|
|
12
|
+
/**
|
|
13
|
+
* Sanitize email addresses
|
|
14
|
+
* Shows first 2 chars of local part + domain
|
|
15
|
+
*/
|
|
16
|
+
export declare function sanitizeEmail(email: string | undefined | null): string;
|
|
17
|
+
/**
|
|
18
|
+
* Sanitize user IDs
|
|
19
|
+
* Shows only first 8 characters with prefix
|
|
20
|
+
*/
|
|
21
|
+
export declare function sanitizeUserId(userId: string | undefined | null): string;
|
|
22
|
+
/**
|
|
23
|
+
* Sanitize objects by redacting sensitive fields
|
|
24
|
+
* Automatically redacts fields containing: token, password, secret, key, authorization
|
|
25
|
+
*/
|
|
26
|
+
export declare function sanitizeObject(obj: any): any;
|
|
27
|
+
declare class Logger {
|
|
28
|
+
private context;
|
|
29
|
+
constructor(context: string);
|
|
30
|
+
private log;
|
|
31
|
+
debug(message: string, data?: LogContext): void;
|
|
32
|
+
info(message: string, data?: LogContext): void;
|
|
33
|
+
warn(message: string, data?: LogContext): void;
|
|
34
|
+
error(message: string, error?: Error | any, data?: LogContext): void;
|
|
35
|
+
}
|
|
36
|
+
export declare function createLogger(context: string): Logger;
|
|
37
|
+
export declare const authLogger: Logger;
|
|
38
|
+
export declare const apiLogger: Logger;
|
|
39
|
+
export declare const dbLogger: Logger;
|
|
40
|
+
export declare const chatLogger: Logger;
|
|
41
|
+
export {};
|
|
42
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"AAIA,UAAU,UAAU;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED;;GAEG;AAEH;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,CAItE;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,CAKtE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,CAGxE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,CAqB5C;AAED,cAAM,MAAM;IACV,OAAO,CAAC,OAAO,CAAS;gBAEZ,OAAO,EAAE,MAAM;IAI3B,OAAO,CAAC,GAAG;IAsBX,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,UAAU;IAIxC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,UAAU;IAIvC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,UAAU;IAIvC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,GAAG,EAAE,IAAI,CAAC,EAAE,UAAU;CAS9D;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEpD;AAGD,eAAO,MAAM,UAAU,QAAuB,CAAC;AAC/C,eAAO,MAAM,SAAS,QAAsB,CAAC;AAC7C,eAAO,MAAM,QAAQ,QAA2B,CAAC;AACjD,eAAO,MAAM,UAAU,QAAuB,CAAC"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { createHash } from 'crypto';
|
|
2
|
+
/**
|
|
3
|
+
* Sanitization utilities for secure logging
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Sanitize tokens by returning only a hash prefix
|
|
7
|
+
* Prevents token exposure while maintaining debuggability
|
|
8
|
+
*/
|
|
9
|
+
export function sanitizeToken(token) {
|
|
10
|
+
if (!token)
|
|
11
|
+
return '[empty]';
|
|
12
|
+
const hash = createHash('sha256').update(token).digest('hex');
|
|
13
|
+
return `${hash.substring(0, 8)}...`;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Sanitize email addresses
|
|
17
|
+
* Shows first 2 chars of local part + domain
|
|
18
|
+
*/
|
|
19
|
+
export function sanitizeEmail(email) {
|
|
20
|
+
if (!email)
|
|
21
|
+
return '[empty]';
|
|
22
|
+
const [local, domain] = email.split('@');
|
|
23
|
+
if (!domain)
|
|
24
|
+
return '[invalid]';
|
|
25
|
+
return `${local.substring(0, 2)}***@${domain}`;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Sanitize user IDs
|
|
29
|
+
* Shows only first 8 characters with prefix
|
|
30
|
+
*/
|
|
31
|
+
export function sanitizeUserId(userId) {
|
|
32
|
+
if (!userId)
|
|
33
|
+
return '[empty]';
|
|
34
|
+
return `user_${userId.substring(0, 8)}`;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Sanitize objects by redacting sensitive fields
|
|
38
|
+
* Automatically redacts fields containing: token, password, secret, key, authorization
|
|
39
|
+
*/
|
|
40
|
+
export function sanitizeObject(obj) {
|
|
41
|
+
if (!obj || typeof obj !== 'object')
|
|
42
|
+
return obj;
|
|
43
|
+
const sensitive = ['token', 'password', 'secret', 'key', 'authorization', 'credential'];
|
|
44
|
+
const result = Array.isArray(obj) ? [] : {};
|
|
45
|
+
for (const key in obj) {
|
|
46
|
+
const lowerKey = key.toLowerCase();
|
|
47
|
+
// Check if key contains sensitive terms
|
|
48
|
+
if (sensitive.some(s => lowerKey.includes(s))) {
|
|
49
|
+
result[key] = '[REDACTED]';
|
|
50
|
+
}
|
|
51
|
+
else if (typeof obj[key] === 'object' && obj[key] !== null) {
|
|
52
|
+
// Recursively sanitize nested objects
|
|
53
|
+
result[key] = sanitizeObject(obj[key]);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
result[key] = obj[key];
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
class Logger {
|
|
62
|
+
context;
|
|
63
|
+
constructor(context) {
|
|
64
|
+
this.context = context;
|
|
65
|
+
}
|
|
66
|
+
log(level, message, data) {
|
|
67
|
+
// Sanitize data before logging
|
|
68
|
+
const sanitizedData = data ? sanitizeObject(data) : undefined;
|
|
69
|
+
const isDevelopment = typeof process !== 'undefined' && process.env?.NODE_ENV === 'development';
|
|
70
|
+
switch (level) {
|
|
71
|
+
case 'debug':
|
|
72
|
+
if (isDevelopment)
|
|
73
|
+
console.debug(`[${this.context}]`, message, sanitizedData || '');
|
|
74
|
+
break;
|
|
75
|
+
case 'info':
|
|
76
|
+
console.log(`[${this.context}]`, message, sanitizedData || '');
|
|
77
|
+
break;
|
|
78
|
+
case 'warn':
|
|
79
|
+
console.warn(`[${this.context}]`, message, sanitizedData || '');
|
|
80
|
+
break;
|
|
81
|
+
case 'error':
|
|
82
|
+
console.error(`[${this.context}]`, message, sanitizedData || '');
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
debug(message, data) {
|
|
87
|
+
this.log('debug', message, data);
|
|
88
|
+
}
|
|
89
|
+
info(message, data) {
|
|
90
|
+
this.log('info', message, data);
|
|
91
|
+
}
|
|
92
|
+
warn(message, data) {
|
|
93
|
+
this.log('warn', message, data);
|
|
94
|
+
}
|
|
95
|
+
error(message, error, data) {
|
|
96
|
+
const isDevelopment = typeof process !== 'undefined' && process.env?.NODE_ENV === 'development';
|
|
97
|
+
this.log('error', message, {
|
|
98
|
+
...data,
|
|
99
|
+
error: error?.message || error,
|
|
100
|
+
stack: isDevelopment ? error?.stack : undefined,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
export function createLogger(context) {
|
|
105
|
+
return new Logger(context);
|
|
106
|
+
}
|
|
107
|
+
// Pre-configured loggers for common contexts
|
|
108
|
+
export const authLogger = createLogger('Auth');
|
|
109
|
+
export const apiLogger = createLogger('API');
|
|
110
|
+
export const dbLogger = createLogger('Database');
|
|
111
|
+
export const chatLogger = createLogger('Chat');
|
|
112
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rate Limiting Utility
|
|
3
|
+
*
|
|
4
|
+
* Provides rate limiting functionality using Cloudflare Workers Rate Limiting API
|
|
5
|
+
*/
|
|
6
|
+
export interface RateLimitConfig {
|
|
7
|
+
limit: number;
|
|
8
|
+
period: number;
|
|
9
|
+
keyPrefix: string;
|
|
10
|
+
}
|
|
11
|
+
export interface RateLimitResult {
|
|
12
|
+
success: boolean;
|
|
13
|
+
limit: number;
|
|
14
|
+
remaining: number;
|
|
15
|
+
retryAfter?: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Check rate limit for a request
|
|
19
|
+
*/
|
|
20
|
+
export declare function checkRateLimit(rateLimiter: any, // Cloudflare Rate Limiter binding
|
|
21
|
+
identifier: string, config: RateLimitConfig): Promise<RateLimitResult>;
|
|
22
|
+
/**
|
|
23
|
+
* Create rate limit error response
|
|
24
|
+
*/
|
|
25
|
+
export declare function createRateLimitResponse(result: RateLimitResult): Response;
|
|
26
|
+
/**
|
|
27
|
+
* Get rate limit identifier from request
|
|
28
|
+
* Uses IP address, falling back to user ID if authenticated
|
|
29
|
+
*/
|
|
30
|
+
export declare function getRateLimitIdentifier(request: Request, userId?: string): string;
|
|
31
|
+
//# sourceMappingURL=rate-limiter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../../src/lib/rate-limiter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,WAAW,EAAE,GAAG,EAAG,kCAAkC;AACrD,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,eAAe,GACtB,OAAO,CAAC,eAAe,CAAC,CAqB1B;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,eAAe,GAAG,QAAQ,CAqBzE;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAUhF"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rate Limiting Utility
|
|
3
|
+
*
|
|
4
|
+
* Provides rate limiting functionality using Cloudflare Workers Rate Limiting API
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Check rate limit for a request
|
|
8
|
+
*/
|
|
9
|
+
export async function checkRateLimit(rateLimiter, // Cloudflare Rate Limiter binding
|
|
10
|
+
identifier, config) {
|
|
11
|
+
const key = `${config.keyPrefix}:${identifier}`;
|
|
12
|
+
try {
|
|
13
|
+
const { success, limit, remaining, retryAfter } = await rateLimiter.limit({ key });
|
|
14
|
+
return {
|
|
15
|
+
success,
|
|
16
|
+
limit,
|
|
17
|
+
remaining,
|
|
18
|
+
retryAfter
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
console.error('[RateLimit] Error checking rate limit:', error);
|
|
23
|
+
// Fail open - allow request if rate limiter fails
|
|
24
|
+
return {
|
|
25
|
+
success: true,
|
|
26
|
+
limit: config.limit,
|
|
27
|
+
remaining: config.limit
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Create rate limit error response
|
|
33
|
+
*/
|
|
34
|
+
export function createRateLimitResponse(result) {
|
|
35
|
+
const retryAfter = result.retryAfter ?? 60;
|
|
36
|
+
const limit = result.limit ?? 100;
|
|
37
|
+
const remaining = result.remaining ?? 0;
|
|
38
|
+
return new Response(JSON.stringify({
|
|
39
|
+
error: 'Too many requests',
|
|
40
|
+
message: 'Rate limit exceeded. Please try again later.',
|
|
41
|
+
retryAfter
|
|
42
|
+
}), {
|
|
43
|
+
status: 429,
|
|
44
|
+
headers: {
|
|
45
|
+
'Content-Type': 'application/json',
|
|
46
|
+
'Retry-After': retryAfter.toString(),
|
|
47
|
+
'X-RateLimit-Limit': limit.toString(),
|
|
48
|
+
'X-RateLimit-Remaining': remaining.toString()
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Get rate limit identifier from request
|
|
54
|
+
* Uses IP address, falling back to user ID if authenticated
|
|
55
|
+
*/
|
|
56
|
+
export function getRateLimitIdentifier(request, userId) {
|
|
57
|
+
if (userId) {
|
|
58
|
+
return `user:${userId}`;
|
|
59
|
+
}
|
|
60
|
+
const ip = request.headers.get('cf-connecting-ip') ||
|
|
61
|
+
request.headers.get('x-forwarded-for') ||
|
|
62
|
+
'unknown';
|
|
63
|
+
return `ip:${ip}`;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=rate-limiter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../src/lib/rate-limiter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAeH;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,WAAgB,EAAG,kCAAkC;AACrD,UAAkB,EAClB,MAAuB;IAEvB,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,SAAS,IAAI,UAAU,EAAE,CAAA;IAE/C,IAAI,CAAC;QACH,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,MAAM,WAAW,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC,CAAA;QAElF,OAAO;YACL,OAAO;YACP,KAAK;YACL,SAAS;YACT,UAAU;SACX,CAAA;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,wCAAwC,EAAE,KAAK,CAAC,CAAA;QAC9D,kDAAkD;QAClD,OAAO;YACL,OAAO,EAAE,IAAI;YACb,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,SAAS,EAAE,MAAM,CAAC,KAAK;SACxB,CAAA;IACH,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAAuB;IAC7D,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,EAAE,CAAA;IAC1C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,GAAG,CAAA;IACjC,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,CAAC,CAAA;IAEvC,OAAO,IAAI,QAAQ,CACjB,IAAI,CAAC,SAAS,CAAC;QACb,KAAK,EAAE,mBAAmB;QAC1B,OAAO,EAAE,8CAA8C;QACvD,UAAU;KACX,CAAC,EACF;QACE,MAAM,EAAE,GAAG;QACX,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,aAAa,EAAE,UAAU,CAAC,QAAQ,EAAE;YACpC,mBAAmB,EAAE,KAAK,CAAC,QAAQ,EAAE;YACrC,uBAAuB,EAAE,SAAS,CAAC,QAAQ,EAAE;SAC9C;KACF,CACF,CAAA;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAAgB,EAAE,MAAe;IACtE,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,QAAQ,MAAM,EAAE,CAAA;IACzB,CAAC;IAED,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;QACtC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;QACtC,SAAS,CAAA;IAErB,OAAO,MAAM,EAAE,EAAE,CAAA;AACnB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UUID Generator Utility
|
|
3
|
+
*
|
|
4
|
+
* Browser-compatible UUID generation.
|
|
5
|
+
* Uses Web Crypto API if available, falls back to simple implementation.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Generate a UUID v4
|
|
9
|
+
* Uses crypto.randomUUID() if available, otherwise uses a fallback
|
|
10
|
+
*/
|
|
11
|
+
export declare function generateUUID(): string;
|
|
12
|
+
//# sourceMappingURL=uuid.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uuid.d.ts","sourceRoot":"","sources":["../../src/lib/uuid.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAYrC"}
|
package/dist/lib/uuid.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UUID Generator Utility
|
|
3
|
+
*
|
|
4
|
+
* Browser-compatible UUID generation.
|
|
5
|
+
* Uses Web Crypto API if available, falls back to simple implementation.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Generate a UUID v4
|
|
9
|
+
* Uses crypto.randomUUID() if available, otherwise uses a fallback
|
|
10
|
+
*/
|
|
11
|
+
export function generateUUID() {
|
|
12
|
+
// Try Web Crypto API first
|
|
13
|
+
if (typeof crypto !== 'undefined' && crypto.randomUUID) {
|
|
14
|
+
return crypto.randomUUID();
|
|
15
|
+
}
|
|
16
|
+
// Fallback implementation
|
|
17
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
18
|
+
const r = (Math.random() * 16) | 0;
|
|
19
|
+
const v = c === 'x' ? r : (r & 0x3) | 0x8;
|
|
20
|
+
return v.toString(16);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=uuid.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uuid.js","sourceRoot":"","sources":["../../src/lib/uuid.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,MAAM,UAAU,YAAY;IAC1B,2BAA2B;IAC3B,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QACvD,OAAO,MAAM,CAAC,UAAU,EAAE,CAAC;IAC7B,CAAC;IAED,0BAA0B;IAC1B,OAAO,sCAAsC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;QACnE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;QACnC,MAAM,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;QAC1C,OAAO,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACxB,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal structured logger interface.
|
|
3
|
+
* Wire in winston, pino, or any other logger at the container level.
|
|
4
|
+
*/
|
|
5
|
+
export interface Logger {
|
|
6
|
+
debug(message: string, context?: Record<string, unknown>): void;
|
|
7
|
+
info(message: string, context?: Record<string, unknown>): void;
|
|
8
|
+
warn(message: string, context?: Record<string, unknown>): void;
|
|
9
|
+
error(message: string, context?: Record<string, unknown>): void;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Abstract base class for all services.
|
|
13
|
+
*
|
|
14
|
+
* Provides:
|
|
15
|
+
* - Constructor injection of config and logger
|
|
16
|
+
* - Optional initialize/shutdown lifecycle hooks
|
|
17
|
+
* - Consistent naming (className from constructor.name)
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* class UserService extends BaseService<ServiceConfig> {
|
|
21
|
+
* constructor(config: ServiceConfig, logger: Logger) {
|
|
22
|
+
* super(config, logger);
|
|
23
|
+
* }
|
|
24
|
+
*
|
|
25
|
+
* async initialize(): Promise<void> {
|
|
26
|
+
* // connect to DB, warm up caches, etc.
|
|
27
|
+
* }
|
|
28
|
+
* }
|
|
29
|
+
*/
|
|
30
|
+
export declare abstract class BaseService<TConfig = unknown> {
|
|
31
|
+
protected readonly config: TConfig;
|
|
32
|
+
protected readonly logger: Logger;
|
|
33
|
+
protected readonly name: string;
|
|
34
|
+
constructor(config: TConfig, logger: Logger);
|
|
35
|
+
/**
|
|
36
|
+
* Called once when the application starts.
|
|
37
|
+
* Override to connect to databases, warm up caches, or validate config.
|
|
38
|
+
*/
|
|
39
|
+
initialize(): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Called once when the application shuts down.
|
|
42
|
+
* Override to close connections, flush buffers, or clean up resources.
|
|
43
|
+
*/
|
|
44
|
+
shutdown(): Promise<void>;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=base.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.service.d.ts","sourceRoot":"","sources":["../../src/services/base.service.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,MAAM,WAAW,MAAM;IACrB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAChE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC/D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC/D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CACjE;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,8BAAsB,WAAW,CAAC,OAAO,GAAG,OAAO;IAI/C,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO;IAClC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM;IAJnC,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAGX,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,MAAM;IAKnC;;;OAGG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAIjC;;;OAGG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAGhC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// src/services/base.service.ts
|
|
2
|
+
// Pattern: Service Base (core-sdk.service-base.md)
|
|
3
|
+
/**
|
|
4
|
+
* Abstract base class for all services.
|
|
5
|
+
*
|
|
6
|
+
* Provides:
|
|
7
|
+
* - Constructor injection of config and logger
|
|
8
|
+
* - Optional initialize/shutdown lifecycle hooks
|
|
9
|
+
* - Consistent naming (className from constructor.name)
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* class UserService extends BaseService<ServiceConfig> {
|
|
13
|
+
* constructor(config: ServiceConfig, logger: Logger) {
|
|
14
|
+
* super(config, logger);
|
|
15
|
+
* }
|
|
16
|
+
*
|
|
17
|
+
* async initialize(): Promise<void> {
|
|
18
|
+
* // connect to DB, warm up caches, etc.
|
|
19
|
+
* }
|
|
20
|
+
* }
|
|
21
|
+
*/
|
|
22
|
+
export class BaseService {
|
|
23
|
+
config;
|
|
24
|
+
logger;
|
|
25
|
+
name;
|
|
26
|
+
constructor(config, logger) {
|
|
27
|
+
this.config = config;
|
|
28
|
+
this.logger = logger;
|
|
29
|
+
this.name = this.constructor.name;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Called once when the application starts.
|
|
33
|
+
* Override to connect to databases, warm up caches, or validate config.
|
|
34
|
+
*/
|
|
35
|
+
async initialize() {
|
|
36
|
+
// No-op by default
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Called once when the application shuts down.
|
|
40
|
+
* Override to close connections, flush buffers, or clean up resources.
|
|
41
|
+
*/
|
|
42
|
+
async shutdown() {
|
|
43
|
+
// No-op by default
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=base.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.service.js","sourceRoot":"","sources":["../../src/services/base.service.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,mDAAmD;AAanD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,OAAgB,WAAW;IAIV;IACA;IAJF,IAAI,CAAS;IAEhC,YACqB,MAAe,EACf,MAAc;QADd,WAAM,GAAN,MAAM,CAAS;QACf,WAAM,GAAN,MAAM,CAAQ;QAEjC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;IACpC,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,UAAU;QACd,mBAAmB;IACrB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,QAAQ;QACZ,mBAAmB;IACrB,CAAC;CACF"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A pending action stored against a confirmation token.
|
|
3
|
+
* Encodes the exact operation parameters to prevent tampering.
|
|
4
|
+
*/
|
|
5
|
+
export interface PendingAction {
|
|
6
|
+
type: string;
|
|
7
|
+
userId: string;
|
|
8
|
+
params: Record<string, unknown>;
|
|
9
|
+
summary: string;
|
|
10
|
+
createdAt: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Confirmation Token Service
|
|
14
|
+
*
|
|
15
|
+
* In-memory token store for two-step confirmation flows.
|
|
16
|
+
* Mutating tools generate a preview + token; a confirm step consumes the token to execute.
|
|
17
|
+
* Tokens are single-use, user-scoped, and expire after TTL.
|
|
18
|
+
*/
|
|
19
|
+
export declare class ConfirmationTokenService {
|
|
20
|
+
private pending;
|
|
21
|
+
private ttlMs;
|
|
22
|
+
constructor(ttlMs?: number);
|
|
23
|
+
/**
|
|
24
|
+
* Generate a confirmation token for a pending action.
|
|
25
|
+
* Returns a 32-char hex string.
|
|
26
|
+
*/
|
|
27
|
+
generateToken(action: PendingAction): string;
|
|
28
|
+
/**
|
|
29
|
+
* Consume a confirmation token.
|
|
30
|
+
* Returns the pending action if valid, null otherwise.
|
|
31
|
+
* Tokens are single-use — consumed on retrieval.
|
|
32
|
+
* Validates userId matches the original initiator.
|
|
33
|
+
*/
|
|
34
|
+
consumeToken(token: string, userId: string): PendingAction | null;
|
|
35
|
+
/**
|
|
36
|
+
* Lazy cleanup of expired tokens.
|
|
37
|
+
*/
|
|
38
|
+
private cleanup;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=confirmation-token.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confirmation-token.service.d.ts","sourceRoot":"","sources":["../../src/services/confirmation-token.service.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC/B,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;CAClB;AAID;;;;;;GAMG;AACH,qBAAa,wBAAwB;IACnC,OAAO,CAAC,OAAO,CAAmC;IAClD,OAAO,CAAC,KAAK,CAAQ;gBAET,KAAK,GAAE,MAAuB;IAI1C;;;OAGG;IACH,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM;IAO5C;;;;;OAKG;IACH,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI;IAoBjE;;OAEG;IACH,OAAO,CAAC,OAAO;CAQhB"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { randomBytes } from 'node:crypto';
|
|
2
|
+
const DEFAULT_TTL_MS = 5 * 60 * 1000; // 5 minutes
|
|
3
|
+
/**
|
|
4
|
+
* Confirmation Token Service
|
|
5
|
+
*
|
|
6
|
+
* In-memory token store for two-step confirmation flows.
|
|
7
|
+
* Mutating tools generate a preview + token; a confirm step consumes the token to execute.
|
|
8
|
+
* Tokens are single-use, user-scoped, and expire after TTL.
|
|
9
|
+
*/
|
|
10
|
+
export class ConfirmationTokenService {
|
|
11
|
+
pending = new Map();
|
|
12
|
+
ttlMs;
|
|
13
|
+
constructor(ttlMs = DEFAULT_TTL_MS) {
|
|
14
|
+
this.ttlMs = ttlMs;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Generate a confirmation token for a pending action.
|
|
18
|
+
* Returns a 32-char hex string.
|
|
19
|
+
*/
|
|
20
|
+
generateToken(action) {
|
|
21
|
+
this.cleanup();
|
|
22
|
+
const token = randomBytes(16).toString('hex');
|
|
23
|
+
this.pending.set(token, action);
|
|
24
|
+
return token;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Consume a confirmation token.
|
|
28
|
+
* Returns the pending action if valid, null otherwise.
|
|
29
|
+
* Tokens are single-use — consumed on retrieval.
|
|
30
|
+
* Validates userId matches the original initiator.
|
|
31
|
+
*/
|
|
32
|
+
consumeToken(token, userId) {
|
|
33
|
+
const action = this.pending.get(token);
|
|
34
|
+
if (!action)
|
|
35
|
+
return null;
|
|
36
|
+
// Always delete — single use
|
|
37
|
+
this.pending.delete(token);
|
|
38
|
+
// Check TTL
|
|
39
|
+
if (Date.now() - action.createdAt > this.ttlMs) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
// Validate userId matches
|
|
43
|
+
if (action.userId !== userId) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
return action;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Lazy cleanup of expired tokens.
|
|
50
|
+
*/
|
|
51
|
+
cleanup() {
|
|
52
|
+
const now = Date.now();
|
|
53
|
+
for (const [token, action] of this.pending) {
|
|
54
|
+
if (now - action.createdAt > this.ttlMs) {
|
|
55
|
+
this.pending.delete(token);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=confirmation-token.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confirmation-token.service.js","sourceRoot":"","sources":["../../src/services/confirmation-token.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAczC,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAA,CAAC,YAAY;AAEjD;;;;;;GAMG;AACH,MAAM,OAAO,wBAAwB;IAC3B,OAAO,GAAG,IAAI,GAAG,EAAyB,CAAA;IAC1C,KAAK,CAAQ;IAErB,YAAY,QAAgB,cAAc;QACxC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;IACpB,CAAC;IAED;;;OAGG;IACH,aAAa,CAAC,MAAqB;QACjC,IAAI,CAAC,OAAO,EAAE,CAAA;QACd,MAAM,KAAK,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;QAC7C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;QAC/B,OAAO,KAAK,CAAA;IACd,CAAC;IAED;;;;;OAKG;IACH,YAAY,CAAC,KAAa,EAAE,MAAc;QACxC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QACtC,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAA;QAExB,6BAA6B;QAC7B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QAE1B,YAAY;QACZ,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;YAC/C,OAAO,IAAI,CAAA;QACb,CAAC;QAED,0BAA0B;QAC1B,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC7B,OAAO,IAAI,CAAA;QACb,CAAC;QAED,OAAO,MAAM,CAAA;IACf,CAAC;IAED;;OAEG;IACK,OAAO;QACb,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QACtB,KAAK,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC3C,IAAI,GAAG,GAAG,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;gBACxC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;YAC5B,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { BaseService } from './base.service.js';
|
|
2
|
+
export type { Logger } from './base.service.js';
|
|
3
|
+
export { ConfirmationTokenService } from './confirmation-token.service.js';
|
|
4
|
+
export type { PendingAction } from './confirmation-token.service.js';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,YAAY,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAA;AAC1E,YAAY,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAE/C,OAAO,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAA"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core auth types used across agentbase projects.
|
|
3
|
+
*/
|
|
4
|
+
export interface AuthUser {
|
|
5
|
+
uid: string;
|
|
6
|
+
email: string | null;
|
|
7
|
+
displayName: string | null;
|
|
8
|
+
photoURL: string | null;
|
|
9
|
+
emailVerified: boolean;
|
|
10
|
+
isAnonymous: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface ServerSession {
|
|
13
|
+
user: AuthUser;
|
|
14
|
+
}
|
|
15
|
+
export interface AuthResult {
|
|
16
|
+
success: boolean;
|
|
17
|
+
error?: string;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,aAAa,EAAE,OAAO,CAAC;IACvB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,QAAQ,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
package/package.json
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@prmichaelsen/agentbase-core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Shared service infrastructure for agentbase projects — BaseService, auth, Firebase wrappers, logging, and common utilities",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
},
|
|
13
|
+
"./services": {
|
|
14
|
+
"import": "./dist/services/index.js",
|
|
15
|
+
"types": "./dist/services/index.d.ts"
|
|
16
|
+
},
|
|
17
|
+
"./lib": {
|
|
18
|
+
"import": "./dist/lib/index.js",
|
|
19
|
+
"types": "./dist/lib/index.d.ts"
|
|
20
|
+
},
|
|
21
|
+
"./lib/auth": {
|
|
22
|
+
"import": "./dist/lib/auth/index.js",
|
|
23
|
+
"types": "./dist/lib/auth/index.d.ts"
|
|
24
|
+
},
|
|
25
|
+
"./types": {
|
|
26
|
+
"import": "./dist/types/index.js",
|
|
27
|
+
"types": "./dist/types/index.d.ts"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"dist"
|
|
32
|
+
],
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "tsc",
|
|
35
|
+
"dev": "tsc --watch",
|
|
36
|
+
"typecheck": "tsc --noEmit",
|
|
37
|
+
"prepublishOnly": "npm run build"
|
|
38
|
+
},
|
|
39
|
+
"keywords": [
|
|
40
|
+
"agentbase",
|
|
41
|
+
"service",
|
|
42
|
+
"firebase",
|
|
43
|
+
"auth"
|
|
44
|
+
],
|
|
45
|
+
"author": "prmichaelsen",
|
|
46
|
+
"license": "MIT",
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"@prmichaelsen/firebase-admin-sdk-v8": ">=2.0.0",
|
|
49
|
+
"firebase": ">=10.0.0",
|
|
50
|
+
"jsonwebtoken": ">=9.0.0"
|
|
51
|
+
},
|
|
52
|
+
"peerDependenciesMeta": {
|
|
53
|
+
"@prmichaelsen/firebase-admin-sdk-v8": {
|
|
54
|
+
"optional": true
|
|
55
|
+
},
|
|
56
|
+
"firebase": {
|
|
57
|
+
"optional": true
|
|
58
|
+
},
|
|
59
|
+
"jsonwebtoken": {
|
|
60
|
+
"optional": true
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
"devDependencies": {
|
|
64
|
+
"@prmichaelsen/firebase-admin-sdk-v8": "^2.8.0",
|
|
65
|
+
"firebase": "^10.14.1",
|
|
66
|
+
"jsonwebtoken": "^9.0.3",
|
|
67
|
+
"@types/jsonwebtoken": "^9.0.0",
|
|
68
|
+
"typescript": "^5.5.0"
|
|
69
|
+
}
|
|
70
|
+
}
|