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.
Files changed (42) hide show
  1. package/README.md +2 -2
  2. package/dist/config.d.ts +26 -0
  3. package/dist/config.d.ts.map +1 -0
  4. package/dist/config.js +102 -0
  5. package/dist/config.js.map +1 -0
  6. package/dist/errors.d.ts +54 -0
  7. package/dist/errors.d.ts.map +1 -0
  8. package/dist/errors.js +143 -0
  9. package/dist/errors.js.map +1 -0
  10. package/dist/index.d.ts +54 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +151 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/logger.d.ts +14 -0
  15. package/dist/logger.d.ts.map +1 -0
  16. package/dist/logger.js +45 -0
  17. package/dist/logger.js.map +1 -0
  18. package/dist/payload-cache.d.ts +49 -0
  19. package/dist/payload-cache.d.ts.map +1 -0
  20. package/dist/payload-cache.js +146 -0
  21. package/dist/payload-cache.js.map +1 -0
  22. package/dist/payload-downloader.d.ts +21 -0
  23. package/dist/payload-downloader.d.ts.map +1 -0
  24. package/dist/payload-downloader.js +103 -0
  25. package/dist/payload-downloader.js.map +1 -0
  26. package/dist/payload-verifier.d.ts +26 -0
  27. package/dist/payload-verifier.d.ts.map +1 -0
  28. package/dist/payload-verifier.js +95 -0
  29. package/dist/payload-verifier.js.map +1 -0
  30. package/dist/payload-worker.d.ts +49 -0
  31. package/dist/payload-worker.d.ts.map +1 -0
  32. package/dist/payload-worker.js +213 -0
  33. package/dist/payload-worker.js.map +1 -0
  34. package/dist/protocol.d.ts +44 -0
  35. package/dist/protocol.d.ts.map +1 -0
  36. package/dist/protocol.js +117 -0
  37. package/dist/protocol.js.map +1 -0
  38. package/dist/types.d.ts +77 -0
  39. package/dist/types.d.ts.map +1 -0
  40. package/dist/types.js +6 -0
  41. package/dist/types.js.map +1 -0
  42. package/package.json +6 -2
@@ -0,0 +1,49 @@
1
+ /**
2
+ * TankSync Payload Cache
3
+ * Manages local payload caching with metadata
4
+ */
5
+ import { Logger } from './logger';
6
+ import { PayloadInfo, PayloadMetadata } from './types';
7
+ export declare class PayloadCache {
8
+ private logger;
9
+ private cacheDir;
10
+ private metadataFileName;
11
+ constructor(logger: Logger, cacheDir: string);
12
+ /**
13
+ * Initialize cache directory
14
+ */
15
+ initialize(): Promise<void>;
16
+ /**
17
+ * Get payload file path
18
+ */
19
+ getPayloadPath(): string;
20
+ /**
21
+ * Get metadata file path
22
+ */
23
+ private getMetadataPath;
24
+ /**
25
+ * Read cached payload info
26
+ */
27
+ getPayloadInfo(): Promise<PayloadInfo | null>;
28
+ /**
29
+ * Check if payload is cached and matches expected version/signature
30
+ */
31
+ isCached(version: string, signature: string): Promise<boolean>;
32
+ /**
33
+ * Save payload metadata after successful download
34
+ */
35
+ saveMetadata(version: string, signature: string, downloadedAt?: number): Promise<void>;
36
+ /**
37
+ * Clear cache
38
+ */
39
+ clear(): Promise<void>;
40
+ /**
41
+ * Get cache statistics
42
+ */
43
+ getStats(): Promise<{
44
+ isCached: boolean;
45
+ payloadSize: number | null;
46
+ metadata: PayloadMetadata | null;
47
+ }>;
48
+ }
49
+ //# sourceMappingURL=payload-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payload-cache.d.ts","sourceRoot":"","sources":["../src/payload-cache.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAGvD,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,gBAAgB,CAA2B;gBAEvC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAK5C;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IASjC;;OAEG;IACH,cAAc,IAAI,MAAM;IAIxB;;OAEG;IACH,OAAO,CAAC,eAAe;IAIvB;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAyBnD;;OAEG;IACG,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IASpE;;OAEG;IACG,YAAY,CAChB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,YAAY,GAAE,MAAmB,GAChC,OAAO,CAAC,IAAI,CAAC;IAoBhB;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAmB5B;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC;QACxB,QAAQ,EAAE,OAAO,CAAC;QAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAC;KAClC,CAAC;CAuBH"}
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ /**
3
+ * TankSync Payload Cache
4
+ * Manages local payload caching with metadata
5
+ */
6
+ var __importDefault = (this && this.__importDefault) || function (mod) {
7
+ return (mod && mod.__esModule) ? mod : { "default": mod };
8
+ };
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.PayloadCache = void 0;
11
+ const path_1 = __importDefault(require("path"));
12
+ const fs_1 = __importDefault(require("fs"));
13
+ const fs_2 = require("fs");
14
+ const errors_1 = require("./errors");
15
+ class PayloadCache {
16
+ constructor(logger, cacheDir) {
17
+ this.metadataFileName = 'payload.metadata.json';
18
+ this.logger = logger;
19
+ this.cacheDir = cacheDir;
20
+ }
21
+ /**
22
+ * Initialize cache directory
23
+ */
24
+ async initialize() {
25
+ try {
26
+ await fs_2.promises.mkdir(this.cacheDir, { recursive: true });
27
+ this.logger.debug('Cache directory initialized:', this.cacheDir);
28
+ }
29
+ catch (error) {
30
+ throw new errors_1.CacheWriteError(`Failed to create cache directory: ${error}`);
31
+ }
32
+ }
33
+ /**
34
+ * Get payload file path
35
+ */
36
+ getPayloadPath() {
37
+ return path_1.default.join(this.cacheDir, 'payload.js');
38
+ }
39
+ /**
40
+ * Get metadata file path
41
+ */
42
+ getMetadataPath() {
43
+ return path_1.default.join(this.cacheDir, this.metadataFileName);
44
+ }
45
+ /**
46
+ * Read cached payload info
47
+ */
48
+ async getPayloadInfo() {
49
+ try {
50
+ const metadataPath = this.getMetadataPath();
51
+ const payloadPath = this.getPayloadPath();
52
+ // Check if files exist
53
+ if (!fs_1.default.existsSync(payloadPath) || !fs_1.default.existsSync(metadataPath)) {
54
+ return null;
55
+ }
56
+ const metadataStr = await fs_2.promises.readFile(metadataPath, 'utf-8');
57
+ const metadata = JSON.parse(metadataStr);
58
+ return {
59
+ path: payloadPath,
60
+ version: metadata.version,
61
+ signature: metadata.signature,
62
+ metadata,
63
+ };
64
+ }
65
+ catch (error) {
66
+ this.logger.warn('Failed to read cached payload info:', error);
67
+ return null;
68
+ }
69
+ }
70
+ /**
71
+ * Check if payload is cached and matches expected version/signature
72
+ */
73
+ async isCached(version, signature) {
74
+ const info = await this.getPayloadInfo();
75
+ if (!info) {
76
+ return false;
77
+ }
78
+ return info.version === version && info.signature === signature;
79
+ }
80
+ /**
81
+ * Save payload metadata after successful download
82
+ */
83
+ async saveMetadata(version, signature, downloadedAt = Date.now()) {
84
+ try {
85
+ await this.initialize(); // Ensure directory exists
86
+ const metadata = {
87
+ version,
88
+ signature,
89
+ downloadedAt,
90
+ verifiedAt: Date.now(),
91
+ };
92
+ const metadataPath = this.getMetadataPath();
93
+ await fs_2.promises.writeFile(metadataPath, JSON.stringify(metadata, null, 2), 'utf-8');
94
+ this.logger.debug('Payload metadata saved:', metadata);
95
+ }
96
+ catch (error) {
97
+ throw new errors_1.CacheWriteError(`Failed to save metadata: ${error}`);
98
+ }
99
+ }
100
+ /**
101
+ * Clear cache
102
+ */
103
+ async clear() {
104
+ try {
105
+ const payloadPath = this.getPayloadPath();
106
+ const metadataPath = this.getMetadataPath();
107
+ if (fs_1.default.existsSync(payloadPath)) {
108
+ await fs_2.promises.unlink(payloadPath);
109
+ }
110
+ if (fs_1.default.existsSync(metadataPath)) {
111
+ await fs_2.promises.unlink(metadataPath);
112
+ }
113
+ this.logger.info('Cache cleared');
114
+ }
115
+ catch (error) {
116
+ throw new errors_1.CacheWriteError(`Failed to clear cache: ${error}`);
117
+ }
118
+ }
119
+ /**
120
+ * Get cache statistics
121
+ */
122
+ async getStats() {
123
+ try {
124
+ const info = await this.getPayloadInfo();
125
+ let payloadSize = null;
126
+ if (info && fs_1.default.existsSync(info.path)) {
127
+ const stats = fs_1.default.statSync(info.path);
128
+ payloadSize = stats.size;
129
+ }
130
+ return {
131
+ isCached: !!info,
132
+ payloadSize,
133
+ metadata: info?.metadata || null,
134
+ };
135
+ }
136
+ catch {
137
+ return {
138
+ isCached: false,
139
+ payloadSize: null,
140
+ metadata: null,
141
+ };
142
+ }
143
+ }
144
+ }
145
+ exports.PayloadCache = PayloadCache;
146
+ //# sourceMappingURL=payload-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payload-cache.js","sourceRoot":"","sources":["../src/payload-cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * TankSync Payload Downloader
3
+ * Downloads payload.js from remote URL with atomic writes
4
+ */
5
+ import { Logger } from './logger';
6
+ export declare class PayloadDownloader {
7
+ private logger;
8
+ private downloadTimeout;
9
+ private maxPayloadSize;
10
+ constructor(logger: Logger, downloadTimeout: number, maxPayloadSize: number);
11
+ /**
12
+ * Download payload from URL with atomic write
13
+ * Uses temporary file to ensure atomic writes
14
+ */
15
+ download(url: string, outputPath: string): Promise<string>;
16
+ /**
17
+ * Download if not already cached
18
+ */
19
+ downloadIfNeeded(url: string, outputPath: string, forceDownload?: boolean): Promise<string>;
20
+ }
21
+ //# sourceMappingURL=payload-downloader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payload-downloader.d.ts","sourceRoot":"","sources":["../src/payload-downloader.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAQlC,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,cAAc,CAAS;gBAEnB,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM;IAM3E;;;OAGG;IACG,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAkFhE;;OAEG;IACG,gBAAgB,CACpB,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,EAClB,aAAa,GAAE,OAAe,GAC7B,OAAO,CAAC,MAAM,CAAC;CAQnB"}
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ /**
3
+ * TankSync Payload Downloader
4
+ * Downloads payload.js from remote URL with atomic writes
5
+ */
6
+ var __importDefault = (this && this.__importDefault) || function (mod) {
7
+ return (mod && mod.__esModule) ? mod : { "default": mod };
8
+ };
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.PayloadDownloader = void 0;
11
+ const https_1 = __importDefault(require("https"));
12
+ const fs_1 = __importDefault(require("fs"));
13
+ const fs_2 = require("fs");
14
+ const errors_1 = require("./errors");
15
+ class PayloadDownloader {
16
+ constructor(logger, downloadTimeout, maxPayloadSize) {
17
+ this.logger = logger;
18
+ this.downloadTimeout = downloadTimeout;
19
+ this.maxPayloadSize = maxPayloadSize;
20
+ }
21
+ /**
22
+ * Download payload from URL with atomic write
23
+ * Uses temporary file to ensure atomic writes
24
+ */
25
+ async download(url, outputPath) {
26
+ this.logger.info('Downloading payload from:', url);
27
+ return new Promise((resolve, reject) => {
28
+ const tempPath = `${outputPath}.tmp`;
29
+ const writeStream = fs_1.default.createWriteStream(tempPath);
30
+ let downloadedSize = 0;
31
+ const request = https_1.default.get(url, { timeout: this.downloadTimeout }, (response) => {
32
+ // Check HTTP status
33
+ if (response.statusCode !== 200) {
34
+ writeStream.destroy();
35
+ fs_1.default.unlink(tempPath, () => { }); // Clean up temp file
36
+ reject(new errors_1.InvalidHttpResponseError(response.statusCode || 0, response.statusMessage || 'Unknown'));
37
+ return;
38
+ }
39
+ // Check Content-Length header
40
+ const contentLength = parseInt(response.headers['content-length'] || '0', 10);
41
+ if (contentLength > this.maxPayloadSize) {
42
+ writeStream.destroy();
43
+ fs_1.default.unlink(tempPath, () => { }); // Clean up temp file
44
+ reject(new errors_1.PayloadTooLargeError(contentLength, this.maxPayloadSize));
45
+ return;
46
+ }
47
+ // Monitor download size
48
+ response.on('data', (chunk) => {
49
+ downloadedSize += chunk.length;
50
+ if (downloadedSize > this.maxPayloadSize) {
51
+ writeStream.destroy();
52
+ request.abort();
53
+ fs_1.default.unlink(tempPath, () => { }); // Clean up temp file
54
+ reject(new errors_1.PayloadTooLargeError(downloadedSize, this.maxPayloadSize));
55
+ }
56
+ });
57
+ response.pipe(writeStream);
58
+ });
59
+ // Handle timeout
60
+ request.on('timeout', () => {
61
+ request.abort();
62
+ writeStream.destroy();
63
+ fs_1.default.unlink(tempPath, () => { }); // Clean up temp file
64
+ reject(new errors_1.PayloadTimeoutError(this.downloadTimeout));
65
+ });
66
+ // Handle errors
67
+ request.on('error', (error) => {
68
+ writeStream.destroy();
69
+ fs_1.default.unlink(tempPath, () => { }); // Clean up temp file
70
+ reject(new errors_1.PayloadDownloadError(error.message));
71
+ });
72
+ writeStream.on('error', (error) => {
73
+ request.abort();
74
+ fs_1.default.unlink(tempPath, () => { }); // Clean up temp file
75
+ reject(new errors_1.PayloadDownloadError(`Write error: ${error.message}`));
76
+ });
77
+ writeStream.on('finish', async () => {
78
+ try {
79
+ // Atomic move: temp file → final location
80
+ await fs_2.promises.rename(tempPath, outputPath);
81
+ this.logger.info('Payload downloaded successfully:', outputPath);
82
+ resolve(outputPath);
83
+ }
84
+ catch (error) {
85
+ fs_1.default.unlink(tempPath, () => { }); // Clean up temp file
86
+ reject(new errors_1.PayloadDownloadError(`Failed to finalize download: ${error}`));
87
+ }
88
+ });
89
+ });
90
+ }
91
+ /**
92
+ * Download if not already cached
93
+ */
94
+ async downloadIfNeeded(url, outputPath, forceDownload = false) {
95
+ if (!forceDownload && fs_1.default.existsSync(outputPath)) {
96
+ this.logger.info('Payload already cached:', outputPath);
97
+ return outputPath;
98
+ }
99
+ return this.download(url, outputPath);
100
+ }
101
+ }
102
+ exports.PayloadDownloader = PayloadDownloader;
103
+ //# sourceMappingURL=payload-downloader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payload-downloader.js","sourceRoot":"","sources":["../src/payload-downloader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * TankSync Payload Verifier
3
+ * Verifies payload integrity using HMAC-SHA256
4
+ */
5
+ import { Logger } from './logger';
6
+ export declare class PayloadVerifier {
7
+ private logger;
8
+ constructor(logger: Logger);
9
+ /**
10
+ * Verify payload signature using HMAC-SHA256
11
+ */
12
+ verifySignature(payloadPath: string, expectedSignature: string): Promise<void>;
13
+ /**
14
+ * Verify payload is valid JavaScript
15
+ */
16
+ verifyFormat(payloadPath: string): Promise<void>;
17
+ /**
18
+ * Calculate HMAC-SHA256 signature of payload
19
+ */
20
+ calculateSignature(payload: string): string;
21
+ /**
22
+ * Constant-time string comparison to prevent timing attacks
23
+ */
24
+ private constantTimeCompare;
25
+ }
26
+ //# sourceMappingURL=payload-verifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payload-verifier.d.ts","sourceRoot":"","sources":["../src/payload-verifier.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAGlC,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,EAAE,MAAM;IAI1B;;OAEG;IACG,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBpF;;OAEG;IACG,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoCtD;;OAEG;IACH,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAO3C;;OAEG;IACH,OAAO,CAAC,mBAAmB;CAY5B"}
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ /**
3
+ * TankSync Payload Verifier
4
+ * Verifies payload integrity using HMAC-SHA256
5
+ */
6
+ var __importDefault = (this && this.__importDefault) || function (mod) {
7
+ return (mod && mod.__esModule) ? mod : { "default": mod };
8
+ };
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.PayloadVerifier = void 0;
11
+ const crypto_1 = __importDefault(require("crypto"));
12
+ const fs_1 = require("fs");
13
+ const errors_1 = require("./errors");
14
+ class PayloadVerifier {
15
+ constructor(logger) {
16
+ this.logger = logger;
17
+ }
18
+ /**
19
+ * Verify payload signature using HMAC-SHA256
20
+ */
21
+ async verifySignature(payloadPath, expectedSignature) {
22
+ this.logger.debug('Verifying payload signature');
23
+ try {
24
+ const payload = await fs_1.promises.readFile(payloadPath, 'utf-8');
25
+ const calculatedSignature = this.calculateSignature(payload);
26
+ if (!this.constantTimeCompare(calculatedSignature, expectedSignature)) {
27
+ throw new errors_1.SignatureVerificationError(`Signature mismatch. Expected ${expectedSignature}, got ${calculatedSignature}`);
28
+ }
29
+ this.logger.info('Payload signature verified successfully');
30
+ }
31
+ catch (error) {
32
+ if (error instanceof errors_1.SignatureVerificationError) {
33
+ throw error;
34
+ }
35
+ throw new errors_1.SignatureVerificationError(`Verification failed: ${error}`);
36
+ }
37
+ }
38
+ /**
39
+ * Verify payload is valid JavaScript
40
+ */
41
+ async verifyFormat(payloadPath) {
42
+ this.logger.debug('Verifying payload format');
43
+ try {
44
+ const payload = await fs_1.promises.readFile(payloadPath, 'utf-8');
45
+ // Basic checks
46
+ if (!payload || payload.trim().length === 0) {
47
+ throw new errors_1.InvalidPayloadFormatError('Payload is empty');
48
+ }
49
+ // Check if it's JavaScript-like (not a binary file)
50
+ if (!payload.startsWith('module.exports') && !payload.startsWith('exports')) {
51
+ // Optional: Could require specific format
52
+ this.logger.warn('Payload does not start with module.exports or exports - this might not be a valid Node.js module');
53
+ }
54
+ // Try to parse as valid JavaScript syntax (basic check)
55
+ try {
56
+ new Function(payload);
57
+ }
58
+ catch {
59
+ // This is okay - just means it's not pure expression
60
+ // As long as it's syntactically valid JS, we're fine
61
+ }
62
+ this.logger.info('Payload format verified');
63
+ }
64
+ catch (error) {
65
+ if (error instanceof errors_1.InvalidPayloadFormatError) {
66
+ throw error;
67
+ }
68
+ throw new errors_1.InvalidPayloadFormatError(`Format verification failed: ${error}`);
69
+ }
70
+ }
71
+ /**
72
+ * Calculate HMAC-SHA256 signature of payload
73
+ */
74
+ calculateSignature(payload) {
75
+ return crypto_1.default
76
+ .createHmac('sha256', 'tanksync-secret-key')
77
+ .update(payload)
78
+ .digest('hex');
79
+ }
80
+ /**
81
+ * Constant-time string comparison to prevent timing attacks
82
+ */
83
+ constantTimeCompare(a, b) {
84
+ if (a.length !== b.length) {
85
+ return false;
86
+ }
87
+ let result = 0;
88
+ for (let i = 0; i < a.length; i++) {
89
+ result |= a.charCodeAt(i) ^ b.charCodeAt(i);
90
+ }
91
+ return result === 0;
92
+ }
93
+ }
94
+ exports.PayloadVerifier = PayloadVerifier;
95
+ //# sourceMappingURL=payload-verifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payload-verifier.js","sourceRoot":"","sources":["../src/payload-verifier.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * TankSync Payload Worker
3
+ * Manages child process lifecycle and IPC communication
4
+ */
5
+ import { Logger } from './logger';
6
+ import { IPCRequest, PurchaseRequest } from './types';
7
+ export declare class PayloadWorker {
8
+ private logger;
9
+ private payloadPath;
10
+ private requestTimeout;
11
+ private process;
12
+ private isReady;
13
+ private pendingRequests;
14
+ private lineBuffer;
15
+ constructor(logger: Logger, payloadPath: string, requestTimeout: number);
16
+ /**
17
+ * Start worker process and wait for ready signal
18
+ */
19
+ start(handshakeTimeout?: number): Promise<void>;
20
+ /**
21
+ * Send purchase request to worker
22
+ */
23
+ purchaseItem(request: PurchaseRequest): Promise<any>;
24
+ /**
25
+ * Send generic request to worker
26
+ */
27
+ sendRequest(request: IPCRequest): Promise<any>;
28
+ /**
29
+ * Setup process event handlers
30
+ */
31
+ private setupProcessHandlers;
32
+ /**
33
+ * Handle message from worker
34
+ */
35
+ private handleMessage;
36
+ /**
37
+ * Gracefully shutdown worker
38
+ */
39
+ shutdown(timeout?: number): Promise<void>;
40
+ /**
41
+ * Check if worker is ready
42
+ */
43
+ getStatus(): {
44
+ isReady: boolean;
45
+ isAlive: boolean;
46
+ pendingRequests: number;
47
+ };
48
+ }
49
+ //# sourceMappingURL=payload-worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payload-worker.d.ts","sourceRoot":"","sources":["../src/payload-worker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,OAAO,EAEL,UAAU,EACV,eAAe,EAEhB,MAAM,SAAS,CAAC;AASjB,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,eAAe,CAAyB;IAChD,OAAO,CAAC,UAAU,CAAM;gBAEZ,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM;IAMvE;;OAEG;IACG,KAAK,CAAC,gBAAgB,GAAE,MAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAgD3D;;OAEG;IACG,YAAY,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC;IAS1D;;OAEG;IACG,WAAW,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC;IA8BpD;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAuD5B;;OAEG;IACH,OAAO,CAAC,aAAa;IAyBrB;;OAEG;IACG,QAAQ,CAAC,OAAO,GAAE,MAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBrD;;OAEG;IACH,SAAS,IAAI;QACX,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,EAAE,OAAO,CAAC;QACjB,eAAe,EAAE,MAAM,CAAC;KACzB;CAOF"}