@kb-labs/marketplace-api 2.32.0 → 2.33.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/index.js CHANGED
@@ -100,7 +100,7 @@ function registerPackagesRoutes(app) {
100
100
  );
101
101
  return reply.send({ entries, total: entries.length });
102
102
  });
103
- app.post("/packages", {
103
+ app.post("/packages/install", {
104
104
  schema: {
105
105
  tags: ["Marketplace"],
106
106
  summary: "Install package(s)",
@@ -123,7 +123,7 @@ function registerPackagesRoutes(app) {
123
123
  );
124
124
  return reply.code(201).send(result);
125
125
  });
126
- app.delete("/packages", {
126
+ app.post("/packages/uninstall", {
127
127
  schema: {
128
128
  tags: ["Marketplace"],
129
129
  summary: "Uninstall package(s)",
@@ -145,72 +145,75 @@ function registerPackagesRoutes(app) {
145
145
  );
146
146
  return reply.code(204).send();
147
147
  });
148
- app.patch("/packages/:id", {
148
+ app.post("/packages/enable", {
149
149
  schema: {
150
150
  tags: ["Marketplace"],
151
- summary: "Update package state (enable or disable)",
152
- params: {
151
+ summary: "Enable a package",
152
+ body: {
153
153
  type: "object",
154
- required: ["id"],
154
+ required: ["packageId"],
155
155
  properties: {
156
- id: { type: "string" }
156
+ packageId: { type: "string" },
157
+ ...scopeBodySchemaFragment
157
158
  }
158
- },
159
+ }
160
+ }
161
+ }, async (request, reply) => {
162
+ const body = request.body;
163
+ const ctx = parseMutatingScope(body);
164
+ await app.observability.observeOperation(
165
+ "marketplace.enable",
166
+ () => app.marketplace.enable(ctx, body.packageId)
167
+ );
168
+ return reply.send({ id: body.packageId, enabled: true, scope: ctx.scope });
169
+ });
170
+ app.post("/packages/disable", {
171
+ schema: {
172
+ tags: ["Marketplace"],
173
+ summary: "Disable a package",
159
174
  body: {
160
175
  type: "object",
161
- required: ["enabled"],
176
+ required: ["packageId"],
162
177
  properties: {
163
- enabled: { type: "boolean" },
178
+ packageId: { type: "string" },
164
179
  ...scopeBodySchemaFragment
165
180
  }
166
181
  }
167
182
  }
168
183
  }, async (request, reply) => {
169
- const { id } = request.params;
170
184
  const body = request.body;
171
185
  const ctx = parseMutatingScope(body);
172
- const operation = body.enabled ? "marketplace.enable" : "marketplace.disable";
173
- const method = body.enabled ? () => app.marketplace.enable(ctx, id) : () => app.marketplace.disable(ctx, id);
174
- await app.observability.observeOperation(operation, method);
175
- return reply.send({ id, enabled: body.enabled, scope: ctx.scope });
186
+ await app.observability.observeOperation(
187
+ "marketplace.disable",
188
+ () => app.marketplace.disable(ctx, body.packageId)
189
+ );
190
+ return reply.send({ id: body.packageId, enabled: false, scope: ctx.scope });
176
191
  });
177
- app.post("/packages/:id/update", {
192
+ app.post("/packages/update", {
178
193
  schema: {
179
194
  tags: ["Marketplace"],
180
- summary: "Update package to latest version",
181
- params: {
195
+ summary: "Update package(s) to latest version",
196
+ body: {
182
197
  type: "object",
183
- required: ["id"],
184
198
  properties: {
185
- id: { type: "string" }
199
+ packageIds: { type: "array", items: { type: "string" }, description: 'Specific ids to update; omit for "all installed"' },
200
+ ...scopeBodySchemaFragment
186
201
  }
187
- },
188
- body: {
189
- type: "object",
190
- properties: scopeBodySchemaFragment
191
202
  }
192
203
  }
193
204
  }, async (request, reply) => {
194
- const { id } = request.params;
195
205
  const body = request.body ?? {};
196
206
  const ctx = parseMutatingScope(body);
197
207
  const result = await app.observability.observeOperation(
198
208
  "marketplace.update",
199
- () => app.marketplace.update(ctx, [id])
209
+ () => app.marketplace.update(ctx, body.packageIds)
200
210
  );
201
211
  return reply.send(result);
202
212
  });
203
- app.post("/packages/:id/link", {
213
+ app.post("/packages/link", {
204
214
  schema: {
205
215
  tags: ["Marketplace"],
206
216
  summary: "Link a local package path for development",
207
- params: {
208
- type: "object",
209
- required: ["id"],
210
- properties: {
211
- id: { type: "string" }
212
- }
213
- },
214
217
  body: {
215
218
  type: "object",
216
219
  required: ["path"],
@@ -229,29 +232,25 @@ function registerPackagesRoutes(app) {
229
232
  );
230
233
  return reply.send(result);
231
234
  });
232
- app.delete("/packages/:id/link", {
235
+ app.post("/packages/unlink", {
233
236
  schema: {
234
237
  tags: ["Marketplace"],
235
238
  summary: "Unlink a local package",
236
- params: {
239
+ body: {
237
240
  type: "object",
238
- required: ["id"],
241
+ required: ["packageId"],
239
242
  properties: {
240
- id: { type: "string" }
243
+ packageId: { type: "string" },
244
+ ...scopeBodySchemaFragment
241
245
  }
242
- },
243
- body: {
244
- type: "object",
245
- properties: scopeBodySchemaFragment
246
246
  }
247
247
  }
248
248
  }, async (request, reply) => {
249
- const { id } = request.params;
250
- const body = request.body ?? {};
249
+ const body = request.body;
251
250
  const ctx = parseMutatingScope(body);
252
251
  await app.observability.observeOperation(
253
252
  "marketplace.unlink",
254
- () => app.marketplace.unlink(ctx, id)
253
+ () => app.marketplace.unlink(ctx, body.packageId)
255
254
  );
256
255
  return reply.code(204).send();
257
256
  });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/scope-parser.ts","../src/routes/packages.ts","../src/routes/workspace.ts","../src/routes/diagnostics.ts","../src/routes/index.ts","../src/server.ts"],"names":["logger"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @module @kb-labs/marketplace-api/scope-parser\n *\n * Parses scope + projectRoot from HTTP request body/query into the\n * typed context shapes the marketplace service expects. Centralising this\n * logic guarantees the same validation rules (allowed values, required\n * fields, absolute paths, no traversal) are applied uniformly across routes.\n */\n\nimport * as path from 'node:path';\nimport type {\n ScopeContext,\n QueryScopeContext,\n MarketplaceScope,\n MarketplaceQueryScope,\n} from '@kb-labs/marketplace-contracts';\n\nconst MUTATING_SCOPES: readonly MarketplaceScope[] = ['platform', 'project'];\nconst QUERY_SCOPES: readonly MarketplaceQueryScope[] = ['platform', 'project', 'all'];\n\nexport class ScopeRequestError extends Error {\n readonly statusCode = 400;\n readonly code: string;\n constructor(code: string, message: string) {\n super(message);\n this.name = 'ScopeRequestError';\n this.code = code;\n }\n}\n\n/**\n * Extract a `ScopeContext` (mutating calls) from an untyped field map.\n * Server-side default is `platform` — glue layer for callers that don't\n * care about scope (e.g. health-check style tools).\n */\nexport function parseMutatingScope(input: Record<string, unknown> | undefined): ScopeContext {\n const rawScope = input?.scope;\n const scope = normalizeScope(rawScope, MUTATING_SCOPES, 'platform') as MarketplaceScope;\n const projectRoot = normalizeProjectRoot(input?.projectRoot, scope);\n return { scope, projectRoot };\n}\n\n/**\n * Extract a `QueryScopeContext` (read calls). Allows `scope: 'all'`.\n */\nexport function parseQueryScope(input: Record<string, unknown> | undefined): QueryScopeContext {\n const rawScope = input?.scope;\n const scope = normalizeScope(rawScope, QUERY_SCOPES, 'platform') as MarketplaceQueryScope;\n const projectRoot = normalizeProjectRoot(input?.projectRoot, scope);\n return { scope, projectRoot };\n}\n\nfunction normalizeScope<T extends string>(\n raw: unknown,\n allowed: readonly T[],\n fallback: T,\n): T {\n if (raw === undefined || raw === null || raw === '') {\n return fallback;\n }\n if (typeof raw !== 'string' || !allowed.includes(raw as T)) {\n throw new ScopeRequestError(\n 'SCOPE_INVALID',\n `scope must be one of: ${allowed.join(', ')} (got ${JSON.stringify(raw)})`,\n );\n }\n return raw as T;\n}\n\nfunction normalizeProjectRoot(\n raw: unknown,\n scope: MarketplaceScope | MarketplaceQueryScope,\n): string | undefined {\n if (raw === undefined || raw === null || raw === '') {\n // Required only for `project`. For `all`, if absent the service silently\n // degrades to platform-only — callers that want strictness should pass it.\n if (scope === 'project') {\n throw new ScopeRequestError(\n 'SCOPE_PROJECT_ROOT_REQUIRED',\n 'projectRoot is required when scope=\"project\"',\n );\n }\n return undefined;\n }\n if (typeof raw !== 'string') {\n throw new ScopeRequestError('SCOPE_PROJECT_ROOT_TYPE', 'projectRoot must be a string');\n }\n if (!path.isAbsolute(raw)) {\n throw new ScopeRequestError(\n 'SCOPE_PROJECT_ROOT_NOT_ABSOLUTE',\n `projectRoot must be absolute, got \"${raw}\"`,\n );\n }\n if (raw.includes('..')) {\n throw new ScopeRequestError(\n 'SCOPE_PROJECT_ROOT_TRAVERSAL',\n 'projectRoot must not contain \"..\" segments',\n );\n }\n return path.resolve(raw);\n}\n\n/** Fragment added to route body schemas so OpenAPI documents the scope fields. */\nexport const scopeBodySchemaFragment = {\n scope: { type: 'string', enum: MUTATING_SCOPES, description: 'Target scope. Default: platform.' },\n projectRoot: { type: 'string', description: 'Absolute project root (required when scope=\"project\").' },\n} as const;\n\nexport const queryScopeBodySchemaFragment = {\n scope: { type: 'string', enum: QUERY_SCOPES, description: 'Query scope. Default: platform.' },\n projectRoot: { type: 'string', description: 'Absolute project root (required when scope=\"project\", recommended for scope=\"all\").' },\n} as const;\n","/**\n * @module @kb-labs/marketplace-api/routes/packages\n * REST routes for marketplace packages (plugins, adapters, etc.)\n *\n * Every mutating route accepts `{ scope, projectRoot? }` in its body.\n * `GET /packages` accepts the same pair in its query. Default scope is\n * `platform` — CLI clients always pass the explicit scope. Project scope\n * additionally requires an absolute `projectRoot` (validated by\n * `parseMutatingScope` / `parseQueryScope`).\n *\n * GET /packages — list installed packages (supports scope=all)\n * POST /packages — install package(s)\n * DELETE /packages — uninstall package(s)\n * PATCH /packages/:id — update state (enabled/disabled)\n * POST /packages/:id/update — update to latest version\n * POST /packages/:id/link — link local path for development\n * DELETE /packages/:id/link — unlink\n */\n\nimport '../types.js';\nimport type { FastifyInstance } from 'fastify';\nimport type { EntityKind } from '@kb-labs/core-discovery';\nimport {\n parseMutatingScope,\n parseQueryScope,\n queryScopeBodySchemaFragment,\n scopeBodySchemaFragment,\n} from '../scope-parser.js';\n\nexport function registerPackagesRoutes(app: FastifyInstance): void {\n // GET /packages — list installed packages\n app.get('/packages', {\n schema: {\n tags: ['Marketplace'],\n summary: 'List installed packages',\n querystring: {\n type: 'object',\n properties: {\n kind: { type: 'string', description: 'Filter by entity kind (plugin, adapter, …)' },\n ...queryScopeBodySchemaFragment,\n },\n },\n },\n }, async (request, reply) => {\n const query = request.query as Record<string, unknown>;\n const ctx = parseQueryScope(query);\n const kind = typeof query.kind === 'string' ? (query.kind as EntityKind) : undefined;\n const entries = await app.observability.observeOperation(\n 'marketplace.list',\n () => app.marketplace.list(ctx, kind ? { kind } : undefined),\n );\n return reply.send({ entries, total: entries.length });\n });\n\n // POST /packages — install one or more packages\n app.post('/packages', {\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' }, description: 'Package specs (name, name@version, etc.)' },\n dev: { type: 'boolean', description: 'Install as dev dependency' },\n ...scopeBodySchemaFragment,\n },\n },\n },\n }, async (request, reply) => {\n const body = request.body as { specs: string[]; dev?: boolean } & Record<string, unknown>;\n const ctx = parseMutatingScope(body);\n const result = await app.observability.observeOperation(\n 'marketplace.install',\n () => app.marketplace.install(ctx, body.specs, { dev: body.dev }),\n );\n return reply.code(201).send(result);\n });\n\n // DELETE /packages — uninstall one or more packages\n app.delete('/packages', {\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 ...scopeBodySchemaFragment,\n },\n },\n },\n }, async (request, reply) => {\n const body = request.body as { packageIds: string[] } & Record<string, unknown>;\n const ctx = parseMutatingScope(body);\n await app.observability.observeOperation(\n 'marketplace.uninstall',\n () => app.marketplace.uninstall(ctx, body.packageIds),\n );\n return reply.code(204).send();\n });\n\n // PATCH /packages/:id — update package state (enable/disable)\n app.patch('/packages/:id', {\n schema: {\n tags: ['Marketplace'],\n summary: 'Update package state (enable or disable)',\n params: {\n type: 'object',\n required: ['id'],\n properties: {\n id: { type: 'string' },\n },\n },\n body: {\n type: 'object',\n required: ['enabled'],\n properties: {\n enabled: { type: 'boolean' },\n ...scopeBodySchemaFragment,\n },\n },\n },\n }, async (request, reply) => {\n const { id } = request.params as { id: string };\n const body = request.body as { enabled: boolean } & Record<string, unknown>;\n const ctx = parseMutatingScope(body);\n const operation = body.enabled ? 'marketplace.enable' : 'marketplace.disable';\n const method = body.enabled\n ? () => app.marketplace.enable(ctx, id)\n : () => app.marketplace.disable(ctx, id);\n await app.observability.observeOperation(operation, method);\n return reply.send({ id, enabled: body.enabled, scope: ctx.scope });\n });\n\n // POST /packages/:id/update — update package to latest version\n app.post('/packages/:id/update', {\n schema: {\n tags: ['Marketplace'],\n summary: 'Update package to latest version',\n params: {\n type: 'object',\n required: ['id'],\n properties: {\n id: { type: 'string' },\n },\n },\n body: {\n type: 'object',\n properties: scopeBodySchemaFragment,\n },\n },\n }, async (request, reply) => {\n const { id } = request.params as { id: string };\n const body = (request.body ?? {}) as Record<string, unknown>;\n const ctx = parseMutatingScope(body);\n const result = await app.observability.observeOperation(\n 'marketplace.update',\n () => app.marketplace.update(ctx, [id]),\n );\n return reply.send(result);\n });\n\n // POST /packages/:id/link — link a local path for development\n app.post('/packages/:id/link', {\n schema: {\n tags: ['Marketplace'],\n summary: 'Link a local package path for development',\n params: {\n type: 'object',\n required: ['id'],\n properties: {\n id: { type: 'string' },\n },\n },\n body: {\n type: 'object',\n required: ['path'],\n properties: {\n path: { type: 'string', description: 'Absolute path to local package' },\n ...scopeBodySchemaFragment,\n },\n },\n },\n }, async (request, reply) => {\n const body = request.body as { path: string } & Record<string, unknown>;\n const ctx = parseMutatingScope(body);\n const result = await app.observability.observeOperation(\n 'marketplace.link',\n () => app.marketplace.link(ctx, body.path),\n );\n return reply.send(result);\n });\n\n // DELETE /packages/:id/link — unlink a local package\n app.delete('/packages/:id/link', {\n schema: {\n tags: ['Marketplace'],\n summary: 'Unlink a local package',\n params: {\n type: 'object',\n required: ['id'],\n properties: {\n id: { type: 'string' },\n },\n },\n body: {\n type: 'object',\n properties: scopeBodySchemaFragment,\n },\n },\n }, async (request, reply) => {\n const { id } = request.params as { id: string };\n const body = (request.body ?? {}) as Record<string, unknown>;\n const ctx = parseMutatingScope(body);\n await app.observability.observeOperation(\n 'marketplace.unlink',\n () => app.marketplace.unlink(ctx, id),\n );\n return reply.code(204).send();\n });\n}\n","/**\n * @module @kb-labs/marketplace-api/routes/workspace\n * Workspace-level operations (not tied to a specific package).\n *\n * POST /workspace/sync — scan workspace and populate lock. Scope-bound:\n * globs resolve against the selected scope root and results land in that\n * scope's lock. Adapter entries are rejected in project scope by the core.\n */\n\nimport '../types.js';\nimport type { FastifyInstance } from 'fastify';\nimport { parseMutatingScope, scopeBodySchemaFragment } from '../scope-parser.js';\n\nexport function registerWorkspaceRoutes(app: FastifyInstance): void {\n // POST /workspace/sync — scan for plugins/adapters and populate lock\n app.post('/workspace/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: {\n type: 'array',\n items: { type: 'string' },\n description: 'Glob patterns to scan (relative to the scope root)',\n },\n exclude: {\n type: 'array',\n items: { type: 'string' },\n description: 'Patterns to skip',\n },\n autoEnable: {\n type: 'boolean',\n description: 'Auto-enable newly discovered entries (default: false)',\n },\n ...scopeBodySchemaFragment,\n },\n },\n },\n }, async (request, reply) => {\n const body = request.body as {\n include: string[];\n exclude?: string[];\n autoEnable?: boolean;\n } & Record<string, unknown>;\n const ctx = parseMutatingScope(body);\n const result = await app.observability.observeOperation(\n 'marketplace.sync',\n () => app.marketplace.sync(ctx, {\n include: body.include,\n exclude: body.exclude,\n autoEnable: body.autoEnable,\n }),\n );\n return reply.send(result);\n });\n}\n","/**\n * @module @kb-labs/marketplace-api/routes/diagnostics\n * Service-level diagnostic endpoints.\n *\n * GET /diagnostics — marketplace health report. Accepts scope + projectRoot\n * in query so callers can probe either scope's lock health.\n */\n\nimport '../types.js';\nimport type { FastifyInstance } from 'fastify';\nimport { parseMutatingScope, scopeBodySchemaFragment } from '../scope-parser.js';\n\nexport function registerDiagnosticsRoutes(app: FastifyInstance): void {\n app.get('/diagnostics', {\n schema: {\n tags: ['Marketplace'],\n summary: 'Marketplace health and diagnostics report',\n querystring: {\n type: 'object',\n properties: scopeBodySchemaFragment,\n },\n },\n }, async (request, reply) => {\n const ctx = parseMutatingScope(request.query as Record<string, unknown>);\n const report = await app.observability.observeOperation(\n 'marketplace.doctor',\n () => app.marketplace.doctor(ctx),\n );\n return reply.send(report);\n });\n}\n","/**\n * @module @kb-labs/marketplace-api/routes\n * Register all marketplace API routes.\n */\n\nimport type { FastifyInstance } from 'fastify';\nimport { registerPackagesRoutes } from './packages.js';\nimport { registerWorkspaceRoutes } from './workspace.js';\nimport { registerDiagnosticsRoutes } from './diagnostics.js';\n\nexport async function registerRoutes(server: FastifyInstance): Promise<void> {\n await server.register(async (app) => {\n registerPackagesRoutes(app);\n registerWorkspaceRoutes(app);\n registerDiagnosticsRoutes(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 { ScopeResolutionError, AdapterScopeError } from '@kb-labs/marketplace-core';\nimport { ScopeRequestError } from './scope-parser.js';\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 // Scope-related errors → 400. All three share a `code` property so clients\n // can discriminate (SCOPE_INVALID, SCOPE_PROJECT_ROOT_REQUIRED,\n // SCOPE_PROJECT_EQUALS_PLATFORM, MARKETPLACE_ADAPTER_PROJECT_SCOPE, ...).\n server.setErrorHandler((err, _request, reply) => {\n if (\n err instanceof ScopeRequestError ||\n err instanceof ScopeResolutionError ||\n err instanceof AdapterScopeError\n ) {\n return reply.code(400).send({\n error: err.name,\n code: err.code,\n message: err.message,\n });\n }\n // Fallback to Fastify default behaviour.\n throw err;\n });\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"]}
1
+ {"version":3,"sources":["../src/scope-parser.ts","../src/routes/packages.ts","../src/routes/workspace.ts","../src/routes/diagnostics.ts","../src/routes/index.ts","../src/server.ts"],"names":["logger"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @module @kb-labs/marketplace-api/scope-parser\n *\n * Parses scope + projectRoot from HTTP request body/query into the\n * typed context shapes the marketplace service expects. Centralising this\n * logic guarantees the same validation rules (allowed values, required\n * fields, absolute paths, no traversal) are applied uniformly across routes.\n */\n\nimport * as path from 'node:path';\nimport type {\n ScopeContext,\n QueryScopeContext,\n MarketplaceScope,\n MarketplaceQueryScope,\n} from '@kb-labs/marketplace-contracts';\n\nconst MUTATING_SCOPES: readonly MarketplaceScope[] = ['platform', 'project'];\nconst QUERY_SCOPES: readonly MarketplaceQueryScope[] = ['platform', 'project', 'all'];\n\nexport class ScopeRequestError extends Error {\n readonly statusCode = 400;\n readonly code: string;\n constructor(code: string, message: string) {\n super(message);\n this.name = 'ScopeRequestError';\n this.code = code;\n }\n}\n\n/**\n * Extract a `ScopeContext` (mutating calls) from an untyped field map.\n * Server-side default is `platform` — glue layer for callers that don't\n * care about scope (e.g. health-check style tools).\n */\nexport function parseMutatingScope(input: Record<string, unknown> | undefined): ScopeContext {\n const rawScope = input?.scope;\n const scope = normalizeScope(rawScope, MUTATING_SCOPES, 'platform') as MarketplaceScope;\n const projectRoot = normalizeProjectRoot(input?.projectRoot, scope);\n return { scope, projectRoot };\n}\n\n/**\n * Extract a `QueryScopeContext` (read calls). Allows `scope: 'all'`.\n */\nexport function parseQueryScope(input: Record<string, unknown> | undefined): QueryScopeContext {\n const rawScope = input?.scope;\n const scope = normalizeScope(rawScope, QUERY_SCOPES, 'platform') as MarketplaceQueryScope;\n const projectRoot = normalizeProjectRoot(input?.projectRoot, scope);\n return { scope, projectRoot };\n}\n\nfunction normalizeScope<T extends string>(\n raw: unknown,\n allowed: readonly T[],\n fallback: T,\n): T {\n if (raw === undefined || raw === null || raw === '') {\n return fallback;\n }\n if (typeof raw !== 'string' || !allowed.includes(raw as T)) {\n throw new ScopeRequestError(\n 'SCOPE_INVALID',\n `scope must be one of: ${allowed.join(', ')} (got ${JSON.stringify(raw)})`,\n );\n }\n return raw as T;\n}\n\nfunction normalizeProjectRoot(\n raw: unknown,\n scope: MarketplaceScope | MarketplaceQueryScope,\n): string | undefined {\n if (raw === undefined || raw === null || raw === '') {\n // Required only for `project`. For `all`, if absent the service silently\n // degrades to platform-only — callers that want strictness should pass it.\n if (scope === 'project') {\n throw new ScopeRequestError(\n 'SCOPE_PROJECT_ROOT_REQUIRED',\n 'projectRoot is required when scope=\"project\"',\n );\n }\n return undefined;\n }\n if (typeof raw !== 'string') {\n throw new ScopeRequestError('SCOPE_PROJECT_ROOT_TYPE', 'projectRoot must be a string');\n }\n if (!path.isAbsolute(raw)) {\n throw new ScopeRequestError(\n 'SCOPE_PROJECT_ROOT_NOT_ABSOLUTE',\n `projectRoot must be absolute, got \"${raw}\"`,\n );\n }\n if (raw.includes('..')) {\n throw new ScopeRequestError(\n 'SCOPE_PROJECT_ROOT_TRAVERSAL',\n 'projectRoot must not contain \"..\" segments',\n );\n }\n return path.resolve(raw);\n}\n\n/** Fragment added to route body schemas so OpenAPI documents the scope fields. */\nexport const scopeBodySchemaFragment = {\n scope: { type: 'string', enum: MUTATING_SCOPES, description: 'Target scope. Default: platform.' },\n projectRoot: { type: 'string', description: 'Absolute project root (required when scope=\"project\").' },\n} as const;\n\nexport const queryScopeBodySchemaFragment = {\n scope: { type: 'string', enum: QUERY_SCOPES, description: 'Query scope. Default: platform.' },\n projectRoot: { type: 'string', description: 'Absolute project root (required when scope=\"project\", recommended for scope=\"all\").' },\n} as const;\n","/**\n * @module @kb-labs/marketplace-api/routes/packages\n * REST routes for marketplace packages (plugins, adapters, etc.).\n *\n * The URL surface is intentionally action-oriented (\"POST /packages/link\")\n * rather than resource-style (\"POST /packages/:id/link\"). Plugin IDs carry\n * `@` and `/` (`@kb-labs/demo-entry`), which round-trip badly through proxies\n * and API gateways as URL-encoded path segments. Every action takes its\n * target id from the request body instead, eliminating an entire class of\n * routing failures.\n *\n * GET /packages — list installed packages (query: scope, projectRoot, kind)\n * POST /packages/install — install package(s)\n * POST /packages/uninstall— uninstall package(s)\n * POST /packages/link — link a local path\n * POST /packages/unlink — unlink a package\n * POST /packages/enable — mark a package enabled\n * POST /packages/disable — mark a package disabled\n * POST /packages/update — update package(s) to latest\n */\n\nimport '../types.js';\nimport type { FastifyInstance } from 'fastify';\nimport type { EntityKind } from '@kb-labs/core-discovery';\nimport {\n parseMutatingScope,\n parseQueryScope,\n queryScopeBodySchemaFragment,\n scopeBodySchemaFragment,\n} from '../scope-parser.js';\n\nexport function registerPackagesRoutes(app: FastifyInstance): void {\n // GET /packages — list installed packages\n app.get('/packages', {\n schema: {\n tags: ['Marketplace'],\n summary: 'List installed packages',\n querystring: {\n type: 'object',\n properties: {\n kind: { type: 'string', description: 'Filter by entity kind (plugin, adapter, …)' },\n ...queryScopeBodySchemaFragment,\n },\n },\n },\n }, async (request, reply) => {\n const query = request.query as Record<string, unknown>;\n const ctx = parseQueryScope(query);\n const kind = typeof query.kind === 'string' ? (query.kind as EntityKind) : undefined;\n const entries = await app.observability.observeOperation(\n 'marketplace.list',\n () => app.marketplace.list(ctx, kind ? { kind } : undefined),\n );\n return reply.send({ entries, total: entries.length });\n });\n\n // POST /packages/install — install one or more packages\n app.post('/packages/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' }, description: 'Package specs (name, name@version, etc.)' },\n dev: { type: 'boolean', description: 'Install as dev dependency' },\n ...scopeBodySchemaFragment,\n },\n },\n },\n }, async (request, reply) => {\n const body = request.body as { specs: string[]; dev?: boolean } & Record<string, unknown>;\n const ctx = parseMutatingScope(body);\n const result = await app.observability.observeOperation(\n 'marketplace.install',\n () => app.marketplace.install(ctx, body.specs, { dev: body.dev }),\n );\n return reply.code(201).send(result);\n });\n\n // POST /packages/uninstall — uninstall one or more packages\n app.post('/packages/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 ...scopeBodySchemaFragment,\n },\n },\n },\n }, async (request, reply) => {\n const body = request.body as { packageIds: string[] } & Record<string, unknown>;\n const ctx = parseMutatingScope(body);\n await app.observability.observeOperation(\n 'marketplace.uninstall',\n () => app.marketplace.uninstall(ctx, body.packageIds),\n );\n return reply.code(204).send();\n });\n\n // POST /packages/enable — enable a package\n app.post('/packages/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 ...scopeBodySchemaFragment,\n },\n },\n },\n }, async (request, reply) => {\n const body = request.body as { packageId: string } & Record<string, unknown>;\n const ctx = parseMutatingScope(body);\n await app.observability.observeOperation(\n 'marketplace.enable',\n () => app.marketplace.enable(ctx, body.packageId),\n );\n return reply.send({ id: body.packageId, enabled: true, scope: ctx.scope });\n });\n\n // POST /packages/disable — disable a package\n app.post('/packages/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 ...scopeBodySchemaFragment,\n },\n },\n },\n }, async (request, reply) => {\n const body = request.body as { packageId: string } & Record<string, unknown>;\n const ctx = parseMutatingScope(body);\n await app.observability.observeOperation(\n 'marketplace.disable',\n () => app.marketplace.disable(ctx, body.packageId),\n );\n return reply.send({ id: body.packageId, enabled: false, scope: ctx.scope });\n });\n\n // POST /packages/update — update package(s) to latest version\n app.post('/packages/update', {\n schema: {\n tags: ['Marketplace'],\n summary: 'Update package(s) to latest version',\n body: {\n type: 'object',\n properties: {\n packageIds: { type: 'array', items: { type: 'string' }, description: 'Specific ids to update; omit for \"all installed\"' },\n ...scopeBodySchemaFragment,\n },\n },\n },\n }, async (request, reply) => {\n const body = (request.body ?? {}) as { packageIds?: string[] } & Record<string, unknown>;\n const ctx = parseMutatingScope(body);\n const result = await app.observability.observeOperation(\n 'marketplace.update',\n () => app.marketplace.update(ctx, body.packageIds),\n );\n return reply.send(result);\n });\n\n // POST /packages/link — link a local path for development\n app.post('/packages/link', {\n schema: {\n tags: ['Marketplace'],\n summary: 'Link a local package path for development',\n body: {\n type: 'object',\n required: ['path'],\n properties: {\n path: { type: 'string', description: 'Absolute path to local package' },\n ...scopeBodySchemaFragment,\n },\n },\n },\n }, async (request, reply) => {\n const body = request.body as { path: string } & Record<string, unknown>;\n const ctx = parseMutatingScope(body);\n const result = await app.observability.observeOperation(\n 'marketplace.link',\n () => app.marketplace.link(ctx, body.path),\n );\n return reply.send(result);\n });\n\n // POST /packages/unlink — unlink a local package\n app.post('/packages/unlink', {\n schema: {\n tags: ['Marketplace'],\n summary: 'Unlink a local package',\n body: {\n type: 'object',\n required: ['packageId'],\n properties: {\n packageId: { type: 'string' },\n ...scopeBodySchemaFragment,\n },\n },\n },\n }, async (request, reply) => {\n const body = request.body as { packageId: string } & Record<string, unknown>;\n const ctx = parseMutatingScope(body);\n await app.observability.observeOperation(\n 'marketplace.unlink',\n () => app.marketplace.unlink(ctx, body.packageId),\n );\n return reply.code(204).send();\n });\n}\n","/**\n * @module @kb-labs/marketplace-api/routes/workspace\n * Workspace-level operations (not tied to a specific package).\n *\n * POST /workspace/sync — scan workspace and populate lock. Scope-bound:\n * globs resolve against the selected scope root and results land in that\n * scope's lock. Adapter entries are rejected in project scope by the core.\n */\n\nimport '../types.js';\nimport type { FastifyInstance } from 'fastify';\nimport { parseMutatingScope, scopeBodySchemaFragment } from '../scope-parser.js';\n\nexport function registerWorkspaceRoutes(app: FastifyInstance): void {\n // POST /workspace/sync — scan for plugins/adapters and populate lock\n app.post('/workspace/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: {\n type: 'array',\n items: { type: 'string' },\n description: 'Glob patterns to scan (relative to the scope root)',\n },\n exclude: {\n type: 'array',\n items: { type: 'string' },\n description: 'Patterns to skip',\n },\n autoEnable: {\n type: 'boolean',\n description: 'Auto-enable newly discovered entries (default: false)',\n },\n ...scopeBodySchemaFragment,\n },\n },\n },\n }, async (request, reply) => {\n const body = request.body as {\n include: string[];\n exclude?: string[];\n autoEnable?: boolean;\n } & Record<string, unknown>;\n const ctx = parseMutatingScope(body);\n const result = await app.observability.observeOperation(\n 'marketplace.sync',\n () => app.marketplace.sync(ctx, {\n include: body.include,\n exclude: body.exclude,\n autoEnable: body.autoEnable,\n }),\n );\n return reply.send(result);\n });\n}\n","/**\n * @module @kb-labs/marketplace-api/routes/diagnostics\n * Service-level diagnostic endpoints.\n *\n * GET /diagnostics — marketplace health report. Accepts scope + projectRoot\n * in query so callers can probe either scope's lock health.\n */\n\nimport '../types.js';\nimport type { FastifyInstance } from 'fastify';\nimport { parseMutatingScope, scopeBodySchemaFragment } from '../scope-parser.js';\n\nexport function registerDiagnosticsRoutes(app: FastifyInstance): void {\n app.get('/diagnostics', {\n schema: {\n tags: ['Marketplace'],\n summary: 'Marketplace health and diagnostics report',\n querystring: {\n type: 'object',\n properties: scopeBodySchemaFragment,\n },\n },\n }, async (request, reply) => {\n const ctx = parseMutatingScope(request.query as Record<string, unknown>);\n const report = await app.observability.observeOperation(\n 'marketplace.doctor',\n () => app.marketplace.doctor(ctx),\n );\n return reply.send(report);\n });\n}\n","/**\n * @module @kb-labs/marketplace-api/routes\n * Register all marketplace API routes.\n */\n\nimport type { FastifyInstance } from 'fastify';\nimport { registerPackagesRoutes } from './packages.js';\nimport { registerWorkspaceRoutes } from './workspace.js';\nimport { registerDiagnosticsRoutes } from './diagnostics.js';\n\nexport async function registerRoutes(server: FastifyInstance): Promise<void> {\n await server.register(async (app) => {\n registerPackagesRoutes(app);\n registerWorkspaceRoutes(app);\n registerDiagnosticsRoutes(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 { ScopeResolutionError, AdapterScopeError } from '@kb-labs/marketplace-core';\nimport { ScopeRequestError } from './scope-parser.js';\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 // Scope-related errors → 400. All three share a `code` property so clients\n // can discriminate (SCOPE_INVALID, SCOPE_PROJECT_ROOT_REQUIRED,\n // SCOPE_PROJECT_EQUALS_PLATFORM, MARKETPLACE_ADAPTER_PROJECT_SCOPE, ...).\n server.setErrorHandler((err, _request, reply) => {\n if (\n err instanceof ScopeRequestError ||\n err instanceof ScopeResolutionError ||\n err instanceof AdapterScopeError\n ) {\n return reply.code(400).send({\n error: err.name,\n code: err.code,\n message: err.message,\n });\n }\n // Fallback to Fastify default behaviour.\n throw err;\n });\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 CHANGED
@@ -5,12 +5,12 @@
5
5
  "fastify": "^5.3.3",
6
6
  "fastify-type-provider-zod": "^6.0.0",
7
7
  "zod": "^3.25.76",
8
- "@kb-labs/core-discovery": "2.32.0",
9
- "@kb-labs/marketplace-contracts": "2.32.0",
10
- "@kb-labs/shared-http": "2.32.0",
11
- "@kb-labs/marketplace-core": "2.32.0",
12
- "@kb-labs/core-contracts": "2.32.0",
13
- "@kb-labs/core-platform": "2.32.0"
8
+ "@kb-labs/core-contracts": "2.33.0",
9
+ "@kb-labs/core-platform": "2.33.0",
10
+ "@kb-labs/core-discovery": "2.33.0",
11
+ "@kb-labs/marketplace-contracts": "2.33.0",
12
+ "@kb-labs/marketplace-core": "2.33.0",
13
+ "@kb-labs/shared-http": "2.33.0"
14
14
  },
15
15
  "description": "Fastify routes for KB Labs marketplace service",
16
16
  "devDependencies": {
@@ -18,7 +18,7 @@
18
18
  "tsup": "^8.5.0",
19
19
  "typescript": "^5",
20
20
  "vitest": "^3.2.4",
21
- "@kb-labs/devkit": "2.32.0"
21
+ "@kb-labs/devkit": "2.33.0"
22
22
  },
23
23
  "engines": {
24
24
  "node": ">=20.0.0",
@@ -38,7 +38,7 @@
38
38
  "sideEffects": false,
39
39
  "type": "module",
40
40
  "types": "./dist/index.d.ts",
41
- "version": "2.32.0",
41
+ "version": "2.33.0",
42
42
  "scripts": {
43
43
  "build": "tsup",
44
44
  "clean": "rimraf dist",