@pikku/core 0.6.16 → 0.6.18
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.
- package/CHANGELOG.md +14 -0
- package/dist/channel/channel-handler.js +2 -2
- package/dist/channel/channel-runner.d.ts +2 -14
- package/dist/channel/channel-runner.js +5 -36
- package/dist/channel/channel-store.d.ts +9 -6
- package/dist/channel/index.d.ts +0 -1
- package/dist/channel/index.js +0 -1
- package/dist/channel/local/local-channel-runner.js +2 -2
- package/dist/channel/log-channels.js +2 -2
- package/dist/channel/serverless/serverless-channel-runner.js +8 -7
- package/dist/errors/error-handler.d.ts +1 -1
- package/dist/errors/error-handler.js +6 -14
- package/dist/errors/errors.d.ts +1 -1
- package/dist/errors/errors.js +2 -2
- package/dist/http/http-route-runner.d.ts +3 -23
- package/dist/http/http-route-runner.js +13 -82
- package/dist/http/index.d.ts +1 -1
- package/dist/http/index.js +1 -1
- package/dist/http/log-http-routes.js +2 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/middleware/auth-apikey.d.ts +15 -0
- package/dist/middleware/auth-apikey.js +36 -0
- package/dist/middleware/auth-bearer.d.ts +12 -0
- package/dist/middleware/auth-bearer.js +40 -0
- package/dist/middleware/auth-cookie.d.ts +16 -0
- package/dist/middleware/auth-cookie.js +43 -0
- package/dist/middleware/index.d.ts +3 -4
- package/dist/middleware/index.js +3 -4
- package/dist/middleware/timeout.d.ts +2 -0
- package/dist/middleware/timeout.js +10 -0
- package/dist/middleware-runner.d.ts +1 -1
- package/dist/pikku-state.d.ts +29 -0
- package/dist/pikku-state.js +30 -0
- package/dist/scheduler/index.d.ts +1 -1
- package/dist/scheduler/index.js +1 -1
- package/dist/scheduler/log-schedulers.js +2 -2
- package/dist/scheduler/scheduler-runner.d.ts +1 -11
- package/dist/scheduler/scheduler-runner.js +5 -33
- package/dist/schema.js +2 -2
- package/dist/services/jwt-service.d.ts +1 -10
- package/dist/services/user-session-service.d.ts +2 -2
- package/dist/services/user-session-service.js +6 -6
- package/dist/types/core.types.d.ts +3 -3
- package/lcov.info +814 -907
- package/package.json +2 -1
- package/src/channel/channel-handler.ts +2 -2
- package/src/channel/channel-runner.ts +4 -43
- package/src/channel/channel-store.ts +8 -11
- package/src/channel/index.ts +0 -1
- package/src/channel/local/local-channel-runner.test.ts +10 -20
- package/src/channel/local/local-channel-runner.ts +2 -2
- package/src/channel/log-channels.ts +2 -2
- package/src/channel/serverless/serverless-channel-runner.ts +10 -9
- package/src/errors/error-handler.ts +7 -18
- package/src/errors/errors.ts +2 -3
- package/src/handle-error.ts +0 -1
- package/src/http/http-route-runner.test.ts +3 -2
- package/src/http/http-route-runner.ts +18 -99
- package/src/http/index.ts +1 -6
- package/src/http/log-http-routes.ts +2 -2
- package/src/index.ts +2 -1
- package/src/middleware/auth-apikey.ts +65 -0
- package/src/middleware/auth-bearer.ts +65 -0
- package/src/middleware/auth-cookie.ts +76 -0
- package/src/middleware/index.ts +3 -4
- package/src/middleware/timeout.ts +13 -0
- package/src/middleware-runner.ts +1 -1
- package/src/pikku-state.ts +70 -0
- package/src/scheduler/index.ts +1 -7
- package/src/scheduler/log-schedulers.ts +2 -2
- package/src/scheduler/scheduler-runner.ts +6 -45
- package/src/schema.ts +2 -2
- package/src/services/jwt-service.ts +1 -12
- package/src/services/user-session-service.ts +8 -6
- package/src/types/core.types.ts +3 -6
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/channel/eventhub-forwarder.d.ts +0 -17
- package/dist/channel/eventhub-forwarder.js +0 -1
- package/dist/middleware/auth-api-key.d.ts +0 -9
- package/dist/middleware/auth-api-key.js +0 -23
- package/dist/middleware/auth-cookie-middleware.d.ts +0 -11
- package/dist/middleware/auth-cookie-middleware.js +0 -36
- package/dist/middleware/auth-jwt-middleware.d.ts +0 -10
- package/dist/middleware/auth-jwt-middleware.js +0 -32
- package/dist/middleware/auth-query-middleware.d.ts +0 -10
- package/dist/middleware/auth-query-middleware.js +0 -21
- package/src/channel/eventhub-forwarder.ts +0 -25
- package/src/middleware/auth-api-key.ts +0 -32
- package/src/middleware/auth-cookie-middleware.ts +0 -54
- package/src/middleware/auth-jwt-middleware.ts +0 -47
- package/src/middleware/auth-query-middleware.ts +0 -33
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
## 0.6
|
|
2
2
|
|
|
3
|
+
## 0.6.18
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 6be081b: fix: export addMiddleware correctly
|
|
8
|
+
|
|
9
|
+
## 0.6.17
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- ebc04eb: refactor: move all global state into pikku state
|
|
14
|
+
- 8a14f3a: refactor: removing user session from channel object
|
|
15
|
+
- 2c47386: refactor: improving middleware
|
|
16
|
+
|
|
3
17
|
## 0.6.16
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { verifyPermissions } from '../permissions.js';
|
|
2
|
-
import {
|
|
2
|
+
import { pikkuState } from '../pikku-state.js';
|
|
3
3
|
const validateSchema = (logger, data, channelName, routingProperty, routerValue) => {
|
|
4
|
-
const
|
|
4
|
+
const channelsMeta = pikkuState('channel', 'meta');
|
|
5
5
|
for (const channelMeta of channelsMeta) {
|
|
6
6
|
if (routingProperty && routerValue) {
|
|
7
7
|
const channelRoute = channelMeta.messageRoutes[routingProperty]?.[routerValue];
|
|
@@ -1,25 +1,13 @@
|
|
|
1
1
|
import { UserSessionService } from '../services/user-session-service.js';
|
|
2
|
-
import { CoreAPIChannel,
|
|
3
|
-
/**
|
|
4
|
-
* Returns all the registered routes and associated metadata.
|
|
5
|
-
* @internal
|
|
6
|
-
*/
|
|
7
|
-
export declare const getChannels: () => {
|
|
8
|
-
channels: CoreAPIChannels;
|
|
9
|
-
channelsMeta: ChannelsMeta;
|
|
10
|
-
};
|
|
2
|
+
import { CoreAPIChannel, RunChannelOptions, RunChannelParams } from './channel.types.js';
|
|
11
3
|
export declare const addChannel: <In, Channel extends string, ChannelFunction, ChannelFunctionSessionless, APIPermission>(channel: CoreAPIChannel<In, Channel, ChannelFunction, ChannelFunctionSessionless, APIPermission>) => void;
|
|
12
|
-
/**
|
|
13
|
-
* @ignore
|
|
14
|
-
*/
|
|
15
|
-
export declare const setChannelsMeta: (_channelsMeta: ChannelsMeta) => void;
|
|
16
4
|
export declare const getMatchingChannelConfig: (request: string) => {
|
|
17
5
|
matchedPath: import("path-to-regexp").MatchResult<Partial<Record<string, string | string[]>>>;
|
|
18
6
|
params: Partial<Record<string, string | string[]>>;
|
|
19
7
|
channelConfig: CoreAPIChannel<any, string, import("./channel.types.js").CoreChannelConnection<any, unknown, import("../index.js").CoreServices>, import("./channel.types.js").CoreChannelDisconnection<any, import("../index.js").CoreServices>, import("./channel.types.js").CoreChannelMessage<unknown, unknown, unknown, import("../index.js").CoreServices>, import("./channel.types.js").CoreChannelMessage<unknown, unknown, unknown, import("../index.js").CoreServices>, import("../index.js").CoreAPIPermission<any>>;
|
|
20
8
|
schemaName: string | null | undefined;
|
|
21
9
|
} | null;
|
|
22
|
-
export declare const openChannel: ({ route, singletonServices, coerceToArray, http,
|
|
10
|
+
export declare const openChannel: ({ route, singletonServices, coerceToArray, http, }: Pick<CoreAPIChannel<unknown, string>, "route"> & Omit<RunChannelParams<unknown>, "response" | "request"> & {
|
|
23
11
|
userSessionService?: UserSessionService<any>;
|
|
24
12
|
} & RunChannelOptions) => Promise<{
|
|
25
13
|
openingData: unknown;
|
|
@@ -1,44 +1,13 @@
|
|
|
1
1
|
import { NotFoundError } from '../errors/errors.js';
|
|
2
|
+
import { pikkuState } from '../pikku-state.js';
|
|
2
3
|
import { coerceQueryStringToArray, validateSchema } from '../schema.js';
|
|
3
4
|
import { match } from 'path-to-regexp';
|
|
4
|
-
if (!globalThis.pikku?.channels) {
|
|
5
|
-
globalThis.pikku = globalThis.pikku || {};
|
|
6
|
-
globalThis.pikku.channels = [];
|
|
7
|
-
globalThis.pikku.channelsMeta = [];
|
|
8
|
-
}
|
|
9
|
-
const channels = (data) => {
|
|
10
|
-
if (data) {
|
|
11
|
-
globalThis.pikku.channels = data;
|
|
12
|
-
}
|
|
13
|
-
return globalThis.pikku.channels;
|
|
14
|
-
};
|
|
15
|
-
const channelsMeta = (data) => {
|
|
16
|
-
if (data) {
|
|
17
|
-
globalThis.pikku.channelsMeta = data;
|
|
18
|
-
}
|
|
19
|
-
return globalThis.pikku.channelsMeta;
|
|
20
|
-
};
|
|
21
|
-
/**
|
|
22
|
-
* Returns all the registered routes and associated metadata.
|
|
23
|
-
* @internal
|
|
24
|
-
*/
|
|
25
|
-
export const getChannels = () => {
|
|
26
|
-
return {
|
|
27
|
-
channels: channels(),
|
|
28
|
-
channelsMeta: channelsMeta(),
|
|
29
|
-
};
|
|
30
|
-
};
|
|
31
5
|
export const addChannel = (channel) => {
|
|
32
|
-
channels
|
|
33
|
-
};
|
|
34
|
-
/**
|
|
35
|
-
* @ignore
|
|
36
|
-
*/
|
|
37
|
-
export const setChannelsMeta = (_channelsMeta) => {
|
|
38
|
-
channelsMeta(_channelsMeta);
|
|
6
|
+
pikkuState('channel', 'channels').push(channel);
|
|
39
7
|
};
|
|
40
8
|
export const getMatchingChannelConfig = (request) => {
|
|
41
|
-
const
|
|
9
|
+
const channels = pikkuState('channel', 'channels');
|
|
10
|
+
const channelsMeta = pikkuState('channel', 'meta');
|
|
42
11
|
for (const channelConfig of channels) {
|
|
43
12
|
const cleanedRoute = channelConfig.route.replace(/^\/\//, '/');
|
|
44
13
|
const cleanedRequest = request.replace(/^\/\//, '/');
|
|
@@ -58,7 +27,7 @@ export const getMatchingChannelConfig = (request) => {
|
|
|
58
27
|
}
|
|
59
28
|
return null;
|
|
60
29
|
};
|
|
61
|
-
export const openChannel = async ({ route, singletonServices, coerceToArray = false, http,
|
|
30
|
+
export const openChannel = async ({ route, singletonServices, coerceToArray = false, http, }) => {
|
|
62
31
|
const matchingChannel = getMatchingChannelConfig(route);
|
|
63
32
|
if (!matchingChannel) {
|
|
64
33
|
singletonServices.logger.info(`Channel not found: ${route}`);
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import { CoreUserSession } from '../types/core.types.js';
|
|
2
|
-
export type Channel<ChannelType = unknown, OpeningData = unknown
|
|
2
|
+
export type Channel<ChannelType = unknown, OpeningData = unknown> = {
|
|
3
3
|
channelId: string;
|
|
4
4
|
channelName: string;
|
|
5
5
|
channelObject?: ChannelType;
|
|
6
6
|
openingData?: OpeningData;
|
|
7
|
-
userSession?: UserSession;
|
|
8
7
|
};
|
|
9
|
-
export declare abstract class ChannelStore<ChannelType = unknown, OpeningData = unknown, UserSession extends CoreUserSession = CoreUserSession, TypedChannel = Channel<ChannelType, OpeningData
|
|
10
|
-
abstract addChannel(channel: Channel<ChannelType, OpeningData
|
|
8
|
+
export declare abstract class ChannelStore<ChannelType = unknown, OpeningData = unknown, UserSession extends CoreUserSession = CoreUserSession, TypedChannel = Channel<ChannelType, OpeningData>> {
|
|
9
|
+
abstract addChannel(channel: Channel<ChannelType, OpeningData>): Promise<void> | void;
|
|
11
10
|
abstract removeChannels(channelId: string[]): Promise<void> | void;
|
|
12
|
-
abstract setUserSession(channelId: string, userSession:
|
|
13
|
-
abstract
|
|
11
|
+
abstract setUserSession(channelId: string, userSession: UserSession | null): Promise<void> | void;
|
|
12
|
+
abstract getChannelAndSession(channelId: string): Promise<TypedChannel & {
|
|
13
|
+
session: UserSession;
|
|
14
|
+
}> | (TypedChannel & {
|
|
15
|
+
session: UserSession;
|
|
16
|
+
});
|
|
14
17
|
}
|
package/dist/channel/index.d.ts
CHANGED
|
@@ -3,7 +3,6 @@ export * from './channel.types.js';
|
|
|
3
3
|
export * from './log-channels.js';
|
|
4
4
|
export * from './pikku-abstract-channel-handler.js';
|
|
5
5
|
export * from './eventhub-service.js';
|
|
6
|
-
export * from './eventhub-forwarder.js';
|
|
7
6
|
export * from './eventhub-service.js';
|
|
8
7
|
export * from './channel-store.js';
|
|
9
8
|
export * from './eventhub-store.js';
|
package/dist/channel/index.js
CHANGED
|
@@ -3,7 +3,6 @@ export * from './channel.types.js';
|
|
|
3
3
|
export * from './log-channels.js';
|
|
4
4
|
export * from './pikku-abstract-channel-handler.js';
|
|
5
5
|
export * from './eventhub-service.js';
|
|
6
|
-
export * from './eventhub-forwarder.js';
|
|
7
6
|
export * from './eventhub-service.js';
|
|
8
7
|
export * from './channel-store.js';
|
|
9
8
|
export * from './eventhub-store.js';
|
|
@@ -32,7 +32,7 @@ export const runLocalChannel = async ({ singletonServices, channelId, request, r
|
|
|
32
32
|
const allServices = {
|
|
33
33
|
...singletonServices,
|
|
34
34
|
...sessionServices,
|
|
35
|
-
userSessionService,
|
|
35
|
+
userSession: userSessionService,
|
|
36
36
|
};
|
|
37
37
|
channelHandler.registerOnOpen(() => {
|
|
38
38
|
channelConfig.onConnect?.(allServices, channel);
|
|
@@ -56,7 +56,7 @@ export const runLocalChannel = async ({ singletonServices, channelId, request, r
|
|
|
56
56
|
};
|
|
57
57
|
await runMiddleware({
|
|
58
58
|
...singletonServices,
|
|
59
|
-
userSessionService,
|
|
59
|
+
userSession: userSessionService,
|
|
60
60
|
}, { http }, route.middleware || [], main);
|
|
61
61
|
return channelHandler;
|
|
62
62
|
};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { pikkuState } from '../pikku-state.js';
|
|
2
2
|
/**
|
|
3
3
|
* Logs all the loaded channels.
|
|
4
4
|
* @param logger - A logger for logging information.
|
|
5
5
|
*/
|
|
6
6
|
export const logChannels = (logger) => {
|
|
7
|
-
const
|
|
7
|
+
const channels = pikkuState('channel', 'channels');
|
|
8
8
|
if (channels.length === 0) {
|
|
9
9
|
logger.info('No channels added');
|
|
10
10
|
return;
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { closeSessionServices } from '../../utils.js';
|
|
2
2
|
import { processMessageHandlers } from '../channel-handler.js';
|
|
3
|
-
import {
|
|
3
|
+
import { openChannel } from '../channel-runner.js';
|
|
4
4
|
import { createHTTPInteraction } from '../../http/http-route-runner.js';
|
|
5
5
|
import { handleError } from '../../handle-error.js';
|
|
6
6
|
import { RemoteUserSessionService } from '../../services/user-session-service.js';
|
|
7
7
|
import { runMiddleware } from '../../middleware-runner.js';
|
|
8
|
+
import { pikkuState } from '../../pikku-state.js';
|
|
8
9
|
const getVariablesForChannel = ({ channelId, channelName, channelHandlerFactory, openingData, }) => {
|
|
9
|
-
const
|
|
10
|
+
const channels = pikkuState('channel', 'channels');
|
|
10
11
|
const channelConfig = channels.find((channelConfig) => channelConfig.name === channelName);
|
|
11
12
|
if (!channelConfig) {
|
|
12
13
|
throw new Error(`Channel not found: ${channelName}`);
|
|
@@ -60,19 +61,19 @@ export const runChannelConnect = async ({ singletonServices, channelId, channelO
|
|
|
60
61
|
};
|
|
61
62
|
await runMiddleware({
|
|
62
63
|
...singletonServices,
|
|
63
|
-
userSessionService,
|
|
64
|
+
userSession: userSessionService,
|
|
64
65
|
}, { http }, channelConfig.middleware || [], main);
|
|
65
66
|
};
|
|
66
67
|
export const runChannelDisconnect = async ({ singletonServices, ...params }) => {
|
|
67
68
|
let sessionServices;
|
|
68
|
-
const {
|
|
69
|
+
const { openingData, channelName, session } = await params.channelStore.getChannelAndSession(params.channelId);
|
|
69
70
|
const { channel, channelConfig } = getVariablesForChannel({
|
|
70
71
|
...params,
|
|
71
72
|
openingData,
|
|
72
73
|
channelName,
|
|
73
74
|
});
|
|
74
75
|
if (!sessionServices && params.createSessionServices) {
|
|
75
|
-
sessionServices = await params.createSessionServices(singletonServices, {},
|
|
76
|
+
sessionServices = await params.createSessionServices(singletonServices, {}, session);
|
|
76
77
|
}
|
|
77
78
|
await channelConfig.onDisconnect?.({ ...singletonServices, ...sessionServices }, channel);
|
|
78
79
|
await params.channelStore.removeChannels([channel.channelId]);
|
|
@@ -82,14 +83,14 @@ export const runChannelDisconnect = async ({ singletonServices, ...params }) =>
|
|
|
82
83
|
};
|
|
83
84
|
export const runChannelMessage = async ({ singletonServices, ...params }, data) => {
|
|
84
85
|
let sessionServices;
|
|
85
|
-
const {
|
|
86
|
+
const { openingData, channelName, session } = await params.channelStore.getChannelAndSession(params.channelId);
|
|
86
87
|
const { channelHandler, channelConfig } = getVariablesForChannel({
|
|
87
88
|
...params,
|
|
88
89
|
openingData,
|
|
89
90
|
channelName,
|
|
90
91
|
});
|
|
91
92
|
if (params.createSessionServices) {
|
|
92
|
-
sessionServices = await params.createSessionServices(singletonServices, {},
|
|
93
|
+
sessionServices = await params.createSessionServices(singletonServices, {}, session);
|
|
93
94
|
}
|
|
94
95
|
let response;
|
|
95
96
|
try {
|
|
@@ -16,7 +16,7 @@ export interface ErrorDetails {
|
|
|
16
16
|
status: number;
|
|
17
17
|
message: string;
|
|
18
18
|
}
|
|
19
|
-
export declare const getErrors: () => Map<
|
|
19
|
+
export declare const getErrors: () => Map<PikkuError, ErrorDetails>;
|
|
20
20
|
/**
|
|
21
21
|
* Adds an error to the API errors map.
|
|
22
22
|
* @param error - The error to add.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { pikkuState } from '../pikku-state.js';
|
|
1
2
|
/**
|
|
2
3
|
* Base class for custom errors.
|
|
3
4
|
* @extends {Error}
|
|
@@ -12,24 +13,14 @@ export class PikkuError extends Error {
|
|
|
12
13
|
Object.setPrototypeOf(this, new.target.prototype);
|
|
13
14
|
}
|
|
14
15
|
}
|
|
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();
|
|
16
|
+
export const getErrors = () => pikkuState('errors', 'errors');
|
|
26
17
|
/**
|
|
27
18
|
* Adds an error to the API errors map.
|
|
28
19
|
* @param error - The error to add.
|
|
29
20
|
* @param details - The details of the error.
|
|
30
21
|
*/
|
|
31
22
|
export const addError = (error, { status, message }) => {
|
|
32
|
-
|
|
23
|
+
pikkuState('errors', 'errors').set(error, { status, message });
|
|
33
24
|
};
|
|
34
25
|
/**
|
|
35
26
|
* Adds multiple errors to the API errors map.
|
|
@@ -46,9 +37,10 @@ export const addErrors = (errors) => {
|
|
|
46
37
|
* @returns An object containing the status and message, or undefined if the error is not found.
|
|
47
38
|
*/
|
|
48
39
|
export const getErrorResponse = (error) => {
|
|
49
|
-
const
|
|
40
|
+
const errors = Array.from(pikkuState('errors', 'errors').entries());
|
|
41
|
+
const foundError = errors.find(([e]) => e.name === error.constructor.name);
|
|
50
42
|
if (foundError) {
|
|
51
43
|
return foundError[1];
|
|
52
44
|
}
|
|
53
|
-
return
|
|
45
|
+
return pikkuState('errors', 'errors').get(error);
|
|
54
46
|
};
|
package/dist/errors/errors.d.ts
CHANGED
|
@@ -69,7 +69,7 @@ export declare class NotAcceptableError extends PikkuError {
|
|
|
69
69
|
export declare class ProxyAuthenticationRequiredError extends PikkuError {
|
|
70
70
|
}
|
|
71
71
|
/**
|
|
72
|
-
* The server
|
|
72
|
+
* The server request expired
|
|
73
73
|
* @group Error
|
|
74
74
|
*/
|
|
75
75
|
export declare class RequestTimeoutError extends PikkuError {
|
package/dist/errors/errors.js
CHANGED
|
@@ -114,14 +114,14 @@ addError(ProxyAuthenticationRequiredError, {
|
|
|
114
114
|
message: 'The client must authenticate itself to get the requested response.',
|
|
115
115
|
});
|
|
116
116
|
/**
|
|
117
|
-
* The server
|
|
117
|
+
* The server request expired
|
|
118
118
|
* @group Error
|
|
119
119
|
*/
|
|
120
120
|
export class RequestTimeoutError extends PikkuError {
|
|
121
121
|
}
|
|
122
122
|
addError(RequestTimeoutError, {
|
|
123
123
|
status: 408,
|
|
124
|
-
message: 'The
|
|
124
|
+
message: 'The request timeout has expired.',
|
|
125
125
|
});
|
|
126
126
|
/**
|
|
127
127
|
* The request could not be completed due to a conflict with the current state of the target resource.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { CoreHTTPFunctionRoute,
|
|
1
|
+
import { CoreHTTPFunctionRoute, RunRouteOptions, RunRouteParams, PikkuHTTP } from './http-routes.types.js';
|
|
2
|
+
import { PikkuMiddleware } from '../types/core.types.js';
|
|
2
3
|
import { PikkuRequest } from '../pikku-request.js';
|
|
3
4
|
import { PikkuResponse } from '../pikku-response.js';
|
|
4
5
|
/**
|
|
@@ -7,34 +8,13 @@ import { PikkuResponse } from '../pikku-response.js';
|
|
|
7
8
|
* @param {APIMiddleware[] | string} routeOrMiddleware - Route pattern to match or middleware array
|
|
8
9
|
* @param {APIMiddleware} [middleware] - Middleware to add (required if first param is a string)
|
|
9
10
|
*/
|
|
10
|
-
export declare const addMiddleware: <APIMiddleware>(routeOrMiddleware: APIMiddleware[] | string, middleware?: APIMiddleware) => void;
|
|
11
|
+
export declare const addMiddleware: <APIMiddleware extends PikkuMiddleware>(routeOrMiddleware: APIMiddleware[] | string, middleware?: APIMiddleware[]) => void;
|
|
11
12
|
/**
|
|
12
13
|
* Add a route to the global routes registry
|
|
13
14
|
*
|
|
14
15
|
* @param {CoreHTTPFunctionRoute} route - Route configuration to add
|
|
15
16
|
*/
|
|
16
17
|
export declare const addRoute: <In, Out, Route extends string, APIFunction, APIFunctionSessionless, APIPermission, APIMiddleware>(route: CoreHTTPFunctionRoute<In, Out, Route, APIFunction, APIFunctionSessionless, APIPermission, APIMiddleware>) => void;
|
|
17
|
-
/**
|
|
18
|
-
* Remove all routes from the global registry
|
|
19
|
-
*/
|
|
20
|
-
export declare const clearRoutes: () => void;
|
|
21
|
-
/**
|
|
22
|
-
* Set the HTTP routes metadata
|
|
23
|
-
*
|
|
24
|
-
* @param {HTTPRoutesMeta} routeMeta - Metadata for routes
|
|
25
|
-
* @ignore
|
|
26
|
-
*/
|
|
27
|
-
export declare const setHTTPRoutesMeta: (routeMeta: HTTPRoutesMeta) => void;
|
|
28
|
-
/**
|
|
29
|
-
* Returns all the registered routes and associated metadata
|
|
30
|
-
*
|
|
31
|
-
* @returns {Object} Object containing routes and routesMeta
|
|
32
|
-
* @internal
|
|
33
|
-
*/
|
|
34
|
-
export declare const getRoutes: () => {
|
|
35
|
-
routes: CoreHTTPFunctionRoute<any, any, any>[];
|
|
36
|
-
routesMeta: HTTPRoutesMeta;
|
|
37
|
-
};
|
|
38
18
|
/**
|
|
39
19
|
* Create an HTTP interaction object from request and response
|
|
40
20
|
*
|
|
@@ -9,51 +9,7 @@ import { coerceQueryStringToArray, validateSchema } from '../schema.js';
|
|
|
9
9
|
import { LocalUserSessionService } from '../services/user-session-service.js';
|
|
10
10
|
import { runMiddleware } from '../middleware-runner.js';
|
|
11
11
|
import { handleError } from '../handle-error.js';
|
|
12
|
-
|
|
13
|
-
* Initialize global state for HTTP routes and middleware if not already available
|
|
14
|
-
*/
|
|
15
|
-
if (!globalThis.pikku?.httpRoutes) {
|
|
16
|
-
globalThis.pikku = globalThis.pikku || {};
|
|
17
|
-
globalThis.pikku.httpMiddleware = [];
|
|
18
|
-
globalThis.pikku.httpRoutes = [];
|
|
19
|
-
globalThis.pikku.httpRoutesMeta = [];
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Get or set the global HTTP routes
|
|
23
|
-
*
|
|
24
|
-
* @param {CoreHTTPFunctionRoute<any, any, any>[]} [data] - Optional routes data to set
|
|
25
|
-
* @returns {CoreHTTPFunctionRoute<any, any, any>[]} Current routes
|
|
26
|
-
*/
|
|
27
|
-
const httpRoutes = (data) => {
|
|
28
|
-
if (data) {
|
|
29
|
-
globalThis.pikku.httpRoutes = data;
|
|
30
|
-
}
|
|
31
|
-
return globalThis.pikku.httpRoutes;
|
|
32
|
-
};
|
|
33
|
-
/**
|
|
34
|
-
* Get or set the global HTTP route metadata
|
|
35
|
-
*
|
|
36
|
-
* @param {HTTPRoutesMeta} [data] - Optional route metadata to set
|
|
37
|
-
* @returns {HTTPRoutesMeta} Current route metadata
|
|
38
|
-
*/
|
|
39
|
-
const httpRoutesMeta = (data) => {
|
|
40
|
-
if (data) {
|
|
41
|
-
globalThis.pikku.httpRoutesMeta = data;
|
|
42
|
-
}
|
|
43
|
-
return globalThis.pikku.httpRoutesMeta;
|
|
44
|
-
};
|
|
45
|
-
/**
|
|
46
|
-
* Get or set the global HTTP middleware
|
|
47
|
-
*
|
|
48
|
-
* @param {HTTPRouteMiddleware[]} [data] - Optional middleware to set
|
|
49
|
-
* @returns {HTTPRouteMiddleware[]} Current middleware
|
|
50
|
-
*/
|
|
51
|
-
const httpMiddleware = (data) => {
|
|
52
|
-
if (data) {
|
|
53
|
-
globalThis.pikku.httpMiddleware = data;
|
|
54
|
-
}
|
|
55
|
-
return globalThis.pikku.httpMiddleware;
|
|
56
|
-
};
|
|
12
|
+
import { pikkuState } from '../pikku-state.js';
|
|
57
13
|
/**
|
|
58
14
|
* Add middleware to a specific route or globally
|
|
59
15
|
*
|
|
@@ -61,14 +17,14 @@ const httpMiddleware = (data) => {
|
|
|
61
17
|
* @param {APIMiddleware} [middleware] - Middleware to add (required if first param is a string)
|
|
62
18
|
*/
|
|
63
19
|
export const addMiddleware = (routeOrMiddleware, middleware) => {
|
|
64
|
-
if (typeof routeOrMiddleware === 'string') {
|
|
65
|
-
|
|
20
|
+
if (typeof routeOrMiddleware === 'string' && middleware) {
|
|
21
|
+
pikkuState('http', 'middleware').push({
|
|
66
22
|
route: routeOrMiddleware,
|
|
67
|
-
middleware
|
|
23
|
+
middleware,
|
|
68
24
|
});
|
|
69
25
|
}
|
|
70
26
|
else {
|
|
71
|
-
|
|
27
|
+
pikkuState('http', 'middleware').push({
|
|
72
28
|
route: '*',
|
|
73
29
|
middleware: routeOrMiddleware,
|
|
74
30
|
});
|
|
@@ -80,34 +36,7 @@ export const addMiddleware = (routeOrMiddleware, middleware) => {
|
|
|
80
36
|
* @param {CoreHTTPFunctionRoute} route - Route configuration to add
|
|
81
37
|
*/
|
|
82
38
|
export const addRoute = (route) => {
|
|
83
|
-
|
|
84
|
-
};
|
|
85
|
-
/**
|
|
86
|
-
* Remove all routes from the global registry
|
|
87
|
-
*/
|
|
88
|
-
export const clearRoutes = () => {
|
|
89
|
-
httpRoutes([]);
|
|
90
|
-
};
|
|
91
|
-
/**
|
|
92
|
-
* Set the HTTP routes metadata
|
|
93
|
-
*
|
|
94
|
-
* @param {HTTPRoutesMeta} routeMeta - Metadata for routes
|
|
95
|
-
* @ignore
|
|
96
|
-
*/
|
|
97
|
-
export const setHTTPRoutesMeta = (routeMeta) => {
|
|
98
|
-
httpRoutesMeta(routeMeta);
|
|
99
|
-
};
|
|
100
|
-
/**
|
|
101
|
-
* Returns all the registered routes and associated metadata
|
|
102
|
-
*
|
|
103
|
-
* @returns {Object} Object containing routes and routesMeta
|
|
104
|
-
* @internal
|
|
105
|
-
*/
|
|
106
|
-
export const getRoutes = () => {
|
|
107
|
-
return {
|
|
108
|
-
routes: httpRoutes(),
|
|
109
|
-
routesMeta: httpRoutesMeta(),
|
|
110
|
-
};
|
|
39
|
+
pikkuState('http', 'routes').push(route);
|
|
111
40
|
};
|
|
112
41
|
/**
|
|
113
42
|
* Find a route that matches the given request type and path
|
|
@@ -117,7 +46,10 @@ export const getRoutes = () => {
|
|
|
117
46
|
* @returns {Object | undefined} Matching route information or undefined if no match
|
|
118
47
|
*/
|
|
119
48
|
const getMatchingRoute = (requestType, requestPath) => {
|
|
120
|
-
|
|
49
|
+
const routes = pikkuState('http', 'routes');
|
|
50
|
+
const middleware = pikkuState('http', 'middleware');
|
|
51
|
+
const routesMeta = pikkuState('http', 'meta');
|
|
52
|
+
for (const route of routes) {
|
|
121
53
|
// Skip routes that don't match the request method
|
|
122
54
|
if (route.method !== requestType.toLowerCase()) {
|
|
123
55
|
continue;
|
|
@@ -130,12 +62,12 @@ const getMatchingRoute = (requestType, requestPath) => {
|
|
|
130
62
|
const matchedPath = matchFunc(requestPath.replace(/^\/\//, '/'));
|
|
131
63
|
if (matchedPath) {
|
|
132
64
|
// Get all middleware for this route
|
|
133
|
-
const globalMiddleware =
|
|
65
|
+
const globalMiddleware = middleware
|
|
134
66
|
.filter((m) => m.route === '*' || new RegExp(m.route).test(route.route))
|
|
135
67
|
.map((m) => m.middleware)
|
|
136
68
|
.flat();
|
|
137
69
|
// Find schema for this route
|
|
138
|
-
const schemaName =
|
|
70
|
+
const schemaName = routesMeta.find((routeMeta) => routeMeta.method === route.method && routeMeta.route === route.route)?.input;
|
|
139
71
|
return {
|
|
140
72
|
matchedPath,
|
|
141
73
|
params: matchedPath.params,
|
|
@@ -180,7 +112,6 @@ export const createHTTPInteraction = (request, response) => {
|
|
|
180
112
|
const executeRouteWithMiddleware = async (services, matchedRoute, http, options) => {
|
|
181
113
|
const { matchedPath, params, route, middleware, schemaName } = matchedRoute;
|
|
182
114
|
const { singletonServices, userSessionService, createSessionServices, skipUserSession, } = services;
|
|
183
|
-
const { coerceToArray } = options;
|
|
184
115
|
const requiresSession = route.auth !== false;
|
|
185
116
|
let sessionServices;
|
|
186
117
|
let result;
|
|
@@ -206,7 +137,7 @@ const executeRouteWithMiddleware = async (services, matchedRoute, http, options)
|
|
|
206
137
|
const data = await http?.request?.getData();
|
|
207
138
|
// Validate schema
|
|
208
139
|
validateSchema(singletonServices.logger, singletonServices.schemaService, schemaName, data);
|
|
209
|
-
if (coerceToArray && schemaName) {
|
|
140
|
+
if (options.coerceToArray && schemaName) {
|
|
210
141
|
coerceQueryStringToArray(schemaName, data);
|
|
211
142
|
}
|
|
212
143
|
// Run permission checks
|
package/dist/http/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export * from './pikku-http-abstract-request.js';
|
|
2
2
|
export * from './pikku-http-abstract-response.js';
|
|
3
3
|
export * from './log-http-routes.js';
|
|
4
|
-
export { runHTTPRoute,
|
|
4
|
+
export { runHTTPRoute, addRoute } from './http-route-runner.js';
|
|
5
5
|
export type * from './http-routes.types.js';
|
package/dist/http/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export * from './pikku-http-abstract-request.js';
|
|
2
2
|
export * from './pikku-http-abstract-response.js';
|
|
3
3
|
export * from './log-http-routes.js';
|
|
4
|
-
export { runHTTPRoute,
|
|
4
|
+
export { runHTTPRoute, addRoute } from './http-route-runner.js';
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { pikkuState } from '../pikku-state.js';
|
|
2
2
|
/**
|
|
3
3
|
* Logs all the loaded routes.
|
|
4
4
|
* @param logger - A logger for logging information.
|
|
5
5
|
*/
|
|
6
6
|
export const logRoutes = (logger) => {
|
|
7
|
-
const
|
|
7
|
+
const routes = pikkuState('http', 'routes');
|
|
8
8
|
if (routes.length === 0) {
|
|
9
9
|
logger.info('No routes added');
|
|
10
10
|
return;
|
package/dist/index.d.ts
CHANGED
|
@@ -11,7 +11,8 @@ export * from './channel/index.js';
|
|
|
11
11
|
export * from './scheduler/index.js';
|
|
12
12
|
export * from './errors/index.js';
|
|
13
13
|
export * from './middleware/index.js';
|
|
14
|
+
export { pikkuState } from './pikku-state.js';
|
|
14
15
|
export { runMiddleware } from './middleware-runner.js';
|
|
15
|
-
export { addRoute } from './http/http-route-runner.js';
|
|
16
|
+
export { addRoute, addMiddleware } from './http/http-route-runner.js';
|
|
16
17
|
export { addChannel } from './channel/channel-runner.js';
|
|
17
18
|
export { addScheduledTask } from './scheduler/scheduler-runner.js';
|
package/dist/index.js
CHANGED
|
@@ -11,7 +11,8 @@ export * from './channel/index.js';
|
|
|
11
11
|
export * from './scheduler/index.js';
|
|
12
12
|
export * from './errors/index.js';
|
|
13
13
|
export * from './middleware/index.js';
|
|
14
|
+
export { pikkuState } from './pikku-state.js';
|
|
14
15
|
export { runMiddleware } from './middleware-runner.js';
|
|
15
|
-
export { addRoute } from './http/http-route-runner.js';
|
|
16
|
+
export { addRoute, addMiddleware } from './http/http-route-runner.js';
|
|
16
17
|
export { addChannel } from './channel/channel-runner.js';
|
|
17
18
|
export { addScheduledTask } from './scheduler/scheduler-runner.js';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { CoreConfig, CoreSingletonServices, CoreUserSession, PikkuMiddleware } from '../types/core.types.js';
|
|
2
|
+
/**
|
|
3
|
+
* API key middleware that retrieves a session from the 'x-api-key' header using a provided callback.
|
|
4
|
+
*
|
|
5
|
+
* @param options.getSessionForAPIKey - A function that returns a session when provided an API key.
|
|
6
|
+
*/
|
|
7
|
+
export declare const authAPIKey: <SingletonServices extends CoreSingletonServices<CoreConfig>, UserSession extends CoreUserSession>({ source, getSessionForAPIKey, jwt, }: {
|
|
8
|
+
source: "header" | "query" | "all";
|
|
9
|
+
} & ({
|
|
10
|
+
getSessionForAPIKey?: undefined;
|
|
11
|
+
jwt?: true;
|
|
12
|
+
} | {
|
|
13
|
+
getSessionForAPIKey: (services: SingletonServices, apiKey: string) => Promise<any>;
|
|
14
|
+
jwt?: false;
|
|
15
|
+
})) => PikkuMiddleware;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API key middleware that retrieves a session from the 'x-api-key' header using a provided callback.
|
|
3
|
+
*
|
|
4
|
+
* @param options.getSessionForAPIKey - A function that returns a session when provided an API key.
|
|
5
|
+
*/
|
|
6
|
+
export const authAPIKey = ({ source, getSessionForAPIKey, jwt, }) => {
|
|
7
|
+
const middleware = async (services, { http }, next) => {
|
|
8
|
+
if (!http?.request || services.userSession.get()) {
|
|
9
|
+
return next();
|
|
10
|
+
}
|
|
11
|
+
let apiKey = null;
|
|
12
|
+
if (source === 'header' || source === 'all') {
|
|
13
|
+
apiKey = http.request.getHeader('x-api-key');
|
|
14
|
+
}
|
|
15
|
+
if (!apiKey && (source === 'query' || source === 'all')) {
|
|
16
|
+
apiKey = http.request.getQuery().apiKey;
|
|
17
|
+
}
|
|
18
|
+
if (apiKey) {
|
|
19
|
+
let userSession = null;
|
|
20
|
+
if (jwt) {
|
|
21
|
+
if (!services.jwt) {
|
|
22
|
+
throw new Error('JWT service is required for JWT decoding.');
|
|
23
|
+
}
|
|
24
|
+
userSession = await services.jwt.decode(apiKey);
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
userSession = await getSessionForAPIKey(services, apiKey);
|
|
28
|
+
}
|
|
29
|
+
if (userSession) {
|
|
30
|
+
await services.userSession.set(userSession);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return next();
|
|
34
|
+
};
|
|
35
|
+
return middleware;
|
|
36
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { CoreConfig, CoreSingletonServices, CoreUserSession, PikkuMiddleware } from '../types/core.types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Extracts the Bearer token from the Authorization header
|
|
4
|
+
*/
|
|
5
|
+
export declare const authBearer: <SingletonServices extends CoreSingletonServices<CoreConfig>, UserSession extends CoreUserSession>({ token, jwt, getSession, }?: {
|
|
6
|
+
token?: {
|
|
7
|
+
value: string;
|
|
8
|
+
userSession: UserSession;
|
|
9
|
+
};
|
|
10
|
+
jwt?: boolean;
|
|
11
|
+
getSession?: (services: SingletonServices, token: string) => Promise<UserSession> | UserSession;
|
|
12
|
+
}) => PikkuMiddleware;
|