@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,45 @@
1
+ import { HTTPSessionService } from './http-session-service.js';
2
+ import { JWTService } from '../services/jwt-service.js';
3
+ import { PikkuHTTPAbstractRequest } from './pikku-http-abstract-request.js';
4
+ import { PikkuQuery } from './http-routes.types.js';
5
+ /**
6
+ * The `PikkuHTTPSessionService` class provides session management capabilities, including handling JWT-based sessions,
7
+ * cookie-based sessions, and API key-based sessions. It allows for retrieving and transforming user sessions based on different
8
+ * authentication mechanisms.
9
+ *
10
+ * @template UserSession - The type representing a user session.
11
+ */
12
+ export declare class PikkuHTTPSessionService<UserSession> implements HTTPSessionService<UserSession> {
13
+ private jwtService;
14
+ private options;
15
+ /**
16
+ * Constructs a new instance of the `PikkuHTTPSessionService` class.
17
+ *
18
+ * @param jwtService - The service for handling JWT operations.
19
+ * @param options - Options for configuring the session service.
20
+ */
21
+ constructor(jwtService: JWTService<UserSession>, options: {
22
+ cookieNames?: string[];
23
+ getSessionForCookieValue?: (cookieValue: string, cookieName: string) => Promise<UserSession>;
24
+ getSessionForQueryValue?: (queryValue: PikkuQuery) => Promise<UserSession> | undefined;
25
+ getSessionForAPIKey?: (apiKey: string) => Promise<UserSession> | undefined;
26
+ transformSession?: (session: any) => Promise<UserSession>;
27
+ });
28
+ /**
29
+ * Retrieves a session from cookies if available.
30
+ *
31
+ * @param request - The request object containing cookies.
32
+ * @returns A promise that resolves to the user session, or `undefined` if no session is found.
33
+ */
34
+ private getCookieSession;
35
+ /**
36
+ * Retrieves the user session based on available credentials (JWT, API key, or cookies).
37
+ *
38
+ * @param credentialsRequired - Whether credentials are required to proceed.
39
+ * @param request - The request object containing headers and cookies.
40
+ * @param debugJWTDecode - Whether to enable debugging for JWT decoding.
41
+ * @returns A promise that resolves to the user session, or `undefined` if no session is found and credentials are not required.
42
+ * @throws {MissingSessionError} - Throws an error if credentials are required but no session is found.
43
+ */
44
+ getUserSession(credentialsRequired: boolean, request: PikkuHTTPAbstractRequest, debugJWTDecode?: boolean): Promise<UserSession | undefined>;
45
+ }
@@ -0,0 +1,92 @@
1
+ import { InvalidSessionError, MissingSessionError } from '../errors/errors.js';
2
+ /**
3
+ * The `PikkuHTTPSessionService` class provides session management capabilities, including handling JWT-based sessions,
4
+ * cookie-based sessions, and API key-based sessions. It allows for retrieving and transforming user sessions based on different
5
+ * authentication mechanisms.
6
+ *
7
+ * @template UserSession - The type representing a user session.
8
+ */
9
+ export class PikkuHTTPSessionService {
10
+ jwtService;
11
+ options;
12
+ /**
13
+ * Constructs a new instance of the `PikkuHTTPSessionService` class.
14
+ *
15
+ * @param jwtService - The service for handling JWT operations.
16
+ * @param options - Options for configuring the session service.
17
+ */
18
+ constructor(jwtService, options) {
19
+ this.jwtService = jwtService;
20
+ this.options = options;
21
+ }
22
+ /**
23
+ * Retrieves a session from cookies if available.
24
+ *
25
+ * @param request - The request object containing cookies.
26
+ * @returns A promise that resolves to the user session, or `undefined` if no session is found.
27
+ */
28
+ async getCookieSession(request) {
29
+ const cookies = request.getCookies();
30
+ if (!cookies) {
31
+ return;
32
+ }
33
+ let cookieName;
34
+ if (this.options.cookieNames) {
35
+ for (const name of this.options.cookieNames) {
36
+ if (cookies[name]) {
37
+ cookieName = name;
38
+ }
39
+ }
40
+ }
41
+ if (!cookieName) {
42
+ return;
43
+ }
44
+ const cookieValue = cookies[cookieName];
45
+ if (!cookieValue) {
46
+ return;
47
+ }
48
+ if (!this.options.getSessionForCookieValue) {
49
+ return;
50
+ }
51
+ return await this.options.getSessionForCookieValue(cookieValue, cookieName);
52
+ }
53
+ /**
54
+ * Retrieves the user session based on available credentials (JWT, API key, or cookies).
55
+ *
56
+ * @param credentialsRequired - Whether credentials are required to proceed.
57
+ * @param request - The request object containing headers and cookies.
58
+ * @param debugJWTDecode - Whether to enable debugging for JWT decoding.
59
+ * @returns A promise that resolves to the user session, or `undefined` if no session is found and credentials are not required.
60
+ * @throws {MissingSessionError} - Throws an error if credentials are required but no session is found.
61
+ */
62
+ async getUserSession(credentialsRequired, request, debugJWTDecode) {
63
+ let userSession;
64
+ const authorization = request.getHeader('authorization') || request.getHeader('Authorization');
65
+ if (authorization) {
66
+ const [part1, part2] = authorization.split(' ');
67
+ if (part1 !== 'Bearer' || !part2) {
68
+ throw new InvalidSessionError();
69
+ }
70
+ userSession = await this.jwtService.decode(part2, undefined, debugJWTDecode);
71
+ }
72
+ if (!userSession && this.options.getSessionForAPIKey) {
73
+ const apiKey = request.getHeader('x-api-key');
74
+ if (apiKey) {
75
+ userSession = await this.options.getSessionForAPIKey(apiKey);
76
+ }
77
+ }
78
+ if (!userSession && this.options.getSessionForCookieValue) {
79
+ userSession = await this.getCookieSession(request);
80
+ }
81
+ if (!userSession && this.options.getSessionForQueryValue) {
82
+ userSession = await this.options.getSessionForQueryValue(request.getQuery());
83
+ }
84
+ if (!userSession && credentialsRequired) {
85
+ throw new MissingSessionError();
86
+ }
87
+ if (userSession && this.options.transformSession) {
88
+ return await this.options.transformSession(userSession);
89
+ }
90
+ return userSession;
91
+ }
92
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @module @pikku/core
3
+ */
4
+ export * from './types/core.types.js';
5
+ export * from './types/functions.types.js';
6
+ export * from './pikku-request.js';
7
+ export * from './pikku-response.js';
8
+ export * from './services/index.js';
9
+ export * from './http/index.js';
10
+ export * from './channel/index.js';
11
+ export * from './scheduler/index.js';
12
+ export { addRoute } from './http/http-route-runner.js';
13
+ export { addChannel } from './channel/channel-runner.js';
14
+ export { addScheduledTask } from './scheduler/scheduler-runner.js';
package/dist/index.js ADDED
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @module @pikku/core
3
+ */
4
+ export * from './types/core.types.js';
5
+ export * from './types/functions.types.js';
6
+ export * from './pikku-request.js';
7
+ export * from './pikku-response.js';
8
+ export * from './services/index.js';
9
+ export * from './http/index.js';
10
+ export * from './channel/index.js';
11
+ export * from './scheduler/index.js';
12
+ export { addRoute } from './http/http-route-runner.js';
13
+ export { addChannel } from './channel/channel-runner.js';
14
+ export { addScheduledTask } from './scheduler/scheduler-runner.js';
@@ -0,0 +1,10 @@
1
+ import { CoreServices, CoreUserSession } from './types/core.types.js';
2
+ import { CoreAPIPermission } from './types/functions.types.js';
3
+ /**
4
+ * This function validates permissions by iterating over permission groups and executing the corresponding permission functions. If all functions in at least one group return true, the permission is considered valid.
5
+ * @param services - The core services required for permission validation.
6
+ * @param data - The data to be used in the permission validation functions.
7
+ * @param session - An optional user session for permission validation.
8
+ * @returns A promise that resolves to void.
9
+ */
10
+ export declare const verifyPermissions: (permissions: Record<string, CoreAPIPermission<any>[] | CoreAPIPermission<any>> | undefined, services: CoreServices, data: any, session?: CoreUserSession) => Promise<boolean>;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * This function validates permissions by iterating over permission groups and executing the corresponding permission functions. If all functions in at least one group return true, the permission is considered valid.
3
+ * @param services - The core services required for permission validation.
4
+ * @param data - The data to be used in the permission validation functions.
5
+ * @param session - An optional user session for permission validation.
6
+ * @returns A promise that resolves to void.
7
+ */
8
+ export const verifyPermissions = async (permissions, services, data, session) => {
9
+ if (!permissions) {
10
+ return true;
11
+ }
12
+ let valid = false;
13
+ const permissionGroups = Object.values(permissions);
14
+ if (permissionGroups.length === 0) {
15
+ return true;
16
+ }
17
+ for (const funcs of permissionGroups) {
18
+ if (funcs instanceof Array) {
19
+ const permissioned = await Promise.all(funcs.map((func) => func(services, data, session)));
20
+ if (permissioned.every((result) => result)) {
21
+ valid = true;
22
+ }
23
+ }
24
+ else {
25
+ valid = await funcs(services, data, session);
26
+ }
27
+ if (valid) {
28
+ return true;
29
+ }
30
+ }
31
+ return false;
32
+ };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Simplest class to represent a pikku request.
3
+ * @template In - The type of the request body.
4
+ * @group RequestResponse
5
+ */
6
+ export declare abstract class PikkuRequest<In = any> {
7
+ private data?;
8
+ constructor(data?: In | undefined);
9
+ /**
10
+ * Retrieves the data
11
+ * @returns A promise that resolves to an object containing the combined data.
12
+ */
13
+ getData(): Promise<In>;
14
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Simplest class to represent a pikku request.
3
+ * @template In - The type of the request body.
4
+ * @group RequestResponse
5
+ */
6
+ export class PikkuRequest {
7
+ data;
8
+ constructor(data) {
9
+ this.data = data;
10
+ }
11
+ /**
12
+ * Retrieves the data
13
+ * @returns A promise that resolves to an object containing the combined data.
14
+ */
15
+ async getData() {
16
+ if (!this.data) {
17
+ throw new Error('Data not found');
18
+ }
19
+ return this.data;
20
+ }
21
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Abstract class representing a pikku response.
3
+ * @group RequestResponse
4
+ */
5
+ export declare abstract class PikkuResponse {
6
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Abstract class representing a pikku response.
3
+ * @group RequestResponse
4
+ */
5
+ export class PikkuResponse {
6
+ }
@@ -0,0 +1,3 @@
1
+ export * from './scheduler.types.js';
2
+ export { runScheduledTask, getScheduledTasks, addScheduledTask, clearScheduledTasks, setScheduledTasksMeta, } from './scheduler-runner.js';
3
+ export * from './log-schedulers.js';
@@ -0,0 +1,3 @@
1
+ export * from './scheduler.types.js';
2
+ export { runScheduledTask, getScheduledTasks, addScheduledTask, clearScheduledTasks, setScheduledTasksMeta, } from './scheduler-runner.js';
3
+ export * from './log-schedulers.js';
@@ -0,0 +1,6 @@
1
+ import { Logger } from '../services/index.js';
2
+ /**
3
+ * Logs all the loaded scheduled tasks.
4
+ * @param logger - A logger for logging information.
5
+ */
6
+ export declare const logSchedulers: (logger: Logger) => void;
@@ -0,0 +1,17 @@
1
+ import { getScheduledTasks } from './scheduler-runner.js';
2
+ /**
3
+ * Logs all the loaded scheduled tasks.
4
+ * @param logger - A logger for logging information.
5
+ */
6
+ export const logSchedulers = (logger) => {
7
+ const { scheduledTasks } = getScheduledTasks();
8
+ if (scheduledTasks.size === 0) {
9
+ logger.info('No scheduled tasks added');
10
+ return;
11
+ }
12
+ let scheduledTasksMessage = 'Scheduled tasks:';
13
+ scheduledTasks.forEach(({ schedule }, name) => {
14
+ scheduledTasksMessage += `\n\t- ${name} -> ${schedule}`;
15
+ });
16
+ logger.info(scheduledTasksMessage);
17
+ };
@@ -0,0 +1,21 @@
1
+ import type { CoreServices, CoreSingletonServices, CoreUserSession, CreateSessionServices } from '../types/core.types.js';
2
+ import type { CoreScheduledTask, ScheduledTasksMeta } from './scheduler.types.js';
3
+ import type { CoreAPIFunctionSessionless } from '../types/functions.types.js';
4
+ export type RunScheduledTasksParams = {
5
+ name: string;
6
+ session?: CoreUserSession;
7
+ singletonServices: CoreSingletonServices;
8
+ createSessionServices?: CreateSessionServices<CoreSingletonServices, CoreServices<CoreSingletonServices>, CoreUserSession>;
9
+ };
10
+ export declare const addScheduledTask: <APIFunction extends CoreAPIFunctionSessionless<void, void>>(scheduledTask: CoreScheduledTask<APIFunction>) => void;
11
+ export declare const clearScheduledTasks: () => void;
12
+ export declare const setScheduledTasksMeta: (_scheduledTasksMeta: ScheduledTasksMeta) => void;
13
+ /**
14
+ * Returns all the cron jobs
15
+ * @internal
16
+ */
17
+ export declare const getScheduledTasks: () => {
18
+ scheduledTasks: Map<string, CoreScheduledTask>;
19
+ scheduledTasksMeta: any;
20
+ };
21
+ export declare function runScheduledTask<SingletonServices extends CoreSingletonServices = CoreSingletonServices, UserSession extends CoreUserSession = CoreUserSession, Services extends CoreServices<SingletonServices> = CoreServices<SingletonServices>>({ name, session, singletonServices, createSessionServices, }: RunScheduledTasksParams): Promise<void>;
@@ -0,0 +1,73 @@
1
+ import { getErrorResponse } from '../errors/error-handler.js';
2
+ import { closeSessionServices } from '../utils.js';
3
+ if (!global.pikku?.scheduledTasks) {
4
+ global.pikku = global.pikku || {};
5
+ global.pikku.scheduledTasks = new Map();
6
+ global.pikku.scheduledTasksMeta = [];
7
+ }
8
+ const scheduledTasks = () => {
9
+ return global.pikku.scheduledTasks;
10
+ };
11
+ const scheduledTasksMeta = (data) => {
12
+ if (data) {
13
+ global.pikku.scheduledTasksMeta = data;
14
+ }
15
+ return global.pikku.scheduledTasksMeta;
16
+ };
17
+ export const addScheduledTask = (scheduledTask) => {
18
+ if (scheduledTasks().has(scheduledTask.name)) {
19
+ throw new Error(`Scheduled task already exists: ${scheduledTask.name}`);
20
+ }
21
+ scheduledTasks().set(scheduledTask.name, scheduledTask);
22
+ };
23
+ export const clearScheduledTasks = () => {
24
+ scheduledTasks().clear();
25
+ };
26
+ export const setScheduledTasksMeta = (_scheduledTasksMeta) => {
27
+ scheduledTasksMeta(_scheduledTasksMeta);
28
+ };
29
+ /**
30
+ * Returns all the cron jobs
31
+ * @internal
32
+ */
33
+ export const getScheduledTasks = () => {
34
+ return {
35
+ scheduledTasks: scheduledTasks(),
36
+ scheduledTasksMeta: scheduledTasksMeta(),
37
+ };
38
+ };
39
+ class ScheduledTaskNotFoundError extends Error {
40
+ constructor(title) {
41
+ super(`Scheduled task not found: ${title}`);
42
+ }
43
+ }
44
+ export async function runScheduledTask({ name, session, singletonServices, createSessionServices, }) {
45
+ let sessionServices;
46
+ const trackerId = crypto.randomUUID().toString();
47
+ try {
48
+ const task = scheduledTasks().get(name);
49
+ if (!task) {
50
+ throw new ScheduledTaskNotFoundError(`Scheduled task not found: ${name}`);
51
+ }
52
+ singletonServices.logger.info(`Running schedule task: ${name} | schedule: ${task.schedule}}`);
53
+ let allServices = singletonServices;
54
+ if (createSessionServices) {
55
+ const sessionServices = await createSessionServices(singletonServices, {}, session);
56
+ allServices = { ...singletonServices, ...sessionServices };
57
+ }
58
+ await task.func(allServices, undefined, session);
59
+ }
60
+ catch (e) {
61
+ const errorResponse = getErrorResponse(e);
62
+ if (errorResponse != null) {
63
+ singletonServices.logger.warn(`Error id: ${trackerId}`);
64
+ singletonServices.logger.error(e);
65
+ }
66
+ throw e;
67
+ }
68
+ finally {
69
+ if (sessionServices) {
70
+ await closeSessionServices(singletonServices.logger, sessionServices);
71
+ }
72
+ }
73
+ }
@@ -0,0 +1,21 @@
1
+ import { APIDocs, CoreUserSession } from '../types/core.types.js';
2
+ import { CoreAPIFunctionSessionless } from '../types/functions.types.js';
3
+ /**
4
+ * Represents metadata for scheduled tasks, including title, schedule, and documentation.
5
+ */
6
+ export type ScheduledTasksMeta<UserSession extends CoreUserSession = any> = Array<{
7
+ name: string;
8
+ schedule: string;
9
+ session?: UserSession;
10
+ docs?: APIDocs;
11
+ }>;
12
+ /**
13
+ * Represents a core scheduled task.
14
+ */
15
+ export type CoreScheduledTask<APIFunction = CoreAPIFunctionSessionless<void, void>, UserSession extends CoreUserSession = CoreUserSession> = {
16
+ name: string;
17
+ schedule: string;
18
+ func: APIFunction;
19
+ docs?: APIDocs;
20
+ session?: UserSession;
21
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,26 @@
1
+ import { Logger } from './services/logger.js';
2
+ import { SchemaService } from './services/schema-service.js';
3
+ /**
4
+ * Retrieves the global schemas map.
5
+ * @returns A map of schemas.
6
+ */
7
+ export declare const getSchemas: () => any;
8
+ /**
9
+ * Retrieves a schema from the schemas map.
10
+ * @returns A schema.
11
+ */
12
+ export declare const getSchema: (schemaName: string) => any;
13
+ /**
14
+ * Adds a schema to the global schemas map.
15
+ * @param name - The name of the schema.
16
+ * @param value - The schema value.
17
+ * @ignore
18
+ */
19
+ export declare const addSchema: (name: string, value: any) => void;
20
+ /**
21
+ * Loads a schema and compiles it into a validator.
22
+ * @param logger - A logger for logging information.
23
+ */
24
+ export declare const compileAllSchemas: (logger: Logger, schemaService?: SchemaService) => void;
25
+ export declare const coerceQueryStringToArray: (schemaName: string, data: any) => void;
26
+ export declare const validateAndCoerce: (logger: Logger, schemaService: SchemaService | undefined, schemaName: string | undefined | null, data: any, coerceToArray: boolean) => void;
package/dist/schema.js ADDED
@@ -0,0 +1,100 @@
1
+ import { getRoutes } from './http/http-route-runner.js';
2
+ import { BadRequestError } from './errors/errors.js';
3
+ /**
4
+ * Retrieves the global schemas map.
5
+ * @returns A map of schemas.
6
+ */
7
+ export const getSchemas = () => {
8
+ if (!global.pikkuSchemas) {
9
+ global.pikkuSchemas = new Map();
10
+ }
11
+ return global.pikkuSchemas;
12
+ };
13
+ /**
14
+ * Retrieves a schema from the schemas map.
15
+ * @returns A schema.
16
+ */
17
+ export const getSchema = (schemaName) => {
18
+ const schemas = getSchemas();
19
+ const schema = schemas.get(schemaName);
20
+ if (!schema) {
21
+ throw new Error(`Schema not found: ${schemaName}`);
22
+ }
23
+ return schema;
24
+ };
25
+ /**
26
+ * Adds a schema to the global schemas map.
27
+ * @param name - The name of the schema.
28
+ * @param value - The schema value.
29
+ * @ignore
30
+ */
31
+ export const addSchema = (name, value) => {
32
+ getSchemas().set(name, value);
33
+ };
34
+ /**
35
+ * Loads a schema and compiles it into a validator.
36
+ * @param logger - A logger for logging information.
37
+ */
38
+ export const compileAllSchemas = (logger, schemaService) => {
39
+ if (!schemaService) {
40
+ throw new Error('SchemaService needs to be defined to load schemas');
41
+ }
42
+ for (const [name, schema] of getSchemas()) {
43
+ schemaService.compileSchema(name, schema);
44
+ }
45
+ validateAllSchemasLoaded(logger, schemaService);
46
+ };
47
+ const validateAllSchemasLoaded = (logger, schemaService) => {
48
+ const { routesMeta } = getRoutes();
49
+ const validators = schemaService.getSchemaNames();
50
+ const missingSchemas = [];
51
+ for (const route of routesMeta) {
52
+ if (!route.input || validators.has(route.input)) {
53
+ continue;
54
+ }
55
+ missingSchemas.push(route.input);
56
+ }
57
+ if (missingSchemas.length > 0) {
58
+ logger.error(`Error: Failed to load schemas:\n.${missingSchemas.join('\n')}`);
59
+ logger.error('\tHave you run the schema generation?');
60
+ logger.error('\tnpx @pikku/cli schemas');
61
+ }
62
+ else {
63
+ logger.info('All schemas loaded');
64
+ }
65
+ };
66
+ export const coerceQueryStringToArray = (schemaName, data) => {
67
+ const schema = getSchema(schemaName);
68
+ for (const key in schema.properties) {
69
+ const property = schema.properties[key];
70
+ if (typeof property === 'boolean') {
71
+ continue;
72
+ }
73
+ const type = property.type;
74
+ if (typeof type === 'boolean') {
75
+ continue;
76
+ }
77
+ if (type === 'array' && typeof data[key] === 'string') {
78
+ data[key] = data[key].split(',');
79
+ }
80
+ }
81
+ };
82
+ export const validateAndCoerce = (logger, schemaService, schemaName, data, coerceToArray) => {
83
+ if (schemaService) {
84
+ if (!schemaName) {
85
+ if (data && (data.length > 0 || Object.keys(data).length > 0)) {
86
+ logger.warn('No schema provided, but data was passed');
87
+ throw new BadRequestError('No data expected');
88
+ }
89
+ else {
90
+ return;
91
+ }
92
+ }
93
+ const schema = getSchema(schemaName);
94
+ schemaService.compileSchema(schemaName, schema);
95
+ if (coerceToArray) {
96
+ coerceQueryStringToArray(schemaName, data);
97
+ }
98
+ schemaService.validateSchema(schemaName, data);
99
+ }
100
+ };
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Interface for handling content operations.
3
+ */
4
+ export interface ContentService {
5
+ /**
6
+ * Signs a content key to provide secure access.
7
+ * @param contentKey - The key of the content to sign.
8
+ * @returns A promise that resolves to the signed content key URL.
9
+ */
10
+ signContentKey: (contentKey: string, dateLessThan: Date, dateGreaterThan?: Date) => Promise<string>;
11
+ /**
12
+ * Signs a URL to provide secure access.
13
+ * @param url - The URL to sign.
14
+ * @returns A promise that resolves to the signed URL.
15
+ */
16
+ signURL: (url: string, dateLessThan: Date, dateGreaterThan?: Date) => Promise<string>;
17
+ /**
18
+ * Gets an upload URL for a file.
19
+ * @param fileKey - The key of the file to upload.
20
+ * @param contentType - The content type of the file.
21
+ * @returns A promise that resolves to an object containing the upload URL and asset key.
22
+ * This method generates an upload URL for the specified file key and content type, allowing the file to be uploaded.
23
+ */
24
+ getUploadURL: (fileKey: string, contentType: string) => Promise<{
25
+ uploadUrl: string;
26
+ assetKey: string;
27
+ }>;
28
+ /**
29
+ * Deletes a file.
30
+ * @param fileName - The name of the file to delete.
31
+ * @returns A promise that resolves to a boolean indicating success.
32
+ * This method deletes the specified file and returns a boolean indicating whether the deletion was successful.
33
+ */
34
+ deleteFile?: (fileName: string) => Promise<boolean>;
35
+ /**
36
+ * Writes a file.
37
+ * @param assetKey - The key of the asset to write.
38
+ * @param buffer - The buffer containing the file data.
39
+ * @returns A promise that resolves to a boolean indicating success.
40
+ */
41
+ writeFile?: (assetKey: string, buffer: Buffer) => Promise<boolean>;
42
+ /**
43
+ * This method copies the file from the specified absolute path to the location identified by the asset key and returns a boolean indicating success.
44
+ * @param assetKey - The key of the asset to copy.
45
+ * @param fromAbsolutePath - The absolute path of the source file.
46
+ * @returns A promise that resolves to a boolean indicating success.
47
+ */
48
+ copyFile?: (assetKey: string, fromAbsolutePath: string) => Promise<boolean>;
49
+ /**
50
+ * Reads a file.
51
+ * @param assetKey - The key of the asset to read.
52
+ * @returns A promise that resolves to a buffer containing the file data.
53
+ */
54
+ readFile?: (assetKey: string) => Promise<Buffer>;
55
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @module @pikku/core
3
+ */
4
+ export * from './content-service.js';
5
+ export * from './jwt-service.js';
6
+ export * from './logger.js';
7
+ export * from './logger-console.js';
8
+ export * from './secret-service.js';
9
+ export * from './variables-service.js';
10
+ export * from './schema-service.js';
11
+ export * from './local-secrets.js';
12
+ export * from './local-variables.js';
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @module @pikku/core
3
+ */
4
+ // Interfaces
5
+ export * from './content-service.js';
6
+ export * from './jwt-service.js';
7
+ export * from './logger.js';
8
+ export * from './logger-console.js';
9
+ export * from './secret-service.js';
10
+ export * from './variables-service.js';
11
+ export * from './schema-service.js';
12
+ // Local implementations
13
+ export * from './local-secrets.js';
14
+ export * from './local-variables.js';