@wopr-network/platform-core 1.14.7 → 1.14.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +10 -0
- package/dist/config/provider-endpoints.d.ts +4 -0
- package/dist/config/provider-endpoints.js +10 -6
- package/dist/db/index.d.ts +1 -1
- package/dist/db/index.js +1 -1
- package/dist/fleet/node-repository.d.ts +1 -3
- package/dist/security/key-validation.test.js +65 -8
- package/package.json +1 -1
- package/src/config/provider-endpoints.ts +10 -6
- package/src/db/index.ts +1 -2
- package/src/fleet/node-repository.ts +8 -3
- package/src/security/key-validation.test.ts +74 -8
package/.env.example
CHANGED
|
@@ -14,6 +14,16 @@ AFFILIATE_BASE_URL=https://wopr.network/join?ref=
|
|
|
14
14
|
# internal network. Enabling on public deployments weakens SSRF protections.
|
|
15
15
|
# ALLOW_PRIVATE_NODE_HOSTS=false
|
|
16
16
|
|
|
17
|
+
# --- Provider API probe URLs ---
|
|
18
|
+
# Override the default health-check/validation endpoints per provider.
|
|
19
|
+
# Useful for air-gapped, proxied, or self-hosted deployments.
|
|
20
|
+
# ANTHROPIC_API_URL=https://api.anthropic.com/v1/models
|
|
21
|
+
# OPENAI_API_URL=https://api.openai.com/v1/models
|
|
22
|
+
# GOOGLE_API_URL=https://generativelanguage.googleapis.com/v1/models
|
|
23
|
+
# DISCORD_API_URL=https://discord.com/api/v10/users/@me
|
|
24
|
+
# ELEVENLABS_API_URL=https://api.elevenlabs.io/v1/user
|
|
25
|
+
# DEEPGRAM_API_URL=https://api.deepgram.com/v1/projects
|
|
26
|
+
|
|
17
27
|
# --- Affiliate billing caps ---
|
|
18
28
|
|
|
19
29
|
# Maximum number of referrals an affiliate can earn credit for in a 30-day window (default: 20)
|
|
@@ -2,5 +2,9 @@ import type { Provider } from "../security/types.js";
|
|
|
2
2
|
/**
|
|
3
3
|
* Base API URLs used to validate provider keys.
|
|
4
4
|
* Centralised here so every consumer references one source of truth.
|
|
5
|
+
*
|
|
6
|
+
* Each URL can be overridden via env var for proxied / air-gapped / self-hosted deployments:
|
|
7
|
+
* ANTHROPIC_API_URL, OPENAI_API_URL, GOOGLE_API_URL,
|
|
8
|
+
* DISCORD_API_URL, ELEVENLABS_API_URL, DEEPGRAM_API_URL
|
|
5
9
|
*/
|
|
6
10
|
export declare const PROVIDER_API_URLS: Record<Provider, string>;
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Base API URLs used to validate provider keys.
|
|
3
3
|
* Centralised here so every consumer references one source of truth.
|
|
4
|
+
*
|
|
5
|
+
* Each URL can be overridden via env var for proxied / air-gapped / self-hosted deployments:
|
|
6
|
+
* ANTHROPIC_API_URL, OPENAI_API_URL, GOOGLE_API_URL,
|
|
7
|
+
* DISCORD_API_URL, ELEVENLABS_API_URL, DEEPGRAM_API_URL
|
|
4
8
|
*/
|
|
5
9
|
export const PROVIDER_API_URLS = {
|
|
6
|
-
anthropic: "https://api.anthropic.com/v1/models",
|
|
7
|
-
openai: "https://api.openai.com/v1/models",
|
|
8
|
-
google: "https://generativelanguage.googleapis.com/v1/models",
|
|
9
|
-
discord: "https://discord.com/api/v10/users/@me",
|
|
10
|
-
elevenlabs: "https://api.elevenlabs.io/v1/user",
|
|
11
|
-
deepgram: "https://api.deepgram.com/v1/projects",
|
|
10
|
+
anthropic: process.env.ANTHROPIC_API_URL || "https://api.anthropic.com/v1/models",
|
|
11
|
+
openai: process.env.OPENAI_API_URL || "https://api.openai.com/v1/models",
|
|
12
|
+
google: process.env.GOOGLE_API_URL || "https://generativelanguage.googleapis.com/v1/models",
|
|
13
|
+
discord: process.env.DISCORD_API_URL || "https://discord.com/api/v10/users/@me",
|
|
14
|
+
elevenlabs: process.env.ELEVENLABS_API_URL || "https://api.elevenlabs.io/v1/user",
|
|
15
|
+
deepgram: process.env.DEEPGRAM_API_URL || "https://api.deepgram.com/v1/projects",
|
|
12
16
|
};
|
package/dist/db/index.d.ts
CHANGED
|
@@ -14,10 +14,10 @@ export type DrizzleDb = PgDatabase<PgQueryResultHKT, PlatformSchema>;
|
|
|
14
14
|
export type PlatformDb = DrizzleDb;
|
|
15
15
|
/** Create a Drizzle database instance wrapping the given pg.Pool. */
|
|
16
16
|
export declare function createDb(pool: Pool): PlatformDb;
|
|
17
|
-
export { schema };
|
|
18
17
|
export type { SQL } from "drizzle-orm";
|
|
19
18
|
export { and, asc, count, desc, eq, gt, gte, ilike, inArray, isNull, like, lt, lte, ne, or, sql } from "drizzle-orm";
|
|
20
19
|
export { pgTable, text } from "drizzle-orm/pg-core";
|
|
21
20
|
export type { AuthUser, IAuthUserRepository } from "./auth-user-repository.js";
|
|
22
21
|
export { BetterAuthUserRepository } from "./auth-user-repository.js";
|
|
23
22
|
export { creditColumn } from "./credit-column.js";
|
|
23
|
+
export { schema };
|
package/dist/db/index.js
CHANGED
|
@@ -4,7 +4,6 @@ import * as schema from "./schema/index.js";
|
|
|
4
4
|
export function createDb(pool) {
|
|
5
5
|
return drizzle(pool, { schema });
|
|
6
6
|
}
|
|
7
|
-
export { schema };
|
|
8
7
|
// Re-export commonly used drizzle-orm operators so consumers using pnpm link
|
|
9
8
|
// resolve them from the same drizzle-orm instance as the schema tables.
|
|
10
9
|
export { and, asc, count, desc, eq, gt, gte, ilike, inArray, isNull, like, lt, lte, ne, or, sql } from "drizzle-orm";
|
|
@@ -12,3 +11,4 @@ export { and, asc, count, desc, eq, gt, gte, ilike, inArray, isNull, like, lt, l
|
|
|
12
11
|
export { pgTable, text } from "drizzle-orm/pg-core";
|
|
13
12
|
export { BetterAuthUserRepository } from "./auth-user-repository.js";
|
|
14
13
|
export { creditColumn } from "./credit-column.js";
|
|
14
|
+
export { schema };
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import type { NodeStatus } from "./node-state-machine.js";
|
|
2
2
|
import type { NewProvisioningNode, Node, NodeRegistration, NodeTransition, ProvisionDataUpdate, SelfHostedNodeRegistration } from "./repository-types.js";
|
|
3
|
-
export type { Node, NodeTransition };
|
|
4
|
-
export type { NodeRegistration, SelfHostedNodeRegistration };
|
|
5
|
-
export type { NewProvisioningNode, ProvisionDataUpdate };
|
|
3
|
+
export type { NewProvisioningNode, Node, NodeRegistration, NodeTransition, ProvisionDataUpdate, SelfHostedNodeRegistration, };
|
|
6
4
|
export interface INodeRepository {
|
|
7
5
|
getById(id: string): Promise<Node | null>;
|
|
8
6
|
getBySecret(secret: string): Promise<Node | null>;
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
-
import { PROVIDER_API_URLS } from "../config/provider-endpoints.js";
|
|
3
2
|
import { PROVIDER_ENDPOINTS, validateProviderKey } from "./key-validation.js";
|
|
4
3
|
describe("key-validation", () => {
|
|
5
4
|
describe("PROVIDER_API_URLS", () => {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
afterEach(() => {
|
|
6
|
+
vi.unstubAllEnvs();
|
|
7
|
+
vi.resetModules();
|
|
8
|
+
});
|
|
9
|
+
it("exports a URL for every supported provider", async () => {
|
|
10
|
+
vi.resetModules();
|
|
11
|
+
const { PROVIDER_API_URLS: urls } = await import("../config/provider-endpoints.js");
|
|
12
|
+
expect(urls.anthropic).toBe("https://api.anthropic.com/v1/models");
|
|
13
|
+
expect(urls.openai).toBe("https://api.openai.com/v1/models");
|
|
14
|
+
expect(urls.google).toBe("https://generativelanguage.googleapis.com/v1/models");
|
|
15
|
+
expect(urls.discord).toBe("https://discord.com/api/v10/users/@me");
|
|
16
|
+
expect(urls.elevenlabs).toBe("https://api.elevenlabs.io/v1/user");
|
|
17
|
+
expect(urls.deepgram).toBe("https://api.deepgram.com/v1/projects");
|
|
13
18
|
});
|
|
14
19
|
});
|
|
15
20
|
describe("PROVIDER_ENDPOINTS", () => {
|
|
@@ -84,4 +89,56 @@ describe("key-validation", () => {
|
|
|
84
89
|
}));
|
|
85
90
|
});
|
|
86
91
|
});
|
|
92
|
+
describe("PROVIDER_API_URLS env overrides", () => {
|
|
93
|
+
afterEach(() => {
|
|
94
|
+
vi.unstubAllEnvs();
|
|
95
|
+
vi.resetModules();
|
|
96
|
+
});
|
|
97
|
+
it("uses ANTHROPIC_API_URL when set", async () => {
|
|
98
|
+
vi.stubEnv("ANTHROPIC_API_URL", "https://custom-anthropic.example.com/v1/models");
|
|
99
|
+
vi.resetModules();
|
|
100
|
+
const { PROVIDER_API_URLS: urls } = await import("../config/provider-endpoints.js");
|
|
101
|
+
expect(urls.anthropic).toBe("https://custom-anthropic.example.com/v1/models");
|
|
102
|
+
});
|
|
103
|
+
it("uses OPENAI_API_URL when set", async () => {
|
|
104
|
+
vi.stubEnv("OPENAI_API_URL", "https://custom-openai.example.com/v1/models");
|
|
105
|
+
vi.resetModules();
|
|
106
|
+
const { PROVIDER_API_URLS: urls } = await import("../config/provider-endpoints.js");
|
|
107
|
+
expect(urls.openai).toBe("https://custom-openai.example.com/v1/models");
|
|
108
|
+
});
|
|
109
|
+
it("uses GOOGLE_API_URL when set", async () => {
|
|
110
|
+
vi.stubEnv("GOOGLE_API_URL", "https://custom-google.example.com/v1/models");
|
|
111
|
+
vi.resetModules();
|
|
112
|
+
const { PROVIDER_API_URLS: urls } = await import("../config/provider-endpoints.js");
|
|
113
|
+
expect(urls.google).toBe("https://custom-google.example.com/v1/models");
|
|
114
|
+
});
|
|
115
|
+
it("uses DISCORD_API_URL when set", async () => {
|
|
116
|
+
vi.stubEnv("DISCORD_API_URL", "https://custom-discord.example.com/api/v10/users/@me");
|
|
117
|
+
vi.resetModules();
|
|
118
|
+
const { PROVIDER_API_URLS: urls } = await import("../config/provider-endpoints.js");
|
|
119
|
+
expect(urls.discord).toBe("https://custom-discord.example.com/api/v10/users/@me");
|
|
120
|
+
});
|
|
121
|
+
it("uses ELEVENLABS_API_URL when set", async () => {
|
|
122
|
+
vi.stubEnv("ELEVENLABS_API_URL", "https://custom-elevenlabs.example.com/v1/user");
|
|
123
|
+
vi.resetModules();
|
|
124
|
+
const { PROVIDER_API_URLS: urls } = await import("../config/provider-endpoints.js");
|
|
125
|
+
expect(urls.elevenlabs).toBe("https://custom-elevenlabs.example.com/v1/user");
|
|
126
|
+
});
|
|
127
|
+
it("uses DEEPGRAM_API_URL when set", async () => {
|
|
128
|
+
vi.stubEnv("DEEPGRAM_API_URL", "https://custom-deepgram.example.com/v1/projects");
|
|
129
|
+
vi.resetModules();
|
|
130
|
+
const { PROVIDER_API_URLS: urls } = await import("../config/provider-endpoints.js");
|
|
131
|
+
expect(urls.deepgram).toBe("https://custom-deepgram.example.com/v1/projects");
|
|
132
|
+
});
|
|
133
|
+
it("falls back to defaults when env vars are not set", async () => {
|
|
134
|
+
vi.resetModules();
|
|
135
|
+
const { PROVIDER_API_URLS: urls } = await import("../config/provider-endpoints.js");
|
|
136
|
+
expect(urls.anthropic).toBe("https://api.anthropic.com/v1/models");
|
|
137
|
+
expect(urls.openai).toBe("https://api.openai.com/v1/models");
|
|
138
|
+
expect(urls.google).toBe("https://generativelanguage.googleapis.com/v1/models");
|
|
139
|
+
expect(urls.discord).toBe("https://discord.com/api/v10/users/@me");
|
|
140
|
+
expect(urls.elevenlabs).toBe("https://api.elevenlabs.io/v1/user");
|
|
141
|
+
expect(urls.deepgram).toBe("https://api.deepgram.com/v1/projects");
|
|
142
|
+
});
|
|
143
|
+
});
|
|
87
144
|
});
|
package/package.json
CHANGED
|
@@ -3,12 +3,16 @@ import type { Provider } from "../security/types.js";
|
|
|
3
3
|
/**
|
|
4
4
|
* Base API URLs used to validate provider keys.
|
|
5
5
|
* Centralised here so every consumer references one source of truth.
|
|
6
|
+
*
|
|
7
|
+
* Each URL can be overridden via env var for proxied / air-gapped / self-hosted deployments:
|
|
8
|
+
* ANTHROPIC_API_URL, OPENAI_API_URL, GOOGLE_API_URL,
|
|
9
|
+
* DISCORD_API_URL, ELEVENLABS_API_URL, DEEPGRAM_API_URL
|
|
6
10
|
*/
|
|
7
11
|
export const PROVIDER_API_URLS: Record<Provider, string> = {
|
|
8
|
-
anthropic: "https://api.anthropic.com/v1/models",
|
|
9
|
-
openai: "https://api.openai.com/v1/models",
|
|
10
|
-
google: "https://generativelanguage.googleapis.com/v1/models",
|
|
11
|
-
discord: "https://discord.com/api/v10/users/@me",
|
|
12
|
-
elevenlabs: "https://api.elevenlabs.io/v1/user",
|
|
13
|
-
deepgram: "https://api.deepgram.com/v1/projects",
|
|
12
|
+
anthropic: process.env.ANTHROPIC_API_URL || "https://api.anthropic.com/v1/models",
|
|
13
|
+
openai: process.env.OPENAI_API_URL || "https://api.openai.com/v1/models",
|
|
14
|
+
google: process.env.GOOGLE_API_URL || "https://generativelanguage.googleapis.com/v1/models",
|
|
15
|
+
discord: process.env.DISCORD_API_URL || "https://discord.com/api/v10/users/@me",
|
|
16
|
+
elevenlabs: process.env.ELEVENLABS_API_URL || "https://api.elevenlabs.io/v1/user",
|
|
17
|
+
deepgram: process.env.DEEPGRAM_API_URL || "https://api.deepgram.com/v1/projects",
|
|
14
18
|
};
|
package/src/db/index.ts
CHANGED
|
@@ -23,8 +23,6 @@ export function createDb(pool: Pool): PlatformDb {
|
|
|
23
23
|
return drizzle(pool, { schema }) as unknown as PlatformDb;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
export { schema };
|
|
27
|
-
|
|
28
26
|
export type { SQL } from "drizzle-orm";
|
|
29
27
|
// Re-export commonly used drizzle-orm operators so consumers using pnpm link
|
|
30
28
|
// resolve them from the same drizzle-orm instance as the schema tables.
|
|
@@ -34,3 +32,4 @@ export { pgTable, text } from "drizzle-orm/pg-core";
|
|
|
34
32
|
export type { AuthUser, IAuthUserRepository } from "./auth-user-repository.js";
|
|
35
33
|
export { BetterAuthUserRepository } from "./auth-user-repository.js";
|
|
36
34
|
export { creditColumn } from "./credit-column.js";
|
|
35
|
+
export { schema };
|
|
@@ -9,9 +9,14 @@ import type {
|
|
|
9
9
|
} from "./repository-types.js";
|
|
10
10
|
|
|
11
11
|
// Re-export domain types so existing consumers don't break
|
|
12
|
-
export type {
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
export type {
|
|
13
|
+
NewProvisioningNode,
|
|
14
|
+
Node,
|
|
15
|
+
NodeRegistration,
|
|
16
|
+
NodeTransition,
|
|
17
|
+
ProvisionDataUpdate,
|
|
18
|
+
SelfHostedNodeRegistration,
|
|
19
|
+
};
|
|
15
20
|
|
|
16
21
|
export interface INodeRepository {
|
|
17
22
|
getById(id: string): Promise<Node | null>;
|
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
-
import { PROVIDER_API_URLS } from "../config/provider-endpoints.js";
|
|
3
2
|
import { PROVIDER_ENDPOINTS, validateProviderKey } from "./key-validation.js";
|
|
4
3
|
|
|
5
4
|
describe("key-validation", () => {
|
|
6
5
|
describe("PROVIDER_API_URLS", () => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
6
|
+
afterEach(() => {
|
|
7
|
+
vi.unstubAllEnvs();
|
|
8
|
+
vi.resetModules();
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it("exports a URL for every supported provider", async () => {
|
|
12
|
+
vi.resetModules();
|
|
13
|
+
const { PROVIDER_API_URLS: urls } = await import("../config/provider-endpoints.js");
|
|
14
|
+
expect(urls.anthropic).toBe("https://api.anthropic.com/v1/models");
|
|
15
|
+
expect(urls.openai).toBe("https://api.openai.com/v1/models");
|
|
16
|
+
expect(urls.google).toBe("https://generativelanguage.googleapis.com/v1/models");
|
|
17
|
+
expect(urls.discord).toBe("https://discord.com/api/v10/users/@me");
|
|
18
|
+
expect(urls.elevenlabs).toBe("https://api.elevenlabs.io/v1/user");
|
|
19
|
+
expect(urls.deepgram).toBe("https://api.deepgram.com/v1/projects");
|
|
14
20
|
});
|
|
15
21
|
});
|
|
16
22
|
|
|
@@ -108,4 +114,64 @@ describe("key-validation", () => {
|
|
|
108
114
|
);
|
|
109
115
|
});
|
|
110
116
|
});
|
|
117
|
+
|
|
118
|
+
describe("PROVIDER_API_URLS env overrides", () => {
|
|
119
|
+
afterEach(() => {
|
|
120
|
+
vi.unstubAllEnvs();
|
|
121
|
+
vi.resetModules();
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it("uses ANTHROPIC_API_URL when set", async () => {
|
|
125
|
+
vi.stubEnv("ANTHROPIC_API_URL", "https://custom-anthropic.example.com/v1/models");
|
|
126
|
+
vi.resetModules();
|
|
127
|
+
const { PROVIDER_API_URLS: urls } = await import("../config/provider-endpoints.js");
|
|
128
|
+
expect(urls.anthropic).toBe("https://custom-anthropic.example.com/v1/models");
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it("uses OPENAI_API_URL when set", async () => {
|
|
132
|
+
vi.stubEnv("OPENAI_API_URL", "https://custom-openai.example.com/v1/models");
|
|
133
|
+
vi.resetModules();
|
|
134
|
+
const { PROVIDER_API_URLS: urls } = await import("../config/provider-endpoints.js");
|
|
135
|
+
expect(urls.openai).toBe("https://custom-openai.example.com/v1/models");
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it("uses GOOGLE_API_URL when set", async () => {
|
|
139
|
+
vi.stubEnv("GOOGLE_API_URL", "https://custom-google.example.com/v1/models");
|
|
140
|
+
vi.resetModules();
|
|
141
|
+
const { PROVIDER_API_URLS: urls } = await import("../config/provider-endpoints.js");
|
|
142
|
+
expect(urls.google).toBe("https://custom-google.example.com/v1/models");
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it("uses DISCORD_API_URL when set", async () => {
|
|
146
|
+
vi.stubEnv("DISCORD_API_URL", "https://custom-discord.example.com/api/v10/users/@me");
|
|
147
|
+
vi.resetModules();
|
|
148
|
+
const { PROVIDER_API_URLS: urls } = await import("../config/provider-endpoints.js");
|
|
149
|
+
expect(urls.discord).toBe("https://custom-discord.example.com/api/v10/users/@me");
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it("uses ELEVENLABS_API_URL when set", async () => {
|
|
153
|
+
vi.stubEnv("ELEVENLABS_API_URL", "https://custom-elevenlabs.example.com/v1/user");
|
|
154
|
+
vi.resetModules();
|
|
155
|
+
const { PROVIDER_API_URLS: urls } = await import("../config/provider-endpoints.js");
|
|
156
|
+
expect(urls.elevenlabs).toBe("https://custom-elevenlabs.example.com/v1/user");
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it("uses DEEPGRAM_API_URL when set", async () => {
|
|
160
|
+
vi.stubEnv("DEEPGRAM_API_URL", "https://custom-deepgram.example.com/v1/projects");
|
|
161
|
+
vi.resetModules();
|
|
162
|
+
const { PROVIDER_API_URLS: urls } = await import("../config/provider-endpoints.js");
|
|
163
|
+
expect(urls.deepgram).toBe("https://custom-deepgram.example.com/v1/projects");
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it("falls back to defaults when env vars are not set", async () => {
|
|
167
|
+
vi.resetModules();
|
|
168
|
+
const { PROVIDER_API_URLS: urls } = await import("../config/provider-endpoints.js");
|
|
169
|
+
expect(urls.anthropic).toBe("https://api.anthropic.com/v1/models");
|
|
170
|
+
expect(urls.openai).toBe("https://api.openai.com/v1/models");
|
|
171
|
+
expect(urls.google).toBe("https://generativelanguage.googleapis.com/v1/models");
|
|
172
|
+
expect(urls.discord).toBe("https://discord.com/api/v10/users/@me");
|
|
173
|
+
expect(urls.elevenlabs).toBe("https://api.elevenlabs.io/v1/user");
|
|
174
|
+
expect(urls.deepgram).toBe("https://api.deepgram.com/v1/projects");
|
|
175
|
+
});
|
|
176
|
+
});
|
|
111
177
|
});
|