@apiquest/fracture 1.0.2 → 1.0.4
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/README.md +119 -0
- package/bin/cli.js +2 -2
- package/dist/CollectionRunner.js +3 -3
- package/dist/ScriptEngine.js +4 -4
- package/dist/cli/plugin-commands.d.ts.map +1 -1
- package/dist/cli/plugin-commands.js +2 -1
- package/dist/cli/plugin-commands.js.map +1 -1
- package/package.json +55 -50
- package/src/CollectionAnalyzer.ts +102 -102
- package/src/CollectionRunner.ts +1423 -1423
- package/src/CollectionRunner.types.ts +9 -9
- package/src/CollectionValidator.ts +289 -289
- package/src/ConsoleReporter.ts +143 -143
- package/src/CookieJar.ts +258 -258
- package/src/DagScheduler.ts +439 -439
- package/src/Logger.ts +85 -85
- package/src/PluginLoader.ts +126 -126
- package/src/PluginManager.ts +208 -208
- package/src/PluginResolver.ts +154 -154
- package/src/QuestAPI.ts +764 -764
- package/src/QuestAPI.types.ts +33 -33
- package/src/QuestTestAPI.ts +164 -164
- package/src/RequestFilter.ts +224 -224
- package/src/ScriptEngine.ts +219 -219
- package/src/ScriptValidator.ts +428 -428
- package/src/TaskGraph.ts +598 -598
- package/src/TestCounter.ts +109 -109
- package/src/VariableResolver.ts +114 -114
- package/src/cli/index.ts +480 -480
- package/src/cli/plugin-commands.ts +342 -341
- package/src/cli/plugin-discovery.ts +44 -44
- package/src/index.ts +24 -24
- package/src/utils.ts +52 -52
- package/tsconfig.json +20 -20
- package/tsconfig.test.json +5 -5
- package/vitest.config.ts +22 -22
- package/dist/ExecutionTree.d.ts +0 -77
- package/dist/ExecutionTree.d.ts.map +0 -1
- package/dist/ExecutionTree.js +0 -265
- package/dist/ExecutionTree.js.map +0 -1
- package/dist/fracture/src/CollectionAnalyzer.d.ts +0 -17
- package/dist/fracture/src/CollectionAnalyzer.d.ts.map +0 -1
- package/dist/fracture/src/CollectionAnalyzer.js +0 -70
- package/dist/fracture/src/CollectionAnalyzer.js.map +0 -1
- package/dist/fracture/src/CollectionRunner.d.ts +0 -39
- package/dist/fracture/src/CollectionRunner.d.ts.map +0 -1
- package/dist/fracture/src/CollectionRunner.js +0 -802
- package/dist/fracture/src/CollectionRunner.js.map +0 -1
- package/dist/fracture/src/CollectionRunner.types.d.ts +0 -8
- package/dist/fracture/src/CollectionRunner.types.d.ts.map +0 -1
- package/dist/fracture/src/CollectionRunner.types.js +0 -2
- package/dist/fracture/src/CollectionRunner.types.js.map +0 -1
- package/dist/fracture/src/CollectionValidator.d.ts +0 -14
- package/dist/fracture/src/CollectionValidator.d.ts.map +0 -1
- package/dist/fracture/src/CollectionValidator.js +0 -145
- package/dist/fracture/src/CollectionValidator.js.map +0 -1
- package/dist/fracture/src/ConsoleReporter.d.ts +0 -24
- package/dist/fracture/src/ConsoleReporter.d.ts.map +0 -1
- package/dist/fracture/src/ConsoleReporter.js +0 -123
- package/dist/fracture/src/ConsoleReporter.js.map +0 -1
- package/dist/fracture/src/CookieJar.d.ts +0 -70
- package/dist/fracture/src/CookieJar.d.ts.map +0 -1
- package/dist/fracture/src/CookieJar.js +0 -233
- package/dist/fracture/src/CookieJar.js.map +0 -1
- package/dist/fracture/src/ExecutionTree.d.ts +0 -77
- package/dist/fracture/src/ExecutionTree.d.ts.map +0 -1
- package/dist/fracture/src/ExecutionTree.js +0 -258
- package/dist/fracture/src/ExecutionTree.js.map +0 -1
- package/dist/fracture/src/Logger.d.ts +0 -25
- package/dist/fracture/src/Logger.d.ts.map +0 -1
- package/dist/fracture/src/Logger.js +0 -78
- package/dist/fracture/src/Logger.js.map +0 -1
- package/dist/fracture/src/PluginLoader.d.ts +0 -23
- package/dist/fracture/src/PluginLoader.d.ts.map +0 -1
- package/dist/fracture/src/PluginLoader.js +0 -102
- package/dist/fracture/src/PluginLoader.js.map +0 -1
- package/dist/fracture/src/PluginManager.d.ts +0 -64
- package/dist/fracture/src/PluginManager.d.ts.map +0 -1
- package/dist/fracture/src/PluginManager.js +0 -162
- package/dist/fracture/src/PluginManager.js.map +0 -1
- package/dist/fracture/src/PluginResolver.d.ts +0 -35
- package/dist/fracture/src/PluginResolver.d.ts.map +0 -1
- package/dist/fracture/src/PluginResolver.js +0 -128
- package/dist/fracture/src/PluginResolver.js.map +0 -1
- package/dist/fracture/src/QuestAPI.d.ts +0 -9
- package/dist/fracture/src/QuestAPI.d.ts.map +0 -1
- package/dist/fracture/src/QuestAPI.js +0 -679
- package/dist/fracture/src/QuestAPI.js.map +0 -1
- package/dist/fracture/src/QuestAPI.types.d.ts +0 -35
- package/dist/fracture/src/QuestAPI.types.d.ts.map +0 -1
- package/dist/fracture/src/QuestAPI.types.js +0 -3
- package/dist/fracture/src/QuestAPI.types.js.map +0 -1
- package/dist/fracture/src/QuestTestAPI.d.ts +0 -12
- package/dist/fracture/src/QuestTestAPI.d.ts.map +0 -1
- package/dist/fracture/src/QuestTestAPI.js +0 -133
- package/dist/fracture/src/QuestTestAPI.js.map +0 -1
- package/dist/fracture/src/ScriptEngine.d.ts +0 -21
- package/dist/fracture/src/ScriptEngine.d.ts.map +0 -1
- package/dist/fracture/src/ScriptEngine.js +0 -183
- package/dist/fracture/src/ScriptEngine.js.map +0 -1
- package/dist/fracture/src/ScriptValidator.d.ts +0 -68
- package/dist/fracture/src/ScriptValidator.d.ts.map +0 -1
- package/dist/fracture/src/ScriptValidator.js +0 -351
- package/dist/fracture/src/ScriptValidator.js.map +0 -1
- package/dist/fracture/src/TestCounter.d.ts +0 -18
- package/dist/fracture/src/TestCounter.d.ts.map +0 -1
- package/dist/fracture/src/TestCounter.js +0 -82
- package/dist/fracture/src/TestCounter.js.map +0 -1
- package/dist/fracture/src/VariableResolver.d.ts +0 -20
- package/dist/fracture/src/VariableResolver.d.ts.map +0 -1
- package/dist/fracture/src/VariableResolver.js +0 -100
- package/dist/fracture/src/VariableResolver.js.map +0 -1
- package/dist/fracture/src/cli/index.d.ts +0 -3
- package/dist/fracture/src/cli/index.d.ts.map +0 -1
- package/dist/fracture/src/cli/index.js +0 -347
- package/dist/fracture/src/cli/index.js.map +0 -1
- package/dist/fracture/src/cli/plugin-commands.d.ts +0 -6
- package/dist/fracture/src/cli/plugin-commands.d.ts.map +0 -1
- package/dist/fracture/src/cli/plugin-commands.js +0 -263
- package/dist/fracture/src/cli/plugin-commands.js.map +0 -1
- package/dist/fracture/src/cli/plugin-discovery.d.ts +0 -11
- package/dist/fracture/src/cli/plugin-discovery.d.ts.map +0 -1
- package/dist/fracture/src/cli/plugin-discovery.js +0 -64
- package/dist/fracture/src/cli/plugin-discovery.js.map +0 -1
- package/dist/fracture/src/index.d.ts +0 -13
- package/dist/fracture/src/index.d.ts.map +0 -1
- package/dist/fracture/src/index.js +0 -17
- package/dist/fracture/src/index.js.map +0 -1
- package/dist/fracture/src/utils.d.ts +0 -28
- package/dist/fracture/src/utils.d.ts.map +0 -1
- package/dist/fracture/src/utils.js +0 -48
- package/dist/fracture/src/utils.js.map +0 -1
- package/dist/plugin-auth/src/apikey-auth.d.ts +0 -3
- package/dist/plugin-auth/src/apikey-auth.d.ts.map +0 -1
- package/dist/plugin-auth/src/apikey-auth.js +0 -73
- package/dist/plugin-auth/src/apikey-auth.js.map +0 -1
- package/dist/plugin-auth/src/basic-auth.d.ts +0 -3
- package/dist/plugin-auth/src/basic-auth.d.ts.map +0 -1
- package/dist/plugin-auth/src/basic-auth.js +0 -61
- package/dist/plugin-auth/src/basic-auth.js.map +0 -1
- package/dist/plugin-auth/src/bearer-auth.d.ts +0 -3
- package/dist/plugin-auth/src/bearer-auth.d.ts.map +0 -1
- package/dist/plugin-auth/src/bearer-auth.js +0 -49
- package/dist/plugin-auth/src/bearer-auth.js.map +0 -1
- package/dist/plugin-auth/src/helpers.d.ts +0 -3
- package/dist/plugin-auth/src/helpers.d.ts.map +0 -1
- package/dist/plugin-auth/src/helpers.js +0 -8
- package/dist/plugin-auth/src/helpers.js.map +0 -1
- package/dist/plugin-auth/src/index.d.ts +0 -10
- package/dist/plugin-auth/src/index.d.ts.map +0 -1
- package/dist/plugin-auth/src/index.js +0 -25
- package/dist/plugin-auth/src/index.js.map +0 -1
- package/dist/plugin-auth/src/oauth2-auth.d.ts +0 -35
- package/dist/plugin-auth/src/oauth2-auth.d.ts.map +0 -1
- package/dist/plugin-auth/src/oauth2-auth.js +0 -266
- package/dist/plugin-auth/src/oauth2-auth.js.map +0 -1
- package/dist/plugin-http/src/index.d.ts +0 -4
- package/dist/plugin-http/src/index.d.ts.map +0 -1
- package/dist/plugin-http/src/index.js +0 -266
- package/dist/plugin-http/src/index.js.map +0 -1
- package/dist/plugin-vault-file/src/index.d.ts +0 -67
- package/dist/plugin-vault-file/src/index.d.ts.map +0 -1
- package/dist/plugin-vault-file/src/index.js +0 -171
- package/dist/plugin-vault-file/src/index.js.map +0 -1
- package/dist/types.d.ts +0 -374
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -13
- package/dist/types.js.map +0 -1
package/src/PluginResolver.ts
CHANGED
|
@@ -1,154 +1,154 @@
|
|
|
1
|
-
import type { PluginPackageJson } from '@apiquest/types';
|
|
2
|
-
import { Logger } from './Logger.js';
|
|
3
|
-
|
|
4
|
-
export interface ResolvedPlugin {
|
|
5
|
-
name: string;
|
|
6
|
-
version: string;
|
|
7
|
-
type: 'protocol' | 'auth' | 'value';
|
|
8
|
-
path: string;
|
|
9
|
-
entryPoint: string;
|
|
10
|
-
protocols?: string[];
|
|
11
|
-
authTypes?: string[];
|
|
12
|
-
provider?: string;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export class PluginResolver {
|
|
16
|
-
private resolved: Map<string, ResolvedPlugin> = new Map();
|
|
17
|
-
private logger: Logger;
|
|
18
|
-
|
|
19
|
-
constructor(baseLogger?: Logger) {
|
|
20
|
-
this.logger = baseLogger?.createLogger('PluginResolver') ?? new Logger('PluginResolver');
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Scan multiple directories and resolve all available plugins
|
|
25
|
-
* This is fast - just file I/O, no module loading
|
|
26
|
-
*/
|
|
27
|
-
async scanDirectories(dirs: string[]): Promise<ResolvedPlugin[]> {
|
|
28
|
-
const scanPromises = dirs.map(dir =>
|
|
29
|
-
this.scanDirectory(dir).catch(err => {
|
|
30
|
-
this.logger.error('Plugin scanning failed:', err);
|
|
31
|
-
})
|
|
32
|
-
);
|
|
33
|
-
|
|
34
|
-
await Promise.all(scanPromises);
|
|
35
|
-
|
|
36
|
-
return Array.from(this.resolved.values());
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Scan single directory for plugins
|
|
41
|
-
*/
|
|
42
|
-
private async scanDirectory(pluginsDir: string): Promise<void> {
|
|
43
|
-
const { readdir, readFile, access } = await import('fs/promises');
|
|
44
|
-
const path = await import('path');
|
|
45
|
-
|
|
46
|
-
this.logger.debug(`Scanning plugins: ${pluginsDir}`);
|
|
47
|
-
|
|
48
|
-
// Check if directory exists
|
|
49
|
-
try {
|
|
50
|
-
await access(pluginsDir);
|
|
51
|
-
} catch {
|
|
52
|
-
this.logger.debug(`Plugins directory does not exist: ${pluginsDir}`);
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const entries = await readdir(pluginsDir, { withFileTypes: true });
|
|
57
|
-
|
|
58
|
-
for (const entry of entries) {
|
|
59
|
-
// Only process plugin-* directories
|
|
60
|
-
if (!entry.isDirectory() || !entry.name.startsWith('plugin-')) {
|
|
61
|
-
continue;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const pluginPath = path.join(pluginsDir, entry.name);
|
|
65
|
-
await this.resolvePlugin(pluginPath);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Resolve a single plugin - read metadata but don't load module
|
|
71
|
-
*/
|
|
72
|
-
private async resolvePlugin(pluginPath: string): Promise<void> {
|
|
73
|
-
const { readFile } = await import('fs/promises');
|
|
74
|
-
const path = await import('path');
|
|
75
|
-
|
|
76
|
-
const packageJsonPath = path.join(pluginPath, 'package.json');
|
|
77
|
-
|
|
78
|
-
try {
|
|
79
|
-
// Read package.json
|
|
80
|
-
const pkgContent = await readFile(packageJsonPath, 'utf-8');
|
|
81
|
-
const pkg = JSON.parse(pkgContent) as PluginPackageJson;
|
|
82
|
-
|
|
83
|
-
// Check if plugin is for fracture runtime
|
|
84
|
-
const runtime = pkg.apiquest?.runtime;
|
|
85
|
-
const runtimeArray = Array.isArray(runtime) ? runtime : [runtime];
|
|
86
|
-
if (pkg.apiquest === null || pkg.apiquest === undefined || !runtimeArray.includes('fracture')) {
|
|
87
|
-
this.logger.debug(`Skipping ${pkg.name} (runtime: ${runtime ?? 'undefined'})`);
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// Extract metadata from package.json
|
|
92
|
-
const type = pkg.apiquest.type;
|
|
93
|
-
if (!['protocol', 'auth', 'value'].includes(type)) {
|
|
94
|
-
this.logger.warn(`Unknown plugin type: ${type} (${pkg.name})`);
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// Resolve entry point
|
|
99
|
-
const entryPoint = pkg.main ?? 'dist/index.js';
|
|
100
|
-
const fullEntryPath = path.join(pluginPath, entryPoint);
|
|
101
|
-
|
|
102
|
-
// Extract capabilities from apiquest.capabilities.provides
|
|
103
|
-
const provides = pkg.apiquest.capabilities?.provides ?? {};
|
|
104
|
-
|
|
105
|
-
// Create resolved plugin info
|
|
106
|
-
const resolved: ResolvedPlugin = {
|
|
107
|
-
name: pkg.name,
|
|
108
|
-
version: pkg.version,
|
|
109
|
-
type: type as 'protocol' | 'auth' | 'value',
|
|
110
|
-
path: pluginPath,
|
|
111
|
-
entryPoint: fullEntryPath,
|
|
112
|
-
protocols: provides.protocols,
|
|
113
|
-
authTypes: provides.authTypes,
|
|
114
|
-
provider: provides.provider,
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
// Check for version conflicts
|
|
118
|
-
const existing = this.resolved.get(pkg.name);
|
|
119
|
-
if (existing !== null && existing !== undefined) {
|
|
120
|
-
if (this.compareVersions(pkg.version, existing.version) > 0) {
|
|
121
|
-
this.logger.debug(`Upgrading ${pkg.name} from v${existing.version} to v${pkg.version}`);
|
|
122
|
-
this.resolved.set(pkg.name, resolved);
|
|
123
|
-
} else {
|
|
124
|
-
this.logger.debug(`Skipping ${pkg.name} v${pkg.version} (v${existing.version} already resolved)`);
|
|
125
|
-
}
|
|
126
|
-
} else {
|
|
127
|
-
this.logger.debug(`Resolved ${pkg.name} v${pkg.version} (${type})`);
|
|
128
|
-
this.resolved.set(pkg.name, resolved);
|
|
129
|
-
}
|
|
130
|
-
} catch (error: unknown) {
|
|
131
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
132
|
-
this.logger.error(`Failed to resolve plugin at ${pluginPath}:`, errorMsg);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Compare semantic versions
|
|
138
|
-
* Returns: 1 if a > b, -1 if a < b, 0 if equal
|
|
139
|
-
*/
|
|
140
|
-
private compareVersions(a: string, b: string): number {
|
|
141
|
-
const aParts = a.split('.').map(Number);
|
|
142
|
-
const bParts = b.split('.').map(Number);
|
|
143
|
-
|
|
144
|
-
for (let i = 0; i < Math.max(aParts.length, bParts.length); i++) {
|
|
145
|
-
const aNum = aParts[i] ?? 0;
|
|
146
|
-
const bNum = bParts[i] ?? 0;
|
|
147
|
-
|
|
148
|
-
if (aNum > bNum) return 1;
|
|
149
|
-
if (aNum < bNum) return -1;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
return 0;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
1
|
+
import type { PluginPackageJson } from '@apiquest/types';
|
|
2
|
+
import { Logger } from './Logger.js';
|
|
3
|
+
|
|
4
|
+
export interface ResolvedPlugin {
|
|
5
|
+
name: string;
|
|
6
|
+
version: string;
|
|
7
|
+
type: 'protocol' | 'auth' | 'value';
|
|
8
|
+
path: string;
|
|
9
|
+
entryPoint: string;
|
|
10
|
+
protocols?: string[];
|
|
11
|
+
authTypes?: string[];
|
|
12
|
+
provider?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export class PluginResolver {
|
|
16
|
+
private resolved: Map<string, ResolvedPlugin> = new Map();
|
|
17
|
+
private logger: Logger;
|
|
18
|
+
|
|
19
|
+
constructor(baseLogger?: Logger) {
|
|
20
|
+
this.logger = baseLogger?.createLogger('PluginResolver') ?? new Logger('PluginResolver');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Scan multiple directories and resolve all available plugins
|
|
25
|
+
* This is fast - just file I/O, no module loading
|
|
26
|
+
*/
|
|
27
|
+
async scanDirectories(dirs: string[]): Promise<ResolvedPlugin[]> {
|
|
28
|
+
const scanPromises = dirs.map(dir =>
|
|
29
|
+
this.scanDirectory(dir).catch(err => {
|
|
30
|
+
this.logger.error('Plugin scanning failed:', err);
|
|
31
|
+
})
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
await Promise.all(scanPromises);
|
|
35
|
+
|
|
36
|
+
return Array.from(this.resolved.values());
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Scan single directory for plugins
|
|
41
|
+
*/
|
|
42
|
+
private async scanDirectory(pluginsDir: string): Promise<void> {
|
|
43
|
+
const { readdir, readFile, access } = await import('fs/promises');
|
|
44
|
+
const path = await import('path');
|
|
45
|
+
|
|
46
|
+
this.logger.debug(`Scanning plugins: ${pluginsDir}`);
|
|
47
|
+
|
|
48
|
+
// Check if directory exists
|
|
49
|
+
try {
|
|
50
|
+
await access(pluginsDir);
|
|
51
|
+
} catch {
|
|
52
|
+
this.logger.debug(`Plugins directory does not exist: ${pluginsDir}`);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const entries = await readdir(pluginsDir, { withFileTypes: true });
|
|
57
|
+
|
|
58
|
+
for (const entry of entries) {
|
|
59
|
+
// Only process plugin-* directories
|
|
60
|
+
if (!entry.isDirectory() || !entry.name.startsWith('plugin-')) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const pluginPath = path.join(pluginsDir, entry.name);
|
|
65
|
+
await this.resolvePlugin(pluginPath);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Resolve a single plugin - read metadata but don't load module
|
|
71
|
+
*/
|
|
72
|
+
private async resolvePlugin(pluginPath: string): Promise<void> {
|
|
73
|
+
const { readFile } = await import('fs/promises');
|
|
74
|
+
const path = await import('path');
|
|
75
|
+
|
|
76
|
+
const packageJsonPath = path.join(pluginPath, 'package.json');
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
// Read package.json
|
|
80
|
+
const pkgContent = await readFile(packageJsonPath, 'utf-8');
|
|
81
|
+
const pkg = JSON.parse(pkgContent) as PluginPackageJson;
|
|
82
|
+
|
|
83
|
+
// Check if plugin is for fracture runtime
|
|
84
|
+
const runtime = pkg.apiquest?.runtime;
|
|
85
|
+
const runtimeArray = Array.isArray(runtime) ? runtime : [runtime];
|
|
86
|
+
if (pkg.apiquest === null || pkg.apiquest === undefined || !runtimeArray.includes('fracture')) {
|
|
87
|
+
this.logger.debug(`Skipping ${pkg.name} (runtime: ${runtime ?? 'undefined'})`);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Extract metadata from package.json
|
|
92
|
+
const type = pkg.apiquest.type;
|
|
93
|
+
if (!['protocol', 'auth', 'value'].includes(type)) {
|
|
94
|
+
this.logger.warn(`Unknown plugin type: ${type} (${pkg.name})`);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Resolve entry point
|
|
99
|
+
const entryPoint = pkg.main ?? 'dist/index.js';
|
|
100
|
+
const fullEntryPath = path.join(pluginPath, entryPoint);
|
|
101
|
+
|
|
102
|
+
// Extract capabilities from apiquest.capabilities.provides
|
|
103
|
+
const provides = pkg.apiquest.capabilities?.provides ?? {};
|
|
104
|
+
|
|
105
|
+
// Create resolved plugin info
|
|
106
|
+
const resolved: ResolvedPlugin = {
|
|
107
|
+
name: pkg.name,
|
|
108
|
+
version: pkg.version,
|
|
109
|
+
type: type as 'protocol' | 'auth' | 'value',
|
|
110
|
+
path: pluginPath,
|
|
111
|
+
entryPoint: fullEntryPath,
|
|
112
|
+
protocols: provides.protocols,
|
|
113
|
+
authTypes: provides.authTypes,
|
|
114
|
+
provider: provides.provider,
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
// Check for version conflicts
|
|
118
|
+
const existing = this.resolved.get(pkg.name);
|
|
119
|
+
if (existing !== null && existing !== undefined) {
|
|
120
|
+
if (this.compareVersions(pkg.version, existing.version) > 0) {
|
|
121
|
+
this.logger.debug(`Upgrading ${pkg.name} from v${existing.version} to v${pkg.version}`);
|
|
122
|
+
this.resolved.set(pkg.name, resolved);
|
|
123
|
+
} else {
|
|
124
|
+
this.logger.debug(`Skipping ${pkg.name} v${pkg.version} (v${existing.version} already resolved)`);
|
|
125
|
+
}
|
|
126
|
+
} else {
|
|
127
|
+
this.logger.debug(`Resolved ${pkg.name} v${pkg.version} (${type})`);
|
|
128
|
+
this.resolved.set(pkg.name, resolved);
|
|
129
|
+
}
|
|
130
|
+
} catch (error: unknown) {
|
|
131
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
132
|
+
this.logger.error(`Failed to resolve plugin at ${pluginPath}:`, errorMsg);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Compare semantic versions
|
|
138
|
+
* Returns: 1 if a > b, -1 if a < b, 0 if equal
|
|
139
|
+
*/
|
|
140
|
+
private compareVersions(a: string, b: string): number {
|
|
141
|
+
const aParts = a.split('.').map(Number);
|
|
142
|
+
const bParts = b.split('.').map(Number);
|
|
143
|
+
|
|
144
|
+
for (let i = 0; i < Math.max(aParts.length, bParts.length); i++) {
|
|
145
|
+
const aNum = aParts[i] ?? 0;
|
|
146
|
+
const bNum = bParts[i] ?? 0;
|
|
147
|
+
|
|
148
|
+
if (aNum > bNum) return 1;
|
|
149
|
+
if (aNum < bNum) return -1;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return 0;
|
|
153
|
+
}
|
|
154
|
+
}
|