@open-skills-hub/api 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.
- package/dist/controllers/audit.d.ts +33 -0
- package/dist/controllers/audit.d.ts.map +1 -0
- package/dist/controllers/audit.js +122 -0
- package/dist/controllers/audit.js.map +1 -0
- package/dist/controllers/cache.d.ts +42 -0
- package/dist/controllers/cache.d.ts.map +1 -0
- package/dist/controllers/cache.js +247 -0
- package/dist/controllers/cache.js.map +1 -0
- package/dist/controllers/feedback.d.ts +44 -0
- package/dist/controllers/feedback.d.ts.map +1 -0
- package/dist/controllers/feedback.js +216 -0
- package/dist/controllers/feedback.js.map +1 -0
- package/dist/controllers/index.d.ts +9 -0
- package/dist/controllers/index.d.ts.map +1 -0
- package/dist/controllers/index.js +9 -0
- package/dist/controllers/index.js.map +1 -0
- package/dist/controllers/skills.d.ts +66 -0
- package/dist/controllers/skills.d.ts.map +1 -0
- package/dist/controllers/skills.js +355 -0
- package/dist/controllers/skills.js.map +1 -0
- package/dist/controllers/versions.d.ts +43 -0
- package/dist/controllers/versions.d.ts.map +1 -0
- package/dist/controllers/versions.js +298 -0
- package/dist/controllers/versions.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +78 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/auth.d.ts +34 -0
- package/dist/middleware/auth.d.ts.map +1 -0
- package/dist/middleware/auth.js +148 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/middleware/error.d.ts +26 -0
- package/dist/middleware/error.d.ts.map +1 -0
- package/dist/middleware/error.js +102 -0
- package/dist/middleware/error.js.map +1 -0
- package/dist/middleware/index.d.ts +8 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +8 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/middleware/logger.d.ts +19 -0
- package/dist/middleware/logger.d.ts.map +1 -0
- package/dist/middleware/logger.js +54 -0
- package/dist/middleware/logger.js.map +1 -0
- package/dist/middleware/validation.d.ts +671 -0
- package/dist/middleware/validation.d.ts.map +1 -0
- package/dist/middleware/validation.js +225 -0
- package/dist/middleware/validation.js.map +1 -0
- package/dist/routes/audit.d.ts +6 -0
- package/dist/routes/audit.d.ts.map +1 -0
- package/dist/routes/audit.js +54 -0
- package/dist/routes/audit.js.map +1 -0
- package/dist/routes/cache.d.ts +6 -0
- package/dist/routes/cache.d.ts.map +1 -0
- package/dist/routes/cache.js +70 -0
- package/dist/routes/cache.js.map +1 -0
- package/dist/routes/feedback.d.ts +6 -0
- package/dist/routes/feedback.d.ts.map +1 -0
- package/dist/routes/feedback.js +68 -0
- package/dist/routes/feedback.js.map +1 -0
- package/dist/routes/health.d.ts +6 -0
- package/dist/routes/health.d.ts.map +1 -0
- package/dist/routes/health.js +122 -0
- package/dist/routes/health.js.map +1 -0
- package/dist/routes/index.d.ts +12 -0
- package/dist/routes/index.d.ts.map +1 -0
- package/dist/routes/index.js +12 -0
- package/dist/routes/index.js.map +1 -0
- package/dist/routes/scan.d.ts +8 -0
- package/dist/routes/scan.d.ts.map +1 -0
- package/dist/routes/scan.js +315 -0
- package/dist/routes/scan.js.map +1 -0
- package/dist/routes/search.d.ts +6 -0
- package/dist/routes/search.d.ts.map +1 -0
- package/dist/routes/search.js +44 -0
- package/dist/routes/search.js.map +1 -0
- package/dist/routes/skills.d.ts +6 -0
- package/dist/routes/skills.d.ts.map +1 -0
- package/dist/routes/skills.js +74 -0
- package/dist/routes/skills.js.map +1 -0
- package/dist/routes/versions.d.ts +6 -0
- package/dist/routes/versions.d.ts.map +1 -0
- package/dist/routes/versions.js +66 -0
- package/dist/routes/versions.js.map +1 -0
- package/dist/server.d.ts +26 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +166 -0
- package/dist/server.js.map +1 -0
- package/package.json +42 -0
- package/src/controllers/audit.ts +175 -0
- package/src/controllers/cache.ts +344 -0
- package/src/controllers/feedback.ts +309 -0
- package/src/controllers/index.ts +9 -0
- package/src/controllers/skills.ts +489 -0
- package/src/controllers/versions.ts +427 -0
- package/src/index.ts +87 -0
- package/src/middleware/auth.ts +219 -0
- package/src/middleware/error.ts +180 -0
- package/src/middleware/index.ts +8 -0
- package/src/middleware/logger.ts +71 -0
- package/src/middleware/validation.ts +270 -0
- package/src/routes/audit.ts +74 -0
- package/src/routes/cache.ts +93 -0
- package/src/routes/feedback.ts +93 -0
- package/src/routes/health.ts +151 -0
- package/src/routes/index.ts +12 -0
- package/src/routes/scan.ts +428 -0
- package/src/routes/search.ts +51 -0
- package/src/routes/skills.ts +102 -0
- package/src/routes/versions.ts +91 -0
- package/src/server.ts +205 -0
- package/tsconfig.json +13 -0
package/src/server.ts
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Open Skills Hub - API Server Configuration
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import Fastify, { FastifyInstance } from 'fastify';
|
|
6
|
+
import cors from '@fastify/cors';
|
|
7
|
+
import helmet from '@fastify/helmet';
|
|
8
|
+
import rateLimit from '@fastify/rate-limit';
|
|
9
|
+
import multipart from '@fastify/multipart';
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
getConfig,
|
|
13
|
+
getStorage,
|
|
14
|
+
logger,
|
|
15
|
+
} from '@open-skills-hub/core';
|
|
16
|
+
|
|
17
|
+
import { errorHandler, notFoundHandler } from './middleware/error.js';
|
|
18
|
+
import { requestLogger } from './middleware/logger.js';
|
|
19
|
+
import { skillsRoutes } from './routes/skills.js';
|
|
20
|
+
import { versionsRoutes } from './routes/versions.js';
|
|
21
|
+
import { searchRoutes } from './routes/search.js';
|
|
22
|
+
import { scanRoutes } from './routes/scan.js';
|
|
23
|
+
import { feedbackRoutes } from './routes/feedback.js';
|
|
24
|
+
import { auditRoutes } from './routes/audit.js';
|
|
25
|
+
import { cacheRoutes } from './routes/cache.js';
|
|
26
|
+
import { healthRoutes } from './routes/health.js';
|
|
27
|
+
|
|
28
|
+
export interface ServerOptions {
|
|
29
|
+
host?: string;
|
|
30
|
+
port?: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Create and configure the Fastify server
|
|
35
|
+
*/
|
|
36
|
+
export async function createServer(options?: ServerOptions): Promise<FastifyInstance> {
|
|
37
|
+
const config = getConfig().get();
|
|
38
|
+
const serverConfig = config.server;
|
|
39
|
+
|
|
40
|
+
const server = Fastify({
|
|
41
|
+
logger: false, // We use our own logger
|
|
42
|
+
trustProxy: serverConfig.trustProxy,
|
|
43
|
+
requestIdHeader: 'x-request-id',
|
|
44
|
+
requestIdLogLabel: 'requestId',
|
|
45
|
+
genReqId: () => `req_${Date.now().toString(36)}_${Math.random().toString(36).substr(2, 9)}`,
|
|
46
|
+
// Increase body size limit to support large skills with many files (e.g., XSD schemas)
|
|
47
|
+
bodyLimit: 50 * 1024 * 1024, // 50MB
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// Register plugins
|
|
51
|
+
await registerPlugins(server, config);
|
|
52
|
+
|
|
53
|
+
// Register middleware
|
|
54
|
+
await registerMiddleware(server);
|
|
55
|
+
|
|
56
|
+
// Register routes
|
|
57
|
+
await registerRoutes(server);
|
|
58
|
+
|
|
59
|
+
// Set error handlers
|
|
60
|
+
server.setNotFoundHandler(notFoundHandler);
|
|
61
|
+
server.setErrorHandler(errorHandler);
|
|
62
|
+
|
|
63
|
+
return server;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Register Fastify plugins
|
|
68
|
+
*/
|
|
69
|
+
async function registerPlugins(server: FastifyInstance, config: ReturnType<ReturnType<typeof getConfig>['get']>) {
|
|
70
|
+
// CORS
|
|
71
|
+
if (config.server.cors) {
|
|
72
|
+
await server.register(cors, {
|
|
73
|
+
origin: true,
|
|
74
|
+
methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
|
|
75
|
+
allowedHeaders: ['Content-Type', 'Authorization', 'X-Request-ID'],
|
|
76
|
+
exposedHeaders: ['X-Request-ID', 'X-RateLimit-Limit', 'X-RateLimit-Remaining'],
|
|
77
|
+
credentials: true,
|
|
78
|
+
maxAge: 86400,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Security headers
|
|
83
|
+
await server.register(helmet, {
|
|
84
|
+
contentSecurityPolicy: false, // Disabled for API
|
|
85
|
+
crossOriginResourcePolicy: { policy: 'cross-origin' },
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// Rate limiting
|
|
89
|
+
if (config.rateLimit.enabled) {
|
|
90
|
+
await server.register(rateLimit, {
|
|
91
|
+
global: true,
|
|
92
|
+
max: config.rateLimit.max,
|
|
93
|
+
timeWindow: config.rateLimit.windowMs,
|
|
94
|
+
allowList: ['127.0.0.1'],
|
|
95
|
+
addHeadersOnExceeding: {
|
|
96
|
+
'x-ratelimit-limit': true,
|
|
97
|
+
'x-ratelimit-remaining': true,
|
|
98
|
+
'x-ratelimit-reset': true,
|
|
99
|
+
},
|
|
100
|
+
addHeaders: {
|
|
101
|
+
'x-ratelimit-limit': true,
|
|
102
|
+
'x-ratelimit-remaining': true,
|
|
103
|
+
'x-ratelimit-reset': true,
|
|
104
|
+
'retry-after': true,
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Multipart form data (for file uploads)
|
|
110
|
+
await server.register(multipart, {
|
|
111
|
+
limits: {
|
|
112
|
+
fileSize: 10 * 1024 * 1024, // 10MB max file size
|
|
113
|
+
files: 10, // Max number of files
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Register middleware
|
|
120
|
+
*/
|
|
121
|
+
async function registerMiddleware(server: FastifyInstance) {
|
|
122
|
+
// Request logging
|
|
123
|
+
server.addHook('onRequest', requestLogger);
|
|
124
|
+
|
|
125
|
+
// Add request timing
|
|
126
|
+
server.addHook('onRequest', async (request) => {
|
|
127
|
+
request.startTime = Date.now();
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// Add response timing header
|
|
131
|
+
server.addHook('onSend', async (request, reply) => {
|
|
132
|
+
if (request.startTime) {
|
|
133
|
+
const duration = Date.now() - request.startTime;
|
|
134
|
+
reply.header('X-Response-Time', `${duration}ms`);
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Register API routes
|
|
141
|
+
*/
|
|
142
|
+
async function registerRoutes(server: FastifyInstance) {
|
|
143
|
+
// Health check (no prefix)
|
|
144
|
+
await server.register(healthRoutes);
|
|
145
|
+
|
|
146
|
+
// API v1 routes
|
|
147
|
+
await server.register(async (api) => {
|
|
148
|
+
await api.register(skillsRoutes, { prefix: '/skills' });
|
|
149
|
+
await api.register(versionsRoutes, { prefix: '/skills' });
|
|
150
|
+
await api.register(searchRoutes, { prefix: '/search' });
|
|
151
|
+
await api.register(scanRoutes, { prefix: '/scan' });
|
|
152
|
+
await api.register(feedbackRoutes, { prefix: '/feedback' });
|
|
153
|
+
await api.register(auditRoutes, { prefix: '/audit' });
|
|
154
|
+
await api.register(cacheRoutes, { prefix: '/cache' });
|
|
155
|
+
}, { prefix: '/v1' });
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Start the server
|
|
160
|
+
*/
|
|
161
|
+
export async function startServer(server: FastifyInstance, options?: ServerOptions): Promise<string> {
|
|
162
|
+
const config = getConfig().get();
|
|
163
|
+
const host = options?.host ?? config.server.host;
|
|
164
|
+
const port = options?.port ?? config.server.port;
|
|
165
|
+
|
|
166
|
+
try {
|
|
167
|
+
// Initialize storage
|
|
168
|
+
const storage = await getStorage();
|
|
169
|
+
await storage.initialize();
|
|
170
|
+
logger.info('Storage initialized');
|
|
171
|
+
|
|
172
|
+
// Start listening
|
|
173
|
+
const address = await server.listen({ host, port });
|
|
174
|
+
logger.info(`Server started`, { address, mode: config.mode });
|
|
175
|
+
|
|
176
|
+
return address;
|
|
177
|
+
} catch (error) {
|
|
178
|
+
logger.error('Failed to start server', { error });
|
|
179
|
+
throw error;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Stop the server gracefully
|
|
185
|
+
*/
|
|
186
|
+
export async function stopServer(server: FastifyInstance): Promise<void> {
|
|
187
|
+
try {
|
|
188
|
+
await server.close();
|
|
189
|
+
|
|
190
|
+
const storage = await getStorage();
|
|
191
|
+
await storage.close();
|
|
192
|
+
|
|
193
|
+
logger.info('Server stopped gracefully');
|
|
194
|
+
} catch (error) {
|
|
195
|
+
logger.error('Error during server shutdown', { error });
|
|
196
|
+
throw error;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Extend FastifyRequest type
|
|
201
|
+
declare module 'fastify' {
|
|
202
|
+
interface FastifyRequest {
|
|
203
|
+
startTime?: number;
|
|
204
|
+
}
|
|
205
|
+
}
|
package/tsconfig.json
ADDED