@thenewlabs/entangle-utils 1.0.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.
Files changed (45) hide show
  1. package/dist/browser.d.ts +4 -0
  2. package/dist/browser.d.ts.map +1 -0
  3. package/dist/browser.js +5 -0
  4. package/dist/browser.js.map +1 -0
  5. package/dist/config.d.ts +24 -0
  6. package/dist/config.d.ts.map +1 -0
  7. package/dist/config.js +36 -0
  8. package/dist/config.js.map +1 -0
  9. package/dist/counters.d.ts +11 -0
  10. package/dist/counters.d.ts.map +1 -0
  11. package/dist/counters.js +20 -0
  12. package/dist/counters.js.map +1 -0
  13. package/dist/counters.test.d.ts +2 -0
  14. package/dist/counters.test.d.ts.map +1 -0
  15. package/dist/counters.test.js +72 -0
  16. package/dist/counters.test.js.map +1 -0
  17. package/dist/index.d.ts +7 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +7 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/logger.d.ts +3 -0
  22. package/dist/logger.d.ts.map +1 -0
  23. package/dist/logger.js +49 -0
  24. package/dist/logger.js.map +1 -0
  25. package/dist/output.d.ts +26 -0
  26. package/dist/output.d.ts.map +1 -0
  27. package/dist/output.js +119 -0
  28. package/dist/output.js.map +1 -0
  29. package/dist/stream-counters.d.ts +31 -0
  30. package/dist/stream-counters.d.ts.map +1 -0
  31. package/dist/stream-counters.js +52 -0
  32. package/dist/stream-counters.js.map +1 -0
  33. package/dist/validation.d.ts +9 -0
  34. package/dist/validation.d.ts.map +1 -0
  35. package/dist/validation.js +79 -0
  36. package/dist/validation.js.map +1 -0
  37. package/dist/validation.test.d.ts +2 -0
  38. package/dist/validation.test.d.ts.map +1 -0
  39. package/dist/validation.test.js +121 -0
  40. package/dist/validation.test.js.map +1 -0
  41. package/dist/version.d.ts +4 -0
  42. package/dist/version.d.ts.map +1 -0
  43. package/dist/version.js +6 -0
  44. package/dist/version.js.map +1 -0
  45. package/package.json +34 -0
@@ -0,0 +1,4 @@
1
+ export * from './validation.js';
2
+ export * from './counters.js';
3
+ export * from './stream-counters.js';
4
+ //# sourceMappingURL=browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AACA,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC"}
@@ -0,0 +1,5 @@
1
+ // Browser-safe exports (no Node.js dependencies)
2
+ export * from './validation.js';
3
+ export * from './counters.js';
4
+ export * from './stream-counters.js';
5
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC"}
@@ -0,0 +1,24 @@
1
+ export declare function loadConfig(): void;
2
+ export interface Config {
3
+ port: number;
4
+ host: string;
5
+ publicOrigin: string;
6
+ maxFrameBytes: number;
7
+ relayIdleTimeoutMs: number;
8
+ agentHeartbeatMs: number;
9
+ cmdDefaultWallMs: number;
10
+ ttyIdleTimeoutMs: number;
11
+ maxOutBytes: number;
12
+ logLevel: string;
13
+ relayRateRps: number;
14
+ relayBurst: number;
15
+ agentShell: string;
16
+ agentDefaultCwd: string;
17
+ agentAllowedCwd: string[] | undefined;
18
+ spawnSandbox: string;
19
+ maxArgCount: number;
20
+ maxArgLen: number;
21
+ relayUrl: string | undefined;
22
+ }
23
+ export declare function getConfig(): Config;
24
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAQA,wBAAgB,UAAU,IAAI,IAAI,CAIjC;AAED,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IACtC,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9B;AAED,wBAAgB,SAAS,IAAI,MAAM,CAwBlC"}
package/dist/config.js ADDED
@@ -0,0 +1,36 @@
1
+ import { config } from 'dotenv';
2
+ import { resolve } from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ import { dirname } from 'path';
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = dirname(__filename);
7
+ export function loadConfig() {
8
+ const rootDir = resolve(__dirname, '../../..');
9
+ const envPath = resolve(rootDir, '.env');
10
+ config({ path: envPath });
11
+ }
12
+ export function getConfig() {
13
+ loadConfig();
14
+ return {
15
+ port: parseInt(process.env.PORT || '8080', 10),
16
+ host: process.env.HOST || '0.0.0.0',
17
+ publicOrigin: process.env.PUBLIC_ORIGIN || 'http://localhost:8080',
18
+ maxFrameBytes: parseInt(process.env.MAX_FRAME_BYTES || '1048576', 10),
19
+ relayIdleTimeoutMs: parseInt(process.env.RELAY_IDLE_TIMEOUT_MS || '120000', 10),
20
+ agentHeartbeatMs: parseInt(process.env.AGENT_HEARTBEAT_MS || '15000', 10),
21
+ cmdDefaultWallMs: parseInt(process.env.CMD_DEFAULT_WALL_MS || '60000', 10),
22
+ ttyIdleTimeoutMs: parseInt(process.env.TTY_IDLE_TIMEOUT_MS || '1200000', 10),
23
+ maxOutBytes: parseInt(process.env.MAX_OUT_BYTES || '10485760', 10),
24
+ logLevel: process.env.LOG_LEVEL || 'info',
25
+ relayRateRps: parseInt(process.env.RELAY_RATE_RPS || '10', 10),
26
+ relayBurst: parseInt(process.env.RELAY_BURST || '50', 10),
27
+ agentShell: process.env.AGENT_SHELL || process.env.SHELL || '/bin/bash',
28
+ agentDefaultCwd: process.env.AGENT_DEFAULT_CWD || process.env.HOME || process.cwd(),
29
+ agentAllowedCwd: process.env.AGENT_ALLOWED_CWD?.split(':').filter(Boolean),
30
+ spawnSandbox: process.env.SPAWN_SANDBOX || 'none',
31
+ maxArgCount: parseInt(process.env.MAX_ARG_COUNT || '256', 10),
32
+ maxArgLen: parseInt(process.env.MAX_ARG_LEN || '16384', 10),
33
+ relayUrl: process.env.RELAY_URL,
34
+ };
35
+ }
36
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAE/B,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,MAAM,UAAU,UAAU;IACxB,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACzC,MAAM,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;AAC5B,CAAC;AAwBD,MAAM,UAAU,SAAS;IACvB,UAAU,EAAE,CAAC;IAEb,OAAO;QACL,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,EAAE,EAAE,CAAC;QAC9C,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,SAAS;QACnC,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,uBAAuB;QAClE,aAAa,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,SAAS,EAAE,EAAE,CAAC;QACrE,kBAAkB,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,QAAQ,EAAE,EAAE,CAAC;QAC/E,gBAAgB,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,OAAO,EAAE,EAAE,CAAC;QACzE,gBAAgB,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,OAAO,EAAE,EAAE,CAAC;QAC1E,gBAAgB,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,SAAS,EAAE,EAAE,CAAC;QAC5E,WAAW,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,UAAU,EAAE,EAAE,CAAC;QAClE,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,MAAM;QACzC,YAAY,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,IAAI,EAAE,EAAE,CAAC;QAC9D,UAAU,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,IAAI,EAAE,EAAE,CAAC;QACzD,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,WAAW;QACvE,eAAe,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE;QACnF,eAAe,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC;QAC1E,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,MAAM;QACjD,WAAW,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,KAAK,EAAE,EAAE,CAAC;QAC7D,SAAS,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,OAAO,EAAE,EAAE,CAAC;QAC3D,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS;KAChC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,11 @@
1
+ export declare class MonotonicCounter {
2
+ private lastSeen;
3
+ validate(ctr: number): void;
4
+ next(): number;
5
+ current(): number;
6
+ }
7
+ export declare class BidirectionalCounters {
8
+ readonly incoming: MonotonicCounter;
9
+ readonly outgoing: MonotonicCounter;
10
+ }
11
+ //# sourceMappingURL=counters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"counters.d.ts","sourceRoot":"","sources":["../src/counters.ts"],"names":[],"mappings":"AAAA,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAc;IAE9B,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAO3B,IAAI,IAAI,MAAM;IAId,OAAO,IAAI,MAAM;CAGlB;AAED,qBAAa,qBAAqB;IAChC,QAAQ,CAAC,QAAQ,mBAA0B;IAC3C,QAAQ,CAAC,QAAQ,mBAA0B;CAC5C"}
@@ -0,0 +1,20 @@
1
+ export class MonotonicCounter {
2
+ lastSeen = -1;
3
+ validate(ctr) {
4
+ if (ctr <= this.lastSeen) {
5
+ throw new Error(`Counter not strictly increasing: ${ctr} <= ${this.lastSeen}`);
6
+ }
7
+ this.lastSeen = ctr;
8
+ }
9
+ next() {
10
+ return ++this.lastSeen;
11
+ }
12
+ current() {
13
+ return this.lastSeen;
14
+ }
15
+ }
16
+ export class BidirectionalCounters {
17
+ incoming = new MonotonicCounter();
18
+ outgoing = new MonotonicCounter();
19
+ }
20
+ //# sourceMappingURL=counters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"counters.js","sourceRoot":"","sources":["../src/counters.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,gBAAgB;IACnB,QAAQ,GAAW,CAAC,CAAC,CAAC;IAE9B,QAAQ,CAAC,GAAW;QAClB,IAAI,GAAG,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,oCAAoC,GAAG,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QACjF,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,GAAG,CAAC;IACtB,CAAC;IAED,IAAI;QACF,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC;IACzB,CAAC;IAED,OAAO;QACL,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;CACF;AAED,MAAM,OAAO,qBAAqB;IACvB,QAAQ,GAAG,IAAI,gBAAgB,EAAE,CAAC;IAClC,QAAQ,GAAG,IAAI,gBAAgB,EAAE,CAAC;CAC5C"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=counters.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"counters.test.d.ts","sourceRoot":"","sources":["../src/counters.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,72 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { MonotonicCounter, BidirectionalCounters } from './counters.js';
3
+ describe('Counters', () => {
4
+ describe('MonotonicCounter', () => {
5
+ it('should start at -1', () => {
6
+ const counter = new MonotonicCounter();
7
+ expect(counter.current()).toBe(-1);
8
+ });
9
+ it('should increment with next()', () => {
10
+ const counter = new MonotonicCounter();
11
+ expect(counter.next()).toBe(0);
12
+ expect(counter.next()).toBe(1);
13
+ expect(counter.next()).toBe(2);
14
+ expect(counter.current()).toBe(2);
15
+ });
16
+ it('should validate strictly increasing values', () => {
17
+ const counter = new MonotonicCounter();
18
+ expect(() => counter.validate(0)).not.toThrow();
19
+ expect(() => counter.validate(1)).not.toThrow();
20
+ expect(() => counter.validate(2)).not.toThrow();
21
+ });
22
+ it('should reject non-increasing values', () => {
23
+ const counter = new MonotonicCounter();
24
+ counter.validate(5);
25
+ expect(() => counter.validate(5))
26
+ .toThrow('Counter not strictly increasing: 5 <= 5');
27
+ expect(() => counter.validate(4))
28
+ .toThrow('Counter not strictly increasing: 4 <= 5');
29
+ });
30
+ it('should reject zero after positive value', () => {
31
+ const counter = new MonotonicCounter();
32
+ counter.validate(10);
33
+ expect(() => counter.validate(0))
34
+ .toThrow('Counter not strictly increasing: 0 <= 10');
35
+ });
36
+ it('should handle large values', () => {
37
+ const counter = new MonotonicCounter();
38
+ counter.validate(1000000);
39
+ expect(() => counter.validate(1000001)).not.toThrow();
40
+ expect(counter.current()).toBe(1000001);
41
+ });
42
+ });
43
+ describe('BidirectionalCounters', () => {
44
+ it('should maintain separate incoming and outgoing counters', () => {
45
+ const counters = new BidirectionalCounters();
46
+ expect(counters.incoming.current()).toBe(-1);
47
+ expect(counters.outgoing.current()).toBe(-1);
48
+ });
49
+ it('should increment counters independently', () => {
50
+ const counters = new BidirectionalCounters();
51
+ expect(counters.incoming.next()).toBe(0);
52
+ expect(counters.incoming.next()).toBe(1);
53
+ expect(counters.outgoing.next()).toBe(0);
54
+ expect(counters.outgoing.next()).toBe(1);
55
+ expect(counters.outgoing.next()).toBe(2);
56
+ expect(counters.incoming.current()).toBe(1);
57
+ expect(counters.outgoing.current()).toBe(2);
58
+ });
59
+ it('should validate counters independently', () => {
60
+ const counters = new BidirectionalCounters();
61
+ counters.incoming.validate(5);
62
+ counters.outgoing.validate(10);
63
+ expect(() => counters.incoming.validate(6)).not.toThrow();
64
+ expect(() => counters.outgoing.validate(11)).not.toThrow();
65
+ expect(() => counters.incoming.validate(5))
66
+ .toThrow('Counter not strictly increasing: 5 <= 6');
67
+ expect(() => counters.outgoing.validate(10))
68
+ .toThrow('Counter not strictly increasing: 10 <= 11');
69
+ });
70
+ });
71
+ });
72
+ //# sourceMappingURL=counters.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"counters.test.js","sourceRoot":"","sources":["../src/counters.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export * from './config.js';
2
+ export * from './validation.js';
3
+ export * from './counters.js';
4
+ export * from './stream-counters.js';
5
+ export * from './version.js';
6
+ export * from './output.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ export * from './config.js';
2
+ export * from './validation.js';
3
+ export * from './counters.js';
4
+ export * from './stream-counters.js';
5
+ export * from './version.js';
6
+ export * from './output.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC"}
@@ -0,0 +1,3 @@
1
+ import pino from 'pino';
2
+ export declare function createLogger(name: string, outputMode?: string): pino.Logger;
3
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAQxB,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC,MAAM,CAmD3E"}
package/dist/logger.js ADDED
@@ -0,0 +1,49 @@
1
+ import pino from 'pino';
2
+ import { Writable } from 'stream';
3
+ import { OutputHandler, parseOutputMode } from './output.js';
4
+ export function createLogger(name, outputMode) {
5
+ const level = process.env.LOG_LEVEL || 'info';
6
+ const mode = parseOutputMode(outputMode || process.env.OUTPUT_MODE);
7
+ const outputHandler = new OutputHandler({ mode });
8
+ // Create a custom writable stream that routes Pino logs through OutputHandler
9
+ const destination = new Writable({
10
+ write(chunk, _encoding, callback) {
11
+ try {
12
+ const str = typeof chunk === 'string' ? chunk : chunk.toString();
13
+ const obj = JSON.parse(str);
14
+ const { level: lvl, msg, ...data } = obj;
15
+ // Convert pino numeric level to name; if already a string, keep it
16
+ const levelName = typeof lvl === 'number'
17
+ ? (pino.levels.labels[lvl] || 'info')
18
+ : (typeof lvl === 'string' ? lvl : 'info');
19
+ // Remove boilerplate fields
20
+ if (data.name === name)
21
+ delete data.name;
22
+ delete data.time;
23
+ delete data.pid;
24
+ delete data.hostname;
25
+ const hasData = Object.keys(data).length > 0;
26
+ outputHandler.log(levelName, msg, hasData ? data : undefined);
27
+ }
28
+ catch (_err) {
29
+ // Fallback for non-JSON chunk
30
+ const str = typeof chunk === 'string' ? chunk : chunk.toString();
31
+ outputHandler.write(str);
32
+ }
33
+ finally {
34
+ callback();
35
+ }
36
+ }
37
+ });
38
+ const logger = pino({
39
+ name,
40
+ level,
41
+ formatters: {
42
+ level: (label) => ({ level: label }),
43
+ },
44
+ }, destination);
45
+ // Attach outputHandler for direct access if needed
46
+ logger.outputHandler = outputHandler;
47
+ return logger;
48
+ }
49
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAM7D,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,UAAmB;IAC5D,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,MAAM,CAAC;IAC9C,MAAM,IAAI,GAAG,eAAe,CAAC,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACpE,MAAM,aAAa,GAAG,IAAI,aAAa,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IAElD,8EAA8E;IAC9E,MAAM,WAAW,GAAG,IAAI,QAAQ,CAAC;QAC/B,KAAK,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ;YAC9B,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACjE,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAC5B,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,GAAG,GAAU,CAAC;gBAEhD,mEAAmE;gBACnE,MAAM,SAAS,GAAG,OAAO,GAAG,KAAK,QAAQ;oBACvC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAsC,CAAC,IAAI,MAAM,CAAC;oBACxE,CAAC,CAAC,CAAC,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAE,GAAc,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;gBAEzD,4BAA4B;gBAC5B,IAAK,IAAY,CAAC,IAAI,KAAK,IAAI;oBAAE,OAAQ,IAAY,CAAC,IAAI,CAAC;gBAC3D,OAAQ,IAAY,CAAC,IAAI,CAAC;gBAC1B,OAAQ,IAAY,CAAC,GAAG,CAAC;gBACzB,OAAQ,IAAY,CAAC,QAAQ,CAAC;gBAE9B,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;gBAC7C,aAAa,CAAC,GAAG,CAAC,SAAS,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YAChE,CAAC;YAAC,OAAO,IAAI,EAAE,CAAC;gBACd,8BAA8B;gBAC9B,MAAM,GAAG,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACjE,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC3B,CAAC;oBAAS,CAAC;gBACT,QAAQ,EAAE,CAAC;YACb,CAAC;QACH,CAAC;KACF,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,IAAI,CACjB;QACE,IAAI;QACJ,KAAK;QACL,UAAU,EAAE;YACV,KAAK,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;SAC7C;KACF,EACD,WAAgD,CAC7B,CAAC;IAEtB,mDAAmD;IACnD,MAAM,CAAC,aAAa,GAAG,aAAa,CAAC;IAErC,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,26 @@
1
+ export declare enum OutputMode {
2
+ TEXT = "text",
3
+ STREAM_JSON = "stream-json"
4
+ }
5
+ export interface OutputOptions {
6
+ mode: OutputMode;
7
+ timestamp?: boolean;
8
+ }
9
+ export declare class OutputHandler {
10
+ private mode;
11
+ private timestamp;
12
+ constructor(options?: OutputOptions);
13
+ log(level: string, message: string, data?: any): void;
14
+ info(message: string, data?: any): void;
15
+ error(message: string, data?: any): void;
16
+ debug(message: string, data?: any): void;
17
+ warn(message: string, data?: any): void;
18
+ text(message: string, data?: any): void;
19
+ write(data: string | Buffer): void;
20
+ version(name: string, version: string): void;
21
+ private textOutput;
22
+ private formatLevel;
23
+ private jsonOutput;
24
+ }
25
+ export declare function parseOutputMode(mode: string | undefined): OutputMode;
26
+ //# sourceMappingURL=output.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAAA,oBAAY,UAAU;IACpB,IAAI,SAAS;IACb,WAAW,gBAAgB;CAC5B;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,UAAU,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,SAAS,CAAU;gBAEf,OAAO,GAAE,aAAyC;IAK9D,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI;IAcrD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI;IAIvC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI;IAIxC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI;IAIxC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI;IAIvC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI;IAKvC,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAclC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAc5C,OAAO,CAAC,UAAU;IAalB,OAAO,CAAC,WAAW;IAwBnB,OAAO,CAAC,UAAU;CAUnB;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,CASpE"}
package/dist/output.js ADDED
@@ -0,0 +1,119 @@
1
+ export var OutputMode;
2
+ (function (OutputMode) {
3
+ OutputMode["TEXT"] = "text";
4
+ OutputMode["STREAM_JSON"] = "stream-json";
5
+ })(OutputMode || (OutputMode = {}));
6
+ export class OutputHandler {
7
+ mode;
8
+ timestamp;
9
+ constructor(options = { mode: OutputMode.TEXT }) {
10
+ this.mode = options.mode;
11
+ this.timestamp = options.timestamp ?? false;
12
+ }
13
+ log(level, message, data) {
14
+ const timestamp = this.timestamp ? new Date().toISOString() : undefined;
15
+ switch (this.mode) {
16
+ case OutputMode.TEXT:
17
+ this.textOutput(level, message, data);
18
+ break;
19
+ case OutputMode.STREAM_JSON:
20
+ this.jsonOutput(level, message, data, timestamp);
21
+ break;
22
+ }
23
+ }
24
+ info(message, data) {
25
+ this.log('info', message, data);
26
+ }
27
+ error(message, data) {
28
+ this.log('error', message, data);
29
+ }
30
+ debug(message, data) {
31
+ this.log('debug', message, data);
32
+ }
33
+ warn(message, data) {
34
+ this.log('warn', message, data);
35
+ }
36
+ text(message, data) {
37
+ this.log('text', message, data);
38
+ }
39
+ // Direct output for things like command output
40
+ write(data) {
41
+ if (this.mode === OutputMode.TEXT) {
42
+ process.stdout.write(data);
43
+ }
44
+ else {
45
+ const output = {
46
+ type: 'output',
47
+ data: data.toString(),
48
+ timestamp: this.timestamp ? new Date().toISOString() : undefined,
49
+ };
50
+ console.log(JSON.stringify(output));
51
+ }
52
+ }
53
+ // Version output
54
+ version(name, version) {
55
+ if (this.mode === OutputMode.TEXT) {
56
+ console.log(`${name} ${version}`);
57
+ }
58
+ else {
59
+ const output = {
60
+ type: 'version',
61
+ name,
62
+ version,
63
+ timestamp: this.timestamp ? new Date().toISOString() : undefined,
64
+ };
65
+ console.log(JSON.stringify(output));
66
+ }
67
+ }
68
+ textOutput(level, message, data) {
69
+ // Format level with consistent width and color codes (if terminal supports)
70
+ const levelFormatted = this.formatLevel(level);
71
+ const levelAndMessage = [levelFormatted, message].filter(x => x).join(' ');
72
+ if (data && Object.keys(data).length > 0) {
73
+ console.log(`${levelAndMessage}`, data);
74
+ }
75
+ else {
76
+ console.log(`${levelAndMessage}`);
77
+ }
78
+ }
79
+ formatLevel(level) {
80
+ // Add color codes if we're in a TTY
81
+ const isTTY = process.stdout.isTTY;
82
+ const colors = {
83
+ error: '\x1b[31m', // Red
84
+ warn: '\x1b[33m', // Yellow
85
+ info: '\x1b[36m', // Cyan
86
+ debug: '\x1b[90m', // Gray
87
+ reset: '\x1b[0m'
88
+ };
89
+ const levelUpper = level.toLowerCase();
90
+ if (isTTY && colors[level]) {
91
+ return `${colors[level]}[${levelUpper}]${colors.reset}`;
92
+ }
93
+ if (level === 'text') {
94
+ return '';
95
+ }
96
+ return `[${levelUpper}]`;
97
+ }
98
+ jsonOutput(level, message, data, timestamp) {
99
+ const output = {
100
+ type: 'log',
101
+ level,
102
+ message,
103
+ ...(data && { data }),
104
+ ...(timestamp && { timestamp }),
105
+ };
106
+ console.log(JSON.stringify(output));
107
+ }
108
+ }
109
+ export function parseOutputMode(mode) {
110
+ switch (mode?.toLowerCase()) {
111
+ case 'stream-json':
112
+ case 'json':
113
+ return OutputMode.STREAM_JSON;
114
+ case 'text':
115
+ default:
116
+ return OutputMode.TEXT;
117
+ }
118
+ }
119
+ //# sourceMappingURL=output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Per-stream counter management for multi-stream protocol
3
+ */
4
+ export declare class StreamCounters {
5
+ private streamCounters;
6
+ /**
7
+ * Get counter for a stream, creating if needed
8
+ */
9
+ private getStreamCounter;
10
+ /**
11
+ * Get next expected counter value
12
+ */
13
+ getNext(sid: string, direction: 'incoming' | 'outgoing'): number;
14
+ /**
15
+ * Increment counter after successful validation
16
+ */
17
+ increment(sid: string, direction: 'incoming' | 'outgoing'): number;
18
+ /**
19
+ * Remove counters for a stream
20
+ */
21
+ removeStream(sid: string): void;
22
+ /**
23
+ * Get all stream IDs
24
+ */
25
+ getStreamIds(): string[];
26
+ /**
27
+ * Clear all counters
28
+ */
29
+ clear(): void;
30
+ }
31
+ //# sourceMappingURL=stream-counters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream-counters.d.ts","sourceRoot":"","sources":["../src/stream-counters.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,cAAc,CAA6D;IAEnF;;OAEG;IACH,OAAO,CAAC,gBAAgB;IASxB;;OAEG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,GAAG,UAAU,GAAG,MAAM;IAKhE;;OAEG;IACH,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,GAAG,UAAU,GAAG,MAAM;IAOlE;;OAEG;IACH,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAI/B;;OAEG;IACH,YAAY,IAAI,MAAM,EAAE;IAIxB;;OAEG;IACH,KAAK,IAAI,IAAI;CAGd"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Per-stream counter management for multi-stream protocol
3
+ */
4
+ export class StreamCounters {
5
+ streamCounters = new Map();
6
+ /**
7
+ * Get counter for a stream, creating if needed
8
+ */
9
+ getStreamCounter(sid) {
10
+ let counter = this.streamCounters.get(sid);
11
+ if (!counter) {
12
+ counter = { incoming: 0, outgoing: 0 };
13
+ this.streamCounters.set(sid, counter);
14
+ }
15
+ return counter;
16
+ }
17
+ /**
18
+ * Get next expected counter value
19
+ */
20
+ getNext(sid, direction) {
21
+ const counter = this.getStreamCounter(sid);
22
+ return counter[direction];
23
+ }
24
+ /**
25
+ * Increment counter after successful validation
26
+ */
27
+ increment(sid, direction) {
28
+ const counter = this.getStreamCounter(sid);
29
+ const value = counter[direction];
30
+ counter[direction]++;
31
+ return value;
32
+ }
33
+ /**
34
+ * Remove counters for a stream
35
+ */
36
+ removeStream(sid) {
37
+ this.streamCounters.delete(sid);
38
+ }
39
+ /**
40
+ * Get all stream IDs
41
+ */
42
+ getStreamIds() {
43
+ return Array.from(this.streamCounters.keys());
44
+ }
45
+ /**
46
+ * Clear all counters
47
+ */
48
+ clear() {
49
+ this.streamCounters.clear();
50
+ }
51
+ }
52
+ //# sourceMappingURL=stream-counters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream-counters.js","sourceRoot":"","sources":["../src/stream-counters.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,OAAO,cAAc;IACjB,cAAc,GAAG,IAAI,GAAG,EAAkD,CAAC;IAEnF;;OAEG;IACK,gBAAgB,CAAC,GAAW;QAClC,IAAI,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC3C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;YACvC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QACxC,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,GAAW,EAAE,SAAkC;QACrD,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC;QAC3C,OAAO,OAAO,CAAC,SAAS,CAAC,CAAC;IAC5B,CAAC;IAED;;OAEG;IACH,SAAS,CAAC,GAAW,EAAE,SAAkC;QACvD,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC;QAC3C,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;QACjC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QACrB,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,GAAW;QACtB,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAClC,CAAC;IAED;;OAEG;IACH,YAAY;QACV,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC;IAC9B,CAAC;CACF"}
@@ -0,0 +1,9 @@
1
+ export declare function validateArguments(argv: string[], maxCount: number, maxLen: number): void;
2
+ export declare function validateCwd(cwd: string, allowedPrefixes?: string[]): void;
3
+ export declare function validateLimits(limits?: {
4
+ cpuMs?: number;
5
+ memMB?: number;
6
+ wallMs?: number;
7
+ maxOutBytes?: number;
8
+ }): void;
9
+ //# sourceMappingURL=validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAEA,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAsBxF;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAqBzE;AA4BD,wBAAgB,cAAc,CAAC,MAAM,CAAC,EAAE;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,IAAI,CAkBP"}
@@ -0,0 +1,79 @@
1
+ import { DEFAULT_LIMITS } from '@thenewlabs/entangle-protocol';
2
+ export function validateArguments(argv, maxCount, maxLen) {
3
+ if (argv.length > maxCount) {
4
+ throw new Error(`Too many arguments: ${argv.length} > ${maxCount}`);
5
+ }
6
+ for (const arg of argv) {
7
+ if (arg.length > maxLen) {
8
+ throw new Error(`Argument too long: ${arg.length} > ${maxLen}`);
9
+ }
10
+ if (arg.includes('\0')) {
11
+ throw new Error('Arguments cannot contain NUL bytes');
12
+ }
13
+ for (let i = 0; i < arg.length; i++) {
14
+ const code = arg.charCodeAt(i);
15
+ if ((code >= 0xD800 && code <= 0xDBFF) && (i + 1 >= arg.length ||
16
+ arg.charCodeAt(i + 1) < 0xDC00 || arg.charCodeAt(i + 1) > 0xDFFF)) {
17
+ throw new Error('Arguments cannot contain unpaired surrogates');
18
+ }
19
+ }
20
+ }
21
+ }
22
+ export function validateCwd(cwd, allowedPrefixes) {
23
+ if (!allowedPrefixes || allowedPrefixes.length === 0) {
24
+ return;
25
+ }
26
+ // Normalize path separators
27
+ const normalized = cwd.replace(/\\/g, '/');
28
+ // Resolve relative path components like '../' to prevent traversal
29
+ const resolved = resolvePath(normalized);
30
+ const allowed = allowedPrefixes.some(prefix => {
31
+ const normalizedPrefix = prefix.replace(/\\/g, '/');
32
+ // Remove trailing slash from prefix for consistent comparison
33
+ const cleanPrefix = normalizedPrefix.endsWith('/') ? normalizedPrefix.slice(0, -1) : normalizedPrefix;
34
+ return resolved.startsWith(cleanPrefix + '/') || resolved === cleanPrefix;
35
+ });
36
+ if (!allowed) {
37
+ throw new Error(`CWD not in allowed directories: ${cwd}`);
38
+ }
39
+ }
40
+ // Simple path resolution to handle '..' and '.' components
41
+ function resolvePath(path) {
42
+ if (!path.startsWith('/')) {
43
+ // Convert relative paths to absolute by prefixing with '/'
44
+ path = '/' + path;
45
+ }
46
+ const parts = path.split('/').filter(Boolean);
47
+ const resolved = [];
48
+ for (const part of parts) {
49
+ if (part === '..') {
50
+ // Go up one directory (remove last component)
51
+ if (resolved.length > 0) {
52
+ resolved.pop();
53
+ }
54
+ // If we're already at root, ignore additional '..'
55
+ }
56
+ else if (part !== '.') {
57
+ // Add normal directory component (ignore '.')
58
+ resolved.push(part);
59
+ }
60
+ }
61
+ return '/' + resolved.join('/');
62
+ }
63
+ export function validateLimits(limits) {
64
+ if (!limits)
65
+ return;
66
+ if (limits.cpuMs !== undefined && (limits.cpuMs <= 0 || limits.cpuMs > DEFAULT_LIMITS.MAX_CPU_MS)) {
67
+ throw new Error(`Invalid CPU limit: ${limits.cpuMs}`);
68
+ }
69
+ if (limits.memMB !== undefined && (limits.memMB <= 0 || limits.memMB > DEFAULT_LIMITS.MAX_MEM_MB)) {
70
+ throw new Error(`Invalid memory limit: ${limits.memMB}`);
71
+ }
72
+ if (limits.wallMs !== undefined && (limits.wallMs <= 0 || limits.wallMs > DEFAULT_LIMITS.MAX_WALL_MS)) {
73
+ throw new Error(`Invalid wall time limit: ${limits.wallMs}`);
74
+ }
75
+ if (limits.maxOutBytes !== undefined && (limits.maxOutBytes <= 0 || limits.maxOutBytes > DEFAULT_LIMITS.MAX_OUT_BYTES)) {
76
+ throw new Error(`Invalid output limit: ${limits.maxOutBytes}`);
77
+ }
78
+ }
79
+ //# sourceMappingURL=validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAE/D,MAAM,UAAU,iBAAiB,CAAC,IAAc,EAAE,QAAgB,EAAE,MAAc;IAChF,IAAI,IAAI,CAAC,MAAM,GAAG,QAAQ,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,uBAAuB,IAAI,CAAC,MAAM,MAAM,QAAQ,EAAE,CAAC,CAAC;IACtE,CAAC;IAED,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,GAAG,CAAC,MAAM,GAAG,MAAM,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,sBAAsB,GAAG,CAAC,MAAM,MAAM,MAAM,EAAE,CAAC,CAAC;QAClE,CAAC;QAED,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QACxD,CAAC;QAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACpC,MAAM,IAAI,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YAC/B,IAAI,CAAC,IAAI,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,MAAM;gBAC1D,GAAG,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC;gBACtE,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;YAClE,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAAW,EAAE,eAA0B;IACjE,IAAI,CAAC,eAAe,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrD,OAAO;IACT,CAAC;IAED,4BAA4B;IAC5B,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAE3C,mEAAmE;IACnE,MAAM,QAAQ,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;IAEzC,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;QAC5C,MAAM,gBAAgB,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACpD,8DAA8D;QAC9D,MAAM,WAAW,GAAG,gBAAgB,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC;QACtG,OAAO,QAAQ,CAAC,UAAU,CAAC,WAAW,GAAG,GAAG,CAAC,IAAI,QAAQ,KAAK,WAAW,CAAC;IAC5E,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,mCAAmC,GAAG,EAAE,CAAC,CAAC;IAC5D,CAAC;AACH,CAAC;AAED,2DAA2D;AAC3D,SAAS,WAAW,CAAC,IAAY;IAC/B,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1B,2DAA2D;QAC3D,IAAI,GAAG,GAAG,GAAG,IAAI,CAAC;IACpB,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC9C,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAClB,8CAA8C;YAC9C,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACxB,QAAQ,CAAC,GAAG,EAAE,CAAC;YACjB,CAAC;YACD,mDAAmD;QACrD,CAAC;aAAM,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACxB,8CAA8C;YAC9C,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IAED,OAAO,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAK9B;IACC,IAAI,CAAC,MAAM;QAAE,OAAO;IAEpB,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,IAAI,MAAM,CAAC,KAAK,GAAG,cAAc,CAAC,UAAU,CAAC,EAAE,CAAC;QAClG,MAAM,IAAI,KAAK,CAAC,sBAAsB,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,IAAI,MAAM,CAAC,KAAK,GAAG,cAAc,CAAC,UAAU,CAAC,EAAE,CAAC;QAClG,MAAM,IAAI,KAAK,CAAC,yBAAyB,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,cAAc,CAAC,WAAW,CAAC,EAAE,CAAC;QACtG,MAAM,IAAI,KAAK,CAAC,4BAA4B,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,IAAI,MAAM,CAAC,WAAW,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,WAAW,IAAI,CAAC,IAAI,MAAM,CAAC,WAAW,GAAG,cAAc,CAAC,aAAa,CAAC,EAAE,CAAC;QACvH,MAAM,IAAI,KAAK,CAAC,yBAAyB,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;IACjE,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=validation.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.test.d.ts","sourceRoot":"","sources":["../src/validation.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,121 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { validateArguments, validateCwd, validateLimits } from './validation.js';
3
+ describe('Validation Utils', () => {
4
+ describe('validateArguments', () => {
5
+ it('should accept valid arguments', () => {
6
+ const argv = ['--help', 'test', 'file.txt'];
7
+ expect(() => validateArguments(argv, 10, 100)).not.toThrow();
8
+ });
9
+ it('should reject too many arguments', () => {
10
+ const argv = new Array(10).fill('arg');
11
+ expect(() => validateArguments(argv, 5, 100))
12
+ .toThrow('Too many arguments: 10 > 5');
13
+ });
14
+ it('should reject arguments that are too long', () => {
15
+ const argv = ['x'.repeat(101)];
16
+ expect(() => validateArguments(argv, 10, 100))
17
+ .toThrow('Argument too long: 101 > 100');
18
+ });
19
+ it('should reject arguments with NUL bytes', () => {
20
+ const argv = ['test\0arg'];
21
+ expect(() => validateArguments(argv, 10, 100))
22
+ .toThrow('Arguments cannot contain NUL bytes');
23
+ });
24
+ it('should reject arguments with unpaired surrogates', () => {
25
+ const argv = ['test\uD800'];
26
+ expect(() => validateArguments(argv, 10, 100))
27
+ .toThrow('Arguments cannot contain unpaired surrogates');
28
+ });
29
+ it('should accept empty arguments array', () => {
30
+ expect(() => validateArguments([], 10, 100)).not.toThrow();
31
+ });
32
+ it('should accept arguments with paired surrogates', () => {
33
+ const argv = ['test\uD800\uDC00']; // Valid surrogate pair
34
+ expect(() => validateArguments(argv, 10, 100)).not.toThrow();
35
+ });
36
+ });
37
+ describe('validateCwd', () => {
38
+ it('should accept any cwd when no prefixes specified', () => {
39
+ expect(() => validateCwd('/any/path')).not.toThrow();
40
+ expect(() => validateCwd('/etc/passwd')).not.toThrow();
41
+ });
42
+ it('should accept cwd with empty prefixes array', () => {
43
+ expect(() => validateCwd('/any/path', [])).not.toThrow();
44
+ });
45
+ it('should accept cwd matching allowed prefix', () => {
46
+ const prefixes = ['/home', '/srv'];
47
+ expect(() => validateCwd('/home/user/project', prefixes)).not.toThrow();
48
+ expect(() => validateCwd('/srv/app', prefixes)).not.toThrow();
49
+ });
50
+ it('should reject cwd not matching any prefix', () => {
51
+ const prefixes = ['/home', '/srv'];
52
+ expect(() => validateCwd('/etc/passwd', prefixes))
53
+ .toThrow('CWD not in allowed directories: /etc/passwd');
54
+ });
55
+ it('should normalize Windows paths', () => {
56
+ const prefixes = ['/home'];
57
+ expect(() => validateCwd('\\home\\user', prefixes)).not.toThrow();
58
+ });
59
+ it('should handle trailing slashes', () => {
60
+ const prefixes = ['/home/'];
61
+ expect(() => validateCwd('/home/user', prefixes)).not.toThrow();
62
+ });
63
+ });
64
+ describe('validateLimits', () => {
65
+ it('should accept undefined limits', () => {
66
+ expect(() => validateLimits()).not.toThrow();
67
+ });
68
+ it('should accept valid limits', () => {
69
+ const limits = {
70
+ cpuMs: 1000,
71
+ memMB: 256,
72
+ wallMs: 5000,
73
+ maxOutBytes: 1024,
74
+ };
75
+ expect(() => validateLimits(limits)).not.toThrow();
76
+ });
77
+ it('should reject zero CPU limit', () => {
78
+ expect(() => validateLimits({ cpuMs: 0 }))
79
+ .toThrow('Invalid CPU limit: 0');
80
+ });
81
+ it('should reject negative CPU limit', () => {
82
+ expect(() => validateLimits({ cpuMs: -1 }))
83
+ .toThrow('Invalid CPU limit: -1');
84
+ });
85
+ it('should reject CPU limit exceeding max', () => {
86
+ expect(() => validateLimits({ cpuMs: 100000 }))
87
+ .toThrow('Invalid CPU limit: 100000');
88
+ });
89
+ it('should reject zero memory limit', () => {
90
+ expect(() => validateLimits({ memMB: 0 }))
91
+ .toThrow('Invalid memory limit: 0');
92
+ });
93
+ it('should reject memory limit exceeding max', () => {
94
+ expect(() => validateLimits({ memMB: 1024 }))
95
+ .toThrow('Invalid memory limit: 1024');
96
+ });
97
+ it('should reject zero wall time limit', () => {
98
+ expect(() => validateLimits({ wallMs: 0 }))
99
+ .toThrow('Invalid wall time limit: 0');
100
+ });
101
+ it('should reject wall time limit exceeding max', () => {
102
+ expect(() => validateLimits({ wallMs: 400000 }))
103
+ .toThrow('Invalid wall time limit: 400000');
104
+ });
105
+ it('should reject zero output limit', () => {
106
+ expect(() => validateLimits({ maxOutBytes: 0 }))
107
+ .toThrow('Invalid output limit: 0');
108
+ });
109
+ it('should reject output limit exceeding max', () => {
110
+ expect(() => validateLimits({ maxOutBytes: 20000000 }))
111
+ .toThrow('Invalid output limit: 20000000');
112
+ });
113
+ it('should accept partial limits', () => {
114
+ expect(() => validateLimits({ cpuMs: 1000 })).not.toThrow();
115
+ expect(() => validateLimits({ memMB: 256 })).not.toThrow();
116
+ expect(() => validateLimits({ wallMs: 5000 })).not.toThrow();
117
+ expect(() => validateLimits({ maxOutBytes: 1024 })).not.toThrow();
118
+ });
119
+ });
120
+ });
121
+ //# sourceMappingURL=validation.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.test.js","sourceRoot":"","sources":["../src/validation.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjF,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;QACjC,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;YACvC,MAAM,IAAI,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;YAE5C,MAAM,CAAC,GAAG,EAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QAC/D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;YAC1C,MAAM,IAAI,GAAG,IAAI,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAEvC,MAAM,CAAC,GAAG,EAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;iBAC1C,OAAO,CAAC,4BAA4B,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;YACnD,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YAE/B,MAAM,CAAC,GAAG,EAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;iBAC3C,OAAO,CAAC,8BAA8B,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;YAChD,MAAM,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC;YAE3B,MAAM,CAAC,GAAG,EAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;iBAC3C,OAAO,CAAC,oCAAoC,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;YAC1D,MAAM,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC;YAE5B,MAAM,CAAC,GAAG,EAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;iBAC3C,OAAO,CAAC,8CAA8C,CAAC,CAAC;QAC7D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;YAC7C,MAAM,CAAC,GAAG,EAAE,CAAC,iBAAiB,CAAC,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QAC7D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;YACxD,MAAM,IAAI,GAAG,CAAC,kBAAkB,CAAC,CAAC,CAAC,uBAAuB;YAE1D,MAAM,CAAC,GAAG,EAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QAC/D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;QAC3B,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;YAC1D,MAAM,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;YACrD,MAAM,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QACzD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;YACrD,MAAM,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QAC3D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;YACnD,MAAM,QAAQ,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAEnC,MAAM,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,oBAAoB,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;YACxE,MAAM,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QAChE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;YACnD,MAAM,QAAQ,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAEnC,MAAM,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;iBAC/C,OAAO,CAAC,6CAA6C,CAAC,CAAC;QAC5D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;YACxC,MAAM,QAAQ,GAAG,CAAC,OAAO,CAAC,CAAC;YAE3B,MAAM,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QACpE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;YACxC,MAAM,QAAQ,GAAG,CAAC,QAAQ,CAAC,CAAC;YAE5B,MAAM,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QAClE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;QAC9B,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;YACxC,MAAM,CAAC,GAAG,EAAE,CAAC,cAAc,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QAC/C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;YACpC,MAAM,MAAM,GAAG;gBACb,KAAK,EAAE,IAAI;gBACX,KAAK,EAAE,GAAG;gBACV,MAAM,EAAE,IAAI;gBACZ,WAAW,EAAE,IAAI;aAClB,CAAC;YAEF,MAAM,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QACrD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;YACtC,MAAM,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;iBACvC,OAAO,CAAC,sBAAsB,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;YAC1C,MAAM,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;iBACxC,OAAO,CAAC,uBAAuB,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;YAC/C,MAAM,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;iBAC5C,OAAO,CAAC,2BAA2B,CAAC,CAAC;QAC1C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;YACzC,MAAM,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;iBACvC,OAAO,CAAC,yBAAyB,CAAC,CAAC;QACxC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;YAClD,MAAM,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;iBAC1C,OAAO,CAAC,4BAA4B,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;YAC5C,MAAM,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;iBACxC,OAAO,CAAC,4BAA4B,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;YACrD,MAAM,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;iBAC7C,OAAO,CAAC,iCAAiC,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;YACzC,MAAM,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC,CAAC;iBAC7C,OAAO,CAAC,yBAAyB,CAAC,CAAC;QACxC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;YAClD,MAAM,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC,CAAC;iBACpD,OAAO,CAAC,gCAAgC,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;YACtC,MAAM,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;YAC5D,MAAM,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;YAC3D,MAAM,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;YAC7D,MAAM,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QACpE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare const VERSION = "1.0.0";
2
+ export declare const BUILD_TIME: string;
3
+ export declare function getVersionInfo(): string;
4
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,OAAO,UAAU,CAAC;AAC/B,eAAO,MAAM,UAAU,QAA2B,CAAC;AAEnD,wBAAgB,cAAc,IAAI,MAAM,CAEvC"}
@@ -0,0 +1,6 @@
1
+ export const VERSION = '1.0.0';
2
+ export const BUILD_TIME = new Date().toISOString();
3
+ export function getVersionInfo() {
4
+ return `v${VERSION} (built: ${BUILD_TIME})`;
5
+ }
6
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAC/B,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAEnD,MAAM,UAAU,cAAc;IAC5B,OAAO,IAAI,OAAO,YAAY,UAAU,GAAG,CAAC;AAC9C,CAAC"}
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@thenewlabs/entangle-utils",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "default": "./dist/index.js"
11
+ },
12
+ "./browser": {
13
+ "types": "./dist/browser.d.ts",
14
+ "default": "./dist/browser.js"
15
+ }
16
+ },
17
+ "scripts": {
18
+ "build": "tsc",
19
+ "clean": "rm -rf dist",
20
+ "prepublishOnly": "npm run build"
21
+ },
22
+ "dependencies": {
23
+ "@thenewlabs/entangle-protocol": "^1.0.0",
24
+ "dotenv": "^17.4.2",
25
+ "pino": "^10.3.1"
26
+ },
27
+ "devDependencies": {
28
+ "@types/node": "^20.19.43",
29
+ "typescript": "^5.9.3"
30
+ },
31
+ "files": [
32
+ "dist"
33
+ ]
34
+ }