@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.
Files changed (112) hide show
  1. package/dist/controllers/audit.d.ts +33 -0
  2. package/dist/controllers/audit.d.ts.map +1 -0
  3. package/dist/controllers/audit.js +122 -0
  4. package/dist/controllers/audit.js.map +1 -0
  5. package/dist/controllers/cache.d.ts +42 -0
  6. package/dist/controllers/cache.d.ts.map +1 -0
  7. package/dist/controllers/cache.js +247 -0
  8. package/dist/controllers/cache.js.map +1 -0
  9. package/dist/controllers/feedback.d.ts +44 -0
  10. package/dist/controllers/feedback.d.ts.map +1 -0
  11. package/dist/controllers/feedback.js +216 -0
  12. package/dist/controllers/feedback.js.map +1 -0
  13. package/dist/controllers/index.d.ts +9 -0
  14. package/dist/controllers/index.d.ts.map +1 -0
  15. package/dist/controllers/index.js +9 -0
  16. package/dist/controllers/index.js.map +1 -0
  17. package/dist/controllers/skills.d.ts +66 -0
  18. package/dist/controllers/skills.d.ts.map +1 -0
  19. package/dist/controllers/skills.js +355 -0
  20. package/dist/controllers/skills.js.map +1 -0
  21. package/dist/controllers/versions.d.ts +43 -0
  22. package/dist/controllers/versions.d.ts.map +1 -0
  23. package/dist/controllers/versions.js +298 -0
  24. package/dist/controllers/versions.js.map +1 -0
  25. package/dist/index.d.ts +9 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +78 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/middleware/auth.d.ts +34 -0
  30. package/dist/middleware/auth.d.ts.map +1 -0
  31. package/dist/middleware/auth.js +148 -0
  32. package/dist/middleware/auth.js.map +1 -0
  33. package/dist/middleware/error.d.ts +26 -0
  34. package/dist/middleware/error.d.ts.map +1 -0
  35. package/dist/middleware/error.js +102 -0
  36. package/dist/middleware/error.js.map +1 -0
  37. package/dist/middleware/index.d.ts +8 -0
  38. package/dist/middleware/index.d.ts.map +1 -0
  39. package/dist/middleware/index.js +8 -0
  40. package/dist/middleware/index.js.map +1 -0
  41. package/dist/middleware/logger.d.ts +19 -0
  42. package/dist/middleware/logger.d.ts.map +1 -0
  43. package/dist/middleware/logger.js +54 -0
  44. package/dist/middleware/logger.js.map +1 -0
  45. package/dist/middleware/validation.d.ts +671 -0
  46. package/dist/middleware/validation.d.ts.map +1 -0
  47. package/dist/middleware/validation.js +225 -0
  48. package/dist/middleware/validation.js.map +1 -0
  49. package/dist/routes/audit.d.ts +6 -0
  50. package/dist/routes/audit.d.ts.map +1 -0
  51. package/dist/routes/audit.js +54 -0
  52. package/dist/routes/audit.js.map +1 -0
  53. package/dist/routes/cache.d.ts +6 -0
  54. package/dist/routes/cache.d.ts.map +1 -0
  55. package/dist/routes/cache.js +70 -0
  56. package/dist/routes/cache.js.map +1 -0
  57. package/dist/routes/feedback.d.ts +6 -0
  58. package/dist/routes/feedback.d.ts.map +1 -0
  59. package/dist/routes/feedback.js +68 -0
  60. package/dist/routes/feedback.js.map +1 -0
  61. package/dist/routes/health.d.ts +6 -0
  62. package/dist/routes/health.d.ts.map +1 -0
  63. package/dist/routes/health.js +122 -0
  64. package/dist/routes/health.js.map +1 -0
  65. package/dist/routes/index.d.ts +12 -0
  66. package/dist/routes/index.d.ts.map +1 -0
  67. package/dist/routes/index.js +12 -0
  68. package/dist/routes/index.js.map +1 -0
  69. package/dist/routes/scan.d.ts +8 -0
  70. package/dist/routes/scan.d.ts.map +1 -0
  71. package/dist/routes/scan.js +315 -0
  72. package/dist/routes/scan.js.map +1 -0
  73. package/dist/routes/search.d.ts +6 -0
  74. package/dist/routes/search.d.ts.map +1 -0
  75. package/dist/routes/search.js +44 -0
  76. package/dist/routes/search.js.map +1 -0
  77. package/dist/routes/skills.d.ts +6 -0
  78. package/dist/routes/skills.d.ts.map +1 -0
  79. package/dist/routes/skills.js +74 -0
  80. package/dist/routes/skills.js.map +1 -0
  81. package/dist/routes/versions.d.ts +6 -0
  82. package/dist/routes/versions.d.ts.map +1 -0
  83. package/dist/routes/versions.js +66 -0
  84. package/dist/routes/versions.js.map +1 -0
  85. package/dist/server.d.ts +26 -0
  86. package/dist/server.d.ts.map +1 -0
  87. package/dist/server.js +166 -0
  88. package/dist/server.js.map +1 -0
  89. package/package.json +42 -0
  90. package/src/controllers/audit.ts +175 -0
  91. package/src/controllers/cache.ts +344 -0
  92. package/src/controllers/feedback.ts +309 -0
  93. package/src/controllers/index.ts +9 -0
  94. package/src/controllers/skills.ts +489 -0
  95. package/src/controllers/versions.ts +427 -0
  96. package/src/index.ts +87 -0
  97. package/src/middleware/auth.ts +219 -0
  98. package/src/middleware/error.ts +180 -0
  99. package/src/middleware/index.ts +8 -0
  100. package/src/middleware/logger.ts +71 -0
  101. package/src/middleware/validation.ts +270 -0
  102. package/src/routes/audit.ts +74 -0
  103. package/src/routes/cache.ts +93 -0
  104. package/src/routes/feedback.ts +93 -0
  105. package/src/routes/health.ts +151 -0
  106. package/src/routes/index.ts +12 -0
  107. package/src/routes/scan.ts +428 -0
  108. package/src/routes/search.ts +51 -0
  109. package/src/routes/skills.ts +102 -0
  110. package/src/routes/versions.ts +91 -0
  111. package/src/server.ts +205 -0
  112. 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
@@ -0,0 +1,13 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist",
5
+ "rootDir": "./src",
6
+ "composite": true
7
+ },
8
+ "include": ["src/**/*"],
9
+ "exclude": ["node_modules", "dist"],
10
+ "references": [
11
+ { "path": "../core" }
12
+ ]
13
+ }