@prosopo/load-balancer 2.6.17 → 2.8.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.
@@ -0,0 +1,53 @@
1
+ import { ProsopoEnvError } from "@prosopo/common";
2
+ import { z } from "zod";
3
+ const HardcodedProviderSchema = z.object({
4
+ address: z.string(),
5
+ url: z.string(),
6
+ datasetId: z.string(),
7
+ weight: z.number().optional().default(1).transform((val) => {
8
+ const weight = Math.round(val);
9
+ return Math.max(1, Math.min(100, weight));
10
+ })
11
+ });
12
+ const convertHostedProvider = (provider) => {
13
+ const providers = Object.values(provider).map(
14
+ (p) => HardcodedProviderSchema.parse(p)
15
+ );
16
+ return providers.sort((a, b) => a.url.localeCompare(b.url));
17
+ };
18
+ const getLoadBalancerUrl = (environment) => {
19
+ if (environment === "production") {
20
+ return "https://provider-list.prosopo.io/";
21
+ }
22
+ if (environment === "staging") {
23
+ return "https://provider-list.prosopo.io/staging.json";
24
+ }
25
+ throw new ProsopoEnvError("CONFIG.UNKNOWN_ENVIRONMENT", {
26
+ context: { environment }
27
+ });
28
+ };
29
+ const loadBalancer = async (environment) => {
30
+ if (environment === "development") {
31
+ return [
32
+ {
33
+ address: "5EjTA28bKSbFPPyMbUjNtArxyqjwq38r1BapVmLZShaqEedV",
34
+ url: "http://localhost:9229",
35
+ datasetId: "0x9f460e81ac9c71b486f796a21bb36e2263694756a6621134d110da217fd3ef25",
36
+ weight: 1
37
+ }
38
+ ];
39
+ }
40
+ const providers = await fetch(
41
+ getLoadBalancerUrl(environment),
42
+ {
43
+ method: "GET",
44
+ mode: "cors"
45
+ }
46
+ ).then((res) => res.json());
47
+ return convertHostedProvider(providers);
48
+ };
49
+ export {
50
+ convertHostedProvider,
51
+ getLoadBalancerUrl,
52
+ loadBalancer
53
+ };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"balancer.js","sourceRoot":"","sources":["../src/balancer.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAElD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;IACf,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,MAAM,EAAE,CAAC;SACP,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,OAAO,CAAC,CAAC,CAAC;SACV,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE;QAElB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3C,CAAC,CAAC;CACH,CAAC,CAAC;AAMH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CACpC,QAAyB,EACH,EAAE;IACxB,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACnD,uBAAuB,CAAC,KAAK,CAAC,CAAC,CAAC,CAChC,CAAC;IACF,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7D,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,WAA6B,EAAU,EAAE;IAC3E,IAAI,WAAW,KAAK,YAAY,EAAE,CAAC;QAClC,OAAO,mCAAmC,CAAC;IAC5C,CAAC;IACD,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,+CAA+C,CAAC;IACxD,CAAC;IACD,MAAM,IAAI,eAAe,CAAC,4BAA4B,EAAE;QACvD,OAAO,EAAE,EAAE,WAAW,EAAE;KACxB,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,EAChC,WAA6B,EACE,EAAE;IACjC,IAAI,WAAW,KAAK,aAAa,EAAE,CAAC;QACnC,OAAO;YACN;gBACC,OAAO,EAAE,kDAAkD;gBAC3D,GAAG,EAAE,uBAAuB;gBAC5B,SAAS,EACR,oEAAoE;gBACrE,MAAM,EAAE,CAAC;aACT;SACD,CAAC;IACH,CAAC;IAED,MAAM,SAAS,GAAoB,MAAM,KAAK,CAC7C,kBAAkB,CAAC,WAAW,CAAC,EAC/B;QACC,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,MAAM;KACZ,CACD,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IAC5B,OAAO,qBAAqB,CAAC,SAAS,CAAC,CAAC;AACzC,CAAC,CAAC"}
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const common = require("@prosopo/common");
4
+ const zod = require("zod");
5
+ const HardcodedProviderSchema = zod.z.object({
6
+ address: zod.z.string(),
7
+ url: zod.z.string(),
8
+ datasetId: zod.z.string(),
9
+ weight: zod.z.number().optional().default(1).transform((val) => {
10
+ const weight = Math.round(val);
11
+ return Math.max(1, Math.min(100, weight));
12
+ })
13
+ });
14
+ const convertHostedProvider = (provider) => {
15
+ const providers = Object.values(provider).map(
16
+ (p) => HardcodedProviderSchema.parse(p)
17
+ );
18
+ return providers.sort((a, b) => a.url.localeCompare(b.url));
19
+ };
20
+ const getLoadBalancerUrl = (environment) => {
21
+ if (environment === "production") {
22
+ return "https://provider-list.prosopo.io/";
23
+ }
24
+ if (environment === "staging") {
25
+ return "https://provider-list.prosopo.io/staging.json";
26
+ }
27
+ throw new common.ProsopoEnvError("CONFIG.UNKNOWN_ENVIRONMENT", {
28
+ context: { environment }
29
+ });
30
+ };
31
+ const loadBalancer = async (environment) => {
32
+ if (environment === "development") {
33
+ return [
34
+ {
35
+ address: "5EjTA28bKSbFPPyMbUjNtArxyqjwq38r1BapVmLZShaqEedV",
36
+ url: "http://localhost:9229",
37
+ datasetId: "0x9f460e81ac9c71b486f796a21bb36e2263694756a6621134d110da217fd3ef25",
38
+ weight: 1
39
+ }
40
+ ];
41
+ }
42
+ const providers = await fetch(
43
+ getLoadBalancerUrl(environment),
44
+ {
45
+ method: "GET",
46
+ mode: "cors"
47
+ }
48
+ ).then((res) => res.json());
49
+ return convertHostedProvider(providers);
50
+ };
51
+ exports.convertHostedProvider = convertHostedProvider;
52
+ exports.getLoadBalancerUrl = getLoadBalancerUrl;
53
+ exports.loadBalancer = loadBalancer;
@@ -1,38 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const common = require("@prosopo/common");
4
- const convertHostedProvider = (provider) => {
5
- return Object.values(provider);
6
- };
7
- const loadBalancer = async (environment) => {
8
- if (environment === "production") {
9
- const providers = await fetch(
10
- "https://provider-list.prosopo.io/",
11
- {
12
- method: "GET",
13
- mode: "cors"
14
- }
15
- ).then((res) => res.json());
16
- return convertHostedProvider(providers);
17
- }
18
- if (environment === "staging") {
19
- const providers = await fetch(
20
- "https://provider-list.prosopo.io/staging.json",
21
- { method: "GET", mode: "cors" }
22
- ).then((res) => res.json());
23
- return convertHostedProvider(providers);
24
- }
25
- if (environment === "development") {
26
- return [
27
- {
28
- address: "5EjTA28bKSbFPPyMbUjNtArxyqjwq38r1BapVmLZShaqEedV",
29
- url: "http://localhost:9229",
30
- datasetId: "0x9f460e81ac9c71b486f796a21bb36e2263694756a6621134d110da217fd3ef25"
31
- }
32
- ];
33
- }
34
- throw new common.ProsopoEnvError("CONFIG.UNKNOWN_ENVIRONMENT", {
35
- context: { environment }
36
- });
37
- };
38
- exports.loadBalancer = loadBalancer;
3
+ const providers = require("./providers.cjs");
4
+ const balancer = require("./balancer.cjs");
5
+ exports._resetCache = providers._resetCache;
6
+ exports.getRandomActiveProvider = providers.getRandomActiveProvider;
7
+ exports.selectWeightedProvider = providers.selectWeightedProvider;
8
+ exports.convertHostedProvider = balancer.convertHostedProvider;
9
+ exports.getLoadBalancerUrl = balancer.getLoadBalancerUrl;
10
+ exports.loadBalancer = balancer.loadBalancer;
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ require("./index.cjs");
4
+ const balancer = require("./balancer.cjs");
5
+ let cachedProviders = [];
6
+ function _resetCache() {
7
+ cachedProviders = [];
8
+ }
9
+ function selectWeightedProvider(providers, entropy) {
10
+ if (providers.length === 0) {
11
+ throw new Error("No providers available");
12
+ }
13
+ const totalWeight = providers.reduce((sum, p) => sum + p.weight, 0);
14
+ const randomValue = entropy % totalWeight;
15
+ let cumulativeWeight = 0;
16
+ for (const provider of providers) {
17
+ cumulativeWeight += provider.weight;
18
+ if (randomValue < cumulativeWeight) {
19
+ return provider;
20
+ }
21
+ }
22
+ const selectedProvider = providers[providers.length - 1];
23
+ if (!selectedProvider) {
24
+ throw new Error("No providers available");
25
+ }
26
+ return selectedProvider;
27
+ }
28
+ const getRandomActiveProvider = async (env, entropy) => {
29
+ if (cachedProviders.length === 0) {
30
+ cachedProviders = await balancer.loadBalancer(env);
31
+ }
32
+ const randomProviderObj = selectWeightedProvider(cachedProviders, entropy);
33
+ return {
34
+ providerAccount: randomProviderObj.address,
35
+ provider: {
36
+ url: randomProviderObj.url,
37
+ datasetId: randomProviderObj.datasetId
38
+ }
39
+ };
40
+ };
41
+ exports._resetCache = _resetCache;
42
+ exports.getRandomActiveProvider = getRandomActiveProvider;
43
+ exports.selectWeightedProvider = selectWeightedProvider;
@@ -0,0 +1,3 @@
1
+ export * from "./providers.js";
2
+ export * from "./balancer.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC"}
package/dist/index.js CHANGED
@@ -1,38 +1,10 @@
1
- import { ProsopoEnvError } from "@prosopo/common";
2
- const convertHostedProvider = (provider) => {
3
- return Object.values(provider);
4
- };
5
- const loadBalancer = async (environment) => {
6
- if (environment === "production") {
7
- const providers = await fetch(
8
- "https://provider-list.prosopo.io/",
9
- {
10
- method: "GET",
11
- mode: "cors"
12
- }
13
- ).then((res) => res.json());
14
- return convertHostedProvider(providers);
15
- }
16
- if (environment === "staging") {
17
- const providers = await fetch(
18
- "https://provider-list.prosopo.io/staging.json",
19
- { method: "GET", mode: "cors" }
20
- ).then((res) => res.json());
21
- return convertHostedProvider(providers);
22
- }
23
- if (environment === "development") {
24
- return [
25
- {
26
- address: "5EjTA28bKSbFPPyMbUjNtArxyqjwq38r1BapVmLZShaqEedV",
27
- url: "http://localhost:9229",
28
- datasetId: "0x9f460e81ac9c71b486f796a21bb36e2263694756a6621134d110da217fd3ef25"
29
- }
30
- ];
31
- }
32
- throw new ProsopoEnvError("CONFIG.UNKNOWN_ENVIRONMENT", {
33
- context: { environment }
34
- });
35
- };
1
+ import { _resetCache, getRandomActiveProvider, selectWeightedProvider } from "./providers.js";
2
+ import { convertHostedProvider, getLoadBalancerUrl, loadBalancer } from "./balancer.js";
36
3
  export {
37
- loadBalancer
4
+ _resetCache,
5
+ convertHostedProvider,
6
+ getLoadBalancerUrl,
7
+ getRandomActiveProvider,
8
+ loadBalancer,
9
+ selectWeightedProvider
38
10
  };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { EnvironmentTypes, RandomProvider } from "@prosopo/types";
2
+ import { type HardcodedProvider } from "./index.js";
3
+ export declare function _resetCache(): void;
4
+ export declare function selectWeightedProvider(providers: HardcodedProvider[], entropy: number): HardcodedProvider;
5
+ export declare const getRandomActiveProvider: (env: EnvironmentTypes, entropy: number) => Promise<RandomProvider>;
6
+ //# sourceMappingURL=providers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../src/providers.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACvE,OAAO,EAAE,KAAK,iBAAiB,EAAgB,MAAM,YAAY,CAAC;AAIlE,wBAAgB,WAAW,SAE1B;AAUD,wBAAgB,sBAAsB,CACrC,SAAS,EAAE,iBAAiB,EAAE,EAC9B,OAAO,EAAE,MAAM,GACb,iBAAiB,CAyBnB;AAED,eAAO,MAAM,uBAAuB,QAC9B,gBAAgB,WACZ,MAAM,KACb,OAAO,CAAC,cAAc,CAexB,CAAC"}
@@ -0,0 +1,43 @@
1
+ import "./index.js";
2
+ import { loadBalancer } from "./balancer.js";
3
+ let cachedProviders = [];
4
+ function _resetCache() {
5
+ cachedProviders = [];
6
+ }
7
+ function selectWeightedProvider(providers, entropy) {
8
+ if (providers.length === 0) {
9
+ throw new Error("No providers available");
10
+ }
11
+ const totalWeight = providers.reduce((sum, p) => sum + p.weight, 0);
12
+ const randomValue = entropy % totalWeight;
13
+ let cumulativeWeight = 0;
14
+ for (const provider of providers) {
15
+ cumulativeWeight += provider.weight;
16
+ if (randomValue < cumulativeWeight) {
17
+ return provider;
18
+ }
19
+ }
20
+ const selectedProvider = providers[providers.length - 1];
21
+ if (!selectedProvider) {
22
+ throw new Error("No providers available");
23
+ }
24
+ return selectedProvider;
25
+ }
26
+ const getRandomActiveProvider = async (env, entropy) => {
27
+ if (cachedProviders.length === 0) {
28
+ cachedProviders = await loadBalancer(env);
29
+ }
30
+ const randomProviderObj = selectWeightedProvider(cachedProviders, entropy);
31
+ return {
32
+ providerAccount: randomProviderObj.address,
33
+ provider: {
34
+ url: randomProviderObj.url,
35
+ datasetId: randomProviderObj.datasetId
36
+ }
37
+ };
38
+ };
39
+ export {
40
+ _resetCache,
41
+ getRandomActiveProvider,
42
+ selectWeightedProvider
43
+ };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers.js","sourceRoot":"","sources":["../src/providers.ts"],"names":[],"mappings":"AAeA,OAAO,EAA0B,YAAY,EAAE,MAAM,YAAY,CAAC;AAElE,IAAI,eAAe,GAAwB,EAAE,CAAC;AAE9C,MAAM,UAAU,WAAW;IAC1B,eAAe,GAAG,EAAE,CAAC;AACtB,CAAC;AAUD,MAAM,UAAU,sBAAsB,CACrC,SAA8B,EAC9B,OAAe;IAEf,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAC3C,CAAC;IAED,MAAM,WAAW,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAGpE,MAAM,WAAW,GAAG,OAAO,GAAG,WAAW,CAAC;IAG1C,IAAI,gBAAgB,GAAG,CAAC,CAAC;IACzB,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QAClC,gBAAgB,IAAI,QAAQ,CAAC,MAAM,CAAC;QACpC,IAAI,WAAW,GAAG,gBAAgB,EAAE,CAAC;YACpC,OAAO,QAAQ,CAAC;QACjB,CAAC;IACF,CAAC;IAGD,MAAM,gBAAgB,GAAG,SAAS,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACzD,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,gBAAgB,CAAC;AACzB,CAAC;AAED,MAAM,CAAC,MAAM,uBAAuB,GAAG,KAAK,EAC3C,GAAqB,EACrB,OAAe,EACW,EAAE;IAC5B,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAElC,eAAe,GAAG,MAAM,YAAY,CAAC,GAAG,CAAC,CAAC;IAC3C,CAAC;IAED,MAAM,iBAAiB,GAAG,sBAAsB,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;IAE3E,OAAO;QACN,eAAe,EAAE,iBAAiB,CAAC,OAAO;QAC1C,QAAQ,EAAE;YACT,GAAG,EAAE,iBAAiB,CAAC,GAAG;YAC1B,SAAS,EAAE,iBAAiB,CAAC,SAAS;SACtC;KACD,CAAC;AACH,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=providers.unit.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers.unit.test.d.ts","sourceRoot":"","sources":["../../src/tests/providers.unit.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,224 @@
1
+ import { beforeEach, describe, expect, it, vi } from "vitest";
2
+ import { loadBalancer } from "../index.js";
3
+ import { getRandomActiveProvider, selectWeightedProvider, } from "../providers.js";
4
+ import { _resetCache } from "../providers.js";
5
+ vi.mock("../index.js", () => ({
6
+ loadBalancer: vi.fn(),
7
+ }));
8
+ describe("selectWeightedProvider", () => {
9
+ it("selects provider based on weight distribution", () => {
10
+ const providers = [
11
+ {
12
+ address: "address1",
13
+ url: "url1",
14
+ datasetId: "dataset1",
15
+ weight: 1,
16
+ },
17
+ {
18
+ address: "address2",
19
+ url: "url2",
20
+ datasetId: "dataset2",
21
+ weight: 3,
22
+ },
23
+ {
24
+ address: "address3",
25
+ url: "url3",
26
+ datasetId: "dataset3",
27
+ weight: 1,
28
+ },
29
+ ];
30
+ expect(selectWeightedProvider(providers, 0).address).toBe("address1");
31
+ expect(selectWeightedProvider(providers, 1).address).toBe("address2");
32
+ expect(selectWeightedProvider(providers, 2).address).toBe("address2");
33
+ expect(selectWeightedProvider(providers, 3).address).toBe("address2");
34
+ expect(selectWeightedProvider(providers, 4).address).toBe("address3");
35
+ expect(selectWeightedProvider(providers, 5).address).toBe("address1");
36
+ expect(selectWeightedProvider(providers, 6).address).toBe("address2");
37
+ });
38
+ it("handles equal weights correctly", () => {
39
+ const providers = [
40
+ {
41
+ address: "address1",
42
+ url: "url1",
43
+ datasetId: "dataset1",
44
+ weight: 1,
45
+ },
46
+ {
47
+ address: "address2",
48
+ url: "url2",
49
+ datasetId: "dataset2",
50
+ weight: 1,
51
+ },
52
+ ];
53
+ expect(selectWeightedProvider(providers, 0).address).toBe("address1");
54
+ expect(selectWeightedProvider(providers, 1).address).toBe("address2");
55
+ expect(selectWeightedProvider(providers, 2).address).toBe("address1");
56
+ expect(selectWeightedProvider(providers, 3).address).toBe("address2");
57
+ });
58
+ it("handles single provider", () => {
59
+ const providers = [
60
+ {
61
+ address: "address1",
62
+ url: "url1",
63
+ datasetId: "dataset1",
64
+ weight: 10,
65
+ },
66
+ ];
67
+ expect(selectWeightedProvider(providers, 0).address).toBe("address1");
68
+ expect(selectWeightedProvider(providers, 5).address).toBe("address1");
69
+ expect(selectWeightedProvider(providers, 100).address).toBe("address1");
70
+ });
71
+ it("throws error for empty provider list", () => {
72
+ expect(() => selectWeightedProvider([], 0)).toThrow("No providers available");
73
+ });
74
+ it("heavily weighted provider is selected more often", () => {
75
+ const providers = [
76
+ {
77
+ address: "address1",
78
+ url: "url1",
79
+ datasetId: "dataset1",
80
+ weight: 1,
81
+ },
82
+ {
83
+ address: "address2",
84
+ url: "url2",
85
+ datasetId: "dataset2",
86
+ weight: 99,
87
+ },
88
+ ];
89
+ const selections = { address1: 0, address2: 0 };
90
+ for (let i = 0; i < 100; i++) {
91
+ const selected = selectWeightedProvider(providers, i);
92
+ if (selected.address === "address1") {
93
+ selections.address1++;
94
+ }
95
+ else {
96
+ selections.address2++;
97
+ }
98
+ }
99
+ expect(selections.address1).toBe(1);
100
+ expect(selections.address2).toBe(99);
101
+ });
102
+ it("handles maximum weight value (100)", () => {
103
+ const providers = [
104
+ {
105
+ address: "address1",
106
+ url: "url1",
107
+ datasetId: "dataset1",
108
+ weight: 100,
109
+ },
110
+ {
111
+ address: "address2",
112
+ url: "url2",
113
+ datasetId: "dataset2",
114
+ weight: 100,
115
+ },
116
+ ];
117
+ const selections = { address1: 0, address2: 0 };
118
+ for (let i = 0; i < 200; i++) {
119
+ const selected = selectWeightedProvider(providers, i);
120
+ if (selected.address === "address1") {
121
+ selections.address1++;
122
+ }
123
+ else {
124
+ selections.address2++;
125
+ }
126
+ }
127
+ expect(selections.address1).toBe(100);
128
+ expect(selections.address2).toBe(100);
129
+ });
130
+ it("correctly handles providers without values for weight", () => {
131
+ const providers = [
132
+ {
133
+ address: "address1",
134
+ url: "url1",
135
+ datasetId: "dataset1",
136
+ },
137
+ {
138
+ address: "address2",
139
+ url: "url2",
140
+ datasetId: "dataset2",
141
+ weight: 3,
142
+ },
143
+ ];
144
+ const providersWithDefaults = [
145
+ { ...providers[0], weight: 1 },
146
+ providers[1],
147
+ ];
148
+ const selections = { address1: 0, address2: 0 };
149
+ for (let i = 0; i < 100; i++) {
150
+ const selected = selectWeightedProvider(providersWithDefaults, i);
151
+ if (selected.address === "address1") {
152
+ selections.address1++;
153
+ }
154
+ else {
155
+ selections.address2++;
156
+ }
157
+ }
158
+ expect(selections.address1).toBe(25);
159
+ expect(selections.address2).toBe(75);
160
+ });
161
+ });
162
+ describe("getRandomActiveProvider", () => {
163
+ beforeEach(() => {
164
+ _resetCache();
165
+ vi.clearAllMocks();
166
+ vi.resetAllMocks();
167
+ vi.resetModules();
168
+ });
169
+ it("returns a random provider when providers list is populated", async () => {
170
+ const mockProviders = [
171
+ { address: "address1", url: "url1", datasetId: "dataset1", weight: 1 },
172
+ { address: "address2", url: "url2", datasetId: "dataset2", weight: 1 },
173
+ ];
174
+ loadBalancer.mockResolvedValue(mockProviders);
175
+ const result = await getRandomActiveProvider("development", 1);
176
+ expect(result.providerAccount).toBe("address2");
177
+ expect(result.provider.url).toBe("url2");
178
+ expect(result.provider.datasetId).toBe("dataset2");
179
+ });
180
+ it("loads providers only once when called multiple times", async () => {
181
+ const mockProviders = [
182
+ { address: "address1", url: "url1", datasetId: "dataset1", weight: 1 },
183
+ ];
184
+ loadBalancer.mockResolvedValue(mockProviders);
185
+ await getRandomActiveProvider("development", 123);
186
+ await getRandomActiveProvider("development", 456);
187
+ expect(loadBalancer).toHaveBeenCalledTimes(1);
188
+ });
189
+ it("handles empty providers list gracefully", async () => {
190
+ loadBalancer.mockResolvedValue([]);
191
+ await expect(getRandomActiveProvider("development", 123)).rejects.toThrow();
192
+ });
193
+ it("respects provider weights when selecting", async () => {
194
+ const mockProviders = [
195
+ { address: "address1", url: "url1", datasetId: "dataset1", weight: 1 },
196
+ { address: "address2", url: "url2", datasetId: "dataset2", weight: 3 },
197
+ ];
198
+ loadBalancer.mockResolvedValue(mockProviders);
199
+ const result0 = await getRandomActiveProvider("development", 0);
200
+ expect(result0.providerAccount).toBe("address1");
201
+ _resetCache();
202
+ const result1 = await getRandomActiveProvider("development", 1);
203
+ expect(result1.providerAccount).toBe("address2");
204
+ _resetCache();
205
+ const result2 = await getRandomActiveProvider("development", 2);
206
+ expect(result2.providerAccount).toBe("address2");
207
+ _resetCache();
208
+ const result3 = await getRandomActiveProvider("development", 3);
209
+ expect(result3.providerAccount).toBe("address2");
210
+ });
211
+ it("handles providers with missing weight field (defaults to 1)", async () => {
212
+ const mockProviders = [
213
+ { address: "address1", url: "url1", datasetId: "dataset1", weight: 1 },
214
+ { address: "address2", url: "url2", datasetId: "dataset2", weight: 1 },
215
+ ];
216
+ loadBalancer.mockResolvedValue(mockProviders);
217
+ const result0 = await getRandomActiveProvider("development", 0);
218
+ expect(result0.providerAccount).toBe("address1");
219
+ _resetCache();
220
+ const result1 = await getRandomActiveProvider("development", 1);
221
+ expect(result1.providerAccount).toBe("address2");
222
+ });
223
+ });
224
+ //# sourceMappingURL=providers.unit.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers.unit.test.js","sourceRoot":"","sources":["../../src/tests/providers.unit.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@prosopo/load-balancer",
3
- "version": "2.6.17",
3
+ "version": "2.8.8",
4
4
  "description": "Provider load balancer",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "type": "module",
8
8
  "engines": {
9
- "node": "20",
10
- "npm": "10.8.2"
9
+ "node": ">=v20.0.0",
10
+ "npm": ">=10.6.0"
11
11
  },
12
12
  "exports": {
13
13
  ".": {
@@ -21,7 +21,8 @@
21
21
  "build": "NODE_ENV=${NODE_ENV:-development}; vite build --config vite.esm.config.ts --mode $NODE_ENV",
22
22
  "build:tsc": "tsc --build --verbose",
23
23
  "build:cjs": "NODE_ENV=${NODE_ENV:-development}; vite build --config vite.cjs.config.ts --mode $NODE_ENV",
24
- "typecheck": "tsc --build --declaration --emitDeclarationOnly"
24
+ "test": "NODE_ENV=${NODE_ENV:-test}; npx vitest run --config ./vite.test.config.ts --mode $NODE_ENV",
25
+ "typecheck": "tsc --project tsconfig.types.json"
25
26
  },
26
27
  "repository": {
27
28
  "type": "git",
@@ -34,26 +35,23 @@
34
35
  },
35
36
  "homepage": "https://github.com/prosopo/captcha#readme",
36
37
  "dependencies": {
37
- "@prosopo/common": "3.1.2",
38
- "@prosopo/config": "3.1.3",
39
- "@prosopo/types": "3.0.6",
40
- "@typegoose/auto-increment": "4.13.0",
41
- "axios": "1.10.0",
42
- "esbuild": "0.25.6",
43
- "express": "4.21.2",
44
- "openpgp": "5.11.3",
45
- "webpack-dev-server": "5.2.2"
38
+ "@prosopo/common": "3.1.21",
39
+ "@prosopo/config": "3.1.21",
40
+ "@prosopo/types": "3.5.11",
41
+ "zod": "3.23.8"
46
42
  },
47
43
  "devDependencies": {
48
- "@vitest/coverage-v8": "3.0.9",
44
+ "@types/node": "22.10.2",
45
+ "@vitest/coverage-v8": "3.2.4",
49
46
  "concurrently": "9.0.1",
50
47
  "del-cli": "6.0.0",
48
+ "dotenv": "17.2.1",
51
49
  "npm-run-all": "4.1.5",
52
50
  "tslib": "2.7.0",
53
51
  "tsx": "4.20.3",
54
52
  "typescript": "5.6.2",
55
- "vite": "6.3.5",
56
- "vitest": "3.0.9"
53
+ "vite": "6.4.1",
54
+ "vitest": "3.2.4"
57
55
  },
58
56
  "sideEffects": false
59
57
  }