anz-legislation 1.2.1
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 +23 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.js +198 -0
- package/dist/client.d.ts +84 -0
- package/dist/client.js +492 -0
- package/dist/commands/batch.d.ts +5 -0
- package/dist/commands/batch.js +121 -0
- package/dist/commands/cache.d.ts +5 -0
- package/dist/commands/cache.js +43 -0
- package/dist/commands/cite.d.ts +5 -0
- package/dist/commands/cite.js +68 -0
- package/dist/commands/config.d.ts +5 -0
- package/dist/commands/config.js +56 -0
- package/dist/commands/export.d.ts +8 -0
- package/dist/commands/export.js +169 -0
- package/dist/commands/generate.d.ts +10 -0
- package/dist/commands/generate.js +320 -0
- package/dist/commands/get.d.ts +5 -0
- package/dist/commands/get.js +99 -0
- package/dist/commands/help.d.ts +13 -0
- package/dist/commands/help.js +298 -0
- package/dist/commands/search.d.ts +5 -0
- package/dist/commands/search.js +96 -0
- package/dist/commands/stream.d.ts +5 -0
- package/dist/commands/stream.js +100 -0
- package/dist/config.d.ts +81 -0
- package/dist/config.js +209 -0
- package/dist/errors.d.ts +108 -0
- package/dist/errors.js +173 -0
- package/dist/mcp/server.d.ts +13 -0
- package/dist/mcp/server.js +428 -0
- package/dist/mcp-cli.d.ts +6 -0
- package/dist/mcp-cli.js +37 -0
- package/dist/models/canonical.d.ts +423 -0
- package/dist/models/canonical.js +92 -0
- package/dist/models/index.d.ts +892 -0
- package/dist/models/index.js +223 -0
- package/dist/output/index.d.ts +34 -0
- package/dist/output/index.js +195 -0
- package/dist/output/legal-metadata-publication.d.ts +18 -0
- package/dist/output/legal-metadata-publication.js +23 -0
- package/dist/providers/canonical-metadata.d.ts +3 -0
- package/dist/providers/canonical-metadata.js +202 -0
- package/dist/providers/commonwealth-provider.d.ts +27 -0
- package/dist/providers/commonwealth-provider.js +81 -0
- package/dist/providers/index.d.ts +20 -0
- package/dist/providers/index.js +27 -0
- package/dist/providers/legislation-provider.d.ts +227 -0
- package/dist/providers/legislation-provider.js +308 -0
- package/dist/providers/nz-provider.d.ts +36 -0
- package/dist/providers/nz-provider.js +130 -0
- package/dist/providers/output-adapters.d.ts +14 -0
- package/dist/providers/output-adapters.js +116 -0
- package/dist/providers/plugin-discovery.d.ts +39 -0
- package/dist/providers/plugin-discovery.js +91 -0
- package/dist/providers/plugin-loader.d.ts +86 -0
- package/dist/providers/plugin-loader.js +219 -0
- package/dist/providers/queensland-provider.d.ts +42 -0
- package/dist/providers/queensland-provider.js +105 -0
- package/dist/utils/api-optimization.d.ts +92 -0
- package/dist/utils/api-optimization.js +276 -0
- package/dist/utils/batch.d.ts +110 -0
- package/dist/utils/batch.js +269 -0
- package/dist/utils/branded-types.d.ts +0 -0
- package/dist/utils/branded-types.js +1 -0
- package/dist/utils/compatibility-matrix.d.ts +89 -0
- package/dist/utils/compatibility-matrix.js +214 -0
- package/dist/utils/config-validator.d.ts +39 -0
- package/dist/utils/config-validator.js +197 -0
- package/dist/utils/env-loader.d.ts +55 -0
- package/dist/utils/env-loader.js +77 -0
- package/dist/utils/health-monitor.d.ts +93 -0
- package/dist/utils/health-monitor.js +209 -0
- package/dist/utils/invocation.d.ts +4 -0
- package/dist/utils/invocation.js +33 -0
- package/dist/utils/logger.d.ts +94 -0
- package/dist/utils/logger.js +220 -0
- package/dist/utils/plugin-marketplace.d.ts +77 -0
- package/dist/utils/plugin-marketplace.js +191 -0
- package/dist/utils/presentation.d.ts +2 -0
- package/dist/utils/presentation.js +32 -0
- package/dist/utils/rate-limiter.d.ts +100 -0
- package/dist/utils/rate-limiter.js +256 -0
- package/dist/utils/scraper-cache.d.ts +115 -0
- package/dist/utils/scraper-cache.js +229 -0
- package/dist/utils/secure-config.d.ts +40 -0
- package/dist/utils/secure-config.js +195 -0
- package/dist/utils/streaming.d.ts +121 -0
- package/dist/utils/streaming.js +333 -0
- package/dist/utils/validation.d.ts +190 -0
- package/dist/utils/validation.js +209 -0
- package/dist/utils/version.d.ts +13 -0
- package/dist/utils/version.js +46 -0
- package/package.json +56 -0
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin Loader
|
|
3
|
+
*
|
|
4
|
+
* Dynamically loads and registers jurisdiction plugins.
|
|
5
|
+
* Supports both official and community plugins.
|
|
6
|
+
*/
|
|
7
|
+
import { ProviderRegistry } from '../providers/legislation-provider.js';
|
|
8
|
+
import { CompatibilityMatrix } from '../utils/compatibility-matrix.js';
|
|
9
|
+
export class PluginLoader {
|
|
10
|
+
registry;
|
|
11
|
+
compatibilityMatrix;
|
|
12
|
+
loadedPlugins = new Map();
|
|
13
|
+
coreVersion;
|
|
14
|
+
constructor(coreVersion, registry) {
|
|
15
|
+
this.coreVersion = coreVersion;
|
|
16
|
+
this.registry = registry ?? new ProviderRegistry();
|
|
17
|
+
this.compatibilityMatrix = new CompatibilityMatrix(coreVersion);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Load a plugin from path
|
|
21
|
+
*/
|
|
22
|
+
async loadPlugin(pluginPath) {
|
|
23
|
+
try {
|
|
24
|
+
// Import plugin module
|
|
25
|
+
const module = await import(pluginPath);
|
|
26
|
+
// Get manifest
|
|
27
|
+
const manifest = module.default?.manifest ?? module.manifest;
|
|
28
|
+
if (!manifest) {
|
|
29
|
+
throw new Error('Plugin manifest not found');
|
|
30
|
+
}
|
|
31
|
+
// Verify plugin integrity (trust official plugins, warn on community)
|
|
32
|
+
if (manifest.pluginType === 'community') {
|
|
33
|
+
console.warn(`⚠️ Loading community plugin: ${manifest.name}. Ensure you trust the source.`);
|
|
34
|
+
}
|
|
35
|
+
// Check compatibility
|
|
36
|
+
this.compatibilityMatrix.register({
|
|
37
|
+
name: manifest.name,
|
|
38
|
+
version: manifest.version,
|
|
39
|
+
requires: {
|
|
40
|
+
core: manifest.peerDependencies['nz-legislation-tool'] ?? '*',
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
if (!this.compatibilityMatrix.check(manifest.name, manifest.version)) {
|
|
44
|
+
throw new Error(`Plugin ${manifest.name}@${manifest.version} is not compatible with core v${this.coreVersion}`);
|
|
45
|
+
}
|
|
46
|
+
// Get provider class and instantiate
|
|
47
|
+
const ProviderClass = module[manifest.provider] ?? module.default;
|
|
48
|
+
if (!ProviderClass) {
|
|
49
|
+
throw new Error(`Provider class "${manifest.provider}" not found in plugin`);
|
|
50
|
+
}
|
|
51
|
+
const provider = new ProviderClass();
|
|
52
|
+
// Verify provider implements interface
|
|
53
|
+
if (!this.isValidProvider(provider)) {
|
|
54
|
+
throw new Error('Plugin does not implement LegislationProvider interface');
|
|
55
|
+
}
|
|
56
|
+
// Register provider
|
|
57
|
+
this.registry.register(provider);
|
|
58
|
+
// Store loaded plugin
|
|
59
|
+
const loadedPlugin = {
|
|
60
|
+
manifest,
|
|
61
|
+
provider,
|
|
62
|
+
loaded: true,
|
|
63
|
+
};
|
|
64
|
+
this.loadedPlugins.set(manifest.name, loadedPlugin);
|
|
65
|
+
console.log(`✅ Plugin loaded: ${manifest.name}@${manifest.version}`);
|
|
66
|
+
return loadedPlugin;
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
const loadedPlugin = {
|
|
70
|
+
manifest: {
|
|
71
|
+
name: pluginPath,
|
|
72
|
+
version: 'unknown',
|
|
73
|
+
main: '',
|
|
74
|
+
provider: '',
|
|
75
|
+
peerDependencies: {},
|
|
76
|
+
pluginType: 'community',
|
|
77
|
+
pluginStatus: 'alpha',
|
|
78
|
+
},
|
|
79
|
+
provider: null,
|
|
80
|
+
loaded: false,
|
|
81
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
82
|
+
};
|
|
83
|
+
this.loadedPlugins.set(pluginPath, loadedPlugin);
|
|
84
|
+
console.error(`❌ Failed to load plugin: ${pluginPath}`);
|
|
85
|
+
console.error(` Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
86
|
+
return loadedPlugin;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Load multiple plugins in parallel
|
|
91
|
+
*/
|
|
92
|
+
async loadPlugins(pluginPaths) {
|
|
93
|
+
const results = await Promise.allSettled(pluginPaths.map(path => this.loadPlugin(path)));
|
|
94
|
+
return results
|
|
95
|
+
.filter((r) => r.status === 'fulfilled')
|
|
96
|
+
.map(r => r.value);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Auto-discover plugins from directory
|
|
100
|
+
*/
|
|
101
|
+
async discoverPlugins(directory) {
|
|
102
|
+
const plugins = [];
|
|
103
|
+
try {
|
|
104
|
+
const fs = await import('fs');
|
|
105
|
+
const path = await import('path');
|
|
106
|
+
if (!fs.existsSync(directory)) {
|
|
107
|
+
console.debug(`Plugin directory not found: ${directory}`);
|
|
108
|
+
return plugins;
|
|
109
|
+
}
|
|
110
|
+
const files = fs.readdirSync(directory);
|
|
111
|
+
for (const file of files) {
|
|
112
|
+
if (file.startsWith('@')) {
|
|
113
|
+
// Scoped package directory
|
|
114
|
+
const scopeDir = path.join(directory, file);
|
|
115
|
+
const scopedPlugins = await this.discoverPlugins(scopeDir);
|
|
116
|
+
plugins.push(...scopedPlugins.map(p => path.join(file, p)));
|
|
117
|
+
}
|
|
118
|
+
else if (file.startsWith('nz-legislation-') || file.startsWith('legislation-')) {
|
|
119
|
+
// Plugin directory
|
|
120
|
+
plugins.push(file);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
console.log(`🔍 Discovered ${plugins.length} potential plugins in ${directory}`);
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
console.error('Error discovering plugins:', error);
|
|
127
|
+
}
|
|
128
|
+
return plugins;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Get loaded plugin
|
|
132
|
+
*/
|
|
133
|
+
getPlugin(name) {
|
|
134
|
+
return this.loadedPlugins.get(name);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Get all loaded plugins
|
|
138
|
+
*/
|
|
139
|
+
getLoadedPlugins() {
|
|
140
|
+
return Array.from(this.loadedPlugins.values());
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Get registry
|
|
144
|
+
*/
|
|
145
|
+
getRegistry() {
|
|
146
|
+
return this.registry;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Get compatibility matrix
|
|
150
|
+
*/
|
|
151
|
+
getCompatibilityMatrix() {
|
|
152
|
+
return this.compatibilityMatrix;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Unload plugin
|
|
156
|
+
*/
|
|
157
|
+
unloadPlugin(name) {
|
|
158
|
+
const plugin = this.loadedPlugins.get(name);
|
|
159
|
+
if (plugin) {
|
|
160
|
+
// Note: In Node.js, we can't truly unload modules, but we can remove from registry
|
|
161
|
+
this.loadedPlugins.delete(name);
|
|
162
|
+
console.log(`Plugin unloaded: ${name}`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Get plugin status report
|
|
167
|
+
*/
|
|
168
|
+
getStatusReport() {
|
|
169
|
+
const plugins = this.getLoadedPlugins().map(p => ({
|
|
170
|
+
name: p.manifest.name,
|
|
171
|
+
version: p.manifest.version,
|
|
172
|
+
loaded: p.loaded,
|
|
173
|
+
error: p.error?.message,
|
|
174
|
+
}));
|
|
175
|
+
return {
|
|
176
|
+
coreVersion: this.coreVersion,
|
|
177
|
+
totalPlugins: plugins.length,
|
|
178
|
+
loaded: plugins.filter(p => p.loaded).length,
|
|
179
|
+
failed: plugins.filter(p => !p.loaded).length,
|
|
180
|
+
plugins,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Validate provider implements interface
|
|
185
|
+
*/
|
|
186
|
+
isValidProvider(obj) {
|
|
187
|
+
return (typeof obj.getJurisdiction === 'function' &&
|
|
188
|
+
typeof obj.getDisplayName === 'function' &&
|
|
189
|
+
typeof obj.search === 'function' &&
|
|
190
|
+
typeof obj.getWork === 'function' &&
|
|
191
|
+
typeof obj.healthCheck === 'function');
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Create global plugin loader instance
|
|
196
|
+
*/
|
|
197
|
+
let globalPluginLoader = null;
|
|
198
|
+
export function getGlobalPluginLoader(coreVersion) {
|
|
199
|
+
if (!globalPluginLoader) {
|
|
200
|
+
globalPluginLoader = new PluginLoader(coreVersion);
|
|
201
|
+
}
|
|
202
|
+
return globalPluginLoader;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* CLI helper for plugin status
|
|
206
|
+
*/
|
|
207
|
+
export function formatPluginStatus(report) {
|
|
208
|
+
const lines = [
|
|
209
|
+
`Plugin Status (Core v${report.coreVersion})`,
|
|
210
|
+
`Total: ${report.totalPlugins} | Loaded: ${report.loaded} | Failed: ${report.failed}`,
|
|
211
|
+
'',
|
|
212
|
+
];
|
|
213
|
+
for (const plugin of report.plugins) {
|
|
214
|
+
const icon = plugin.loaded ? '✅' : '❌';
|
|
215
|
+
const error = plugin.error ? ` - ${plugin.error}` : '';
|
|
216
|
+
lines.push(` ${icon} ${plugin.name}@${plugin.version}${error}`);
|
|
217
|
+
}
|
|
218
|
+
return lines.join('\n');
|
|
219
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Queensland Legislation Provider
|
|
3
|
+
*
|
|
4
|
+
* Provides access to Queensland legislation via the official API at
|
|
5
|
+
* https://api.legislation.qld.gov.au/
|
|
6
|
+
*/
|
|
7
|
+
import { BaseLegislationProvider } from './legislation-provider.js';
|
|
8
|
+
import type { SearchParams, SearchResults, Work, VersionSummary, CitationStyle } from './legislation-provider.js';
|
|
9
|
+
export declare class QueenslandProvider extends BaseLegislationProvider {
|
|
10
|
+
private baseUrl;
|
|
11
|
+
private apiKey?;
|
|
12
|
+
constructor(apiKey?: string);
|
|
13
|
+
/**
|
|
14
|
+
* Search Queensland legislation
|
|
15
|
+
*/
|
|
16
|
+
protected searchImpl(params: SearchParams): Promise<SearchResults>;
|
|
17
|
+
/**
|
|
18
|
+
* Get work by ID
|
|
19
|
+
*/
|
|
20
|
+
protected getWorkImpl(workId: string): Promise<Work>;
|
|
21
|
+
/**
|
|
22
|
+
* Get versions of a work
|
|
23
|
+
*/
|
|
24
|
+
protected getVersionsImpl(_workId: string): Promise<VersionSummary[]>;
|
|
25
|
+
/**
|
|
26
|
+
* Get specific version
|
|
27
|
+
*/
|
|
28
|
+
protected getVersionImpl(_versionId: string): Promise<Work>;
|
|
29
|
+
/**
|
|
30
|
+
* Health check
|
|
31
|
+
*/
|
|
32
|
+
healthCheck(): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Custom citation generation for Queensland
|
|
35
|
+
*/
|
|
36
|
+
getCitation(work: Work, style: CitationStyle): string;
|
|
37
|
+
/**
|
|
38
|
+
* Ensure API key is present for authenticated requests
|
|
39
|
+
*/
|
|
40
|
+
private ensureAuthenticated;
|
|
41
|
+
}
|
|
42
|
+
export default QueenslandProvider;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Queensland Legislation Provider
|
|
3
|
+
*
|
|
4
|
+
* Provides access to Queensland legislation via the official API at
|
|
5
|
+
* https://api.legislation.qld.gov.au/
|
|
6
|
+
*/
|
|
7
|
+
import { logger } from '../utils/logger.js';
|
|
8
|
+
import { BaseLegislationProvider } from './legislation-provider.js';
|
|
9
|
+
import { normalizeWorkType, parseWorkIdMetadata } from './output-adapters.js';
|
|
10
|
+
export class QueenslandProvider extends BaseLegislationProvider {
|
|
11
|
+
baseUrl = 'https://api.legislation.qld.gov.au/v1';
|
|
12
|
+
apiKey;
|
|
13
|
+
constructor(apiKey) {
|
|
14
|
+
super('au-qld', 'Queensland', { requests: 30, per: 60 }, // 30 requests per minute
|
|
15
|
+
{ max: 500, ttl: 24 * 60 * 60 * 1000 } // 500 entries, 24 hour TTL
|
|
16
|
+
);
|
|
17
|
+
this.apiKey = apiKey;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Search Queensland legislation
|
|
21
|
+
*/
|
|
22
|
+
searchImpl(params) {
|
|
23
|
+
this.ensureAuthenticated();
|
|
24
|
+
// Implementation for the official QLD API search is currently in development.
|
|
25
|
+
logger.debug('Searching Queensland legislation', { params });
|
|
26
|
+
return Promise.reject(new Error('Queensland search is currently in development. Please use direct ID retrieval with "nzlegislation get <id> --jurisdiction au-qld".'));
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Get work by ID
|
|
30
|
+
*/
|
|
31
|
+
getWorkImpl(workId) {
|
|
32
|
+
this.ensureAuthenticated();
|
|
33
|
+
// Implementation for retrieving a specific work from QLD API
|
|
34
|
+
// e.g., GET /v1/content('{id}')
|
|
35
|
+
const metadata = parseWorkIdMetadata(workId);
|
|
36
|
+
return Promise.resolve({
|
|
37
|
+
...metadata,
|
|
38
|
+
work_id: workId,
|
|
39
|
+
title: `${normalizeWorkType(metadata.type)} ${metadata.year} (Qld)`,
|
|
40
|
+
type: normalizeWorkType(metadata.type),
|
|
41
|
+
jurisdiction: 'au-qld',
|
|
42
|
+
status: 'in-force',
|
|
43
|
+
date: `${metadata.year || 1900}-01-01`,
|
|
44
|
+
url: `https://www.legislation.qld.gov.au/view/html/inforce/current/${workId.replace(/\//g, '-')}`,
|
|
45
|
+
versionCount: 1,
|
|
46
|
+
versions: [],
|
|
47
|
+
citations: {
|
|
48
|
+
australian: `${normalizeWorkType(metadata.type)} ${metadata.year} (Qld)`,
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Get versions of a work
|
|
54
|
+
*/
|
|
55
|
+
getVersionsImpl(_workId) {
|
|
56
|
+
this.ensureAuthenticated();
|
|
57
|
+
return Promise.resolve([]);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Get specific version
|
|
61
|
+
*/
|
|
62
|
+
getVersionImpl(_versionId) {
|
|
63
|
+
this.ensureAuthenticated();
|
|
64
|
+
return Promise.reject(new Error('Not implemented - scraper pending'));
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Health check
|
|
68
|
+
*/
|
|
69
|
+
async healthCheck() {
|
|
70
|
+
// Check if Queensland legislation API is accessible
|
|
71
|
+
const controller = new AbortController();
|
|
72
|
+
const timeoutId = setTimeout(() => controller.abort(), 5000);
|
|
73
|
+
try {
|
|
74
|
+
const response = await fetch(`${this.baseUrl}/health`, {
|
|
75
|
+
signal: controller.signal,
|
|
76
|
+
method: 'HEAD',
|
|
77
|
+
});
|
|
78
|
+
if (!response.ok && response.status !== 401) {
|
|
79
|
+
// 401 is fine for health check if we lack key
|
|
80
|
+
throw new Error(`Health check failed with status ${response.status}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
finally {
|
|
84
|
+
clearTimeout(timeoutId);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Custom citation generation for Queensland
|
|
89
|
+
*/
|
|
90
|
+
getCitation(work, style) {
|
|
91
|
+
if (style === 'australian') {
|
|
92
|
+
return `${work.title} (Qld)`;
|
|
93
|
+
}
|
|
94
|
+
return super.getCitation(work, style);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Ensure API key is present for authenticated requests
|
|
98
|
+
*/
|
|
99
|
+
ensureAuthenticated() {
|
|
100
|
+
if (!this.apiKey) {
|
|
101
|
+
throw new Error('Queensland API key is required. Please set QUEENSLAND_API_KEY.');
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
export default QueenslandProvider;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API Call Optimization Utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides connection pooling, retry strategies, request deduplication,
|
|
5
|
+
* and payload optimization for improved API performance.
|
|
6
|
+
*/
|
|
7
|
+
import { EventEmitter } from 'events';
|
|
8
|
+
type SearchParamValue = string | number | boolean | null | undefined;
|
|
9
|
+
type SearchParams = Record<string, SearchParamValue>;
|
|
10
|
+
interface RequestOptions {
|
|
11
|
+
searchParams?: SearchParams;
|
|
12
|
+
}
|
|
13
|
+
interface DeduplicationStats {
|
|
14
|
+
pendingRequests: number;
|
|
15
|
+
recentRequests: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Connection pool configuration
|
|
19
|
+
*/
|
|
20
|
+
export interface ConnectionPoolConfig {
|
|
21
|
+
maxSockets?: number;
|
|
22
|
+
maxFreeSockets?: number;
|
|
23
|
+
timeout?: number;
|
|
24
|
+
keepAlive?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Retry configuration
|
|
28
|
+
*/
|
|
29
|
+
export interface RetryConfig {
|
|
30
|
+
maxRetries?: number;
|
|
31
|
+
baseDelay?: number;
|
|
32
|
+
maxDelay?: number;
|
|
33
|
+
retryableStatusCodes?: number[];
|
|
34
|
+
retryableMethods?: string[];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Request deduplication configuration
|
|
38
|
+
*/
|
|
39
|
+
export interface DeduplicationConfig {
|
|
40
|
+
enabled?: boolean;
|
|
41
|
+
windowMs?: number;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Optimized API client options
|
|
45
|
+
*/
|
|
46
|
+
export interface OptimizedClientOptions {
|
|
47
|
+
baseUrl: string;
|
|
48
|
+
apiKey: string;
|
|
49
|
+
pool?: ConnectionPoolConfig;
|
|
50
|
+
retry?: RetryConfig;
|
|
51
|
+
deduplication?: DeduplicationConfig;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Request metrics
|
|
55
|
+
*/
|
|
56
|
+
export interface RequestMetrics {
|
|
57
|
+
totalRequests: number;
|
|
58
|
+
successfulRequests: number;
|
|
59
|
+
failedRequests: number;
|
|
60
|
+
retriedRequests: number;
|
|
61
|
+
deduplicatedRequests: number;
|
|
62
|
+
averageResponseTime: number;
|
|
63
|
+
p95ResponseTime: number;
|
|
64
|
+
p99ResponseTime: number;
|
|
65
|
+
}
|
|
66
|
+
export declare class OptimizedApiClient extends EventEmitter {
|
|
67
|
+
private readonly baseUrl;
|
|
68
|
+
private readonly apiKey;
|
|
69
|
+
private readonly pool;
|
|
70
|
+
private readonly retryManager;
|
|
71
|
+
private readonly deduplicationManager;
|
|
72
|
+
private metrics;
|
|
73
|
+
private responseTimes;
|
|
74
|
+
constructor(options: OptimizedClientOptions);
|
|
75
|
+
get<T>(endpoint: string, options?: RequestOptions): Promise<T>;
|
|
76
|
+
private createClient;
|
|
77
|
+
private executeWithRetry;
|
|
78
|
+
private trackResponseTime;
|
|
79
|
+
getMetrics(): RequestMetrics;
|
|
80
|
+
resetMetrics(): void;
|
|
81
|
+
getDeduplicationStats(): DeduplicationStats;
|
|
82
|
+
close(): void;
|
|
83
|
+
}
|
|
84
|
+
export declare class PayloadOptimizer {
|
|
85
|
+
static compressPayload(data: unknown, fields?: string[]): unknown;
|
|
86
|
+
private static pickFields;
|
|
87
|
+
static minify(data: unknown): string;
|
|
88
|
+
static estimateSize(data: unknown): number;
|
|
89
|
+
private static isJsonObject;
|
|
90
|
+
}
|
|
91
|
+
export declare function createOptimizedClient(options: OptimizedClientOptions): OptimizedApiClient;
|
|
92
|
+
export {};
|