@forestadmin/agent-bff 1.2.0 → 1.4.0

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 (45) hide show
  1. package/README.md +53 -5
  2. package/dist/agent/agent-stub.d.ts +3 -0
  3. package/dist/agent/agent-stub.js +19 -0
  4. package/dist/agent/build-agent-query.d.ts +8 -0
  5. package/dist/agent/build-agent-query.js +7 -0
  6. package/dist/api-key/agent-token.d.ts +8 -0
  7. package/dist/api-key/agent-token.js +34 -0
  8. package/dist/api-key/api-key-authenticator.d.ts +17 -0
  9. package/dist/api-key/api-key-authenticator.js +61 -0
  10. package/dist/api-key/api-key-client.d.ts +37 -0
  11. package/dist/api-key/api-key-client.js +85 -0
  12. package/dist/api-key/api-key-error.d.ts +20 -0
  13. package/dist/api-key/api-key-error.js +34 -0
  14. package/dist/api-key/api-key-middleware.d.ts +10 -0
  15. package/dist/api-key/api-key-middleware.js +47 -0
  16. package/dist/api-key/api-key-resolve-error.d.ts +16 -0
  17. package/dist/api-key/api-key-resolve-error.js +16 -0
  18. package/dist/api-key/api-key.d.ts +8 -0
  19. package/dist/api-key/api-key.js +23 -0
  20. package/dist/api-key/resolve-cache.d.ts +17 -0
  21. package/dist/api-key/resolve-cache.js +56 -0
  22. package/dist/auth/auth-mode-middleware.d.ts +7 -0
  23. package/dist/auth/auth-mode-middleware.js +53 -0
  24. package/dist/auth/auth-mode.d.ts +7 -0
  25. package/dist/auth/auth-mode.js +25 -0
  26. package/dist/cli-core.js +90 -3
  27. package/dist/config/env-config.d.ts +3 -0
  28. package/dist/config/env-config.js +15 -1
  29. package/dist/cors/cors-middleware.d.ts +9 -0
  30. package/dist/cors/cors-middleware.js +29 -0
  31. package/dist/cors/origin.d.ts +7 -0
  32. package/dist/cors/origin.js +47 -0
  33. package/dist/cors/per-key-origin.d.ts +3 -0
  34. package/dist/cors/per-key-origin.js +16 -0
  35. package/dist/http/bff-http-error.d.ts +34 -0
  36. package/dist/http/bff-http-error.js +55 -0
  37. package/dist/http/error-middleware.d.ts +7 -0
  38. package/dist/http/error-middleware.js +49 -0
  39. package/dist/index.d.ts +12 -0
  40. package/dist/index.js +26 -2
  41. package/dist/timezone/timezone-middleware.d.ts +7 -0
  42. package/dist/timezone/timezone-middleware.js +24 -0
  43. package/dist/timezone/timezone.d.ts +8 -0
  44. package/dist/timezone/timezone.js +35 -0
  45. package/package.json +1 -1
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = createErrorMiddleware;
4
+ const bff_http_error_1 = require("./bff-http-error");
5
+ const CLIENT_ERROR_TYPES = {
6
+ 413: 'payload_too_large',
7
+ 415: 'unsupported_media_type',
8
+ };
9
+ function clientErrorStatus(error) {
10
+ if (typeof error !== 'object' || error === null)
11
+ return undefined;
12
+ const { status, statusCode } = error;
13
+ const value = typeof status === 'number' ? status : statusCode;
14
+ return typeof value === 'number' && value >= 400 && value < 500 ? value : undefined;
15
+ }
16
+ function createErrorMiddleware({ logger }) {
17
+ return async function errorMiddleware(ctx, next) {
18
+ try {
19
+ await next();
20
+ }
21
+ catch (error) {
22
+ if ((0, bff_http_error_1.isSerializableError)(error)) {
23
+ if (error.retryAfter !== undefined)
24
+ ctx.set('Retry-After', String(error.retryAfter));
25
+ ctx.status = error.status;
26
+ ctx.body = (0, bff_http_error_1.toErrorBody)(error);
27
+ return;
28
+ }
29
+ const clientStatus = clientErrorStatus(error);
30
+ if (clientStatus !== undefined) {
31
+ ctx.status = clientStatus;
32
+ ctx.body = (0, bff_http_error_1.toErrorBody)({
33
+ status: clientStatus,
34
+ type: CLIENT_ERROR_TYPES[clientStatus] ?? 'invalid_request',
35
+ message: 'Invalid request',
36
+ });
37
+ return;
38
+ }
39
+ logger('Error', 'Unhandled BFF edge error', {
40
+ cause: error instanceof Error ? `${error.name}: ${error.message}` : String(error),
41
+ });
42
+ ctx.status = 500;
43
+ ctx.body = {
44
+ error: { type: 'internal_error', status: 500, message: 'Internal server error' },
45
+ };
46
+ }
47
+ };
48
+ }
49
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3ItbWlkZGxld2FyZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9odHRwL2Vycm9yLW1pZGRsZXdhcmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUF1QkEsd0NBbUNDO0FBdkRELHFEQUFvRTtBQU1wRSxNQUFNLGtCQUFrQixHQUEyQjtJQUNqRCxHQUFHLEVBQUUsbUJBQW1CO0lBQ3hCLEdBQUcsRUFBRSx3QkFBd0I7Q0FDOUIsQ0FBQztBQUVGLFNBQVMsaUJBQWlCLENBQUMsS0FBYztJQUN2QyxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsSUFBSSxLQUFLLEtBQUssSUFBSTtRQUFFLE9BQU8sU0FBUyxDQUFDO0lBRWxFLE1BQU0sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLEdBQUcsS0FBbUQsQ0FBQztJQUNuRixNQUFNLEtBQUssR0FBRyxPQUFPLE1BQU0sS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDO0lBRS9ELE9BQU8sT0FBTyxLQUFLLEtBQUssUUFBUSxJQUFJLEtBQUssSUFBSSxHQUFHLElBQUksS0FBSyxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7QUFDdEYsQ0FBQztBQUVELFNBQXdCLHFCQUFxQixDQUFDLEVBQUUsTUFBTSxFQUEwQjtJQUM5RSxPQUFPLEtBQUssVUFBVSxlQUFlLENBQUMsR0FBRyxFQUFFLElBQUk7UUFDN0MsSUFBSSxDQUFDO1lBQ0gsTUFBTSxJQUFJLEVBQUUsQ0FBQztRQUNmLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsSUFBSSxJQUFBLG9DQUFtQixFQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7Z0JBQy9CLElBQUksS0FBSyxDQUFDLFVBQVUsS0FBSyxTQUFTO29CQUFFLEdBQUcsQ0FBQyxHQUFHLENBQUMsYUFBYSxFQUFFLE1BQU0sQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztnQkFDckYsR0FBRyxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDO2dCQUMxQixHQUFHLENBQUMsSUFBSSxHQUFHLElBQUEsNEJBQVcsRUFBQyxLQUFLLENBQUMsQ0FBQztnQkFFOUIsT0FBTztZQUNULENBQUM7WUFFRCxNQUFNLFlBQVksR0FBRyxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUU5QyxJQUFJLFlBQVksS0FBSyxTQUFTLEVBQUUsQ0FBQztnQkFDL0IsR0FBRyxDQUFDLE1BQU0sR0FBRyxZQUFZLENBQUM7Z0JBQzFCLEdBQUcsQ0FBQyxJQUFJLEdBQUcsSUFBQSw0QkFBVyxFQUFDO29CQUNyQixNQUFNLEVBQUUsWUFBWTtvQkFDcEIsSUFBSSxFQUFFLGtCQUFrQixDQUFDLFlBQVksQ0FBQyxJQUFJLGlCQUFpQjtvQkFDM0QsT0FBTyxFQUFFLGlCQUFpQjtpQkFDM0IsQ0FBQyxDQUFDO2dCQUVILE9BQU87WUFDVCxDQUFDO1lBRUQsTUFBTSxDQUFDLE9BQU8sRUFBRSwwQkFBMEIsRUFBRTtnQkFDMUMsS0FBSyxFQUFFLEtBQUssWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDLElBQUksS0FBSyxLQUFLLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUM7YUFDbEYsQ0FBQyxDQUFDO1lBQ0gsR0FBRyxDQUFDLE1BQU0sR0FBRyxHQUFHLENBQUM7WUFDakIsR0FBRyxDQUFDLElBQUksR0FBRztnQkFDVCxLQUFLLEVBQUUsRUFBRSxJQUFJLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUUsdUJBQXVCLEVBQUU7YUFDakYsQ0FBQztRQUNKLENBQUM7SUFDSCxDQUFDLENBQUM7QUFDSixDQUFDIn0=
package/dist/index.d.ts CHANGED
@@ -18,4 +18,16 @@ export { issueBffAccessToken, BFF_ACCESS_TOKEN_TYPE } from './oauth/bff-token';
18
18
  export type { BffAccessTokenPayload } from './oauth/bff-token';
19
19
  export { createPkcePair } from './oauth/pkce';
20
20
  export { OAuthRequestError } from './oauth/oauth-error';
21
+ export { parseApiKey, hashApiKey, fingerprintApiKey } from './api-key/api-key';
22
+ export type { ParsedApiKey } from './api-key/api-key';
23
+ export { issueAgentToken, AGENT_TOKEN_EXPIRES_IN } from './api-key/agent-token';
24
+ export { default as ApiKeyClient, ApiKeyResolveError } from './api-key/api-key-client';
25
+ export type { ResolvedApiKeyIdentity, ApiKeyIdentityUser, ApiKeyClientOptions, } from './api-key/api-key-client';
26
+ export { default as createResolveCache } from './api-key/resolve-cache';
27
+ export type { ResolveCache, ResolveCacheOptions } from './api-key/resolve-cache';
28
+ export { default as createApiKeyAuthenticator } from './api-key/api-key-authenticator';
29
+ export type { ApiKeyAuthenticator, AuthenticatedApiKey, ApiKeyAuthenticatorOptions, } from './api-key/api-key-authenticator';
30
+ export { default as createApiKeyMiddleware, BFF_KEY_HEADER } from './api-key/api-key-middleware';
31
+ export { ApiKeyError, invalidApiKey, forestIdentityNotAllowed, invalidRequest, keyResolutionUnavailable, toErrorBody as toApiKeyErrorBody, } from './api-key/api-key-error';
32
+ export type { ApiKeyErrorType, ApiKeyErrorBody } from './api-key/api-key-error';
21
33
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.OAuthRequestError = exports.createPkcePair = exports.BFF_ACCESS_TOKEN_TYPE = exports.issueBffAccessToken = exports.ensureFreshServerAccess = exports.createTokenCipher = exports.createInMemorySessionStore = exports.createOAuthRoutes = exports.OAuthExchangeError = exports.ForestServerClient = exports.version = exports.createConsoleLogger = exports.DEFAULT_BFF_PORT = exports.ConfigurationError = exports.runCli = exports.REQUIRED_KEYS = exports.parseConfig = exports.BFFHttpServer = void 0;
6
+ exports.toApiKeyErrorBody = exports.keyResolutionUnavailable = exports.invalidRequest = exports.forestIdentityNotAllowed = exports.invalidApiKey = exports.ApiKeyError = exports.BFF_KEY_HEADER = exports.createApiKeyMiddleware = exports.createApiKeyAuthenticator = exports.createResolveCache = exports.ApiKeyResolveError = exports.ApiKeyClient = exports.AGENT_TOKEN_EXPIRES_IN = exports.issueAgentToken = exports.fingerprintApiKey = exports.hashApiKey = exports.parseApiKey = exports.OAuthRequestError = exports.createPkcePair = exports.BFF_ACCESS_TOKEN_TYPE = exports.issueBffAccessToken = exports.ensureFreshServerAccess = exports.createTokenCipher = exports.createInMemorySessionStore = exports.createOAuthRoutes = exports.OAuthExchangeError = exports.ForestServerClient = exports.version = exports.createConsoleLogger = exports.DEFAULT_BFF_PORT = exports.ConfigurationError = exports.runCli = exports.REQUIRED_KEYS = exports.parseConfig = exports.BFFHttpServer = void 0;
7
7
  var bff_http_server_1 = require("./http/bff-http-server");
8
8
  Object.defineProperty(exports, "BFFHttpServer", { enumerable: true, get: function () { return __importDefault(bff_http_server_1).default; } });
9
9
  var env_config_1 = require("./config/env-config");
@@ -37,4 +37,28 @@ var pkce_1 = require("./oauth/pkce");
37
37
  Object.defineProperty(exports, "createPkcePair", { enumerable: true, get: function () { return pkce_1.createPkcePair; } });
38
38
  var oauth_error_1 = require("./oauth/oauth-error");
39
39
  Object.defineProperty(exports, "OAuthRequestError", { enumerable: true, get: function () { return oauth_error_1.OAuthRequestError; } });
40
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsMERBQWtFO0FBQXpELGlJQUFBLE9BQU8sT0FBaUI7QUFDakMsa0RBQWlFO0FBQXhELHlHQUFBLFdBQVcsT0FBQTtBQUFFLDJHQUFBLGFBQWEsT0FBQTtBQUVuQyx1Q0FBK0M7QUFBdEMsbUhBQUEsT0FBTyxPQUFVO0FBQzFCLG1DQUE4QztBQUFyQyw0R0FBQSxrQkFBa0IsT0FBQTtBQUMzQix1Q0FBeUQ7QUFBaEQsNkhBQUEsT0FBTyxPQUFvQjtBQUNwQyw0REFBMkU7QUFBbEUsc0lBQUEsT0FBTyxPQUF1QjtBQUV2QyxxQ0FBK0M7QUFBdEMsbUhBQUEsT0FBTyxPQUFXO0FBQzNCLHFFQUFpRztBQUF4RiwySUFBQSxPQUFPLE9BQXNCO0FBQUUsMEhBQUEsa0JBQWtCLE9BQUE7QUFNMUQscURBQW9FO0FBQTNELGtJQUFBLE9BQU8sT0FBcUI7QUFDckMsdURBQThFO0FBQXJFLDRJQUFBLE9BQU8sT0FBOEI7QUFFOUMscURBQW9FO0FBQTNELGtJQUFBLE9BQU8sT0FBcUI7QUFDckMsK0RBQStFO0FBQXRFLDZJQUFBLE9BQU8sT0FBMkI7QUFDM0MsK0NBQStFO0FBQXRFLGdIQUFBLG1CQUFtQixPQUFBO0FBQUUsa0hBQUEscUJBQXFCLE9BQUE7QUFFbkQscUNBQThDO0FBQXJDLHNHQUFBLGNBQWMsT0FBQTtBQUN2QixtREFBd0Q7QUFBL0MsZ0hBQUEsaUJBQWlCLE9BQUEifQ==
40
+ var api_key_1 = require("./api-key/api-key");
41
+ Object.defineProperty(exports, "parseApiKey", { enumerable: true, get: function () { return api_key_1.parseApiKey; } });
42
+ Object.defineProperty(exports, "hashApiKey", { enumerable: true, get: function () { return api_key_1.hashApiKey; } });
43
+ Object.defineProperty(exports, "fingerprintApiKey", { enumerable: true, get: function () { return api_key_1.fingerprintApiKey; } });
44
+ var agent_token_1 = require("./api-key/agent-token");
45
+ Object.defineProperty(exports, "issueAgentToken", { enumerable: true, get: function () { return agent_token_1.issueAgentToken; } });
46
+ Object.defineProperty(exports, "AGENT_TOKEN_EXPIRES_IN", { enumerable: true, get: function () { return agent_token_1.AGENT_TOKEN_EXPIRES_IN; } });
47
+ var api_key_client_1 = require("./api-key/api-key-client");
48
+ Object.defineProperty(exports, "ApiKeyClient", { enumerable: true, get: function () { return __importDefault(api_key_client_1).default; } });
49
+ Object.defineProperty(exports, "ApiKeyResolveError", { enumerable: true, get: function () { return api_key_client_1.ApiKeyResolveError; } });
50
+ var resolve_cache_1 = require("./api-key/resolve-cache");
51
+ Object.defineProperty(exports, "createResolveCache", { enumerable: true, get: function () { return __importDefault(resolve_cache_1).default; } });
52
+ var api_key_authenticator_1 = require("./api-key/api-key-authenticator");
53
+ Object.defineProperty(exports, "createApiKeyAuthenticator", { enumerable: true, get: function () { return __importDefault(api_key_authenticator_1).default; } });
54
+ var api_key_middleware_1 = require("./api-key/api-key-middleware");
55
+ Object.defineProperty(exports, "createApiKeyMiddleware", { enumerable: true, get: function () { return __importDefault(api_key_middleware_1).default; } });
56
+ Object.defineProperty(exports, "BFF_KEY_HEADER", { enumerable: true, get: function () { return api_key_middleware_1.BFF_KEY_HEADER; } });
57
+ var api_key_error_1 = require("./api-key/api-key-error");
58
+ Object.defineProperty(exports, "ApiKeyError", { enumerable: true, get: function () { return api_key_error_1.ApiKeyError; } });
59
+ Object.defineProperty(exports, "invalidApiKey", { enumerable: true, get: function () { return api_key_error_1.invalidApiKey; } });
60
+ Object.defineProperty(exports, "forestIdentityNotAllowed", { enumerable: true, get: function () { return api_key_error_1.forestIdentityNotAllowed; } });
61
+ Object.defineProperty(exports, "invalidRequest", { enumerable: true, get: function () { return api_key_error_1.invalidRequest; } });
62
+ Object.defineProperty(exports, "keyResolutionUnavailable", { enumerable: true, get: function () { return api_key_error_1.keyResolutionUnavailable; } });
63
+ Object.defineProperty(exports, "toApiKeyErrorBody", { enumerable: true, get: function () { return api_key_error_1.toErrorBody; } });
64
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsMERBQWtFO0FBQXpELGlJQUFBLE9BQU8sT0FBaUI7QUFDakMsa0RBQWlFO0FBQXhELHlHQUFBLFdBQVcsT0FBQTtBQUFFLDJHQUFBLGFBQWEsT0FBQTtBQUVuQyx1Q0FBK0M7QUFBdEMsbUhBQUEsT0FBTyxPQUFVO0FBQzFCLG1DQUE4QztBQUFyQyw0R0FBQSxrQkFBa0IsT0FBQTtBQUMzQix1Q0FBeUQ7QUFBaEQsNkhBQUEsT0FBTyxPQUFvQjtBQUNwQyw0REFBMkU7QUFBbEUsc0lBQUEsT0FBTyxPQUF1QjtBQUV2QyxxQ0FBK0M7QUFBdEMsbUhBQUEsT0FBTyxPQUFXO0FBQzNCLHFFQUFpRztBQUF4RiwySUFBQSxPQUFPLE9BQXNCO0FBQUUsMEhBQUEsa0JBQWtCLE9BQUE7QUFNMUQscURBQW9FO0FBQTNELGtJQUFBLE9BQU8sT0FBcUI7QUFDckMsdURBQThFO0FBQXJFLDRJQUFBLE9BQU8sT0FBOEI7QUFFOUMscURBQW9FO0FBQTNELGtJQUFBLE9BQU8sT0FBcUI7QUFDckMsK0RBQStFO0FBQXRFLDZJQUFBLE9BQU8sT0FBMkI7QUFDM0MsK0NBQStFO0FBQXRFLGdIQUFBLG1CQUFtQixPQUFBO0FBQUUsa0hBQUEscUJBQXFCLE9BQUE7QUFFbkQscUNBQThDO0FBQXJDLHNHQUFBLGNBQWMsT0FBQTtBQUN2QixtREFBd0Q7QUFBL0MsZ0hBQUEsaUJBQWlCLE9BQUE7QUFDMUIsNkNBQStFO0FBQXRFLHNHQUFBLFdBQVcsT0FBQTtBQUFFLHFHQUFBLFVBQVUsT0FBQTtBQUFFLDRHQUFBLGlCQUFpQixPQUFBO0FBRW5ELHFEQUFnRjtBQUF2RSw4R0FBQSxlQUFlLE9BQUE7QUFBRSxxSEFBQSxzQkFBc0IsT0FBQTtBQUNoRCwyREFBdUY7QUFBOUUsK0hBQUEsT0FBTyxPQUFnQjtBQUFFLG9IQUFBLGtCQUFrQixPQUFBO0FBTXBELHlEQUF3RTtBQUEvRCxvSUFBQSxPQUFPLE9BQXNCO0FBRXRDLHlFQUF1RjtBQUE5RSxtSkFBQSxPQUFPLE9BQTZCO0FBTTdDLG1FQUFpRztBQUF4Riw2SUFBQSxPQUFPLE9BQTBCO0FBQUUsb0hBQUEsY0FBYyxPQUFBO0FBQzFELHlEQU9pQztBQU4vQiw0R0FBQSxXQUFXLE9BQUE7QUFDWCw4R0FBQSxhQUFhLE9BQUE7QUFDYix5SEFBQSx3QkFBd0IsT0FBQTtBQUN4QiwrR0FBQSxjQUFjLE9BQUE7QUFDZCx5SEFBQSx3QkFBd0IsT0FBQTtBQUN4QixrSEFBQSxXQUFXLE9BQXFCIn0=
@@ -0,0 +1,7 @@
1
+ import type { Middleware } from 'koa';
2
+ export declare const TIMEZONE_HEADER = "X-Forest-Timezone";
3
+ export interface TimezoneMiddlewareOptions {
4
+ defaultTimezone?: string;
5
+ }
6
+ export default function createTimezoneMiddleware({ defaultTimezone, }: TimezoneMiddlewareOptions): Middleware;
7
+ //# sourceMappingURL=timezone-middleware.d.ts.map
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TIMEZONE_HEADER = void 0;
4
+ exports.default = createTimezoneMiddleware;
5
+ const timezone_1 = require("./timezone");
6
+ exports.TIMEZONE_HEADER = 'X-Forest-Timezone';
7
+ function bodyTimezone(ctx) {
8
+ const { body } = ctx.request;
9
+ if (typeof body !== 'object' || body === null)
10
+ return undefined;
11
+ const value = body.timezone;
12
+ return typeof value === 'string' ? value : undefined;
13
+ }
14
+ function createTimezoneMiddleware({ defaultTimezone, }) {
15
+ return async function timezoneMiddleware(ctx, next) {
16
+ ctx.state.timezone = (0, timezone_1.resolveTimezone)({
17
+ header: ctx.get(exports.TIMEZONE_HEADER),
18
+ body: bodyTimezone(ctx),
19
+ fallback: defaultTimezone,
20
+ });
21
+ await next();
22
+ };
23
+ }
24
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGltZXpvbmUtbWlkZGxld2FyZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90aW1lem9uZS90aW1lem9uZS1taWRkbGV3YXJlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQW9CQSwyQ0FZQztBQTlCRCx5Q0FBNkM7QUFFaEMsUUFBQSxlQUFlLEdBQUcsbUJBQW1CLENBQUM7QUFNbkQsU0FBUyxZQUFZLENBQUMsR0FBOEI7SUFDbEQsTUFBTSxFQUFFLElBQUksRUFBRSxHQUFHLEdBQUcsQ0FBQyxPQUE2QixDQUFDO0lBRW5ELElBQUksT0FBTyxJQUFJLEtBQUssUUFBUSxJQUFJLElBQUksS0FBSyxJQUFJO1FBQUUsT0FBTyxTQUFTLENBQUM7SUFFaEUsTUFBTSxLQUFLLEdBQUksSUFBK0IsQ0FBQyxRQUFRLENBQUM7SUFFeEQsT0FBTyxPQUFPLEtBQUssS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0FBQ3ZELENBQUM7QUFFRCxTQUF3Qix3QkFBd0IsQ0FBQyxFQUMvQyxlQUFlLEdBQ1c7SUFDMUIsT0FBTyxLQUFLLFVBQVUsa0JBQWtCLENBQUMsR0FBRyxFQUFFLElBQUk7UUFDaEQsR0FBRyxDQUFDLEtBQUssQ0FBQyxRQUFRLEdBQUcsSUFBQSwwQkFBZSxFQUFDO1lBQ25DLE1BQU0sRUFBRSxHQUFHLENBQUMsR0FBRyxDQUFDLHVCQUFlLENBQUM7WUFDaEMsSUFBSSxFQUFFLFlBQVksQ0FBQyxHQUFHLENBQUM7WUFDdkIsUUFBUSxFQUFFLGVBQWU7U0FDMUIsQ0FBQyxDQUFDO1FBRUgsTUFBTSxJQUFJLEVBQUUsQ0FBQztJQUNmLENBQUMsQ0FBQztBQUNKLENBQUMifQ==
@@ -0,0 +1,8 @@
1
+ export interface TimezoneSources {
2
+ header?: string;
3
+ body?: string;
4
+ fallback?: string;
5
+ }
6
+ export declare function isValidTimezone(value: string): boolean;
7
+ export declare function resolveTimezone({ header, body, fallback }: TimezoneSources): string;
8
+ //# sourceMappingURL=timezone.d.ts.map
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isValidTimezone = isValidTimezone;
4
+ exports.resolveTimezone = resolveTimezone;
5
+ const bff_http_error_1 = require("../http/bff-http-error");
6
+ const VALID_TIMEZONES = new Set();
7
+ function isValidTimezone(value) {
8
+ if (value === '')
9
+ return false;
10
+ if (VALID_TIMEZONES.has(value))
11
+ return true;
12
+ let canonical;
13
+ try {
14
+ canonical = Intl.DateTimeFormat('en-US', { timeZone: value }).resolvedOptions().timeZone;
15
+ }
16
+ catch {
17
+ return false;
18
+ }
19
+ // Cache the canonical form, not the raw input: Intl matches IANA names
20
+ // case-insensitively, so caching raw casings would grow this Set without
21
+ // bound on attacker-controlled input.
22
+ VALID_TIMEZONES.add(canonical);
23
+ return true;
24
+ }
25
+ function resolveTimezone({ header, body, fallback }) {
26
+ const candidate = [header, body, fallback]
27
+ .map(value => value?.trim())
28
+ .find(value => value !== undefined && value !== '');
29
+ if (candidate === undefined)
30
+ throw (0, bff_http_error_1.missingTimezone)();
31
+ if (!isValidTimezone(candidate))
32
+ throw (0, bff_http_error_1.invalidTimezone)(candidate);
33
+ return candidate;
34
+ }
35
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGltZXpvbmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdGltZXpvbmUvdGltZXpvbmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFVQSwwQ0FrQkM7QUFFRCwwQ0FTQztBQXZDRCwyREFBMEU7QUFFMUUsTUFBTSxlQUFlLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztBQVExQyxTQUFnQixlQUFlLENBQUMsS0FBYTtJQUMzQyxJQUFJLEtBQUssS0FBSyxFQUFFO1FBQUUsT0FBTyxLQUFLLENBQUM7SUFDL0IsSUFBSSxlQUFlLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQztRQUFFLE9BQU8sSUFBSSxDQUFDO0lBRTVDLElBQUksU0FBaUIsQ0FBQztJQUV0QixJQUFJLENBQUM7UUFDSCxTQUFTLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxlQUFlLEVBQUUsQ0FBQyxRQUFRLENBQUM7SUFDM0YsQ0FBQztJQUFDLE1BQU0sQ0FBQztRQUNQLE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUVELHVFQUF1RTtJQUN2RSx5RUFBeUU7SUFDekUsc0NBQXNDO0lBQ3RDLGVBQWUsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUM7SUFFL0IsT0FBTyxJQUFJLENBQUM7QUFDZCxDQUFDO0FBRUQsU0FBZ0IsZUFBZSxDQUFDLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQW1CO0lBQ3pFLE1BQU0sU0FBUyxHQUFHLENBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxRQUFRLENBQUM7U0FDdkMsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxDQUFDO1NBQzNCLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLEtBQUssS0FBSyxTQUFTLElBQUksS0FBSyxLQUFLLEVBQUUsQ0FBQyxDQUFDO0lBRXRELElBQUksU0FBUyxLQUFLLFNBQVM7UUFBRSxNQUFNLElBQUEsZ0NBQWUsR0FBRSxDQUFDO0lBQ3JELElBQUksQ0FBQyxlQUFlLENBQUMsU0FBUyxDQUFDO1FBQUUsTUFBTSxJQUFBLGdDQUFlLEVBQUMsU0FBUyxDQUFDLENBQUM7SUFFbEUsT0FBTyxTQUFTLENBQUM7QUFDbkIsQ0FBQyJ9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forestadmin/agent-bff",
3
- "version": "1.2.0",
3
+ "version": "1.4.0",
4
4
  "main": "dist/index.js",
5
5
  "bin": {
6
6
  "forest-bff": "dist/cli.js"