@antelopejs/interface-core 0.0.6 → 0.0.8
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/dist/errors.d.ts +20 -0
- package/dist/errors.js +46 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -1
- package/dist/proxies.js +3 -4
- package/dist/proxies.js.map +1 -1
- package/dist/tests/stub-mode.test.js +34 -3
- package/dist/tests/stub-mode.test.js.map +1 -1
- package/docs/1.introduction.md +69 -0
- package/docs/2.proxies.md +226 -0
- package/docs/3.decorators.md +169 -0
- package/docs/4.metadata.md +107 -0
- package/docs/5.modules.md +180 -0
- package/docs/6.logging.md +106 -0
- package/docs/7.configuration.md +182 -0
- package/docs/8.runtime.md +60 -0
- package/package.json +8 -3
- package/skills/core-interface/SKILL.md +98 -0
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# Decorators
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The `@antelopejs/interface-core/decorators` module provides factory functions for creating type-safe TypeScript decorators. These factories handle the boilerplate of splitting decorator arguments from factory arguments, producing reusable, parameterized decorators for classes, properties, methods, and parameters.
|
|
6
|
+
|
|
7
|
+
## Import
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import {
|
|
11
|
+
MakeClassDecorator,
|
|
12
|
+
MakePropertyDecorator,
|
|
13
|
+
MakeMethodDecorator,
|
|
14
|
+
MakeParameterDecorator,
|
|
15
|
+
} from "@antelopejs/interface-core/decorators";
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Types
|
|
19
|
+
|
|
20
|
+
The module exports several utility types used throughout the decorator system:
|
|
21
|
+
|
|
22
|
+
| Type | Description |
|
|
23
|
+
| -------------------- | ------------------------------------------------------------ |
|
|
24
|
+
| `Func<A, R>` | Generic function type with arguments `A` and return type `R` |
|
|
25
|
+
| `Class<T, A>` | Class constructor that creates instances of type `T` |
|
|
26
|
+
| `ClassDecorator<C>` | Decorator applied to class constructors |
|
|
27
|
+
| `PropertyDecorator` | Decorator applied to class properties |
|
|
28
|
+
| `MethodDecorator` | Decorator applied to class methods and accessors |
|
|
29
|
+
| `ParameterDecorator` | Decorator applied to method parameters |
|
|
30
|
+
|
|
31
|
+
## Single-target decorator factories
|
|
32
|
+
|
|
33
|
+
### `MakeClassDecorator`
|
|
34
|
+
|
|
35
|
+
Creates a decorator factory that targets classes. The handler receives the decorated class as its first argument, followed by any factory parameters.
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { MakeClassDecorator } from "@antelopejs/interface-core/decorators";
|
|
39
|
+
|
|
40
|
+
const Entity = MakeClassDecorator((target: Function, tableName: string) => {
|
|
41
|
+
Reflect.defineMetadata("table", tableName, target);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
@Entity("users")
|
|
45
|
+
class User {
|
|
46
|
+
name!: string;
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### `MakePropertyDecorator`
|
|
51
|
+
|
|
52
|
+
Creates a decorator factory that targets properties. The handler receives the target object and property key, followed by factory parameters.
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
import { MakePropertyDecorator } from "@antelopejs/interface-core/decorators";
|
|
56
|
+
|
|
57
|
+
const Column = MakePropertyDecorator((target: any, key: PropertyKey, columnName: string) => {
|
|
58
|
+
const columns = Reflect.getOwnMetadata("columns", target) || [];
|
|
59
|
+
columns.push({ key, columnName });
|
|
60
|
+
Reflect.defineMetadata("columns", columns, target);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
class User {
|
|
64
|
+
@Column("user_name")
|
|
65
|
+
name!: string;
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### `MakeMethodDecorator`
|
|
70
|
+
|
|
71
|
+
Creates a decorator factory that targets methods and accessors. The handler receives the target object, method key, and property descriptor, followed by factory parameters.
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
import { MakeMethodDecorator } from "@antelopejs/interface-core/decorators";
|
|
75
|
+
|
|
76
|
+
const Log = MakeMethodDecorator(
|
|
77
|
+
(target: any, key: PropertyKey, descriptor: PropertyDescriptor, level: string) => {
|
|
78
|
+
const original = descriptor.value;
|
|
79
|
+
descriptor.value = function (...args: any[]) {
|
|
80
|
+
console.log(`[${level}] Calling ${String(key)}`);
|
|
81
|
+
return original.apply(this, args);
|
|
82
|
+
};
|
|
83
|
+
},
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
class Service {
|
|
87
|
+
@Log("info")
|
|
88
|
+
process() {
|
|
89
|
+
// ...
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### `MakeParameterDecorator`
|
|
95
|
+
|
|
96
|
+
Creates a decorator factory that targets method parameters. The handler receives the target object, method key, and parameter index, followed by factory parameters.
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
import { MakeParameterDecorator } from "@antelopejs/interface-core/decorators";
|
|
100
|
+
|
|
101
|
+
const Inject = MakeParameterDecorator(
|
|
102
|
+
(target: any, key: PropertyKey, index: number, token: string) => {
|
|
103
|
+
const injections = Reflect.getOwnMetadata("injections", target, key) || [];
|
|
104
|
+
injections[index] = token;
|
|
105
|
+
Reflect.defineMetadata("injections", injections, target, key);
|
|
106
|
+
},
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
class Controller {
|
|
110
|
+
handle(@Inject("db") db: any) {
|
|
111
|
+
// ...
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Multi-target decorator factories
|
|
117
|
+
|
|
118
|
+
For decorators that apply to multiple targets, the module provides combined factory functions. These detect the decorator context automatically based on the number and types of arguments received.
|
|
119
|
+
|
|
120
|
+
| Factory | Targets |
|
|
121
|
+
| -------------------------------------------------- | ----------------------------------------- |
|
|
122
|
+
| `MakePropertyAndClassDecorator` | Properties and classes |
|
|
123
|
+
| `MakeMethodAndClassDecorator` | Methods and classes |
|
|
124
|
+
| `MakeMethodAndPropertyDecorator` | Methods and properties |
|
|
125
|
+
| `MakeMethodAndPropertyAndClassDecorator` | Methods, properties, and classes |
|
|
126
|
+
| `MakeParameterAndClassDecorator` | Parameters and classes |
|
|
127
|
+
| `MakeParameterAndPropertyDecorator` | Parameters and properties |
|
|
128
|
+
| `MakeParameterAndPropertyAndClassDecorator` | Parameters, properties, and classes |
|
|
129
|
+
| `MakeParameterAndMethodDecorator` | Parameters and methods |
|
|
130
|
+
| `MakeParameterAndMethodAndClassDecorator` | Parameters, methods, and classes |
|
|
131
|
+
| `MakeParameterAndMethodAndPropertyDecorator` | Parameters, methods, and properties |
|
|
132
|
+
| `MakeParameterAndMethodAndPropertyAndClassDecorator`| Parameters, methods, properties, classes |
|
|
133
|
+
|
|
134
|
+
### Example: method and class decorator
|
|
135
|
+
|
|
136
|
+
```ts
|
|
137
|
+
import { MakeMethodAndClassDecorator } from "@antelopejs/interface-core/decorators";
|
|
138
|
+
|
|
139
|
+
const Track = MakeMethodAndClassDecorator(
|
|
140
|
+
(target: any, key: PropertyKey | undefined, descriptor: PropertyDescriptor | undefined, category: string) => {
|
|
141
|
+
if (descriptor) {
|
|
142
|
+
// Applied to a method
|
|
143
|
+
const original = descriptor.value;
|
|
144
|
+
descriptor.value = function (...args: any[]) {
|
|
145
|
+
console.log(`[${category}] ${String(key)} called`);
|
|
146
|
+
return original.apply(this, args);
|
|
147
|
+
};
|
|
148
|
+
} else {
|
|
149
|
+
// Applied to a class
|
|
150
|
+
Reflect.defineMetadata("trackCategory", category, target);
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
@Track("api")
|
|
156
|
+
class ApiController {
|
|
157
|
+
@Track("endpoint")
|
|
158
|
+
getUsers() {
|
|
159
|
+
// ...
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
When applied to a class, the `key` and `descriptor` arguments are `undefined`. When applied to a method, all three arguments are provided.
|
|
165
|
+
|
|
166
|
+
## Next steps
|
|
167
|
+
|
|
168
|
+
- [Metadata](./4.metadata.md) - Reflection-based metadata with `GetMetadata`
|
|
169
|
+
- [Proxies](./2.proxies.md) - Module-aware proxy classes
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# Metadata
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The `GetMetadata` function provides a reflection-based metadata system built on top of the `reflect-metadata` library. It retrieves or creates metadata instances associated with target objects, supporting inheritance through the prototype chain.
|
|
6
|
+
|
|
7
|
+
## Import
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { GetMetadata } from "@antelopejs/interface-core";
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## `GetMetadata`
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
function GetMetadata<T, U>(target: U, meta: Class<T, [U]> & { key: symbol }, inherit?: boolean): T
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Parameters
|
|
20
|
+
|
|
21
|
+
| Parameter | Type | Default | Description |
|
|
22
|
+
| --------- | -------------------------------- | ------- | ---------------------------------------------------- |
|
|
23
|
+
| `target` | `U` | - | The object to retrieve or create metadata for |
|
|
24
|
+
| `meta` | `Class<T, [U]> & { key: symbol }` | - | A metadata class with a static `key` symbol |
|
|
25
|
+
| `inherit` | `boolean` | `true` | Whether to inherit metadata from the prototype chain |
|
|
26
|
+
|
|
27
|
+
### Return value
|
|
28
|
+
|
|
29
|
+
Returns the metadata instance of type `T` associated with the target.
|
|
30
|
+
|
|
31
|
+
## Define a metadata class
|
|
32
|
+
|
|
33
|
+
A metadata class must have a static `key` property (a `Symbol`) and accept the target object as a constructor argument.
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
class RouteMetadata {
|
|
37
|
+
static key = Symbol("RouteMetadata");
|
|
38
|
+
|
|
39
|
+
public routes: Map<string, string> = new Map();
|
|
40
|
+
|
|
41
|
+
constructor(_target: any) {
|
|
42
|
+
// Initialize metadata for the target
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Retrieve metadata
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
import { GetMetadata } from "@antelopejs/interface-core";
|
|
51
|
+
|
|
52
|
+
class UserController {
|
|
53
|
+
getUser() {}
|
|
54
|
+
listUsers() {}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const meta = GetMetadata(UserController.prototype, RouteMetadata);
|
|
58
|
+
meta.routes.set("getUser", "/users/:id");
|
|
59
|
+
meta.routes.set("listUsers", "/users");
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Calling `GetMetadata` multiple times with the same target and metadata class returns the same instance. The metadata is stored on the target using `Reflect.defineMetadata`.
|
|
63
|
+
|
|
64
|
+
## Inheritance
|
|
65
|
+
|
|
66
|
+
When `inherit` is `true` (the default), `GetMetadata` walks the prototype chain to find parent metadata. If the metadata class defines an `inherit` method, that method is called with the parent metadata. Otherwise, properties from the parent are copied to the child metadata where they do not already exist.
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
class ControllerMeta {
|
|
70
|
+
static key = Symbol("ControllerMeta");
|
|
71
|
+
|
|
72
|
+
public middleware: string[] = [];
|
|
73
|
+
|
|
74
|
+
constructor(_target: any) {}
|
|
75
|
+
|
|
76
|
+
inherit(parent: ControllerMeta) {
|
|
77
|
+
this.middleware = [...parent.middleware];
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
class BaseController {}
|
|
82
|
+
const baseMeta = GetMetadata(BaseController.prototype, ControllerMeta);
|
|
83
|
+
baseMeta.middleware.push("auth");
|
|
84
|
+
|
|
85
|
+
class AdminController extends BaseController {}
|
|
86
|
+
const adminMeta = GetMetadata(AdminController.prototype, ControllerMeta);
|
|
87
|
+
// adminMeta.middleware contains ["auth"] (inherited from BaseController)
|
|
88
|
+
|
|
89
|
+
adminMeta.middleware.push("adminOnly");
|
|
90
|
+
// adminMeta.middleware is now ["auth", "adminOnly"]
|
|
91
|
+
// baseMeta.middleware remains ["auth"]
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Without a custom `inherit` method, properties are shallow-copied from parent to child using `Object.getOwnPropertyNames`, but only for keys that do not already exist on the child metadata instance.
|
|
95
|
+
|
|
96
|
+
## Disable inheritance
|
|
97
|
+
|
|
98
|
+
Pass `false` as the third argument to prevent prototype chain traversal:
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
const meta = GetMetadata(target, RouteMetadata, false);
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Next steps
|
|
105
|
+
|
|
106
|
+
- [Decorators](./3.decorators.md) - Combine metadata with decorator factories
|
|
107
|
+
- [Modules](./5.modules.md) - Module lifecycle events and management
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# Modules
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The `@antelopejs/interface-core/modules` module provides lifecycle events and management functions for AntelopeJS modules. Modules transition through a defined lifecycle, and each transition emits an event that other modules can observe.
|
|
6
|
+
|
|
7
|
+
## Import
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import {
|
|
11
|
+
Events,
|
|
12
|
+
ListModules,
|
|
13
|
+
GetModuleInfo,
|
|
14
|
+
LoadModule,
|
|
15
|
+
StartModule,
|
|
16
|
+
StopModule,
|
|
17
|
+
DestroyModule,
|
|
18
|
+
ReloadModule,
|
|
19
|
+
} from "@antelopejs/interface-core/modules";
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Module lifecycle
|
|
23
|
+
|
|
24
|
+
A module moves through these states:
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
loaded -> constructed -> active -> constructed -> loaded
|
|
28
|
+
(stopped) (destroyed)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
| State | Description |
|
|
32
|
+
| ------------- | ------------------------------------------------------------ |
|
|
33
|
+
| `loaded` | Module code is loaded but no instance exists |
|
|
34
|
+
| `constructed` | Module instance is created but not started |
|
|
35
|
+
| `active` | Module is fully started and providing services |
|
|
36
|
+
| `unknown` | Module status cannot be determined |
|
|
37
|
+
|
|
38
|
+
## Lifecycle events
|
|
39
|
+
|
|
40
|
+
The `Events` namespace exposes four `EventProxy` instances that fire during module lifecycle transitions.
|
|
41
|
+
|
|
42
|
+
### `Events.ModuleConstructed`
|
|
43
|
+
|
|
44
|
+
Fires after a module instance is created, before the module is started.
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
import { Events } from "@antelopejs/interface-core/modules";
|
|
48
|
+
|
|
49
|
+
Events.ModuleConstructed.register((moduleId: string) => {
|
|
50
|
+
console.log(`Module constructed: ${moduleId}`);
|
|
51
|
+
});
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### `Events.ModuleStarted`
|
|
55
|
+
|
|
56
|
+
Fires after a module has been started and is fully operational.
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
Events.ModuleStarted.register((moduleId: string) => {
|
|
60
|
+
console.log(`Module started: ${moduleId}`);
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### `Events.ModuleStopped`
|
|
65
|
+
|
|
66
|
+
Fires after a module has been stopped. The module instance still exists but is no longer active.
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
Events.ModuleStopped.register((moduleId: string) => {
|
|
70
|
+
console.log(`Module stopped: ${moduleId}`);
|
|
71
|
+
});
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### `Events.ModuleDestroyed`
|
|
75
|
+
|
|
76
|
+
Fires after a module instance has been destroyed and all its resources have been released. The system uses this event internally to clean up proxy attachments and event handlers associated with the destroyed module.
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
Events.ModuleDestroyed.register((moduleId: string) => {
|
|
80
|
+
console.log(`Module destroyed: ${moduleId}`);
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Management functions
|
|
85
|
+
|
|
86
|
+
These functions are declared as `InterfaceFunction` proxies. They are available once the core runtime provides their implementation.
|
|
87
|
+
|
|
88
|
+
### `ListModules`
|
|
89
|
+
|
|
90
|
+
Returns the identifiers of all loaded modules.
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
const modules = await ListModules();
|
|
94
|
+
// ["auth-module", "database-module", "api-module"]
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### `GetModuleInfo`
|
|
98
|
+
|
|
99
|
+
Returns detailed information about a specific module, including its configuration, status, and file system path.
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
import type { ModuleInfo } from "@antelopejs/interface-core/modules";
|
|
103
|
+
|
|
104
|
+
const info: ModuleInfo = await GetModuleInfo("auth-module");
|
|
105
|
+
// info.status -> "active"
|
|
106
|
+
// info.localPath -> "/path/to/auth-module"
|
|
107
|
+
// info.source -> { type: "package", ... }
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### `LoadModule`
|
|
111
|
+
|
|
112
|
+
Loads a new module with the given configuration. Set `autostart` to `true` to automatically start the module after loading.
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
import type { ModuleDefinition } from "@antelopejs/interface-core/modules";
|
|
116
|
+
|
|
117
|
+
const definition: ModuleDefinition = {
|
|
118
|
+
source: { type: "package", package: "@my/module", version: "1.0.0" },
|
|
119
|
+
config: { key: "value" },
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
await LoadModule("my-module", definition, true);
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### `StartModule`
|
|
126
|
+
|
|
127
|
+
Starts a loaded but inactive module.
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
await StartModule("my-module");
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### `StopModule`
|
|
134
|
+
|
|
135
|
+
Stops an active module. The module instance remains but stops providing services.
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
await StopModule("my-module");
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### `DestroyModule`
|
|
142
|
+
|
|
143
|
+
Destroys a stopped module instance. The module code remains loaded.
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
await DestroyModule("my-module");
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### `ReloadModule`
|
|
150
|
+
|
|
151
|
+
Stops, destroys, unloads, and reloads a module from its source. This is useful for applying updates without restarting the application.
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
await ReloadModule("my-module");
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## `ModuleDefinition`
|
|
158
|
+
|
|
159
|
+
The configuration object for defining a module.
|
|
160
|
+
|
|
161
|
+
| Property | Type | Description |
|
|
162
|
+
| ------------------ | --------------------------------- | -------------------------------------------------- |
|
|
163
|
+
| `source` | `{ type: string } & Record<...>` | Source location and loading mechanism |
|
|
164
|
+
| `config` | `unknown` | Optional configuration data for the module |
|
|
165
|
+
| `importOverrides` | `Record<string, string[]>` | Optional mapping of import paths to alternatives |
|
|
166
|
+
| `disabledExports` | `string[]` | Optional list of exports to hide from this module |
|
|
167
|
+
|
|
168
|
+
## `ModuleInfo`
|
|
169
|
+
|
|
170
|
+
Extends `ModuleDefinition` with runtime information.
|
|
171
|
+
|
|
172
|
+
| Property | Type | Description |
|
|
173
|
+
| ----------- | -------- | ---------------------------------------- |
|
|
174
|
+
| `status` | `string` | Current lifecycle state of the module |
|
|
175
|
+
| `localPath` | `string` | File system path where the module exists |
|
|
176
|
+
|
|
177
|
+
## Next steps
|
|
178
|
+
|
|
179
|
+
- [Logging](./6.logging.md) - Structured logging with channels and levels
|
|
180
|
+
- [Configuration](./7.configuration.md) - Project configuration types
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# Logging
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The `@antelopejs/interface-core/logging` module provides a structured logging system with multiple severity levels and named channels. Log entries are emitted as events through an `EventProxy`, allowing any part of the application to listen for and process log output.
|
|
6
|
+
|
|
7
|
+
## Import
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { Logging } from "@antelopejs/interface-core/logging";
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Severity levels
|
|
14
|
+
|
|
15
|
+
The `Logging.Level` enum defines the available severity levels:
|
|
16
|
+
|
|
17
|
+
| Level | Value | Purpose |
|
|
18
|
+
| ----------- | ----- | -------------------------------------------- |
|
|
19
|
+
| `ERROR` | 40 | Critical errors that may cause failure |
|
|
20
|
+
| `WARN` | 30 | Issues that do not prevent operation |
|
|
21
|
+
| `INFO` | 20 | General status updates and information |
|
|
22
|
+
| `DEBUG` | 10 | Detailed information for debugging |
|
|
23
|
+
| `TRACE` | 0 | Highly detailed tracing information |
|
|
24
|
+
| `NO_PREFIX` | -1 | Messages displayed without a level prefix |
|
|
25
|
+
|
|
26
|
+
## Log to the main channel
|
|
27
|
+
|
|
28
|
+
The `Logging` namespace exposes convenience functions that write to the `"main"` channel:
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
import { Logging } from "@antelopejs/interface-core/logging";
|
|
32
|
+
|
|
33
|
+
Logging.Error("Database connection failed", error);
|
|
34
|
+
Logging.Warn("Cache miss for key:", cacheKey);
|
|
35
|
+
Logging.Info("Server started on port", port);
|
|
36
|
+
Logging.Debug("Request payload:", payload);
|
|
37
|
+
Logging.Trace("Entering function processItem");
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Each function accepts any number of arguments of any type.
|
|
41
|
+
|
|
42
|
+
## Use named channels
|
|
43
|
+
|
|
44
|
+
For categorized logging, create a `Logging.Channel` instance with a channel name:
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
import { Logging } from "@antelopejs/interface-core/logging";
|
|
48
|
+
|
|
49
|
+
const dbLog = new Logging.Channel("database");
|
|
50
|
+
const httpLog = new Logging.Channel("http");
|
|
51
|
+
|
|
52
|
+
dbLog.Info("Connected to", dbHost);
|
|
53
|
+
dbLog.Error("Query failed:", query, error);
|
|
54
|
+
|
|
55
|
+
httpLog.Info("GET /api/users", statusCode);
|
|
56
|
+
httpLog.Debug("Response headers:", headers);
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Channels provide the same methods as the main logging functions: `Error`, `Warn`, `Info`, `Debug`, and `Trace`.
|
|
60
|
+
|
|
61
|
+
## Write at a custom level
|
|
62
|
+
|
|
63
|
+
Use the `Write` function for logs at a custom severity level:
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
// Static function on the Logging namespace
|
|
67
|
+
Logging.Write(25, "custom-channel", "Custom level message");
|
|
68
|
+
|
|
69
|
+
// Instance method on a channel
|
|
70
|
+
const channel = new Logging.Channel("metrics");
|
|
71
|
+
channel.Write(15, "Custom level within the metrics channel");
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Log entry structure
|
|
75
|
+
|
|
76
|
+
Each log entry emitted through the event system has the following structure:
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
interface Log {
|
|
80
|
+
time: number; // Timestamp in milliseconds since epoch
|
|
81
|
+
channel: string; // Channel name (e.g., "main", "database")
|
|
82
|
+
levelId: number; // Numeric severity level
|
|
83
|
+
args: any[]; // The logged values
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Listen for log events
|
|
88
|
+
|
|
89
|
+
The logging system uses an `EventProxy` as its transport. Import the listener to register custom log handlers:
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
import eventLog from "@antelopejs/interface-core/logging/listener";
|
|
93
|
+
|
|
94
|
+
eventLog.register((log) => {
|
|
95
|
+
const date = new Date(log.time).toISOString();
|
|
96
|
+
const level = log.levelId >= 40 ? "ERROR" : log.levelId >= 30 ? "WARN" : "INFO";
|
|
97
|
+
console.log(`[${date}] [${level}] [${log.channel}]`, ...log.args);
|
|
98
|
+
});
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The listener is module-aware. Handlers registered by a module are automatically removed when that module is unloaded.
|
|
102
|
+
|
|
103
|
+
## Next steps
|
|
104
|
+
|
|
105
|
+
- [Configuration](./7.configuration.md) - Project configuration with logging settings
|
|
106
|
+
- [Proxies](./2.proxies.md) - Understand the `EventProxy` that powers the logging transport
|