@aluvia/sdk 1.0.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.
Files changed (46) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +423 -0
  3. package/dist/cjs/api/AluviaApi.js +51 -0
  4. package/dist/cjs/api/account.js +155 -0
  5. package/dist/cjs/api/geos.js +76 -0
  6. package/dist/cjs/api/request.js +84 -0
  7. package/dist/cjs/api/types.js +2 -0
  8. package/dist/cjs/client/AluviaClient.js +325 -0
  9. package/dist/cjs/client/ConfigManager.js +303 -0
  10. package/dist/cjs/client/ProxyServer.js +182 -0
  11. package/dist/cjs/client/adapters.js +49 -0
  12. package/dist/cjs/client/logger.js +52 -0
  13. package/dist/cjs/client/rules.js +128 -0
  14. package/dist/cjs/client/types.js +3 -0
  15. package/dist/cjs/errors.js +49 -0
  16. package/dist/cjs/index.js +16 -0
  17. package/dist/cjs/package.json +1 -0
  18. package/dist/esm/api/AluviaApi.js +47 -0
  19. package/dist/esm/api/account.js +152 -0
  20. package/dist/esm/api/geos.js +73 -0
  21. package/dist/esm/api/request.js +81 -0
  22. package/dist/esm/api/types.js +1 -0
  23. package/dist/esm/client/AluviaClient.js +321 -0
  24. package/dist/esm/client/ConfigManager.js +299 -0
  25. package/dist/esm/client/ProxyServer.js +178 -0
  26. package/dist/esm/client/adapters.js +39 -0
  27. package/dist/esm/client/logger.js +48 -0
  28. package/dist/esm/client/rules.js +124 -0
  29. package/dist/esm/client/types.js +2 -0
  30. package/dist/esm/errors.js +42 -0
  31. package/dist/esm/index.js +7 -0
  32. package/dist/types/api/AluviaApi.d.ts +29 -0
  33. package/dist/types/api/account.d.ts +41 -0
  34. package/dist/types/api/geos.d.ts +5 -0
  35. package/dist/types/api/request.d.ts +20 -0
  36. package/dist/types/api/types.d.ts +30 -0
  37. package/dist/types/client/AluviaClient.d.ts +50 -0
  38. package/dist/types/client/ConfigManager.d.ts +100 -0
  39. package/dist/types/client/ProxyServer.d.ts +47 -0
  40. package/dist/types/client/adapters.d.ts +26 -0
  41. package/dist/types/client/logger.d.ts +33 -0
  42. package/dist/types/client/rules.d.ts +34 -0
  43. package/dist/types/client/types.d.ts +194 -0
  44. package/dist/types/errors.d.ts +25 -0
  45. package/dist/types/index.d.ts +5 -0
  46. package/package.json +65 -0
@@ -0,0 +1,100 @@
1
+ import type { GatewayProtocol, LogLevel } from './types.js';
2
+ /**
3
+ * Raw proxy configuration derived from the account-connection response and client options.
4
+ */
5
+ export type RawProxyConfig = {
6
+ protocol: GatewayProtocol;
7
+ host: 'gateway.aluvia.io';
8
+ port: number;
9
+ username: string;
10
+ password: string;
11
+ };
12
+ /**
13
+ * Complete connection network configuration including proxy, rules, and metadata.
14
+ */
15
+ export type ConnectionNetworkConfig = {
16
+ rawProxy: RawProxyConfig;
17
+ rules: string[];
18
+ sessionId: string | null;
19
+ targetGeo: string | null;
20
+ /**
21
+ * ETag returned by the API for this config snapshot (if present).
22
+ * Used for efficient conditional polling via If-None-Match.
23
+ */
24
+ etag: string | null;
25
+ };
26
+ /**
27
+ * Options for ConfigManager constructor.
28
+ */
29
+ export type ConfigManagerOptions = {
30
+ apiKey: string;
31
+ apiBaseUrl: string;
32
+ pollIntervalMs: number;
33
+ gatewayProtocol: GatewayProtocol;
34
+ gatewayPort: number;
35
+ logLevel: LogLevel;
36
+ /**
37
+ * Optional: if provided, use /account/connections/:id.
38
+ * If omitted, init() will attempt POST /account/connections.
39
+ */
40
+ connectionId?: number;
41
+ /**
42
+ * Optional: strict behavior (default true).
43
+ *
44
+ * If true, init() throws when it cannot load/create a usable config.
45
+ * If false, init() may return without config (client proxy mode can still start
46
+ * and will route direct until config becomes available).
47
+ */
48
+ strict?: boolean;
49
+ };
50
+ /**
51
+ * ConfigManager handles fetching and maintaining connection configuration from the Aluvia API.
52
+ *
53
+ * Responsibilities:
54
+ * - Initial fetch of account connection config
55
+ * - Polling for updates using ETag
56
+ * - Providing current config to ProxyServer
57
+ */
58
+ export declare class ConfigManager {
59
+ private config;
60
+ private timer;
61
+ private readonly logger;
62
+ private readonly options;
63
+ private readonly strict;
64
+ private accountConnectionId;
65
+ private pollInFlight;
66
+ constructor(options: ConfigManagerOptions);
67
+ /**
68
+ * Fetch initial configuration from the account connections API.
69
+ * Must be called before starting the proxy.
70
+ *
71
+ * @throws InvalidApiKeyError if apiKey is invalid (401/403)
72
+ * @throws ApiError for other API errors
73
+ */
74
+ init(): Promise<void>;
75
+ /**
76
+ * Start polling for configuration updates.
77
+ * Uses ETag for efficient conditional requests.
78
+ */
79
+ startPolling(): void;
80
+ /**
81
+ * Stop polling for configuration updates.
82
+ */
83
+ stopPolling(): void;
84
+ /**
85
+ * Get the current configuration.
86
+ * Returns null if init() hasn't been called or failed.
87
+ */
88
+ getConfig(): ConnectionNetworkConfig | null;
89
+ setConfig(body: Object): Promise<ConnectionNetworkConfig | null>;
90
+ /**
91
+ * Perform a single poll iteration.
92
+ * Called by the polling timer.
93
+ */
94
+ private pollOnce;
95
+ /**
96
+ * Build ConnectionNetworkConfig from API response.
97
+ */
98
+ private buildConfigFromAny;
99
+ private redactConfig;
100
+ }
@@ -0,0 +1,47 @@
1
+ import type { ConfigManager } from './ConfigManager.js';
2
+ import type { LogLevel } from './types.js';
3
+ /**
4
+ * Result of starting the proxy server.
5
+ */
6
+ export type ProxyServerInfo = {
7
+ host: string;
8
+ port: number;
9
+ url: string;
10
+ };
11
+ /**
12
+ * ProxyServer manages the local HTTP(S) proxy that routes traffic
13
+ * through Aluvia or directly based on rules.
14
+ */
15
+ export declare class ProxyServer {
16
+ private server;
17
+ private readonly configManager;
18
+ private readonly logger;
19
+ private readonly bindHost;
20
+ private static readonly NO_CONFIG_WARN_INTERVAL_MS;
21
+ private lastNoConfigWarnAt;
22
+ private suppressedNoConfigWarnCount;
23
+ constructor(configManager: ConfigManager, options?: {
24
+ logLevel?: LogLevel;
25
+ });
26
+ /**
27
+ * Start the local proxy server.
28
+ *
29
+ * @param port - Optional port to listen on. If not provided, OS assigns a free port.
30
+ * @returns ProxyServerInfo with host, port, and url
31
+ * @throws ProxyStartError if server fails to start
32
+ */
33
+ start(port?: number): Promise<ProxyServerInfo>;
34
+ /**
35
+ * Stop the local proxy server.
36
+ */
37
+ stop(): Promise<void>;
38
+ /**
39
+ * Handle incoming proxy requests.
40
+ * Decides whether to route through Aluvia or direct.
41
+ */
42
+ private handleRequest;
43
+ /**
44
+ * Extract hostname from request parameters.
45
+ */
46
+ private extractHostname;
47
+ }
@@ -0,0 +1,26 @@
1
+ import type { Dispatcher } from 'undici';
2
+ import type { Agent as NodeAgent } from 'node:http';
3
+ import type { PlaywrightProxySettings } from './types.js';
4
+ export type NodeProxyAgents = {
5
+ http: NodeAgent;
6
+ https: NodeAgent;
7
+ };
8
+ export type AxiosProxyConfig = {
9
+ proxy: false;
10
+ httpAgent: NodeAgent;
11
+ httpsAgent: NodeAgent;
12
+ };
13
+ export type GotProxyOptions = {
14
+ agent: {
15
+ http: NodeAgent;
16
+ https: NodeAgent;
17
+ };
18
+ };
19
+ export declare function toPlaywrightProxySettings(serverUrl: string): PlaywrightProxySettings;
20
+ export declare function toPuppeteerArgs(serverUrl: string): Array<string>;
21
+ export declare function toSeleniumArgs(serverUrl: string): string;
22
+ export declare function createNodeProxyAgents(serverUrl: string): NodeProxyAgents;
23
+ export declare function toAxiosConfig(agents: NodeProxyAgents): AxiosProxyConfig;
24
+ export declare function toGotOptions(agents: NodeProxyAgents): GotProxyOptions;
25
+ export declare function createUndiciDispatcher(serverUrl: string): Dispatcher;
26
+ export declare function createUndiciFetch(dispatcher: Dispatcher): typeof fetch;
@@ -0,0 +1,33 @@
1
+ import type { LogLevel } from './types.js';
2
+ /**
3
+ * Simple logger that respects log levels.
4
+ *
5
+ * Log level hierarchy:
6
+ * - 'silent': only error() logs
7
+ * - 'info': info(), warn(), error() log
8
+ * - 'debug': all methods log
9
+ */
10
+ export declare class Logger {
11
+ private readonly level;
12
+ constructor(level: LogLevel);
13
+ /**
14
+ * Log informational messages.
15
+ * Logs when level is 'info' or 'debug'.
16
+ */
17
+ info(...args: unknown[]): void;
18
+ /**
19
+ * Log debug messages.
20
+ * Logs only when level is 'debug'.
21
+ */
22
+ debug(...args: unknown[]): void;
23
+ /**
24
+ * Log warning messages.
25
+ * Logs when level is not 'silent'.
26
+ */
27
+ warn(...args: unknown[]): void;
28
+ /**
29
+ * Log error messages.
30
+ * Always logs regardless of level.
31
+ */
32
+ error(...args: unknown[]): void;
33
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Match a hostname against a pattern.
3
+ *
4
+ * Supported patterns:
5
+ * - '*' matches any hostname
6
+ * - '*.example.com' matches subdomains of example.com (but not example.com itself)
7
+ * - 'example.com' exact match
8
+ * - 'google.*' matches google.com, google.co.uk, etc.
9
+ *
10
+ * @param hostname - The hostname to match
11
+ * @param pattern - The pattern to match against
12
+ * @returns true if hostname matches pattern
13
+ */
14
+ export declare function matchPattern(hostname: string, pattern: string): boolean;
15
+ /**
16
+ * Determine if a hostname should be proxied based on rules.
17
+ *
18
+ * Rules semantics:
19
+ * - [] (empty) → no proxy (return false)
20
+ * - ['*'] → proxy everything
21
+ * - ['example.com'] → proxy only example.com
22
+ * - ['*.google.com'] → proxy subdomains of google.com
23
+ * - ['*', '-example.com'] → proxy everything except example.com
24
+ * - ['AUTO', 'example.com'] → AUTO is placeholder (ignored), proxy example.com
25
+ *
26
+ * Negative patterns (prefixed with '-') exclude hosts from proxying.
27
+ * If '*' is in rules, default is to proxy unless excluded.
28
+ * Without '*', only explicitly matched patterns are proxied.
29
+ *
30
+ * @param hostname - The hostname to check
31
+ * @param rules - Array of rule patterns
32
+ * @returns true if the hostname should be proxied
33
+ */
34
+ export declare function shouldProxy(hostname: string, rules: string[]): boolean;
@@ -0,0 +1,194 @@
1
+ /**
2
+ * Protocol used to connect to the Aluvia gateway.
3
+ */
4
+ export type GatewayProtocol = 'http' | 'https';
5
+ /**
6
+ * Log level for the client.
7
+ */
8
+ export type LogLevel = 'silent' | 'info' | 'debug';
9
+ export type PlaywrightProxySettings = {
10
+ server: string;
11
+ username?: string;
12
+ password?: string;
13
+ };
14
+ /**
15
+ * Options for creating an AluviaClient instance.
16
+ */
17
+ export type AluviaClientOptions = {
18
+ /**
19
+ * Required: user API apiKey (Bearer).
20
+ * This is the apiKey for a single Aluvia user/agent.
21
+ */
22
+ apiKey: string;
23
+ /**
24
+ * Optional: base URL for the Aluvia API.
25
+ * Default: 'https://api.aluvia.io/v1'
26
+ */
27
+ apiBaseUrl?: string;
28
+ /**
29
+ * Optional: polling interval for refreshing account connection config.
30
+ * Default: 5000 ms.
31
+ */
32
+ pollIntervalMs?: number;
33
+ /**
34
+ * Optional: request timeout for API calls made via `client.api`.
35
+ * Default: 30000 ms.
36
+ */
37
+ timeoutMs?: number;
38
+ /**
39
+ * Optional: how the client talks to the Aluvia gateway.
40
+ *
41
+ * - 'http' -> gatewayPort defaults to 8080
42
+ * - 'https' -> gatewayPort defaults to 8443
43
+ *
44
+ * Default: 'http'.
45
+ */
46
+ gatewayProtocol?: GatewayProtocol;
47
+ /**
48
+ * Optional: upstream Aluvia gateway port.
49
+ *
50
+ * If omitted:
51
+ * - 8080 is used when gatewayProtocol === 'http'
52
+ * - 8443 is used when gatewayProtocol === 'https'
53
+ */
54
+ gatewayPort?: number;
55
+ /**
56
+ * Optional: local port for the agent's *local* proxy (127.0.0.1:<localPort>).
57
+ *
58
+ * If omitted, the client will pick a free port automatically by binding to port 0.
59
+ */
60
+ localPort?: number;
61
+ /**
62
+ * Optional: logging verbosity for the client.
63
+ */
64
+ logLevel?: LogLevel;
65
+ /**
66
+ * Optional: use an existing account connection by ID.
67
+ *
68
+ * If provided, the client retrieves config via:
69
+ * GET /account/connections/:connection_id
70
+ *
71
+ * If omitted, the client will attempt to create a new account connection via:
72
+ * POST /account/connections
73
+ */
74
+ connectionId?: number;
75
+ /**
76
+ * Optional: enable local proxy mode (client proxy mode).
77
+ *
78
+ * If true (default): start the local proxy (127.0.0.1:<port>) and route traffic dynamically.
79
+ * If false: do NOT start a local proxy; adapters return gateway proxy settings
80
+ * from the account connection API response for direct use by Playwright/Axios/etc.
81
+ */
82
+ localProxy?: boolean;
83
+ /**
84
+ * Optional: strict startup behavior.
85
+ *
86
+ * If true (default): `client.start()` throws if the SDK cannot load/create
87
+ * an account connection config (proxy credentials + rules). This prevents
88
+ * "silent direct routing" where the local proxy starts but bypasses Aluvia.
89
+ *
90
+ * If false: in client proxy mode, the SDK may still start a local proxy and
91
+ * route traffic directly when config is unavailable.
92
+ */
93
+ strict?: boolean;
94
+ };
95
+ /**
96
+ * Represents an active Aluvia Client connection.
97
+ */
98
+ export type AluviaClientConnection = {
99
+ /**
100
+ * Proxy host to configure in your client.
101
+ *
102
+ * - In client proxy mode (localProxy: true): this is the local proxy host ('127.0.0.1').
103
+ * - In gateway mode: this is the Aluvia gateway host (typically 'gateway.aluvia.io').
104
+ */
105
+ host: string;
106
+ /**
107
+ * Proxy port to configure in your client.
108
+ *
109
+ * - In client proxy mode (localProxy: true): this is the local proxy port.
110
+ * - In gateway mode: this is the Aluvia gateway port (typically 8080 or 8443).
111
+ */
112
+ port: number;
113
+ /**
114
+ * Convenience URL for the proxy server endpoint (without embedding credentials).
115
+ *
116
+ * - In client proxy mode (localProxy: true): 'http://127.0.0.1:<port>'
117
+ * - In gateway mode: '<protocol>://gateway.aluvia.io:<port>'
118
+ *
119
+ * (The local proxy itself is always HTTP; it may tunnel to an HTTP or HTTPS
120
+ * gateway upstream based on gatewayProtocol/gatewayPort.)
121
+ */
122
+ url: string;
123
+ /**
124
+ * Returns a credential-embedded proxy URL intended for clients that require auth in the URL.
125
+ *
126
+ * Note: This value contains secrets (proxy username/password). Avoid logging it or putting it
127
+ * in places that may be exposed (e.g., process args).
128
+ */
129
+ getUrl(): string;
130
+ /**
131
+ * Playwright adapter for chromium/firefox/webkit launch options.
132
+ */
133
+ asPlaywright(): PlaywrightProxySettings;
134
+ /**
135
+ * Puppeteer adapter for launch args.
136
+ */
137
+ asPuppeteer(): Array<string>;
138
+ /**
139
+ * Selenium adapter for launch args.
140
+ */
141
+ asSelenium(): string;
142
+ /**
143
+ * Node HTTP(S) proxy agents for libraries that accept per-protocol agents.
144
+ *
145
+ * Useful for: Axios, got, node-fetch (legacy).
146
+ */
147
+ asNodeAgents(): {
148
+ http: import('node:http').Agent;
149
+ https: import('node:http').Agent;
150
+ };
151
+ /**
152
+ * Axios adapter config.
153
+ *
154
+ * Returns `{ proxy: false, httpAgent, httpsAgent }` so Axios uses the provided agents
155
+ * instead of its built-in proxy option handling.
156
+ */
157
+ asAxiosConfig(): {
158
+ proxy: false;
159
+ httpAgent: import('node:http').Agent;
160
+ httpsAgent: import('node:http').Agent;
161
+ };
162
+ /**
163
+ * got adapter options.
164
+ *
165
+ * Returns `{ agent: { http, https } }`.
166
+ */
167
+ asGotOptions(): {
168
+ agent: {
169
+ http: import('node:http').Agent;
170
+ https: import('node:http').Agent;
171
+ };
172
+ };
173
+ /**
174
+ * undici proxy dispatcher (for undici fetch / undici clients).
175
+ */
176
+ asUndiciDispatcher(): import('undici').Dispatcher;
177
+ /**
178
+ * Returns a `fetch` function powered by undici that uses the proxy dispatcher per request.
179
+ *
180
+ * Note: Node's built-in `fetch()` does not accept a Node `Agent`. Use this for proxying
181
+ * fetch calls through Aluvia.
182
+ */
183
+ asUndiciFetch(): typeof fetch;
184
+ /**
185
+ * Stop this proxy instance:
186
+ * - Close the local proxy server.
187
+ * - Stop using it for new connections.
188
+ */
189
+ stop(): Promise<void>;
190
+ /**
191
+ * Alias for stop().
192
+ */
193
+ close(): Promise<void>;
194
+ };
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Thrown when the apiKey is not provided to AluviaClient.
3
+ */
4
+ export declare class MissingApiKeyError extends Error {
5
+ constructor(message?: string);
6
+ }
7
+ /**
8
+ * Thrown when the API returns 401 or 403, indicating the apiKey is invalid.
9
+ */
10
+ export declare class InvalidApiKeyError extends Error {
11
+ constructor(message?: string);
12
+ }
13
+ /**
14
+ * Thrown for general API errors (non-2xx responses other than auth errors).
15
+ */
16
+ export declare class ApiError extends Error {
17
+ readonly statusCode?: number;
18
+ constructor(message: string, statusCode?: number);
19
+ }
20
+ /**
21
+ * Thrown when the local proxy server fails to start.
22
+ */
23
+ export declare class ProxyStartError extends Error {
24
+ constructor(message?: string);
25
+ }
@@ -0,0 +1,5 @@
1
+ export { AluviaClient } from './client/AluviaClient.js';
2
+ export { AluviaApi } from './api/AluviaApi.js';
3
+ export { MissingApiKeyError, InvalidApiKeyError, ApiError, ProxyStartError, } from './errors.js';
4
+ export type { GatewayProtocol, LogLevel, AluviaClientOptions, AluviaClientConnection, PlaywrightProxySettings, } from './client/types.js';
5
+ export type { Account, AccountUsage, AccountPayment, AccountConnection, AccountConnectionDeleteResult, Geo, SuccessEnvelope, ErrorEnvelope, Envelope, } from './api/types.js';
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "@aluvia/sdk",
3
+ "version": "1.0.0",
4
+ "description": "Aluvia SDK for Node.js - local smart proxy for automation workloads and AI agents",
5
+ "license": "MIT",
6
+ "author": "Aluvia",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/aluvia-connect/sdk-node.git"
10
+ },
11
+ "homepage": "https://aluvia.io",
12
+ "bugs": {
13
+ "url": "https://github.com/aluvia-connect/sdk-node/issues"
14
+ },
15
+ "type": "module",
16
+ "main": "./dist/cjs/index.js",
17
+ "module": "./dist/esm/index.js",
18
+ "types": "./dist/types/index.d.ts",
19
+ "exports": {
20
+ ".": {
21
+ "types": "./dist/types/index.d.ts",
22
+ "import": "./dist/esm/index.js",
23
+ "require": "./dist/cjs/index.js"
24
+ },
25
+ "./package.json": "./package.json"
26
+ },
27
+ "files": [
28
+ "dist/**/*",
29
+ "README.md",
30
+ "LICENSE"
31
+ ],
32
+ "scripts": {
33
+ "build": "tsc -p tsconfig.esm.json && tsc -p tsconfig.cjs.json && node -e \"require('fs').mkdirSync('dist/cjs',{recursive:true});require('fs').writeFileSync('dist/cjs/package.json','{\\\"type\\\":\\\"commonjs\\\"}')\"",
34
+ "prepare": "npm run build",
35
+ "test": "node --import tsx --test test/integration.test.ts",
36
+ "lint": "prettier --check src test",
37
+ "lint:fix": "prettier --write src test"
38
+ },
39
+ "publishConfig": {
40
+ "access": "public"
41
+ },
42
+ "engines": {
43
+ "node": ">=18"
44
+ },
45
+ "keywords": [
46
+ "proxy",
47
+ "ai-agent",
48
+ "playwright",
49
+ "puppeteer",
50
+ "aluvia"
51
+ ],
52
+ "devDependencies": {
53
+ "@types/node": "^24.10.2",
54
+ "axios": "^1.13.2",
55
+ "prettier": "^3.4.2",
56
+ "tsx": "^4.21.0",
57
+ "typescript": "^5.9.3"
58
+ },
59
+ "dependencies": {
60
+ "http-proxy-agent": "^7.0.2",
61
+ "https-proxy-agent": "^7.0.6",
62
+ "proxy-chain": "^2.6.1",
63
+ "undici": "^6.22.0"
64
+ }
65
+ }