@lemoncloud/chatic-sockets-lib 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +44 -0
  2. package/dist/client-socket-v2/common.d.ts +4 -0
  3. package/dist/client-socket-v2/common.js +21 -0
  4. package/dist/client-socket-v2/connection-rotation-controller.d.ts +26 -0
  5. package/dist/client-socket-v2/connection-rotation-controller.js +79 -0
  6. package/dist/client-socket-v2/create-client-socket-v2.d.ts +2 -0
  7. package/dist/client-socket-v2/create-client-socket-v2.js +164 -0
  8. package/dist/client-socket-v2/create-device-runtime.d.ts +19 -0
  9. package/dist/client-socket-v2/create-device-runtime.js +53 -0
  10. package/dist/client-socket-v2/domain-sync-plan.d.ts +1 -0
  11. package/dist/client-socket-v2/domain-sync-plan.js +2 -0
  12. package/dist/client-socket-v2/gateways/create-domain-gateway.d.ts +6 -0
  13. package/dist/client-socket-v2/gateways/create-domain-gateway.js +19 -0
  14. package/dist/client-socket-v2/gateways/device-gateway.d.ts +8 -0
  15. package/dist/client-socket-v2/gateways/device-gateway.js +13 -0
  16. package/dist/client-socket-v2/index.d.ts +23 -0
  17. package/dist/client-socket-v2/index.js +41 -0
  18. package/dist/client-socket-v2/keep-alive-loop.d.ts +29 -0
  19. package/dist/client-socket-v2/keep-alive-loop.js +93 -0
  20. package/dist/client-socket-v2/message-router.d.ts +9 -0
  21. package/dist/client-socket-v2/message-router.js +45 -0
  22. package/dist/client-socket-v2/pending-request-store.d.ts +23 -0
  23. package/dist/client-socket-v2/pending-request-store.js +85 -0
  24. package/dist/client-socket-v2/plans/device-sync-plan.d.ts +30 -0
  25. package/dist/client-socket-v2/plans/device-sync-plan.js +64 -0
  26. package/dist/client-socket-v2/reconnect-controller.d.ts +32 -0
  27. package/dist/client-socket-v2/reconnect-controller.js +120 -0
  28. package/dist/client-socket-v2/shared-timer-scheduler.d.ts +17 -0
  29. package/dist/client-socket-v2/shared-timer-scheduler.js +72 -0
  30. package/dist/client-socket-v2/socket-runtime.d.ts +32 -0
  31. package/dist/client-socket-v2/socket-runtime.js +52 -0
  32. package/dist/client-socket-v2/socket-transport.d.ts +18 -0
  33. package/dist/client-socket-v2/socket-transport.js +124 -0
  34. package/dist/client-socket-v2/sync-scheduler.d.ts +36 -0
  35. package/dist/client-socket-v2/sync-scheduler.js +189 -0
  36. package/dist/client-socket-v2/types.d.ts +135 -0
  37. package/dist/client-socket-v2/types.js +2 -0
  38. package/dist/lib/device/contracts.d.ts +36 -0
  39. package/dist/lib/device/contracts.js +7 -0
  40. package/dist/lib/device/types.d.ts +55 -0
  41. package/dist/lib/device/types.js +2 -0
  42. package/dist/lib/sockets/packets.d.ts +67 -0
  43. package/dist/lib/sockets/packets.js +2 -0
  44. package/dist/lib/types.d.ts +122 -0
  45. package/dist/lib/types.js +11 -0
  46. package/package.json +31 -0
package/README.md ADDED
@@ -0,0 +1,44 @@
1
+ # @lemoncloud/chatic-sockets-lib
2
+
3
+ `@lemoncloud/chatic-sockets-lib`는 `ClientSocketV2`와 동기화 런타임을 실제 앱에서 재사용할 수 있도록 분리한 npm 배포 패키지다.
4
+
5
+ ## Goals
6
+
7
+ - 기본 엔트리는 `createClientSocketV2`
8
+ - `lemon-core` 미포함
9
+ - `system.*`, `device.*` socket packet 타입 포함
10
+ - `device.save`, `device.read`, `device.sync`용 중요 타입 포함
11
+ - 클라이언트 생성 시 초기 장치 정보(`id` 포함 가능)를 선택적으로 받을 수 있음
12
+
13
+ ## Main Export
14
+
15
+ ```ts
16
+ import createClientSocketV2, { createDeviceRuntime } from '@lemoncloud/chatic-sockets-lib';
17
+
18
+ const client = createClientSocketV2({
19
+ url: 'wss://example.com/dev',
20
+ device: {
21
+ id: 'device-web-1',
22
+ name: 'Device A',
23
+ platform: 'web'
24
+ }
25
+ });
26
+
27
+ const runtime = createDeviceRuntime({ client });
28
+ await runtime.start();
29
+ ```
30
+
31
+ ## Notes
32
+
33
+ - `device.tick`은 서버 관리 값이므로 클라이언트 입력으로는 사용되지 않는다.
34
+ - `device` 옵션에 `tick`이 들어와도 라이브러리에서 제외한다.
35
+ - 패키지 빌드는 `src/client-socket-v2/`와 client-safe 계약 타입만 포함한다.
36
+
37
+ ## Build
38
+
39
+ 루트에서 아래를 실행한다.
40
+
41
+ ```bash
42
+ npm run lib:build
43
+ npm run lib:pack
44
+ ```
@@ -0,0 +1,4 @@
1
+ export declare const cleanString: <T extends string = string>(value?: unknown, fallback?: string) => T;
2
+ export declare const asString: <T extends string = string>(value?: unknown, fallback?: string) => T;
3
+ export declare const onlyDefined: <T>(value: T) => T;
4
+ export declare const omitKeys: <T extends Record<string, any>, TKey extends keyof T>(value: T, keys: TKey[]) => Omit<T, TKey>;
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.omitKeys = exports.onlyDefined = exports.asString = exports.cleanString = void 0;
4
+ const cleanString = (value, fallback = '') => { var _a; return `${(_a = value !== null && value !== void 0 ? value : fallback) !== null && _a !== void 0 ? _a : ''}`.trim(); };
5
+ exports.cleanString = cleanString;
6
+ const asString = (value, fallback = '') => { var _a; return `${(_a = value !== null && value !== void 0 ? value : fallback) !== null && _a !== void 0 ? _a : ''}`; };
7
+ exports.asString = asString;
8
+ const onlyDefined = (value) => value && typeof value === 'object'
9
+ ? Object.entries(value).reduce((acc, [key, item]) => {
10
+ if (item !== undefined)
11
+ acc[key] = item;
12
+ return acc;
13
+ }, {})
14
+ : null;
15
+ exports.onlyDefined = onlyDefined;
16
+ const omitKeys = (value, keys) => Object.entries(value || {}).reduce((acc, [key, item]) => {
17
+ if (!keys.includes(key))
18
+ acc[key] = item;
19
+ return acc;
20
+ }, {});
21
+ exports.omitKeys = omitKeys;
@@ -0,0 +1,26 @@
1
+ import type { ClientSocketV2, ReconnectController, SharedTimerScheduler } from './types';
2
+ export interface ConnectionRotationControllerOptions {
3
+ client: ClientSocketV2;
4
+ reconnect?: ReconnectController;
5
+ maxLifetimeMs?: number;
6
+ refreshBeforeMs?: number;
7
+ timerScheduler?: SharedTimerScheduler;
8
+ timerKey?: string;
9
+ }
10
+ export declare class ConnectionRotationController {
11
+ private readonly options;
12
+ private readonly maxLifetimeMs;
13
+ private readonly refreshBeforeMs;
14
+ private readonly timerScheduler?;
15
+ private readonly timerKey;
16
+ private readonly unsubs;
17
+ private timer?;
18
+ private active;
19
+ constructor(options: ConnectionRotationControllerOptions);
20
+ start: () => void;
21
+ stop: () => void;
22
+ destroy: () => void;
23
+ private scheduleRotation;
24
+ private rotate;
25
+ private clearTimer;
26
+ }
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.ConnectionRotationController = void 0;
13
+ class ConnectionRotationController {
14
+ constructor(options) {
15
+ var _a, _b, _c;
16
+ this.options = options;
17
+ this.unsubs = [];
18
+ this.active = false;
19
+ this.start = () => {
20
+ this.active = true;
21
+ if (this.options.client.state === 'connected')
22
+ this.scheduleRotation();
23
+ };
24
+ this.stop = () => {
25
+ this.active = false;
26
+ this.clearTimer();
27
+ };
28
+ this.destroy = () => {
29
+ this.stop();
30
+ this.unsubs.splice(0).forEach(unsub => unsub());
31
+ };
32
+ this.scheduleRotation = () => {
33
+ this.clearTimer();
34
+ if (!this.active)
35
+ return;
36
+ const delayMs = Math.max(0, this.maxLifetimeMs - this.refreshBeforeMs);
37
+ if (this.timerScheduler) {
38
+ this.timerScheduler.schedule(this.timerKey, delayMs, () => this.rotate());
39
+ return;
40
+ }
41
+ this.timer = setTimeout(() => void this.rotate(), delayMs);
42
+ };
43
+ this.rotate = () => __awaiter(this, void 0, void 0, function* () {
44
+ if (!this.active)
45
+ return;
46
+ try {
47
+ if (this.options.reconnect) {
48
+ yield this.options.reconnect.restart();
49
+ return;
50
+ }
51
+ yield this.options.client.disconnect(1012, 'service-restart');
52
+ yield this.options.client.connect();
53
+ }
54
+ catch (_e) {
55
+ return;
56
+ }
57
+ });
58
+ this.clearTimer = () => {
59
+ var _a;
60
+ (_a = this.timerScheduler) === null || _a === void 0 ? void 0 : _a.cancel(this.timerKey);
61
+ if (this.timer)
62
+ clearTimeout(this.timer);
63
+ this.timer = undefined;
64
+ };
65
+ this.maxLifetimeMs = (_a = options.maxLifetimeMs) !== null && _a !== void 0 ? _a : 1000 * 60 * 110;
66
+ this.refreshBeforeMs = (_b = options.refreshBeforeMs) !== null && _b !== void 0 ? _b : 1000 * 60 * 10;
67
+ this.timerScheduler = options.timerScheduler;
68
+ this.timerKey = (_c = options.timerKey) !== null && _c !== void 0 ? _c : 'rotation';
69
+ this.unsubs.push(options.client.onState(event => {
70
+ if (!this.active)
71
+ return;
72
+ if (event.next === 'connected')
73
+ this.scheduleRotation();
74
+ if (event.next === 'closing' || event.next === 'closed')
75
+ this.clearTimer();
76
+ }));
77
+ }
78
+ }
79
+ exports.ConnectionRotationController = ConnectionRotationController;
@@ -0,0 +1,2 @@
1
+ import type { ClientSocketOptions, ClientSocketV2 } from './types';
2
+ export declare const createClientSocketV2: (options: ClientSocketOptions) => ClientSocketV2;
@@ -0,0 +1,164 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.createClientSocketV2 = void 0;
13
+ const common_1 = require("./common");
14
+ const message_router_1 = require("./message-router");
15
+ const pending_request_store_1 = require("./pending-request-store");
16
+ const shared_timer_scheduler_1 = require("./shared-timer-scheduler");
17
+ const socket_transport_1 = require("./socket-transport");
18
+ const buildMid = () => `m-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
19
+ const parseMessage = (raw) => {
20
+ const text = `${raw !== null && raw !== void 0 ? raw : ''}`.trim();
21
+ if (!text)
22
+ throw new Error(`@raw message is empty`);
23
+ if (!text.startsWith('{') || !text.endsWith('}'))
24
+ throw new Error(`invalid socket JSON message`);
25
+ const message = JSON.parse(text);
26
+ if (typeof (message === null || message === void 0 ? void 0 : message.type) !== 'string' || !message.type.trim()) {
27
+ throw new Error(`@message.type (string) is required`);
28
+ }
29
+ return (0, common_1.onlyDefined)(Object.assign(Object.assign({}, message), { type: (0, common_1.cleanString)(message.type) }));
30
+ };
31
+ class ClientSocketV2Impl {
32
+ constructor(options) {
33
+ var _a;
34
+ this.options = options;
35
+ this.router = new message_router_1.MessageRouter();
36
+ this.stateListeners = new Set();
37
+ this.errorListeners = new Set();
38
+ this.messageListeners = new Set();
39
+ this._state = 'idle';
40
+ this.connect = () => __awaiter(this, void 0, void 0, function* () {
41
+ if (this._state === 'connected' || this._state === 'connecting')
42
+ return;
43
+ this.setState('connecting');
44
+ try {
45
+ yield this.transport.connect();
46
+ }
47
+ catch (error) {
48
+ this.emitError({ error, phase: 'connect' });
49
+ this.setState('closed');
50
+ throw error;
51
+ }
52
+ });
53
+ this.disconnect = (code, reason) => __awaiter(this, void 0, void 0, function* () {
54
+ if (this._state === 'closed' || this._state === 'idle')
55
+ return;
56
+ this.setState('closing');
57
+ try {
58
+ yield this.transport.disconnect(code, reason);
59
+ }
60
+ catch (error) {
61
+ this.emitError({ error, phase: 'disconnect' });
62
+ throw error;
63
+ }
64
+ });
65
+ this.send = (arg1, arg2) => {
66
+ var _a;
67
+ const message = typeof arg1 === 'string'
68
+ ? (0, common_1.onlyDefined)({
69
+ type: this.normalizeType(arg1),
70
+ data: (_a = arg2) !== null && _a !== void 0 ? _a : null,
71
+ })
72
+ : (0, common_1.onlyDefined)(Object.assign(Object.assign({}, arg1), { type: this.normalizeType(arg1.type) }));
73
+ this.transport.send(JSON.stringify(message));
74
+ };
75
+ this.request = (type, data, options) => __awaiter(this, void 0, void 0, function* () {
76
+ var _b, _c, _d, _e, _f;
77
+ const mid = (_d = (_c = (_b = this.options).createMid) === null || _c === void 0 ? void 0 : _c.call(_b)) !== null && _d !== void 0 ? _d : buildMid();
78
+ const canonicalType = this.normalizeType(type);
79
+ const promise = this.pending.create(mid, {
80
+ timeoutMs: (_e = options === null || options === void 0 ? void 0 : options.timeoutMs) !== null && _e !== void 0 ? _e : this.options.requestTimeoutMs,
81
+ onTimeout: requestMid => new Error(`408 REQUEST TIMEOUT - ${canonicalType}[${requestMid}]`),
82
+ });
83
+ try {
84
+ this.transport.send(JSON.stringify((0, common_1.onlyDefined)({
85
+ type: canonicalType,
86
+ data: (_f = data) !== null && _f !== void 0 ? _f : null,
87
+ mid,
88
+ })));
89
+ }
90
+ catch (error) {
91
+ this.pending.reject(mid, error);
92
+ this.emitError({ error, phase: 'request' });
93
+ throw error;
94
+ }
95
+ return promise;
96
+ });
97
+ this.onState = (listener) => {
98
+ this.stateListeners.add(listener);
99
+ return () => this.stateListeners.delete(listener);
100
+ };
101
+ this.onError = (listener) => {
102
+ this.errorListeners.add(listener);
103
+ return () => this.errorListeners.delete(listener);
104
+ };
105
+ this.onMessage = (listener) => {
106
+ this.messageListeners.add(listener);
107
+ return () => this.messageListeners.delete(listener);
108
+ };
109
+ this.onType = (type, listener) => this.router.onType(type, listener);
110
+ this.normalizeType = (type) => {
111
+ var _a;
112
+ const source = (0, common_1.cleanString)(type);
113
+ if (!source)
114
+ throw new Error(`@type (string) is required - ClientSocketV2`);
115
+ return ((_a = this.aliases[source]) !== null && _a !== void 0 ? _a : source);
116
+ };
117
+ this.handleRawMessage = (raw) => {
118
+ try {
119
+ const message = parseMessage(raw);
120
+ const handled = this.pending.settle(message);
121
+ const event = { message, raw };
122
+ this.messageListeners.forEach(listener => listener(event));
123
+ if (!handled)
124
+ this.router.route(message);
125
+ }
126
+ catch (error) {
127
+ this.emitError({ error, phase: 'message', raw });
128
+ }
129
+ };
130
+ this.setState = (next) => {
131
+ const prev = this._state;
132
+ this._state = next;
133
+ if (prev === next)
134
+ return;
135
+ const event = { prev, next };
136
+ this.stateListeners.forEach(listener => listener(event));
137
+ };
138
+ this.emitError = (event) => {
139
+ this.errorListeners.forEach(listener => listener(event));
140
+ };
141
+ this.deviceDefaults = options.device ? (0, common_1.omitKeys)(options.device, ['tick']) : undefined;
142
+ this.timerScheduler = (_a = options.timerScheduler) !== null && _a !== void 0 ? _a : new shared_timer_scheduler_1.InMemorySharedTimerScheduler(options.now ? { now: options.now } : {});
143
+ this.pending = new pending_request_store_1.PendingRequestStore({
144
+ timerScheduler: this.timerScheduler,
145
+ timerPrefix: 'pending:',
146
+ });
147
+ this.aliases = Object.assign({ ping: 'system.ping' }, (options.aliases || {}));
148
+ this.transport = new socket_transport_1.WebSocketTransport(options.url, options.protocols, options.socketFactory);
149
+ this.transport.on('open', () => this.setState('connected'));
150
+ this.transport.on('close', () => {
151
+ this.pending.clear(new Error(`499 CLIENT CLOSED REQUEST - socket closed`));
152
+ this.setState('closed');
153
+ });
154
+ this.transport.on('error', event => {
155
+ this.emitError({ error: event === null || event === void 0 ? void 0 : event.error, phase: 'transport' });
156
+ });
157
+ this.transport.on('message', event => this.handleRawMessage(event.data));
158
+ }
159
+ get state() {
160
+ return this._state;
161
+ }
162
+ }
163
+ const createClientSocketV2 = (options) => new ClientSocketV2Impl(options);
164
+ exports.createClientSocketV2 = createClientSocketV2;
@@ -0,0 +1,19 @@
1
+ import { type DeviceGateway } from './gateways/device-gateway';
2
+ import { DeviceSyncPlan, type DeviceSyncPlanOptions } from './plans/device-sync-plan';
3
+ import { type ClientSocketRuntimeOptions } from './socket-runtime';
4
+ import type { ClientSocketRuntime, ClientSocketV2 } from './types';
5
+ export interface DeviceSocketRuntime extends ClientSocketRuntime {
6
+ readonly client: ClientSocketV2;
7
+ readonly device: DeviceGateway;
8
+ readonly devicePlan: DeviceSyncPlan;
9
+ saveCurrentDevice(): Promise<void>;
10
+ startCurrentDeviceSync(intervalMs?: number): void;
11
+ startDeviceSync(id: string, intervalMs?: number): void;
12
+ }
13
+ export interface CreateDeviceRuntimeOptions extends Omit<ClientSocketRuntimeOptions, 'client' | 'syncPlans' | 'scheduler' | 'keepAlive' | 'reconnect' | 'rotation'> {
14
+ client: ClientSocketV2;
15
+ devicePlan?: DeviceSyncPlan;
16
+ devicePlanOptions?: DeviceSyncPlanOptions;
17
+ extraSyncPlans?: ClientSocketRuntimeOptions['syncPlans'];
18
+ }
19
+ export declare const createDeviceRuntime: (options: CreateDeviceRuntimeOptions) => DeviceSocketRuntime;
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.createDeviceRuntime = void 0;
13
+ const device_gateway_1 = require("./gateways/device-gateway");
14
+ const device_sync_plan_1 = require("./plans/device-sync-plan");
15
+ const socket_runtime_1 = require("./socket-runtime");
16
+ const createDeviceRuntime = (options) => {
17
+ var _a, _b;
18
+ const devicePlan = (_a = options.devicePlan) !== null && _a !== void 0 ? _a : new device_sync_plan_1.DeviceSyncPlan(options.devicePlanOptions);
19
+ const runtime = new socket_runtime_1.SocketRuntime(Object.assign(Object.assign({}, options), { client: options.client, syncPlans: [devicePlan, ...((_b = options.extraSyncPlans) !== null && _b !== void 0 ? _b : [])] }));
20
+ const device = (0, device_gateway_1.createDeviceGateway)(options.client);
21
+ let active = false;
22
+ const saveCurrentDevice = () => __awaiter(void 0, void 0, void 0, function* () {
23
+ if (!active || !options.client.deviceDefaults)
24
+ return;
25
+ yield device.save(options.client.deviceDefaults);
26
+ });
27
+ options.client.onState(event => {
28
+ if (event.next === 'connected')
29
+ void saveCurrentDevice();
30
+ });
31
+ return {
32
+ client: options.client,
33
+ device,
34
+ devicePlan,
35
+ start: () => __awaiter(void 0, void 0, void 0, function* () {
36
+ active = true;
37
+ yield runtime.start();
38
+ }),
39
+ stop: () => __awaiter(void 0, void 0, void 0, function* () {
40
+ active = false;
41
+ yield runtime.stop();
42
+ }),
43
+ startSync: runtime.startSync,
44
+ stopSync: runtime.stopSync,
45
+ stopAllSync: runtime.stopAllSync,
46
+ listSyncTargets: runtime.listSyncTargets,
47
+ updateLocalSnapshot: runtime.updateLocalSnapshot,
48
+ saveCurrentDevice,
49
+ startCurrentDeviceSync: (intervalMs) => runtime.startSync({ type: 'device', intervalMs }),
50
+ startDeviceSync: (id, intervalMs) => runtime.startSync({ type: 'device', id, intervalMs }),
51
+ };
52
+ };
53
+ exports.createDeviceRuntime = createDeviceRuntime;
@@ -0,0 +1 @@
1
+ export type { DomainSyncContext, DomainSyncPlan, SyncTargetDescriptor, SyncTargetType } from './types';
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,6 @@
1
+ import type { ClientSocketV2 } from '../types';
2
+ export interface DomainGateway {
3
+ send(action: string, data?: unknown): void;
4
+ request<TResult = unknown>(action: string, data?: unknown): Promise<TResult>;
5
+ }
6
+ export declare const createDomainGateway: (domain: string, client: ClientSocketV2) => DomainGateway;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createDomainGateway = void 0;
4
+ const createDomainGateway = (domain, client) => {
5
+ const prefix = `${domain !== null && domain !== void 0 ? domain : ''}`.trim();
6
+ if (!prefix)
7
+ throw new Error(`@domain (string) is required - createDomainGateway()`);
8
+ const resolveType = (action) => {
9
+ const suffix = `${action !== null && action !== void 0 ? action : ''}`.trim();
10
+ if (!suffix)
11
+ throw new Error(`@action (string) is required - createDomainGateway(${prefix})`);
12
+ return `${prefix}.${suffix}`;
13
+ };
14
+ return {
15
+ send: (action, data) => client.send(resolveType(action), data),
16
+ request: (action, data) => client.request(resolveType(action), data),
17
+ };
18
+ };
19
+ exports.createDomainGateway = createDomainGateway;
@@ -0,0 +1,8 @@
1
+ import type { DeviceGetInput, DeviceGetResponseData, DeviceSaveInput, DeviceSaveResponseData, DeviceSyncInput } from '../../lib/device/types';
2
+ import type { ClientSocketV2 } from '../types';
3
+ export interface DeviceGateway {
4
+ save(data: DeviceSaveInput): Promise<DeviceSaveResponseData>;
5
+ read(data?: DeviceGetInput | null): Promise<DeviceGetResponseData>;
6
+ sync(data?: DeviceSyncInput | null): void;
7
+ }
8
+ export declare const createDeviceGateway: (client: ClientSocketV2) => DeviceGateway;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createDeviceGateway = void 0;
4
+ const create_domain_gateway_1 = require("./create-domain-gateway");
5
+ const createDeviceGateway = (client) => {
6
+ const gateway = (0, create_domain_gateway_1.createDomainGateway)('device', client);
7
+ return {
8
+ save: data => gateway.request('save', data),
9
+ read: data => gateway.request('read', data !== null && data !== void 0 ? data : null),
10
+ sync: data => gateway.send('sync', data !== null && data !== void 0 ? data : null),
11
+ };
12
+ };
13
+ exports.createDeviceGateway = createDeviceGateway;
@@ -0,0 +1,23 @@
1
+ import '../lib/sockets/packets';
2
+ import '../lib/device/types';
3
+ export * from './types';
4
+ export * from './common';
5
+ export { createClientSocketV2 as default } from './create-client-socket-v2';
6
+ export * from './domain-sync-plan';
7
+ export * from './pending-request-store';
8
+ export * from './message-router';
9
+ export * from './shared-timer-scheduler';
10
+ export * from './socket-transport';
11
+ export * from './create-client-socket-v2';
12
+ export * from './keep-alive-loop';
13
+ export * from './reconnect-controller';
14
+ export * from './connection-rotation-controller';
15
+ export * from './sync-scheduler';
16
+ export * from './socket-runtime';
17
+ export * from './create-device-runtime';
18
+ export * from './plans/device-sync-plan';
19
+ export * from './gateways/create-domain-gateway';
20
+ export * from './gateways/device-gateway';
21
+ export * from '../lib/types';
22
+ export * from '../lib/device/types';
23
+ export * from '../lib/device/contracts';
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.default = void 0;
18
+ require("../lib/sockets/packets");
19
+ require("../lib/device/types");
20
+ __exportStar(require("./types"), exports);
21
+ __exportStar(require("./common"), exports);
22
+ var create_client_socket_v2_1 = require("./create-client-socket-v2");
23
+ Object.defineProperty(exports, "default", { enumerable: true, get: function () { return create_client_socket_v2_1.createClientSocketV2; } });
24
+ __exportStar(require("./domain-sync-plan"), exports);
25
+ __exportStar(require("./pending-request-store"), exports);
26
+ __exportStar(require("./message-router"), exports);
27
+ __exportStar(require("./shared-timer-scheduler"), exports);
28
+ __exportStar(require("./socket-transport"), exports);
29
+ __exportStar(require("./create-client-socket-v2"), exports);
30
+ __exportStar(require("./keep-alive-loop"), exports);
31
+ __exportStar(require("./reconnect-controller"), exports);
32
+ __exportStar(require("./connection-rotation-controller"), exports);
33
+ __exportStar(require("./sync-scheduler"), exports);
34
+ __exportStar(require("./socket-runtime"), exports);
35
+ __exportStar(require("./create-device-runtime"), exports);
36
+ __exportStar(require("./plans/device-sync-plan"), exports);
37
+ __exportStar(require("./gateways/create-domain-gateway"), exports);
38
+ __exportStar(require("./gateways/device-gateway"), exports);
39
+ __exportStar(require("../lib/types"), exports);
40
+ __exportStar(require("../lib/device/types"), exports);
41
+ __exportStar(require("../lib/device/contracts"), exports);
@@ -0,0 +1,29 @@
1
+ import type { KeepAliveLoopControl, ClientSocketV2, SharedTimerScheduler } from './types';
2
+ export interface KeepAliveLoopOptions {
3
+ client: ClientSocketV2;
4
+ intervalMs?: number;
5
+ timeoutMs?: number;
6
+ buildPayload?: () => unknown;
7
+ mode?: 'send' | 'request';
8
+ timerScheduler?: SharedTimerScheduler;
9
+ timerKey?: string;
10
+ }
11
+ export declare class KeepAliveLoop implements KeepAliveLoopControl {
12
+ private readonly options;
13
+ private readonly intervalMs;
14
+ private readonly mode;
15
+ private readonly timerScheduler?;
16
+ private readonly timerKey;
17
+ private readonly unsubs;
18
+ private timer?;
19
+ private running;
20
+ private inFlight?;
21
+ constructor(options: KeepAliveLoopOptions);
22
+ start: () => void;
23
+ stop: () => void;
24
+ destroy: () => void;
25
+ private scheduleNow;
26
+ private scheduleNext;
27
+ private clearTimer;
28
+ private tick;
29
+ }