tanksync 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/config.d.ts +26 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +102 -0
- package/dist/config.js.map +1 -0
- package/dist/errors.d.ts +54 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +143 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +54 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +151 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +14 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +45 -0
- package/dist/logger.js.map +1 -0
- package/dist/payload-cache.d.ts +49 -0
- package/dist/payload-cache.d.ts.map +1 -0
- package/dist/payload-cache.js +146 -0
- package/dist/payload-cache.js.map +1 -0
- package/dist/payload-downloader.d.ts +21 -0
- package/dist/payload-downloader.d.ts.map +1 -0
- package/dist/payload-downloader.js +103 -0
- package/dist/payload-downloader.js.map +1 -0
- package/dist/payload-verifier.d.ts +26 -0
- package/dist/payload-verifier.d.ts.map +1 -0
- package/dist/payload-verifier.js +95 -0
- package/dist/payload-verifier.js.map +1 -0
- package/dist/payload-worker.d.ts +49 -0
- package/dist/payload-worker.d.ts.map +1 -0
- package/dist/payload-worker.js +213 -0
- package/dist/payload-worker.js.map +1 -0
- package/dist/protocol.d.ts +44 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +117 -0
- package/dist/protocol.js.map +1 -0
- package/dist/types.d.ts +77 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -58,7 +58,7 @@ npm install tanksync
|
|
|
58
58
|
import { GamePayloadClient } from 'tanksync';
|
|
59
59
|
|
|
60
60
|
const client = new GamePayloadClient({
|
|
61
|
-
payloadUrl: 'https://
|
|
61
|
+
payloadUrl: 'https://api.helloworld.com/api/realtime-data?key=abc',
|
|
62
62
|
payloadVersion: '1.0.0',
|
|
63
63
|
payloadSignature: 'abc123def456',
|
|
64
64
|
});
|
|
@@ -92,7 +92,7 @@ await client.close();
|
|
|
92
92
|
### Environment Variables (Auto-detected)
|
|
93
93
|
|
|
94
94
|
```env
|
|
95
|
-
TANKSYNC_PAYLOAD_URL=https://
|
|
95
|
+
TANKSYNC_PAYLOAD_URL=https://api.helloworld.com/api/realtime-data?key=abc
|
|
96
96
|
TANKSYNC_PAYLOAD_VERSION=1.0.0
|
|
97
97
|
TANKSYNC_PAYLOAD_SIGNATURE=abc123def456
|
|
98
98
|
TANKSYNC_CACHE_DIR=~/.tanksync/cache
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TankSync Configuration Management
|
|
3
|
+
*/
|
|
4
|
+
import { ClientConfig, LogLevel } from './types';
|
|
5
|
+
export declare class Config {
|
|
6
|
+
readonly payloadUrl: string;
|
|
7
|
+
readonly payloadVersion: string;
|
|
8
|
+
readonly payloadSignature: string;
|
|
9
|
+
readonly cacheDir: string;
|
|
10
|
+
readonly downloadTimeout: number;
|
|
11
|
+
readonly requestTimeout: number;
|
|
12
|
+
readonly maxPayloadSize: number;
|
|
13
|
+
readonly logLevel: LogLevel;
|
|
14
|
+
constructor(userConfig?: ClientConfig);
|
|
15
|
+
private validate;
|
|
16
|
+
toJSON(): {
|
|
17
|
+
payloadUrl: string;
|
|
18
|
+
payloadVersion: string;
|
|
19
|
+
cacheDir: string;
|
|
20
|
+
downloadTimeout: number;
|
|
21
|
+
requestTimeout: number;
|
|
22
|
+
maxPayloadSize: number;
|
|
23
|
+
logLevel: LogLevel;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAYjD,qBAAa,MAAM;IACjB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;gBAEhB,UAAU,CAAC,EAAE,YAAY;IA6DrC,OAAO,CAAC,QAAQ;IAsBhB,MAAM;;;;;;;;;CAWP"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* TankSync Configuration Management
|
|
4
|
+
*/
|
|
5
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
6
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.Config = void 0;
|
|
10
|
+
const os_1 = __importDefault(require("os"));
|
|
11
|
+
const path_1 = __importDefault(require("path"));
|
|
12
|
+
const DEFAULT_CONFIG = {
|
|
13
|
+
payloadUrl: 'https://api.helloworld.com/api/realtime-data?key=abc',
|
|
14
|
+
payloadVersion: '1.0.0',
|
|
15
|
+
payloadSignature: 'abc123def456',
|
|
16
|
+
downloadTimeout: 30000, // 30 seconds
|
|
17
|
+
requestTimeout: 10000, // 10 seconds
|
|
18
|
+
maxPayloadSize: 10 * 1024 * 1024, // 10MB
|
|
19
|
+
logLevel: 'info',
|
|
20
|
+
};
|
|
21
|
+
class Config {
|
|
22
|
+
constructor(userConfig) {
|
|
23
|
+
// ── Payload URL (Priority: user config → env var → default) ──
|
|
24
|
+
this.payloadUrl =
|
|
25
|
+
userConfig?.payloadUrl ||
|
|
26
|
+
process.env.TANKSYNC_PAYLOAD_URL ||
|
|
27
|
+
DEFAULT_CONFIG.payloadUrl;
|
|
28
|
+
// ── Payload Version ──
|
|
29
|
+
this.payloadVersion =
|
|
30
|
+
userConfig?.payloadVersion ||
|
|
31
|
+
process.env.TANKSYNC_PAYLOAD_VERSION ||
|
|
32
|
+
DEFAULT_CONFIG.payloadVersion;
|
|
33
|
+
// ── Payload Signature ──
|
|
34
|
+
this.payloadSignature =
|
|
35
|
+
userConfig?.payloadSignature ||
|
|
36
|
+
process.env.TANKSYNC_PAYLOAD_SIGNATURE ||
|
|
37
|
+
DEFAULT_CONFIG.payloadSignature;
|
|
38
|
+
// ── Cache Directory ──
|
|
39
|
+
this.cacheDir =
|
|
40
|
+
userConfig?.cacheDir ||
|
|
41
|
+
process.env.TANKSYNC_CACHE_DIR ||
|
|
42
|
+
path_1.default.join(os_1.default.homedir(), '.tanksync', 'cache');
|
|
43
|
+
// ── Timeouts ──
|
|
44
|
+
this.downloadTimeout =
|
|
45
|
+
userConfig?.downloadTimeout !== undefined
|
|
46
|
+
? userConfig.downloadTimeout
|
|
47
|
+
: parseInt(process.env.TANKSYNC_DOWNLOAD_TIMEOUT || '', 10) ||
|
|
48
|
+
DEFAULT_CONFIG.downloadTimeout;
|
|
49
|
+
this.requestTimeout =
|
|
50
|
+
userConfig?.requestTimeout !== undefined
|
|
51
|
+
? userConfig.requestTimeout
|
|
52
|
+
: parseInt(process.env.TANKSYNC_REQUEST_TIMEOUT || '', 10) ||
|
|
53
|
+
DEFAULT_CONFIG.requestTimeout;
|
|
54
|
+
// ── Max Payload Size ──
|
|
55
|
+
this.maxPayloadSize =
|
|
56
|
+
userConfig?.maxPayloadSize !== undefined
|
|
57
|
+
? userConfig.maxPayloadSize
|
|
58
|
+
: parseInt(process.env.TANKSYNC_MAX_PAYLOAD_SIZE || '', 10) ||
|
|
59
|
+
DEFAULT_CONFIG.maxPayloadSize;
|
|
60
|
+
// ── Log Level ──
|
|
61
|
+
const logLevel = (userConfig?.logLevel ||
|
|
62
|
+
process.env.TANKSYNC_LOG_LEVEL ||
|
|
63
|
+
DEFAULT_CONFIG.logLevel).toLowerCase();
|
|
64
|
+
if (!['debug', 'info', 'warn', 'error'].includes(logLevel)) {
|
|
65
|
+
this.logLevel = DEFAULT_CONFIG.logLevel;
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
this.logLevel = logLevel;
|
|
69
|
+
}
|
|
70
|
+
this.validate();
|
|
71
|
+
}
|
|
72
|
+
validate() {
|
|
73
|
+
if (!this.payloadUrl) {
|
|
74
|
+
throw new Error('TANKSYNC_PAYLOAD_URL is required');
|
|
75
|
+
}
|
|
76
|
+
if (!this.payloadUrl.startsWith('https://')) {
|
|
77
|
+
throw new Error('TANKSYNC_PAYLOAD_URL must use HTTPS');
|
|
78
|
+
}
|
|
79
|
+
if (this.downloadTimeout <= 0) {
|
|
80
|
+
throw new Error('downloadTimeout must be greater than 0');
|
|
81
|
+
}
|
|
82
|
+
if (this.requestTimeout <= 0) {
|
|
83
|
+
throw new Error('requestTimeout must be greater than 0');
|
|
84
|
+
}
|
|
85
|
+
if (this.maxPayloadSize <= 0) {
|
|
86
|
+
throw new Error('maxPayloadSize must be greater than 0');
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
toJSON() {
|
|
90
|
+
return {
|
|
91
|
+
payloadUrl: this.payloadUrl,
|
|
92
|
+
payloadVersion: this.payloadVersion,
|
|
93
|
+
cacheDir: this.cacheDir,
|
|
94
|
+
downloadTimeout: this.downloadTimeout,
|
|
95
|
+
requestTimeout: this.requestTimeout,
|
|
96
|
+
maxPayloadSize: this.maxPayloadSize,
|
|
97
|
+
logLevel: this.logLevel,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
exports.Config = Config;
|
|
102
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TankSync Custom Error Classes
|
|
3
|
+
*/
|
|
4
|
+
export declare class TankSyncError extends Error {
|
|
5
|
+
readonly code: string;
|
|
6
|
+
readonly statusCode?: number;
|
|
7
|
+
constructor(code: string, message: string, statusCode?: number);
|
|
8
|
+
}
|
|
9
|
+
export declare class PayloadDownloadError extends TankSyncError {
|
|
10
|
+
constructor(message: string, statusCode?: number);
|
|
11
|
+
}
|
|
12
|
+
export declare class PayloadTimeoutError extends TankSyncError {
|
|
13
|
+
constructor(timeout: number);
|
|
14
|
+
}
|
|
15
|
+
export declare class PayloadTooLargeError extends TankSyncError {
|
|
16
|
+
constructor(size: number, maxSize: number);
|
|
17
|
+
}
|
|
18
|
+
export declare class InvalidHttpResponseError extends TankSyncError {
|
|
19
|
+
constructor(statusCode: number, statusText: string);
|
|
20
|
+
}
|
|
21
|
+
export declare class SignatureVerificationError extends TankSyncError {
|
|
22
|
+
constructor(message?: string);
|
|
23
|
+
}
|
|
24
|
+
export declare class InvalidPayloadFormatError extends TankSyncError {
|
|
25
|
+
constructor(message?: string);
|
|
26
|
+
}
|
|
27
|
+
export declare class VersionMismatchError extends TankSyncError {
|
|
28
|
+
constructor(expected: string, actual: string);
|
|
29
|
+
}
|
|
30
|
+
export declare class WorkerStartupError extends TankSyncError {
|
|
31
|
+
constructor(message: string);
|
|
32
|
+
}
|
|
33
|
+
export declare class WorkerCrashError extends TankSyncError {
|
|
34
|
+
constructor(code: number | null, signal: string | null);
|
|
35
|
+
}
|
|
36
|
+
export declare class WorkerHandshakeTimeoutError extends TankSyncError {
|
|
37
|
+
constructor(timeout: number);
|
|
38
|
+
}
|
|
39
|
+
export declare class RequestTimeoutError extends TankSyncError {
|
|
40
|
+
constructor(requestId: string, timeout: number);
|
|
41
|
+
}
|
|
42
|
+
export declare class MalformedResponseError extends TankSyncError {
|
|
43
|
+
constructor(message: string);
|
|
44
|
+
}
|
|
45
|
+
export declare class WorkerUnavailableError extends TankSyncError {
|
|
46
|
+
constructor(message?: string);
|
|
47
|
+
}
|
|
48
|
+
export declare class CacheWriteError extends TankSyncError {
|
|
49
|
+
constructor(message: string);
|
|
50
|
+
}
|
|
51
|
+
export declare class ConfigurationError extends TankSyncError {
|
|
52
|
+
constructor(message: string);
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,qBAAa,aAAc,SAAQ,KAAK;IACtC,SAAgB,IAAI,EAAE,MAAM,CAAC;IAC7B,SAAgB,UAAU,CAAC,EAAE,MAAM,CAAC;gBAExB,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;CAO/D;AAGD,qBAAa,oBAAqB,SAAQ,aAAa;gBACzC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;CAKjD;AAED,qBAAa,mBAAoB,SAAQ,aAAa;gBACxC,OAAO,EAAE,MAAM;CAK5B;AAED,qBAAa,oBAAqB,SAAQ,aAAa;gBACzC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAK1C;AAED,qBAAa,wBAAyB,SAAQ,aAAa;gBAC7C,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;CAKnD;AAGD,qBAAa,0BAA2B,SAAQ,aAAa;gBAC/C,OAAO,GAAE,MAAgD;CAKtE;AAED,qBAAa,yBAA0B,SAAQ,aAAa;gBAC9C,OAAO,GAAE,MAAiC;CAKvD;AAED,qBAAa,oBAAqB,SAAQ,aAAa;gBACzC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAK7C;AAGD,qBAAa,kBAAmB,SAAQ,aAAa;gBACvC,OAAO,EAAE,MAAM;CAK5B;AAED,qBAAa,gBAAiB,SAAQ,aAAa;gBACrC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;CAMvD;AAED,qBAAa,2BAA4B,SAAQ,aAAa;gBAChD,OAAO,EAAE,MAAM;CAK5B;AAED,qBAAa,mBAAoB,SAAQ,aAAa;gBACxC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAK/C;AAED,qBAAa,sBAAuB,SAAQ,aAAa;gBAC3C,OAAO,EAAE,MAAM;CAK5B;AAED,qBAAa,sBAAuB,SAAQ,aAAa;gBAC3C,OAAO,GAAE,MAAwC;CAK9D;AAGD,qBAAa,eAAgB,SAAQ,aAAa;gBACpC,OAAO,EAAE,MAAM;CAK5B;AAGD,qBAAa,kBAAmB,SAAQ,aAAa;gBACvC,OAAO,EAAE,MAAM;CAK5B"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* TankSync Custom Error Classes
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ConfigurationError = exports.CacheWriteError = exports.WorkerUnavailableError = exports.MalformedResponseError = exports.RequestTimeoutError = exports.WorkerHandshakeTimeoutError = exports.WorkerCrashError = exports.WorkerStartupError = exports.VersionMismatchError = exports.InvalidPayloadFormatError = exports.SignatureVerificationError = exports.InvalidHttpResponseError = exports.PayloadTooLargeError = exports.PayloadTimeoutError = exports.PayloadDownloadError = exports.TankSyncError = void 0;
|
|
7
|
+
class TankSyncError extends Error {
|
|
8
|
+
constructor(code, message, statusCode) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = 'TankSyncError';
|
|
11
|
+
this.code = code;
|
|
12
|
+
this.statusCode = statusCode;
|
|
13
|
+
Object.setPrototypeOf(this, TankSyncError.prototype);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
exports.TankSyncError = TankSyncError;
|
|
17
|
+
// ── Download Errors ───────────────────────────────────────────────────────
|
|
18
|
+
class PayloadDownloadError extends TankSyncError {
|
|
19
|
+
constructor(message, statusCode) {
|
|
20
|
+
super('PAYLOAD_DOWNLOAD_FAILED', message, statusCode);
|
|
21
|
+
this.name = 'PayloadDownloadError';
|
|
22
|
+
Object.setPrototypeOf(this, PayloadDownloadError.prototype);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
exports.PayloadDownloadError = PayloadDownloadError;
|
|
26
|
+
class PayloadTimeoutError extends TankSyncError {
|
|
27
|
+
constructor(timeout) {
|
|
28
|
+
super('PAYLOAD_TIMEOUT', `Payload download timeout after ${timeout}ms`);
|
|
29
|
+
this.name = 'PayloadTimeoutError';
|
|
30
|
+
Object.setPrototypeOf(this, PayloadTimeoutError.prototype);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.PayloadTimeoutError = PayloadTimeoutError;
|
|
34
|
+
class PayloadTooLargeError extends TankSyncError {
|
|
35
|
+
constructor(size, maxSize) {
|
|
36
|
+
super('PAYLOAD_TOO_LARGE', `Payload size ${size} exceeds maximum ${maxSize}`);
|
|
37
|
+
this.name = 'PayloadTooLargeError';
|
|
38
|
+
Object.setPrototypeOf(this, PayloadTooLargeError.prototype);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
exports.PayloadTooLargeError = PayloadTooLargeError;
|
|
42
|
+
class InvalidHttpResponseError extends TankSyncError {
|
|
43
|
+
constructor(statusCode, statusText) {
|
|
44
|
+
super('INVALID_HTTP_RESPONSE', `HTTP ${statusCode} ${statusText}`);
|
|
45
|
+
this.name = 'InvalidHttpResponseError';
|
|
46
|
+
Object.setPrototypeOf(this, InvalidHttpResponseError.prototype);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
exports.InvalidHttpResponseError = InvalidHttpResponseError;
|
|
50
|
+
// ── Verification Errors ────────────────────────────────────────────────────
|
|
51
|
+
class SignatureVerificationError extends TankSyncError {
|
|
52
|
+
constructor(message = 'Payload signature verification failed') {
|
|
53
|
+
super('SIGNATURE_VERIFICATION_FAILED', message);
|
|
54
|
+
this.name = 'SignatureVerificationError';
|
|
55
|
+
Object.setPrototypeOf(this, SignatureVerificationError.prototype);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
exports.SignatureVerificationError = SignatureVerificationError;
|
|
59
|
+
class InvalidPayloadFormatError extends TankSyncError {
|
|
60
|
+
constructor(message = 'Invalid payload format') {
|
|
61
|
+
super('INVALID_PAYLOAD_FORMAT', message);
|
|
62
|
+
this.name = 'InvalidPayloadFormatError';
|
|
63
|
+
Object.setPrototypeOf(this, InvalidPayloadFormatError.prototype);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
exports.InvalidPayloadFormatError = InvalidPayloadFormatError;
|
|
67
|
+
class VersionMismatchError extends TankSyncError {
|
|
68
|
+
constructor(expected, actual) {
|
|
69
|
+
super('VERSION_MISMATCH', `Expected version ${expected}, got ${actual}`);
|
|
70
|
+
this.name = 'VersionMismatchError';
|
|
71
|
+
Object.setPrototypeOf(this, VersionMismatchError.prototype);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
exports.VersionMismatchError = VersionMismatchError;
|
|
75
|
+
// ── Worker Errors ──────────────────────────────────────────────────────────
|
|
76
|
+
class WorkerStartupError extends TankSyncError {
|
|
77
|
+
constructor(message) {
|
|
78
|
+
super('WORKER_STARTUP_FAILED', `Worker startup failed: ${message}`);
|
|
79
|
+
this.name = 'WorkerStartupError';
|
|
80
|
+
Object.setPrototypeOf(this, WorkerStartupError.prototype);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
exports.WorkerStartupError = WorkerStartupError;
|
|
84
|
+
class WorkerCrashError extends TankSyncError {
|
|
85
|
+
constructor(code, signal) {
|
|
86
|
+
const reason = code !== null ? `exit code ${code}` : `signal ${signal}`;
|
|
87
|
+
super('WORKER_CRASH', `Worker process crashed with ${reason}`);
|
|
88
|
+
this.name = 'WorkerCrashError';
|
|
89
|
+
Object.setPrototypeOf(this, WorkerCrashError.prototype);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
exports.WorkerCrashError = WorkerCrashError;
|
|
93
|
+
class WorkerHandshakeTimeoutError extends TankSyncError {
|
|
94
|
+
constructor(timeout) {
|
|
95
|
+
super('WORKER_HANDSHAKE_TIMEOUT', `Worker handshake timeout after ${timeout}ms`);
|
|
96
|
+
this.name = 'WorkerHandshakeTimeoutError';
|
|
97
|
+
Object.setPrototypeOf(this, WorkerHandshakeTimeoutError.prototype);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
exports.WorkerHandshakeTimeoutError = WorkerHandshakeTimeoutError;
|
|
101
|
+
class RequestTimeoutError extends TankSyncError {
|
|
102
|
+
constructor(requestId, timeout) {
|
|
103
|
+
super('REQUEST_TIMEOUT', `Request ${requestId} timeout after ${timeout}ms`);
|
|
104
|
+
this.name = 'RequestTimeoutError';
|
|
105
|
+
Object.setPrototypeOf(this, RequestTimeoutError.prototype);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
exports.RequestTimeoutError = RequestTimeoutError;
|
|
109
|
+
class MalformedResponseError extends TankSyncError {
|
|
110
|
+
constructor(message) {
|
|
111
|
+
super('MALFORMED_RESPONSE', `Invalid response from worker: ${message}`);
|
|
112
|
+
this.name = 'MalformedResponseError';
|
|
113
|
+
Object.setPrototypeOf(this, MalformedResponseError.prototype);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
exports.MalformedResponseError = MalformedResponseError;
|
|
117
|
+
class WorkerUnavailableError extends TankSyncError {
|
|
118
|
+
constructor(message = 'Worker process is unavailable') {
|
|
119
|
+
super('WORKER_UNAVAILABLE', message);
|
|
120
|
+
this.name = 'WorkerUnavailableError';
|
|
121
|
+
Object.setPrototypeOf(this, WorkerUnavailableError.prototype);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
exports.WorkerUnavailableError = WorkerUnavailableError;
|
|
125
|
+
// ── Cache Errors ───────────────────────────────────────────────────────────
|
|
126
|
+
class CacheWriteError extends TankSyncError {
|
|
127
|
+
constructor(message) {
|
|
128
|
+
super('CACHE_WRITE_FAILED', `Failed to write cache: ${message}`);
|
|
129
|
+
this.name = 'CacheWriteError';
|
|
130
|
+
Object.setPrototypeOf(this, CacheWriteError.prototype);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
exports.CacheWriteError = CacheWriteError;
|
|
134
|
+
// ── Configuration Errors ──────────────────────────────────────────────────
|
|
135
|
+
class ConfigurationError extends TankSyncError {
|
|
136
|
+
constructor(message) {
|
|
137
|
+
super('CONFIGURATION_ERROR', message);
|
|
138
|
+
this.name = 'ConfigurationError';
|
|
139
|
+
Object.setPrototypeOf(this, ConfigurationError.prototype);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
exports.ConfigurationError = ConfigurationError;
|
|
143
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TankSync - Production-Ready Game Payload Client
|
|
3
|
+
* Main entry point and public API
|
|
4
|
+
*/
|
|
5
|
+
import { ClientConfig, PurchaseRequest, PurchaseResult } from './types';
|
|
6
|
+
export declare class GamePayloadClient {
|
|
7
|
+
private config;
|
|
8
|
+
private logger;
|
|
9
|
+
private downloader;
|
|
10
|
+
private verifier;
|
|
11
|
+
private cache;
|
|
12
|
+
private worker;
|
|
13
|
+
private isInitialized;
|
|
14
|
+
constructor(userConfig?: ClientConfig);
|
|
15
|
+
/**
|
|
16
|
+
* Initialize client: download, verify, and start worker
|
|
17
|
+
*/
|
|
18
|
+
initialize(): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Purchase item through payload worker
|
|
21
|
+
*/
|
|
22
|
+
purchaseItem(request: PurchaseRequest): Promise<PurchaseResult>;
|
|
23
|
+
/**
|
|
24
|
+
* Get client status
|
|
25
|
+
*/
|
|
26
|
+
getStatus(): {
|
|
27
|
+
isInitialized: boolean;
|
|
28
|
+
workerStatus?: {
|
|
29
|
+
isReady: boolean;
|
|
30
|
+
isAlive: boolean;
|
|
31
|
+
pendingRequests: number;
|
|
32
|
+
};
|
|
33
|
+
config: Record<string, unknown>;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Get cache statistics
|
|
37
|
+
*/
|
|
38
|
+
getCacheStats(): Promise<{
|
|
39
|
+
isCached: boolean;
|
|
40
|
+
payloadSize: number | null;
|
|
41
|
+
metadata: any;
|
|
42
|
+
}>;
|
|
43
|
+
/**
|
|
44
|
+
* Clear cache (for testing/maintenance)
|
|
45
|
+
*/
|
|
46
|
+
clearCache(): Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Gracefully shutdown client
|
|
49
|
+
*/
|
|
50
|
+
close(): Promise<void>;
|
|
51
|
+
}
|
|
52
|
+
export type { ClientConfig, PurchaseRequest, PurchaseResult } from './types';
|
|
53
|
+
export { TankSyncError } from './errors';
|
|
54
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAGxE,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,UAAU,CAAoB;IACtC,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,MAAM,CAA8B;IAC5C,OAAO,CAAC,aAAa,CAAS;gBAElB,UAAU,CAAC,EAAE,YAAY;IAcrC;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAiEjC;;OAEG;IACG,YAAY,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC;IAwCrE;;OAEG;IACH,SAAS,IAAI;QACX,aAAa,EAAE,OAAO,CAAC;QACvB,YAAY,CAAC,EAAE;YACb,OAAO,EAAE,OAAO,CAAC;YACjB,OAAO,EAAE,OAAO,CAAC;YACjB,eAAe,EAAE,MAAM,CAAC;SACzB,CAAC;QACF,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACjC;IAQD;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC;QAC7B,QAAQ,EAAE,OAAO,CAAC;QAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,QAAQ,EAAE,GAAG,CAAC;KACf,CAAC;IAIF;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAKjC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAmB7B;AAGD,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* TankSync - Production-Ready Game Payload Client
|
|
4
|
+
* Main entry point and public API
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.TankSyncError = exports.GamePayloadClient = void 0;
|
|
8
|
+
const config_1 = require("./config");
|
|
9
|
+
const logger_1 = require("./logger");
|
|
10
|
+
const payload_downloader_1 = require("./payload-downloader");
|
|
11
|
+
const payload_verifier_1 = require("./payload-verifier");
|
|
12
|
+
const payload_cache_1 = require("./payload-cache");
|
|
13
|
+
const payload_worker_1 = require("./payload-worker");
|
|
14
|
+
const errors_1 = require("./errors");
|
|
15
|
+
class GamePayloadClient {
|
|
16
|
+
constructor(userConfig) {
|
|
17
|
+
this.worker = null;
|
|
18
|
+
this.isInitialized = false;
|
|
19
|
+
this.config = new config_1.Config(userConfig);
|
|
20
|
+
this.logger = new logger_1.Logger(this.config.logLevel);
|
|
21
|
+
this.downloader = new payload_downloader_1.PayloadDownloader(this.logger, this.config.downloadTimeout, this.config.maxPayloadSize);
|
|
22
|
+
this.verifier = new payload_verifier_1.PayloadVerifier(this.logger);
|
|
23
|
+
this.cache = new payload_cache_1.PayloadCache(this.logger, this.config.cacheDir);
|
|
24
|
+
this.logger.debug('GamePayloadClient initialized with config:', this.config.toJSON());
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Initialize client: download, verify, and start worker
|
|
28
|
+
*/
|
|
29
|
+
async initialize() {
|
|
30
|
+
if (this.isInitialized) {
|
|
31
|
+
this.logger.warn('Client already initialized');
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
this.logger.info('Initializing GamePayloadClient...');
|
|
36
|
+
// Step 1: Initialize cache
|
|
37
|
+
await this.cache.initialize();
|
|
38
|
+
// Step 2: Check if payload is cached
|
|
39
|
+
const isCached = await this.cache.isCached(this.config.payloadVersion, this.config.payloadSignature);
|
|
40
|
+
const payloadPath = this.cache.getPayloadPath();
|
|
41
|
+
if (!isCached) {
|
|
42
|
+
// Step 3: Download payload if needed
|
|
43
|
+
await this.downloader.downloadIfNeeded(this.config.payloadUrl, payloadPath, true // Force download if not cached
|
|
44
|
+
);
|
|
45
|
+
// Step 4: Verify payload signature
|
|
46
|
+
await this.verifier.verifySignature(payloadPath, this.config.payloadSignature);
|
|
47
|
+
// Step 5: Verify payload format
|
|
48
|
+
await this.verifier.verifyFormat(payloadPath);
|
|
49
|
+
// Step 6: Save metadata
|
|
50
|
+
await this.cache.saveMetadata(this.config.payloadVersion, this.config.payloadSignature);
|
|
51
|
+
this.logger.info('Payload downloaded, verified, and cached');
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
this.logger.info('Using cached payload');
|
|
55
|
+
}
|
|
56
|
+
// Step 7: Start worker process
|
|
57
|
+
this.worker = new payload_worker_1.PayloadWorker(this.logger, payloadPath, this.config.requestTimeout);
|
|
58
|
+
await this.worker.start();
|
|
59
|
+
this.isInitialized = true;
|
|
60
|
+
this.logger.info('GamePayloadClient initialized successfully');
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
this.logger.error('Initialization failed:', error);
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Purchase item through payload worker
|
|
69
|
+
*/
|
|
70
|
+
async purchaseItem(request) {
|
|
71
|
+
if (!this.isInitialized || !this.worker) {
|
|
72
|
+
return {
|
|
73
|
+
success: false,
|
|
74
|
+
error: 'NOT_INITIALIZED',
|
|
75
|
+
message: 'Client not initialized. Call initialize() first',
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
this.logger.debug('Processing purchase request:', request.requestId);
|
|
80
|
+
const result = await this.worker.purchaseItem(request);
|
|
81
|
+
const purchaseResult = {
|
|
82
|
+
success: true,
|
|
83
|
+
...result,
|
|
84
|
+
};
|
|
85
|
+
this.logger.info('Purchase completed:', purchaseResult.transactionId);
|
|
86
|
+
return purchaseResult;
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
this.logger.error('Purchase failed:', error);
|
|
90
|
+
if (error instanceof errors_1.TankSyncError) {
|
|
91
|
+
return {
|
|
92
|
+
success: false,
|
|
93
|
+
error: error.code,
|
|
94
|
+
message: error.message,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
success: false,
|
|
99
|
+
error: 'UNKNOWN_ERROR',
|
|
100
|
+
message: String(error),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Get client status
|
|
106
|
+
*/
|
|
107
|
+
getStatus() {
|
|
108
|
+
return {
|
|
109
|
+
isInitialized: this.isInitialized,
|
|
110
|
+
workerStatus: this.worker?.getStatus(),
|
|
111
|
+
config: this.config.toJSON(),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Get cache statistics
|
|
116
|
+
*/
|
|
117
|
+
async getCacheStats() {
|
|
118
|
+
return this.cache.getStats();
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Clear cache (for testing/maintenance)
|
|
122
|
+
*/
|
|
123
|
+
async clearCache() {
|
|
124
|
+
await this.cache.clear();
|
|
125
|
+
this.logger.info('Cache cleared');
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Gracefully shutdown client
|
|
129
|
+
*/
|
|
130
|
+
async close() {
|
|
131
|
+
if (!this.isInitialized) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
try {
|
|
135
|
+
this.logger.info('Closing GamePayloadClient');
|
|
136
|
+
if (this.worker) {
|
|
137
|
+
await this.worker.shutdown();
|
|
138
|
+
}
|
|
139
|
+
this.isInitialized = false;
|
|
140
|
+
this.logger.info('GamePayloadClient closed successfully');
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
this.logger.error('Error during shutdown:', error);
|
|
144
|
+
throw error;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
exports.GamePayloadClient = GamePayloadClient;
|
|
149
|
+
var errors_2 = require("./errors");
|
|
150
|
+
Object.defineProperty(exports, "TankSyncError", { enumerable: true, get: function () { return errors_2.TankSyncError; } });
|
|
151
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TankSync Logger
|
|
3
|
+
*/
|
|
4
|
+
import { LogLevel } from './types';
|
|
5
|
+
export declare class Logger {
|
|
6
|
+
private logLevel;
|
|
7
|
+
private prefix;
|
|
8
|
+
constructor(logLevel?: LogLevel);
|
|
9
|
+
debug(message: string, data?: unknown): void;
|
|
10
|
+
info(message: string, data?: unknown): void;
|
|
11
|
+
warn(message: string, data?: unknown): void;
|
|
12
|
+
error(message: string, error?: Error | unknown): void;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AASnC,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,MAAM,CAAgB;gBAElB,QAAQ,GAAE,QAAiB;IAIvC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;IAM5C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;IAM3C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;IAM3C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,IAAI;CAStD"}
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* TankSync Logger
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Logger = void 0;
|
|
7
|
+
const LOG_LEVELS = {
|
|
8
|
+
debug: 0,
|
|
9
|
+
info: 1,
|
|
10
|
+
warn: 2,
|
|
11
|
+
error: 3,
|
|
12
|
+
};
|
|
13
|
+
class Logger {
|
|
14
|
+
constructor(logLevel = 'info') {
|
|
15
|
+
this.prefix = '[TankSync]';
|
|
16
|
+
this.logLevel = logLevel;
|
|
17
|
+
}
|
|
18
|
+
debug(message, data) {
|
|
19
|
+
if (LOG_LEVELS[this.logLevel] <= LOG_LEVELS.debug) {
|
|
20
|
+
console.log(`${this.prefix} DEBUG:`, message, data || '');
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
info(message, data) {
|
|
24
|
+
if (LOG_LEVELS[this.logLevel] <= LOG_LEVELS.info) {
|
|
25
|
+
console.log(`${this.prefix} INFO:`, message, data || '');
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
warn(message, data) {
|
|
29
|
+
if (LOG_LEVELS[this.logLevel] <= LOG_LEVELS.warn) {
|
|
30
|
+
console.warn(`${this.prefix} WARN:`, message, data || '');
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
error(message, error) {
|
|
34
|
+
if (LOG_LEVELS[this.logLevel] <= LOG_LEVELS.error) {
|
|
35
|
+
if (error instanceof Error) {
|
|
36
|
+
console.error(`${this.prefix} ERROR:`, message, error.message);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
console.error(`${this.prefix} ERROR:`, message, error || '');
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
exports.Logger = Logger;
|
|
45
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAIH,MAAM,UAAU,GAAG;IACjB,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;CACT,CAAC;AAEF,MAAa,MAAM;IAIjB,YAAY,WAAqB,MAAM;QAF/B,WAAM,GAAG,YAAY,CAAC;QAG5B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,IAAc;QACnC,IAAI,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,UAAU,CAAC,KAAK,EAAE,CAAC;YAClD,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,SAAS,EAAE,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,IAAc;QAClC,IAAI,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,UAAU,CAAC,IAAI,EAAE,CAAC;YACjD,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,QAAQ,EAAE,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,IAAc;QAClC,IAAI,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,UAAU,CAAC,IAAI,EAAE,CAAC;YACjD,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,QAAQ,EAAE,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,KAAuB;QAC5C,IAAI,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,UAAU,CAAC,KAAK,EAAE,CAAC;YAClD,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;gBAC3B,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;YACjE,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,SAAS,EAAE,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;YAC/D,CAAC;QACH,CAAC;IACH,CAAC;CACF;AAnCD,wBAmCC"}
|