@pipeline-builder/api-core 3.1.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.
- package/LICENSE +202 -0
- package/README.md +51 -0
- package/lib/constants/ai-providers.d.ts +41 -0
- package/lib/constants/ai-providers.js +88 -0
- package/lib/constants/http-status.d.ts +24 -0
- package/lib/constants/http-status.js +29 -0
- package/lib/constants/index.d.ts +3 -0
- package/lib/constants/index.js +22 -0
- package/lib/constants/time.d.ts +10 -0
- package/lib/constants/time.js +16 -0
- package/lib/errors/app-errors.d.ts +30 -0
- package/lib/errors/app-errors.js +62 -0
- package/lib/errors/index.d.ts +1 -0
- package/lib/errors/index.js +20 -0
- package/lib/helpers/access-helpers.d.ts +40 -0
- package/lib/helpers/access-helpers.js +56 -0
- package/lib/helpers/crud-helpers.d.ts +16 -0
- package/lib/helpers/crud-helpers.js +34 -0
- package/lib/helpers/index.d.ts +4 -0
- package/lib/helpers/index.js +23 -0
- package/lib/helpers/mask-helpers.d.ts +33 -0
- package/lib/helpers/mask-helpers.js +54 -0
- package/lib/helpers/sse-helpers.d.ts +13 -0
- package/lib/helpers/sse-helpers.js +40 -0
- package/lib/index.d.ts +57 -0
- package/lib/index.js +86 -0
- package/lib/middleware/auth.d.ts +50 -0
- package/lib/middleware/auth.js +171 -0
- package/lib/middleware/index.d.ts +1 -0
- package/lib/middleware/index.js +20 -0
- package/lib/openapi/extend-zod.d.ts +1 -0
- package/lib/openapi/extend-zod.js +8 -0
- package/lib/openapi/index.d.ts +2 -0
- package/lib/openapi/index.js +10 -0
- package/lib/openapi/registry.d.ts +17 -0
- package/lib/openapi/registry.js +42 -0
- package/lib/openapi/routes/billing-routes.d.ts +1 -0
- package/lib/openapi/routes/billing-routes.js +69 -0
- package/lib/openapi/routes/index.d.ts +5 -0
- package/lib/openapi/routes/index.js +22 -0
- package/lib/openapi/routes/message-routes.d.ts +1 -0
- package/lib/openapi/routes/message-routes.js +108 -0
- package/lib/openapi/routes/pipeline-routes.d.ts +1 -0
- package/lib/openapi/routes/pipeline-routes.js +90 -0
- package/lib/openapi/routes/plugin-routes.d.ts +1 -0
- package/lib/openapi/routes/plugin-routes.js +99 -0
- package/lib/openapi/routes/quota-routes.d.ts +1 -0
- package/lib/openapi/routes/quota-routes.js +65 -0
- package/lib/openapi/schema-registry.d.ts +25 -0
- package/lib/openapi/schema-registry.js +95 -0
- package/lib/routes/health.d.ts +47 -0
- package/lib/routes/health.js +81 -0
- package/lib/routes/index.d.ts +1 -0
- package/lib/routes/index.js +20 -0
- package/lib/services/admin-audit.d.ts +13 -0
- package/lib/services/admin-audit.js +31 -0
- package/lib/services/cache-service.d.ts +108 -0
- package/lib/services/cache-service.js +212 -0
- package/lib/services/compliance-client.d.ts +46 -0
- package/lib/services/compliance-client.js +102 -0
- package/lib/services/compliance-event-subscriber.d.ts +11 -0
- package/lib/services/compliance-event-subscriber.js +60 -0
- package/lib/services/compliance-queue.d.ts +11 -0
- package/lib/services/compliance-queue.js +38 -0
- package/lib/services/entity-events.d.ts +44 -0
- package/lib/services/entity-events.js +63 -0
- package/lib/services/http-client.d.ts +108 -0
- package/lib/services/http-client.js +285 -0
- package/lib/services/index.d.ts +10 -0
- package/lib/services/index.js +40 -0
- package/lib/services/quota.d.ts +59 -0
- package/lib/services/quota.js +137 -0
- package/lib/services/retry-strategy.d.ts +74 -0
- package/lib/services/retry-strategy.js +127 -0
- package/lib/types/billing.d.ts +47 -0
- package/lib/types/billing.js +5 -0
- package/lib/types/common.d.ts +161 -0
- package/lib/types/common.js +53 -0
- package/lib/types/error-codes.d.ts +38 -0
- package/lib/types/error-codes.js +77 -0
- package/lib/types/feature-flags.d.ts +38 -0
- package/lib/types/feature-flags.js +107 -0
- package/lib/types/http.d.ts +37 -0
- package/lib/types/http.js +5 -0
- package/lib/types/index.d.ts +7 -0
- package/lib/types/index.js +26 -0
- package/lib/types/pipeline.d.ts +70 -0
- package/lib/types/pipeline.js +44 -0
- package/lib/types/quota-tiers.d.ts +23 -0
- package/lib/types/quota-tiers.js +26 -0
- package/lib/utils/alias-resolver.d.ts +16 -0
- package/lib/utils/alias-resolver.js +49 -0
- package/lib/utils/headers.d.ts +18 -0
- package/lib/utils/headers.js +24 -0
- package/lib/utils/identity.d.ts +61 -0
- package/lib/utils/identity.js +75 -0
- package/lib/utils/index.d.ts +7 -0
- package/lib/utils/index.js +26 -0
- package/lib/utils/logger.d.ts +28 -0
- package/lib/utils/logger.js +77 -0
- package/lib/utils/object.d.ts +13 -0
- package/lib/utils/object.js +21 -0
- package/lib/utils/params.d.ts +89 -0
- package/lib/utils/params.js +148 -0
- package/lib/utils/response.d.ts +142 -0
- package/lib/utils/response.js +237 -0
- package/lib/validation/ai-schemas.d.ts +61 -0
- package/lib/validation/ai-schemas.js +81 -0
- package/lib/validation/common-schemas.d.ts +72 -0
- package/lib/validation/common-schemas.js +58 -0
- package/lib/validation/index.d.ts +6 -0
- package/lib/validation/index.js +25 -0
- package/lib/validation/message-schemas.d.ts +79 -0
- package/lib/validation/message-schemas.js +42 -0
- package/lib/validation/middleware.d.ts +60 -0
- package/lib/validation/middleware.js +77 -0
- package/lib/validation/pipeline-schemas.d.ts +135 -0
- package/lib/validation/pipeline-schemas.js +85 -0
- package/lib/validation/plugin-schemas.d.ts +127 -0
- package/lib/validation/plugin-schemas.js +84 -0
- package/openapi.yaml +292 -0
- package/package.json +127 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.resolveRecipientAlias = resolveRecipientAlias;
|
|
6
|
+
exports._resetAliasCache = _resetAliasCache;
|
|
7
|
+
const auth_1 = require("../middleware/auth");
|
|
8
|
+
/** Lazily-cached set of support aliases, parsed from SUPPORT_ALIASES on first access. */
|
|
9
|
+
let _supportAliases;
|
|
10
|
+
function getSupportAliases() {
|
|
11
|
+
if (!_supportAliases) {
|
|
12
|
+
const raw = process.env.SUPPORT_ALIASES || '';
|
|
13
|
+
_supportAliases = new Set(raw
|
|
14
|
+
.split(',')
|
|
15
|
+
.map(alias => alias.trim().toLowerCase())
|
|
16
|
+
.filter(alias => alias.length > 0));
|
|
17
|
+
}
|
|
18
|
+
return _supportAliases;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Resolve an email-like alias to an actual organization ID.
|
|
22
|
+
*
|
|
23
|
+
* If the input matches a configured support alias, it resolves to the system
|
|
24
|
+
* org ID. Otherwise the input is returned as-is (lowercased).
|
|
25
|
+
*/
|
|
26
|
+
function resolveRecipientAlias(recipientOrgId) {
|
|
27
|
+
const normalized = recipientOrgId.trim().toLowerCase();
|
|
28
|
+
const aliases = getSupportAliases();
|
|
29
|
+
if (aliases.has(normalized)) {
|
|
30
|
+
return {
|
|
31
|
+
resolvedOrgId: auth_1.SYSTEM_ORG_ID,
|
|
32
|
+
wasAlias: true,
|
|
33
|
+
originalValue: recipientOrgId,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
resolvedOrgId: normalized,
|
|
38
|
+
wasAlias: false,
|
|
39
|
+
originalValue: recipientOrgId,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Reset the cached aliases (for testing purposes only).
|
|
44
|
+
* @internal
|
|
45
|
+
*/
|
|
46
|
+
function _resetAliasCache() {
|
|
47
|
+
_supportAliases = undefined;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWxpYXMtcmVzb2x2ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvYWxpYXMtcmVzb2x2ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7O0FBb0N0QyxzREFpQkM7QUFNRCw0Q0FFQztBQTNERCw2Q0FBbUQ7QUFFbkQseUZBQXlGO0FBQ3pGLElBQUksZUFBd0MsQ0FBQztBQUU3QyxTQUFTLGlCQUFpQjtJQUN4QixJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7UUFDckIsTUFBTSxHQUFHLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxlQUFlLElBQUksRUFBRSxDQUFDO1FBQzlDLGVBQWUsR0FBRyxJQUFJLEdBQUcsQ0FDdkIsR0FBRzthQUNBLEtBQUssQ0FBQyxHQUFHLENBQUM7YUFDVixHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUM7YUFDeEMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FDckMsQ0FBQztJQUNKLENBQUM7SUFDRCxPQUFPLGVBQWUsQ0FBQztBQUN6QixDQUFDO0FBWUQ7Ozs7O0dBS0c7QUFDSCxTQUFnQixxQkFBcUIsQ0FBQyxjQUFzQjtJQUMxRCxNQUFNLFVBQVUsR0FBRyxjQUFjLENBQUMsSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDdkQsTUFBTSxPQUFPLEdBQUcsaUJBQWlCLEVBQUUsQ0FBQztJQUVwQyxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQztRQUM1QixPQUFPO1lBQ0wsYUFBYSxFQUFFLG9CQUFhO1lBQzVCLFFBQVEsRUFBRSxJQUFJO1lBQ2QsYUFBYSxFQUFFLGNBQWM7U0FDOUIsQ0FBQztJQUNKLENBQUM7SUFFRCxPQUFPO1FBQ0wsYUFBYSxFQUFFLFVBQVU7UUFDekIsUUFBUSxFQUFFLEtBQUs7UUFDZixhQUFhLEVBQUUsY0FBYztLQUM5QixDQUFDO0FBQ0osQ0FBQztBQUVEOzs7R0FHRztBQUNILFNBQWdCLGdCQUFnQjtJQUM5QixlQUFlLEdBQUcsU0FBUyxDQUFDO0FBQzlCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0IHsgU1lTVEVNX09SR19JRCB9IGZyb20gJy4uL21pZGRsZXdhcmUvYXV0aCc7XG5cbi8qKiBMYXppbHktY2FjaGVkIHNldCBvZiBzdXBwb3J0IGFsaWFzZXMsIHBhcnNlZCBmcm9tIFNVUFBPUlRfQUxJQVNFUyBvbiBmaXJzdCBhY2Nlc3MuICovXG5sZXQgX3N1cHBvcnRBbGlhc2VzOiBTZXQ8c3RyaW5nPiB8IHVuZGVmaW5lZDtcblxuZnVuY3Rpb24gZ2V0U3VwcG9ydEFsaWFzZXMoKTogU2V0PHN0cmluZz4ge1xuICBpZiAoIV9zdXBwb3J0QWxpYXNlcykge1xuICAgIGNvbnN0IHJhdyA9IHByb2Nlc3MuZW52LlNVUFBPUlRfQUxJQVNFUyB8fCAnJztcbiAgICBfc3VwcG9ydEFsaWFzZXMgPSBuZXcgU2V0KFxuICAgICAgcmF3XG4gICAgICAgIC5zcGxpdCgnLCcpXG4gICAgICAgIC5tYXAoYWxpYXMgPT4gYWxpYXMudHJpbSgpLnRvTG93ZXJDYXNlKCkpXG4gICAgICAgIC5maWx0ZXIoYWxpYXMgPT4gYWxpYXMubGVuZ3RoID4gMCksXG4gICAgKTtcbiAgfVxuICByZXR1cm4gX3N1cHBvcnRBbGlhc2VzO1xufVxuXG4vKiogUmVzdWx0IG9mIGFsaWFzIHJlc29sdXRpb24uICovXG5leHBvcnQgaW50ZXJmYWNlIEFsaWFzUmVzb2x1dGlvbiB7XG4gIC8qKiBUaGUgcmVzb2x2ZWQgb3JnYW5pemF0aW9uIElEIChlLmcuLCAnc3lzdGVtJykuICovXG4gIHJlc29sdmVkT3JnSWQ6IHN0cmluZztcbiAgLyoqIFdoZXRoZXIgdGhlIGlucHV0IHdhcyBhbiBhbGlhcyB0aGF0IGdvdCByZXNvbHZlZC4gKi9cbiAgd2FzQWxpYXM6IGJvb2xlYW47XG4gIC8qKiBUaGUgb3JpZ2luYWwgaW5wdXQgdmFsdWUsIHVzZWZ1bCBmb3IgYXVkaXQgbG9nZ2luZy4gKi9cbiAgb3JpZ2luYWxWYWx1ZTogc3RyaW5nO1xufVxuXG4vKipcbiAqIFJlc29sdmUgYW4gZW1haWwtbGlrZSBhbGlhcyB0byBhbiBhY3R1YWwgb3JnYW5pemF0aW9uIElELlxuICpcbiAqIElmIHRoZSBpbnB1dCBtYXRjaGVzIGEgY29uZmlndXJlZCBzdXBwb3J0IGFsaWFzLCBpdCByZXNvbHZlcyB0byB0aGUgc3lzdGVtXG4gKiBvcmcgSUQuIE90aGVyd2lzZSB0aGUgaW5wdXQgaXMgcmV0dXJuZWQgYXMtaXMgKGxvd2VyY2FzZWQpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZVJlY2lwaWVudEFsaWFzKHJlY2lwaWVudE9yZ0lkOiBzdHJpbmcpOiBBbGlhc1Jlc29sdXRpb24ge1xuICBjb25zdCBub3JtYWxpemVkID0gcmVjaXBpZW50T3JnSWQudHJpbSgpLnRvTG93ZXJDYXNlKCk7XG4gIGNvbnN0IGFsaWFzZXMgPSBnZXRTdXBwb3J0QWxpYXNlcygpO1xuXG4gIGlmIChhbGlhc2VzLmhhcyhub3JtYWxpemVkKSkge1xuICAgIHJldHVybiB7XG4gICAgICByZXNvbHZlZE9yZ0lkOiBTWVNURU1fT1JHX0lELFxuICAgICAgd2FzQWxpYXM6IHRydWUsXG4gICAgICBvcmlnaW5hbFZhbHVlOiByZWNpcGllbnRPcmdJZCxcbiAgICB9O1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICByZXNvbHZlZE9yZ0lkOiBub3JtYWxpemVkLFxuICAgIHdhc0FsaWFzOiBmYWxzZSxcbiAgICBvcmlnaW5hbFZhbHVlOiByZWNpcGllbnRPcmdJZCxcbiAgfTtcbn1cblxuLyoqXG4gKiBSZXNldCB0aGUgY2FjaGVkIGFsaWFzZXMgKGZvciB0ZXN0aW5nIHB1cnBvc2VzIG9ubHkpLlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBfcmVzZXRBbGlhc0NhY2hlKCk6IHZvaWQge1xuICBfc3VwcG9ydEFsaWFzZXMgPSB1bmRlZmluZWQ7XG59XG4iXX0=
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Express 5 header type.
|
|
3
|
+
*/
|
|
4
|
+
type HeaderValue = string | string[] | undefined;
|
|
5
|
+
/**
|
|
6
|
+
* Extract a single string from a header value that may be string | string[] | undefined.
|
|
7
|
+
*
|
|
8
|
+
* @param value - Header value from Express request
|
|
9
|
+
* @returns First value if array, the value if string, or undefined
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* const orgId = getHeaderString(req.headers['x-org-id']);
|
|
14
|
+
* const auth = getHeaderString(req.headers.authorization);
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export declare function getHeaderString(value: HeaderValue): string | undefined;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.getHeaderString = getHeaderString;
|
|
6
|
+
/**
|
|
7
|
+
* Extract a single string from a header value that may be string | string[] | undefined.
|
|
8
|
+
*
|
|
9
|
+
* @param value - Header value from Express request
|
|
10
|
+
* @returns First value if array, the value if string, or undefined
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const orgId = getHeaderString(req.headers['x-org-id']);
|
|
15
|
+
* const auth = getHeaderString(req.headers.authorization);
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
function getHeaderString(value) {
|
|
19
|
+
if (Array.isArray(value)) {
|
|
20
|
+
return value[0];
|
|
21
|
+
}
|
|
22
|
+
return value;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGVhZGVycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9oZWFkZXJzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDOztBQW1CdEMsMENBS0M7QUFqQkQ7Ozs7Ozs7Ozs7O0dBV0c7QUFDSCxTQUFnQixlQUFlLENBQUMsS0FBa0I7SUFDaEQsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDekIsT0FBTyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDbEIsQ0FBQztJQUNELE9BQU8sS0FBSyxDQUFDO0FBQ2YsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG4vKipcbiAqIEV4cHJlc3MgNSBoZWFkZXIgdHlwZS5cbiAqL1xudHlwZSBIZWFkZXJWYWx1ZSA9IHN0cmluZyB8IHN0cmluZ1tdIHwgdW5kZWZpbmVkO1xuXG4vKipcbiAqIEV4dHJhY3QgYSBzaW5nbGUgc3RyaW5nIGZyb20gYSBoZWFkZXIgdmFsdWUgdGhhdCBtYXkgYmUgc3RyaW5nIHwgc3RyaW5nW10gfCB1bmRlZmluZWQuXG4gKlxuICogQHBhcmFtIHZhbHVlIC0gSGVhZGVyIHZhbHVlIGZyb20gRXhwcmVzcyByZXF1ZXN0XG4gKiBAcmV0dXJucyBGaXJzdCB2YWx1ZSBpZiBhcnJheSwgdGhlIHZhbHVlIGlmIHN0cmluZywgb3IgdW5kZWZpbmVkXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IG9yZ0lkID0gZ2V0SGVhZGVyU3RyaW5nKHJlcS5oZWFkZXJzWyd4LW9yZy1pZCddKTtcbiAqIGNvbnN0IGF1dGggPSBnZXRIZWFkZXJTdHJpbmcocmVxLmhlYWRlcnMuYXV0aG9yaXphdGlvbik7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEhlYWRlclN0cmluZyh2YWx1ZTogSGVhZGVyVmFsdWUpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICByZXR1cm4gdmFsdWVbMF07XG4gIH1cbiAgcmV0dXJuIHZhbHVlO1xufVxuIl19
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { HttpRequest } from '../types/http';
|
|
2
|
+
/**
|
|
3
|
+
* Identity information extracted from request headers.
|
|
4
|
+
*/
|
|
5
|
+
export interface RequestIdentity {
|
|
6
|
+
/** Organization ID from x-org-id header */
|
|
7
|
+
readonly orgId?: string;
|
|
8
|
+
/** User ID from x-user-id header */
|
|
9
|
+
readonly userId?: string;
|
|
10
|
+
/** Request ID from x-request-id header */
|
|
11
|
+
readonly requestId?: string;
|
|
12
|
+
/** User role from x-user-role header (decoded from JWT) */
|
|
13
|
+
readonly role?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Extract identity information from request headers.
|
|
17
|
+
*
|
|
18
|
+
* Extracts common identity headers used for multi-tenant authentication:
|
|
19
|
+
* - x-org-id: Organization identifier
|
|
20
|
+
* - x-user-id: User identifier
|
|
21
|
+
* - x-request-id: Request trace identifier
|
|
22
|
+
* - x-user-role: User role
|
|
23
|
+
*
|
|
24
|
+
* @param req - HTTP request object
|
|
25
|
+
* @returns Identity object with orgId, userId, requestId, and role
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* app.post('/api/resource', requireAuth, async (req, res) => {
|
|
30
|
+
* const identity = getIdentity(req);
|
|
31
|
+
*
|
|
32
|
+
* if (!identity.orgId) {
|
|
33
|
+
* return sendError(res, 400, 'x-org-id header required');
|
|
34
|
+
* }
|
|
35
|
+
*
|
|
36
|
+
* // Use identity.orgId, identity.userId, etc.
|
|
37
|
+
* });
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare function getIdentity(req: HttpRequest): RequestIdentity;
|
|
41
|
+
/**
|
|
42
|
+
* Validate that required identity fields are present.
|
|
43
|
+
*
|
|
44
|
+
* @param identity - Identity object to validate
|
|
45
|
+
* @param required - Array of required field names
|
|
46
|
+
* @returns Object with isValid boolean and missing fields array
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* const identity = getIdentity(req);
|
|
51
|
+
* const validation = validateIdentity(identity, ['orgId', 'userId']);
|
|
52
|
+
*
|
|
53
|
+
* if (!validation.isValid) {
|
|
54
|
+
* return sendError(res, 400, `Missing required headers: ${validation.missing.join(', ')}`);
|
|
55
|
+
* }
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export declare function validateIdentity(identity: RequestIdentity, required: (keyof RequestIdentity)[]): {
|
|
59
|
+
isValid: boolean;
|
|
60
|
+
missing: string[];
|
|
61
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.getIdentity = getIdentity;
|
|
6
|
+
exports.validateIdentity = validateIdentity;
|
|
7
|
+
const headers_1 = require("./headers");
|
|
8
|
+
/**
|
|
9
|
+
* Extract identity information from request headers.
|
|
10
|
+
*
|
|
11
|
+
* Extracts common identity headers used for multi-tenant authentication:
|
|
12
|
+
* - x-org-id: Organization identifier
|
|
13
|
+
* - x-user-id: User identifier
|
|
14
|
+
* - x-request-id: Request trace identifier
|
|
15
|
+
* - x-user-role: User role
|
|
16
|
+
*
|
|
17
|
+
* @param req - HTTP request object
|
|
18
|
+
* @returns Identity object with orgId, userId, requestId, and role
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* app.post('/api/resource', requireAuth, async (req, res) => {
|
|
23
|
+
* const identity = getIdentity(req);
|
|
24
|
+
*
|
|
25
|
+
* if (!identity.orgId) {
|
|
26
|
+
* return sendError(res, 400, 'x-org-id header required');
|
|
27
|
+
* }
|
|
28
|
+
*
|
|
29
|
+
* // Use identity.orgId, identity.userId, etc.
|
|
30
|
+
* });
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
function getIdentity(req) {
|
|
34
|
+
// Prefer JWT-verified claims (req.user) over raw headers to prevent spoofing.
|
|
35
|
+
// Headers are only used as fallback or for fields not in the JWT (e.g. requestId).
|
|
36
|
+
const user = req.user;
|
|
37
|
+
return {
|
|
38
|
+
orgId: user?.organizationId || (0, headers_1.getHeaderString)(req.headers['x-org-id']),
|
|
39
|
+
userId: user?.sub
|
|
40
|
+
|| user?.userId
|
|
41
|
+
|| (0, headers_1.getHeaderString)(req.headers['x-user-id']),
|
|
42
|
+
requestId: (0, headers_1.getHeaderString)(req.headers['x-request-id']),
|
|
43
|
+
role: user?.role || (0, headers_1.getHeaderString)(req.headers['x-user-role']),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Validate that required identity fields are present.
|
|
48
|
+
*
|
|
49
|
+
* @param identity - Identity object to validate
|
|
50
|
+
* @param required - Array of required field names
|
|
51
|
+
* @returns Object with isValid boolean and missing fields array
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* const identity = getIdentity(req);
|
|
56
|
+
* const validation = validateIdentity(identity, ['orgId', 'userId']);
|
|
57
|
+
*
|
|
58
|
+
* if (!validation.isValid) {
|
|
59
|
+
* return sendError(res, 400, `Missing required headers: ${validation.missing.join(', ')}`);
|
|
60
|
+
* }
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
function validateIdentity(identity, required) {
|
|
64
|
+
const missing = [];
|
|
65
|
+
for (const field of required) {
|
|
66
|
+
if (!identity[field]) {
|
|
67
|
+
missing.push(`x-${field.replace(/([A-Z])/g, '-$1').toLowerCase()}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
isValid: missing.length === 0,
|
|
72
|
+
missing,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaWRlbnRpdHkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvaWRlbnRpdHkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7O0FBNEN0QyxrQ0FZQztBQW1CRCw0Q0FnQkM7QUF6RkQsdUNBQTRDO0FBaUI1Qzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBd0JHO0FBQ0gsU0FBZ0IsV0FBVyxDQUFDLEdBQWdCO0lBQzFDLDhFQUE4RTtJQUM5RSxtRkFBbUY7SUFDbkYsTUFBTSxJQUFJLEdBQUcsR0FBRyxDQUFDLElBQUksQ0FBQztJQUN0QixPQUFPO1FBQ0wsS0FBSyxFQUFFLElBQUksRUFBRSxjQUFjLElBQUksSUFBQSx5QkFBZSxFQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDdkUsTUFBTSxFQUFHLElBQTRDLEVBQUUsR0FBeUI7ZUFDM0UsSUFBSSxFQUFFLE1BQU07ZUFDWixJQUFBLHlCQUFlLEVBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUM5QyxTQUFTLEVBQUUsSUFBQSx5QkFBZSxFQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDdkQsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLElBQUksSUFBQSx5QkFBZSxFQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLENBQUM7S0FDaEUsQ0FBQztBQUNKLENBQUM7QUFFRDs7Ozs7Ozs7Ozs7Ozs7OztHQWdCRztBQUNILFNBQWdCLGdCQUFnQixDQUM5QixRQUF5QixFQUN6QixRQUFtQztJQUVuQyxNQUFNLE9BQU8sR0FBYSxFQUFFLENBQUM7SUFFN0IsS0FBSyxNQUFNLEtBQUssSUFBSSxRQUFRLEVBQUUsQ0FBQztRQUM3QixJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDckIsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLEtBQUssQ0FBQyxPQUFPLENBQUMsVUFBVSxFQUFFLEtBQUssQ0FBQyxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUN0RSxDQUFDO0lBQ0gsQ0FBQztJQUVELE9BQU87UUFDTCxPQUFPLEVBQUUsT0FBTyxDQUFDLE1BQU0sS0FBSyxDQUFDO1FBQzdCLE9BQU87S0FDUixDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgeyBnZXRIZWFkZXJTdHJpbmcgfSBmcm9tICcuL2hlYWRlcnMnO1xuaW1wb3J0IHsgSHR0cFJlcXVlc3QgfSBmcm9tICcuLi90eXBlcy9odHRwJztcblxuLyoqXG4gKiBJZGVudGl0eSBpbmZvcm1hdGlvbiBleHRyYWN0ZWQgZnJvbSByZXF1ZXN0IGhlYWRlcnMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVxdWVzdElkZW50aXR5IHtcbiAgLyoqIE9yZ2FuaXphdGlvbiBJRCBmcm9tIHgtb3JnLWlkIGhlYWRlciAqL1xuICByZWFkb25seSBvcmdJZD86IHN0cmluZztcbiAgLyoqIFVzZXIgSUQgZnJvbSB4LXVzZXItaWQgaGVhZGVyICovXG4gIHJlYWRvbmx5IHVzZXJJZD86IHN0cmluZztcbiAgLyoqIFJlcXVlc3QgSUQgZnJvbSB4LXJlcXVlc3QtaWQgaGVhZGVyICovXG4gIHJlYWRvbmx5IHJlcXVlc3RJZD86IHN0cmluZztcbiAgLyoqIFVzZXIgcm9sZSBmcm9tIHgtdXNlci1yb2xlIGhlYWRlciAoZGVjb2RlZCBmcm9tIEpXVCkgKi9cbiAgcmVhZG9ubHkgcm9sZT86IHN0cmluZztcbn1cblxuLyoqXG4gKiBFeHRyYWN0IGlkZW50aXR5IGluZm9ybWF0aW9uIGZyb20gcmVxdWVzdCBoZWFkZXJzLlxuICpcbiAqIEV4dHJhY3RzIGNvbW1vbiBpZGVudGl0eSBoZWFkZXJzIHVzZWQgZm9yIG11bHRpLXRlbmFudCBhdXRoZW50aWNhdGlvbjpcbiAqIC0geC1vcmctaWQ6IE9yZ2FuaXphdGlvbiBpZGVudGlmaWVyXG4gKiAtIHgtdXNlci1pZDogVXNlciBpZGVudGlmaWVyXG4gKiAtIHgtcmVxdWVzdC1pZDogUmVxdWVzdCB0cmFjZSBpZGVudGlmaWVyXG4gKiAtIHgtdXNlci1yb2xlOiBVc2VyIHJvbGVcbiAqXG4gKiBAcGFyYW0gcmVxIC0gSFRUUCByZXF1ZXN0IG9iamVjdFxuICogQHJldHVybnMgSWRlbnRpdHkgb2JqZWN0IHdpdGggb3JnSWQsIHVzZXJJZCwgcmVxdWVzdElkLCBhbmQgcm9sZVxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBhcHAucG9zdCgnL2FwaS9yZXNvdXJjZScsIHJlcXVpcmVBdXRoLCBhc3luYyAocmVxLCByZXMpID0+IHtcbiAqICAgY29uc3QgaWRlbnRpdHkgPSBnZXRJZGVudGl0eShyZXEpO1xuICpcbiAqICAgaWYgKCFpZGVudGl0eS5vcmdJZCkge1xuICogICAgIHJldHVybiBzZW5kRXJyb3IocmVzLCA0MDAsICd4LW9yZy1pZCBoZWFkZXIgcmVxdWlyZWQnKTtcbiAqICAgfVxuICpcbiAqICAgLy8gVXNlIGlkZW50aXR5Lm9yZ0lkLCBpZGVudGl0eS51c2VySWQsIGV0Yy5cbiAqIH0pO1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRJZGVudGl0eShyZXE6IEh0dHBSZXF1ZXN0KTogUmVxdWVzdElkZW50aXR5IHtcbiAgLy8gUHJlZmVyIEpXVC12ZXJpZmllZCBjbGFpbXMgKHJlcS51c2VyKSBvdmVyIHJhdyBoZWFkZXJzIHRvIHByZXZlbnQgc3Bvb2ZpbmcuXG4gIC8vIEhlYWRlcnMgYXJlIG9ubHkgdXNlZCBhcyBmYWxsYmFjayBvciBmb3IgZmllbGRzIG5vdCBpbiB0aGUgSldUIChlLmcuIHJlcXVlc3RJZCkuXG4gIGNvbnN0IHVzZXIgPSByZXEudXNlcjtcbiAgcmV0dXJuIHtcbiAgICBvcmdJZDogdXNlcj8ub3JnYW5pemF0aW9uSWQgfHwgZ2V0SGVhZGVyU3RyaW5nKHJlcS5oZWFkZXJzWyd4LW9yZy1pZCddKSxcbiAgICB1c2VySWQ6ICh1c2VyIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+IHwgdW5kZWZpbmVkKT8uc3ViIGFzIHN0cmluZyB8IHVuZGVmaW5lZFxuICAgICAgfHwgdXNlcj8udXNlcklkXG4gICAgICB8fCBnZXRIZWFkZXJTdHJpbmcocmVxLmhlYWRlcnNbJ3gtdXNlci1pZCddKSxcbiAgICByZXF1ZXN0SWQ6IGdldEhlYWRlclN0cmluZyhyZXEuaGVhZGVyc1sneC1yZXF1ZXN0LWlkJ10pLFxuICAgIHJvbGU6IHVzZXI/LnJvbGUgfHwgZ2V0SGVhZGVyU3RyaW5nKHJlcS5oZWFkZXJzWyd4LXVzZXItcm9sZSddKSxcbiAgfTtcbn1cblxuLyoqXG4gKiBWYWxpZGF0ZSB0aGF0IHJlcXVpcmVkIGlkZW50aXR5IGZpZWxkcyBhcmUgcHJlc2VudC5cbiAqXG4gKiBAcGFyYW0gaWRlbnRpdHkgLSBJZGVudGl0eSBvYmplY3QgdG8gdmFsaWRhdGVcbiAqIEBwYXJhbSByZXF1aXJlZCAtIEFycmF5IG9mIHJlcXVpcmVkIGZpZWxkIG5hbWVzXG4gKiBAcmV0dXJucyBPYmplY3Qgd2l0aCBpc1ZhbGlkIGJvb2xlYW4gYW5kIG1pc3NpbmcgZmllbGRzIGFycmF5XG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IGlkZW50aXR5ID0gZ2V0SWRlbnRpdHkocmVxKTtcbiAqIGNvbnN0IHZhbGlkYXRpb24gPSB2YWxpZGF0ZUlkZW50aXR5KGlkZW50aXR5LCBbJ29yZ0lkJywgJ3VzZXJJZCddKTtcbiAqXG4gKiBpZiAoIXZhbGlkYXRpb24uaXNWYWxpZCkge1xuICogICByZXR1cm4gc2VuZEVycm9yKHJlcywgNDAwLCBgTWlzc2luZyByZXF1aXJlZCBoZWFkZXJzOiAke3ZhbGlkYXRpb24ubWlzc2luZy5qb2luKCcsICcpfWApO1xuICogfVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZUlkZW50aXR5KFxuICBpZGVudGl0eTogUmVxdWVzdElkZW50aXR5LFxuICByZXF1aXJlZDogKGtleW9mIFJlcXVlc3RJZGVudGl0eSlbXSxcbik6IHsgaXNWYWxpZDogYm9vbGVhbjsgbWlzc2luZzogc3RyaW5nW10gfSB7XG4gIGNvbnN0IG1pc3Npbmc6IHN0cmluZ1tdID0gW107XG5cbiAgZm9yIChjb25zdCBmaWVsZCBvZiByZXF1aXJlZCkge1xuICAgIGlmICghaWRlbnRpdHlbZmllbGRdKSB7XG4gICAgICBtaXNzaW5nLnB1c2goYHgtJHtmaWVsZC5yZXBsYWNlKC8oW0EtWl0pL2csICctJDEnKS50b0xvd2VyQ2FzZSgpfWApO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7XG4gICAgaXNWYWxpZDogbWlzc2luZy5sZW5ndGggPT09IDAsXG4gICAgbWlzc2luZyxcbiAgfTtcbn1cbiJdfQ==
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
5
|
+
if (k2 === undefined) k2 = k;
|
|
6
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
7
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
8
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
9
|
+
}
|
|
10
|
+
Object.defineProperty(o, k2, desc);
|
|
11
|
+
}) : (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
o[k2] = m[k];
|
|
14
|
+
}));
|
|
15
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
16
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
17
|
+
};
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
__exportStar(require("./logger"), exports);
|
|
20
|
+
__exportStar(require("./response"), exports);
|
|
21
|
+
__exportStar(require("./params"), exports);
|
|
22
|
+
__exportStar(require("./headers"), exports);
|
|
23
|
+
__exportStar(require("./identity"), exports);
|
|
24
|
+
__exportStar(require("./object"), exports);
|
|
25
|
+
__exportStar(require("./alias-resolver"), exports);
|
|
26
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7Ozs7Ozs7Ozs7Ozs7Ozs7QUFFdEMsMkNBQXlCO0FBQ3pCLDZDQUEyQjtBQUMzQiwyQ0FBeUI7QUFDekIsNENBQTBCO0FBQzFCLDZDQUEyQjtBQUMzQiwyQ0FBeUI7QUFDekIsbURBQWlDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmV4cG9ydCAqIGZyb20gJy4vbG9nZ2VyJztcbmV4cG9ydCAqIGZyb20gJy4vcmVzcG9uc2UnO1xuZXhwb3J0ICogZnJvbSAnLi9wYXJhbXMnO1xuZXhwb3J0ICogZnJvbSAnLi9oZWFkZXJzJztcbmV4cG9ydCAqIGZyb20gJy4vaWRlbnRpdHknO1xuZXhwb3J0ICogZnJvbSAnLi9vYmplY3QnO1xuZXhwb3J0ICogZnJvbSAnLi9hbGlhcy1yZXNvbHZlcic7XG4iXX0=
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import winston from 'winston';
|
|
2
|
+
/**
|
|
3
|
+
* Create a logger instance for a service.
|
|
4
|
+
*
|
|
5
|
+
* When LOG_FORMAT=json (default), outputs structured JSON for Loki ingestion:
|
|
6
|
+
* {"level":"info","message":"Server started","service":"pipeline","timestamp":"..."}
|
|
7
|
+
*
|
|
8
|
+
* When LOG_FORMAT=text, outputs colorized human-readable format:
|
|
9
|
+
* 2026-02-13T10:30:00.000Z info [pipeline] Server started
|
|
10
|
+
*
|
|
11
|
+
* @param serviceName - Name of the service for log identification
|
|
12
|
+
* @returns Configured Winston logger instance
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import { createLogger } from '@pipeline-builder/api-core';
|
|
17
|
+
*
|
|
18
|
+
* const logger = createLogger('get-plugin');
|
|
19
|
+
* logger.info('Server started', { port: 3000 });
|
|
20
|
+
* logger.error('Database error', { error: err.message });
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare function createLogger(serviceName: string): winston.Logger;
|
|
24
|
+
/**
|
|
25
|
+
* Default logger instance (service name from SERVICE_NAME env var or 'api').
|
|
26
|
+
*/
|
|
27
|
+
export declare const logger: winston.Logger;
|
|
28
|
+
export default logger;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
5
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
6
|
+
};
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.logger = void 0;
|
|
9
|
+
exports.createLogger = createLogger;
|
|
10
|
+
const winston_1 = __importDefault(require("winston"));
|
|
11
|
+
const { combine, timestamp, printf, colorize, errors, json } = winston_1.default.format;
|
|
12
|
+
/**
|
|
13
|
+
* Custom log format for human-readable console output.
|
|
14
|
+
*/
|
|
15
|
+
const consoleFormat = printf(({ level, message, timestamp, service, ...meta }) => {
|
|
16
|
+
const serviceName = service ? `[${service}]` : '';
|
|
17
|
+
const metaStr = Object.keys(meta).length ? ` ${JSON.stringify(meta)}` : '';
|
|
18
|
+
return `${timestamp} ${level} ${serviceName} ${message}${metaStr}`;
|
|
19
|
+
});
|
|
20
|
+
/**
|
|
21
|
+
* Create a logger instance for a service.
|
|
22
|
+
*
|
|
23
|
+
* When LOG_FORMAT=json (default), outputs structured JSON for Loki ingestion:
|
|
24
|
+
* {"level":"info","message":"Server started","service":"pipeline","timestamp":"..."}
|
|
25
|
+
*
|
|
26
|
+
* When LOG_FORMAT=text, outputs colorized human-readable format:
|
|
27
|
+
* 2026-02-13T10:30:00.000Z info [pipeline] Server started
|
|
28
|
+
*
|
|
29
|
+
* @param serviceName - Name of the service for log identification
|
|
30
|
+
* @returns Configured Winston logger instance
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```typescript
|
|
34
|
+
* import { createLogger } from '@pipeline-builder/api-core';
|
|
35
|
+
*
|
|
36
|
+
* const logger = createLogger('get-plugin');
|
|
37
|
+
* logger.info('Server started', { port: 3000 });
|
|
38
|
+
* logger.error('Database error', { error: err.message });
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
function createLogger(serviceName) {
|
|
42
|
+
const logLevel = process.env.LOG_LEVEL || 'info';
|
|
43
|
+
const logFormat = process.env.LOG_FORMAT || 'json';
|
|
44
|
+
if (logFormat !== 'json' && logFormat !== 'text') {
|
|
45
|
+
// eslint-disable-next-line no-console -- startup warning before logger is available
|
|
46
|
+
console.warn(`Invalid LOG_FORMAT="${logFormat}", expected "json" or "text". Defaulting to "json".`);
|
|
47
|
+
}
|
|
48
|
+
const useJson = logFormat !== 'text';
|
|
49
|
+
const baseFormats = [
|
|
50
|
+
errors({ stack: true }),
|
|
51
|
+
timestamp({ format: 'YYYY-MM-DDTHH:mm:ss.SSSZ' }),
|
|
52
|
+
];
|
|
53
|
+
if (useJson) {
|
|
54
|
+
return winston_1.default.createLogger({
|
|
55
|
+
level: logLevel,
|
|
56
|
+
defaultMeta: { service: serviceName },
|
|
57
|
+
format: combine(...baseFormats, json()),
|
|
58
|
+
transports: [new winston_1.default.transports.Console()],
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
return winston_1.default.createLogger({
|
|
62
|
+
level: logLevel,
|
|
63
|
+
defaultMeta: { service: serviceName },
|
|
64
|
+
format: combine(...baseFormats),
|
|
65
|
+
transports: [
|
|
66
|
+
new winston_1.default.transports.Console({
|
|
67
|
+
format: combine(colorize(), consoleFormat),
|
|
68
|
+
}),
|
|
69
|
+
],
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Default logger instance (service name from SERVICE_NAME env var or 'api').
|
|
74
|
+
*/
|
|
75
|
+
exports.logger = createLogger(process.env.SERVICE_NAME || 'api');
|
|
76
|
+
exports.default = exports.logger;
|
|
77
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9nZ2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL2xvZ2dlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsK0NBQStDO0FBQy9DLHNDQUFzQzs7Ozs7O0FBb0N0QyxvQ0FpQ0M7QUFuRUQsc0RBQThCO0FBRTlCLE1BQU0sRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxHQUFHLGlCQUFPLENBQUMsTUFBTSxDQUFDO0FBRTlFOztHQUVHO0FBQ0gsTUFBTSxhQUFhLEdBQUcsTUFBTSxDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUUsR0FBRyxJQUFJLEVBQUUsRUFBRSxFQUFFO0lBQy9FLE1BQU0sV0FBVyxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxPQUFPLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0lBQ2xELE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0lBQzNFLE9BQU8sR0FBRyxTQUFTLElBQUksS0FBSyxJQUFJLFdBQVcsSUFBSSxPQUFPLEdBQUcsT0FBTyxFQUFFLENBQUM7QUFDckUsQ0FBQyxDQUFDLENBQUM7QUFFSDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FvQkc7QUFDSCxTQUFnQixZQUFZLENBQUMsV0FBbUI7SUFDOUMsTUFBTSxRQUFRLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxTQUFTLElBQUksTUFBTSxDQUFDO0lBQ2pELE1BQU0sU0FBUyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsVUFBVSxJQUFJLE1BQU0sQ0FBQztJQUNuRCxJQUFJLFNBQVMsS0FBSyxNQUFNLElBQUksU0FBUyxLQUFLLE1BQU0sRUFBRSxDQUFDO1FBQ2pELG9GQUFvRjtRQUNwRixPQUFPLENBQUMsSUFBSSxDQUFDLHVCQUF1QixTQUFTLHFEQUFxRCxDQUFDLENBQUM7SUFDdEcsQ0FBQztJQUNELE1BQU0sT0FBTyxHQUFHLFNBQVMsS0FBSyxNQUFNLENBQUM7SUFFckMsTUFBTSxXQUFXLEdBQUc7UUFDbEIsTUFBTSxDQUFDLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxDQUFDO1FBQ3ZCLFNBQVMsQ0FBQyxFQUFFLE1BQU0sRUFBRSwwQkFBMEIsRUFBRSxDQUFDO0tBQ2xELENBQUM7SUFFRixJQUFJLE9BQU8sRUFBRSxDQUFDO1FBQ1osT0FBTyxpQkFBTyxDQUFDLFlBQVksQ0FBQztZQUMxQixLQUFLLEVBQUUsUUFBUTtZQUNmLFdBQVcsRUFBRSxFQUFFLE9BQU8sRUFBRSxXQUFXLEVBQUU7WUFDckMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxHQUFHLFdBQVcsRUFBRSxJQUFJLEVBQUUsQ0FBQztZQUN2QyxVQUFVLEVBQUUsQ0FBQyxJQUFJLGlCQUFPLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxDQUFDO1NBQy9DLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxPQUFPLGlCQUFPLENBQUMsWUFBWSxDQUFDO1FBQzFCLEtBQUssRUFBRSxRQUFRO1FBQ2YsV0FBVyxFQUFFLEVBQUUsT0FBTyxFQUFFLFdBQVcsRUFBRTtRQUNyQyxNQUFNLEVBQUUsT0FBTyxDQUFDLEdBQUcsV0FBVyxDQUFDO1FBQy9CLFVBQVUsRUFBRTtZQUNWLElBQUksaUJBQU8sQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDO2dCQUM3QixNQUFNLEVBQUUsT0FBTyxDQUFDLFFBQVEsRUFBRSxFQUFFLGFBQWEsQ0FBQzthQUMzQyxDQUFDO1NBQ0g7S0FDRixDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQ7O0dBRUc7QUFDVSxRQUFBLE1BQU0sR0FBRyxZQUFZLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxZQUFZLElBQUksS0FBSyxDQUFDLENBQUM7QUFFdEUsa0JBQWUsY0FBTSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCB3aW5zdG9uIGZyb20gJ3dpbnN0b24nO1xuXG5jb25zdCB7IGNvbWJpbmUsIHRpbWVzdGFtcCwgcHJpbnRmLCBjb2xvcml6ZSwgZXJyb3JzLCBqc29uIH0gPSB3aW5zdG9uLmZvcm1hdDtcblxuLyoqXG4gKiBDdXN0b20gbG9nIGZvcm1hdCBmb3IgaHVtYW4tcmVhZGFibGUgY29uc29sZSBvdXRwdXQuXG4gKi9cbmNvbnN0IGNvbnNvbGVGb3JtYXQgPSBwcmludGYoKHsgbGV2ZWwsIG1lc3NhZ2UsIHRpbWVzdGFtcCwgc2VydmljZSwgLi4ubWV0YSB9KSA9PiB7XG4gIGNvbnN0IHNlcnZpY2VOYW1lID0gc2VydmljZSA/IGBbJHtzZXJ2aWNlfV1gIDogJyc7XG4gIGNvbnN0IG1ldGFTdHIgPSBPYmplY3Qua2V5cyhtZXRhKS5sZW5ndGggPyBgICR7SlNPTi5zdHJpbmdpZnkobWV0YSl9YCA6ICcnO1xuICByZXR1cm4gYCR7dGltZXN0YW1wfSAke2xldmVsfSAke3NlcnZpY2VOYW1lfSAke21lc3NhZ2V9JHttZXRhU3RyfWA7XG59KTtcblxuLyoqXG4gKiBDcmVhdGUgYSBsb2dnZXIgaW5zdGFuY2UgZm9yIGEgc2VydmljZS5cbiAqXG4gKiBXaGVuIExPR19GT1JNQVQ9anNvbiAoZGVmYXVsdCksIG91dHB1dHMgc3RydWN0dXJlZCBKU09OIGZvciBMb2tpIGluZ2VzdGlvbjpcbiAqICAge1wibGV2ZWxcIjpcImluZm9cIixcIm1lc3NhZ2VcIjpcIlNlcnZlciBzdGFydGVkXCIsXCJzZXJ2aWNlXCI6XCJwaXBlbGluZVwiLFwidGltZXN0YW1wXCI6XCIuLi5cIn1cbiAqXG4gKiBXaGVuIExPR19GT1JNQVQ9dGV4dCwgb3V0cHV0cyBjb2xvcml6ZWQgaHVtYW4tcmVhZGFibGUgZm9ybWF0OlxuICogICAyMDI2LTAyLTEzVDEwOjMwOjAwLjAwMFogaW5mbyBbcGlwZWxpbmVdIFNlcnZlciBzdGFydGVkXG4gKlxuICogQHBhcmFtIHNlcnZpY2VOYW1lIC0gTmFtZSBvZiB0aGUgc2VydmljZSBmb3IgbG9nIGlkZW50aWZpY2F0aW9uXG4gKiBAcmV0dXJucyBDb25maWd1cmVkIFdpbnN0b24gbG9nZ2VyIGluc3RhbmNlXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGltcG9ydCB7IGNyZWF0ZUxvZ2dlciB9IGZyb20gJ0BwaXBlbGluZS1idWlsZGVyL2FwaS1jb3JlJztcbiAqXG4gKiBjb25zdCBsb2dnZXIgPSBjcmVhdGVMb2dnZXIoJ2dldC1wbHVnaW4nKTtcbiAqIGxvZ2dlci5pbmZvKCdTZXJ2ZXIgc3RhcnRlZCcsIHsgcG9ydDogMzAwMCB9KTtcbiAqIGxvZ2dlci5lcnJvcignRGF0YWJhc2UgZXJyb3InLCB7IGVycm9yOiBlcnIubWVzc2FnZSB9KTtcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlTG9nZ2VyKHNlcnZpY2VOYW1lOiBzdHJpbmcpOiB3aW5zdG9uLkxvZ2dlciB7XG4gIGNvbnN0IGxvZ0xldmVsID0gcHJvY2Vzcy5lbnYuTE9HX0xFVkVMIHx8ICdpbmZvJztcbiAgY29uc3QgbG9nRm9ybWF0ID0gcHJvY2Vzcy5lbnYuTE9HX0ZPUk1BVCB8fCAnanNvbic7XG4gIGlmIChsb2dGb3JtYXQgIT09ICdqc29uJyAmJiBsb2dGb3JtYXQgIT09ICd0ZXh0Jykge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlIC0tIHN0YXJ0dXAgd2FybmluZyBiZWZvcmUgbG9nZ2VyIGlzIGF2YWlsYWJsZVxuICAgIGNvbnNvbGUud2FybihgSW52YWxpZCBMT0dfRk9STUFUPVwiJHtsb2dGb3JtYXR9XCIsIGV4cGVjdGVkIFwianNvblwiIG9yIFwidGV4dFwiLiBEZWZhdWx0aW5nIHRvIFwianNvblwiLmApO1xuICB9XG4gIGNvbnN0IHVzZUpzb24gPSBsb2dGb3JtYXQgIT09ICd0ZXh0JztcblxuICBjb25zdCBiYXNlRm9ybWF0cyA9IFtcbiAgICBlcnJvcnMoeyBzdGFjazogdHJ1ZSB9KSxcbiAgICB0aW1lc3RhbXAoeyBmb3JtYXQ6ICdZWVlZLU1NLUREVEhIOm1tOnNzLlNTU1onIH0pLFxuICBdO1xuXG4gIGlmICh1c2VKc29uKSB7XG4gICAgcmV0dXJuIHdpbnN0b24uY3JlYXRlTG9nZ2VyKHtcbiAgICAgIGxldmVsOiBsb2dMZXZlbCxcbiAgICAgIGRlZmF1bHRNZXRhOiB7IHNlcnZpY2U6IHNlcnZpY2VOYW1lIH0sXG4gICAgICBmb3JtYXQ6IGNvbWJpbmUoLi4uYmFzZUZvcm1hdHMsIGpzb24oKSksXG4gICAgICB0cmFuc3BvcnRzOiBbbmV3IHdpbnN0b24udHJhbnNwb3J0cy5Db25zb2xlKCldLFxuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHdpbnN0b24uY3JlYXRlTG9nZ2VyKHtcbiAgICBsZXZlbDogbG9nTGV2ZWwsXG4gICAgZGVmYXVsdE1ldGE6IHsgc2VydmljZTogc2VydmljZU5hbWUgfSxcbiAgICBmb3JtYXQ6IGNvbWJpbmUoLi4uYmFzZUZvcm1hdHMpLFxuICAgIHRyYW5zcG9ydHM6IFtcbiAgICAgIG5ldyB3aW5zdG9uLnRyYW5zcG9ydHMuQ29uc29sZSh7XG4gICAgICAgIGZvcm1hdDogY29tYmluZShjb2xvcml6ZSgpLCBjb25zb2xlRm9ybWF0KSxcbiAgICAgIH0pLFxuICAgIF0sXG4gIH0pO1xufVxuXG4vKipcbiAqIERlZmF1bHQgbG9nZ2VyIGluc3RhbmNlIChzZXJ2aWNlIG5hbWUgZnJvbSBTRVJWSUNFX05BTUUgZW52IHZhciBvciAnYXBpJykuXG4gKi9cbmV4cG9ydCBjb25zdCBsb2dnZXIgPSBjcmVhdGVMb2dnZXIocHJvY2Vzcy5lbnYuU0VSVklDRV9OQU1FIHx8ICdhcGknKTtcblxuZXhwb3J0IGRlZmF1bHQgbG9nZ2VyO1xuIl19
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Filter an object to only include entries where the value is not `undefined`.
|
|
3
|
+
* Keeps `null`, `false`, `0`, and empty string — only removes `undefined`.
|
|
4
|
+
*
|
|
5
|
+
* Useful for building partial update payloads from validated request bodies.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* const body = { name: 'foo', description: undefined, isActive: false };
|
|
10
|
+
* pickDefined(body); // { name: 'foo', isActive: false }
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export declare function pickDefined<T extends Record<string, unknown>>(obj: T): Partial<T>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.pickDefined = pickDefined;
|
|
6
|
+
/**
|
|
7
|
+
* Filter an object to only include entries where the value is not `undefined`.
|
|
8
|
+
* Keeps `null`, `false`, `0`, and empty string — only removes `undefined`.
|
|
9
|
+
*
|
|
10
|
+
* Useful for building partial update payloads from validated request bodies.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const body = { name: 'foo', description: undefined, isActive: false };
|
|
15
|
+
* pickDefined(body); // { name: 'foo', isActive: false }
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
function pickDefined(obj) {
|
|
19
|
+
return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== undefined));
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib2JqZWN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL29iamVjdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsK0NBQStDO0FBQy9DLHNDQUFzQzs7QUFjdEMsa0NBSUM7QUFoQkQ7Ozs7Ozs7Ozs7O0dBV0c7QUFDSCxTQUFnQixXQUFXLENBQW9DLEdBQU07SUFDbkUsT0FBTyxNQUFNLENBQUMsV0FBVyxDQUN2QixNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxLQUFLLFNBQVMsQ0FBQyxDQUN6QyxDQUFDO0FBQ2xCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuLyoqXG4gKiBGaWx0ZXIgYW4gb2JqZWN0IHRvIG9ubHkgaW5jbHVkZSBlbnRyaWVzIHdoZXJlIHRoZSB2YWx1ZSBpcyBub3QgYHVuZGVmaW5lZGAuXG4gKiBLZWVwcyBgbnVsbGAsIGBmYWxzZWAsIGAwYCwgYW5kIGVtcHR5IHN0cmluZyDigJQgb25seSByZW1vdmVzIGB1bmRlZmluZWRgLlxuICpcbiAqIFVzZWZ1bCBmb3IgYnVpbGRpbmcgcGFydGlhbCB1cGRhdGUgcGF5bG9hZHMgZnJvbSB2YWxpZGF0ZWQgcmVxdWVzdCBib2RpZXMuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IGJvZHkgPSB7IG5hbWU6ICdmb28nLCBkZXNjcmlwdGlvbjogdW5kZWZpbmVkLCBpc0FjdGl2ZTogZmFsc2UgfTtcbiAqIHBpY2tEZWZpbmVkKGJvZHkpOyAvLyB7IG5hbWU6ICdmb28nLCBpc0FjdGl2ZTogZmFsc2UgfVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwaWNrRGVmaW5lZDxUIGV4dGVuZHMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4+KG9iajogVCk6IFBhcnRpYWw8VD4ge1xuICByZXR1cm4gT2JqZWN0LmZyb21FbnRyaWVzKFxuICAgIE9iamVjdC5lbnRyaWVzKG9iaikuZmlsdGVyKChbLCB2XSkgPT4gdiAhPT0gdW5kZWZpbmVkKSxcbiAgKSBhcyBQYXJ0aWFsPFQ+O1xufVxuIl19
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { Request } from 'express';
|
|
2
|
+
/**
|
|
3
|
+
* Express 5 parameter type.
|
|
4
|
+
*/
|
|
5
|
+
type ParamValue = string | string[] | undefined;
|
|
6
|
+
/**
|
|
7
|
+
* Extract a single string parameter from Express 5 route params.
|
|
8
|
+
*
|
|
9
|
+
* @param params - Request params object
|
|
10
|
+
* @param key - Parameter key
|
|
11
|
+
* @returns The parameter value as a string, or undefined if not present
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* // Route: GET /plugins/:id
|
|
16
|
+
* const id = getParam(req.params, 'id');
|
|
17
|
+
* if (!id) {
|
|
18
|
+
* return sendError(res, 400, 'Missing id parameter');
|
|
19
|
+
* }
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare function getParam(params: Record<string, ParamValue>, key: string): string | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* Extract the organization ID from request.
|
|
25
|
+
* Checks params, headers, and user object.
|
|
26
|
+
*
|
|
27
|
+
* @param req - Express request object
|
|
28
|
+
* @returns Organization ID or undefined
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```typescript
|
|
32
|
+
* const orgId = getOrgId(req);
|
|
33
|
+
* if (!orgId) {
|
|
34
|
+
* return sendError(res, 400, 'Organization ID required');
|
|
35
|
+
* }
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare function getOrgId(req: Request): string | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* Get the authorization header from request.
|
|
41
|
+
*
|
|
42
|
+
* @param req - Express request object
|
|
43
|
+
* @returns Authorization header value or empty string
|
|
44
|
+
*/
|
|
45
|
+
export declare function getAuthHeader(req: Request): string;
|
|
46
|
+
/**
|
|
47
|
+
* Parse a query parameter as a boolean.
|
|
48
|
+
*
|
|
49
|
+
* @param value - Query parameter value
|
|
50
|
+
* @returns Parsed boolean or undefined
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```typescript
|
|
54
|
+
* const isActive = parseQueryBoolean(req.query.isActive);
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export declare function parseQueryBoolean(value: unknown): boolean | undefined;
|
|
58
|
+
/**
|
|
59
|
+
* Parse a query parameter as an integer.
|
|
60
|
+
*
|
|
61
|
+
* @param value - Query parameter value
|
|
62
|
+
* @param defaultValue - Default value if parsing fails
|
|
63
|
+
* @returns Parsed integer
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```typescript
|
|
67
|
+
* const limit = parseQueryInt(req.query.limit, 10);
|
|
68
|
+
* const offset = parseQueryInt(req.query.offset, 0);
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
export declare function parseQueryInt(value: unknown, defaultValue: number): number;
|
|
72
|
+
/**
|
|
73
|
+
* Parse a query parameter as a string.
|
|
74
|
+
*
|
|
75
|
+
* @param value - Query parameter value
|
|
76
|
+
* @returns String value or undefined
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```typescript
|
|
80
|
+
* const search = parseQueryString(req.query.search);
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
export declare function parseQueryString(value: unknown): string | undefined;
|
|
84
|
+
/**
|
|
85
|
+
* Parse a string to a positive integer, returning a fallback if invalid.
|
|
86
|
+
* Useful for parsing environment variables with numeric defaults.
|
|
87
|
+
*/
|
|
88
|
+
export declare function parsePositiveInt(value: string | undefined, fallback: number): number;
|
|
89
|
+
export {};
|