@lakutata/core 3.1.0 → 3.1.4
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 +1 -0
- package/README.zh-CN.md +1 -0
- package/dist/cjs/decorators/dto/Expect.d.ts +2 -1
- package/dist/cjs/decorators/dto/Expect.js +2 -1
- package/dist/cjs/exports/Core.d.ts +1 -0
- package/dist/cjs/exports/Core.js +1 -0
- package/dist/cjs/interfaces/IInterfaceListening.d.ts +159 -0
- package/dist/cjs/interfaces/IInterfaceListening.js +2 -0
- package/dist/cjs/lib/base/internal/ConfigurableRecordsInjection.d.ts +7 -7
- package/dist/cjs/lib/base/internal/ConfigurableRecordsInjection.js +10 -14
- package/dist/cjs/lib/core/Container.js +3 -2
- package/dist/cjs/lib/dto/DTO.d.ts +3 -1
- package/dist/cjs/lib/dto/DTO.js +70 -4
- package/dist/esm/decorators/dto/Expect.js +2 -1
- package/dist/esm/exports/Core.js +1 -0
- package/dist/esm/interfaces/IInterfaceListening.js +1 -0
- package/dist/esm/lib/base/internal/ConfigurableRecordsInjection.js +10 -14
- package/dist/esm/lib/core/Container.js +3 -2
- package/dist/esm/lib/dto/DTO.js +70 -4
- package/dist/types/decorators/dto/Expect.d.ts +2 -1
- package/dist/types/exports/Core.d.ts +1 -0
- package/dist/types/interfaces/IInterfaceListening.d.ts +159 -0
- package/dist/types/lib/base/internal/ConfigurableRecordsInjection.d.ts +7 -7
- package/dist/types/lib/dto/DTO.d.ts +3 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -169,6 +169,7 @@ await container.destroy()
|
|
|
169
169
|
| `Before`, `After` | `lakutata/decorator/asst` | Functions run before and after a method |
|
|
170
170
|
| `PaginationSearchDTO`, `PaginationResultDTO`, `paginator`, `FlexibleDTO`, `toJsonSchema`, `fromJsonSchema` | `lakutata/dtos` | Pagination, open DTOs and JSON Schema conversion |
|
|
171
171
|
| `ConsoleLogger`, `ILogger` | `@lakutata/core/com/logger` | The logger interface and its console implementation |
|
|
172
|
+
| `IInterfaceListening`, `IInterfaceListener`, `IInterfaceListenOptions`, `IListeningAddress`, `NetworkInterfaceSelector` | `lakutata` | The contract of the listening on network interfaces, which the entrypoints use for their `interface` option and `@lakutata/netif` implements (types only) |
|
|
172
173
|
|
|
173
174
|
The typings document each declaration with examples.
|
|
174
175
|
|
package/README.zh-CN.md
CHANGED
|
@@ -158,6 +158,7 @@ await container.destroy()
|
|
|
158
158
|
| `Before`、`After` | `lakutata/decorator/asst` | 在方法之前和之后执行的函数 |
|
|
159
159
|
| `PaginationSearchDTO`、`PaginationResultDTO`、`paginator`、`FlexibleDTO`、`toJsonSchema`、`fromJsonSchema` | `lakutata/dtos` | 分页、接受任意字段的 DTO、JSON Schema 转换 |
|
|
160
160
|
| `ConsoleLogger`、`ILogger` | `@lakutata/core/com/logger` | 日志记录器接口及其控制台实现 |
|
|
161
|
+
| `IInterfaceListening`、`IInterfaceListener`、`IInterfaceListenOptions`、`IListeningAddress`、`NetworkInterfaceSelector` | `lakutata` | 按网口监听的接口:入口的 `interface` 选项通过它监听,`@lakutata/netif` 实现了它(只有类型) |
|
|
161
162
|
|
|
162
163
|
类型声明中的每一项都附有说明和示例。
|
|
163
164
|
|
|
@@ -5,7 +5,8 @@ import { Schema } from '../../lib/validation/types/Schema.js';
|
|
|
5
5
|
* Declare the schema of a property of a DTO class. The DTO validates the property against it when it is constructed
|
|
6
6
|
* (the whole object at once: defaults applied, the keys without schema removed unless the class has an
|
|
7
7
|
* `@IndexSignature`), and each time the property, or a value nested in it, is changed afterwards (the change is undone
|
|
8
|
-
* when invalid).
|
|
8
|
+
* when invalid). With `DTO.Any()`, an object of another class the property holds is given as it is, not watched: no
|
|
9
|
+
* change of it can be invalid. The schema is also part of the class schema (`MyDTO.Schema()`) used by `@Accept`, `@Return` and the
|
|
9
10
|
* actions' input validation. Subclasses inherit the property schemas, and may declare a property again to replace its
|
|
10
11
|
* schema. Ignored on a symbol property or on a class which is not a DTO.
|
|
11
12
|
* @param schema The schema of the property, built with the static methods of `DTO` (`DTO.String().required()`); a
|
|
@@ -6,7 +6,8 @@ const ObjectSchemaValidation_js_1 = require("../../lib/dto/ObjectSchemaValidatio
|
|
|
6
6
|
* Declare the schema of a property of a DTO class. The DTO validates the property against it when it is constructed
|
|
7
7
|
* (the whole object at once: defaults applied, the keys without schema removed unless the class has an
|
|
8
8
|
* `@IndexSignature`), and each time the property, or a value nested in it, is changed afterwards (the change is undone
|
|
9
|
-
* when invalid).
|
|
9
|
+
* when invalid). With `DTO.Any()`, an object of another class the property holds is given as it is, not watched: no
|
|
10
|
+
* change of it can be invalid. The schema is also part of the class schema (`MyDTO.Schema()`) used by `@Accept`, `@Return` and the
|
|
10
11
|
* actions' input validation. Subclasses inherit the property schemas, and may declare a property again to replace its
|
|
11
12
|
* schema. Ignored on a symbol property or on a class which is not a DTO.
|
|
12
13
|
* @param schema The schema of the property, built with the static methods of `DTO` (`DTO.String().required()`); a
|
package/dist/cjs/exports/Core.js
CHANGED
|
@@ -121,6 +121,7 @@ __exportStar(require("../types/ModuleOptions.js"), exports);
|
|
|
121
121
|
*/
|
|
122
122
|
__exportStar(require("../interfaces/IBaseObjectConstructor.js"), exports);
|
|
123
123
|
__exportStar(require("../interfaces/ILogger.js"), exports);
|
|
124
|
+
__exportStar(require("../interfaces/IInterfaceListening.js"), exports);
|
|
124
125
|
__exportStar(require("../interfaces/IConstructor.js"), exports);
|
|
125
126
|
|
|
126
127
|
//The default of the entry: the entry itself (scripts/package-build/cjs-package.mjs)
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import type { Server } from 'node:net';
|
|
2
|
+
/**
|
|
3
|
+
* A network interface, as an implementation of {@link IInterfaceListening} takes it: its name (`'eth1'`; on Windows the
|
|
4
|
+
* name of the network connection), its hardware address (`{mac: '52:54:00:12:34:56'}`) or its index (`{index: 3}`).
|
|
5
|
+
*/
|
|
6
|
+
export type NetworkInterfaceSelector = string | {
|
|
7
|
+
/**
|
|
8
|
+
* The hardware address of the interface.
|
|
9
|
+
*/
|
|
10
|
+
mac: string;
|
|
11
|
+
} | {
|
|
12
|
+
/**
|
|
13
|
+
* The index of the interface.
|
|
14
|
+
*/
|
|
15
|
+
index: number;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* An address a listener of a network interface can be reached at.
|
|
19
|
+
*/
|
|
20
|
+
export interface IListeningAddress {
|
|
21
|
+
/**
|
|
22
|
+
* The address (an IPv6 address without its scope).
|
|
23
|
+
*/
|
|
24
|
+
address: string;
|
|
25
|
+
/**
|
|
26
|
+
* `'IPv4'` or `'IPv6'`.
|
|
27
|
+
*/
|
|
28
|
+
family: 'IPv4' | 'IPv6';
|
|
29
|
+
/**
|
|
30
|
+
* The port.
|
|
31
|
+
*/
|
|
32
|
+
port: number;
|
|
33
|
+
/**
|
|
34
|
+
* IPv6 only: the scope of the address (the index of the interface for a link-local one), 0 for a global one.
|
|
35
|
+
*/
|
|
36
|
+
scopeid?: number;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The options of {@link IInterfaceListening.listenOnAll}.
|
|
40
|
+
*/
|
|
41
|
+
export interface IInterfaceListenOptions {
|
|
42
|
+
/**
|
|
43
|
+
* The port; 0 lets the system choose one (for one interface only).
|
|
44
|
+
*/
|
|
45
|
+
port: number;
|
|
46
|
+
/**
|
|
47
|
+
* The families listened on.
|
|
48
|
+
* @default 'both'
|
|
49
|
+
*/
|
|
50
|
+
family?: 'IPv4' | 'IPv6' | 'both';
|
|
51
|
+
/**
|
|
52
|
+
* Refuse to listen where the connections reaching the addresses of the interface through another interface cannot
|
|
53
|
+
* be refused, and stop listening while they cannot. An implementation that never refuses them throws.
|
|
54
|
+
* @default false
|
|
55
|
+
*/
|
|
56
|
+
strict?: boolean;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The listener of a network interface for a server: it accepts the connections of the interface and gives them to the
|
|
60
|
+
* server, whatever the addresses of the interface, again when they change and when the interface is unplugged and
|
|
61
|
+
* plugged back. The server itself does not listen. The `InterfaceListener` of `@lakutata/netif` implements it.
|
|
62
|
+
*/
|
|
63
|
+
export interface IInterfaceListener {
|
|
64
|
+
/**
|
|
65
|
+
* The interface listened on: its name (`undefined` while it does not exist), and whether it is the loopback one.
|
|
66
|
+
*/
|
|
67
|
+
readonly networkInterface: {
|
|
68
|
+
readonly name: string | undefined;
|
|
69
|
+
readonly loopback: boolean;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* The port, `undefined` until a port 0 is given one by the system.
|
|
73
|
+
*/
|
|
74
|
+
readonly port: number | undefined;
|
|
75
|
+
/**
|
|
76
|
+
* The addresses it can be reached at now: none while the interface does not exist or has no address.
|
|
77
|
+
*/
|
|
78
|
+
readonly addresses: IListeningAddress[];
|
|
79
|
+
/**
|
|
80
|
+
* Whether the interface is listened on now.
|
|
81
|
+
*/
|
|
82
|
+
readonly listening: boolean;
|
|
83
|
+
/**
|
|
84
|
+
* Whether the system refuses the connections that reach the addresses of the interface through another interface.
|
|
85
|
+
*/
|
|
86
|
+
readonly enforced: boolean;
|
|
87
|
+
/**
|
|
88
|
+
* Why `enforced` is `false`, when it is.
|
|
89
|
+
*/
|
|
90
|
+
readonly reason: string | undefined;
|
|
91
|
+
/**
|
|
92
|
+
* Whether it was closed.
|
|
93
|
+
*/
|
|
94
|
+
readonly closed: boolean;
|
|
95
|
+
/**
|
|
96
|
+
* Stop listening; the connections established are left to the server.
|
|
97
|
+
*/
|
|
98
|
+
close(): Promise<void>;
|
|
99
|
+
/**
|
|
100
|
+
* The interface is listened on, again after a change.
|
|
101
|
+
* @param event `'listening'`.
|
|
102
|
+
* @param listener Called without argument.
|
|
103
|
+
*/
|
|
104
|
+
on(event: 'listening', listener: () => void): this;
|
|
105
|
+
/**
|
|
106
|
+
* A failure of listening again, retried by the listener; with `strict`, the guarantee lost.
|
|
107
|
+
* @param event `'error'`.
|
|
108
|
+
* @param listener Called with the error.
|
|
109
|
+
*/
|
|
110
|
+
on(event: 'error', listener: (error: Error) => void): this;
|
|
111
|
+
/**
|
|
112
|
+
* `enforced` changed.
|
|
113
|
+
* @param event `'enforced'`.
|
|
114
|
+
* @param listener Called with its new value.
|
|
115
|
+
*/
|
|
116
|
+
on(event: 'enforced', listener: (enforced: boolean) => void): this;
|
|
117
|
+
/**
|
|
118
|
+
* The listener was closed.
|
|
119
|
+
* @param event `'close'`.
|
|
120
|
+
* @param listener Called without argument.
|
|
121
|
+
*/
|
|
122
|
+
on(event: 'close', listener: () => void): this;
|
|
123
|
+
/**
|
|
124
|
+
* Remove a listener of an event.
|
|
125
|
+
* @param event The event.
|
|
126
|
+
* @param listener The listener given to `on()`.
|
|
127
|
+
*/
|
|
128
|
+
off(event: 'listening' | 'error' | 'enforced' | 'close', listener: (...args: any[]) => void): this;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Listening on network interfaces instead of addresses: what the entrypoints use for their `interface` option. The
|
|
132
|
+
* package `@lakutata/netif` implements it, and is the one used by default; another implementation is given in the
|
|
133
|
+
* `interfaceListening` option of the entrypoints.
|
|
134
|
+
* @example
|
|
135
|
+
* ```typescript
|
|
136
|
+
* import type {IInterfaceListener, IInterfaceListening} from 'lakutata'
|
|
137
|
+
* import {listenOnAll} from '@lakutata/netif'
|
|
138
|
+
*
|
|
139
|
+
* //An implementation that writes each listener made before giving it to the entrypoint
|
|
140
|
+
* const logged: IInterfaceListening = {
|
|
141
|
+
* listenOnAll: async (selectors, server, options): Promise<IInterfaceListener[]> => {
|
|
142
|
+
* const listeners: IInterfaceListener[] = await listenOnAll(selectors, server, options)
|
|
143
|
+
* for (const listener of listeners) console.log(listener.networkInterface.name, listener.addresses)
|
|
144
|
+
* return listeners
|
|
145
|
+
* }
|
|
146
|
+
* }
|
|
147
|
+
* ```
|
|
148
|
+
*/
|
|
149
|
+
export interface IInterfaceListening {
|
|
150
|
+
/**
|
|
151
|
+
* Listen on interfaces for a server, one listener by interface; when one cannot be listened on, the others are
|
|
152
|
+
* closed and the error is thrown. An interface that does not exist yet is listened on once it appears.
|
|
153
|
+
* @param selectors The interfaces; several need a port other than 0.
|
|
154
|
+
* @param server The server the connections are given to.
|
|
155
|
+
* @param options The port, the families, and whether the other interfaces must be refused.
|
|
156
|
+
* @returns The listeners, in the order of the interfaces.
|
|
157
|
+
*/
|
|
158
|
+
listenOnAll(selectors: NetworkInterfaceSelector | NetworkInterfaceSelector[], server: Server, options: IInterfaceListenOptions): Promise<IInterfaceListener[]>;
|
|
159
|
+
}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { BaseObject } from '../BaseObject.js';
|
|
2
|
+
import { type Resolver } from '../../ioc/Resolvers.js';
|
|
2
3
|
/**
|
|
3
|
-
* Set configurable records to
|
|
4
|
-
* @param
|
|
5
|
-
* @param registrationName
|
|
4
|
+
* Set configurable records to a registration (the options it was declared with)
|
|
5
|
+
* @param registration
|
|
6
6
|
* @param configurableRecords
|
|
7
7
|
* @constructor
|
|
8
8
|
*/
|
|
9
|
-
export declare function setConfigurableRecords
|
|
9
|
+
export declare function setConfigurableRecords(registration: Resolver<any>, configurableRecords: Record<string, any>): void;
|
|
10
10
|
/**
|
|
11
|
-
* Get configurable records from
|
|
12
|
-
* @param
|
|
11
|
+
* Get configurable records from a registration
|
|
12
|
+
* @param registration
|
|
13
13
|
* @constructor
|
|
14
14
|
*/
|
|
15
|
-
export declare function getConfigurableRecords
|
|
15
|
+
export declare function getConfigurableRecords(registration: Resolver<any> | null): Record<string, any>;
|
|
16
16
|
/**
|
|
17
17
|
* Set id to instance
|
|
18
18
|
* @param target
|
|
@@ -10,28 +10,24 @@ exports.getConfigurableRecordsFromInstance = getConfigurableRecordsFromInstance;
|
|
|
10
10
|
const DIMetadataKey_js_1 = require("../../../constants/DIMetadataKey.js");
|
|
11
11
|
const ConstructorSymbol_js_1 = require("../../ioc/ConstructorSymbol.js");
|
|
12
12
|
const As_1 = require("@lakutata/utils/As");
|
|
13
|
+
//The configurable records of the registrations, by resolver: each container keeps the options of its own registrations
|
|
14
|
+
const registrationRecords = new WeakMap();
|
|
13
15
|
/**
|
|
14
|
-
* Set configurable records to
|
|
15
|
-
* @param
|
|
16
|
-
* @param registrationName
|
|
16
|
+
* Set configurable records to a registration (the options it was declared with)
|
|
17
|
+
* @param registration
|
|
17
18
|
* @param configurableRecords
|
|
18
19
|
* @constructor
|
|
19
20
|
*/
|
|
20
|
-
function setConfigurableRecords(
|
|
21
|
-
|
|
22
|
-
Reflect.deleteMetadata(registrationName, target);
|
|
23
|
-
Reflect.defineMetadata(registrationName, configurableRecords, target);
|
|
21
|
+
function setConfigurableRecords(registration, configurableRecords) {
|
|
22
|
+
registrationRecords.set(registration, configurableRecords);
|
|
24
23
|
}
|
|
25
24
|
/**
|
|
26
|
-
* Get configurable records from
|
|
27
|
-
* @param
|
|
25
|
+
* Get configurable records from a registration
|
|
26
|
+
* @param registration
|
|
28
27
|
* @constructor
|
|
29
28
|
*/
|
|
30
|
-
function getConfigurableRecords(
|
|
31
|
-
|
|
32
|
-
if (configurableRecords)
|
|
33
|
-
return configurableRecords;
|
|
34
|
-
return {};
|
|
29
|
+
function getConfigurableRecords(registration) {
|
|
30
|
+
return (registration && registrationRecords.get(registration)) ?? {};
|
|
35
31
|
}
|
|
36
32
|
/**
|
|
37
33
|
* Set id to instance
|
|
@@ -305,7 +305,8 @@ class Container {
|
|
|
305
305
|
(0, ThrowWarning_js_1.throwWarning)(`The configuration passed for the already created object "${(0, As_1.As)(resolved).className}" is ignored. Use a scoped or transient object to get an instance with its own configuration.`);
|
|
306
306
|
}
|
|
307
307
|
if (isNewSubBaseObject) {
|
|
308
|
-
|
|
308
|
+
//The options of the registration in effect here (a child container's registration shadows its parent's)
|
|
309
|
+
const presetConfigurableRecords = (0, ConfigurableRecordsInjection_js_1.getConfigurableRecords)(this.#dic.getRegistration(registrationName));
|
|
309
310
|
//set id into object instance
|
|
310
311
|
(0, ConfigurableRecordsInjection_js_1.setIdToInstance)((0, As_1.As)(resolved), registrationName);
|
|
311
312
|
//set configurable records into object instance
|
|
@@ -326,8 +327,8 @@ class Container {
|
|
|
326
327
|
const configurableRecords = { ...options, class: void (0) };
|
|
327
328
|
delete configurableRecords.id;
|
|
328
329
|
delete configurableRecords.class;
|
|
329
|
-
(0, ConfigurableRecordsInjection_js_1.setConfigurableRecords)(options.class, id, configurableRecords);
|
|
330
330
|
pair[id] = this.#createResolver(options.class);
|
|
331
|
+
(0, ConfigurableRecordsInjection_js_1.setConfigurableRecords)(pair[id], configurableRecords);
|
|
331
332
|
return pair;
|
|
332
333
|
}
|
|
333
334
|
/**
|
|
@@ -45,7 +45,9 @@ export declare class DTO extends DataValidator {
|
|
|
45
45
|
* Create a DTO from its data, validated against the class schema: the defaults applied, the keys without schema
|
|
46
46
|
* removed (unless the class has an `@IndexSignature`). The instance then validates each change of a property, or
|
|
47
47
|
* of a value nested in it (an array, an object): an invalid change throws an `InvalidValueException` and is
|
|
48
|
-
* undone.
|
|
48
|
+
* undone. A property accepting any value (`DTO.Any()`, or an index signature `DTO.Any()`) gives the objects of
|
|
49
|
+
* other classes it holds as they are, since no change of theirs can be invalid: their getters, their private fields
|
|
50
|
+
* and their identity are those of the object itself.
|
|
49
51
|
* @param props The data of the DTO. Default: no data (`{}`).
|
|
50
52
|
* @throws {InvalidValueException} When the data does not match the class schema.
|
|
51
53
|
*/
|
package/dist/cjs/lib/dto/DTO.js
CHANGED
|
@@ -94,6 +94,55 @@ function getPropertySchema(instance, propertyKey) {
|
|
|
94
94
|
schemas.set(propertyKey, schema);
|
|
95
95
|
return schema;
|
|
96
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Whether the properties of a DTO accept any value, per DTO class
|
|
99
|
+
*/
|
|
100
|
+
const anyValuePropertyCache = new WeakMap();
|
|
101
|
+
/**
|
|
102
|
+
* Whether a schema accepts any value: an any schema without rule, value list, condition or external validation, so no
|
|
103
|
+
* change of a value it holds can fail validation
|
|
104
|
+
* @param schema
|
|
105
|
+
*/
|
|
106
|
+
function acceptsAnything(schema) {
|
|
107
|
+
if (!schema || schema.type !== 'any' || schema._rules.length || schema._valids || schema._invalids)
|
|
108
|
+
return false;
|
|
109
|
+
const terms = schema.$_terms;
|
|
110
|
+
return !['whens', 'externals'].some((term) => Array.isArray(terms[term]) && terms[term].length > 0);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Whether a property of a DTO accepts any value: declared with `DTO.Any()`, or undeclared and matched by an index
|
|
114
|
+
* signature `DTO.Any()` (the transport objects of a context)
|
|
115
|
+
* @param instance
|
|
116
|
+
* @param propertyKey
|
|
117
|
+
*/
|
|
118
|
+
function acceptsAnyValue(instance, propertyKey) {
|
|
119
|
+
if (typeof propertyKey !== 'string')
|
|
120
|
+
return false;
|
|
121
|
+
const properties = (0, ObjectSchemaValidation_js_1.getCachedDTOSchema)(anyValuePropertyCache, (0, ObjectConstructor_1.objectConstructor)(instance), () => new Map());
|
|
122
|
+
let accepts = properties.get(propertyKey);
|
|
123
|
+
if (accepts !== undefined)
|
|
124
|
+
return accepts;
|
|
125
|
+
const objectSchema = (0, As_1.As)(getObjectSchema(instance));
|
|
126
|
+
const child = (objectSchema.$_terms.keys || []).find(({ key }) => key === propertyKey);
|
|
127
|
+
//An undeclared property: the first pattern matching its key (the index signature)
|
|
128
|
+
const pattern = child ? undefined : (objectSchema.$_terms.patterns || []).find((each) => each.regex
|
|
129
|
+
? each.regex.test(propertyKey)
|
|
130
|
+
: !each.schema.validate(propertyKey).error);
|
|
131
|
+
accepts = acceptsAnything(child ? child.schema : pattern?.rule);
|
|
132
|
+
properties.set(propertyKey, accepts);
|
|
133
|
+
return accepts;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Whether an object is plain data: an array, an object literal, or an object without prototype (an instance of a
|
|
137
|
+
* subclass of Array or Object, and the objects of another realm, count as objects of other classes)
|
|
138
|
+
* @param value
|
|
139
|
+
*/
|
|
140
|
+
function isPlainData(value) {
|
|
141
|
+
const constructor = value.constructor;
|
|
142
|
+
if (constructor === Object || constructor === Array)
|
|
143
|
+
return true;
|
|
144
|
+
return constructor === undefined && Object.getPrototypeOf(value) === null;
|
|
145
|
+
}
|
|
97
146
|
/**
|
|
98
147
|
* Validate property value (only the property when the properties are validated independently)
|
|
99
148
|
* @param instance
|
|
@@ -160,8 +209,10 @@ function propertyState(target, prop) {
|
|
|
160
209
|
* @param prop
|
|
161
210
|
* @param receiver
|
|
162
211
|
* @param validateFn
|
|
212
|
+
* @param acceptsAny Whether a property of the DTO holding the value accepts any value
|
|
213
|
+
* @param ownerKey The property of the DTO holding the value
|
|
163
214
|
*/
|
|
164
|
-
function dynamicProxyProperty(target, prop, receiver, validateFn) {
|
|
215
|
+
function dynamicProxyProperty(target, prop, receiver, validateFn, acceptsAny, ownerKey) {
|
|
165
216
|
const propertyValue = Reflect.get(target, prop, receiver);
|
|
166
217
|
if (!propertyValue)
|
|
167
218
|
return propertyValue;
|
|
@@ -190,6 +241,11 @@ function dynamicProxyProperty(target, prop, receiver, validateFn) {
|
|
|
190
241
|
apply: (method, _thisArg, args) => Reflect.apply(method, target, args)
|
|
191
242
|
});
|
|
192
243
|
}
|
|
244
|
+
//An object of another class held by a property accepting any value is given as it is: no change of it can be
|
|
245
|
+
//refused, and a proxy would break the getters reading its private fields, the internal slots of the built-ins (the
|
|
246
|
+
//size of a Map) and its identity
|
|
247
|
+
if (acceptsAny?.(ownerKey) && !isPlainData(propertyValue))
|
|
248
|
+
return propertyValue;
|
|
193
249
|
return new Proxy(propertyValue, {
|
|
194
250
|
set(target, p, value, receiver) {
|
|
195
251
|
const state = propertyState(target, p);
|
|
@@ -204,7 +260,7 @@ function dynamicProxyProperty(target, prop, receiver, validateFn) {
|
|
|
204
260
|
}
|
|
205
261
|
},
|
|
206
262
|
get(target, p, receiver) {
|
|
207
|
-
return dynamicProxyProperty(target, p, receiver, validateFn);
|
|
263
|
+
return dynamicProxyProperty(target, p, receiver, validateFn, acceptsAny, ownerKey);
|
|
208
264
|
},
|
|
209
265
|
deleteProperty: (target, prop) => {
|
|
210
266
|
const state = propertyState(target, prop);
|
|
@@ -262,12 +318,22 @@ let DTO = DTO_1 = class DTO extends DataValidator_js_1.DataValidator {
|
|
|
262
318
|
* Create a DTO from its data, validated against the class schema: the defaults applied, the keys without schema
|
|
263
319
|
* removed (unless the class has an `@IndexSignature`). The instance then validates each change of a property, or
|
|
264
320
|
* of a value nested in it (an array, an object): an invalid change throws an `InvalidValueException` and is
|
|
265
|
-
* undone.
|
|
321
|
+
* undone. A property accepting any value (`DTO.Any()`, or an index signature `DTO.Any()`) gives the objects of
|
|
322
|
+
* other classes it holds as they are, since no change of theirs can be invalid: their getters, their private fields
|
|
323
|
+
* and their identity are those of the object itself.
|
|
266
324
|
* @param props The data of the DTO. Default: no data (`{}`).
|
|
267
325
|
* @throws {InvalidValueException} When the data does not match the class schema.
|
|
268
326
|
*/
|
|
269
327
|
constructor(props = {}) {
|
|
270
328
|
super();
|
|
329
|
+
//Whether each property accepts any value, remembered by the instance once known
|
|
330
|
+
let accepting;
|
|
331
|
+
const acceptsAny = (key) => {
|
|
332
|
+
if (typeof key !== 'string')
|
|
333
|
+
return false;
|
|
334
|
+
accepting ??= Object.create(null);
|
|
335
|
+
return accepting[key] ??= acceptsAnyValue(this, key);
|
|
336
|
+
};
|
|
271
337
|
//Create DTO proxy object
|
|
272
338
|
const DTOInstanceProxy = new Proxy(this, {
|
|
273
339
|
set: (target, prop, value, receiver) => {
|
|
@@ -283,7 +349,7 @@ let DTO = DTO_1 = class DTO extends DataValidator_js_1.DataValidator {
|
|
|
283
349
|
else {
|
|
284
350
|
validatePropertyValue(this, p, Reflect.get(target, p));
|
|
285
351
|
}
|
|
286
|
-
}),
|
|
352
|
+
}, acceptsAny, p),
|
|
287
353
|
deleteProperty: (target, prop) => {
|
|
288
354
|
if (!(0, IsSymbol_1.isSymbol)(prop))
|
|
289
355
|
validatePropertyValue(this, prop, void (0));
|
|
@@ -3,7 +3,8 @@ import { setObjectPropertySchema } from '../../lib/dto/ObjectSchemaValidation.js
|
|
|
3
3
|
* Declare the schema of a property of a DTO class. The DTO validates the property against it when it is constructed
|
|
4
4
|
* (the whole object at once: defaults applied, the keys without schema removed unless the class has an
|
|
5
5
|
* `@IndexSignature`), and each time the property, or a value nested in it, is changed afterwards (the change is undone
|
|
6
|
-
* when invalid).
|
|
6
|
+
* when invalid). With `DTO.Any()`, an object of another class the property holds is given as it is, not watched: no
|
|
7
|
+
* change of it can be invalid. The schema is also part of the class schema (`MyDTO.Schema()`) used by `@Accept`, `@Return` and the
|
|
7
8
|
* actions' input validation. Subclasses inherit the property schemas, and may declare a property again to replace its
|
|
8
9
|
* schema. Ignored on a symbol property or on a class which is not a DTO.
|
|
9
10
|
* @param schema The schema of the property, built with the static methods of `DTO` (`DTO.String().required()`); a
|
package/dist/esm/exports/Core.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,28 +1,24 @@
|
|
|
1
1
|
import { DI_TARGET_ID } from '../../../constants/DIMetadataKey.js';
|
|
2
2
|
import { constructorSymbol } from '../../ioc/ConstructorSymbol.js';
|
|
3
3
|
import { As } from '@lakutata/utils/As';
|
|
4
|
+
//The configurable records of the registrations, by resolver: each container keeps the options of its own registrations
|
|
5
|
+
const registrationRecords = new WeakMap();
|
|
4
6
|
/**
|
|
5
|
-
* Set configurable records to
|
|
6
|
-
* @param
|
|
7
|
-
* @param registrationName
|
|
7
|
+
* Set configurable records to a registration (the options it was declared with)
|
|
8
|
+
* @param registration
|
|
8
9
|
* @param configurableRecords
|
|
9
10
|
* @constructor
|
|
10
11
|
*/
|
|
11
|
-
export function setConfigurableRecords(
|
|
12
|
-
|
|
13
|
-
Reflect.deleteMetadata(registrationName, target);
|
|
14
|
-
Reflect.defineMetadata(registrationName, configurableRecords, target);
|
|
12
|
+
export function setConfigurableRecords(registration, configurableRecords) {
|
|
13
|
+
registrationRecords.set(registration, configurableRecords);
|
|
15
14
|
}
|
|
16
15
|
/**
|
|
17
|
-
* Get configurable records from
|
|
18
|
-
* @param
|
|
16
|
+
* Get configurable records from a registration
|
|
17
|
+
* @param registration
|
|
19
18
|
* @constructor
|
|
20
19
|
*/
|
|
21
|
-
export function getConfigurableRecords(
|
|
22
|
-
|
|
23
|
-
if (configurableRecords)
|
|
24
|
-
return configurableRecords;
|
|
25
|
-
return {};
|
|
20
|
+
export function getConfigurableRecords(registration) {
|
|
21
|
+
return (registration && registrationRecords.get(registration)) ?? {};
|
|
26
22
|
}
|
|
27
23
|
/**
|
|
28
24
|
* Set id to instance
|
|
@@ -268,7 +268,8 @@ export class Container {
|
|
|
268
268
|
throwWarning(`The configuration passed for the already created object "${As(resolved).className}" is ignored. Use a scoped or transient object to get an instance with its own configuration.`);
|
|
269
269
|
}
|
|
270
270
|
if (isNewSubBaseObject) {
|
|
271
|
-
|
|
271
|
+
//The options of the registration in effect here (a child container's registration shadows its parent's)
|
|
272
|
+
const presetConfigurableRecords = getConfigurableRecords(this.#dic.getRegistration(registrationName));
|
|
272
273
|
//set id into object instance
|
|
273
274
|
setIdToInstance(As(resolved), registrationName);
|
|
274
275
|
//set configurable records into object instance
|
|
@@ -289,8 +290,8 @@ export class Container {
|
|
|
289
290
|
const configurableRecords = { ...options, class: void (0) };
|
|
290
291
|
delete configurableRecords.id;
|
|
291
292
|
delete configurableRecords.class;
|
|
292
|
-
setConfigurableRecords(options.class, id, configurableRecords);
|
|
293
293
|
pair[id] = this.#createResolver(options.class);
|
|
294
|
+
setConfigurableRecords(pair[id], configurableRecords);
|
|
294
295
|
return pair;
|
|
295
296
|
}
|
|
296
297
|
/**
|
package/dist/esm/lib/dto/DTO.js
CHANGED
|
@@ -91,6 +91,55 @@ function getPropertySchema(instance, propertyKey) {
|
|
|
91
91
|
schemas.set(propertyKey, schema);
|
|
92
92
|
return schema;
|
|
93
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* Whether the properties of a DTO accept any value, per DTO class
|
|
96
|
+
*/
|
|
97
|
+
const anyValuePropertyCache = new WeakMap();
|
|
98
|
+
/**
|
|
99
|
+
* Whether a schema accepts any value: an any schema without rule, value list, condition or external validation, so no
|
|
100
|
+
* change of a value it holds can fail validation
|
|
101
|
+
* @param schema
|
|
102
|
+
*/
|
|
103
|
+
function acceptsAnything(schema) {
|
|
104
|
+
if (!schema || schema.type !== 'any' || schema._rules.length || schema._valids || schema._invalids)
|
|
105
|
+
return false;
|
|
106
|
+
const terms = schema.$_terms;
|
|
107
|
+
return !['whens', 'externals'].some((term) => Array.isArray(terms[term]) && terms[term].length > 0);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Whether a property of a DTO accepts any value: declared with `DTO.Any()`, or undeclared and matched by an index
|
|
111
|
+
* signature `DTO.Any()` (the transport objects of a context)
|
|
112
|
+
* @param instance
|
|
113
|
+
* @param propertyKey
|
|
114
|
+
*/
|
|
115
|
+
function acceptsAnyValue(instance, propertyKey) {
|
|
116
|
+
if (typeof propertyKey !== 'string')
|
|
117
|
+
return false;
|
|
118
|
+
const properties = getCachedDTOSchema(anyValuePropertyCache, objectConstructor(instance), () => new Map());
|
|
119
|
+
let accepts = properties.get(propertyKey);
|
|
120
|
+
if (accepts !== undefined)
|
|
121
|
+
return accepts;
|
|
122
|
+
const objectSchema = As(getObjectSchema(instance));
|
|
123
|
+
const child = (objectSchema.$_terms.keys || []).find(({ key }) => key === propertyKey);
|
|
124
|
+
//An undeclared property: the first pattern matching its key (the index signature)
|
|
125
|
+
const pattern = child ? undefined : (objectSchema.$_terms.patterns || []).find((each) => each.regex
|
|
126
|
+
? each.regex.test(propertyKey)
|
|
127
|
+
: !each.schema.validate(propertyKey).error);
|
|
128
|
+
accepts = acceptsAnything(child ? child.schema : pattern?.rule);
|
|
129
|
+
properties.set(propertyKey, accepts);
|
|
130
|
+
return accepts;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Whether an object is plain data: an array, an object literal, or an object without prototype (an instance of a
|
|
134
|
+
* subclass of Array or Object, and the objects of another realm, count as objects of other classes)
|
|
135
|
+
* @param value
|
|
136
|
+
*/
|
|
137
|
+
function isPlainData(value) {
|
|
138
|
+
const constructor = value.constructor;
|
|
139
|
+
if (constructor === Object || constructor === Array)
|
|
140
|
+
return true;
|
|
141
|
+
return constructor === undefined && Object.getPrototypeOf(value) === null;
|
|
142
|
+
}
|
|
94
143
|
/**
|
|
95
144
|
* Validate property value (only the property when the properties are validated independently)
|
|
96
145
|
* @param instance
|
|
@@ -157,8 +206,10 @@ function propertyState(target, prop) {
|
|
|
157
206
|
* @param prop
|
|
158
207
|
* @param receiver
|
|
159
208
|
* @param validateFn
|
|
209
|
+
* @param acceptsAny Whether a property of the DTO holding the value accepts any value
|
|
210
|
+
* @param ownerKey The property of the DTO holding the value
|
|
160
211
|
*/
|
|
161
|
-
function dynamicProxyProperty(target, prop, receiver, validateFn) {
|
|
212
|
+
function dynamicProxyProperty(target, prop, receiver, validateFn, acceptsAny, ownerKey) {
|
|
162
213
|
const propertyValue = Reflect.get(target, prop, receiver);
|
|
163
214
|
if (!propertyValue)
|
|
164
215
|
return propertyValue;
|
|
@@ -187,6 +238,11 @@ function dynamicProxyProperty(target, prop, receiver, validateFn) {
|
|
|
187
238
|
apply: (method, _thisArg, args) => Reflect.apply(method, target, args)
|
|
188
239
|
});
|
|
189
240
|
}
|
|
241
|
+
//An object of another class held by a property accepting any value is given as it is: no change of it can be
|
|
242
|
+
//refused, and a proxy would break the getters reading its private fields, the internal slots of the built-ins (the
|
|
243
|
+
//size of a Map) and its identity
|
|
244
|
+
if (acceptsAny?.(ownerKey) && !isPlainData(propertyValue))
|
|
245
|
+
return propertyValue;
|
|
190
246
|
return new Proxy(propertyValue, {
|
|
191
247
|
set(target, p, value, receiver) {
|
|
192
248
|
const state = propertyState(target, p);
|
|
@@ -201,7 +257,7 @@ function dynamicProxyProperty(target, prop, receiver, validateFn) {
|
|
|
201
257
|
}
|
|
202
258
|
},
|
|
203
259
|
get(target, p, receiver) {
|
|
204
|
-
return dynamicProxyProperty(target, p, receiver, validateFn);
|
|
260
|
+
return dynamicProxyProperty(target, p, receiver, validateFn, acceptsAny, ownerKey);
|
|
205
261
|
},
|
|
206
262
|
deleteProperty: (target, prop) => {
|
|
207
263
|
const state = propertyState(target, prop);
|
|
@@ -259,12 +315,22 @@ let DTO = DTO_1 = class DTO extends DataValidator {
|
|
|
259
315
|
* Create a DTO from its data, validated against the class schema: the defaults applied, the keys without schema
|
|
260
316
|
* removed (unless the class has an `@IndexSignature`). The instance then validates each change of a property, or
|
|
261
317
|
* of a value nested in it (an array, an object): an invalid change throws an `InvalidValueException` and is
|
|
262
|
-
* undone.
|
|
318
|
+
* undone. A property accepting any value (`DTO.Any()`, or an index signature `DTO.Any()`) gives the objects of
|
|
319
|
+
* other classes it holds as they are, since no change of theirs can be invalid: their getters, their private fields
|
|
320
|
+
* and their identity are those of the object itself.
|
|
263
321
|
* @param props The data of the DTO. Default: no data (`{}`).
|
|
264
322
|
* @throws {InvalidValueException} When the data does not match the class schema.
|
|
265
323
|
*/
|
|
266
324
|
constructor(props = {}) {
|
|
267
325
|
super();
|
|
326
|
+
//Whether each property accepts any value, remembered by the instance once known
|
|
327
|
+
let accepting;
|
|
328
|
+
const acceptsAny = (key) => {
|
|
329
|
+
if (typeof key !== 'string')
|
|
330
|
+
return false;
|
|
331
|
+
accepting ??= Object.create(null);
|
|
332
|
+
return accepting[key] ??= acceptsAnyValue(this, key);
|
|
333
|
+
};
|
|
268
334
|
//Create DTO proxy object
|
|
269
335
|
const DTOInstanceProxy = new Proxy(this, {
|
|
270
336
|
set: (target, prop, value, receiver) => {
|
|
@@ -280,7 +346,7 @@ let DTO = DTO_1 = class DTO extends DataValidator {
|
|
|
280
346
|
else {
|
|
281
347
|
validatePropertyValue(this, p, Reflect.get(target, p));
|
|
282
348
|
}
|
|
283
|
-
}),
|
|
349
|
+
}, acceptsAny, p),
|
|
284
350
|
deleteProperty: (target, prop) => {
|
|
285
351
|
if (!isSymbol(prop))
|
|
286
352
|
validatePropertyValue(this, prop, void (0));
|
|
@@ -5,7 +5,8 @@ import { Schema } from '../../lib/validation/types/Schema.js';
|
|
|
5
5
|
* Declare the schema of a property of a DTO class. The DTO validates the property against it when it is constructed
|
|
6
6
|
* (the whole object at once: defaults applied, the keys without schema removed unless the class has an
|
|
7
7
|
* `@IndexSignature`), and each time the property, or a value nested in it, is changed afterwards (the change is undone
|
|
8
|
-
* when invalid).
|
|
8
|
+
* when invalid). With `DTO.Any()`, an object of another class the property holds is given as it is, not watched: no
|
|
9
|
+
* change of it can be invalid. The schema is also part of the class schema (`MyDTO.Schema()`) used by `@Accept`, `@Return` and the
|
|
9
10
|
* actions' input validation. Subclasses inherit the property schemas, and may declare a property again to replace its
|
|
10
11
|
* schema. Ignored on a symbol property or on a class which is not a DTO.
|
|
11
12
|
* @param schema The schema of the property, built with the static methods of `DTO` (`DTO.String().required()`); a
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import type { Server } from 'node:net';
|
|
2
|
+
/**
|
|
3
|
+
* A network interface, as an implementation of {@link IInterfaceListening} takes it: its name (`'eth1'`; on Windows the
|
|
4
|
+
* name of the network connection), its hardware address (`{mac: '52:54:00:12:34:56'}`) or its index (`{index: 3}`).
|
|
5
|
+
*/
|
|
6
|
+
export type NetworkInterfaceSelector = string | {
|
|
7
|
+
/**
|
|
8
|
+
* The hardware address of the interface.
|
|
9
|
+
*/
|
|
10
|
+
mac: string;
|
|
11
|
+
} | {
|
|
12
|
+
/**
|
|
13
|
+
* The index of the interface.
|
|
14
|
+
*/
|
|
15
|
+
index: number;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* An address a listener of a network interface can be reached at.
|
|
19
|
+
*/
|
|
20
|
+
export interface IListeningAddress {
|
|
21
|
+
/**
|
|
22
|
+
* The address (an IPv6 address without its scope).
|
|
23
|
+
*/
|
|
24
|
+
address: string;
|
|
25
|
+
/**
|
|
26
|
+
* `'IPv4'` or `'IPv6'`.
|
|
27
|
+
*/
|
|
28
|
+
family: 'IPv4' | 'IPv6';
|
|
29
|
+
/**
|
|
30
|
+
* The port.
|
|
31
|
+
*/
|
|
32
|
+
port: number;
|
|
33
|
+
/**
|
|
34
|
+
* IPv6 only: the scope of the address (the index of the interface for a link-local one), 0 for a global one.
|
|
35
|
+
*/
|
|
36
|
+
scopeid?: number;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The options of {@link IInterfaceListening.listenOnAll}.
|
|
40
|
+
*/
|
|
41
|
+
export interface IInterfaceListenOptions {
|
|
42
|
+
/**
|
|
43
|
+
* The port; 0 lets the system choose one (for one interface only).
|
|
44
|
+
*/
|
|
45
|
+
port: number;
|
|
46
|
+
/**
|
|
47
|
+
* The families listened on.
|
|
48
|
+
* @default 'both'
|
|
49
|
+
*/
|
|
50
|
+
family?: 'IPv4' | 'IPv6' | 'both';
|
|
51
|
+
/**
|
|
52
|
+
* Refuse to listen where the connections reaching the addresses of the interface through another interface cannot
|
|
53
|
+
* be refused, and stop listening while they cannot. An implementation that never refuses them throws.
|
|
54
|
+
* @default false
|
|
55
|
+
*/
|
|
56
|
+
strict?: boolean;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The listener of a network interface for a server: it accepts the connections of the interface and gives them to the
|
|
60
|
+
* server, whatever the addresses of the interface, again when they change and when the interface is unplugged and
|
|
61
|
+
* plugged back. The server itself does not listen. The `InterfaceListener` of `@lakutata/netif` implements it.
|
|
62
|
+
*/
|
|
63
|
+
export interface IInterfaceListener {
|
|
64
|
+
/**
|
|
65
|
+
* The interface listened on: its name (`undefined` while it does not exist), and whether it is the loopback one.
|
|
66
|
+
*/
|
|
67
|
+
readonly networkInterface: {
|
|
68
|
+
readonly name: string | undefined;
|
|
69
|
+
readonly loopback: boolean;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* The port, `undefined` until a port 0 is given one by the system.
|
|
73
|
+
*/
|
|
74
|
+
readonly port: number | undefined;
|
|
75
|
+
/**
|
|
76
|
+
* The addresses it can be reached at now: none while the interface does not exist or has no address.
|
|
77
|
+
*/
|
|
78
|
+
readonly addresses: IListeningAddress[];
|
|
79
|
+
/**
|
|
80
|
+
* Whether the interface is listened on now.
|
|
81
|
+
*/
|
|
82
|
+
readonly listening: boolean;
|
|
83
|
+
/**
|
|
84
|
+
* Whether the system refuses the connections that reach the addresses of the interface through another interface.
|
|
85
|
+
*/
|
|
86
|
+
readonly enforced: boolean;
|
|
87
|
+
/**
|
|
88
|
+
* Why `enforced` is `false`, when it is.
|
|
89
|
+
*/
|
|
90
|
+
readonly reason: string | undefined;
|
|
91
|
+
/**
|
|
92
|
+
* Whether it was closed.
|
|
93
|
+
*/
|
|
94
|
+
readonly closed: boolean;
|
|
95
|
+
/**
|
|
96
|
+
* Stop listening; the connections established are left to the server.
|
|
97
|
+
*/
|
|
98
|
+
close(): Promise<void>;
|
|
99
|
+
/**
|
|
100
|
+
* The interface is listened on, again after a change.
|
|
101
|
+
* @param event `'listening'`.
|
|
102
|
+
* @param listener Called without argument.
|
|
103
|
+
*/
|
|
104
|
+
on(event: 'listening', listener: () => void): this;
|
|
105
|
+
/**
|
|
106
|
+
* A failure of listening again, retried by the listener; with `strict`, the guarantee lost.
|
|
107
|
+
* @param event `'error'`.
|
|
108
|
+
* @param listener Called with the error.
|
|
109
|
+
*/
|
|
110
|
+
on(event: 'error', listener: (error: Error) => void): this;
|
|
111
|
+
/**
|
|
112
|
+
* `enforced` changed.
|
|
113
|
+
* @param event `'enforced'`.
|
|
114
|
+
* @param listener Called with its new value.
|
|
115
|
+
*/
|
|
116
|
+
on(event: 'enforced', listener: (enforced: boolean) => void): this;
|
|
117
|
+
/**
|
|
118
|
+
* The listener was closed.
|
|
119
|
+
* @param event `'close'`.
|
|
120
|
+
* @param listener Called without argument.
|
|
121
|
+
*/
|
|
122
|
+
on(event: 'close', listener: () => void): this;
|
|
123
|
+
/**
|
|
124
|
+
* Remove a listener of an event.
|
|
125
|
+
* @param event The event.
|
|
126
|
+
* @param listener The listener given to `on()`.
|
|
127
|
+
*/
|
|
128
|
+
off(event: 'listening' | 'error' | 'enforced' | 'close', listener: (...args: any[]) => void): this;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Listening on network interfaces instead of addresses: what the entrypoints use for their `interface` option. The
|
|
132
|
+
* package `@lakutata/netif` implements it, and is the one used by default; another implementation is given in the
|
|
133
|
+
* `interfaceListening` option of the entrypoints.
|
|
134
|
+
* @example
|
|
135
|
+
* ```typescript
|
|
136
|
+
* import type {IInterfaceListener, IInterfaceListening} from 'lakutata'
|
|
137
|
+
* import {listenOnAll} from '@lakutata/netif'
|
|
138
|
+
*
|
|
139
|
+
* //An implementation that writes each listener made before giving it to the entrypoint
|
|
140
|
+
* const logged: IInterfaceListening = {
|
|
141
|
+
* listenOnAll: async (selectors, server, options): Promise<IInterfaceListener[]> => {
|
|
142
|
+
* const listeners: IInterfaceListener[] = await listenOnAll(selectors, server, options)
|
|
143
|
+
* for (const listener of listeners) console.log(listener.networkInterface.name, listener.addresses)
|
|
144
|
+
* return listeners
|
|
145
|
+
* }
|
|
146
|
+
* }
|
|
147
|
+
* ```
|
|
148
|
+
*/
|
|
149
|
+
export interface IInterfaceListening {
|
|
150
|
+
/**
|
|
151
|
+
* Listen on interfaces for a server, one listener by interface; when one cannot be listened on, the others are
|
|
152
|
+
* closed and the error is thrown. An interface that does not exist yet is listened on once it appears.
|
|
153
|
+
* @param selectors The interfaces; several need a port other than 0.
|
|
154
|
+
* @param server The server the connections are given to.
|
|
155
|
+
* @param options The port, the families, and whether the other interfaces must be refused.
|
|
156
|
+
* @returns The listeners, in the order of the interfaces.
|
|
157
|
+
*/
|
|
158
|
+
listenOnAll(selectors: NetworkInterfaceSelector | NetworkInterfaceSelector[], server: Server, options: IInterfaceListenOptions): Promise<IInterfaceListener[]>;
|
|
159
|
+
}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { BaseObject } from '../BaseObject.js';
|
|
2
|
+
import { type Resolver } from '../../ioc/Resolvers.js';
|
|
2
3
|
/**
|
|
3
|
-
* Set configurable records to
|
|
4
|
-
* @param
|
|
5
|
-
* @param registrationName
|
|
4
|
+
* Set configurable records to a registration (the options it was declared with)
|
|
5
|
+
* @param registration
|
|
6
6
|
* @param configurableRecords
|
|
7
7
|
* @constructor
|
|
8
8
|
*/
|
|
9
|
-
export declare function setConfigurableRecords
|
|
9
|
+
export declare function setConfigurableRecords(registration: Resolver<any>, configurableRecords: Record<string, any>): void;
|
|
10
10
|
/**
|
|
11
|
-
* Get configurable records from
|
|
12
|
-
* @param
|
|
11
|
+
* Get configurable records from a registration
|
|
12
|
+
* @param registration
|
|
13
13
|
* @constructor
|
|
14
14
|
*/
|
|
15
|
-
export declare function getConfigurableRecords
|
|
15
|
+
export declare function getConfigurableRecords(registration: Resolver<any> | null): Record<string, any>;
|
|
16
16
|
/**
|
|
17
17
|
* Set id to instance
|
|
18
18
|
* @param target
|
|
@@ -45,7 +45,9 @@ export declare class DTO extends DataValidator {
|
|
|
45
45
|
* Create a DTO from its data, validated against the class schema: the defaults applied, the keys without schema
|
|
46
46
|
* removed (unless the class has an `@IndexSignature`). The instance then validates each change of a property, or
|
|
47
47
|
* of a value nested in it (an array, an object): an invalid change throws an `InvalidValueException` and is
|
|
48
|
-
* undone.
|
|
48
|
+
* undone. A property accepting any value (`DTO.Any()`, or an index signature `DTO.Any()`) gives the objects of
|
|
49
|
+
* other classes it holds as they are, since no change of theirs can be invalid: their getters, their private fields
|
|
50
|
+
* and their identity are those of the object itself.
|
|
49
51
|
* @param props The data of the DTO. Default: no data (`{}`).
|
|
50
52
|
* @throws {InvalidValueException} When the data does not match the class schema.
|
|
51
53
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lakutata/core",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.4",
|
|
4
4
|
"description": "The core of the lakutata framework: the IoC container and dependency injection, the object model with asynchronous construction, and DTO schema validation with the API of joi.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"lakutata",
|
|
@@ -107,7 +107,7 @@
|
|
|
107
107
|
"test:engine-types": "node scripts/check-engine-types.mjs"
|
|
108
108
|
},
|
|
109
109
|
"dependencies": {
|
|
110
|
-
"@lakutata/utils": "3.1.
|
|
110
|
+
"@lakutata/utils": "3.1.1",
|
|
111
111
|
"reflect-metadata": "0.2.2"
|
|
112
112
|
},
|
|
113
113
|
"engines": {
|