@push.rocks/smartproxy 26.3.0 → 27.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 (57) hide show
  1. package/changelog.md +7 -0
  2. package/dist_rust/rustproxy_linux_amd64 +0 -0
  3. package/dist_rust/rustproxy_linux_arm64 +0 -0
  4. package/dist_ts/00_commitinfo_data.js +1 -1
  5. package/dist_ts/core/models/wrapped-socket.js +4 -1
  6. package/dist_ts/core/routing/route-manager.js +9 -7
  7. package/dist_ts/proxies/smart-proxy/datagram-handler-server.js +7 -5
  8. package/dist_ts/proxies/smart-proxy/route-preprocessor.js +6 -8
  9. package/dist_ts/proxies/smart-proxy/rust-metrics-adapter.js +186 -184
  10. package/dist_ts/proxies/smart-proxy/rust-proxy-bridge.js +2 -1
  11. package/dist_ts/proxies/smart-proxy/smart-proxy.js +12 -6
  12. package/dist_ts/proxies/smart-proxy/socket-handler-server.js +5 -3
  13. package/dist_ts/proxies/smart-proxy/utils/concurrency-semaphore.js +4 -3
  14. package/dist_ts/proxies/smart-proxy/utils/index.d.ts +2 -3
  15. package/dist_ts/proxies/smart-proxy/utils/index.js +4 -6
  16. package/dist_ts/proxies/smart-proxy/utils/mutex.js +3 -5
  17. package/dist_ts/proxies/smart-proxy/utils/route-validator.js +7 -7
  18. package/dist_ts/proxies/smart-proxy/utils/{route-helpers/socket-handlers.d.ts → socket-handlers.d.ts} +2 -10
  19. package/dist_ts/proxies/smart-proxy/utils/socket-handlers.js +268 -0
  20. package/dist_ts/routing/models/http-types.js +5 -1
  21. package/package.json +1 -1
  22. package/readme.hints.md +42 -20
  23. package/readme.md +144 -146
  24. package/ts/00_commitinfo_data.ts +1 -1
  25. package/ts/proxies/smart-proxy/utils/index.ts +3 -11
  26. package/ts/proxies/smart-proxy/utils/{route-helpers/socket-handlers.ts → socket-handlers.ts} +3 -31
  27. package/dist_ts/proxies/smart-proxy/utils/route-helpers/api-helpers.d.ts +0 -49
  28. package/dist_ts/proxies/smart-proxy/utils/route-helpers/api-helpers.js +0 -108
  29. package/dist_ts/proxies/smart-proxy/utils/route-helpers/dynamic-helpers.d.ts +0 -57
  30. package/dist_ts/proxies/smart-proxy/utils/route-helpers/dynamic-helpers.js +0 -90
  31. package/dist_ts/proxies/smart-proxy/utils/route-helpers/http-helpers.d.ts +0 -17
  32. package/dist_ts/proxies/smart-proxy/utils/route-helpers/http-helpers.js +0 -32
  33. package/dist_ts/proxies/smart-proxy/utils/route-helpers/https-helpers.d.ts +0 -68
  34. package/dist_ts/proxies/smart-proxy/utils/route-helpers/https-helpers.js +0 -117
  35. package/dist_ts/proxies/smart-proxy/utils/route-helpers/index.d.ts +0 -17
  36. package/dist_ts/proxies/smart-proxy/utils/route-helpers/index.js +0 -27
  37. package/dist_ts/proxies/smart-proxy/utils/route-helpers/load-balancer-helpers.d.ts +0 -63
  38. package/dist_ts/proxies/smart-proxy/utils/route-helpers/load-balancer-helpers.js +0 -105
  39. package/dist_ts/proxies/smart-proxy/utils/route-helpers/nftables-helpers.d.ts +0 -83
  40. package/dist_ts/proxies/smart-proxy/utils/route-helpers/nftables-helpers.js +0 -126
  41. package/dist_ts/proxies/smart-proxy/utils/route-helpers/security-helpers.d.ts +0 -47
  42. package/dist_ts/proxies/smart-proxy/utils/route-helpers/security-helpers.js +0 -66
  43. package/dist_ts/proxies/smart-proxy/utils/route-helpers/socket-handlers.js +0 -286
  44. package/dist_ts/proxies/smart-proxy/utils/route-helpers/websocket-helpers.d.ts +0 -46
  45. package/dist_ts/proxies/smart-proxy/utils/route-helpers/websocket-helpers.js +0 -67
  46. package/dist_ts/proxies/smart-proxy/utils/route-helpers.d.ts +0 -9
  47. package/dist_ts/proxies/smart-proxy/utils/route-helpers.js +0 -11
  48. package/ts/proxies/smart-proxy/utils/route-helpers/api-helpers.ts +0 -144
  49. package/ts/proxies/smart-proxy/utils/route-helpers/dynamic-helpers.ts +0 -125
  50. package/ts/proxies/smart-proxy/utils/route-helpers/http-helpers.ts +0 -40
  51. package/ts/proxies/smart-proxy/utils/route-helpers/https-helpers.ts +0 -163
  52. package/ts/proxies/smart-proxy/utils/route-helpers/index.ts +0 -62
  53. package/ts/proxies/smart-proxy/utils/route-helpers/load-balancer-helpers.ts +0 -154
  54. package/ts/proxies/smart-proxy/utils/route-helpers/nftables-helpers.ts +0 -202
  55. package/ts/proxies/smart-proxy/utils/route-helpers/security-helpers.ts +0 -96
  56. package/ts/proxies/smart-proxy/utils/route-helpers/websocket-helpers.ts +0 -98
  57. package/ts/proxies/smart-proxy/utils/route-helpers.ts +0 -11
@@ -1,154 +0,0 @@
1
- /**
2
- * Load Balancer Route Helper Functions
3
- *
4
- * This module provides utility functions for creating load balancer route configurations.
5
- */
6
-
7
- import type { IRouteConfig, IRouteMatch, IRouteAction, IRouteTarget, TPortRange, IRouteContext } from '../../models/route-types.js';
8
-
9
- /**
10
- * Create a load balancer route (round-robin between multiple backend hosts)
11
- * @param domains Domain(s) to match
12
- * @param backendsOrHosts Array of backend servers OR array of host strings (legacy)
13
- * @param portOrOptions Port number (legacy) OR options object
14
- * @param options Additional route options (legacy)
15
- * @returns Route configuration object
16
- */
17
- export function createLoadBalancerRoute(
18
- domains: string | string[],
19
- backendsOrHosts: Array<{ host: string; port: number }> | string[],
20
- portOrOptions?: number | {
21
- tls?: {
22
- mode: 'passthrough' | 'terminate' | 'terminate-and-reencrypt';
23
- certificate?: 'auto' | { key: string; cert: string };
24
- };
25
- useTls?: boolean;
26
- certificate?: 'auto' | { key: string; cert: string };
27
- algorithm?: 'round-robin' | 'least-connections' | 'ip-hash';
28
- healthCheck?: {
29
- path: string;
30
- interval: number;
31
- timeout: number;
32
- unhealthyThreshold: number;
33
- healthyThreshold: number;
34
- };
35
- [key: string]: any;
36
- },
37
- options?: {
38
- tls?: {
39
- mode: 'passthrough' | 'terminate' | 'terminate-and-reencrypt';
40
- certificate?: 'auto' | { key: string; cert: string };
41
- };
42
- [key: string]: any;
43
- }
44
- ): IRouteConfig {
45
- // Handle legacy signature: (domains, hosts[], port, options)
46
- let backends: Array<{ host: string; port: number }>;
47
- let finalOptions: any;
48
-
49
- if (Array.isArray(backendsOrHosts) && backendsOrHosts.length > 0 && typeof backendsOrHosts[0] === 'string') {
50
- // Legacy signature
51
- const hosts = backendsOrHosts as string[];
52
- const port = portOrOptions as number;
53
- backends = hosts.map(host => ({ host, port }));
54
- finalOptions = options || {};
55
- } else {
56
- // New signature
57
- backends = backendsOrHosts as Array<{ host: string; port: number }>;
58
- finalOptions = (portOrOptions as any) || {};
59
- }
60
-
61
- // Extract hosts and ensure all backends use the same port
62
- const port = backends[0].port;
63
- const hosts = backends.map(backend => backend.host);
64
-
65
- // Create route match
66
- const match: IRouteMatch = {
67
- ports: finalOptions.match?.ports || (finalOptions.tls || finalOptions.useTls ? 443 : 80),
68
- domains
69
- };
70
-
71
- // Create route target
72
- const target: IRouteTarget = {
73
- host: hosts,
74
- port
75
- };
76
-
77
- // Create route action
78
- const action: IRouteAction = {
79
- type: 'forward',
80
- targets: [target]
81
- };
82
-
83
- // Add TLS configuration if provided
84
- if (finalOptions.tls || finalOptions.useTls) {
85
- action.tls = {
86
- mode: finalOptions.tls?.mode || 'terminate',
87
- certificate: finalOptions.tls?.certificate || finalOptions.certificate || 'auto'
88
- };
89
- }
90
-
91
- // Add load balancing options
92
- if (finalOptions.algorithm || finalOptions.healthCheck) {
93
- action.loadBalancing = {
94
- algorithm: finalOptions.algorithm || 'round-robin',
95
- healthCheck: finalOptions.healthCheck
96
- };
97
- }
98
-
99
- // Create the route config
100
- return {
101
- match,
102
- action,
103
- name: finalOptions.name || `Load Balancer for ${Array.isArray(domains) ? domains.join(', ') : domains}`,
104
- ...finalOptions
105
- };
106
- }
107
-
108
- /**
109
- * Create a smart load balancer with dynamic domain-based backend selection
110
- * @param options Smart load balancer options
111
- * @returns Route configuration object
112
- */
113
- export function createSmartLoadBalancer(options: {
114
- ports: TPortRange;
115
- domainTargets: Record<string, string | string[]>;
116
- portMapper: (context: IRouteContext) => number;
117
- name?: string;
118
- defaultTarget?: string | string[];
119
- priority?: number;
120
- [key: string]: any;
121
- }): IRouteConfig {
122
- // Extract all domain keys to create the match criteria
123
- const domains = Object.keys(options.domainTargets);
124
-
125
- // Create the smart host selector function
126
- const hostSelector = (context: IRouteContext) => {
127
- const domain = context.domain || '';
128
- return options.domainTargets[domain] || options.defaultTarget || 'localhost';
129
- };
130
-
131
- // Create route match
132
- const match: IRouteMatch = {
133
- ports: options.ports,
134
- domains
135
- };
136
-
137
- // Create route action
138
- const action: IRouteAction = {
139
- type: 'forward',
140
- targets: [{
141
- host: hostSelector,
142
- port: options.portMapper
143
- }]
144
- };
145
-
146
- // Create the route config
147
- return {
148
- match,
149
- action,
150
- name: options.name || `Smart Load Balancer for ${domains.join(', ')}`,
151
- priority: options.priority,
152
- ...options
153
- };
154
- }
@@ -1,202 +0,0 @@
1
- /**
2
- * NFTables Route Helper Functions
3
- *
4
- * This module provides utility functions for creating NFTables-based route configurations
5
- * for high-performance packet forwarding at the kernel level.
6
- */
7
-
8
- import type { IRouteConfig, IRouteMatch, IRouteAction, TPortRange } from '../../models/route-types.js';
9
- import { createHttpToHttpsRedirect } from './https-helpers.js';
10
-
11
- /**
12
- * Create an NFTables-based route for high-performance packet forwarding
13
- * @param nameOrDomains Name or domain(s) to match
14
- * @param target Target host and port
15
- * @param options Additional route options
16
- * @returns Route configuration object
17
- */
18
- export function createNfTablesRoute(
19
- nameOrDomains: string | string[],
20
- target: { host: string; port: number | 'preserve' },
21
- options: {
22
- ports?: TPortRange;
23
- protocol?: 'tcp' | 'udp' | 'all';
24
- preserveSourceIP?: boolean;
25
- ipAllowList?: string[];
26
- ipBlockList?: string[];
27
- maxRate?: string;
28
- priority?: number;
29
- useTls?: boolean;
30
- tableName?: string;
31
- useIPSets?: boolean;
32
- useAdvancedNAT?: boolean;
33
- } = {}
34
- ): IRouteConfig {
35
- // Determine if this is a name or domain
36
- let name: string;
37
- let domains: string | string[] | undefined;
38
-
39
- if (Array.isArray(nameOrDomains) || (typeof nameOrDomains === 'string' && nameOrDomains.includes('.'))) {
40
- domains = nameOrDomains;
41
- name = Array.isArray(nameOrDomains) ? nameOrDomains[0] : nameOrDomains;
42
- } else {
43
- name = nameOrDomains;
44
- domains = undefined; // No domains
45
- }
46
-
47
- // Create route match
48
- const match: IRouteMatch = {
49
- domains,
50
- ports: options.ports || 80
51
- };
52
-
53
- // Create route action
54
- const action: IRouteAction = {
55
- type: 'forward',
56
- targets: [{
57
- host: target.host,
58
- port: target.port
59
- }],
60
- forwardingEngine: 'nftables',
61
- nftables: {
62
- protocol: options.protocol || 'tcp',
63
- preserveSourceIP: options.preserveSourceIP,
64
- maxRate: options.maxRate,
65
- priority: options.priority,
66
- tableName: options.tableName,
67
- useIPSets: options.useIPSets,
68
- useAdvancedNAT: options.useAdvancedNAT
69
- }
70
- };
71
-
72
- // Add TLS options if needed
73
- if (options.useTls) {
74
- action.tls = {
75
- mode: 'passthrough'
76
- };
77
- }
78
-
79
- // Create the route config
80
- const routeConfig: IRouteConfig = {
81
- name,
82
- match,
83
- action
84
- };
85
-
86
- // Add security if allowed or blocked IPs are specified
87
- if (options.ipAllowList?.length || options.ipBlockList?.length) {
88
- routeConfig.security = {
89
- ipAllowList: options.ipAllowList,
90
- ipBlockList: options.ipBlockList
91
- };
92
- }
93
-
94
- return routeConfig;
95
- }
96
-
97
- /**
98
- * Create an NFTables-based TLS termination route
99
- * @param nameOrDomains Name or domain(s) to match
100
- * @param target Target host and port
101
- * @param options Additional route options
102
- * @returns Route configuration object
103
- */
104
- export function createNfTablesTerminateRoute(
105
- nameOrDomains: string | string[],
106
- target: { host: string; port: number | 'preserve' },
107
- options: {
108
- ports?: TPortRange;
109
- protocol?: 'tcp' | 'udp' | 'all';
110
- preserveSourceIP?: boolean;
111
- ipAllowList?: string[];
112
- ipBlockList?: string[];
113
- maxRate?: string;
114
- priority?: number;
115
- tableName?: string;
116
- useIPSets?: boolean;
117
- useAdvancedNAT?: boolean;
118
- certificate?: 'auto' | { key: string; cert: string };
119
- } = {}
120
- ): IRouteConfig {
121
- // Create basic NFTables route
122
- const route = createNfTablesRoute(
123
- nameOrDomains,
124
- target,
125
- {
126
- ...options,
127
- ports: options.ports || 443,
128
- useTls: false
129
- }
130
- );
131
-
132
- // Set TLS termination
133
- route.action.tls = {
134
- mode: 'terminate',
135
- certificate: options.certificate || 'auto'
136
- };
137
-
138
- return route;
139
- }
140
-
141
- /**
142
- * Create a complete NFTables-based HTTPS setup with HTTP redirect
143
- * @param nameOrDomains Name or domain(s) to match
144
- * @param target Target host and port
145
- * @param options Additional route options
146
- * @returns Array of two route configurations (HTTPS and HTTP redirect)
147
- */
148
- export function createCompleteNfTablesHttpsServer(
149
- nameOrDomains: string | string[],
150
- target: { host: string; port: number | 'preserve' },
151
- options: {
152
- httpPort?: TPortRange;
153
- httpsPort?: TPortRange;
154
- protocol?: 'tcp' | 'udp' | 'all';
155
- preserveSourceIP?: boolean;
156
- ipAllowList?: string[];
157
- ipBlockList?: string[];
158
- maxRate?: string;
159
- priority?: number;
160
- tableName?: string;
161
- useIPSets?: boolean;
162
- useAdvancedNAT?: boolean;
163
- certificate?: 'auto' | { key: string; cert: string };
164
- } = {}
165
- ): IRouteConfig[] {
166
- // Create the HTTPS route using NFTables
167
- const httpsRoute = createNfTablesTerminateRoute(
168
- nameOrDomains,
169
- target,
170
- {
171
- ...options,
172
- ports: options.httpsPort || 443
173
- }
174
- );
175
-
176
- // Determine the domain(s) for HTTP redirect
177
- const domains = typeof nameOrDomains === 'string' && !nameOrDomains.includes('.')
178
- ? undefined
179
- : nameOrDomains;
180
-
181
- // Extract the HTTPS port for the redirect destination
182
- const httpsPort = typeof options.httpsPort === 'number'
183
- ? options.httpsPort
184
- : Array.isArray(options.httpsPort) && typeof options.httpsPort[0] === 'number'
185
- ? options.httpsPort[0]
186
- : 443;
187
-
188
- // Create the HTTP redirect route (this uses standard forwarding, not NFTables)
189
- const httpRedirectRoute = createHttpToHttpsRedirect(
190
- domains as any, // Type cast needed since domains can be undefined now
191
- httpsPort,
192
- {
193
- match: {
194
- ports: options.httpPort || 80,
195
- domains: domains as any // Type cast needed since domains can be undefined now
196
- },
197
- name: `HTTP to HTTPS Redirect for ${Array.isArray(domains) ? domains.join(', ') : domains || 'all domains'}`
198
- }
199
- );
200
-
201
- return [httpsRoute, httpRedirectRoute];
202
- }
@@ -1,96 +0,0 @@
1
- /**
2
- * Security Route Helper Functions
3
- *
4
- * This module provides utility functions for adding security features to routes.
5
- */
6
-
7
- import type { IRouteConfig } from '../../models/route-types.js';
8
- import { mergeRouteConfigs } from '../route-utils.js';
9
-
10
- /**
11
- * Create a rate limiting route pattern
12
- * @param baseRoute Base route to add rate limiting to
13
- * @param rateLimit Rate limiting configuration
14
- * @returns Route with rate limiting
15
- */
16
- export function addRateLimiting(
17
- baseRoute: IRouteConfig,
18
- rateLimit: {
19
- maxRequests: number;
20
- window: number; // Time window in seconds
21
- keyBy?: 'ip' | 'path' | 'header';
22
- headerName?: string; // Required if keyBy is 'header'
23
- errorMessage?: string;
24
- }
25
- ): IRouteConfig {
26
- return mergeRouteConfigs(baseRoute, {
27
- security: {
28
- rateLimit: {
29
- enabled: true,
30
- maxRequests: rateLimit.maxRequests,
31
- window: rateLimit.window,
32
- keyBy: rateLimit.keyBy || 'ip',
33
- headerName: rateLimit.headerName,
34
- errorMessage: rateLimit.errorMessage || 'Rate limit exceeded. Please try again later.'
35
- }
36
- }
37
- });
38
- }
39
-
40
- /**
41
- * Create a basic authentication route pattern
42
- * @param baseRoute Base route to add authentication to
43
- * @param auth Authentication configuration
44
- * @returns Route with basic authentication
45
- */
46
- export function addBasicAuth(
47
- baseRoute: IRouteConfig,
48
- auth: {
49
- users: Array<{ username: string; password: string }>;
50
- realm?: string;
51
- excludePaths?: string[];
52
- }
53
- ): IRouteConfig {
54
- return mergeRouteConfigs(baseRoute, {
55
- security: {
56
- basicAuth: {
57
- enabled: true,
58
- users: auth.users,
59
- realm: auth.realm || 'Restricted Area',
60
- excludePaths: auth.excludePaths || []
61
- }
62
- }
63
- });
64
- }
65
-
66
- /**
67
- * Create a JWT authentication route pattern
68
- * @param baseRoute Base route to add JWT authentication to
69
- * @param jwt JWT authentication configuration
70
- * @returns Route with JWT authentication
71
- */
72
- export function addJwtAuth(
73
- baseRoute: IRouteConfig,
74
- jwt: {
75
- secret: string;
76
- algorithm?: string;
77
- issuer?: string;
78
- audience?: string;
79
- expiresIn?: number; // Time in seconds
80
- excludePaths?: string[];
81
- }
82
- ): IRouteConfig {
83
- return mergeRouteConfigs(baseRoute, {
84
- security: {
85
- jwtAuth: {
86
- enabled: true,
87
- secret: jwt.secret,
88
- algorithm: jwt.algorithm || 'HS256',
89
- issuer: jwt.issuer,
90
- audience: jwt.audience,
91
- expiresIn: jwt.expiresIn,
92
- excludePaths: jwt.excludePaths || []
93
- }
94
- }
95
- });
96
- }
@@ -1,98 +0,0 @@
1
- /**
2
- * WebSocket Route Helper Functions
3
- *
4
- * This module provides utility functions for creating WebSocket route configurations.
5
- */
6
-
7
- import type { IRouteConfig, IRouteMatch, IRouteAction } from '../../models/route-types.js';
8
-
9
- /**
10
- * Create a WebSocket route configuration
11
- * @param domains Domain(s) to match
12
- * @param targetOrPath Target server OR WebSocket path (legacy)
13
- * @param targetOrOptions Target server (legacy) OR options
14
- * @param options Additional route options (legacy)
15
- * @returns Route configuration object
16
- */
17
- export function createWebSocketRoute(
18
- domains: string | string[],
19
- targetOrPath: { host: string | string[]; port: number } | string,
20
- targetOrOptions?: { host: string | string[]; port: number } | {
21
- useTls?: boolean;
22
- certificate?: 'auto' | { key: string; cert: string };
23
- path?: string;
24
- httpPort?: number | number[];
25
- httpsPort?: number | number[];
26
- pingInterval?: number;
27
- pingTimeout?: number;
28
- name?: string;
29
- [key: string]: any;
30
- },
31
- options?: {
32
- useTls?: boolean;
33
- certificate?: 'auto' | { key: string; cert: string };
34
- httpPort?: number | number[];
35
- httpsPort?: number | number[];
36
- pingInterval?: number;
37
- pingTimeout?: number;
38
- name?: string;
39
- [key: string]: any;
40
- }
41
- ): IRouteConfig {
42
- // Handle different signatures
43
- let target: { host: string | string[]; port: number };
44
- let wsPath: string;
45
- let finalOptions: any;
46
-
47
- if (typeof targetOrPath === 'string') {
48
- // Legacy signature: (domains, path, target, options)
49
- wsPath = targetOrPath;
50
- target = targetOrOptions as { host: string | string[]; port: number };
51
- finalOptions = options || {};
52
- } else {
53
- // New signature: (domains, target, options)
54
- target = targetOrPath;
55
- finalOptions = (targetOrOptions as any) || {};
56
- wsPath = finalOptions.path || '/ws';
57
- }
58
-
59
- // Normalize WebSocket path
60
- const normalizedPath = wsPath.startsWith('/') ? wsPath : `/${wsPath}`;
61
-
62
- // Create route match
63
- const match: IRouteMatch = {
64
- ports: finalOptions.useTls
65
- ? (finalOptions.httpsPort || 443)
66
- : (finalOptions.httpPort || 80),
67
- domains,
68
- path: normalizedPath
69
- };
70
-
71
- // Create route action
72
- const action: IRouteAction = {
73
- type: 'forward',
74
- targets: [target],
75
- websocket: {
76
- enabled: true,
77
- pingInterval: finalOptions.pingInterval || 30000, // 30 seconds
78
- pingTimeout: finalOptions.pingTimeout || 5000 // 5 seconds
79
- }
80
- };
81
-
82
- // Add TLS configuration if using HTTPS
83
- if (finalOptions.useTls) {
84
- action.tls = {
85
- mode: 'terminate',
86
- certificate: finalOptions.certificate || 'auto'
87
- };
88
- }
89
-
90
- // Create the route config
91
- return {
92
- match,
93
- action,
94
- name: finalOptions.name || `WebSocket Route ${normalizedPath} for ${Array.isArray(domains) ? domains.join(', ') : domains}`,
95
- priority: finalOptions.priority || 100, // Higher priority for WebSocket routes
96
- ...finalOptions
97
- };
98
- }
@@ -1,11 +0,0 @@
1
- /**
2
- * Route Helper Functions
3
- *
4
- * This file re-exports all route helper functions for backwards compatibility.
5
- * The actual implementations have been split into focused modules in the route-helpers/ directory.
6
- *
7
- * @see ./route-helpers/index.ts for the modular exports
8
- */
9
-
10
- // Re-export everything from the modular helpers
11
- export * from './route-helpers/index.js';