topsyde-utils 1.3.2 → 2.0.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 (148) hide show
  1. package/dist/index.d.ts +2 -43
  2. package/dist/index.js +1 -38
  3. package/dist/index.js.map +1 -1
  4. package/dist/utils/Lib.d.ts +0 -12
  5. package/dist/utils/Lib.js +0 -65
  6. package/dist/utils/Lib.js.map +1 -1
  7. package/dist/utils/index.d.ts +0 -3
  8. package/dist/utils/index.js +0 -3
  9. package/dist/utils/index.js.map +1 -1
  10. package/dist/websocket.shared.types.d.ts +25 -0
  11. package/dist/websocket.shared.types.js +4 -0
  12. package/dist/websocket.shared.types.js.map +1 -0
  13. package/package.json +12 -66
  14. package/src/__tests__/singleton.test.ts +0 -143
  15. package/src/index.ts +2 -83
  16. package/src/utils/Lib.ts +0 -77
  17. package/src/utils/index.ts +0 -3
  18. package/src/websocket.shared.types.ts +27 -0
  19. package/dist/application.d.ts +0 -18
  20. package/dist/application.js +0 -60
  21. package/dist/application.js.map +0 -1
  22. package/dist/client/api/base.api.d.ts +0 -63
  23. package/dist/client/api/base.api.js +0 -61
  24. package/dist/client/api/base.api.js.map +0 -1
  25. package/dist/client/api/index.d.ts +0 -2
  26. package/dist/client/api/index.js +0 -5
  27. package/dist/client/api/index.js.map +0 -1
  28. package/dist/client/rxjs/index.d.ts +0 -1
  29. package/dist/client/rxjs/index.js +0 -4
  30. package/dist/client/rxjs/index.js.map +0 -1
  31. package/dist/client/rxjs/useRxjs.d.ts +0 -17
  32. package/dist/client/rxjs/useRxjs.js +0 -87
  33. package/dist/client/rxjs/useRxjs.js.map +0 -1
  34. package/dist/client/vite/plugins/index.d.ts +0 -2
  35. package/dist/client/vite/plugins/index.js +0 -5
  36. package/dist/client/vite/plugins/index.js.map +0 -1
  37. package/dist/client/vite/plugins/topsydeUtilsVitePlugin.d.ts +0 -9
  38. package/dist/client/vite/plugins/topsydeUtilsVitePlugin.js +0 -74
  39. package/dist/client/vite/plugins/topsydeUtilsVitePlugin.js.map +0 -1
  40. package/dist/external/index.d.ts +0 -1
  41. package/dist/external/index.js +0 -4
  42. package/dist/external/index.js.map +0 -1
  43. package/dist/external/re-exports.d.ts +0 -16
  44. package/dist/external/re-exports.js +0 -24
  45. package/dist/external/re-exports.js.map +0 -1
  46. package/dist/server/base/base.database.d.ts +0 -10
  47. package/dist/server/base/base.database.js +0 -23
  48. package/dist/server/base/base.database.js.map +0 -1
  49. package/dist/server/base/index.d.ts +0 -2
  50. package/dist/server/base/index.js +0 -5
  51. package/dist/server/base/index.js.map +0 -1
  52. package/dist/server/bun/index.d.ts +0 -3
  53. package/dist/server/bun/index.js +0 -6
  54. package/dist/server/bun/index.js.map +0 -1
  55. package/dist/server/bun/router/controller-discovery.d.ts +0 -13
  56. package/dist/server/bun/router/controller-discovery.js +0 -83
  57. package/dist/server/bun/router/controller-discovery.js.map +0 -1
  58. package/dist/server/bun/router/index.d.ts +0 -6
  59. package/dist/server/bun/router/index.js +0 -9
  60. package/dist/server/bun/router/index.js.map +0 -1
  61. package/dist/server/bun/router/router.d.ts +0 -12
  62. package/dist/server/bun/router/router.internal.d.ts +0 -15
  63. package/dist/server/bun/router/router.internal.js +0 -51
  64. package/dist/server/bun/router/router.internal.js.map +0 -1
  65. package/dist/server/bun/router/router.js +0 -38
  66. package/dist/server/bun/router/router.js.map +0 -1
  67. package/dist/server/bun/router/routes.d.ts +0 -5
  68. package/dist/server/bun/router/routes.js +0 -2
  69. package/dist/server/bun/router/routes.js.map +0 -1
  70. package/dist/server/bun/websocket/Channel.d.ts +0 -68
  71. package/dist/server/bun/websocket/Channel.js +0 -263
  72. package/dist/server/bun/websocket/Channel.js.map +0 -1
  73. package/dist/server/bun/websocket/Client.d.ts +0 -87
  74. package/dist/server/bun/websocket/Client.js +0 -193
  75. package/dist/server/bun/websocket/Client.js.map +0 -1
  76. package/dist/server/bun/websocket/Message.d.ts +0 -10
  77. package/dist/server/bun/websocket/Message.js +0 -103
  78. package/dist/server/bun/websocket/Message.js.map +0 -1
  79. package/dist/server/bun/websocket/Websocket.d.ts +0 -171
  80. package/dist/server/bun/websocket/Websocket.js +0 -336
  81. package/dist/server/bun/websocket/Websocket.js.map +0 -1
  82. package/dist/server/bun/websocket/index.d.ts +0 -11
  83. package/dist/server/bun/websocket/index.js +0 -14
  84. package/dist/server/bun/websocket/index.js.map +0 -1
  85. package/dist/server/bun/websocket/websocket.enums.d.ts +0 -27
  86. package/dist/server/bun/websocket/websocket.enums.js +0 -31
  87. package/dist/server/bun/websocket/websocket.enums.js.map +0 -1
  88. package/dist/server/bun/websocket/websocket.guards.d.ts +0 -3
  89. package/dist/server/bun/websocket/websocket.guards.js +0 -17
  90. package/dist/server/bun/websocket/websocket.guards.js.map +0 -1
  91. package/dist/server/bun/websocket/websocket.types.d.ts +0 -235
  92. package/dist/server/bun/websocket/websocket.types.js +0 -2
  93. package/dist/server/bun/websocket/websocket.types.js.map +0 -1
  94. package/dist/server/controller.d.ts +0 -62
  95. package/dist/server/controller.js +0 -55
  96. package/dist/server/controller.js.map +0 -1
  97. package/dist/server/index.d.ts +0 -4
  98. package/dist/server/index.js +0 -7
  99. package/dist/server/index.js.map +0 -1
  100. package/dist/server/service.d.ts +0 -5
  101. package/dist/server/service.js +0 -38
  102. package/dist/server/service.js.map +0 -1
  103. package/dist/utils/BaseDto.d.ts +0 -33
  104. package/dist/utils/BaseDto.js +0 -69
  105. package/dist/utils/BaseDto.js.map +0 -1
  106. package/dist/utils/BaseEntity.d.ts +0 -31
  107. package/dist/utils/BaseEntity.js +0 -37
  108. package/dist/utils/BaseEntity.js.map +0 -1
  109. package/dist/utils/dto_validators/IsNumberOrRangeConstraint.d.ts +0 -9
  110. package/dist/utils/dto_validators/IsNumberOrRangeConstraint.js +0 -85
  111. package/dist/utils/dto_validators/IsNumberOrRangeConstraint.js.map +0 -1
  112. package/dist/utils/dto_validators/index.d.ts +0 -1
  113. package/dist/utils/dto_validators/index.js +0 -4
  114. package/dist/utils/dto_validators/index.js.map +0 -1
  115. package/src/__tests__/app.test.ts +0 -206
  116. package/src/application.ts +0 -73
  117. package/src/client/api/base.api.ts +0 -111
  118. package/src/client/api/index.ts +0 -5
  119. package/src/client/rxjs/index.ts +0 -4
  120. package/src/client/rxjs/useRxjs.ts +0 -113
  121. package/src/client/vite/plugins/index.ts +0 -5
  122. package/src/client/vite/plugins/topsydeUtilsVitePlugin.ts +0 -80
  123. package/src/external/index.ts +0 -4
  124. package/src/external/re-exports.ts +0 -54
  125. package/src/server/base/base.database.ts +0 -31
  126. package/src/server/base/index.ts +0 -5
  127. package/src/server/bun/index.ts +0 -6
  128. package/src/server/bun/router/controller-discovery.ts +0 -94
  129. package/src/server/bun/router/index.ts +0 -9
  130. package/src/server/bun/router/router.internal.ts +0 -64
  131. package/src/server/bun/router/router.ts +0 -51
  132. package/src/server/bun/router/routes.ts +0 -7
  133. package/src/server/bun/websocket/Channel.ts +0 -310
  134. package/src/server/bun/websocket/Client.ts +0 -243
  135. package/src/server/bun/websocket/ISSUES.md +0 -1175
  136. package/src/server/bun/websocket/Message.ts +0 -120
  137. package/src/server/bun/websocket/Websocket.ts +0 -402
  138. package/src/server/bun/websocket/index.ts +0 -14
  139. package/src/server/bun/websocket/websocket.enums.ts +0 -29
  140. package/src/server/bun/websocket/websocket.guards.ts +0 -22
  141. package/src/server/bun/websocket/websocket.types.ts +0 -252
  142. package/src/server/controller.ts +0 -121
  143. package/src/server/index.ts +0 -7
  144. package/src/server/service.ts +0 -36
  145. package/src/utils/BaseDto.ts +0 -77
  146. package/src/utils/BaseEntity.ts +0 -49
  147. package/src/utils/dto_validators/IsNumberOrRangeConstraint.ts +0 -32
  148. package/src/utils/dto_validators/index.ts +0 -4
@@ -1,235 +0,0 @@
1
- import { ServerWebSocket, WebSocketHandler } from "bun";
2
- import Channel from "./Channel";
3
- import Websocket from "./Websocket";
4
- import { E_ClientState } from "./websocket.enums";
5
- export type BunWebsocketMessage = string | Buffer<ArrayBufferLike>;
6
- export type WebsocketChannel<T extends I_WebsocketChannel = Channel> = Map<string, T>;
7
- export type WebsocketClients = Map<string, I_WebsocketClient>;
8
- export type WebsocketMessageOptions = {
9
- /**
10
- * Additional data to include in the message content
11
- * If an object is provided, it will be merged with the content
12
- * If a primitive value is provided, it will be added as content.data
13
- */
14
- data?: any;
15
- /**
16
- * Client information to include in the message
17
- * Will be added as content.client
18
- */
19
- client?: Partial<WebsocketEntityData> & {
20
- [key: string]: any;
21
- };
22
- /**
23
- * Channel metadata to include in the message
24
- * If true, all metadata will be included
25
- * If an array of strings, only the specified keys will be included
26
- */
27
- includeMetadata?: boolean | string[];
28
- /**
29
- * Client IDs to exclude from receiving the broadcast
30
- * Useful for sending messages to all clients except the sender
31
- */
32
- excludeClients?: string[];
33
- /**
34
- * Channel to include in the message
35
- * Defaults to the channel of the message
36
- */
37
- channel?: string;
38
- /**
39
- * Whether to include timestamp in the message
40
- * Defaults to true
41
- */
42
- includeTimestamp?: boolean;
43
- /**
44
- * Custom fields to add to the root of the message
45
- * These will be merged with the message object
46
- */
47
- customFields?: Record<string, any>;
48
- /**
49
- * Transform function to modify the final message before sending
50
- * This is applied after all other processing
51
- */
52
- transform?: (message: any) => any;
53
- /**
54
- * Priority of the message (higher numbers = higher priority)
55
- * Can be used by clients to determine processing order
56
- */
57
- priority?: number;
58
- /**
59
- * Message expiration time in milliseconds since epoch
60
- * Can be used by clients to ignore outdated messages
61
- */
62
- expiresAt?: number;
63
- /**
64
- * Metadata to include in the message
65
- * If an array of strings, only the specified keys will be included
66
- */
67
- metadata?: boolean | string[] | Record<string, string>;
68
- };
69
- export type WebsocketMessage<T extends Record<string, any> = Record<string, any>> = {
70
- /**
71
- * Message type identifier used for client-side routing
72
- */
73
- type: string;
74
- /**
75
- * Message content - can be any data structure
76
- * If a string is provided, it will be wrapped in {message: string}
77
- */
78
- content: T;
79
- /**
80
- * Channel ID
81
- */
82
- channel?: string;
83
- /**
84
- * Timestamp of the message
85
- */
86
- timestamp?: string;
87
- /**
88
- * Any additional custom fields
89
- */
90
- [key: string]: any;
91
- };
92
- /**
93
- * Message structure sent over the wire to clients.
94
- * This is the actual WebSocket payload format - transport options are NOT included.
95
- */
96
- export type WebsocketStructuredMessage<T extends Record<string, any> = Record<string, any>> = {
97
- /** Message type identifier for client-side routing */
98
- type: string;
99
- /** Message payload */
100
- content: T;
101
- /** Channel ID where message originated */
102
- channel?: string;
103
- /** ISO timestamp when message was created */
104
- timestamp?: string;
105
- /** Client information (who sent this) */
106
- client?: WebsocketEntityData;
107
- /** Channel metadata (if included) */
108
- metadata?: Record<string, string>;
109
- /** Message priority for client-side processing */
110
- priority?: number;
111
- /** Expiration timestamp (milliseconds since epoch) */
112
- expiresAt?: number;
113
- /** Any additional custom fields */
114
- [key: string]: any;
115
- };
116
- /**
117
- * @deprecated This type incorrectly mixed transport options with wire format.
118
- * Use WebsocketStructuredMessage for wire format and WebsocketMessageOptions for options.
119
- * This will be removed in a future version.
120
- */
121
- export type deprecated_WebsocketStructuredMessage<T extends Record<string, any> = Record<string, any>> = WebsocketMessage<T> & WebsocketMessageOptions;
122
- export type WebsocketEntityId = string;
123
- export type WebsocketEntityName = string;
124
- export type WebsocketEntityData = {
125
- id: WebsocketEntityId;
126
- name: WebsocketEntityName;
127
- };
128
- export interface I_WebsocketEntity extends WebsocketEntityData {
129
- ws: ServerWebSocket<WebsocketEntityData>;
130
- }
131
- export interface I_WebsocketClient extends I_WebsocketEntity {
132
- channels: WebsocketChannel<I_WebsocketChannel>;
133
- state: E_ClientState;
134
- send(message: string, options?: WebsocketMessageOptions): void;
135
- send(message: WebsocketStructuredMessage): void;
136
- subscribe(channel: string): any;
137
- trackChannel(channel: I_WebsocketChannel): void;
138
- untrackChannel(channel: I_WebsocketChannel): void;
139
- joinChannel(channel: I_WebsocketChannel, send?: boolean): {
140
- success: boolean;
141
- reason: string;
142
- };
143
- leaveChannel(channel: I_WebsocketChannel, send?: boolean): void;
144
- joinChannels(channels: I_WebsocketChannel[], send?: boolean): void;
145
- leaveChannels(channels?: I_WebsocketChannel[], send?: boolean): void;
146
- unsubscribe(channel: string): any;
147
- whoami(): WebsocketEntityData;
148
- canReceiveMessages(): boolean;
149
- markConnected(): void;
150
- markDisconnecting(): void;
151
- markDisconnected(): void;
152
- getConnectionInfo(): {
153
- id: string;
154
- name: string;
155
- state: E_ClientState;
156
- connectedAt?: Date;
157
- disconnectedAt?: Date;
158
- uptime: number;
159
- channelCount: number;
160
- };
161
- }
162
- export interface I_WebsocketChannelEntity<T extends Websocket = Websocket> extends WebsocketEntityData {
163
- ws: T;
164
- }
165
- export type BroadcastOptions = WebsocketMessageOptions & {
166
- debug?: boolean;
167
- };
168
- export type AddMemberResult = {
169
- success: true;
170
- client: I_WebsocketClient;
171
- } | {
172
- success: false;
173
- reason: "full" | "already_member" | "error";
174
- error?: Error;
175
- };
176
- export type AddMemberOptions = {
177
- /** Whether to notify client when channel is full (default: false) */
178
- notify_when_full?: boolean;
179
- /** Whether to send welcome notification to client on successful join (default: false) */
180
- notify?: boolean;
181
- };
182
- export type RemoveMemberOptions = {
183
- /** Whether to send goodbye notification to client on successful leave (default: false) */
184
- notify?: boolean;
185
- };
186
- export interface I_WebsocketChannel<T extends Websocket = Websocket> extends I_WebsocketChannelEntity<T> {
187
- limit: number;
188
- members: Map<string, I_WebsocketClient>;
189
- metadata: Record<string, string>;
190
- createdAt: Date;
191
- broadcast(message: WebsocketStructuredMessage | string, options?: BroadcastOptions): void;
192
- hasMember(client: I_WebsocketEntity | string): boolean;
193
- addMember(entity: I_WebsocketClient, options?: AddMemberOptions): AddMemberResult;
194
- removeFromMembersMap(entity: I_WebsocketClient): void;
195
- removeMember(entity: I_WebsocketEntity, options?: RemoveMemberOptions): I_WebsocketClient | false;
196
- getMember(client: I_WebsocketEntity | string): I_WebsocketClient | undefined;
197
- getMembers(clients?: string[] | I_WebsocketEntity[]): I_WebsocketClient[];
198
- getMetadata(): Record<string, string>;
199
- getCreatedAt(): Date;
200
- getId(): string;
201
- getSize(): number;
202
- getLimit(): number;
203
- getName(): string;
204
- canAddMember(): boolean;
205
- }
206
- /**
207
- * Interface for implementing custom WebSocket behavior.
208
- *
209
- * @interface I_WebsocketInterface
210
- *
211
- * @property {Function} setup - Initializes the WebSocket handler with channels and clients
212
- *
213
- * The interface supports three optional handler methods:
214
- *
215
- * - `message`: Custom message handler that replaces the default handler
216
- * - `open`: Connection handler that runs after the default open handler
217
- * - `close`: Disconnection handler that runs before the default close handler
218
- */
219
- export type WebsocketInterfaceHandlers = Partial<WebSocketHandler<WebsocketEntityData>>;
220
- /**
221
- * Interface for implementing custom WebSocket behavior.
222
- *
223
- * @interface I_WebsocketInterface
224
- *
225
- * @property {Function} setup - Initializes the WebSocket handler with channels and clients
226
- *
227
- * The interface supports three optional handler methods:
228
- *
229
- * - `message`: Custom message handler that replaces the default handler
230
- * - `open`: Connection handler that runs after the default open handler
231
- * - `close`: Disconnection handler that runs before the default close handler
232
- */
233
- export interface I_WebsocketInterface {
234
- handlers: (channels: WebsocketChannel, clients: WebsocketClients) => WebsocketInterfaceHandlers;
235
- }
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=websocket.types.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"websocket.types.js","sourceRoot":"","sources":["../../../../src/server/bun/websocket/websocket.types.ts"],"names":[],"mappings":"","sourcesContent":["import { ServerWebSocket, WebSocketHandler } from \"bun\";\nimport Channel from \"./Channel\";\nimport Websocket from \"./Websocket\";\nimport { E_ClientState } from \"./websocket.enums\";\n\nexport type BunWebsocketMessage = string | Buffer<ArrayBufferLike>;\n\nexport type WebsocketChannel<T extends I_WebsocketChannel = Channel> = Map<string, T>;\nexport type WebsocketClients = Map<string, I_WebsocketClient>;\nexport type WebsocketMessageOptions = {\n\t/**\n\t * Additional data to include in the message content\n\t * If an object is provided, it will be merged with the content\n\t * If a primitive value is provided, it will be added as content.data\n\t */\n\tdata?: any;\n\n\t/**\n\t * Client information to include in the message\n\t * Will be added as content.client\n\t */\n\tclient?: Partial<WebsocketEntityData> & {\n\t\t[key: string]: any;\n\t};\n\n\t/**\n\t * Channel metadata to include in the message\n\t * If true, all metadata will be included\n\t * If an array of strings, only the specified keys will be included\n\t */\n\tincludeMetadata?: boolean | string[];\n\n\t/**\n\t * Client IDs to exclude from receiving the broadcast\n\t * Useful for sending messages to all clients except the sender\n\t */\n\texcludeClients?: string[];\n\n\t/**\n\t * Channel to include in the message\n\t * Defaults to the channel of the message\n\t */\n\tchannel?: string;\n\n\t/**\n\t * Whether to include timestamp in the message\n\t * Defaults to true\n\t */\n\tincludeTimestamp?: boolean;\n\n\t/**\n\t * Custom fields to add to the root of the message\n\t * These will be merged with the message object\n\t */\n\tcustomFields?: Record<string, any>;\n\n\t/**\n\t * Transform function to modify the final message before sending\n\t * This is applied after all other processing\n\t */\n\ttransform?: (message: any) => any;\n\n\t/**\n\t * Priority of the message (higher numbers = higher priority)\n\t * Can be used by clients to determine processing order\n\t */\n\tpriority?: number;\n\n\t/**\n\t * Message expiration time in milliseconds since epoch\n\t * Can be used by clients to ignore outdated messages\n\t */\n\texpiresAt?: number;\n\n\t/**\n\t * Metadata to include in the message\n\t * If an array of strings, only the specified keys will be included\n\t */\n\tmetadata?: boolean | string[] | Record<string, string>;\n};\n\nexport type WebsocketMessage<T extends Record<string, any> = Record<string, any>> = {\n\t/**\n\t * Message type identifier used for client-side routing\n\t */\n\ttype: string;\n\t/**\n\t * Message content - can be any data structure\n\t * If a string is provided, it will be wrapped in {message: string}\n\t */\n\tcontent: T;\n\t/**\n\t * Channel ID\n\t */\n\tchannel?: string;\n\t/**\n\t * Timestamp of the message\n\t */\n\ttimestamp?: string;\n\t/**\n\t * Any additional custom fields\n\t */\n\t[key: string]: any;\n};\n\n/**\n * Message structure sent over the wire to clients.\n * This is the actual WebSocket payload format - transport options are NOT included.\n */\nexport type WebsocketStructuredMessage<T extends Record<string, any> = Record<string, any>> = {\n\t/** Message type identifier for client-side routing */\n\ttype: string;\n\n\t/** Message payload */\n\tcontent: T;\n\n\t/** Channel ID where message originated */\n\tchannel?: string;\n\n\t/** ISO timestamp when message was created */\n\ttimestamp?: string;\n\n\t/** Client information (who sent this) */\n\tclient?: WebsocketEntityData;\n\n\t/** Channel metadata (if included) */\n\tmetadata?: Record<string, string>;\n\n\t/** Message priority for client-side processing */\n\tpriority?: number;\n\n\t/** Expiration timestamp (milliseconds since epoch) */\n\texpiresAt?: number;\n\n\t/** Any additional custom fields */\n\t[key: string]: any;\n};\n\n/**\n * @deprecated This type incorrectly mixed transport options with wire format.\n * Use WebsocketStructuredMessage for wire format and WebsocketMessageOptions for options.\n * This will be removed in a future version.\n */\nexport type deprecated_WebsocketStructuredMessage<T extends Record<string, any> = Record<string, any>> = WebsocketMessage<T> & WebsocketMessageOptions;\n\nexport type WebsocketEntityId = string;\nexport type WebsocketEntityName = string;\nexport type WebsocketEntityData = { id: WebsocketEntityId; name: WebsocketEntityName };\n\nexport interface I_WebsocketEntity extends WebsocketEntityData {\n\tws: ServerWebSocket<WebsocketEntityData>;\n}\n\nexport interface I_WebsocketClient extends I_WebsocketEntity {\n\tchannels: WebsocketChannel<I_WebsocketChannel>;\n\tstate: E_ClientState;\n\tsend(message: string, options?: WebsocketMessageOptions): void;\n\tsend(message: WebsocketStructuredMessage): void;\n\tsubscribe(channel: string): any;\n\ttrackChannel(channel: I_WebsocketChannel): void;\n\tuntrackChannel(channel: I_WebsocketChannel): void;\n\tjoinChannel(channel: I_WebsocketChannel, send?: boolean): { success: boolean; reason: string };\n\tleaveChannel(channel: I_WebsocketChannel, send?: boolean): void;\n\tjoinChannels(channels: I_WebsocketChannel[], send?: boolean): void;\n\tleaveChannels(channels?: I_WebsocketChannel[], send?: boolean): void;\n\tunsubscribe(channel: string): any;\n\twhoami(): WebsocketEntityData;\n\tcanReceiveMessages(): boolean;\n\tmarkConnected(): void;\n\tmarkDisconnecting(): void;\n\tmarkDisconnected(): void;\n\tgetConnectionInfo(): { id: string; name: string; state: E_ClientState; connectedAt?: Date; disconnectedAt?: Date; uptime: number; channelCount: number };\n}\n\nexport interface I_WebsocketChannelEntity<T extends Websocket = Websocket> extends WebsocketEntityData {\n\tws: T;\n}\n\n// New types for the broadcast method\nexport type BroadcastOptions = WebsocketMessageOptions & {\n\tdebug?: boolean;\n};\n\n// Result type for addMember operations\nexport type AddMemberResult = { success: true; client: I_WebsocketClient } | { success: false; reason: \"full\" | \"already_member\" | \"error\"; error?: Error };\n\n// Options for addMember operations\nexport type AddMemberOptions = {\n\t/** Whether to notify client when channel is full (default: false) */\n\tnotify_when_full?: boolean;\n\t/** Whether to send welcome notification to client on successful join (default: false) */\n\tnotify?: boolean;\n};\n\n// Options for removeMember operations\nexport type RemoveMemberOptions = {\n\t/** Whether to send goodbye notification to client on successful leave (default: false) */\n\tnotify?: boolean;\n};\n\nexport interface I_WebsocketChannel<T extends Websocket = Websocket> extends I_WebsocketChannelEntity<T> {\n\tlimit: number;\n\tmembers: Map<string, I_WebsocketClient>;\n\tmetadata: Record<string, string>;\n\tcreatedAt: Date;\n\tbroadcast(message: WebsocketStructuredMessage | string, options?: BroadcastOptions): void;\n\thasMember(client: I_WebsocketEntity | string): boolean;\n\taddMember(entity: I_WebsocketClient, options?: AddMemberOptions): AddMemberResult;\n\tremoveFromMembersMap(entity: I_WebsocketClient): void;\n\tremoveMember(entity: I_WebsocketEntity, options?: RemoveMemberOptions): I_WebsocketClient | false;\n\tgetMember(client: I_WebsocketEntity | string): I_WebsocketClient | undefined;\n\tgetMembers(clients?: string[] | I_WebsocketEntity[]): I_WebsocketClient[];\n\tgetMetadata(): Record<string, string>;\n\tgetCreatedAt(): Date;\n\tgetId(): string;\n\tgetSize(): number;\n\tgetLimit(): number;\n\tgetName(): string;\n\tcanAddMember(): boolean;\n}\n\n/**\n * Interface for implementing custom WebSocket behavior.\n *\n * @interface I_WebsocketInterface\n *\n * @property {Function} setup - Initializes the WebSocket handler with channels and clients\n *\n * The interface supports three optional handler methods:\n *\n * - `message`: Custom message handler that replaces the default handler\n * - `open`: Connection handler that runs after the default open handler\n * - `close`: Disconnection handler that runs before the default close handler\n */\nexport type WebsocketInterfaceHandlers = Partial<WebSocketHandler<WebsocketEntityData>>;\n\n/**\n * Interface for implementing custom WebSocket behavior.\n *\n * @interface I_WebsocketInterface\n *\n * @property {Function} setup - Initializes the WebSocket handler with channels and clients\n *\n * The interface supports three optional handler methods:\n *\n * - `message`: Custom message handler that replaces the default handler\n * - `open`: Connection handler that runs after the default open handler\n * - `close`: Disconnection handler that runs before the default close handler\n */\nexport interface I_WebsocketInterface {\n\thandlers: (channels: WebsocketChannel, clients: WebsocketClients) => WebsocketInterfaceHandlers;\n}\n"]}
@@ -1,62 +0,0 @@
1
- import Initializable, { InitializableOptions } from "../initializable";
2
- import { I_ApplicationResponse } from "../types";
3
- export type ControllerResponse<T = unknown> = Promise<I_ApplicationResponse<T> | PromiseLike<I_ApplicationResponse<T>>>;
4
- export type ControllerAction<T> = (req: Request) => ControllerResponse<T>;
5
- export type ControllerMap<T = unknown> = Map<string, ControllerAction<T>>;
6
- export type ControllerOptions<T = unknown> = InitializableOptions & {
7
- path: string | undefined;
8
- post: Map<string, ControllerAction<T>>;
9
- get: ControllerMap<T>;
10
- controllerMap: Map<string, ControllerMap<T>>;
11
- };
12
- export default abstract class Controller extends Initializable {
13
- path: string | undefined;
14
- post: Map<string, ControllerAction<any>>;
15
- get: ControllerMap;
16
- controllerMap: Map<string, ControllerMap>;
17
- constructor();
18
- static Create<T>(this: new () => T): T;
19
- static AsyncCreate<T>(this: new () => T): Promise<T>;
20
- call<T>(request: Request): Promise<T>;
21
- success<T>(data: T, after_action?: () => void | Promise<void>): I_ApplicationResponse<T>;
22
- failure<T>(data: T, after_action?: () => void | Promise<void>): I_ApplicationResponse<T>;
23
- private setControllerMap;
24
- private resolve;
25
- private resolveAction;
26
- /**
27
- * Abstract method that needs to be implemented in derived classes.
28
- * This method is used to map post actions to their corresponding handler methods.
29
- *
30
- * Each action is a string that represents a specific operation, and the handler is a function that performs this operation.
31
- * The handler is bound to the current context (`this`) to ensure it has access to the class's properties and methods.
32
- *
33
- * Example implementation:
34
- *
35
- * ```typescript
36
- * setActionsMap() {
37
- * this.post.set("action", this.controllerMethod.bind(this));
38
- * }
39
- * ```
40
- *
41
- * In this example, when "https://webserver_url:port/controller/action" is called by the router, the `controllerMethod` method will be called.
42
- */
43
- abstract POST(): void;
44
- /**
45
- * Abstract method that needs to be implemented in derived classes.
46
- * This method is used to map actions to their corresponding handler methods.
47
- *
48
- * Each action is a string that represents a specific operation, and the handler is a function that performs this operation.
49
- * The handler is bound to the current context (`this`) to ensure it has access to the class's properties and methods.
50
- *
51
- * Example implementation:
52
- *
53
- * ```typescript
54
- * setActionsMap() {
55
- * this.get.set("action", this.controllerMethod.bind(this));
56
- * }
57
- * ```
58
- *
59
- * In this example, when "https://webserver_url:port/controller/action" is called by the router, the `controllerMethod` method will be called.
60
- */
61
- abstract GET(): void;
62
- }
@@ -1,55 +0,0 @@
1
- import { ERROR_CODE } from "../errors.js";
2
- import Initializable from "../initializable.js";
3
- import { Guards } from "../utils/index.js";
4
- export default class Controller extends Initializable {
5
- constructor() {
6
- super();
7
- this.post = new Map();
8
- this.get = new Map();
9
- this.controllerMap = new Map();
10
- this.POST();
11
- this.GET();
12
- this.setControllerMap();
13
- }
14
- static Create() {
15
- return new this();
16
- }
17
- static async AsyncCreate() {
18
- return new this();
19
- }
20
- async call(request) {
21
- await this.isInitialized();
22
- const action = this.resolve(request);
23
- return await action(request);
24
- }
25
- success(data, after_action) {
26
- return { status: true, data, after_action };
27
- }
28
- failure(data, after_action) {
29
- return { status: false, data, after_action };
30
- }
31
- setControllerMap() {
32
- this.controllerMap.set("GET", this.get);
33
- this.controllerMap.set("POST", this.post);
34
- }
35
- resolve(req) {
36
- const url = new URL(req.url);
37
- const endpointArray = url.pathname.split("/");
38
- const actionName = endpointArray.slice(2).join("/");
39
- if (!Guards.IsString(actionName, true))
40
- throw ERROR_CODE.INVALID_ACTION;
41
- const methodMap = this.controllerMap.get(req.method);
42
- if (Guards.IsNil(methodMap)) {
43
- throw ERROR_CODE.INVALID_METHOD;
44
- }
45
- return this.resolveAction(methodMap, actionName);
46
- }
47
- resolveAction(methodMap, actionName) {
48
- const action = methodMap.get(actionName);
49
- if (!Guards.IsFunction(action, true)) {
50
- throw ERROR_CODE.NO_ACTION_IN_MAP;
51
- }
52
- return action;
53
- }
54
- }
55
- //# sourceMappingURL=controller.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"controller.js","sourceRoot":"","sources":["../../src/server/controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,aAAuC,MAAM,kBAAkB,CAAC;AAEvE,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAclC,MAAM,CAAC,OAAO,OAAgB,UAAW,SAAQ,aAAa;IAM7D;QACC,KAAK,EAAE,CAAC;QALT,SAAI,GAAuC,IAAI,GAAG,EAAE,CAAC;QACrD,QAAG,GAAkB,IAAI,GAAG,EAAE,CAAC;QAC/B,kBAAa,GAA+B,IAAI,GAAG,EAAE,CAAC;QAIrD,IAAI,CAAC,IAAI,EAAE,CAAC;QACZ,IAAI,CAAC,GAAG,EAAE,CAAC;QACX,IAAI,CAAC,gBAAgB,EAAE,CAAC;IACzB,CAAC;IAEM,MAAM,CAAC,MAAM;QACnB,OAAO,IAAI,IAAI,EAAE,CAAC;IACnB,CAAC;IAEM,MAAM,CAAC,KAAK,CAAC,WAAW;QAC9B,OAAO,IAAI,IAAI,EAAE,CAAC;IACnB,CAAC;IAEM,KAAK,CAAC,IAAI,CAAI,OAAgB;QACpC,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACrC,OAAO,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;IAEM,OAAO,CAAI,IAAO,EAAE,YAAyC;QACnE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;IAC7C,CAAC;IAEM,OAAO,CAAI,IAAO,EAAE,YAAyC;QACnE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;IAC9C,CAAC;IAEO,gBAAgB;QACvB,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QACxC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3C,CAAC;IAEO,OAAO,CAAC,GAAY;QAC3B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC7B,MAAM,aAAa,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC9C,MAAM,UAAU,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEpD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC;YAAE,MAAM,UAAU,CAAC,cAAc,CAAC;QAExE,MAAM,SAAS,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAErD,IAAI,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7B,MAAM,UAAU,CAAC,cAAc,CAAC;QACjC,CAAC;QAED,OAAO,IAAI,CAAC,aAAa,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAClD,CAAC;IAEO,aAAa,CAAC,SAAwB,EAAE,UAAkB;QACjE,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,UAAU,CAAa,CAAC;QAErD,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC;YACtC,MAAM,UAAU,CAAC,gBAAgB,CAAC;QACnC,CAAC;QAED,OAAO,MAAM,CAAC;IACf,CAAC;CAuCD","sourcesContent":["import { ERROR_CODE } from \"../errors\";\nimport Initializable, { InitializableOptions } from \"../initializable\";\nimport { I_ApplicationResponse } from \"../types\";\nimport { Guards } from \"../utils\";\n\nexport type ControllerResponse<T = unknown> = Promise<I_ApplicationResponse<T> | PromiseLike<I_ApplicationResponse<T>>>;\nexport type ControllerAction<T> = (req: Request) => ControllerResponse<T>;\n\nexport type ControllerMap<T = unknown> = Map<string, ControllerAction<T>>;\n\nexport type ControllerOptions<T = unknown> = InitializableOptions & {\n\tpath: string | undefined;\n\tpost: Map<string, ControllerAction<T>>;\n\tget: ControllerMap<T>;\n\tcontrollerMap: Map<string, ControllerMap<T>>;\n};\n\nexport default abstract class Controller extends Initializable {\n\tpath: string | undefined;\n\tpost: Map<string, ControllerAction<any>> = new Map();\n\tget: ControllerMap = new Map();\n\tcontrollerMap: Map<string, ControllerMap> = new Map();\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis.POST();\n\t\tthis.GET();\n\t\tthis.setControllerMap();\n\t}\n\n\tpublic static Create<T>(this: new () => T): T {\n\t\treturn new this();\n\t}\n\n\tpublic static async AsyncCreate<T>(this: new () => T): Promise<T> {\n\t\treturn new this();\n\t}\n\n\tpublic async call<T>(request: Request): Promise<T> {\n\t\tawait this.isInitialized();\n\t\tconst action = this.resolve(request);\n\t\treturn await action(request);\n\t}\n\n\tpublic success<T>(data: T, after_action?: () => void | Promise<void>): I_ApplicationResponse<T> {\n\t\treturn { status: true, data, after_action };\n\t}\n\n\tpublic failure<T>(data: T, after_action?: () => void | Promise<void>): I_ApplicationResponse<T> {\n\t\treturn { status: false, data, after_action };\n\t}\n\n\tprivate setControllerMap() {\n\t\tthis.controllerMap.set(\"GET\", this.get);\n\t\tthis.controllerMap.set(\"POST\", this.post);\n\t}\n\n\tprivate resolve(req: Request): Function {\n\t\tconst url = new URL(req.url);\n\t\tconst endpointArray = url.pathname.split(\"/\");\n\t\tconst actionName = endpointArray.slice(2).join(\"/\");\n\n\t\tif (!Guards.IsString(actionName, true)) throw ERROR_CODE.INVALID_ACTION;\n\n\t\tconst methodMap = this.controllerMap.get(req.method);\n\n\t\tif (Guards.IsNil(methodMap)) {\n\t\t\tthrow ERROR_CODE.INVALID_METHOD;\n\t\t}\n\n\t\treturn this.resolveAction(methodMap, actionName);\n\t}\n\n\tprivate resolveAction(methodMap: ControllerMap, actionName: string) {\n\t\tconst action = methodMap.get(actionName) as Function;\n\n\t\tif (!Guards.IsFunction(action, true)) {\n\t\t\tthrow ERROR_CODE.NO_ACTION_IN_MAP;\n\t\t}\n\n\t\treturn action;\n\t}\n\n\t/**\n\t * Abstract method that needs to be implemented in derived classes.\n\t * This method is used to map post actions to their corresponding handler methods.\n\t *\n\t * Each action is a string that represents a specific operation, and the handler is a function that performs this operation.\n\t * The handler is bound to the current context (`this`) to ensure it has access to the class's properties and methods.\n\t *\n\t * Example implementation:\n\t *\n\t * ```typescript\n\t * setActionsMap() {\n\t * this.post.set(\"action\", this.controllerMethod.bind(this));\n\t * }\n\t * ```\n\t *\n\t * In this example, when \"https://webserver_url:port/controller/action\" is called by the router, the `controllerMethod` method will be called.\n\t */\n\tabstract POST(): void;\n\n\t/**\n\t * Abstract method that needs to be implemented in derived classes.\n\t * This method is used to map actions to their corresponding handler methods.\n\t *\n\t * Each action is a string that represents a specific operation, and the handler is a function that performs this operation.\n\t * The handler is bound to the current context (`this`) to ensure it has access to the class's properties and methods.\n\t *\n\t * Example implementation:\n\t *\n\t * ```typescript\n\t * setActionsMap() {\n\t * this.get.set(\"action\", this.controllerMethod.bind(this));\n\t * }\n\t * ```\n\t *\n\t * In this example, when \"https://webserver_url:port/controller/action\" is called by the router, the `controllerMethod` method will be called.\n\t */\n\tabstract GET(): void;\n}\n"]}
@@ -1,4 +0,0 @@
1
- export * from './controller';
2
- export * from './service';
3
- export { default as Controller } from './controller';
4
- export { default as Service } from './service';
@@ -1,7 +0,0 @@
1
- // This file is auto-generated by scripts/generate-indexes.ts
2
- // Do not edit this file directly
3
- export * from './controller.js';
4
- export * from './service.js';
5
- export { default as Controller } from './controller.js';
6
- export { default as Service } from './service.js';
7
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,iCAAiC;AAEjC,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,WAAW,CAAC","sourcesContent":["// This file is auto-generated by scripts/generate-indexes.ts\n// Do not edit this file directly\n\nexport * from './controller';\nexport * from './service';\nexport { default as Controller } from './controller';\nexport { default as Service } from './service';\n"]}
@@ -1,5 +0,0 @@
1
- import Initializable from "../initializable";
2
- export default abstract class Service extends Initializable {
3
- validateRequestBody<T>(request: Request, keys: (keyof T)[]): Promise<T>;
4
- static validateRequestBody<T>(request: Request, keys: (keyof T)[]): Promise<T>;
5
- }
@@ -1,38 +0,0 @@
1
- import { ERROR_CODE } from "../errors.js";
2
- import Initializable from "../initializable.js";
3
- import { Guards } from "../utils/index.js";
4
- export default class Service extends Initializable {
5
- async validateRequestBody(request, keys) {
6
- return await Service.validateRequestBody(request, keys);
7
- }
8
- static async validateRequestBody(request, keys) {
9
- try {
10
- let body;
11
- try {
12
- body = await request.json();
13
- }
14
- catch (e) {
15
- body = await request.text();
16
- const cleanedBody = body
17
- .replace(/\/\/.*$/gm, "") // Remove comments
18
- .replace(/\n/g, "") // Remove newlines
19
- .replace(/\s+/g, " ") // Replace multiple spaces with single space
20
- .trim(); // Remove leading/trailing whitespace
21
- body = JSON.parse(cleanedBody);
22
- }
23
- if (Guards.IsNil(body))
24
- throw ERROR_CODE.REQ_BODY_EMPTY;
25
- if (!Guards.IsType(body, keys)) {
26
- console.error(`Expected keys: ${keys.join(", ")}`);
27
- throw ERROR_CODE.INVALID_METHOD_INPUT;
28
- }
29
- return body;
30
- }
31
- catch (e) {
32
- if (e instanceof Error || e instanceof SyntaxError)
33
- throw "Could not parse request body: " + e;
34
- throw e;
35
- }
36
- }
37
- }
38
- //# sourceMappingURL=service.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/server/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,aAAa,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,MAAM,CAAC,OAAO,OAAgB,OAAQ,SAAQ,aAAa;IAC1D,KAAK,CAAC,mBAAmB,CAAI,OAAgB,EAAE,IAAiB;QAC/D,OAAO,MAAM,OAAO,CAAC,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACzD,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAI,OAAgB,EAAE,IAAiB;QACtE,IAAI,CAAC;YACJ,IAAI,IAAI,CAAC;YACT,IAAI,CAAC;gBACJ,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;YAC7B,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACZ,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;gBAC5B,MAAM,WAAW,GAAG,IAAI;qBACtB,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,kBAAkB;qBAC3C,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,kBAAkB;qBACrC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,4CAA4C;qBACjE,IAAI,EAAE,CAAC,CAAC,qCAAqC;gBAE/C,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;YAChC,CAAC;YACD,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;gBAAE,MAAM,UAAU,CAAC,cAAc,CAAC;YACxD,IAAI,CAAC,MAAM,CAAC,MAAM,CAAI,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;gBACnC,OAAO,CAAC,KAAK,CAAC,kBAAkB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACnD,MAAM,UAAU,CAAC,oBAAoB,CAAC;YACvC,CAAC;YACD,OAAO,IAAI,CAAC;QACb,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACZ,IAAI,CAAC,YAAY,KAAK,IAAI,CAAC,YAAY,WAAW;gBAAE,MAAM,gCAAgC,GAAG,CAAC,CAAC;YAC/F,MAAM,CAAC,CAAC;QACT,CAAC;IACF,CAAC;CACD","sourcesContent":["import { ERROR_CODE } from \"../errors\";\nimport Initializable from \"../initializable\";\nimport { Guards } from \"../utils\";\n\nexport default abstract class Service extends Initializable {\n\tasync validateRequestBody<T>(request: Request, keys: (keyof T)[]): Promise<T> {\n\t\treturn await Service.validateRequestBody(request, keys);\n\t}\n\n\tstatic async validateRequestBody<T>(request: Request, keys: (keyof T)[]): Promise<T> {\n\t\ttry {\n\t\t\tlet body;\n\t\t\ttry {\n\t\t\t\tbody = await request.json();\n\t\t\t} catch (e) {\n\t\t\t\tbody = await request.text();\n\t\t\t\tconst cleanedBody = body\n\t\t\t\t\t.replace(/\\/\\/.*$/gm, \"\") // Remove comments\n\t\t\t\t\t.replace(/\\n/g, \"\") // Remove newlines\n\t\t\t\t\t.replace(/\\s+/g, \" \") // Replace multiple spaces with single space\n\t\t\t\t\t.trim(); // Remove leading/trailing whitespace\n\n\t\t\t\tbody = JSON.parse(cleanedBody);\n\t\t\t}\n\t\t\tif (Guards.IsNil(body)) throw ERROR_CODE.REQ_BODY_EMPTY;\n\t\t\tif (!Guards.IsType<T>(body, keys)) {\n\t\t\t\tconsole.error(`Expected keys: ${keys.join(\", \")}`);\n\t\t\t\tthrow ERROR_CODE.INVALID_METHOD_INPUT;\n\t\t\t}\n\t\t\treturn body;\n\t\t} catch (e) {\n\t\t\tif (e instanceof Error || e instanceof SyntaxError) throw \"Could not parse request body: \" + e;\n\t\t\tthrow e;\n\t\t}\n\t}\n}\n"]}
@@ -1,33 +0,0 @@
1
- import type { ClassConstructor, ClassTransformOptions } from "class-transformer";
2
- import { ValidationError } from "class-validator";
3
- /**
4
- * Base typesafe class for Data Transfer Objects (DTOs)
5
- */
6
- export declare abstract class Dto {
7
- /**
8
- * Default options for class transformation
9
- */
10
- protected static readonly defaultTransformOptions: ClassTransformOptions;
11
- /**
12
- * Validates the DTO instance
13
- * @throws ValidationError[] if validation fails
14
- */
15
- validate(): ValidationError[];
16
- /**
17
- * Converts the DTO to a plain object
18
- * @param options - Class transformer options for controlling exposure and transformation
19
- * @returns Plain object representation of the DTO
20
- */
21
- toJSON<T = Record<string, unknown>>(include_undefined?: boolean, options?: ClassTransformOptions): T;
22
- /**
23
- * Creates a new instance of the DTO with validation (infers class from `this`)
24
- * @param data - Data to create the DTO from
25
- * @param options - Class transformer options
26
- * @returns New instance of the DTO
27
- */
28
- static Create<T extends Dto>(this: ClassConstructor<T>, data: Record<string, unknown>, options?: ClassTransformOptions): T;
29
- /**
30
- * Creates an array of DTOs from an array of plain objects
31
- */
32
- static CreateMany<T extends Dto>(this: ClassConstructor<T>, dataArray: Record<string, unknown>[], options?: ClassTransformOptions): T[];
33
- }
@@ -1,69 +0,0 @@
1
- import { instanceToPlain, plainToInstance } from "class-transformer";
2
- import Guards from "./Guards.js";
3
- import { validateSync } from "class-validator";
4
- /**
5
- * Base typesafe class for Data Transfer Objects (DTOs)
6
- */
7
- export class Dto {
8
- /**
9
- * Validates the DTO instance
10
- * @throws ValidationError[] if validation fails
11
- */
12
- validate() {
13
- const errors = validateSync(this, {
14
- validationError: { target: false },
15
- forbidUnknownValues: true,
16
- });
17
- if (errors.length > 0) {
18
- throw errors;
19
- }
20
- return errors;
21
- }
22
- /**
23
- * Converts the DTO to a plain object
24
- * @param options - Class transformer options for controlling exposure and transformation
25
- * @returns Plain object representation of the DTO
26
- */
27
- toJSON(include_undefined = true, options) {
28
- const value = instanceToPlain(this, {
29
- ...Dto.defaultTransformOptions,
30
- ...options,
31
- });
32
- if (!include_undefined) {
33
- return Object.fromEntries(Object.entries(value).filter(([_, v]) => !Guards.IsNil(v)));
34
- }
35
- return value;
36
- }
37
- /**
38
- * Creates a new instance of the DTO with validation (infers class from `this`)
39
- * @param data - Data to create the DTO from
40
- * @param options - Class transformer options
41
- * @returns New instance of the DTO
42
- */
43
- static Create(data, options = {}) {
44
- const instance = plainToInstance(this, data, {
45
- ...Dto.defaultTransformOptions,
46
- ...options,
47
- });
48
- return instance;
49
- }
50
- /**
51
- * Creates an array of DTOs from an array of plain objects
52
- */
53
- static CreateMany(dataArray, options = {}) {
54
- return plainToInstance(this, dataArray, {
55
- ...Dto.defaultTransformOptions,
56
- ...options,
57
- });
58
- }
59
- }
60
- /**
61
- * Default options for class transformation
62
- */
63
- Dto.defaultTransformOptions = {
64
- excludeExtraneousValues: true,
65
- enableCircularCheck: true,
66
- exposeDefaultValues: true,
67
- enableImplicitConversion: false, // Safer default, especially when using class-validator
68
- };
69
- //# sourceMappingURL=BaseDto.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"BaseDto.js","sourceRoot":"","sources":["../../src/utils/BaseDto.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACrE,OAAO,MAAM,MAAM,UAAU,CAAC;AAC9B,OAAO,EAAmB,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEhE;;GAEG;AACH,MAAM,OAAgB,GAAG;IAWxB;;;OAGG;IACI,QAAQ;QACd,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,EAAE;YACjC,eAAe,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE;YAClC,mBAAmB,EAAE,IAAI;SACzB,CAAC,CAAC;QACH,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,MAAM,MAAM,CAAC;QACd,CAAC;QACD,OAAO,MAAM,CAAC;IACf,CAAC;IAED;;;;OAIG;IACI,MAAM,CAA8B,oBAA6B,IAAI,EAAE,OAA+B;QAC5G,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,EAAE;YACnC,GAAG,GAAG,CAAC,uBAAuB;YAC9B,GAAG,OAAO;SACV,CAAM,CAAC;QAER,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACxB,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAM,CAAC;QACvH,CAAC;QAED,OAAO,KAAK,CAAC;IACd,CAAC;IAED;;;;;OAKG;IACI,MAAM,CAAC,MAAM,CAA2C,IAA6B,EAAE,UAAiC,EAAE;QAChI,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE;YAC5C,GAAG,GAAG,CAAC,uBAAuB;YAC9B,GAAG,OAAO;SACV,CAAC,CAAC;QAEH,OAAO,QAAQ,CAAC;IACjB,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,UAAU,CAA2C,SAAoC,EAAE,UAAiC,EAAE;QAC3I,OAAO,eAAe,CAAC,IAAI,EAAE,SAAS,EAAE;YACvC,GAAG,GAAG,CAAC,uBAAuB;YAC9B,GAAG,OAAO;SACV,CAAQ,CAAC;IACX,CAAC;;AAlED;;GAEG;AACuB,2BAAuB,GAA0B;IAC1E,uBAAuB,EAAE,IAAI;IAC7B,mBAAmB,EAAE,IAAI;IACzB,mBAAmB,EAAE,IAAI;IACzB,wBAAwB,EAAE,KAAK,EAAE,uDAAuD;CACxF,CAAC","sourcesContent":["import type { ClassConstructor, ClassTransformOptions } from \"class-transformer\";\nimport { instanceToPlain, plainToInstance } from \"class-transformer\";\nimport Guards from \"./Guards\";\nimport { ValidationError, validateSync } from \"class-validator\";\n\n/**\n * Base typesafe class for Data Transfer Objects (DTOs)\n */\nexport abstract class Dto {\n\t/**\n\t * Default options for class transformation\n\t */\n\tprotected static readonly defaultTransformOptions: ClassTransformOptions = {\n\t\texcludeExtraneousValues: true,\n\t\tenableCircularCheck: true,\n\t\texposeDefaultValues: true,\n\t\tenableImplicitConversion: false, // Safer default, especially when using class-validator\n\t};\n\n\t/**\n\t * Validates the DTO instance\n\t * @throws ValidationError[] if validation fails\n\t */\n\tpublic validate(): ValidationError[] {\n\t\tconst errors = validateSync(this, {\n\t\t\tvalidationError: { target: false },\n\t\t\tforbidUnknownValues: true,\n\t\t});\n\t\tif (errors.length > 0) {\n\t\t\tthrow errors;\n\t\t}\n\t\treturn errors;\n\t}\n\n\t/**\n\t * Converts the DTO to a plain object\n\t * @param options - Class transformer options for controlling exposure and transformation\n\t * @returns Plain object representation of the DTO\n\t */\n\tpublic toJSON<T = Record<string, unknown>>(include_undefined: boolean = true, options?: ClassTransformOptions): T {\n\t\tconst value = instanceToPlain(this, {\n\t\t\t...Dto.defaultTransformOptions,\n\t\t\t...options,\n\t\t}) as T;\n\n\t\tif (!include_undefined) {\n\t\t\treturn Object.fromEntries(Object.entries(value as Record<string, unknown>).filter(([_, v]) => !Guards.IsNil(v))) as T;\n\t\t}\n\n\t\treturn value;\n\t}\n\n\t/**\n\t * Creates a new instance of the DTO with validation (infers class from `this`)\n\t * @param data - Data to create the DTO from\n\t * @param options - Class transformer options\n\t * @returns New instance of the DTO\n\t */\n\tpublic static Create<T extends Dto>(this: ClassConstructor<T>, data: Record<string, unknown>, options: ClassTransformOptions = {}): T {\n\t\tconst instance = plainToInstance(this, data, {\n\t\t\t...Dto.defaultTransformOptions,\n\t\t\t...options,\n\t\t});\n\n\t\treturn instance;\n\t}\n\n\t/**\n\t * Creates an array of DTOs from an array of plain objects\n\t */\n\tpublic static CreateMany<T extends Dto>(this: ClassConstructor<T>, dataArray: Record<string, unknown>[], options: ClassTransformOptions = {}): T[] {\n\t\treturn plainToInstance(this, dataArray, {\n\t\t\t...Dto.defaultTransformOptions,\n\t\t\t...options,\n\t\t}) as T[];\n\t}\n}\n"]}
@@ -1,31 +0,0 @@
1
- import { ClassConstructor } from "class-transformer";
2
- import { Dto } from "./BaseDto";
3
- export default abstract class BaseEntity {
4
- /**
5
- * Converts entity to plain object
6
- */
7
- toJSON<T = Record<string, unknown>>(): T;
8
- /**
9
- * Abstract method - entities must define how to convert to DTO
10
- */
11
- abstract toDto(): Dto;
12
- /**
13
- * Updates entity with partial data (immutable - returns new instance)
14
- * @param data - Partial data to update
15
- * @param validate - Whether to validate after update (default: true)
16
- */
17
- update<T extends BaseEntity>(this: T, data: Partial<T>): T;
18
- /**
19
- * Creates a new entity instance from DTO (infers class from `this`)
20
- *
21
- * NOTE: This is a BASE implementation that uses plainToInstance.
22
- * Derived classes should override if they need custom construction logic.
23
- *
24
- * @param dto - DTO to create entity from
25
- */
26
- static FromDto<T extends BaseEntity>(this: ClassConstructor<T>, dto: Dto): T;
27
- /**
28
- * Creates multiple entities from DTOs
29
- */
30
- static FromDtos<T extends BaseEntity>(this: ClassConstructor<T>, dtos: Dto[]): T[];
31
- }
@@ -1,37 +0,0 @@
1
- import { instanceToPlain, plainToInstance } from "class-transformer";
2
- export default class BaseEntity {
3
- /**
4
- * Converts entity to plain object
5
- */
6
- toJSON() {
7
- return instanceToPlain(this);
8
- }
9
- /**
10
- * Updates entity with partial data (immutable - returns new instance)
11
- * @param data - Partial data to update
12
- * @param validate - Whether to validate after update (default: true)
13
- */
14
- update(data) {
15
- const updated = Object.assign(Object.create(Object.getPrototypeOf(this)), this, data);
16
- return updated;
17
- }
18
- /**
19
- * Creates a new entity instance from DTO (infers class from `this`)
20
- *
21
- * NOTE: This is a BASE implementation that uses plainToInstance.
22
- * Derived classes should override if they need custom construction logic.
23
- *
24
- * @param dto - DTO to create entity from
25
- */
26
- static FromDto(dto) {
27
- const instance = plainToInstance(this, dto.toJSON());
28
- return instance;
29
- }
30
- /**
31
- * Creates multiple entities from DTOs
32
- */
33
- static FromDtos(dtos) {
34
- return plainToInstance(this, dtos.map((dto) => dto.toJSON()));
35
- }
36
- }
37
- //# sourceMappingURL=BaseEntity.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"BaseEntity.js","sourceRoot":"","sources":["../../src/utils/BaseEntity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,eAAe,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGvF,MAAM,CAAC,OAAO,OAAgB,UAAU;IACvC;;OAEG;IACI,MAAM;QACZ,OAAO,eAAe,CAAC,IAAI,CAAM,CAAC;IACnC,CAAC;IAOD;;;;OAIG;IACI,MAAM,CAAgC,IAAgB;QAC5D,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QACtF,OAAO,OAAO,CAAC;IAChB,CAAC;IAED;;;;;;;OAOG;IACI,MAAM,CAAC,OAAO,CAAkD,GAAQ;QAC9E,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QACrD,OAAO,QAAQ,CAAC;IACjB,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,QAAQ,CAAkD,IAAW;QAClF,OAAO,eAAe,CACrB,IAAI,EACJ,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAC/B,CAAC;IACH,CAAC;CACD","sourcesContent":["import { ClassConstructor, instanceToPlain, plainToInstance } from \"class-transformer\";\nimport { Dto } from \"./BaseDto\";\n\nexport default abstract class BaseEntity {\n\t/**\n\t * Converts entity to plain object\n\t */\n\tpublic toJSON<T = Record<string, unknown>>(): T {\n\t\treturn instanceToPlain(this) as T;\n\t}\n\n\t/**\n\t * Abstract method - entities must define how to convert to DTO\n\t */\n\tpublic abstract toDto(): Dto;\n\n\t/**\n\t * Updates entity with partial data (immutable - returns new instance)\n\t * @param data - Partial data to update\n\t * @param validate - Whether to validate after update (default: true)\n\t */\n\tpublic update<T extends BaseEntity>(this: T, data: Partial<T>): T {\n\t\tconst updated = Object.assign(Object.create(Object.getPrototypeOf(this)), this, data);\n\t\treturn updated;\n\t}\n\n\t/**\n\t * Creates a new entity instance from DTO (infers class from `this`)\n\t *\n\t * NOTE: This is a BASE implementation that uses plainToInstance.\n\t * Derived classes should override if they need custom construction logic.\n\t *\n\t * @param dto - DTO to create entity from\n\t */\n\tpublic static FromDto<T extends BaseEntity>(this: ClassConstructor<T>, dto: Dto): T {\n\t\tconst instance = plainToInstance(this, dto.toJSON());\n\t\treturn instance;\n\t}\n\n\t/**\n\t * Creates multiple entities from DTOs\n\t */\n\tpublic static FromDtos<T extends BaseEntity>(this: ClassConstructor<T>, dtos: Dto[]): T[] {\n\t\treturn plainToInstance(\n\t\t\tthis,\n\t\t\tdtos.map((dto) => dto.toJSON()),\n\t\t);\n\t}\n}\n"]}