@platformatic/kafka 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +270 -0
- package/dist/apis/admin/alter-client-quotas.d.ts +33 -0
- package/dist/apis/admin/alter-client-quotas.js +64 -0
- package/dist/apis/admin/alter-configs.d.ts +26 -0
- package/dist/apis/admin/alter-configs.js +57 -0
- package/dist/apis/admin/alter-partition-reassignments.d.ts +30 -0
- package/dist/apis/admin/alter-partition-reassignments.js +68 -0
- package/dist/apis/admin/alter-partition.d.ts +39 -0
- package/dist/apis/admin/alter-partition.js +87 -0
- package/dist/apis/admin/alter-replica-log-dirs.d.ts +26 -0
- package/dist/apis/admin/alter-replica-log-dirs.js +55 -0
- package/dist/apis/admin/alter-user-scram-credentials.d.ts +27 -0
- package/dist/apis/admin/alter-user-scram-credentials.js +60 -0
- package/dist/apis/admin/consumer-group-describe.d.ts +41 -0
- package/dist/apis/admin/consumer-group-describe.js +103 -0
- package/dist/apis/admin/create-acls.d.ts +24 -0
- package/dist/apis/admin/create-acls.js +55 -0
- package/dist/apis/admin/create-delegation-token.d.ts +24 -0
- package/dist/apis/admin/create-delegation-token.js +54 -0
- package/dist/apis/admin/create-partitions.d.ts +24 -0
- package/dist/apis/admin/create-partitions.js +54 -0
- package/dist/apis/admin/create-topics.d.ts +42 -0
- package/dist/apis/admin/create-topics.js +86 -0
- package/dist/apis/admin/delete-acls.d.ts +36 -0
- package/dist/apis/admin/delete-acls.js +82 -0
- package/dist/apis/admin/delete-groups.d.ts +14 -0
- package/dist/apis/admin/delete-groups.js +40 -0
- package/dist/apis/admin/delete-records.d.ts +27 -0
- package/dist/apis/admin/delete-records.js +59 -0
- package/dist/apis/admin/delete-topics.d.ts +21 -0
- package/dist/apis/admin/delete-topics.js +50 -0
- package/dist/apis/admin/describe-acls.d.ts +25 -0
- package/dist/apis/admin/describe-acls.js +66 -0
- package/dist/apis/admin/describe-client-quotas.d.ts +30 -0
- package/dist/apis/admin/describe-client-quotas.js +57 -0
- package/dist/apis/admin/describe-cluster.d.ts +23 -0
- package/dist/apis/admin/describe-cluster.js +50 -0
- package/dist/apis/admin/describe-configs.d.ts +38 -0
- package/dist/apis/admin/describe-configs.js +85 -0
- package/dist/apis/admin/describe-delegation-token.d.ts +31 -0
- package/dist/apis/admin/describe-delegation-token.js +62 -0
- package/dist/apis/admin/describe-groups.d.ts +28 -0
- package/dist/apis/admin/describe-groups.js +67 -0
- package/dist/apis/admin/describe-log-dirs.d.ts +32 -0
- package/dist/apis/admin/describe-log-dirs.js +75 -0
- package/dist/apis/admin/describe-producers.d.ts +33 -0
- package/dist/apis/admin/describe-producers.js +70 -0
- package/dist/apis/admin/describe-quorum.d.ts +50 -0
- package/dist/apis/admin/describe-quorum.js +116 -0
- package/dist/apis/admin/describe-topic-partitions.d.ts +42 -0
- package/dist/apis/admin/describe-topic-partitions.js +94 -0
- package/dist/apis/admin/describe-transactions.d.ts +24 -0
- package/dist/apis/admin/describe-transactions.js +59 -0
- package/dist/apis/admin/describe-user-scram-credentials.d.ts +26 -0
- package/dist/apis/admin/describe-user-scram-credentials.js +62 -0
- package/dist/apis/admin/envelope.d.ts +10 -0
- package/dist/apis/admin/envelope.js +32 -0
- package/dist/apis/admin/expire-delegation-token.d.ts +11 -0
- package/dist/apis/admin/expire-delegation-token.js +29 -0
- package/dist/apis/admin/incremental-alter-configs.d.ts +27 -0
- package/dist/apis/admin/incremental-alter-configs.js +58 -0
- package/dist/apis/admin/index.d.ts +37 -0
- package/dist/apis/admin/index.js +37 -0
- package/dist/apis/admin/list-groups.d.ts +18 -0
- package/dist/apis/admin/list-groups.js +43 -0
- package/dist/apis/admin/list-partition-reassignments.d.ts +27 -0
- package/dist/apis/admin/list-partition-reassignments.js +56 -0
- package/dist/apis/admin/list-transactions.d.ts +18 -0
- package/dist/apis/admin/list-transactions.js +45 -0
- package/dist/apis/admin/offset-delete.d.ts +26 -0
- package/dist/apis/admin/offset-delete.js +59 -0
- package/dist/apis/admin/renew-delegation-token.d.ts +11 -0
- package/dist/apis/admin/renew-delegation-token.js +29 -0
- package/dist/apis/admin/unregister-broker.d.ts +12 -0
- package/dist/apis/admin/unregister-broker.js +28 -0
- package/dist/apis/admin/update-features.d.ts +23 -0
- package/dist/apis/admin/update-features.js +60 -0
- package/dist/apis/consumer/consumer-group-heartbeat.d.ts +27 -0
- package/dist/apis/consumer/consumer-group-heartbeat.js +70 -0
- package/dist/apis/consumer/fetch.d.ts +46 -0
- package/dist/apis/consumer/fetch.js +121 -0
- package/dist/apis/consumer/heartbeat.d.ts +11 -0
- package/dist/apis/consumer/heartbeat.js +34 -0
- package/dist/apis/consumer/index.d.ts +9 -0
- package/dist/apis/consumer/index.js +9 -0
- package/dist/apis/consumer/join-group.d.ts +27 -0
- package/dist/apis/consumer/join-group.js +71 -0
- package/dist/apis/consumer/leave-group.d.ts +22 -0
- package/dist/apis/consumer/leave-group.js +57 -0
- package/dist/apis/consumer/list-offsets.d.ts +30 -0
- package/dist/apis/consumer/list-offsets.js +68 -0
- package/dist/apis/consumer/offset-commit.d.ts +29 -0
- package/dist/apis/consumer/offset-commit.js +68 -0
- package/dist/apis/consumer/offset-fetch.d.ts +37 -0
- package/dist/apis/consumer/offset-fetch.js +81 -0
- package/dist/apis/consumer/sync-group.d.ts +18 -0
- package/dist/apis/consumer/sync-group.js +49 -0
- package/dist/apis/definitions.d.ts +16 -0
- package/dist/apis/definitions.js +12 -0
- package/dist/apis/enumerations.d.ts +114 -0
- package/dist/apis/enumerations.js +78 -0
- package/dist/apis/index.d.ts +8 -0
- package/dist/apis/index.js +10 -0
- package/dist/apis/metadata/api-versions.d.ts +17 -0
- package/dist/apis/metadata/api-versions.js +41 -0
- package/dist/apis/metadata/find-coordinator.d.ts +19 -0
- package/dist/apis/metadata/find-coordinator.js +50 -0
- package/dist/apis/metadata/index.d.ts +3 -0
- package/dist/apis/metadata/index.js +3 -0
- package/dist/apis/metadata/metadata.d.ts +37 -0
- package/dist/apis/metadata/metadata.js +92 -0
- package/dist/apis/producer/add-offsets-to-txn.d.ts +10 -0
- package/dist/apis/producer/add-offsets-to-txn.js +34 -0
- package/dist/apis/producer/add-partitions-to-txn.d.ts +34 -0
- package/dist/apis/producer/add-partitions-to-txn.js +79 -0
- package/dist/apis/producer/end-txn.d.ts +10 -0
- package/dist/apis/producer/end-txn.js +34 -0
- package/dist/apis/producer/index.d.ts +6 -0
- package/dist/apis/producer/index.js +6 -0
- package/dist/apis/producer/init-producer-id.d.ts +21 -0
- package/dist/apis/producer/init-producer-id.js +38 -0
- package/dist/apis/producer/produce.d.ts +29 -0
- package/dist/apis/producer/produce.js +104 -0
- package/dist/apis/producer/txn-offset-commit.d.ts +29 -0
- package/dist/apis/producer/txn-offset-commit.js +77 -0
- package/dist/apis/security/index.d.ts +2 -0
- package/dist/apis/security/index.js +2 -0
- package/dist/apis/security/sasl-authenticate.d.ts +15 -0
- package/dist/apis/security/sasl-authenticate.js +30 -0
- package/dist/apis/security/sasl-handshake.d.ts +10 -0
- package/dist/apis/security/sasl-handshake.js +28 -0
- package/dist/apis/telemetry/get-telemetry-subscriptions.d.ts +18 -0
- package/dist/apis/telemetry/get-telemetry-subscriptions.js +46 -0
- package/dist/apis/telemetry/index.d.ts +3 -0
- package/dist/apis/telemetry/index.js +3 -0
- package/dist/apis/telemetry/list-client-metrics-resources.d.ts +14 -0
- package/dist/apis/telemetry/list-client-metrics-resources.js +32 -0
- package/dist/apis/telemetry/push-telemetry.d.ts +10 -0
- package/dist/apis/telemetry/push-telemetry.js +36 -0
- package/dist/clients/admin/admin.d.ts +18 -0
- package/dist/clients/admin/admin.js +322 -0
- package/dist/clients/admin/index.d.ts +3 -0
- package/dist/clients/admin/index.js +3 -0
- package/dist/clients/admin/options.d.ts +135 -0
- package/dist/clients/admin/options.js +81 -0
- package/dist/clients/admin/types.d.ts +56 -0
- package/dist/clients/admin/types.js +1 -0
- package/dist/clients/base/base.d.ts +48 -0
- package/dist/clients/base/base.js +242 -0
- package/dist/clients/base/index.d.ts +3 -0
- package/dist/clients/base/index.js +3 -0
- package/dist/clients/base/options.d.ts +115 -0
- package/dist/clients/base/options.js +59 -0
- package/dist/clients/base/types.d.ts +38 -0
- package/dist/clients/base/types.js +1 -0
- package/dist/clients/callbacks.d.ts +8 -0
- package/dist/clients/callbacks.js +42 -0
- package/dist/clients/consumer/consumer.d.ts +33 -0
- package/dist/clients/consumer/consumer.js +767 -0
- package/dist/clients/consumer/index.d.ts +5 -0
- package/dist/clients/consumer/index.js +5 -0
- package/dist/clients/consumer/messages-stream.d.ts +56 -0
- package/dist/clients/consumer/messages-stream.js +404 -0
- package/dist/clients/consumer/options.d.ts +521 -0
- package/dist/clients/consumer/options.js +177 -0
- package/dist/clients/consumer/topics-map.d.ts +8 -0
- package/dist/clients/consumer/topics-map.js +48 -0
- package/dist/clients/consumer/types.d.ts +74 -0
- package/dist/clients/consumer/types.js +11 -0
- package/dist/clients/index.d.ts +6 -0
- package/dist/clients/index.js +6 -0
- package/dist/clients/producer/index.d.ts +3 -0
- package/dist/clients/producer/index.js +3 -0
- package/dist/clients/producer/options.d.ts +122 -0
- package/dist/clients/producer/options.js +47 -0
- package/dist/clients/producer/producer.d.ts +13 -0
- package/dist/clients/producer/producer.js +272 -0
- package/dist/clients/producer/types.d.ts +29 -0
- package/dist/clients/producer/types.js +1 -0
- package/dist/clients/serde.d.ts +40 -0
- package/dist/clients/serde.js +49 -0
- package/dist/errors.d.ts +67 -0
- package/dist/errors.js +160 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +10 -0
- package/dist/network/connection-pool.d.ts +11 -0
- package/dist/network/connection-pool.js +101 -0
- package/dist/network/connection.d.ts +49 -0
- package/dist/network/connection.js +319 -0
- package/dist/network/index.d.ts +2 -0
- package/dist/network/index.js +2 -0
- package/dist/protocol/apis.d.ts +2 -0
- package/dist/protocol/apis.js +191 -0
- package/dist/protocol/compression.d.ts +70 -0
- package/dist/protocol/compression.js +114 -0
- package/dist/protocol/crc32c.d.ts +2 -0
- package/dist/protocol/crc32c.js +83 -0
- package/dist/protocol/definitions.d.ts +12 -0
- package/dist/protocol/definitions.js +11 -0
- package/dist/protocol/dynamic-buffer.d.ts +65 -0
- package/dist/protocol/dynamic-buffer.js +557 -0
- package/dist/protocol/errors.d.ts +8 -0
- package/dist/protocol/errors.js +908 -0
- package/dist/protocol/index.d.ts +14 -0
- package/dist/protocol/index.js +14 -0
- package/dist/protocol/murmur2.d.ts +1 -0
- package/dist/protocol/murmur2.js +55 -0
- package/dist/protocol/reader.d.ts +58 -0
- package/dist/protocol/reader.js +296 -0
- package/dist/protocol/records.d.ts +110 -0
- package/dist/protocol/records.js +149 -0
- package/dist/protocol/sasl/plain.d.ts +3 -0
- package/dist/protocol/sasl/plain.js +3 -0
- package/dist/protocol/sasl/scram-sha.d.ts +28 -0
- package/dist/protocol/sasl/scram-sha.js +104 -0
- package/dist/protocol/varint.d.ts +12 -0
- package/dist/protocol/varint.js +36 -0
- package/dist/protocol/writer.d.ts +48 -0
- package/dist/protocol/writer.js +223 -0
- package/dist/utils.d.ts +20 -0
- package/dist/utils.js +127 -0
- package/package.json +75 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { ConsumerGroupStates } from "../../apis/enumerations.js";
|
|
2
|
+
import { ajv, listErrorMessage } from "../../utils.js";
|
|
3
|
+
import { idProperty } from "../base/options.js";
|
|
4
|
+
export const groupsProperties = {
|
|
5
|
+
groups: {
|
|
6
|
+
type: 'array',
|
|
7
|
+
items: idProperty,
|
|
8
|
+
minItems: 1
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
export const createTopicOptionsSchema = {
|
|
12
|
+
type: 'object',
|
|
13
|
+
properties: {
|
|
14
|
+
topics: { type: 'array', items: idProperty },
|
|
15
|
+
partitions: { type: 'number' },
|
|
16
|
+
replicas: { type: 'number' },
|
|
17
|
+
assignments: {
|
|
18
|
+
type: 'array',
|
|
19
|
+
items: {
|
|
20
|
+
type: 'object',
|
|
21
|
+
properties: {
|
|
22
|
+
partition: { type: 'number', minimum: 0 },
|
|
23
|
+
brokers: { type: 'array', items: { type: 'number' }, minItems: 1 }
|
|
24
|
+
},
|
|
25
|
+
required: ['partition', 'brokers'],
|
|
26
|
+
additionalProperties: false
|
|
27
|
+
},
|
|
28
|
+
minItems: 1
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
required: ['topics'],
|
|
32
|
+
additionalProperties: false
|
|
33
|
+
};
|
|
34
|
+
export const deleteTopicOptionsSchema = {
|
|
35
|
+
type: 'object',
|
|
36
|
+
properties: {
|
|
37
|
+
topics: { type: 'array', items: idProperty }
|
|
38
|
+
},
|
|
39
|
+
required: ['topics'],
|
|
40
|
+
additionalProperties: false
|
|
41
|
+
};
|
|
42
|
+
export const listGroupsOptionsSchema = {
|
|
43
|
+
type: 'object',
|
|
44
|
+
properties: {
|
|
45
|
+
states: {
|
|
46
|
+
type: 'array',
|
|
47
|
+
items: {
|
|
48
|
+
type: 'string',
|
|
49
|
+
enum: ConsumerGroupStates,
|
|
50
|
+
errorMessage: listErrorMessage(ConsumerGroupStates)
|
|
51
|
+
},
|
|
52
|
+
minItems: 0
|
|
53
|
+
},
|
|
54
|
+
types: {
|
|
55
|
+
type: 'array',
|
|
56
|
+
items: idProperty,
|
|
57
|
+
minItems: 0
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
additionalProperties: false
|
|
61
|
+
};
|
|
62
|
+
export const describeGroupsOptionsSchema = {
|
|
63
|
+
type: 'object',
|
|
64
|
+
properties: {
|
|
65
|
+
...groupsProperties,
|
|
66
|
+
includeAuthorizedOperations: { type: 'boolean' }
|
|
67
|
+
},
|
|
68
|
+
required: ['groups'],
|
|
69
|
+
additionalProperties: false
|
|
70
|
+
};
|
|
71
|
+
export const deleteGroupsOptionsSchema = {
|
|
72
|
+
type: 'object',
|
|
73
|
+
properties: groupsProperties,
|
|
74
|
+
required: ['groups'],
|
|
75
|
+
additionalProperties: false
|
|
76
|
+
};
|
|
77
|
+
export const createTopicsOptionsValidator = ajv.compile(createTopicOptionsSchema);
|
|
78
|
+
export const deleteTopicsOptionsValidator = ajv.compile(deleteTopicOptionsSchema);
|
|
79
|
+
export const listGroupsOptionsValidator = ajv.compile(listGroupsOptionsSchema);
|
|
80
|
+
export const describeGroupsOptionsValidator = ajv.compile(describeGroupsOptionsSchema);
|
|
81
|
+
export const deleteGroupsOptionsValidator = ajv.compile(deleteGroupsOptionsSchema);
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { type ConsumerGroupState } from '../../apis/enumerations.ts';
|
|
2
|
+
import { type NullableString } from '../../protocol/definitions.ts';
|
|
3
|
+
import { type BaseOptions } from '../base/types.ts';
|
|
4
|
+
import { type ExtendedGroupProtocolSubscription, type GroupAssignment } from '../consumer/types.ts';
|
|
5
|
+
export interface BrokerAssignment {
|
|
6
|
+
partition: number;
|
|
7
|
+
brokers: number[];
|
|
8
|
+
}
|
|
9
|
+
export interface CreatedTopic {
|
|
10
|
+
id: string;
|
|
11
|
+
name: string;
|
|
12
|
+
partitions: number;
|
|
13
|
+
replicas: number;
|
|
14
|
+
configuration: Record<string, NullableString>;
|
|
15
|
+
}
|
|
16
|
+
export interface GroupMember {
|
|
17
|
+
id: string;
|
|
18
|
+
groupInstanceId: NullableString;
|
|
19
|
+
clientId: string;
|
|
20
|
+
clientHost: string;
|
|
21
|
+
metadata: Omit<ExtendedGroupProtocolSubscription, 'memberId'>;
|
|
22
|
+
assignments: Map<string, GroupAssignment>;
|
|
23
|
+
}
|
|
24
|
+
export interface GroupBase {
|
|
25
|
+
id: string;
|
|
26
|
+
state: ConsumerGroupState;
|
|
27
|
+
groupType: string;
|
|
28
|
+
protocolType: string;
|
|
29
|
+
}
|
|
30
|
+
export interface Group extends Omit<GroupBase, 'groupType'> {
|
|
31
|
+
protocol: string;
|
|
32
|
+
members: Map<string, GroupMember>;
|
|
33
|
+
authorizedOperations: number;
|
|
34
|
+
}
|
|
35
|
+
export interface AdminOptions extends BaseOptions {
|
|
36
|
+
}
|
|
37
|
+
export interface CreateTopicsOptions {
|
|
38
|
+
topics: string[];
|
|
39
|
+
partitions?: number;
|
|
40
|
+
replicas?: number;
|
|
41
|
+
assignments?: BrokerAssignment[];
|
|
42
|
+
}
|
|
43
|
+
export interface DeleteTopicsOptions {
|
|
44
|
+
topics: string[];
|
|
45
|
+
}
|
|
46
|
+
export interface ListGroupsOptions {
|
|
47
|
+
states?: ConsumerGroupState[];
|
|
48
|
+
types?: string[];
|
|
49
|
+
}
|
|
50
|
+
export interface DescribeGroupsOptions {
|
|
51
|
+
groups: string[];
|
|
52
|
+
includeAuthorizedOperations?: boolean;
|
|
53
|
+
}
|
|
54
|
+
export interface DeleteGroupsOptions {
|
|
55
|
+
groups: string[];
|
|
56
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type ValidateFunction } from 'ajv';
|
|
2
|
+
import { EventEmitter } from 'node:events';
|
|
3
|
+
import { type Callback } from '../../apis/definitions.ts';
|
|
4
|
+
import { ConnectionPool } from '../../network/connection-pool.ts';
|
|
5
|
+
import { type Broker } from '../../network/connection.ts';
|
|
6
|
+
import { type CallbackWithPromise } from '../callbacks.ts';
|
|
7
|
+
import { type BaseOptions, type ClusterMetadata, type MetadataOptions } from './types.ts';
|
|
8
|
+
export declare const kClientId: unique symbol;
|
|
9
|
+
export declare const kBootstrapBrokers: unique symbol;
|
|
10
|
+
export declare const kOptions: unique symbol;
|
|
11
|
+
export declare const kConnections: unique symbol;
|
|
12
|
+
export declare const kCreateConnectionPool: unique symbol;
|
|
13
|
+
export declare const kClosed: unique symbol;
|
|
14
|
+
export declare const kMetadata: unique symbol;
|
|
15
|
+
export declare const kCheckNotClosed: unique symbol;
|
|
16
|
+
export declare const kClearMetadata: unique symbol;
|
|
17
|
+
export declare const kParseBroker: unique symbol;
|
|
18
|
+
export declare const kPerformWithRetry: unique symbol;
|
|
19
|
+
export declare const kPerformDeduplicated: unique symbol;
|
|
20
|
+
export declare const kValidateOptions: unique symbol;
|
|
21
|
+
export declare const kInspect: unique symbol;
|
|
22
|
+
export declare const kInstance: unique symbol;
|
|
23
|
+
export declare class Base<OptionsType extends BaseOptions> extends EventEmitter {
|
|
24
|
+
#private;
|
|
25
|
+
[kInstance]: number;
|
|
26
|
+
[kClientId]: string;
|
|
27
|
+
[kBootstrapBrokers]: Broker[];
|
|
28
|
+
[kOptions]: OptionsType;
|
|
29
|
+
[kConnections]: ConnectionPool;
|
|
30
|
+
[kClosed]: boolean;
|
|
31
|
+
constructor(options: OptionsType);
|
|
32
|
+
get clientId(): string;
|
|
33
|
+
get closed(): boolean;
|
|
34
|
+
emitWithDebug(section: string | null, name: string, ...args: any[]): boolean;
|
|
35
|
+
close(callback: CallbackWithPromise<void>): void;
|
|
36
|
+
close(): Promise<void>;
|
|
37
|
+
metadata(options: MetadataOptions, callback: CallbackWithPromise<ClusterMetadata>): void;
|
|
38
|
+
metadata(options: MetadataOptions): Promise<ClusterMetadata>;
|
|
39
|
+
[kCreateConnectionPool](): ConnectionPool;
|
|
40
|
+
[kMetadata](options: MetadataOptions, callback: CallbackWithPromise<ClusterMetadata>): void;
|
|
41
|
+
[kCheckNotClosed](callback: CallbackWithPromise<any>): boolean;
|
|
42
|
+
[kClearMetadata](): void;
|
|
43
|
+
[kParseBroker](broker: Broker | string): Broker;
|
|
44
|
+
[kPerformWithRetry]<ReturnType>(operationId: string, operation: (callback: Callback<ReturnType>) => void, callback: CallbackWithPromise<ReturnType>, attempt?: number, errors?: Error[], shouldSkipRetry?: (e: Error) => boolean): void | Promise<ReturnType>;
|
|
45
|
+
[kPerformDeduplicated]<ReturnType>(operationId: string, operation: (callback: CallbackWithPromise<ReturnType>) => void, callback: CallbackWithPromise<ReturnType>): void | Promise<ReturnType>;
|
|
46
|
+
[kValidateOptions](target: unknown, validator: ValidateFunction<unknown>, targetName: string, throwOnErrors?: boolean): Error | null;
|
|
47
|
+
[kInspect](...args: unknown[]): void;
|
|
48
|
+
}
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import { api as metadataV12 } from "../../apis/metadata/metadata.js";
|
|
3
|
+
import { MultipleErrors, NetworkError, UserError } from "../../errors.js";
|
|
4
|
+
import { ConnectionPool } from "../../network/connection-pool.js";
|
|
5
|
+
import { ajv, debugDump, loggers } from "../../utils.js";
|
|
6
|
+
import { createPromisifiedCallback, kCallbackPromise } from "../callbacks.js";
|
|
7
|
+
import { baseOptionsValidator, defaultBaseOptions, defaultPort, metadataOptionsValidator } from "./options.js";
|
|
8
|
+
export const kClientId = Symbol('plt.kafka.base.clientId');
|
|
9
|
+
export const kBootstrapBrokers = Symbol('plt.kafka.base.bootstrapBrokers');
|
|
10
|
+
export const kOptions = Symbol('plt.kafka.base.options');
|
|
11
|
+
export const kConnections = Symbol('plt.kafka.base.kConnections');
|
|
12
|
+
export const kCreateConnectionPool = Symbol('plt.kafka.base.kCreateConnectionPool');
|
|
13
|
+
export const kClosed = Symbol('plt.kafka.base.kClosed');
|
|
14
|
+
export const kMetadata = Symbol('plt.kafka.base.metadata');
|
|
15
|
+
export const kCheckNotClosed = Symbol('plt.kafka.base.checkNotClosed');
|
|
16
|
+
export const kClearMetadata = Symbol('plt.kafka.base.clearMetadata');
|
|
17
|
+
export const kParseBroker = Symbol('plt.kafka.base.parseBroker');
|
|
18
|
+
export const kPerformWithRetry = Symbol('plt.kafka.base.performWithRetry');
|
|
19
|
+
export const kPerformDeduplicated = Symbol('plt.kafka.base.performDeduplicated');
|
|
20
|
+
export const kValidateOptions = Symbol('plt.kafka.base.validateOptions');
|
|
21
|
+
export const kInspect = Symbol('plt.kafka.base.inspect');
|
|
22
|
+
export const kInstance = Symbol('plt.kafka.base.instance');
|
|
23
|
+
let currentInstance = 0;
|
|
24
|
+
export class Base extends EventEmitter {
|
|
25
|
+
// This is just used for debugging
|
|
26
|
+
[kInstance];
|
|
27
|
+
// General status - Use symbols rather than JS private property to make them "protected" as in C++
|
|
28
|
+
[kClientId];
|
|
29
|
+
[kBootstrapBrokers];
|
|
30
|
+
[kOptions];
|
|
31
|
+
[kConnections];
|
|
32
|
+
[kClosed];
|
|
33
|
+
#metadata;
|
|
34
|
+
#inflightDeduplications;
|
|
35
|
+
constructor(options) {
|
|
36
|
+
super();
|
|
37
|
+
this[kInstance] = currentInstance++;
|
|
38
|
+
// Validate options
|
|
39
|
+
this[kOptions] = Object.assign({}, defaultBaseOptions, options);
|
|
40
|
+
this[kValidateOptions](this[kOptions], baseOptionsValidator, '/options');
|
|
41
|
+
this[kClientId] = options.clientId;
|
|
42
|
+
// Initialize bootstrap brokers
|
|
43
|
+
this[kBootstrapBrokers] = [];
|
|
44
|
+
for (const broker of options.bootstrapBrokers) {
|
|
45
|
+
this[kBootstrapBrokers].push(this[kParseBroker](broker));
|
|
46
|
+
}
|
|
47
|
+
// Initialize main connection pool
|
|
48
|
+
this[kConnections] = this[kCreateConnectionPool]();
|
|
49
|
+
this[kClosed] = false;
|
|
50
|
+
this.#inflightDeduplications = new Map();
|
|
51
|
+
}
|
|
52
|
+
/* c8 ignore next 3 */
|
|
53
|
+
get clientId() {
|
|
54
|
+
return this[kClientId];
|
|
55
|
+
}
|
|
56
|
+
/* c8 ignore next 3 */
|
|
57
|
+
get closed() {
|
|
58
|
+
return this[kClosed] === true;
|
|
59
|
+
}
|
|
60
|
+
emitWithDebug(section, name, ...args) {
|
|
61
|
+
if (!section) {
|
|
62
|
+
return this.emit(name, ...args);
|
|
63
|
+
}
|
|
64
|
+
/* c8 ignore next */
|
|
65
|
+
loggers[section]?.({ event: name, payload: args });
|
|
66
|
+
return this.emit(`${section}:${name}`, ...args);
|
|
67
|
+
}
|
|
68
|
+
close(callback) {
|
|
69
|
+
if (!callback) {
|
|
70
|
+
callback = createPromisifiedCallback();
|
|
71
|
+
}
|
|
72
|
+
this[kClosed] = true;
|
|
73
|
+
this[kConnections].close(callback);
|
|
74
|
+
return callback[kCallbackPromise];
|
|
75
|
+
}
|
|
76
|
+
metadata(options, callback) {
|
|
77
|
+
if (!callback) {
|
|
78
|
+
callback = createPromisifiedCallback();
|
|
79
|
+
}
|
|
80
|
+
const validationError = this[kValidateOptions](options, metadataOptionsValidator, '/options', false);
|
|
81
|
+
if (validationError) {
|
|
82
|
+
callback(validationError, undefined);
|
|
83
|
+
return callback[kCallbackPromise];
|
|
84
|
+
}
|
|
85
|
+
this[kMetadata](options, callback);
|
|
86
|
+
return callback[kCallbackPromise];
|
|
87
|
+
}
|
|
88
|
+
[kCreateConnectionPool]() {
|
|
89
|
+
const pool = new ConnectionPool(this[kClientId], {
|
|
90
|
+
ownerId: this[kInstance],
|
|
91
|
+
...this[kOptions]
|
|
92
|
+
});
|
|
93
|
+
for (const event of ['connect', 'disconnect', 'failed', 'drain']) {
|
|
94
|
+
pool.on(event, payload => this.emitWithDebug('client', `broker:${event}`, payload));
|
|
95
|
+
}
|
|
96
|
+
return pool;
|
|
97
|
+
}
|
|
98
|
+
[kMetadata](options, callback) {
|
|
99
|
+
const metadataMaxAge = options.metadataMaxAge ?? this[kOptions].metadataMaxAge;
|
|
100
|
+
const isStale = options.forceUpdate ||
|
|
101
|
+
!this.#metadata ||
|
|
102
|
+
Date.now() > this.#metadata.lastUpdate + metadataMaxAge ||
|
|
103
|
+
options.topics.some(topic => !this.#metadata?.topics.has(topic));
|
|
104
|
+
if (!isStale) {
|
|
105
|
+
callback(null, this.#metadata);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const autocreateTopics = options.autocreateTopics ?? this[kOptions].autocreateTopics;
|
|
109
|
+
this[kPerformDeduplicated]('metadata', deduplicateCallback => {
|
|
110
|
+
this[kPerformWithRetry]('metadata', retryCallback => {
|
|
111
|
+
this[kConnections].getFirstAvailable(this[kBootstrapBrokers], (error, connection) => {
|
|
112
|
+
if (error) {
|
|
113
|
+
retryCallback(error, undefined);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
metadataV12(connection, options.topics, autocreateTopics, true, retryCallback);
|
|
117
|
+
});
|
|
118
|
+
}, (error, metadata) => {
|
|
119
|
+
if (error) {
|
|
120
|
+
deduplicateCallback(error, undefined);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
const brokers = new Map();
|
|
124
|
+
const topics = new Map();
|
|
125
|
+
for (const broker of metadata.brokers) {
|
|
126
|
+
const { host, port } = broker;
|
|
127
|
+
brokers.set(broker.nodeId, { host, port });
|
|
128
|
+
}
|
|
129
|
+
for (const { name, topicId: id, partitions: rawPartitions, isInternal } of metadata.topics) {
|
|
130
|
+
/* c8 ignore next 3 */
|
|
131
|
+
if (isInternal) {
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
const partitions = [];
|
|
135
|
+
for (const rawPartition of rawPartitions.sort((a, b) => a.partitionIndex - b.partitionIndex)) {
|
|
136
|
+
partitions[rawPartition.partitionIndex] = {
|
|
137
|
+
leader: rawPartition.leaderId,
|
|
138
|
+
leaderEpoch: rawPartition.leaderEpoch,
|
|
139
|
+
replicas: rawPartition.replicaNodes
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
topics.set(name, { id, partitions, partitionsCount: rawPartitions.length });
|
|
143
|
+
}
|
|
144
|
+
this.#metadata = {
|
|
145
|
+
id: metadata.clusterId,
|
|
146
|
+
brokers,
|
|
147
|
+
topics,
|
|
148
|
+
lastUpdate: Date.now()
|
|
149
|
+
};
|
|
150
|
+
this.emitWithDebug('client', 'metadata', this.#metadata);
|
|
151
|
+
deduplicateCallback(null, this.#metadata);
|
|
152
|
+
}, 0);
|
|
153
|
+
}, callback);
|
|
154
|
+
}
|
|
155
|
+
[kCheckNotClosed](callback) {
|
|
156
|
+
if (this[kClosed]) {
|
|
157
|
+
const error = new NetworkError('Client is closed.', { closed: true, instance: this[kInstance] });
|
|
158
|
+
callback(error, undefined);
|
|
159
|
+
return true;
|
|
160
|
+
}
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
[kClearMetadata]() {
|
|
164
|
+
this.#metadata = undefined;
|
|
165
|
+
}
|
|
166
|
+
[kParseBroker](broker) {
|
|
167
|
+
if (typeof broker === 'string') {
|
|
168
|
+
if (broker.includes(':')) {
|
|
169
|
+
const [host, port] = broker.split(':');
|
|
170
|
+
return { host, port: Number(port) };
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
return { host: broker, port: defaultPort };
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return broker;
|
|
177
|
+
}
|
|
178
|
+
[kPerformWithRetry](operationId, operation, callback, attempt = 0, errors = [], shouldSkipRetry) {
|
|
179
|
+
const retries = this[kOptions].retries;
|
|
180
|
+
this.emitWithDebug('client', 'performWithRetry', operationId, attempt, retries);
|
|
181
|
+
operation((error, result) => {
|
|
182
|
+
if (error) {
|
|
183
|
+
const genericError = error;
|
|
184
|
+
const retriable = genericError.findBy?.('code', NetworkError.code) || genericError.findBy?.('canRetry', true);
|
|
185
|
+
errors.push(error);
|
|
186
|
+
if (attempt < retries && retriable && !shouldSkipRetry?.(error)) {
|
|
187
|
+
setTimeout(() => {
|
|
188
|
+
this[kPerformWithRetry](operationId, operation, callback, attempt + 1, errors, shouldSkipRetry);
|
|
189
|
+
}, this[kOptions].retryDelay);
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
if (attempt === 0) {
|
|
193
|
+
callback(error, undefined);
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
callback(new MultipleErrors(`${operationId} failed ${attempt + 1} times.`, errors), undefined);
|
|
197
|
+
}
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
callback(null, result);
|
|
201
|
+
});
|
|
202
|
+
return callback[kCallbackPromise];
|
|
203
|
+
}
|
|
204
|
+
[kPerformDeduplicated](operationId, operation, callback) {
|
|
205
|
+
let inflights = this.#inflightDeduplications.get(operationId);
|
|
206
|
+
if (!inflights) {
|
|
207
|
+
inflights = [];
|
|
208
|
+
this.#inflightDeduplications.set(operationId, inflights);
|
|
209
|
+
}
|
|
210
|
+
inflights.push(callback);
|
|
211
|
+
if (inflights.length === 1) {
|
|
212
|
+
this.emitWithDebug('client', 'performDeduplicated', operationId);
|
|
213
|
+
operation((error, result) => {
|
|
214
|
+
this.#inflightDeduplications.set(operationId, []);
|
|
215
|
+
for (const cb of inflights) {
|
|
216
|
+
cb(error, result);
|
|
217
|
+
}
|
|
218
|
+
inflights = [];
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
return callback[kCallbackPromise];
|
|
222
|
+
}
|
|
223
|
+
[kValidateOptions](target, validator, targetName, throwOnErrors = true) {
|
|
224
|
+
if (!this[kOptions].strict) {
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
const valid = validator(target);
|
|
228
|
+
if (!valid) {
|
|
229
|
+
const error = new UserError(ajv.errorsText(validator.errors, { dataVar: targetName }) + '.');
|
|
230
|
+
if (throwOnErrors) {
|
|
231
|
+
throw error;
|
|
232
|
+
}
|
|
233
|
+
return error;
|
|
234
|
+
}
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
// This is a private API used to debug during development
|
|
238
|
+
/* c8 ignore next 3 */
|
|
239
|
+
[kInspect](...args) {
|
|
240
|
+
debugDump(`client:${this[kInstance]}`, ...args);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { type BaseOptions } from './types.ts';
|
|
2
|
+
export declare const idProperty: {
|
|
3
|
+
type: string;
|
|
4
|
+
pattern: string;
|
|
5
|
+
};
|
|
6
|
+
export declare const topicWithPartitionAndOffsetProperties: {
|
|
7
|
+
topic: {
|
|
8
|
+
type: string;
|
|
9
|
+
pattern: string;
|
|
10
|
+
};
|
|
11
|
+
partition: {
|
|
12
|
+
type: string;
|
|
13
|
+
minimum: number;
|
|
14
|
+
};
|
|
15
|
+
offset: {
|
|
16
|
+
bigint: boolean;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
export declare const baseOptionsSchema: {
|
|
20
|
+
type: string;
|
|
21
|
+
properties: {
|
|
22
|
+
clientId: {
|
|
23
|
+
type: string;
|
|
24
|
+
pattern: string;
|
|
25
|
+
};
|
|
26
|
+
bootstrapBrokers: {
|
|
27
|
+
oneOf: ({
|
|
28
|
+
type: string;
|
|
29
|
+
items: {
|
|
30
|
+
type: string;
|
|
31
|
+
properties?: undefined;
|
|
32
|
+
};
|
|
33
|
+
} | {
|
|
34
|
+
type: string;
|
|
35
|
+
items: {
|
|
36
|
+
type: string;
|
|
37
|
+
properties: {
|
|
38
|
+
host: {
|
|
39
|
+
type: string;
|
|
40
|
+
};
|
|
41
|
+
port: {
|
|
42
|
+
type: string;
|
|
43
|
+
minimum: number;
|
|
44
|
+
maximum: number;
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
})[];
|
|
49
|
+
};
|
|
50
|
+
timeout: {
|
|
51
|
+
type: string;
|
|
52
|
+
minimum: number;
|
|
53
|
+
};
|
|
54
|
+
connectTimeout: {
|
|
55
|
+
type: string;
|
|
56
|
+
minimum: number;
|
|
57
|
+
};
|
|
58
|
+
retries: {
|
|
59
|
+
type: string;
|
|
60
|
+
minimum: number;
|
|
61
|
+
};
|
|
62
|
+
retryDelay: {
|
|
63
|
+
type: string;
|
|
64
|
+
minimum: number;
|
|
65
|
+
};
|
|
66
|
+
maxInflights: {
|
|
67
|
+
type: string;
|
|
68
|
+
minimum: number;
|
|
69
|
+
};
|
|
70
|
+
metadataMaxAge: {
|
|
71
|
+
type: string;
|
|
72
|
+
minimum: number;
|
|
73
|
+
};
|
|
74
|
+
autocreateTopics: {
|
|
75
|
+
type: string;
|
|
76
|
+
};
|
|
77
|
+
strict: {
|
|
78
|
+
type: string;
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
required: string[];
|
|
82
|
+
additionalProperties: boolean;
|
|
83
|
+
};
|
|
84
|
+
export declare const metadataOptionsSchema: {
|
|
85
|
+
type: string;
|
|
86
|
+
properties: {
|
|
87
|
+
topics: {
|
|
88
|
+
type: string;
|
|
89
|
+
items: {
|
|
90
|
+
type: string;
|
|
91
|
+
pattern: string;
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
autocreateTopics: {
|
|
95
|
+
type: string;
|
|
96
|
+
};
|
|
97
|
+
forceUpdate: {
|
|
98
|
+
type: string;
|
|
99
|
+
};
|
|
100
|
+
metadataMaxAge: {
|
|
101
|
+
type: string;
|
|
102
|
+
minimum: number;
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
required: string[];
|
|
106
|
+
additionalProperties: boolean;
|
|
107
|
+
};
|
|
108
|
+
export declare const baseOptionsValidator: import("ajv").ValidateFunction<{
|
|
109
|
+
[x: string]: {};
|
|
110
|
+
}>;
|
|
111
|
+
export declare const metadataOptionsValidator: import("ajv").ValidateFunction<{
|
|
112
|
+
[x: string]: {};
|
|
113
|
+
}>;
|
|
114
|
+
export declare const defaultPort = 9092;
|
|
115
|
+
export declare const defaultBaseOptions: Partial<BaseOptions>;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { ajv } from "../../utils.js";
|
|
2
|
+
export const idProperty = { type: 'string', pattern: '^\\S+$' };
|
|
3
|
+
export const topicWithPartitionAndOffsetProperties = {
|
|
4
|
+
topic: idProperty,
|
|
5
|
+
partition: { type: 'number', minimum: 0 },
|
|
6
|
+
offset: { bigint: true }
|
|
7
|
+
};
|
|
8
|
+
export const baseOptionsSchema = {
|
|
9
|
+
type: 'object',
|
|
10
|
+
properties: {
|
|
11
|
+
clientId: idProperty,
|
|
12
|
+
bootstrapBrokers: {
|
|
13
|
+
oneOf: [
|
|
14
|
+
{ type: 'array', items: { type: 'string' } },
|
|
15
|
+
{
|
|
16
|
+
type: 'array',
|
|
17
|
+
items: {
|
|
18
|
+
type: 'object',
|
|
19
|
+
properties: { host: { type: 'string' }, port: { type: 'number', minimum: 0, maximum: 65535 } }
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
},
|
|
24
|
+
timeout: { type: 'number', minimum: 0 },
|
|
25
|
+
connectTimeout: { type: 'number', minimum: 0 },
|
|
26
|
+
retries: { type: 'number', minimum: 0 },
|
|
27
|
+
retryDelay: { type: 'number', minimum: 0 },
|
|
28
|
+
maxInflights: { type: 'number', minimum: 0 },
|
|
29
|
+
metadataMaxAge: { type: 'number', minimum: 0 },
|
|
30
|
+
autocreateTopics: { type: 'boolean' },
|
|
31
|
+
strict: { type: 'boolean' }
|
|
32
|
+
},
|
|
33
|
+
required: ['clientId', 'bootstrapBrokers'],
|
|
34
|
+
additionalProperties: true
|
|
35
|
+
};
|
|
36
|
+
export const metadataOptionsSchema = {
|
|
37
|
+
type: 'object',
|
|
38
|
+
properties: {
|
|
39
|
+
topics: { type: 'array', items: idProperty },
|
|
40
|
+
autocreateTopics: { type: 'boolean' },
|
|
41
|
+
forceUpdate: { type: 'boolean' },
|
|
42
|
+
metadataMaxAge: { type: 'number', minimum: 0 }
|
|
43
|
+
},
|
|
44
|
+
required: ['topics'],
|
|
45
|
+
additionalProperties: false
|
|
46
|
+
};
|
|
47
|
+
export const baseOptionsValidator = ajv.compile(baseOptionsSchema);
|
|
48
|
+
export const metadataOptionsValidator = ajv.compile(metadataOptionsSchema);
|
|
49
|
+
export const defaultPort = 9092;
|
|
50
|
+
export const defaultBaseOptions = {
|
|
51
|
+
connectTimeout: 5000,
|
|
52
|
+
maxInflights: 5,
|
|
53
|
+
timeout: 5000,
|
|
54
|
+
retries: 3,
|
|
55
|
+
retryDelay: 1000,
|
|
56
|
+
metadataMaxAge: 5000, // 5 minutes
|
|
57
|
+
autocreateTopics: false,
|
|
58
|
+
strict: false
|
|
59
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type Broker, type ConnectionOptions } from '../../network/connection.ts';
|
|
2
|
+
export interface TopicWithPartitionAndOffset {
|
|
3
|
+
topic: string;
|
|
4
|
+
partition: number;
|
|
5
|
+
offset: bigint;
|
|
6
|
+
}
|
|
7
|
+
export interface ClusterPartitionMetadata {
|
|
8
|
+
leader: number;
|
|
9
|
+
leaderEpoch: number;
|
|
10
|
+
replicas: number[];
|
|
11
|
+
}
|
|
12
|
+
export interface ClusterTopicMetadata {
|
|
13
|
+
id: string;
|
|
14
|
+
partitions: ClusterPartitionMetadata[];
|
|
15
|
+
partitionsCount: number;
|
|
16
|
+
}
|
|
17
|
+
export interface ClusterMetadata {
|
|
18
|
+
id: string;
|
|
19
|
+
brokers: Map<number, Broker>;
|
|
20
|
+
topics: Map<string, ClusterTopicMetadata>;
|
|
21
|
+
lastUpdate: number;
|
|
22
|
+
}
|
|
23
|
+
export interface BaseOptions extends ConnectionOptions {
|
|
24
|
+
clientId: string;
|
|
25
|
+
bootstrapBrokers: Broker[] | string[];
|
|
26
|
+
timeout?: number;
|
|
27
|
+
retries?: number;
|
|
28
|
+
retryDelay?: number;
|
|
29
|
+
metadataMaxAge?: number;
|
|
30
|
+
autocreateTopics?: boolean;
|
|
31
|
+
strict?: boolean;
|
|
32
|
+
}
|
|
33
|
+
export interface MetadataOptions {
|
|
34
|
+
topics: string[];
|
|
35
|
+
autocreateTopics?: boolean;
|
|
36
|
+
forceUpdate?: boolean;
|
|
37
|
+
metadataMaxAge?: number;
|
|
38
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type Callback } from '../apis/definitions.ts';
|
|
2
|
+
export declare const kCallbackPromise: unique symbol;
|
|
3
|
+
export declare const noopCallback: CallbackWithPromise<any>;
|
|
4
|
+
export type CallbackWithPromise<ReturnType> = Callback<ReturnType> & {
|
|
5
|
+
[kCallbackPromise]?: Promise<ReturnType>;
|
|
6
|
+
};
|
|
7
|
+
export declare function createPromisifiedCallback<ReturnType>(): CallbackWithPromise<ReturnType>;
|
|
8
|
+
export declare function runConcurrentCallbacks<ReturnType>(errorMessage: string, collection: unknown[] | Set<unknown> | Map<unknown, unknown>, operation: (item: any, cb: Callback<ReturnType>) => void, callback: Callback<ReturnType[]>): void;
|