@lemoncloud/chatic-sockets-lib 0.2.1 → 0.3.1

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/dist/client-socket-v2/gateways/channel-gateway.d.ts +1 -1
  2. package/dist/client-socket-v2/gateways/cloud-gateway.d.ts +7 -1
  3. package/dist/client-socket-v2/gateways/cloud-gateway.js +3 -0
  4. package/dist/client-socket-v2/gateways/place-gateway.d.ts +18 -0
  5. package/dist/client-socket-v2/gateways/place-gateway.js +14 -0
  6. package/dist/client-socket-v2/gateways/profile-gateway.d.ts +18 -0
  7. package/dist/client-socket-v2/gateways/profile-gateway.js +14 -0
  8. package/dist/client-socket-v2/gateways/user-gateway.d.ts +20 -8
  9. package/dist/client-socket-v2/gateways/user-gateway.js +1 -1
  10. package/dist/client-socket-v2/index.d.ts +5 -0
  11. package/dist/client-socket-v2/index.js +5 -0
  12. package/dist/client-socket-v2/plans/channel-sync-plan.d.ts +33 -0
  13. package/dist/client-socket-v2/plans/channel-sync-plan.js +66 -0
  14. package/dist/client-socket-v2/plans/device-sync-plan.d.ts +5 -1
  15. package/dist/client-socket-v2/plans/device-sync-plan.js +6 -3
  16. package/dist/client-socket-v2/plans/place-sync-plan.d.ts +33 -0
  17. package/dist/client-socket-v2/plans/place-sync-plan.js +67 -0
  18. package/dist/client-socket-v2/plans/profile-sync-plan.d.ts +33 -0
  19. package/dist/client-socket-v2/plans/profile-sync-plan.js +67 -0
  20. package/dist/client-socket-v2/socket-runtime.d.ts +5 -1
  21. package/dist/client-socket-v2/socket-runtime.js +5 -1
  22. package/dist/client-socket-v2/sync-scheduler.d.ts +15 -1
  23. package/dist/client-socket-v2/sync-scheduler.js +89 -12
  24. package/dist/client-socket-v2/types.d.ts +22 -0
  25. package/dist/lib/channel/types.d.ts +27 -11
  26. package/dist/lib/cloud/types.d.ts +38 -2
  27. package/dist/lib/device/contracts.d.ts +4 -0
  28. package/dist/lib/device/types.d.ts +3 -1
  29. package/dist/lib/place/types.d.ts +53 -0
  30. package/dist/lib/place/types.js +2 -0
  31. package/dist/lib/profile/types.d.ts +55 -0
  32. package/dist/lib/profile/types.js +2 -0
  33. package/dist/lib/socket-actions.d.ts +55 -3
  34. package/dist/lib/socket-actions.js +44 -2
  35. package/dist/lib/socket-inputs.d.ts +3 -1
  36. package/dist/modules/chat/model.d.ts +107 -0
  37. package/dist/modules/chat/model.js +28 -0
  38. package/dist/modules/chat/views.d.ts +50 -0
  39. package/dist/modules/chat/views.js +23 -0
  40. package/dist/modules/sockets/model.d.ts +206 -0
  41. package/dist/modules/sockets/model.js +28 -0
  42. package/dist/modules/sockets/types.d.ts +100 -0
  43. package/dist/modules/sockets/types.js +86 -0
  44. package/dist/modules/sockets/views.d.ts +67 -0
  45. package/dist/modules/sockets/views.js +23 -0
  46. package/package.json +4 -2
@@ -1,10 +1,16 @@
1
- import type { ClientSocketV2, DomainSyncPlan, SharedTimerScheduler, SyncScheduler, SyncTargetDescriptor } from './types';
1
+ import type { ClientSocketV2, DomainSyncPlan, SharedTimerScheduler, SyncBackoffOptions, SyncFailurePolicy, SyncScheduler, SyncTargetDescriptor } from './types';
2
+ export type { SyncBackoffOptions } from './types';
2
3
  export interface SyncSchedulerOptions {
3
4
  client: ClientSocketV2;
4
5
  plans: DomainSyncPlan<any>[];
5
6
  now?: () => number;
6
7
  timerScheduler?: SharedTimerScheduler;
7
8
  timerPrefix?: string;
9
+ backoff?: SyncBackoffOptions;
10
+ idleBackoff?: SyncBackoffOptions;
11
+ failurePolicy?: SyncFailurePolicy;
12
+ jitterRatio?: number;
13
+ random?: () => number;
8
14
  }
9
15
  export declare class DomainSyncScheduler implements SyncScheduler {
10
16
  private readonly options;
@@ -14,6 +20,11 @@ export declare class DomainSyncScheduler implements SyncScheduler {
14
20
  private readonly now;
15
21
  private readonly timerScheduler?;
16
22
  private readonly timerPrefix;
23
+ private readonly backoff;
24
+ private readonly idleBackoff?;
25
+ private readonly failurePolicy;
26
+ private readonly jitterRatio;
27
+ private readonly random;
17
28
  private readonly unsubs;
18
29
  constructor(options: SyncSchedulerOptions);
19
30
  start: (target: SyncTargetDescriptor) => void;
@@ -30,7 +41,10 @@ export declare class DomainSyncScheduler implements SyncScheduler {
30
41
  private clearTimer;
31
42
  private scheduleNow;
32
43
  private scheduleNext;
44
+ private computeInterval;
45
+ private jitter;
33
46
  private toTimerKey;
34
47
  private runEntry;
48
+ private handleRunFailure;
35
49
  private handleTrigger;
36
50
  }
@@ -10,9 +10,16 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.DomainSyncScheduler = void 0;
13
+ const defaultClassify = (error) => {
14
+ var _a;
15
+ const msg = error instanceof Error ? error.message : `${error !== null && error !== void 0 ? error : ''}`;
16
+ const code = (_a = /^\s*(\d{3})\b/.exec(msg)) === null || _a === void 0 ? void 0 : _a[1];
17
+ return code === '403' || code === '404' ? 'gone' : 'transient';
18
+ };
19
+ const DEFAULT_IDLE_BACKOFF = { factor: 2, maxMs: 60000 };
13
20
  class DomainSyncScheduler {
14
21
  constructor(options) {
15
- var _a, _b;
22
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
16
23
  this.options = options;
17
24
  this.targets = new Map();
18
25
  this.snapshots = new Map();
@@ -95,12 +102,17 @@ class DomainSyncScheduler {
95
102
  const key = entry ? entry.plan.getKey(entry.target) : this.resolvePlan(target).getKey(target);
96
103
  yield this.runEntry(key);
97
104
  }),
105
+ stop: target => this.stop(target),
98
106
  });
99
107
  this.handleConnected = () => __awaiter(this, void 0, void 0, function* () {
100
- var _c, _d;
108
+ var _k, _l;
101
109
  const ctx = this.buildContext();
102
110
  for (const [key, entry] of this.targets.entries()) {
103
- yield ((_d = (_c = entry.plan).onConnected) === null || _d === void 0 ? void 0 : _d.call(_c, entry.target, ctx));
111
+ // reconnect = fresh start
112
+ entry.failures = 0;
113
+ entry.goneStreak = 0;
114
+ entry.idleStreak = 0;
115
+ yield ((_l = (_k = entry.plan).onConnected) === null || _l === void 0 ? void 0 : _l.call(_k, entry.target, ctx));
104
116
  this.scheduleNow(key);
105
117
  }
106
118
  });
@@ -133,13 +145,28 @@ class DomainSyncScheduler {
133
145
  this.clearTimer(entry);
134
146
  if (this.options.client.state !== 'connected')
135
147
  return;
136
- const intervalMs = (_d = (_a = entry.target.intervalMs) !== null && _a !== void 0 ? _a : (_c = (_b = entry.plan).getIntervalMs) === null || _c === void 0 ? void 0 : _c.call(_b, entry.target)) !== null && _d !== void 0 ? _d : 5000;
148
+ const baseMs = (_d = (_a = entry.target.intervalMs) !== null && _a !== void 0 ? _a : (_c = (_b = entry.plan).getIntervalMs) === null || _c === void 0 ? void 0 : _c.call(_b, entry.target)) !== null && _d !== void 0 ? _d : 5000;
149
+ const intervalMs = this.computeInterval(entry, baseMs);
137
150
  if (this.timerScheduler) {
138
151
  this.timerScheduler.schedule(this.toTimerKey(key), intervalMs, () => this.runEntry(key));
139
152
  return;
140
153
  }
141
154
  entry.timer = setTimeout(() => void this.runEntry(key), intervalMs);
142
155
  };
156
+ this.computeInterval = (entry, baseMs) => {
157
+ var _a, _b, _c, _d, _e, _f;
158
+ const failures = (_a = entry.failures) !== null && _a !== void 0 ? _a : 0;
159
+ if (failures > 0)
160
+ return this.jitter(Math.min(baseMs * Math.pow(this.backoff.factor, failures), this.backoff.maxMs));
161
+ const idle = (_c = (_b = entry.plan.idleBackoff) !== null && _b !== void 0 ? _b : this.idleBackoff) !== null && _c !== void 0 ? _c : DEFAULT_IDLE_BACKOFF;
162
+ const idleFactor = Math.max(1, (_d = idle === null || idle === void 0 ? void 0 : idle.factor) !== null && _d !== void 0 ? _d : 1);
163
+ const idleStreak = (_e = entry.idleStreak) !== null && _e !== void 0 ? _e : 0;
164
+ if (idleFactor > 1 && idleStreak > 0) {
165
+ return this.jitter(Math.min(baseMs * Math.pow(idleFactor, idleStreak), (_f = idle === null || idle === void 0 ? void 0 : idle.maxMs) !== null && _f !== void 0 ? _f : 60000));
166
+ }
167
+ return baseMs;
168
+ };
169
+ this.jitter = (ms) => this.jitterRatio > 0 ? Math.max(0, Math.round(ms * (1 + (this.random() * 2 - 1) * this.jitterRatio))) : ms;
143
170
  this.toTimerKey = (key) => `${this.timerPrefix}${key}`;
144
171
  this.runEntry = (key) => __awaiter(this, void 0, void 0, function* () {
145
172
  const entry = this.targets.get(key);
@@ -148,33 +175,83 @@ class DomainSyncScheduler {
148
175
  if (entry.inFlight)
149
176
  return;
150
177
  const ctx = this.buildContext();
151
- entry.inFlight = Promise.resolve(entry.plan.run(entry.target, ctx))
152
- .catch(() => undefined)
153
- .then(() => {
178
+ // no snapshot write during run = unchanged = idle
179
+ const before = this.snapshots.get(key);
180
+ entry.inFlight = Promise.resolve(entry.plan.run(entry.target, ctx)).then(() => {
181
+ var _a;
154
182
  entry.inFlight = undefined;
183
+ entry.failures = 0;
184
+ entry.goneStreak = 0;
185
+ const changed = this.snapshots.get(key) !== before;
186
+ entry.idleStreak = changed ? 0 : ((_a = entry.idleStreak) !== null && _a !== void 0 ? _a : 0) + 1;
155
187
  this.scheduleNext(key);
188
+ }, error => {
189
+ entry.inFlight = undefined;
190
+ this.handleRunFailure(key, error, ctx);
156
191
  });
157
192
  yield entry.inFlight;
158
193
  });
194
+ this.handleRunFailure = (key, error, ctx) => {
195
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
196
+ const entry = this.targets.get(key);
197
+ if (!entry)
198
+ return;
199
+ const plan = (_a = entry.plan.failurePolicy) !== null && _a !== void 0 ? _a : {};
200
+ const sched = this.failurePolicy;
201
+ const classify = (_c = (_b = plan.classify) !== null && _b !== void 0 ? _b : sched.classify) !== null && _c !== void 0 ? _c : defaultClassify;
202
+ const stopAfter = (_e = (_d = plan.stopAfter) !== null && _d !== void 0 ? _d : sched.stopAfter) !== null && _e !== void 0 ? _e : 2;
203
+ const decide = (_g = (_f = plan.decide) !== null && _f !== void 0 ? _f : sched.decide) !== null && _g !== void 0 ? _g : ((info) => (info.kind === 'gone' && info.goneStreak >= stopAfter ? 'stop' : 'retry'));
204
+ const kind = classify(error, entry.target);
205
+ entry.failures = ((_h = entry.failures) !== null && _h !== void 0 ? _h : 0) + 1;
206
+ entry.goneStreak = kind === 'gone' ? ((_j = entry.goneStreak) !== null && _j !== void 0 ? _j : 0) + 1 : 0;
207
+ entry.idleStreak = 0;
208
+ const info = {
209
+ target: Object.assign({}, entry.target),
210
+ error,
211
+ kind,
212
+ failures: entry.failures,
213
+ goneStreak: entry.goneStreak,
214
+ };
215
+ const decision = decide(info);
216
+ if (decision === 'stop') {
217
+ (_l = (_k = entry.plan).onStopped) === null || _l === void 0 ? void 0 : _l.call(_k, entry.target, info, ctx);
218
+ this.stop(entry.target);
219
+ return;
220
+ }
221
+ if (decision === 'keep') {
222
+ entry.failures = 0;
223
+ entry.goneStreak = 0;
224
+ }
225
+ this.scheduleNext(key);
226
+ };
159
227
  this.handleTrigger = (message) => __awaiter(this, void 0, void 0, function* () {
160
- var _e;
161
- const type = `${(_e = message === null || message === void 0 ? void 0 : message.type) !== null && _e !== void 0 ? _e : ''}`;
228
+ var _m;
229
+ const type = `${(_m = message === null || message === void 0 ? void 0 : message.type) !== null && _m !== void 0 ? _m : ''}`;
162
230
  if (!type.endsWith('.sync'))
163
231
  return;
164
- const targets = [...this.targets.values()];
232
+ const entries = [...this.targets.entries()];
165
233
  const ctx = this.buildContext();
166
- yield Promise.all(targets.map((entry) => __awaiter(this, void 0, void 0, function* () {
234
+ yield Promise.all(entries.map(([key, entry]) => __awaiter(this, void 0, void 0, function* () {
167
235
  if (!entry.plan.onTrigger)
168
236
  return;
169
237
  if (!type.startsWith(`${entry.target.type}.`))
170
238
  return;
171
- yield entry.plan.onTrigger(entry.target, message, ctx);
239
+ // nudge resets idle backoff (best-effort)
240
+ entry.idleStreak = 0;
241
+ yield entry.plan.onTrigger(entry.target, message, ctx).catch(() => undefined);
242
+ if (!entry.inFlight)
243
+ this.scheduleNext(key);
172
244
  })));
173
245
  });
174
246
  this.plans = [...(options.plans || [])];
175
247
  this.now = (_a = options.now) !== null && _a !== void 0 ? _a : (() => Date.now());
176
248
  this.timerScheduler = options.timerScheduler;
177
249
  this.timerPrefix = (_b = options.timerPrefix) !== null && _b !== void 0 ? _b : 'sync:';
250
+ this.backoff = { factor: Math.max(1, (_d = (_c = options.backoff) === null || _c === void 0 ? void 0 : _c.factor) !== null && _d !== void 0 ? _d : 2), maxMs: (_f = (_e = options.backoff) === null || _e === void 0 ? void 0 : _e.maxMs) !== null && _f !== void 0 ? _f : 30000 };
251
+ this.idleBackoff = options.idleBackoff;
252
+ this.failurePolicy = (_g = options.failurePolicy) !== null && _g !== void 0 ? _g : {};
253
+ this.jitterRatio = Math.max(0, (_h = options.jitterRatio) !== null && _h !== void 0 ? _h : 0.1);
254
+ this.random = (_j = options.random) !== null && _j !== void 0 ? _j : Math.random;
178
255
  this.unsubs.push(options.client.onState(event => {
179
256
  if (event.next === 'connected')
180
257
  void this.handleConnected();
@@ -123,21 +123,43 @@ export interface SyncTargetDescriptor {
123
123
  intervalMs?: number;
124
124
  meta?: Record<string, unknown>;
125
125
  }
126
+ export declare type SyncFailureKind = 'gone' | 'transient';
127
+ export declare type SyncFailureDecision = 'stop' | 'keep' | 'retry';
128
+ export interface SyncFailureInfo {
129
+ target: SyncTargetDescriptor;
130
+ error: unknown;
131
+ kind: SyncFailureKind;
132
+ failures: number;
133
+ goneStreak: number;
134
+ }
135
+ export interface SyncFailurePolicy {
136
+ classify?(error: unknown, target: SyncTargetDescriptor): SyncFailureKind;
137
+ decide?(info: SyncFailureInfo): SyncFailureDecision;
138
+ stopAfter?: number;
139
+ }
140
+ export interface SyncBackoffOptions {
141
+ factor?: number;
142
+ maxMs?: number;
143
+ }
126
144
  export interface DomainSyncContext {
127
145
  client: ClientSocketV2;
128
146
  now(): number;
129
147
  readSnapshot<T = unknown>(target: SyncTargetDescriptor): T | undefined;
130
148
  writeSnapshot<T = unknown>(target: SyncTargetDescriptor, snapshot: T | undefined): void;
131
149
  requestResync(target: SyncTargetDescriptor): Promise<void>;
150
+ stop(target: SyncTargetDescriptor): void;
132
151
  }
133
152
  export interface DomainSyncPlan<TTarget extends SyncTargetDescriptor = SyncTargetDescriptor> {
134
153
  readonly domain: string;
154
+ readonly failurePolicy?: SyncFailurePolicy;
155
+ readonly idleBackoff?: SyncBackoffOptions;
135
156
  supports(target: SyncTargetDescriptor): target is TTarget;
136
157
  getKey(target: TTarget): string;
137
158
  getIntervalMs?(target: TTarget): number;
138
159
  onConnected?(target: TTarget, ctx: DomainSyncContext): Promise<void> | void;
139
160
  run(target: TTarget, ctx: DomainSyncContext): Promise<void>;
140
161
  onTrigger?(target: TTarget, message: SocketMessage<any>, ctx: DomainSyncContext): Promise<void>;
162
+ onStopped?(target: TTarget, info: SyncFailureInfo, ctx: DomainSyncContext): void;
141
163
  updateLocalState?(target: TTarget, snapshot: unknown, ctx: DomainSyncContext): void;
142
164
  }
143
165
  export interface SyncScheduler {
@@ -1,5 +1,6 @@
1
1
  import type { InferSocketRequest, SocketRequestMessage } from '../types';
2
2
  import type { ChannelStereo } from '../../modules/chat/types';
3
+ import type { ChannelView } from '../../modules/chat/views';
3
4
  export interface ChannelCreateRequestData {
4
5
  stereo: ChannelStereo;
5
6
  name?: string;
@@ -42,6 +43,9 @@ export interface ChannelUpdateJoinRequestData {
42
43
  export interface ChannelSyncRequestData {
43
44
  since?: number;
44
45
  }
46
+ export interface ChannelGetRequestData {
47
+ id?: string;
48
+ }
45
49
  export interface ChannelSyncUsersRequestData {
46
50
  channelId: string;
47
51
  since?: number;
@@ -50,7 +54,22 @@ declare module '../types' {
50
54
  interface SocketPacketRegistry {
51
55
  'channel.create': {
52
56
  request: ChannelCreateRequestData;
53
- response: unknown;
57
+ response: ChannelView;
58
+ error: null;
59
+ };
60
+ 'channel.get': {
61
+ request: ChannelGetRequestData;
62
+ response: ChannelView;
63
+ error: null;
64
+ };
65
+ 'channel.update': {
66
+ request: ChannelUpdateRequestData;
67
+ response: ChannelView;
68
+ error: null;
69
+ };
70
+ 'channel.delete': {
71
+ request: ChannelByIdRequestData;
72
+ response: ChannelView;
54
73
  error: null;
55
74
  };
56
75
  'channel.join': {
@@ -83,21 +102,11 @@ declare module '../types' {
83
102
  response: unknown;
84
103
  error: null;
85
104
  };
86
- 'channel.update': {
87
- request: ChannelUpdateRequestData;
88
- response: unknown;
89
- error: null;
90
- };
91
105
  'channel.update-join': {
92
106
  request: ChannelUpdateJoinRequestData;
93
107
  response: unknown;
94
108
  error: null;
95
109
  };
96
- 'channel.delete': {
97
- request: ChannelByIdRequestData;
98
- response: unknown;
99
- error: null;
100
- };
101
110
  'channel.sync': {
102
111
  request: ChannelSyncRequestData;
103
112
  response: unknown;
@@ -155,12 +164,19 @@ export declare type ChannelDeleteRequestMessage = SocketRequestMessage<ChannelDe
155
164
  export declare type ChannelSyncType = 'channel.sync';
156
165
  export declare type ChannelSyncInput = InferSocketRequest<ChannelSyncType>;
157
166
  export declare type ChannelSyncRequestMessage = SocketRequestMessage<ChannelSyncType>;
167
+ export declare type ChannelGetType = 'channel.get';
168
+ export declare type ChannelGetInput = InferSocketRequest<ChannelGetType>;
169
+ export declare type ChannelGetRequestMessage = SocketRequestMessage<ChannelGetType>;
158
170
  export declare type ChannelSyncUsersType = 'channel.sync-users';
159
171
  export declare type ChannelSyncUsersInput = InferSocketRequest<ChannelSyncUsersType>;
160
172
  export declare type ChannelSyncUsersRequestMessage = SocketRequestMessage<ChannelSyncUsersType>;
173
+ /** @deprecated use `profile.sync` (ProfileSyncInput). 하위호환용. */
161
174
  export declare type ChannelSyncProfileType = 'channel.sync-site-profile';
175
+ /** @deprecated use `profile.sync` (ProfileSyncInput). 하위호환용. */
162
176
  export declare type ChannelSyncProfileInput = InferSocketRequest<ChannelSyncProfileType>;
177
+ /** @deprecated use `profile.sync` (ProfileSyncInput). 하위호환용. */
163
178
  export declare type ChannelSyncSiteProfileInput = ChannelSyncProfileInput;
179
+ /** @deprecated use `profile.sync`. 하위호환용. */
164
180
  export declare type ChannelSyncProfileRequestMessage = SocketRequestMessage<ChannelSyncProfileType>;
165
181
  export declare type ChannelUnreadsType = 'channel.unreads';
166
182
  export declare type ChannelUnreadsInput = InferSocketRequest<ChannelUnreadsType>;
@@ -1,18 +1,54 @@
1
1
  import type { InferSocketRequest, SocketRequestMessage } from '../types';
2
- export interface CloudUpdateRequestData {
3
- cloudId?: string;
2
+ /** cloud 공통 body 필드 — create/update 양쪽에서 동일하게 사용 */
3
+ export interface CloudBodyData {
4
4
  name?: string;
5
5
  }
6
+ export declare type CloudCreateRequestData = CloudBodyData;
7
+ export interface CloudGetRequestData {
8
+ id: string;
9
+ }
10
+ export interface CloudUpdateRequestData extends CloudBodyData {
11
+ id?: string;
12
+ /** @deprecated use `id` instead. 하위호환용으로만 유지. */
13
+ cloudId?: string;
14
+ }
15
+ export interface CloudDeleteRequestData {
16
+ id: string;
17
+ }
6
18
  declare module '../types' {
7
19
  interface SocketPacketRegistry {
20
+ 'cloud.create': {
21
+ request: CloudCreateRequestData;
22
+ response: unknown;
23
+ error: null;
24
+ };
25
+ 'cloud.get': {
26
+ request: CloudGetRequestData;
27
+ response: unknown;
28
+ error: null;
29
+ };
8
30
  'cloud.update': {
9
31
  request: CloudUpdateRequestData;
10
32
  response: unknown;
11
33
  error: null;
12
34
  };
35
+ 'cloud.delete': {
36
+ request: CloudDeleteRequestData;
37
+ response: unknown;
38
+ error: null;
39
+ };
13
40
  }
14
41
  }
42
+ export declare type CloudCreateType = 'cloud.create';
43
+ export declare type CloudCreateInput = InferSocketRequest<CloudCreateType>;
44
+ export declare type CloudCreateRequestMessage = SocketRequestMessage<CloudCreateType>;
45
+ export declare type CloudGetType = 'cloud.get';
46
+ export declare type CloudGetInput = InferSocketRequest<CloudGetType>;
47
+ export declare type CloudGetRequestMessage = SocketRequestMessage<CloudGetType>;
15
48
  export declare type CloudUpdateType = 'cloud.update';
16
49
  export declare type CloudUpdateInput = InferSocketRequest<CloudUpdateType>;
17
50
  export declare type UpdateCloudInput = CloudUpdateInput;
18
51
  export declare type CloudUpdateRequestMessage = SocketRequestMessage<CloudUpdateType>;
52
+ export declare type CloudDeleteType = 'cloud.delete';
53
+ export declare type CloudDeleteInput = InferSocketRequest<CloudDeleteType>;
54
+ export declare type CloudDeleteRequestMessage = SocketRequestMessage<CloudDeleteType>;
@@ -5,6 +5,7 @@
5
5
  */
6
6
  export declare type DeviceStatus = '' | 'green' | 'red' | 'yellow';
7
7
  export declare type DevicePlatform = '' | 'ios' | 'android' | 'web' | 'macos' | 'windows' | 'linux';
8
+ export declare type ViewingType = '' | 'channel';
8
9
  /**
9
10
  * common device shape shared across websocket client/server contracts.
10
11
  */
@@ -20,6 +21,9 @@ export interface DeviceView {
20
21
  connectedAt?: number;
21
22
  disconnectedAt?: number;
22
23
  connId?: string;
24
+ viewingType?: ViewingType;
25
+ viewingId?: string;
26
+ viewingSince?: number;
23
27
  }
24
28
  /**
25
29
  * mutable device body accepted by `device.save`.
@@ -1,5 +1,5 @@
1
1
  import type { InferSocketError, InferSocketRequest, InferSocketResponse, SocketErrorMessage, SocketRequestMessage, SocketResponseMessage } from '../types';
2
- import type { DeviceBody, DeviceSeed, DeviceView } from './contracts';
2
+ import type { DeviceBody, DeviceSeed, DeviceView, ViewingType } from './contracts';
3
3
  /**
4
4
  * request payload for `device.read`
5
5
  * - omit `id` to read the device linked to the current connection.
@@ -10,6 +10,8 @@ export interface DeviceGetRequestData {
10
10
  export interface DeviceSyncRequestData {
11
11
  id?: string;
12
12
  tick?: number;
13
+ viewingType?: ViewingType;
14
+ viewingId?: string;
13
15
  }
14
16
  declare module '../types' {
15
17
  interface SocketPacketRegistry {
@@ -0,0 +1,53 @@
1
+ import type { InferSocketRequest, SocketRequestMessage } from '../types';
2
+ /** place(site) 공통 body 필드 — create/update 양쪽에서 동일하게 사용 */
3
+ export interface PlaceBodyData {
4
+ name?: string;
5
+ stereo?: string;
6
+ thumbnail?: string;
7
+ }
8
+ export declare type PlaceCreateRequestData = PlaceBodyData;
9
+ export interface PlaceGetRequestData {
10
+ id: string;
11
+ }
12
+ export interface PlaceUpdateRequestData extends PlaceBodyData {
13
+ id?: string;
14
+ }
15
+ export interface PlaceDeleteRequestData {
16
+ id: string;
17
+ }
18
+ declare module '../types' {
19
+ interface SocketPacketRegistry {
20
+ 'place.create': {
21
+ request: PlaceCreateRequestData;
22
+ response: unknown;
23
+ error: null;
24
+ };
25
+ 'place.get': {
26
+ request: PlaceGetRequestData;
27
+ response: unknown;
28
+ error: null;
29
+ };
30
+ 'place.update': {
31
+ request: PlaceUpdateRequestData;
32
+ response: unknown;
33
+ error: null;
34
+ };
35
+ 'place.delete': {
36
+ request: PlaceDeleteRequestData;
37
+ response: unknown;
38
+ error: null;
39
+ };
40
+ }
41
+ }
42
+ export declare type PlaceCreateType = 'place.create';
43
+ export declare type PlaceCreateInput = InferSocketRequest<PlaceCreateType>;
44
+ export declare type PlaceCreateRequestMessage = SocketRequestMessage<PlaceCreateType>;
45
+ export declare type PlaceGetType = 'place.get';
46
+ export declare type PlaceGetInput = InferSocketRequest<PlaceGetType>;
47
+ export declare type PlaceGetRequestMessage = SocketRequestMessage<PlaceGetType>;
48
+ export declare type PlaceUpdateType = 'place.update';
49
+ export declare type PlaceUpdateInput = InferSocketRequest<PlaceUpdateType>;
50
+ export declare type PlaceUpdateRequestMessage = SocketRequestMessage<PlaceUpdateType>;
51
+ export declare type PlaceDeleteType = 'place.delete';
52
+ export declare type PlaceDeleteInput = InferSocketRequest<PlaceDeleteType>;
53
+ export declare type PlaceDeleteRequestMessage = SocketRequestMessage<PlaceDeleteType>;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,55 @@
1
+ import type { InferSocketRequest, SocketRequestMessage } from '../types';
2
+ /** profile 단건 조회 — id 기반 (ProfileView.id = `siteId@userId`) */
3
+ export interface ProfileGetRequestData {
4
+ id: string;
5
+ }
6
+ /** profile(site-profile) set body 필드 — socials ProfileBody pass-through */
7
+ export interface ProfileSetRequestData {
8
+ id?: string;
9
+ userId?: string;
10
+ siteId?: string;
11
+ nick?: string;
12
+ thumbnail?: string;
13
+ active?: boolean;
14
+ [key: string]: unknown;
15
+ }
16
+ /** profile 동기화 — 사이트 수준 멀티프로필 delta(since cursor). 누락 시 전체 */
17
+ export interface ProfileSyncRequestData {
18
+ since?: number;
19
+ }
20
+ declare module '../types' {
21
+ interface SocketPacketRegistry {
22
+ 'profile.get': {
23
+ request: ProfileGetRequestData;
24
+ response: unknown;
25
+ error: null;
26
+ };
27
+ 'profile.get-mine': {
28
+ request: Record<string, never>;
29
+ response: unknown;
30
+ error: null;
31
+ };
32
+ 'profile.set': {
33
+ request: ProfileSetRequestData;
34
+ response: unknown;
35
+ error: null;
36
+ };
37
+ 'profile.sync': {
38
+ request: ProfileSyncRequestData;
39
+ response: unknown;
40
+ error: null;
41
+ };
42
+ }
43
+ }
44
+ export declare type ProfileGetType = 'profile.get';
45
+ export declare type ProfileGetInput = InferSocketRequest<ProfileGetType>;
46
+ export declare type ProfileGetRequestMessage = SocketRequestMessage<ProfileGetType>;
47
+ export declare type ProfileGetMineType = 'profile.get-mine';
48
+ export declare type ProfileGetMineInput = InferSocketRequest<ProfileGetMineType>;
49
+ export declare type ProfileGetMineRequestMessage = SocketRequestMessage<ProfileGetMineType>;
50
+ export declare type ProfileSetType = 'profile.set';
51
+ export declare type ProfileSetInput = InferSocketRequest<ProfileSetType>;
52
+ export declare type ProfileSetRequestMessage = SocketRequestMessage<ProfileSetType>;
53
+ export declare type ProfileSyncType = 'profile.sync';
54
+ export declare type ProfileSyncInput = InferSocketRequest<ProfileSyncType>;
55
+ export declare type ProfileSyncRequestMessage = SocketRequestMessage<ProfileSyncType>;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -30,6 +30,10 @@ export declare const SocketActionTypeLUT: {
30
30
  readonly chat: "chat";
31
31
  /** user - user/site profile operations */
32
32
  readonly user: "user";
33
+ /** place - place(site) CRUD operations */
34
+ readonly place: "place";
35
+ /** profile - site profile operations */
36
+ readonly profile: "profile";
33
37
  /** cloud - cloud profile operations */
34
38
  readonly cloud: "cloud";
35
39
  };
@@ -109,9 +113,11 @@ export declare const SocketActionTypeLUT: {
109
113
  readonly delete: "delete";
110
114
  /** sync - synchronize channel list/state */
111
115
  readonly sync: "sync";
116
+ /** read - pull authoritative single-channel item */
117
+ readonly read: "read";
112
118
  /** sync-users - synchronize channel users */
113
119
  readonly 'sync-users': "sync-users";
114
- /** sync-site-profile - synchronize related site profile */
120
+ /** @deprecated use `profile.sync`. synchronize related site profile (하위호환) */
115
121
  readonly 'sync-site-profile': "sync-site-profile";
116
122
  /** unreads - get unread message summary */
117
123
  readonly unreads: "unreads";
@@ -152,14 +158,50 @@ export declare const SocketActionTypeLUT: {
152
158
  /** set-site-profile - set site profile */
153
159
  readonly 'set-site-profile': "set-site-profile";
154
160
  };
161
+ /**
162
+ * PlaceActionType
163
+ * - place(site) 도메인 액션
164
+ */
165
+ readonly PlaceActionType: {
166
+ readonly '': "";
167
+ /** create - create a place(site) */
168
+ readonly create: "create";
169
+ /** get - get a place(site) */
170
+ readonly get: "get";
171
+ /** update - update a place(site) */
172
+ readonly update: "update";
173
+ /** delete - delete a place(site) */
174
+ readonly delete: "delete";
175
+ };
176
+ /**
177
+ * ProfileActionType
178
+ * - profile(site-profile) 도메인 액션
179
+ */
180
+ readonly ProfileActionType: {
181
+ readonly '': "";
182
+ /** get - get site profile by id */
183
+ readonly get: "get";
184
+ /** get-mine - get current session's site profile */
185
+ readonly 'get-mine': "get-mine";
186
+ /** set - set site profile */
187
+ readonly set: "set";
188
+ /** sync - synchronize site multi-profiles (delta since cursor) */
189
+ readonly sync: "sync";
190
+ };
155
191
  /**
156
192
  * CloudActionType
157
193
  * - cloud 도메인 액션
158
194
  */
159
195
  readonly CloudActionType: {
160
196
  readonly '': "";
161
- /** update - update cloud profile */
197
+ /** create - create a cloud (미구현/500) */
198
+ readonly create: "create";
199
+ /** get - get a cloud */
200
+ readonly get: "get";
201
+ /** update - update a cloud */
162
202
  readonly update: "update";
203
+ /** delete - delete a cloud */
204
+ readonly delete: "delete";
163
205
  };
164
206
  };
165
207
  declare type SocketActionKeyOf<T> = Extract<keyof T, string>;
@@ -196,6 +238,14 @@ export declare type SocketChatActionType = SocketActionKeyOf<typeof SocketAction
196
238
  * type: `SocketUserActionType`
197
239
  */
198
240
  export declare type SocketUserActionType = SocketActionKeyOf<typeof SocketActionTypeLUT.UserActionType>;
241
+ /**
242
+ * type: `SocketPlaceActionType`
243
+ */
244
+ export declare type SocketPlaceActionType = SocketActionKeyOf<typeof SocketActionTypeLUT.PlaceActionType>;
245
+ /**
246
+ * type: `SocketProfileActionType`
247
+ */
248
+ export declare type SocketProfileActionType = SocketActionKeyOf<typeof SocketActionTypeLUT.ProfileActionType>;
199
249
  /**
200
250
  * type: `SocketCloudActionType`
201
251
  */
@@ -203,7 +253,7 @@ export declare type SocketCloudActionType = SocketActionKeyOf<typeof SocketActio
203
253
  /**
204
254
  * type: `SocketActionType`
205
255
  */
206
- export declare type SocketActionType = SocketSystemActionType | SocketSocketsActionType | SocketDeviceActionType | SocketAuthActionType | SocketChannelActionType | SocketChatActionType | SocketUserActionType | SocketCloudActionType;
256
+ export declare type SocketActionType = SocketSystemActionType | SocketSocketsActionType | SocketDeviceActionType | SocketAuthActionType | SocketChannelActionType | SocketChatActionType | SocketUserActionType | SocketPlaceActionType | SocketProfileActionType | SocketCloudActionType;
207
257
  /**
208
258
  * interface: `SocketActionTypeMap`
209
259
  * - domain to action type map
@@ -216,6 +266,8 @@ export interface SocketActionTypeMap {
216
266
  channel: SocketChannelActionType;
217
267
  chat: SocketChatActionType;
218
268
  user: SocketUserActionType;
269
+ place: SocketPlaceActionType;
270
+ profile: SocketProfileActionType;
219
271
  cloud: SocketCloudActionType;
220
272
  }
221
273
  /**