creo-flow-extensions-base 1.2.0-dev.1 → 1.2.0-dev.11
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/README.md +31 -0
- package/lib/connection/index.d.ts +1 -0
- package/lib/extension/enum/ContextMode.d.ts +19 -0
- package/lib/extension/enum/ContextMode.js +23 -0
- package/lib/extension/index.d.ts +2 -0
- package/lib/extension/index.js +2 -0
- package/lib/extension/interfaces/index.d.ts +15 -0
- package/lib/fields/code/index.d.ts +1 -1
- package/lib/fields/enum/index.d.ts +2 -1
- package/lib/fields/enum/index.js +1 -0
- package/lib/fields/index.d.ts +2 -1
- package/lib/fields/textarea/index.d.ts +5 -0
- package/lib/fields/textarea/index.js +2 -0
- package/lib/logger/configure.d.ts +8 -0
- package/lib/logger/configure.js +13 -0
- package/lib/logger/index.d.ts +6 -0
- package/lib/logger/index.js +9 -0
- package/lib/logger/interfaces/index.d.ts +4 -0
- package/lib/logger/interfaces/index.js +2 -0
- package/lib/logger/private/index.d.ts +89 -4
- package/lib/logger/private/index.js +170 -5
- package/lib/logger/private/logger-executor.d.ts +9 -2
- package/lib/logger/private/logger-executor.js +7 -0
- package/lib/logger/public/index.d.ts +9 -4
- package/lib/logger/public/index.js +26 -8
- package/lib/method/index.d.ts +13 -2
- package/lib/method/interfaces/index.d.ts +7 -0
- package/lib/method/interfaces/index.js +2 -0
- package/package.json +2 -2
package/README.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# creo-flow-extension-base
|
|
2
|
+
|
|
3
|
+
[](https://github.com/CloudDataHub/creo-flow-extension-base/actions/workflows/ci.yml)
|
|
4
|
+
|
|
5
|
+
Base library for Creo Flow extensions.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install creo-flow-extension-base
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Development
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Install dependencies
|
|
17
|
+
npm install
|
|
18
|
+
|
|
19
|
+
# Build TypeScript
|
|
20
|
+
npm run build
|
|
21
|
+
|
|
22
|
+
# Run linter
|
|
23
|
+
npm run lint
|
|
24
|
+
|
|
25
|
+
# Format code
|
|
26
|
+
npm run format
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## License
|
|
30
|
+
|
|
31
|
+
ISC
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Defines how the extension receives and processes context.
|
|
3
|
+
*
|
|
4
|
+
* - `SIMPLIFIED` — the platform automatically parses the context and passes
|
|
5
|
+
* a pre-processed, small context payload to the extension.
|
|
6
|
+
* This mode supports only small context sizes (less than 0.1 MB).
|
|
7
|
+
* Use this mode when you want a simple setup and do not need to handle
|
|
8
|
+
* large or highly customized context structures.
|
|
9
|
+
*
|
|
10
|
+
* - `MANUAL` — the context is delivered to the extension as a separate,
|
|
11
|
+
* raw object and must be parsed manually inside the extension.
|
|
12
|
+
* In this mode, the `context` object is also passed directly into the
|
|
13
|
+
* extension method, giving you more flexibility and control over how the
|
|
14
|
+
* context is interpreted, transformed, and used.
|
|
15
|
+
*/
|
|
16
|
+
export declare enum ContextMode {
|
|
17
|
+
SIMPLIFIED = "simplified",
|
|
18
|
+
MANUAL = "manual"
|
|
19
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ContextMode = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Defines how the extension receives and processes context.
|
|
6
|
+
*
|
|
7
|
+
* - `SIMPLIFIED` — the platform automatically parses the context and passes
|
|
8
|
+
* a pre-processed, small context payload to the extension.
|
|
9
|
+
* This mode supports only small context sizes (less than 0.1 MB).
|
|
10
|
+
* Use this mode when you want a simple setup and do not need to handle
|
|
11
|
+
* large or highly customized context structures.
|
|
12
|
+
*
|
|
13
|
+
* - `MANUAL` — the context is delivered to the extension as a separate,
|
|
14
|
+
* raw object and must be parsed manually inside the extension.
|
|
15
|
+
* In this mode, the `context` object is also passed directly into the
|
|
16
|
+
* extension method, giving you more flexibility and control over how the
|
|
17
|
+
* context is interpreted, transformed, and used.
|
|
18
|
+
*/
|
|
19
|
+
var ContextMode;
|
|
20
|
+
(function (ContextMode) {
|
|
21
|
+
ContextMode["SIMPLIFIED"] = "simplified";
|
|
22
|
+
ContextMode["MANUAL"] = "manual";
|
|
23
|
+
})(ContextMode || (exports.ContextMode = ContextMode = {}));
|
package/lib/extension/index.d.ts
CHANGED
package/lib/extension/index.js
CHANGED
|
@@ -16,6 +16,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
exports.createExtension = void 0;
|
|
18
18
|
__exportStar(require("./enum/ExtensionTypes"), exports);
|
|
19
|
+
__exportStar(require("./enum/ContextMode"), exports);
|
|
20
|
+
__exportStar(require("./interfaces"), exports);
|
|
19
21
|
const createExtension = (extension) => {
|
|
20
22
|
return extension;
|
|
21
23
|
};
|
|
@@ -2,6 +2,7 @@ import { IMethodSchema } from '../../method';
|
|
|
2
2
|
import { Field } from '../../fields';
|
|
3
3
|
import { IConnectionSchema } from '../../connection';
|
|
4
4
|
import { ExtensionTypes } from '../enum/ExtensionTypes';
|
|
5
|
+
import { ContextMode } from '../enum/ContextMode';
|
|
5
6
|
export interface ICreateExtensionParams {
|
|
6
7
|
methods: IMethodSchema<readonly Field[], readonly Field[]>[];
|
|
7
8
|
connections?: IConnectionSchema<readonly Field[]>[];
|
|
@@ -11,4 +12,18 @@ export interface ICreateExtensionParams {
|
|
|
11
12
|
version: string;
|
|
12
13
|
icon: string;
|
|
13
14
|
type: ExtensionTypes;
|
|
15
|
+
/**
|
|
16
|
+
* Context processing mode used by this extension.
|
|
17
|
+
*
|
|
18
|
+
* - `ContextMode.SIMPLIFIED` — the platform automatically parses the context
|
|
19
|
+
* and passes a simplified, small context payload to the extension
|
|
20
|
+
* (maximum size: less than 0.1 MB). Use this when you do not need to
|
|
21
|
+
* handle large or highly customized context structures.
|
|
22
|
+
*
|
|
23
|
+
* - `ContextMode.MANUAL` — the context is passed as a separate raw object
|
|
24
|
+
* and must be parsed manually inside the extension. In this mode, the
|
|
25
|
+
* context object is also forwarded to the extension method, allowing more
|
|
26
|
+
* flexible handling of complex or large context payloads.
|
|
27
|
+
*/
|
|
28
|
+
contextMode: ContextMode;
|
|
14
29
|
}
|
|
@@ -6,7 +6,8 @@ export declare enum FieldTypes {
|
|
|
6
6
|
AUTOCOMPLETE = "autocomplete",
|
|
7
7
|
DYNAMIC_FIELDS_LIST = "dynamicFieldsList",
|
|
8
8
|
FIELDS_GROUP = "fieldsListGroup",
|
|
9
|
-
COLLAPSIBLE_FIELDS_LIST = "collapsibleFieldsList"
|
|
9
|
+
COLLAPSIBLE_FIELDS_LIST = "collapsibleFieldsList",
|
|
10
|
+
TEXTAREA = "textarea"
|
|
10
11
|
}
|
|
11
12
|
export declare enum ContentType {
|
|
12
13
|
STRING = "string",
|
package/lib/fields/enum/index.js
CHANGED
|
@@ -11,6 +11,7 @@ var FieldTypes;
|
|
|
11
11
|
FieldTypes["DYNAMIC_FIELDS_LIST"] = "dynamicFieldsList";
|
|
12
12
|
FieldTypes["FIELDS_GROUP"] = "fieldsListGroup";
|
|
13
13
|
FieldTypes["COLLAPSIBLE_FIELDS_LIST"] = "collapsibleFieldsList";
|
|
14
|
+
FieldTypes["TEXTAREA"] = "textarea";
|
|
14
15
|
})(FieldTypes || (exports.FieldTypes = FieldTypes = {}));
|
|
15
16
|
var ContentType;
|
|
16
17
|
(function (ContentType) {
|
package/lib/fields/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { ICodeField } from './code';
|
|
|
5
5
|
import { ICollapsibleFieldsList } from './collapsibleFieldsList';
|
|
6
6
|
import { IDynamicFieldsList } from './dynamicFieldsList';
|
|
7
7
|
import { IFieldsGroup } from './fieldsGroup';
|
|
8
|
+
import { ITextareaField } from './textarea';
|
|
8
9
|
export * from './enum';
|
|
9
|
-
export type Field = IInputField | ISelectField | ICheckboxField | ICodeField | ICollapsibleFieldsList | IDynamicFieldsList | IFieldsGroup;
|
|
10
|
+
export type Field = IInputField | ISelectField | ICheckboxField | ICodeField | ICollapsibleFieldsList | IDynamicFieldsList | IFieldsGroup | ITextareaField;
|
|
10
11
|
export declare function createFields<const T extends readonly Field[]>(fields: T & Field[]): T;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { LoggerOptions } from './private';
|
|
2
|
+
/**
|
|
3
|
+
* Configures the shared extension logger used by both the template (extension-service-base)
|
|
4
|
+
* and extensions. Call this once at container/bootstrap before loading extensions.
|
|
5
|
+
*
|
|
6
|
+
* @param options - Logger configuration (transport, storeInMemory, etc.)
|
|
7
|
+
*/
|
|
8
|
+
export declare function configureExtensionLogger(options: LoggerOptions): void;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.configureExtensionLogger = configureExtensionLogger;
|
|
4
|
+
const private_1 = require("./private");
|
|
5
|
+
/**
|
|
6
|
+
* Configures the shared extension logger used by both the template (extension-service-base)
|
|
7
|
+
* and extensions. Call this once at container/bootstrap before loading extensions.
|
|
8
|
+
*
|
|
9
|
+
* @param options - Logger configuration (transport, storeInMemory, etc.)
|
|
10
|
+
*/
|
|
11
|
+
function configureExtensionLogger(options) {
|
|
12
|
+
private_1.internalLogger.initialize(undefined, options);
|
|
13
|
+
}
|
package/lib/logger/index.d.ts
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
1
|
export * from './public';
|
|
2
|
+
export { Logger, LogEntry } from './private';
|
|
3
|
+
export type { LoggerOptions, LogTransport } from './private';
|
|
4
|
+
export { runWithLogger } from './private/logger-executor';
|
|
5
|
+
export { configureExtensionLogger } from './configure';
|
|
6
|
+
export { LogType } from './enum/LogType';
|
|
7
|
+
export type { ILogPayload } from './interfaces';
|
package/lib/logger/index.js
CHANGED
|
@@ -14,4 +14,13 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.LogType = exports.configureExtensionLogger = exports.runWithLogger = exports.Logger = void 0;
|
|
17
18
|
__exportStar(require("./public"), exports);
|
|
19
|
+
var private_1 = require("./private");
|
|
20
|
+
Object.defineProperty(exports, "Logger", { enumerable: true, get: function () { return private_1.Logger; } });
|
|
21
|
+
var logger_executor_1 = require("./private/logger-executor");
|
|
22
|
+
Object.defineProperty(exports, "runWithLogger", { enumerable: true, get: function () { return logger_executor_1.runWithLogger; } });
|
|
23
|
+
var configure_1 = require("./configure");
|
|
24
|
+
Object.defineProperty(exports, "configureExtensionLogger", { enumerable: true, get: function () { return configure_1.configureExtensionLogger; } });
|
|
25
|
+
var LogType_1 = require("./enum/LogType");
|
|
26
|
+
Object.defineProperty(exports, "LogType", { enumerable: true, get: function () { return LogType_1.LogType; } });
|
|
@@ -1,13 +1,98 @@
|
|
|
1
1
|
import { LogType } from '../enum/LogType';
|
|
2
|
+
import { ILogPayload } from '../interfaces';
|
|
2
3
|
export interface LogEntry {
|
|
3
4
|
type: LogType;
|
|
4
|
-
payload:
|
|
5
|
+
payload: ILogPayload;
|
|
5
6
|
timestamp: number;
|
|
6
7
|
}
|
|
7
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Transport function for forwarding logs to external systems (e.g., CloudWatch).
|
|
10
|
+
* Called asynchronously for each log entry.
|
|
11
|
+
*/
|
|
12
|
+
export type LogTransport = (entry: LogEntry) => void | Promise<void>;
|
|
13
|
+
export interface LoggerOptions {
|
|
14
|
+
/**
|
|
15
|
+
* Whether to store logs in memory.
|
|
16
|
+
* If false, logs are only forwarded to transport (if configured) and not stored.
|
|
17
|
+
* Default: false
|
|
18
|
+
*/
|
|
19
|
+
storeInMemory?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Maximum number of log entries to keep in memory.
|
|
22
|
+
* When exceeded, oldest logs are removed (FIFO).
|
|
23
|
+
* Only applies if storeInMemory is true.
|
|
24
|
+
* Default: 1000
|
|
25
|
+
*/
|
|
26
|
+
maxLogCount?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Maximum total size of log entries in bytes (approximate).
|
|
29
|
+
* When exceeded, oldest logs are removed until under limit.
|
|
30
|
+
* Only applies if storeInMemory is true.
|
|
31
|
+
* Default: 10MB (10 * 1024 * 1024)
|
|
32
|
+
*/
|
|
33
|
+
maxLogSizeBytes?: number;
|
|
34
|
+
/**
|
|
35
|
+
* Whether to warn when log limits are exceeded.
|
|
36
|
+
* Default: true
|
|
37
|
+
*/
|
|
38
|
+
warnOnLimitExceeded?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Optional transport function to forward logs to external systems (e.g., CloudWatch).
|
|
41
|
+
* This is called for each log entry asynchronously (fire-and-forget).
|
|
42
|
+
* Works independently of storeInMemory - logs are always forwarded if transport is set.
|
|
43
|
+
*/
|
|
44
|
+
transport?: LogTransport;
|
|
45
|
+
}
|
|
46
|
+
export declare class Logger {
|
|
8
47
|
private readonly storage;
|
|
48
|
+
private defaultStore;
|
|
49
|
+
private options;
|
|
50
|
+
private hasWarnedLimit;
|
|
51
|
+
/**
|
|
52
|
+
* Initialize the logger with a default store and optional configuration.
|
|
53
|
+
*
|
|
54
|
+
* @param defaultStore - Optional array to store logs in. If not provided and storeInMemory is true, creates a new array.
|
|
55
|
+
* @param options - Logger configuration options
|
|
56
|
+
*/
|
|
57
|
+
initialize(defaultStore?: LogEntry[], options?: LoggerOptions): void;
|
|
58
|
+
/**
|
|
59
|
+
* Configure logger options.
|
|
60
|
+
*/
|
|
61
|
+
configure(options: LoggerOptions): void;
|
|
62
|
+
/**
|
|
63
|
+
* Set or update the transport function for forwarding logs.
|
|
64
|
+
*/
|
|
65
|
+
setTransport(transport: LogTransport | undefined): void;
|
|
66
|
+
/**
|
|
67
|
+
* Run a function with a specific logger store in async context.
|
|
68
|
+
*/
|
|
9
69
|
runWithLogger<T>(store: LogEntry[], fn: () => T): T;
|
|
10
|
-
|
|
70
|
+
/**
|
|
71
|
+
* Log an entry. Uses AsyncLocalStorage if available, otherwise falls back to default store.
|
|
72
|
+
* If storeInMemory is false, only forwards to transport (if configured).
|
|
73
|
+
* Automatically truncates logs if limits are exceeded (only if storing in memory).
|
|
74
|
+
* If a transport is configured, forwards the log entry to it asynchronously.
|
|
75
|
+
*/
|
|
76
|
+
log(type: LogType, payload: ILogPayload): void;
|
|
77
|
+
/**
|
|
78
|
+
* Get the current log entries from the store.
|
|
79
|
+
* Returns empty array if storeInMemory is false.
|
|
80
|
+
*/
|
|
81
|
+
getLogs(): ReadonlyArray<LogEntry>;
|
|
82
|
+
/**
|
|
83
|
+
* Get approximate total size of logs in bytes.
|
|
84
|
+
* Returns 0 if storeInMemory is false.
|
|
85
|
+
*/
|
|
86
|
+
getLogsSize(): number;
|
|
87
|
+
/**
|
|
88
|
+
* Clear the current log entries.
|
|
89
|
+
*/
|
|
90
|
+
clear(): void;
|
|
91
|
+
private getStore;
|
|
92
|
+
private estimateLogSize;
|
|
93
|
+
private truncateLogsIfNeeded;
|
|
94
|
+
private calculateTotalSize;
|
|
95
|
+
private warnLimitExceeded;
|
|
96
|
+
private forwardToTransport;
|
|
11
97
|
}
|
|
12
98
|
export declare const internalLogger: Logger;
|
|
13
|
-
export {};
|
|
@@ -1,17 +1,182 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.internalLogger = void 0;
|
|
3
|
+
exports.internalLogger = exports.Logger = void 0;
|
|
4
4
|
const node_async_hooks_1 = require("node:async_hooks");
|
|
5
|
+
const DEFAULT_MAX_LOG_COUNT = 1000;
|
|
6
|
+
const DEFAULT_MAX_LOG_SIZE_BYTES = 10 * 1024 * 1024;
|
|
7
|
+
const FALLBACK_PAYLOAD_SIZE = 1024;
|
|
8
|
+
const BYTES_PER_CHAR = 2;
|
|
5
9
|
class Logger {
|
|
6
10
|
storage = new node_async_hooks_1.AsyncLocalStorage();
|
|
11
|
+
defaultStore = null;
|
|
12
|
+
options = {
|
|
13
|
+
storeInMemory: false,
|
|
14
|
+
maxLogCount: DEFAULT_MAX_LOG_COUNT,
|
|
15
|
+
maxLogSizeBytes: DEFAULT_MAX_LOG_SIZE_BYTES,
|
|
16
|
+
warnOnLimitExceeded: true,
|
|
17
|
+
};
|
|
18
|
+
hasWarnedLimit = false;
|
|
19
|
+
/**
|
|
20
|
+
* Initialize the logger with a default store and optional configuration.
|
|
21
|
+
*
|
|
22
|
+
* @param defaultStore - Optional array to store logs in. If not provided and storeInMemory is true, creates a new array.
|
|
23
|
+
* @param options - Logger configuration options
|
|
24
|
+
*/
|
|
25
|
+
initialize(defaultStore, options) {
|
|
26
|
+
const storeInMemory = options?.storeInMemory ?? this.options.storeInMemory;
|
|
27
|
+
this.defaultStore = storeInMemory ? (defaultStore ?? []) : null;
|
|
28
|
+
if (options) {
|
|
29
|
+
this.options = {
|
|
30
|
+
storeInMemory,
|
|
31
|
+
maxLogCount: options.maxLogCount ?? this.options.maxLogCount,
|
|
32
|
+
maxLogSizeBytes: options.maxLogSizeBytes ?? this.options.maxLogSizeBytes,
|
|
33
|
+
warnOnLimitExceeded: options.warnOnLimitExceeded ?? this.options.warnOnLimitExceeded,
|
|
34
|
+
transport: options.transport ?? this.options.transport,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Configure logger options.
|
|
40
|
+
*/
|
|
41
|
+
configure(options) {
|
|
42
|
+
this.options = {
|
|
43
|
+
...this.options,
|
|
44
|
+
...options,
|
|
45
|
+
maxLogCount: options.maxLogCount ?? this.options.maxLogCount,
|
|
46
|
+
maxLogSizeBytes: options.maxLogSizeBytes ?? this.options.maxLogSizeBytes,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Set or update the transport function for forwarding logs.
|
|
51
|
+
*/
|
|
52
|
+
setTransport(transport) {
|
|
53
|
+
this.options.transport = transport;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Run a function with a specific logger store in async context.
|
|
57
|
+
*/
|
|
7
58
|
runWithLogger(store, fn) {
|
|
8
59
|
return this.storage.run(store, fn);
|
|
9
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Log an entry. Uses AsyncLocalStorage if available, otherwise falls back to default store.
|
|
63
|
+
* If storeInMemory is false, only forwards to transport (if configured).
|
|
64
|
+
* Automatically truncates logs if limits are exceeded (only if storing in memory).
|
|
65
|
+
* If a transport is configured, forwards the log entry to it asynchronously.
|
|
66
|
+
*/
|
|
10
67
|
log(type, payload) {
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
68
|
+
const safePayload = payload ?? {};
|
|
69
|
+
const entry = { type, payload: safePayload, timestamp: Date.now() };
|
|
70
|
+
if (this.options.storeInMemory) {
|
|
71
|
+
const store = this.getStore();
|
|
72
|
+
store.push(entry);
|
|
73
|
+
this.truncateLogsIfNeeded(store);
|
|
74
|
+
}
|
|
75
|
+
this.forwardToTransport(entry);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Get the current log entries from the store.
|
|
79
|
+
* Returns empty array if storeInMemory is false.
|
|
80
|
+
*/
|
|
81
|
+
getLogs() {
|
|
82
|
+
if (!this.options.storeInMemory) {
|
|
83
|
+
return [];
|
|
84
|
+
}
|
|
85
|
+
return this.getStore();
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Get approximate total size of logs in bytes.
|
|
89
|
+
* Returns 0 if storeInMemory is false.
|
|
90
|
+
*/
|
|
91
|
+
getLogsSize() {
|
|
92
|
+
if (!this.options.storeInMemory) {
|
|
93
|
+
return 0;
|
|
94
|
+
}
|
|
95
|
+
return this.calculateTotalSize(this.getStore());
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Clear the current log entries.
|
|
99
|
+
*/
|
|
100
|
+
clear() {
|
|
101
|
+
if (!this.options.storeInMemory) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const store = this.getStore();
|
|
105
|
+
store.length = 0;
|
|
106
|
+
this.hasWarnedLimit = false;
|
|
107
|
+
}
|
|
108
|
+
getStore() {
|
|
109
|
+
const store = this.storage.getStore() || this.defaultStore;
|
|
110
|
+
if (!store) {
|
|
111
|
+
throw new Error('Logger store not set. Call initialize() or runWithLogger() first.');
|
|
112
|
+
}
|
|
113
|
+
return store;
|
|
114
|
+
}
|
|
115
|
+
estimateLogSize(entry) {
|
|
116
|
+
let size = entry.type.length * BYTES_PER_CHAR + 8;
|
|
117
|
+
if (entry.payload.message) {
|
|
118
|
+
size += entry.payload.message.length * BYTES_PER_CHAR;
|
|
119
|
+
}
|
|
120
|
+
if (entry.payload.payload) {
|
|
121
|
+
try {
|
|
122
|
+
const serialized = JSON.stringify(entry.payload.payload);
|
|
123
|
+
size += serialized.length * BYTES_PER_CHAR;
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
size += FALLBACK_PAYLOAD_SIZE;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return size;
|
|
130
|
+
}
|
|
131
|
+
truncateLogsIfNeeded(store) {
|
|
132
|
+
const wasOverCountLimit = store.length > this.options.maxLogCount;
|
|
133
|
+
if (wasOverCountLimit) {
|
|
134
|
+
const removeCount = store.length - this.options.maxLogCount;
|
|
135
|
+
store.splice(0, removeCount);
|
|
136
|
+
}
|
|
137
|
+
let totalSize = this.calculateTotalSize(store);
|
|
138
|
+
const wasOverSizeLimit = totalSize > this.options.maxLogSizeBytes;
|
|
139
|
+
while (totalSize > this.options.maxLogSizeBytes && store.length > 0) {
|
|
140
|
+
const removed = store.shift();
|
|
141
|
+
if (removed) {
|
|
142
|
+
totalSize -= this.estimateLogSize(removed);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
const shouldWarn = (wasOverCountLimit || wasOverSizeLimit) &&
|
|
146
|
+
this.options.warnOnLimitExceeded &&
|
|
147
|
+
!this.hasWarnedLimit;
|
|
148
|
+
if (shouldWarn) {
|
|
149
|
+
this.warnLimitExceeded(store.length, totalSize);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
calculateTotalSize(store) {
|
|
153
|
+
return store.reduce((total, entry) => total + this.estimateLogSize(entry), 0);
|
|
154
|
+
}
|
|
155
|
+
warnLimitExceeded(entryCount, totalSize) {
|
|
156
|
+
console.warn(`[Logger] Log limits exceeded. Logs have been truncated. ` +
|
|
157
|
+
`Current: ${entryCount} entries, ~${Math.round(totalSize / 1024)}KB. ` +
|
|
158
|
+
`Limits: ${this.options.maxLogCount} entries, ${Math.round(this.options.maxLogSizeBytes / 1024 / 1024)}MB`);
|
|
159
|
+
this.hasWarnedLimit = true;
|
|
160
|
+
}
|
|
161
|
+
forwardToTransport(entry) {
|
|
162
|
+
const transport = this.options.transport;
|
|
163
|
+
if (!transport) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
setImmediate(() => {
|
|
167
|
+
try {
|
|
168
|
+
const result = transport(entry);
|
|
169
|
+
if (result instanceof Promise) {
|
|
170
|
+
result.catch((error) => {
|
|
171
|
+
console.error('[Logger] Transport error:', error);
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
catch (error) {
|
|
176
|
+
console.error('[Logger] Transport error:', error);
|
|
177
|
+
}
|
|
178
|
+
});
|
|
15
179
|
}
|
|
16
180
|
}
|
|
181
|
+
exports.Logger = Logger;
|
|
17
182
|
exports.internalLogger = new Logger();
|
|
@@ -1,2 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { LogEntry } from '.';
|
|
2
|
+
/**
|
|
3
|
+
* Run a function with a logger store in async context.
|
|
4
|
+
*
|
|
5
|
+
* @param store - Array to store log entries for this execution context
|
|
6
|
+
* @param fn - Function to execute within the logger context
|
|
7
|
+
* @returns The return value of the executed function
|
|
8
|
+
*/
|
|
9
|
+
export declare function runWithLogger<T>(store: LogEntry[], fn: () => T): T;
|
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.runWithLogger = runWithLogger;
|
|
4
4
|
const _1 = require(".");
|
|
5
|
+
/**
|
|
6
|
+
* Run a function with a logger store in async context.
|
|
7
|
+
*
|
|
8
|
+
* @param store - Array to store log entries for this execution context
|
|
9
|
+
* @param fn - Function to execute within the logger context
|
|
10
|
+
* @returns The return value of the executed function
|
|
11
|
+
*/
|
|
5
12
|
function runWithLogger(store, fn) {
|
|
6
13
|
return _1.internalLogger.runWithLogger(store, fn);
|
|
7
14
|
}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
+
import { ILogPayload } from '../interfaces';
|
|
2
|
+
/**
|
|
3
|
+
* Public logger interface for convenient logging methods.
|
|
4
|
+
* Accepts ILogPayload, Error, string, or null/undefined.
|
|
5
|
+
*/
|
|
1
6
|
export declare const logger: {
|
|
2
|
-
info: (payload:
|
|
3
|
-
error: (payload:
|
|
4
|
-
warning: (payload:
|
|
5
|
-
debug: (payload:
|
|
7
|
+
info: (payload: ILogPayload | Error | string | null | undefined) => void;
|
|
8
|
+
error: (payload: ILogPayload | Error | string | null | undefined) => void;
|
|
9
|
+
warning: (payload: ILogPayload | Error | string | null | undefined) => void;
|
|
10
|
+
debug: (payload: ILogPayload | Error | string | null | undefined) => void;
|
|
6
11
|
};
|
|
@@ -3,13 +3,31 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.logger = void 0;
|
|
4
4
|
const private_1 = require("../private");
|
|
5
5
|
const LogType_1 = require("../enum/LogType");
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Normalizes input to ILogPayload. Handles null/undefined, Error, string, and ILogPayload.
|
|
8
|
+
*/
|
|
9
|
+
function normalizePayload(input) {
|
|
10
|
+
if (input == null) {
|
|
11
|
+
return {};
|
|
12
|
+
}
|
|
13
|
+
if (input instanceof Error) {
|
|
14
|
+
return {
|
|
15
|
+
message: input.message,
|
|
16
|
+
payload: { name: input.name, stack: input.stack },
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
if (typeof input === 'string') {
|
|
20
|
+
return { message: input };
|
|
21
|
+
}
|
|
22
|
+
return input;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Public logger interface for convenient logging methods.
|
|
26
|
+
* Accepts ILogPayload, Error, string, or null/undefined.
|
|
27
|
+
*/
|
|
10
28
|
exports.logger = {
|
|
11
|
-
info:
|
|
12
|
-
error:
|
|
13
|
-
warning:
|
|
14
|
-
debug:
|
|
29
|
+
info: (payload) => private_1.internalLogger.log(LogType_1.LogType.INFO, normalizePayload(payload)),
|
|
30
|
+
error: (payload) => private_1.internalLogger.log(LogType_1.LogType.ERROR, normalizePayload(payload)),
|
|
31
|
+
warning: (payload) => private_1.internalLogger.log(LogType_1.LogType.WARNING, normalizePayload(payload)),
|
|
32
|
+
debug: (payload) => private_1.internalLogger.log(LogType_1.LogType.DEBUG, normalizePayload(payload)),
|
|
15
33
|
};
|
package/lib/method/index.d.ts
CHANGED
|
@@ -1,17 +1,28 @@
|
|
|
1
1
|
import { Field } from '../fields';
|
|
2
2
|
import { FieldNameMap } from '../fields/interfaces';
|
|
3
3
|
import { SafeAny } from '../common/interfaces';
|
|
4
|
+
import { IDefaultExecutionArgs } from './interfaces';
|
|
4
5
|
export interface IMethodSchema<T extends readonly Field[], C extends readonly Field[] = [], S = SafeAny> {
|
|
5
6
|
label: string;
|
|
6
7
|
name: string;
|
|
7
8
|
description: string;
|
|
8
9
|
fields: T;
|
|
9
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Executes the method logic.
|
|
12
|
+
*
|
|
13
|
+
* @param args - Aggregated field values and default execution arguments.
|
|
14
|
+
*/
|
|
15
|
+
execute: (args: FieldNameMap<T> & FieldNameMap<C> & IDefaultExecutionArgs) => S;
|
|
10
16
|
}
|
|
11
17
|
export declare function createMethodSchema<const T extends readonly Field[], const C extends readonly Field[] = [], S = SafeAny>(schema: {
|
|
12
18
|
label: string;
|
|
13
19
|
name: string;
|
|
14
20
|
description: string;
|
|
15
21
|
fields: T;
|
|
16
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Executes the method logic.
|
|
24
|
+
*
|
|
25
|
+
* @param args - Aggregated field values and default execution arguments.
|
|
26
|
+
*/
|
|
27
|
+
execute: (args: FieldNameMap<T> & FieldNameMap<C> & IDefaultExecutionArgs) => S;
|
|
17
28
|
}): IMethodSchema<T, C, S>;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "creo-flow-extensions-base",
|
|
3
|
-
"version": "1.2.0-dev.
|
|
4
|
-
"main": "index.js",
|
|
3
|
+
"version": "1.2.0-dev.11",
|
|
4
|
+
"main": "lib/index.js",
|
|
5
5
|
"repository": "git@github.com:CloudDataHub/creo-flow-extension-base.git",
|
|
6
6
|
"author": "Naum Zakletskyi",
|
|
7
7
|
"license": "ISC",
|