@kb-labs/marketplace-api 0.1.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.
@@ -0,0 +1,25 @@
1
+ import { FastifyInstance } from 'fastify';
2
+ import { ILogger } from '@kb-labs/core-platform';
3
+ import { MarketplaceService } from '@kb-labs/marketplace-core';
4
+
5
+ /**
6
+ * @module @kb-labs/marketplace-api/server
7
+ * Fastify server factory for marketplace service.
8
+ */
9
+
10
+ interface CreateServerOptions {
11
+ service: MarketplaceService;
12
+ logger?: ILogger;
13
+ port?: number;
14
+ host?: string;
15
+ }
16
+ declare function createServer(opts: CreateServerOptions): Promise<FastifyInstance>;
17
+
18
+ /**
19
+ * @module @kb-labs/marketplace-api/routes
20
+ * Register all marketplace API routes.
21
+ */
22
+
23
+ declare function registerRoutes(server: FastifyInstance): Promise<void>;
24
+
25
+ export { type CreateServerOptions, createServer, registerRoutes };
package/dist/index.js ADDED
@@ -0,0 +1,342 @@
1
+ import Fastify from 'fastify';
2
+ import { HttpObservabilityCollector, registerOpenAPI, createCorrelatedLogger, createServiceReadyResponse } from '@kb-labs/shared-http';
3
+ import { randomUUID } from 'crypto';
4
+
5
+ // src/server.ts
6
+
7
+ // src/routes/install.ts
8
+ function installRoute(app) {
9
+ app.post("/install", {
10
+ schema: {
11
+ tags: ["Marketplace"],
12
+ summary: "Install package(s)",
13
+ body: {
14
+ type: "object",
15
+ required: ["specs"],
16
+ properties: {
17
+ specs: { type: "array", items: { type: "string" } },
18
+ dev: { type: "boolean" }
19
+ }
20
+ }
21
+ }
22
+ }, async (request, reply) => {
23
+ const { specs, dev } = request.body;
24
+ const service = app.marketplace;
25
+ const result = await app.observability.observeOperation("marketplace.install", () => service.install(specs, { dev }));
26
+ return reply.send(result);
27
+ });
28
+ }
29
+
30
+ // src/routes/uninstall.ts
31
+ function uninstallRoute(app) {
32
+ app.post("/uninstall", {
33
+ schema: {
34
+ tags: ["Marketplace"],
35
+ summary: "Uninstall package(s)",
36
+ body: {
37
+ type: "object",
38
+ required: ["packageIds"],
39
+ properties: {
40
+ packageIds: { type: "array", items: { type: "string" } }
41
+ }
42
+ }
43
+ }
44
+ }, async (request, reply) => {
45
+ const { packageIds } = request.body;
46
+ const service = app.marketplace;
47
+ await app.observability.observeOperation("marketplace.uninstall", () => service.uninstall(packageIds));
48
+ return reply.send({ ok: true, removed: packageIds });
49
+ });
50
+ }
51
+
52
+ // src/routes/update.ts
53
+ function updateRoute(app) {
54
+ app.post("/update", {
55
+ schema: {
56
+ tags: ["Marketplace"],
57
+ summary: "Update installed package(s)",
58
+ body: {
59
+ type: "object",
60
+ properties: {
61
+ packageIds: { type: "array", items: { type: "string" } }
62
+ }
63
+ }
64
+ }
65
+ }, async (request, reply) => {
66
+ const { packageIds } = request.body ?? {};
67
+ const service = app.marketplace;
68
+ const result = await app.observability.observeOperation("marketplace.update", () => service.update(packageIds));
69
+ return reply.send(result);
70
+ });
71
+ }
72
+
73
+ // src/routes/list.ts
74
+ function listRoute(app) {
75
+ app.get("/list", {
76
+ schema: {
77
+ tags: ["Marketplace"],
78
+ summary: "List installed packages",
79
+ querystring: {
80
+ type: "object",
81
+ properties: {
82
+ kind: { type: "string" }
83
+ }
84
+ }
85
+ }
86
+ }, async (request, reply) => {
87
+ const { kind } = request.query;
88
+ const service = app.marketplace;
89
+ const entries = await app.observability.observeOperation(
90
+ "marketplace.list",
91
+ () => service.list(kind ? { kind } : void 0)
92
+ );
93
+ return reply.send({ entries, total: entries.length });
94
+ });
95
+ }
96
+
97
+ // src/routes/enable-disable.ts
98
+ function enableDisableRoute(app) {
99
+ app.post("/enable", {
100
+ schema: {
101
+ tags: ["Marketplace"],
102
+ summary: "Enable a package",
103
+ body: {
104
+ type: "object",
105
+ required: ["packageId"],
106
+ properties: {
107
+ packageId: { type: "string" }
108
+ }
109
+ }
110
+ }
111
+ }, async (request, reply) => {
112
+ const { packageId } = request.body;
113
+ const service = app.marketplace;
114
+ await app.observability.observeOperation("marketplace.enable", () => service.enable(packageId));
115
+ return reply.send({ ok: true, packageId, enabled: true });
116
+ });
117
+ app.post("/disable", {
118
+ schema: {
119
+ tags: ["Marketplace"],
120
+ summary: "Disable a package",
121
+ body: {
122
+ type: "object",
123
+ required: ["packageId"],
124
+ properties: {
125
+ packageId: { type: "string" }
126
+ }
127
+ }
128
+ }
129
+ }, async (request, reply) => {
130
+ const { packageId } = request.body;
131
+ const service = app.marketplace;
132
+ await app.observability.observeOperation("marketplace.disable", () => service.disable(packageId));
133
+ return reply.send({ ok: true, packageId, enabled: false });
134
+ });
135
+ }
136
+
137
+ // src/routes/link-unlink.ts
138
+ function linkUnlinkRoute(app) {
139
+ app.post("/link", {
140
+ schema: {
141
+ tags: ["Marketplace"],
142
+ summary: "Link a local package for development",
143
+ body: {
144
+ type: "object",
145
+ required: ["path"],
146
+ properties: {
147
+ path: { type: "string" }
148
+ }
149
+ }
150
+ }
151
+ }, async (request, reply) => {
152
+ const { path } = request.body;
153
+ const service = app.marketplace;
154
+ const result = await app.observability.observeOperation("marketplace.link", () => service.link(path));
155
+ return reply.send({ ok: true, ...result });
156
+ });
157
+ app.post("/unlink", {
158
+ schema: {
159
+ tags: ["Marketplace"],
160
+ summary: "Unlink a package",
161
+ body: {
162
+ type: "object",
163
+ required: ["packageId"],
164
+ properties: {
165
+ packageId: { type: "string" }
166
+ }
167
+ }
168
+ }
169
+ }, async (request, reply) => {
170
+ const { packageId } = request.body;
171
+ const service = app.marketplace;
172
+ await app.observability.observeOperation("marketplace.unlink", () => service.unlink(packageId));
173
+ return reply.send({ ok: true, packageId });
174
+ });
175
+ }
176
+
177
+ // src/routes/doctor.ts
178
+ function doctorRoute(app) {
179
+ app.get("/doctor", {
180
+ schema: {
181
+ tags: ["Marketplace"],
182
+ summary: "Diagnose marketplace health"
183
+ }
184
+ }, async (_request, reply) => {
185
+ const service = app.marketplace;
186
+ const report = await app.observability.observeOperation("marketplace.doctor", () => service.doctor());
187
+ return reply.send(report);
188
+ });
189
+ }
190
+
191
+ // src/routes/sync.ts
192
+ function syncRoute(app) {
193
+ app.post("/sync", {
194
+ schema: {
195
+ tags: ["Marketplace"],
196
+ summary: "Sync workspace \u2014 scan for plugins/adapters and populate lock",
197
+ body: {
198
+ type: "object",
199
+ required: ["include"],
200
+ properties: {
201
+ include: { type: "array", items: { type: "string" }, description: "Glob patterns to scan (relative to workspace root)" },
202
+ exclude: { type: "array", items: { type: "string" }, description: "Optional patterns to skip" },
203
+ autoEnable: { type: "boolean", description: "Enable new entries (default: false, safe for prod)" }
204
+ }
205
+ }
206
+ }
207
+ }, async (request, reply) => {
208
+ const body = request.body;
209
+ const result = await app.observability.observeOperation("marketplace.sync", () => app.marketplace.sync(body));
210
+ return reply.send(result);
211
+ });
212
+ }
213
+
214
+ // src/routes/index.ts
215
+ async function registerRoutes(server) {
216
+ await server.register(async (app) => {
217
+ installRoute(app);
218
+ uninstallRoute(app);
219
+ updateRoute(app);
220
+ listRoute(app);
221
+ enableDisableRoute(app);
222
+ linkUnlinkRoute(app);
223
+ doctorRoute(app);
224
+ syncRoute(app);
225
+ }, { prefix: "/api/v1/marketplace" });
226
+ }
227
+ var DEFAULT_PORT = 5070;
228
+ function createFallbackLogger() {
229
+ const child = (_bindings) => createFallbackLogger();
230
+ return {
231
+ trace: () => {
232
+ },
233
+ debug: () => {
234
+ },
235
+ info: () => {
236
+ },
237
+ warn: () => {
238
+ },
239
+ error: () => {
240
+ },
241
+ fatal: () => {
242
+ },
243
+ child
244
+ };
245
+ }
246
+ async function createServer(opts) {
247
+ const port = opts.port ?? DEFAULT_PORT;
248
+ const logger = opts.logger ?? createFallbackLogger();
249
+ const observability = new HttpObservabilityCollector({
250
+ serviceId: "marketplace",
251
+ serviceType: "http-api",
252
+ version: "0.1.0",
253
+ logsSource: "marketplace"
254
+ });
255
+ const server = Fastify({
256
+ logger: false
257
+ // using platform.logger
258
+ });
259
+ await registerOpenAPI(server, {
260
+ title: "KB Labs Marketplace",
261
+ version: "0.1.0",
262
+ description: "Unified marketplace for plugins, adapters, workflows, and more",
263
+ servers: [
264
+ { url: `http://localhost:${port}`, description: "Local dev" }
265
+ ],
266
+ ui: process.env.NODE_ENV !== "production"
267
+ });
268
+ server.decorate("marketplace", opts.service);
269
+ server.decorate("observability", observability);
270
+ observability.register(server);
271
+ server.addHook("onRequest", async (request, reply) => {
272
+ const requestId = request.headers["x-request-id"] || randomUUID();
273
+ const traceId = request.headers["x-trace-id"] || randomUUID();
274
+ request.id = requestId;
275
+ reply.header("X-Request-Id", requestId);
276
+ reply.header("X-Trace-Id", traceId);
277
+ request.kbLogger = createCorrelatedLogger(logger, {
278
+ serviceId: "marketplace",
279
+ logsSource: "marketplace",
280
+ layer: "marketplace",
281
+ service: "request",
282
+ requestId,
283
+ traceId,
284
+ method: request.method,
285
+ url: request.url,
286
+ operation: "http.request"
287
+ });
288
+ request.kbLogger.info(`\u2192 ${request.method.toUpperCase()} ${request.url}`);
289
+ });
290
+ server.addHook("onResponse", async (request, reply) => {
291
+ const logger2 = request.kbLogger;
292
+ if (!logger2) {
293
+ return;
294
+ }
295
+ logger2.info(`\u2713 ${request.method.toUpperCase()} ${request.url} ${reply.statusCode}`, {
296
+ statusCode: reply.statusCode
297
+ });
298
+ });
299
+ server.get("/health", async () => ({
300
+ status: "ok",
301
+ service: "marketplace",
302
+ ts: Date.now()
303
+ }));
304
+ server.get(
305
+ "/ready",
306
+ async () => createServiceReadyResponse({
307
+ ready: true,
308
+ components: {
309
+ marketplaceService: {
310
+ ready: true
311
+ }
312
+ }
313
+ })
314
+ );
315
+ server.get("/metrics", async (_request, reply) => {
316
+ reply.header("Content-Type", "text/plain; version=0.0.4; charset=utf-8");
317
+ return observability.renderPrometheusMetrics("healthy");
318
+ });
319
+ server.get("/observability/describe", async () => observability.buildDescribe());
320
+ server.get(
321
+ "/observability/health",
322
+ async () => observability.buildHealth({
323
+ status: "healthy",
324
+ checks: [
325
+ {
326
+ id: "marketplace-service",
327
+ status: "ok",
328
+ message: "Marketplace service registered"
329
+ }
330
+ ],
331
+ meta: {
332
+ serviceHealthEndpoint: "/health"
333
+ }
334
+ })
335
+ );
336
+ await observability.observeOperation("marketplace.bootstrap", () => registerRoutes(server));
337
+ return server;
338
+ }
339
+
340
+ export { createServer, registerRoutes };
341
+ //# sourceMappingURL=index.js.map
342
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/routes/install.ts","../src/routes/uninstall.ts","../src/routes/update.ts","../src/routes/list.ts","../src/routes/enable-disable.ts","../src/routes/link-unlink.ts","../src/routes/doctor.ts","../src/routes/sync.ts","../src/routes/index.ts","../src/server.ts"],"names":["logger"],"mappings":"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","file":"index.js","sourcesContent":["import '../types.js';\nimport type { FastifyInstance } from 'fastify';\n\nexport function installRoute(app: FastifyInstance): void {\n app.post('/install', {\n schema: {\n tags: ['Marketplace'],\n summary: 'Install package(s)',\n body: {\n type: 'object',\n required: ['specs'],\n properties: {\n specs: { type: 'array', items: { type: 'string' } },\n dev: { type: 'boolean' },\n },\n },\n },\n }, async (request, reply) => {\n const { specs, dev } = request.body as { specs: string[]; dev?: boolean };\n const service = app.marketplace;\n const result = await app.observability.observeOperation('marketplace.install', () => service.install(specs, { dev }));\n return reply.send(result);\n });\n}\n","import '../types.js';\nimport type { FastifyInstance } from 'fastify';\n\nexport function uninstallRoute(app: FastifyInstance): void {\n app.post('/uninstall', {\n schema: {\n tags: ['Marketplace'],\n summary: 'Uninstall package(s)',\n body: {\n type: 'object',\n required: ['packageIds'],\n properties: {\n packageIds: { type: 'array', items: { type: 'string' } },\n },\n },\n },\n }, async (request, reply) => {\n const { packageIds } = request.body as { packageIds: string[] };\n const service = app.marketplace;\n await app.observability.observeOperation('marketplace.uninstall', () => service.uninstall(packageIds));\n return reply.send({ ok: true, removed: packageIds });\n });\n}\n","import '../types.js';\nimport type { FastifyInstance } from 'fastify';\n\nexport function updateRoute(app: FastifyInstance): void {\n app.post('/update', {\n schema: {\n tags: ['Marketplace'],\n summary: 'Update installed package(s)',\n body: {\n type: 'object',\n properties: {\n packageIds: { type: 'array', items: { type: 'string' } },\n },\n },\n },\n }, async (request, reply) => {\n const { packageIds } = (request.body as { packageIds?: string[] }) ?? {};\n const service = app.marketplace;\n const result = await app.observability.observeOperation('marketplace.update', () => service.update(packageIds));\n return reply.send(result);\n });\n}\n","import '../types.js';\nimport type { FastifyInstance } from 'fastify';\nimport type { EntityKind } from '@kb-labs/core-discovery';\n\nexport function listRoute(app: FastifyInstance): void {\n app.get('/list', {\n schema: {\n tags: ['Marketplace'],\n summary: 'List installed packages',\n querystring: {\n type: 'object',\n properties: {\n kind: { type: 'string' },\n },\n },\n },\n }, async (request, reply) => {\n const { kind } = request.query as { kind?: string };\n const service = app.marketplace;\n const entries = await app.observability.observeOperation(\n 'marketplace.list',\n () => service.list(kind ? { kind: kind as EntityKind } : undefined),\n );\n return reply.send({ entries, total: entries.length });\n });\n}\n","import '../types.js';\nimport type { FastifyInstance } from 'fastify';\n\nexport function enableDisableRoute(app: FastifyInstance): void {\n app.post('/enable', {\n schema: {\n tags: ['Marketplace'],\n summary: 'Enable a package',\n body: {\n type: 'object',\n required: ['packageId'],\n properties: {\n packageId: { type: 'string' },\n },\n },\n },\n }, async (request, reply) => {\n const { packageId } = request.body as { packageId: string };\n const service = app.marketplace;\n await app.observability.observeOperation('marketplace.enable', () => service.enable(packageId));\n return reply.send({ ok: true, packageId, enabled: true });\n });\n\n app.post('/disable', {\n schema: {\n tags: ['Marketplace'],\n summary: 'Disable a package',\n body: {\n type: 'object',\n required: ['packageId'],\n properties: {\n packageId: { type: 'string' },\n },\n },\n },\n }, async (request, reply) => {\n const { packageId } = request.body as { packageId: string };\n const service = app.marketplace;\n await app.observability.observeOperation('marketplace.disable', () => service.disable(packageId));\n return reply.send({ ok: true, packageId, enabled: false });\n });\n}\n","import '../types.js';\nimport type { FastifyInstance } from 'fastify';\n\nexport function linkUnlinkRoute(app: FastifyInstance): void {\n app.post('/link', {\n schema: {\n tags: ['Marketplace'],\n summary: 'Link a local package for development',\n body: {\n type: 'object',\n required: ['path'],\n properties: {\n path: { type: 'string' },\n },\n },\n },\n }, async (request, reply) => {\n const { path } = request.body as { path: string };\n const service = app.marketplace;\n const result = await app.observability.observeOperation('marketplace.link', () => service.link(path));\n return reply.send({ ok: true, ...result });\n });\n\n app.post('/unlink', {\n schema: {\n tags: ['Marketplace'],\n summary: 'Unlink a package',\n body: {\n type: 'object',\n required: ['packageId'],\n properties: {\n packageId: { type: 'string' },\n },\n },\n },\n }, async (request, reply) => {\n const { packageId } = request.body as { packageId: string };\n const service = app.marketplace;\n await app.observability.observeOperation('marketplace.unlink', () => service.unlink(packageId));\n return reply.send({ ok: true, packageId });\n });\n}\n","import '../types.js';\nimport type { FastifyInstance } from 'fastify';\n\nexport function doctorRoute(app: FastifyInstance): void {\n app.get('/doctor', {\n schema: {\n tags: ['Marketplace'],\n summary: 'Diagnose marketplace health',\n },\n }, async (_request, reply) => {\n const service = app.marketplace;\n const report = await app.observability.observeOperation('marketplace.doctor', () => service.doctor());\n return reply.send(report);\n });\n}\n","import '../types.js';\nimport type { FastifyInstance } from 'fastify';\n\nexport function syncRoute(app: FastifyInstance): void {\n app.post('/sync', {\n schema: {\n tags: ['Marketplace'],\n summary: 'Sync workspace — scan for plugins/adapters and populate lock',\n body: {\n type: 'object',\n required: ['include'],\n properties: {\n include: { type: 'array', items: { type: 'string' }, description: 'Glob patterns to scan (relative to workspace root)' },\n exclude: { type: 'array', items: { type: 'string' }, description: 'Optional patterns to skip' },\n autoEnable: { type: 'boolean', description: 'Enable new entries (default: false, safe for prod)' },\n },\n },\n },\n }, async (request, reply) => {\n const body = request.body as {\n include: string[];\n exclude?: string[];\n autoEnable?: boolean;\n };\n const result = await app.observability.observeOperation('marketplace.sync', () => app.marketplace.sync(body));\n return reply.send(result);\n });\n}\n","/**\n * @module @kb-labs/marketplace-api/routes\n * Register all marketplace API routes.\n */\n\nimport type { FastifyInstance } from 'fastify';\nimport { installRoute } from './install.js';\nimport { uninstallRoute } from './uninstall.js';\nimport { updateRoute } from './update.js';\nimport { listRoute } from './list.js';\nimport { enableDisableRoute } from './enable-disable.js';\nimport { linkUnlinkRoute } from './link-unlink.js';\nimport { doctorRoute } from './doctor.js';\nimport { syncRoute } from './sync.js';\n\nexport async function registerRoutes(server: FastifyInstance): Promise<void> {\n await server.register(async (app) => {\n installRoute(app);\n uninstallRoute(app);\n updateRoute(app);\n listRoute(app);\n enableDisableRoute(app);\n linkUnlinkRoute(app);\n doctorRoute(app);\n syncRoute(app);\n }, { prefix: '/api/v1/marketplace' });\n}\n","/**\n * @module @kb-labs/marketplace-api/server\n * Fastify server factory for marketplace service.\n */\n\nimport Fastify, { type FastifyInstance } from 'fastify';\nimport {\n createCorrelatedLogger,\n HttpObservabilityCollector,\n createServiceReadyResponse,\n registerOpenAPI,\n} from '@kb-labs/shared-http';\nimport type { ILogger } from '@kb-labs/core-platform';\nimport { registerRoutes } from './routes/index.js';\nimport type { MarketplaceService } from '@kb-labs/marketplace-core';\nimport { randomUUID } from 'node:crypto';\n\nconst DEFAULT_PORT = 5070;\n\nfunction createFallbackLogger(): ILogger {\n const child = (_bindings: Record<string, unknown>): ILogger => createFallbackLogger();\n return {\n trace: () => {},\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n fatal: () => {},\n child,\n };\n}\n\nexport interface CreateServerOptions {\n service: MarketplaceService;\n logger?: ILogger;\n port?: number;\n host?: string;\n}\n\nexport async function createServer(opts: CreateServerOptions): Promise<FastifyInstance> {\n const port = opts.port ?? DEFAULT_PORT;\n const logger = opts.logger ?? createFallbackLogger();\n const observability = new HttpObservabilityCollector({\n serviceId: 'marketplace',\n serviceType: 'http-api',\n version: '0.1.0',\n logsSource: 'marketplace',\n });\n const server = Fastify({\n logger: false, // using platform.logger\n });\n\n // OpenAPI docs\n await registerOpenAPI(server, {\n title: 'KB Labs Marketplace',\n version: '0.1.0',\n description: 'Unified marketplace for plugins, adapters, workflows, and more',\n servers: [\n { url: `http://localhost:${port}`, description: 'Local dev' },\n ],\n ui: process.env.NODE_ENV !== 'production',\n });\n\n // Decorate with service instance\n server.decorate('marketplace', opts.service);\n server.decorate('observability', observability);\n observability.register(server);\n\n server.addHook('onRequest', async (request, reply) => {\n const requestId = (request.headers['x-request-id'] as string | undefined) || randomUUID();\n const traceId = (request.headers['x-trace-id'] as string | undefined) || randomUUID();\n\n request.id = requestId;\n reply.header('X-Request-Id', requestId);\n reply.header('X-Trace-Id', traceId);\n\n (request as any).kbLogger = createCorrelatedLogger(logger, {\n serviceId: 'marketplace',\n logsSource: 'marketplace',\n layer: 'marketplace',\n service: 'request',\n requestId,\n traceId,\n method: request.method,\n url: request.url,\n operation: 'http.request',\n });\n (request as any).kbLogger.info(`→ ${request.method.toUpperCase()} ${request.url}`);\n });\n\n server.addHook('onResponse', async (request, reply) => {\n const logger = (request as any).kbLogger as { info: (message: string, meta?: Record<string, unknown>) => void } | undefined;\n if (!logger) {\n return;\n }\n\n logger.info(`✓ ${request.method.toUpperCase()} ${request.url} ${reply.statusCode}`, {\n statusCode: reply.statusCode,\n });\n });\n\n server.get('/health', async () => ({\n status: 'ok',\n service: 'marketplace',\n ts: Date.now(),\n }));\n\n server.get('/ready', async () =>\n createServiceReadyResponse({\n ready: true,\n components: {\n marketplaceService: {\n ready: true,\n },\n },\n })\n );\n\n server.get('/metrics', async (_request, reply) => {\n reply.header('Content-Type', 'text/plain; version=0.0.4; charset=utf-8');\n return observability.renderPrometheusMetrics('healthy');\n });\n\n server.get('/observability/describe', async () => observability.buildDescribe());\n\n server.get('/observability/health', async () =>\n observability.buildHealth({\n status: 'healthy',\n checks: [\n {\n id: 'marketplace-service',\n status: 'ok',\n message: 'Marketplace service registered',\n },\n ],\n meta: {\n serviceHealthEndpoint: '/health',\n },\n })\n );\n\n // Register routes\n await observability.observeOperation('marketplace.bootstrap', () => registerRoutes(server));\n\n return server;\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@kb-labs/marketplace-api",
3
+ "version": "0.1.1",
4
+ "description": "Fastify routes for KB Labs marketplace service",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "sideEffects": false,
18
+ "scripts": {
19
+ "clean": "rimraf dist",
20
+ "build": "tsup",
21
+ "dev": "tsup --watch",
22
+ "type-check": "tsc --noEmit",
23
+ "lint": "eslint .",
24
+ "lint:fix": "eslint . --fix",
25
+ "test": "vitest run --passWithNoTests -c ../../vitest.config.ts"
26
+ },
27
+ "dependencies": {
28
+ "@kb-labs/core-contracts": "^1.5.0",
29
+ "@kb-labs/core-discovery": "^1.5.0",
30
+ "@kb-labs/core-platform": "^1.5.0",
31
+ "@kb-labs/marketplace-contracts": "^0.1.1",
32
+ "@kb-labs/marketplace-core": "^0.1.1",
33
+ "@kb-labs/shared-http": "^1.3.0",
34
+ "fastify": "^5.3.3",
35
+ "@fastify/swagger": ">=9.5.1",
36
+ "@fastify/swagger-ui": "^5.2.0",
37
+ "fastify-type-provider-zod": "^6.0.0",
38
+ "zod": "^3.23.8"
39
+ },
40
+ "devDependencies": {
41
+ "tsup": "^8.5.0",
42
+ "vitest": "^3.2.4",
43
+ "@kb-labs/devkit": "link:../../../../infra/kb-labs-devkit",
44
+ "@types/node": "^24.3.3"
45
+ }
46
+ }