@pikku/core 0.6.9

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 (167) hide show
  1. package/CHANGELOG.md +339 -0
  2. package/README.md +5 -0
  3. package/dist/channel/channel-handler.d.ts +3 -0
  4. package/dist/channel/channel-handler.js +97 -0
  5. package/dist/channel/channel-runner.d.ts +26 -0
  6. package/dist/channel/channel-runner.js +86 -0
  7. package/dist/channel/channel-store.d.ts +14 -0
  8. package/dist/channel/channel-store.js +2 -0
  9. package/dist/channel/channel.types.d.ts +106 -0
  10. package/dist/channel/channel.types.js +1 -0
  11. package/dist/channel/eventhub-forwarder.d.ts +17 -0
  12. package/dist/channel/eventhub-forwarder.js +1 -0
  13. package/dist/channel/eventhub-service.d.ts +23 -0
  14. package/dist/channel/eventhub-service.js +1 -0
  15. package/dist/channel/eventhub-store.d.ts +5 -0
  16. package/dist/channel/eventhub-store.js +2 -0
  17. package/dist/channel/index.d.ts +9 -0
  18. package/dist/channel/index.js +9 -0
  19. package/dist/channel/local/index.d.ts +3 -0
  20. package/dist/channel/local/index.js +3 -0
  21. package/dist/channel/local/local-channel-handler.d.ts +17 -0
  22. package/dist/channel/local/local-channel-handler.js +41 -0
  23. package/dist/channel/local/local-channel-runner.d.ts +3 -0
  24. package/dist/channel/local/local-channel-runner.js +46 -0
  25. package/dist/channel/local/local-eventhub-service.d.ts +44 -0
  26. package/dist/channel/local/local-eventhub-service.js +81 -0
  27. package/dist/channel/log-channels.d.ts +6 -0
  28. package/dist/channel/log-channels.js +17 -0
  29. package/dist/channel/pikku-abstract-channel-handler.d.ts +15 -0
  30. package/dist/channel/pikku-abstract-channel-handler.js +33 -0
  31. package/dist/channel/serverless/index.d.ts +1 -0
  32. package/dist/channel/serverless/index.js +1 -0
  33. package/dist/channel/serverless/serverless-channel-runner.d.ts +10 -0
  34. package/dist/channel/serverless/serverless-channel-runner.js +98 -0
  35. package/dist/errors/error-handler.d.ts +39 -0
  36. package/dist/errors/error-handler.js +54 -0
  37. package/dist/errors/errors.d.ts +190 -0
  38. package/dist/errors/errors.js +315 -0
  39. package/dist/errors/index.d.ts +2 -0
  40. package/dist/errors/index.js +2 -0
  41. package/dist/http/http-route-runner.d.ts +30 -0
  42. package/dist/http/http-route-runner.js +208 -0
  43. package/dist/http/http-routes.types.d.ts +127 -0
  44. package/dist/http/http-routes.types.js +1 -0
  45. package/dist/http/http-session-service.d.ts +15 -0
  46. package/dist/http/http-session-service.js +1 -0
  47. package/dist/http/index.d.ts +6 -0
  48. package/dist/http/index.js +5 -0
  49. package/dist/http/log-http-routes.d.ts +6 -0
  50. package/dist/http/log-http-routes.js +17 -0
  51. package/dist/http/pikku-http-abstract-request.d.ts +57 -0
  52. package/dist/http/pikku-http-abstract-request.js +69 -0
  53. package/dist/http/pikku-http-abstract-response.d.ts +58 -0
  54. package/dist/http/pikku-http-abstract-response.js +54 -0
  55. package/dist/http/pikku-http-session-service.d.ts +45 -0
  56. package/dist/http/pikku-http-session-service.js +92 -0
  57. package/dist/index.d.ts +14 -0
  58. package/dist/index.js +14 -0
  59. package/dist/permissions.d.ts +10 -0
  60. package/dist/permissions.js +32 -0
  61. package/dist/pikku-request.d.ts +14 -0
  62. package/dist/pikku-request.js +21 -0
  63. package/dist/pikku-response.d.ts +6 -0
  64. package/dist/pikku-response.js +6 -0
  65. package/dist/scheduler/index.d.ts +3 -0
  66. package/dist/scheduler/index.js +3 -0
  67. package/dist/scheduler/log-schedulers.d.ts +6 -0
  68. package/dist/scheduler/log-schedulers.js +17 -0
  69. package/dist/scheduler/scheduler-runner.d.ts +21 -0
  70. package/dist/scheduler/scheduler-runner.js +73 -0
  71. package/dist/scheduler/scheduler.types.d.ts +21 -0
  72. package/dist/scheduler/scheduler.types.js +1 -0
  73. package/dist/schema.d.ts +26 -0
  74. package/dist/schema.js +100 -0
  75. package/dist/services/content-service.d.ts +55 -0
  76. package/dist/services/content-service.js +1 -0
  77. package/dist/services/index.d.ts +12 -0
  78. package/dist/services/index.js +14 -0
  79. package/dist/services/jwt-service.d.ts +29 -0
  80. package/dist/services/jwt-service.js +1 -0
  81. package/dist/services/local-content.d.ts +33 -0
  82. package/dist/services/local-content.js +6 -0
  83. package/dist/services/local-secrets.d.ts +26 -0
  84. package/dist/services/local-secrets.js +39 -0
  85. package/dist/services/local-variables.d.ts +7 -0
  86. package/dist/services/local-variables.js +12 -0
  87. package/dist/services/logger-console.d.ts +52 -0
  88. package/dist/services/logger-console.js +82 -0
  89. package/dist/services/logger.d.ts +48 -0
  90. package/dist/services/logger.js +9 -0
  91. package/dist/services/schema-service.d.ts +24 -0
  92. package/dist/services/schema-service.js +1 -0
  93. package/dist/services/secret-service.d.ts +17 -0
  94. package/dist/services/secret-service.js +1 -0
  95. package/dist/services/user-session-service.d.ts +6 -0
  96. package/dist/services/user-session-service.js +1 -0
  97. package/dist/services/variables-service.d.ts +4 -0
  98. package/dist/services/variables-service.js +1 -0
  99. package/dist/types/core.types.d.ts +109 -0
  100. package/dist/types/core.types.js +1 -0
  101. package/dist/types/functions.types.d.ts +27 -0
  102. package/dist/types/functions.types.js +1 -0
  103. package/dist/utils.d.ts +2 -0
  104. package/dist/utils.js +15 -0
  105. package/package.json +48 -0
  106. package/run-tests.sh +53 -0
  107. package/src/channel/channel-handler.ts +179 -0
  108. package/src/channel/channel-runner.ts +156 -0
  109. package/src/channel/channel-store.ts +32 -0
  110. package/src/channel/channel.types.ts +202 -0
  111. package/src/channel/eventhub-forwarder.ts +25 -0
  112. package/src/channel/eventhub-service.ts +30 -0
  113. package/src/channel/eventhub-store.ts +8 -0
  114. package/src/channel/index.ts +9 -0
  115. package/src/channel/local/index.ts +3 -0
  116. package/src/channel/local/local-channel-handler.ts +56 -0
  117. package/src/channel/local/local-channel-runner.test.ts +128 -0
  118. package/src/channel/local/local-channel-runner.ts +94 -0
  119. package/src/channel/local/local-eventhub-service.test.ts +95 -0
  120. package/src/channel/local/local-eventhub-service.ts +95 -0
  121. package/src/channel/log-channels.ts +20 -0
  122. package/src/channel/pikku-abstract-channel-handler.test.ts +77 -0
  123. package/src/channel/pikku-abstract-channel-handler.ts +44 -0
  124. package/src/channel/serverless/index.ts +1 -0
  125. package/src/channel/serverless/serverless-channel-runner.ts +190 -0
  126. package/src/errors/error-handler.ts +74 -0
  127. package/src/errors/error.test.ts +54 -0
  128. package/src/errors/errors.ts +340 -0
  129. package/src/errors/index.ts +2 -0
  130. package/src/http/http-route-runner.test.ts +193 -0
  131. package/src/http/http-route-runner.ts +365 -0
  132. package/src/http/http-routes.types.ts +189 -0
  133. package/src/http/http-session-service.ts +19 -0
  134. package/src/http/index.ts +16 -0
  135. package/src/http/log-http-routes.ts +20 -0
  136. package/src/http/pikku-http-abstract-request.ts +95 -0
  137. package/src/http/pikku-http-abstract-response.ts +79 -0
  138. package/src/http/pikku-http-session-service.test.ts +106 -0
  139. package/src/http/pikku-http-session-service.ts +135 -0
  140. package/src/index.ts +15 -0
  141. package/src/permissions.test.ts +58 -0
  142. package/src/permissions.ts +45 -0
  143. package/src/pikku-request.ts +19 -0
  144. package/src/pikku-response.ts +5 -0
  145. package/src/scheduler/index.ts +11 -0
  146. package/src/scheduler/log-schedulers.ts +20 -0
  147. package/src/scheduler/scheduler-runner.ts +132 -0
  148. package/src/scheduler/scheduler.types.ts +27 -0
  149. package/src/schema.test.ts +57 -0
  150. package/src/schema.ts +124 -0
  151. package/src/services/content-service.ts +69 -0
  152. package/src/services/index.ts +16 -0
  153. package/src/services/jwt-service.ts +36 -0
  154. package/src/services/local-content.ts +39 -0
  155. package/src/services/local-secrets.ts +43 -0
  156. package/src/services/local-variables.ts +17 -0
  157. package/src/services/logger-console.ts +97 -0
  158. package/src/services/logger.ts +57 -0
  159. package/src/services/schema-service.ts +26 -0
  160. package/src/services/secret-service.ts +17 -0
  161. package/src/services/user-session-service.ts +7 -0
  162. package/src/services/variables-service.ts +6 -0
  163. package/src/types/core.types.ts +162 -0
  164. package/src/types/functions.types.ts +44 -0
  165. package/src/utils.ts +21 -0
  166. package/tsconfig.json +13 -0
  167. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Interface defining the methods of a EventHub Service.
3
+ */
4
+ export interface EventHubForwarder {
5
+ /**
6
+ * Sends data to all connections subscribed to a topic.
7
+ * @param topic - The topic to send data to.
8
+ * @param data - The data to send to the subscribers.
9
+ */
10
+ forwardPublish(topic: string, channelId: string, data: unknown, isBinary?: boolean): Promise<void>;
11
+ /**
12
+ * Sends data to all connections subscribed to a topic.
13
+ * @param topic - The topic to send data to.
14
+ * @param data - The data to send to the subscribers.
15
+ */
16
+ onForwardedPublishMessage(callback: (topic: string, data: unknown, isBinary?: boolean) => void): void;
17
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Interface defining the methods of a EventHub Service.
3
+ */
4
+ export interface EventHubService<Out = unknown> {
5
+ /**
6
+ * Subscribes a connection to a specific topic.
7
+ * @param topic - The topic to subscribe to.
8
+ * @param channelId - The unique ID of the connection to subscribe.
9
+ */
10
+ subscribe(topic: string, channelId: string): Promise<void> | void;
11
+ /**
12
+ * Unsubscribes a connection from a specific topic.
13
+ * @param topic - The topic to unsubscribe from.
14
+ * @param channelId - The unique ID of the connection to unsubscribe.
15
+ */
16
+ unsubscribe(topic: string, channelId: string): Promise<void> | void;
17
+ /**
18
+ * Sends data to all connections subscribed to a topic.
19
+ * @param topic - The topic to send data to.
20
+ * @param data - The data to send to the subscribers.
21
+ */
22
+ publish(topic: string, channelId: string | null, data: Out, isBinary?: boolean): Promise<void> | void;
23
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ export declare abstract class EventHubStore {
2
+ abstract getChannelIdsForTopic(topic: string): Promise<string[]>;
3
+ abstract subscribe(topic: string, channelId: string): Promise<boolean>;
4
+ abstract unsubscribe(topic: string, channelId: string): Promise<boolean>;
5
+ }
@@ -0,0 +1,2 @@
1
+ export class EventHubStore {
2
+ }
@@ -0,0 +1,9 @@
1
+ export * from './channel-runner.js';
2
+ export * from './channel.types.js';
3
+ export * from './log-channels.js';
4
+ export * from './pikku-abstract-channel-handler.js';
5
+ export * from './eventhub-service.js';
6
+ export * from './eventhub-forwarder.js';
7
+ export * from './eventhub-service.js';
8
+ export * from './channel-store.js';
9
+ export * from './eventhub-store.js';
@@ -0,0 +1,9 @@
1
+ export * from './channel-runner.js';
2
+ export * from './channel.types.js';
3
+ export * from './log-channels.js';
4
+ export * from './pikku-abstract-channel-handler.js';
5
+ export * from './eventhub-service.js';
6
+ export * from './eventhub-forwarder.js';
7
+ export * from './eventhub-service.js';
8
+ export * from './channel-store.js';
9
+ export * from './eventhub-store.js';
@@ -0,0 +1,3 @@
1
+ export * from './local-channel-handler.js';
2
+ export * from './local-channel-runner.js';
3
+ export * from './local-eventhub-service.js';
@@ -0,0 +1,3 @@
1
+ export * from './local-channel-handler.js';
2
+ export * from './local-channel-runner.js';
3
+ export * from './local-eventhub-service.js';
@@ -0,0 +1,17 @@
1
+ import { CoreUserSession } from '../../types/core.types.js';
2
+ import { PikkuAbstractChannelHandler } from '../pikku-abstract-channel-handler.js';
3
+ export declare class PikkuLocalChannelHandler<UserSession extends CoreUserSession = CoreUserSession, OpeningData = unknown, Out = unknown> extends PikkuAbstractChannelHandler<UserSession, OpeningData, Out> {
4
+ private onMessageCallback?;
5
+ private openCallBack?;
6
+ private closeCallback?;
7
+ private sendCallback?;
8
+ registerOnOpen(callback: () => void): void;
9
+ open(): void;
10
+ registerOnMessage(callback: (data: any) => Promise<unknown>): void;
11
+ message(data: unknown): Promise<unknown>;
12
+ registerOnClose(callback: () => void): void;
13
+ close(): void;
14
+ registerOnSend(send: (message: Out) => void): void;
15
+ send(message: Out, isBinary?: boolean): void;
16
+ setUserSession(userSession: UserSession): void;
17
+ }
@@ -0,0 +1,41 @@
1
+ import { PikkuAbstractChannelHandler } from '../pikku-abstract-channel-handler.js';
2
+ export class PikkuLocalChannelHandler extends PikkuAbstractChannelHandler {
3
+ onMessageCallback;
4
+ openCallBack;
5
+ closeCallback;
6
+ sendCallback;
7
+ registerOnOpen(callback) {
8
+ this.openCallBack = callback;
9
+ }
10
+ open() {
11
+ this.getChannel().state = 'open';
12
+ if (this.openCallBack) {
13
+ this.openCallBack();
14
+ }
15
+ }
16
+ registerOnMessage(callback) {
17
+ this.onMessageCallback = callback;
18
+ }
19
+ async message(data) {
20
+ return this.onMessageCallback?.(data);
21
+ }
22
+ registerOnClose(callback) {
23
+ this.closeCallback = callback;
24
+ }
25
+ close() {
26
+ super.close();
27
+ this.closeCallback?.();
28
+ }
29
+ registerOnSend(send) {
30
+ this.sendCallback = send;
31
+ }
32
+ send(message, isBinary) {
33
+ if (!this.sendCallback) {
34
+ throw new Error('No send callback registered');
35
+ }
36
+ return this.sendCallback?.(message, isBinary);
37
+ }
38
+ setUserSession(userSession) {
39
+ this.getChannel().userSession = userSession;
40
+ }
41
+ }
@@ -0,0 +1,3 @@
1
+ import { CoreAPIChannel, RunChannelOptions, RunChannelParams } from '../channel.types.js';
2
+ import { PikkuLocalChannelHandler } from './local-channel-handler.js';
3
+ export declare const runLocalChannel: ({ singletonServices, channelId, request, response, route, createSessionServices, skipUserSession, respondWith404, coerceToArray, logWarningsForStatusCodes, bubbleErrors, }: Pick<CoreAPIChannel<unknown, any>, "route"> & RunChannelOptions & RunChannelParams<unknown>) => Promise<PikkuLocalChannelHandler | void>;
@@ -0,0 +1,46 @@
1
+ import { openChannel } from '../channel-runner.js';
2
+ import { createHTTPInteraction, handleError, } from '../../http/http-route-runner.js';
3
+ import { closeSessionServices } from '../../utils.js';
4
+ import { processMessageHandlers } from '../channel-handler.js';
5
+ import { PikkuLocalChannelHandler } from './local-channel-handler.js';
6
+ export const runLocalChannel = async ({ singletonServices, channelId, request, response, route, createSessionServices, skipUserSession = false, respondWith404 = true, coerceToArray = false, logWarningsForStatusCodes = [], bubbleErrors = false, }) => {
7
+ let sessionServices;
8
+ const http = createHTTPInteraction(request, response);
9
+ try {
10
+ const { userSession, openingData, channelConfig } = await openChannel({
11
+ channelId,
12
+ createSessionServices,
13
+ respondWith404,
14
+ http,
15
+ route,
16
+ singletonServices,
17
+ skipUserSession,
18
+ coerceToArray,
19
+ });
20
+ const channelHandler = new PikkuLocalChannelHandler(channelId, channelConfig.name, userSession, openingData);
21
+ const channel = channelHandler.getChannel();
22
+ if (createSessionServices) {
23
+ sessionServices = await createSessionServices(singletonServices, { http }, userSession);
24
+ }
25
+ const allServices = { ...singletonServices, ...sessionServices };
26
+ channelHandler.registerOnOpen(() => {
27
+ channelConfig.onConnect?.(allServices, channel);
28
+ });
29
+ channelHandler.registerOnClose(async () => {
30
+ channelConfig.onDisconnect?.(allServices, channel);
31
+ if (sessionServices) {
32
+ await closeSessionServices(singletonServices.logger, sessionServices);
33
+ }
34
+ });
35
+ channelHandler.registerOnMessage(processMessageHandlers(allServices, channelConfig, channelHandler));
36
+ return channelHandler;
37
+ }
38
+ catch (e) {
39
+ handleError(e, http, channelId, singletonServices.logger, logWarningsForStatusCodes, respondWith404, bubbleErrors);
40
+ }
41
+ finally {
42
+ if (sessionServices) {
43
+ await closeSessionServices(singletonServices.logger, sessionServices);
44
+ }
45
+ }
46
+ };
@@ -0,0 +1,44 @@
1
+ import { PikkuChannelHandler } from '../channel.types.js';
2
+ import { EventHubService } from '../eventhub-service.js';
3
+ /**
4
+ * Implementation of the SubscriptionService interface.
5
+ * Manages subscriptions and publishes messages to subscribers.
6
+ */
7
+ export declare class LocalEventHubService<Data = unknown> implements EventHubService<Data> {
8
+ private channels;
9
+ /**
10
+ * A map storing topics and their associated connection IDs.
11
+ */
12
+ private subscriptions;
13
+ /**
14
+ * Subscribes a connection to a specific topic.
15
+ * Creates the topic if it does not already exist.
16
+ * @param topic - The topic to subscribe to.
17
+ * @param channelId - The unique ID of the connection to subscribe.
18
+ */
19
+ subscribe(topic: string, channelId: string): void;
20
+ /**
21
+ * Unsubscribes a connection from a specific topic.
22
+ * Removes the topic if it has no more subscribers.
23
+ * @param topic - The topic to unsubscribe from.
24
+ * @param channelId - The unique ID of the connection to unsubscribe.
25
+ */
26
+ unsubscribe(topic: string, channelId: string): void;
27
+ /**
28
+ * Sends data to all connections subscribed to a topic.
29
+ * @param topic - The topic to send data to.
30
+ * @param data - The data to send to the subscribers.
31
+ */
32
+ publish(topic: string, channelId: string, data: Data, isBinary?: boolean): void;
33
+ /**
34
+ * Registers a channel on open
35
+ */
36
+ onChannelOpened(channelHandler: PikkuChannelHandler): void;
37
+ /**
38
+ * Handles cleanup when a channel is closed.
39
+ * Removes the channel from all topics it is subscribed to.
40
+ * Deletes the topic if no more channels are subscribed to it.
41
+ * @param channelId - The ID of the channel that was closed.
42
+ */
43
+ onChannelClosed(channelId: string): void;
44
+ }
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Implementation of the SubscriptionService interface.
3
+ * Manages subscriptions and publishes messages to subscribers.
4
+ */
5
+ export class LocalEventHubService {
6
+ channels = new Map();
7
+ /**
8
+ * A map storing topics and their associated connection IDs.
9
+ */
10
+ subscriptions = new Map();
11
+ /**
12
+ * Subscribes a connection to a specific topic.
13
+ * Creates the topic if it does not already exist.
14
+ * @param topic - The topic to subscribe to.
15
+ * @param channelId - The unique ID of the connection to subscribe.
16
+ */
17
+ subscribe(topic, channelId) {
18
+ if (!this.subscriptions.has(topic)) {
19
+ this.subscriptions.set(topic, new Set());
20
+ }
21
+ this.subscriptions.get(topic).add(channelId);
22
+ }
23
+ /**
24
+ * Unsubscribes a connection from a specific topic.
25
+ * Removes the topic if it has no more subscribers.
26
+ * @param topic - The topic to unsubscribe from.
27
+ * @param channelId - The unique ID of the connection to unsubscribe.
28
+ */
29
+ unsubscribe(topic, channelId) {
30
+ const topicSubscriptions = this.subscriptions.get(topic);
31
+ if (topicSubscriptions) {
32
+ topicSubscriptions.delete(channelId);
33
+ if (topicSubscriptions.size === 0) {
34
+ this.subscriptions.delete(topic); // Cleanup empty subscriptions
35
+ }
36
+ }
37
+ }
38
+ /**
39
+ * Sends data to all connections subscribed to a topic.
40
+ * @param topic - The topic to send data to.
41
+ * @param data - The data to send to the subscribers.
42
+ */
43
+ publish(topic, channelId, data, isBinary) {
44
+ const subscribedChannelIds = this.subscriptions.get(topic);
45
+ if (!subscribedChannelIds) {
46
+ return;
47
+ }
48
+ for (const toChannelId of subscribedChannelIds) {
49
+ if (channelId === toChannelId)
50
+ continue; // Skip sending to the sender
51
+ const channel = this.channels.get(toChannelId);
52
+ if (channel) {
53
+ channel.send(data, isBinary);
54
+ }
55
+ else {
56
+ // TODO: Websocket is closed, remove the channel from the topic
57
+ }
58
+ }
59
+ }
60
+ /**
61
+ * Registers a channel on open
62
+ */
63
+ onChannelOpened(channelHandler) {
64
+ this.channels.set(channelHandler.getChannel().channelId, channelHandler);
65
+ }
66
+ /**
67
+ * Handles cleanup when a channel is closed.
68
+ * Removes the channel from all topics it is subscribed to.
69
+ * Deletes the topic if no more channels are subscribed to it.
70
+ * @param channelId - The ID of the channel that was closed.
71
+ */
72
+ onChannelClosed(channelId) {
73
+ for (const [topic, channelIds] of this.subscriptions.entries()) {
74
+ channelIds.delete(channelId);
75
+ if (channelIds.size === 0) {
76
+ this.subscriptions.delete(topic); // Cleanup empty topics
77
+ }
78
+ }
79
+ this.channels.delete(channelId);
80
+ }
81
+ }
@@ -0,0 +1,6 @@
1
+ import { Logger } from '../services/index.js';
2
+ /**
3
+ * Logs all the loaded channels.
4
+ * @param logger - A logger for logging information.
5
+ */
6
+ export declare const logChannels: (logger: Logger) => void;
@@ -0,0 +1,17 @@
1
+ import { getChannels } from './channel-runner.js';
2
+ /**
3
+ * Logs all the loaded channels.
4
+ * @param logger - A logger for logging information.
5
+ */
6
+ export const logChannels = (logger) => {
7
+ const { channels } = getChannels();
8
+ if (channels.length === 0) {
9
+ logger.info('No channels added');
10
+ return;
11
+ }
12
+ let scheduledChannels = 'Channels:';
13
+ for (const { name, route } of channels) {
14
+ scheduledChannels += `\n\t- ${name} at ${route}`;
15
+ }
16
+ logger.info(scheduledChannels);
17
+ };
@@ -0,0 +1,15 @@
1
+ import { CoreUserSession } from '../types/core.types.js';
2
+ import { PikkuChannel, PikkuChannelHandler } from './channel.types.js';
3
+ export declare abstract class PikkuAbstractChannelHandler<UserSession extends CoreUserSession = CoreUserSession, OpeningData = unknown, Out = unknown> implements PikkuChannelHandler<UserSession, OpeningData, Out> {
4
+ channelId: string;
5
+ channelName: string;
6
+ protected userSession: UserSession | undefined;
7
+ protected openingData: OpeningData;
8
+ protected channel?: PikkuChannel<UserSession, OpeningData, Out>;
9
+ constructor(channelId: string, channelName: string, userSession: UserSession | undefined, openingData: OpeningData);
10
+ abstract setUserSession(userSession: UserSession): Promise<void> | void;
11
+ abstract send(message: Out, isBinary?: boolean): Promise<void> | void;
12
+ getChannel(): PikkuChannel<UserSession, OpeningData, Out>;
13
+ open(): void;
14
+ close(): Promise<void> | void;
15
+ }
@@ -0,0 +1,33 @@
1
+ export class PikkuAbstractChannelHandler {
2
+ channelId;
3
+ channelName;
4
+ userSession;
5
+ openingData;
6
+ channel;
7
+ constructor(channelId, channelName, userSession, openingData) {
8
+ this.channelId = channelId;
9
+ this.channelName = channelName;
10
+ this.userSession = userSession;
11
+ this.openingData = openingData;
12
+ }
13
+ getChannel() {
14
+ if (!this.channel) {
15
+ this.channel = {
16
+ channelId: this.channelId,
17
+ userSession: this.userSession,
18
+ openingData: this.openingData,
19
+ setUserSession: this.setUserSession.bind(this),
20
+ send: this.send.bind(this),
21
+ close: this.close.bind(this),
22
+ state: 'initial',
23
+ };
24
+ }
25
+ return this.channel;
26
+ }
27
+ open() {
28
+ this.getChannel().state = 'open';
29
+ }
30
+ close() {
31
+ this.getChannel().state = 'closed';
32
+ }
33
+ }
@@ -0,0 +1 @@
1
+ export * from './serverless-channel-runner.js';
@@ -0,0 +1 @@
1
+ export * from './serverless-channel-runner.js';
@@ -0,0 +1,10 @@
1
+ import type { CoreAPIChannel, RunChannelOptions, RunChannelParams, PikkuChannelHandlerFactory } from '../channel.types.js';
2
+ import { ChannelStore } from '../channel-store.js';
3
+ export interface RunServerlessChannelParams<ChannelData> extends RunChannelParams<ChannelData> {
4
+ channelStore: ChannelStore;
5
+ channelHandlerFactory: PikkuChannelHandlerFactory;
6
+ channelObject?: unknown;
7
+ }
8
+ export declare const runChannelConnect: ({ singletonServices, channelId, channelObject, request, response, route, createSessionServices, channelStore, channelHandlerFactory, coerceToArray, logWarningsForStatusCodes, respondWith404, bubbleErrors, }: Pick<CoreAPIChannel<unknown, any>, "route"> & RunChannelOptions & RunServerlessChannelParams<unknown>) => Promise<void>;
9
+ export declare const runChannelDisconnect: ({ singletonServices, ...params }: RunServerlessChannelParams<unknown>) => Promise<void>;
10
+ export declare const runChannelMessage: ({ singletonServices, ...params }: RunServerlessChannelParams<unknown>, data: unknown) => Promise<unknown>;
@@ -0,0 +1,98 @@
1
+ import { closeSessionServices } from '../../utils.js';
2
+ import { processMessageHandlers } from '../channel-handler.js';
3
+ import { getChannels, openChannel } from '../channel-runner.js';
4
+ import { createHTTPInteraction, handleError, } from '../../http/http-route-runner.js';
5
+ const getVariablesForChannel = ({ channelId, userSession, channelName, channelHandlerFactory, openingData, }) => {
6
+ const { channels } = getChannels();
7
+ const channelConfig = channels.find((channelConfig) => channelConfig.name === channelName);
8
+ if (!channelConfig) {
9
+ throw new Error(`Channel not found: ${channelName}`);
10
+ }
11
+ const channelHandler = channelHandlerFactory(channelId, channelConfig.name, openingData, userSession);
12
+ return {
13
+ channelConfig,
14
+ channelHandler,
15
+ channel: channelHandler.getChannel(),
16
+ };
17
+ };
18
+ export const runChannelConnect = async ({ singletonServices, channelId, channelObject, request, response, route, createSessionServices, channelStore, channelHandlerFactory, coerceToArray = false, logWarningsForStatusCodes = [], respondWith404 = true, bubbleErrors = false, }) => {
19
+ let sessionServices;
20
+ const http = createHTTPInteraction(request, response);
21
+ try {
22
+ const { userSession, channelConfig, openingData } = await openChannel({
23
+ channelId,
24
+ createSessionServices,
25
+ http,
26
+ route,
27
+ singletonServices,
28
+ coerceToArray,
29
+ });
30
+ await channelStore.addChannel({
31
+ channelId,
32
+ channelName: channelConfig.name,
33
+ openingData,
34
+ channelObject,
35
+ });
36
+ const { channel } = getVariablesForChannel({
37
+ channelId,
38
+ userSession,
39
+ channelHandlerFactory,
40
+ channelName: channelConfig.name,
41
+ });
42
+ if (createSessionServices) {
43
+ sessionServices = await createSessionServices(singletonServices, { http }, userSession);
44
+ }
45
+ await channelConfig.onConnect?.({ ...singletonServices, ...sessionServices }, channel);
46
+ http?.response?.setStatus(101);
47
+ }
48
+ catch (e) {
49
+ handleError(e, http, channelId, singletonServices.logger, logWarningsForStatusCodes, respondWith404, bubbleErrors);
50
+ }
51
+ finally {
52
+ if (sessionServices) {
53
+ await closeSessionServices(singletonServices.logger, sessionServices);
54
+ }
55
+ }
56
+ };
57
+ export const runChannelDisconnect = async ({ singletonServices, ...params }) => {
58
+ let sessionServices;
59
+ const { userSession, openingData, channelName } = await params.channelStore.getChannel(params.channelId);
60
+ const { channel, channelConfig } = getVariablesForChannel({
61
+ ...params,
62
+ userSession,
63
+ openingData,
64
+ channelName,
65
+ });
66
+ if (!sessionServices && params.createSessionServices) {
67
+ sessionServices = await params.createSessionServices(singletonServices, {}, userSession);
68
+ }
69
+ await channelConfig.onDisconnect?.({ ...singletonServices, ...sessionServices }, channel);
70
+ await params.channelStore.removeChannels([channel.channelId]);
71
+ if (sessionServices) {
72
+ await closeSessionServices(singletonServices.logger, sessionServices);
73
+ }
74
+ };
75
+ export const runChannelMessage = async ({ singletonServices, ...params }, data) => {
76
+ let sessionServices;
77
+ const { userSession, openingData, channelName } = await params.channelStore.getChannel(params.channelId);
78
+ const { channelHandler, channelConfig } = getVariablesForChannel({
79
+ ...params,
80
+ userSession,
81
+ openingData,
82
+ channelName,
83
+ });
84
+ if (params.createSessionServices) {
85
+ sessionServices = await params.createSessionServices(singletonServices, {}, userSession);
86
+ }
87
+ let response;
88
+ try {
89
+ const onMessage = processMessageHandlers({ ...singletonServices, ...sessionServices }, channelConfig, channelHandler);
90
+ response = await onMessage(data);
91
+ }
92
+ finally {
93
+ if (sessionServices) {
94
+ await closeSessionServices(singletonServices.logger, sessionServices);
95
+ }
96
+ }
97
+ return response;
98
+ };
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Base class for custom errors.
3
+ * @extends {Error}
4
+ */
5
+ export declare class EError extends Error {
6
+ /**
7
+ * Creates an instance of EError.
8
+ * @param message - The error message.
9
+ */
10
+ constructor(message?: string);
11
+ }
12
+ /**
13
+ * Interface for error details.
14
+ */
15
+ export interface ErrorDetails {
16
+ status: number;
17
+ message: string;
18
+ }
19
+ export declare const getErrors: () => Map<any, ErrorDetails>;
20
+ /**
21
+ * Adds an error to the API errors map.
22
+ * @param error - The error to add.
23
+ * @param details - The details of the error.
24
+ */
25
+ export declare const addError: (error: any, { status, message }: ErrorDetails) => void;
26
+ /**
27
+ * Adds multiple errors to the API errors map.
28
+ * @param errors - An array of errors and their details.
29
+ */
30
+ export declare const addErrors: (errors: Array<[error: any, details: ErrorDetails]>) => void;
31
+ /**
32
+ * Retrieves the error response for a given error.
33
+ * @param error - The error to get the response for.
34
+ * @returns An object containing the status and message, or undefined if the error is not found.
35
+ */
36
+ export declare const getErrorResponse: (error: Error) => {
37
+ status: number;
38
+ message: string;
39
+ } | undefined;
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Base class for custom errors.
3
+ * @extends {Error}
4
+ */
5
+ export class EError extends Error {
6
+ /**
7
+ * Creates an instance of EError.
8
+ * @param message - The error message.
9
+ */
10
+ constructor(message = 'An error occurred') {
11
+ super(message);
12
+ Object.setPrototypeOf(this, new.target.prototype);
13
+ }
14
+ }
15
+ /**
16
+ * Map of API errors to their details.
17
+ */
18
+ if (!globalThis.pikku?.apiErrors) {
19
+ globalThis.pikku = globalThis.pikku || {};
20
+ globalThis.pikku.apiErrors = new Map([]);
21
+ }
22
+ const apiErrors = () => {
23
+ return globalThis.pikku.apiErrors;
24
+ };
25
+ export const getErrors = () => apiErrors();
26
+ /**
27
+ * Adds an error to the API errors map.
28
+ * @param error - The error to add.
29
+ * @param details - The details of the error.
30
+ */
31
+ export const addError = (error, { status, message }) => {
32
+ apiErrors().set(error, { status, message });
33
+ };
34
+ /**
35
+ * Adds multiple errors to the API errors map.
36
+ * @param errors - An array of errors and their details.
37
+ */
38
+ export const addErrors = (errors) => {
39
+ errors.forEach((error) => {
40
+ addError(error[0], error[1]);
41
+ });
42
+ };
43
+ /**
44
+ * Retrieves the error response for a given error.
45
+ * @param error - The error to get the response for.
46
+ * @returns An object containing the status and message, or undefined if the error is not found.
47
+ */
48
+ export const getErrorResponse = (error) => {
49
+ const foundError = Array.from(apiErrors().entries()).find(([e]) => e.name === error.constructor.name);
50
+ if (foundError) {
51
+ return foundError[1];
52
+ }
53
+ return apiErrors().get(error);
54
+ };