@cyanheads/brapi-mcp-server 0.3.5
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/CLAUDE.md +391 -0
- package/Dockerfile +99 -0
- package/LICENSE +201 -0
- package/README.md +590 -0
- package/changelog/0.1.x/0.1.0.md +19 -0
- package/changelog/0.1.x/0.1.1.md +27 -0
- package/changelog/0.1.x/0.1.2.md +22 -0
- package/changelog/0.2.x/0.2.0.md +35 -0
- package/changelog/0.2.x/0.2.1.md +36 -0
- package/changelog/0.3.x/0.3.0.md +38 -0
- package/changelog/0.3.x/0.3.1.md +40 -0
- package/changelog/0.3.x/0.3.2.md +29 -0
- package/changelog/0.3.x/0.3.3.md +19 -0
- package/changelog/0.3.x/0.3.4.md +33 -0
- package/changelog/0.3.x/0.3.5.md +24 -0
- package/changelog/template.md +51 -0
- package/dist/config/alias-credentials.d.ts +82 -0
- package/dist/config/alias-credentials.d.ts.map +1 -0
- package/dist/config/alias-credentials.js +159 -0
- package/dist/config/alias-credentials.js.map +1 -0
- package/dist/config/server-config.d.ts +39 -0
- package/dist/config/server-config.d.ts.map +1 -0
- package/dist/config/server-config.js +128 -0
- package/dist/config/server-config.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +85 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-server/prompts/definitions/brapi-eda-study.prompt.d.ts +14 -0
- package/dist/mcp-server/prompts/definitions/brapi-eda-study.prompt.d.ts.map +1 -0
- package/dist/mcp-server/prompts/definitions/brapi-eda-study.prompt.js +75 -0
- package/dist/mcp-server/prompts/definitions/brapi-eda-study.prompt.js.map +1 -0
- package/dist/mcp-server/prompts/definitions/brapi-meta-analysis.prompt.d.ts +16 -0
- package/dist/mcp-server/prompts/definitions/brapi-meta-analysis.prompt.d.ts.map +1 -0
- package/dist/mcp-server/prompts/definitions/brapi-meta-analysis.prompt.js +109 -0
- package/dist/mcp-server/prompts/definitions/brapi-meta-analysis.prompt.js.map +1 -0
- package/dist/mcp-server/resources/definitions/brapi-calls.resource.d.ts +11 -0
- package/dist/mcp-server/resources/definitions/brapi-calls.resource.d.ts.map +1 -0
- package/dist/mcp-server/resources/definitions/brapi-calls.resource.js +46 -0
- package/dist/mcp-server/resources/definitions/brapi-calls.resource.js.map +1 -0
- package/dist/mcp-server/resources/definitions/brapi-dataset.resource.d.ts +13 -0
- package/dist/mcp-server/resources/definitions/brapi-dataset.resource.d.ts.map +1 -0
- package/dist/mcp-server/resources/definitions/brapi-dataset.resource.js +26 -0
- package/dist/mcp-server/resources/definitions/brapi-dataset.resource.js.map +1 -0
- package/dist/mcp-server/resources/definitions/brapi-filters.resource.d.ts +19 -0
- package/dist/mcp-server/resources/definitions/brapi-filters.resource.d.ts.map +1 -0
- package/dist/mcp-server/resources/definitions/brapi-filters.resource.js +45 -0
- package/dist/mcp-server/resources/definitions/brapi-filters.resource.js.map +1 -0
- package/dist/mcp-server/resources/definitions/brapi-germplasm.resource.d.ts +18 -0
- package/dist/mcp-server/resources/definitions/brapi-germplasm.resource.d.ts.map +1 -0
- package/dist/mcp-server/resources/definitions/brapi-germplasm.resource.js +34 -0
- package/dist/mcp-server/resources/definitions/brapi-germplasm.resource.js.map +1 -0
- package/dist/mcp-server/resources/definitions/brapi-server-info.resource.d.ts +11 -0
- package/dist/mcp-server/resources/definitions/brapi-server-info.resource.d.ts.map +1 -0
- package/dist/mcp-server/resources/definitions/brapi-server-info.resource.js +28 -0
- package/dist/mcp-server/resources/definitions/brapi-server-info.resource.js.map +1 -0
- package/dist/mcp-server/resources/definitions/brapi-study.resource.d.ts +18 -0
- package/dist/mcp-server/resources/definitions/brapi-study.resource.d.ts.map +1 -0
- package/dist/mcp-server/resources/definitions/brapi-study.resource.js +34 -0
- package/dist/mcp-server/resources/definitions/brapi-study.resource.js.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-connect.tool.d.ts +82 -0
- package/dist/mcp-server/tools/definitions/brapi-connect.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-connect.tool.js +106 -0
- package/dist/mcp-server/tools/definitions/brapi-connect.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-describe-filters.tool.d.ts +41 -0
- package/dist/mcp-server/tools/definitions/brapi-describe-filters.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-describe-filters.tool.js +88 -0
- package/dist/mcp-server/tools/definitions/brapi-describe-filters.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-find-genotype-calls.tool.d.ts +74 -0
- package/dist/mcp-server/tools/definitions/brapi-find-genotype-calls.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-find-genotype-calls.tool.js +386 -0
- package/dist/mcp-server/tools/definitions/brapi-find-genotype-calls.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-find-germplasm.tool.d.ts +72 -0
- package/dist/mcp-server/tools/definitions/brapi-find-germplasm.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-find-germplasm.tool.js +290 -0
- package/dist/mcp-server/tools/definitions/brapi-find-germplasm.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-find-images.tool.d.ts +65 -0
- package/dist/mcp-server/tools/definitions/brapi-find-images.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-find-images.tool.js +243 -0
- package/dist/mcp-server/tools/definitions/brapi-find-images.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-find-locations.tool.d.ts +63 -0
- package/dist/mcp-server/tools/definitions/brapi-find-locations.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-find-locations.tool.js +278 -0
- package/dist/mcp-server/tools/definitions/brapi-find-locations.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-find-observations.tool.d.ts +74 -0
- package/dist/mcp-server/tools/definitions/brapi-find-observations.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-find-observations.tool.js +288 -0
- package/dist/mcp-server/tools/definitions/brapi-find-observations.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-find-studies.tool.d.ts +69 -0
- package/dist/mcp-server/tools/definitions/brapi-find-studies.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-find-studies.tool.js +243 -0
- package/dist/mcp-server/tools/definitions/brapi-find-studies.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-find-variables.tool.d.ts +86 -0
- package/dist/mcp-server/tools/definitions/brapi-find-variables.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-find-variables.tool.js +337 -0
- package/dist/mcp-server/tools/definitions/brapi-find-variables.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-find-variants.tool.d.ts +59 -0
- package/dist/mcp-server/tools/definitions/brapi-find-variants.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-find-variants.tool.js +248 -0
- package/dist/mcp-server/tools/definitions/brapi-find-variants.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-get-germplasm.tool.d.ts +59 -0
- package/dist/mcp-server/tools/definitions/brapi-get-germplasm.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-get-germplasm.tool.js +306 -0
- package/dist/mcp-server/tools/definitions/brapi-get-germplasm.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-get-image.tool.d.ts +57 -0
- package/dist/mcp-server/tools/definitions/brapi-get-image.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-get-image.tool.js +291 -0
- package/dist/mcp-server/tools/definitions/brapi-get-image.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-get-study.tool.d.ts +75 -0
- package/dist/mcp-server/tools/definitions/brapi-get-study.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-get-study.tool.js +323 -0
- package/dist/mcp-server/tools/definitions/brapi-get-study.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-manage-dataset.tool.d.ts +87 -0
- package/dist/mcp-server/tools/definitions/brapi-manage-dataset.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-manage-dataset.tool.js +296 -0
- package/dist/mcp-server/tools/definitions/brapi-manage-dataset.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-raw-get.tool.d.ts +35 -0
- package/dist/mcp-server/tools/definitions/brapi-raw-get.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-raw-get.tool.js +148 -0
- package/dist/mcp-server/tools/definitions/brapi-raw-get.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-raw-search.tool.d.ts +33 -0
- package/dist/mcp-server/tools/definitions/brapi-raw-search.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-raw-search.tool.js +126 -0
- package/dist/mcp-server/tools/definitions/brapi-raw-search.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-server-info.tool.d.ts +51 -0
- package/dist/mcp-server/tools/definitions/brapi-server-info.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-server-info.tool.js +41 -0
- package/dist/mcp-server/tools/definitions/brapi-server-info.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-submit-observations.tool.d.ts +117 -0
- package/dist/mcp-server/tools/definitions/brapi-submit-observations.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-submit-observations.tool.js +574 -0
- package/dist/mcp-server/tools/definitions/brapi-submit-observations.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-walk-pedigree.tool.d.ts +52 -0
- package/dist/mcp-server/tools/definitions/brapi-walk-pedigree.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-walk-pedigree.tool.js +420 -0
- package/dist/mcp-server/tools/definitions/brapi-walk-pedigree.tool.js.map +1 -0
- package/dist/mcp-server/tools/shared/connect-auth-schema.d.ts +29 -0
- package/dist/mcp-server/tools/shared/connect-auth-schema.d.ts.map +1 -0
- package/dist/mcp-server/tools/shared/connect-auth-schema.js +55 -0
- package/dist/mcp-server/tools/shared/connect-auth-schema.js.map +1 -0
- package/dist/mcp-server/tools/shared/find-helpers.d.ts +143 -0
- package/dist/mcp-server/tools/shared/find-helpers.d.ts.map +1 -0
- package/dist/mcp-server/tools/shared/find-helpers.js +319 -0
- package/dist/mcp-server/tools/shared/find-helpers.js.map +1 -0
- package/dist/mcp-server/tools/shared/orientation-envelope.d.ts +97 -0
- package/dist/mcp-server/tools/shared/orientation-envelope.d.ts.map +1 -0
- package/dist/mcp-server/tools/shared/orientation-envelope.js +254 -0
- package/dist/mcp-server/tools/shared/orientation-envelope.js.map +1 -0
- package/dist/mcp-server/tools/shared/raw-routing-hints.d.ts +10 -0
- package/dist/mcp-server/tools/shared/raw-routing-hints.d.ts.map +1 -0
- package/dist/mcp-server/tools/shared/raw-routing-hints.js +46 -0
- package/dist/mcp-server/tools/shared/raw-routing-hints.js.map +1 -0
- package/dist/services/brapi-client/brapi-client.d.ts +76 -0
- package/dist/services/brapi-client/brapi-client.d.ts.map +1 -0
- package/dist/services/brapi-client/brapi-client.js +320 -0
- package/dist/services/brapi-client/brapi-client.js.map +1 -0
- package/dist/services/brapi-client/index.d.ts +9 -0
- package/dist/services/brapi-client/index.d.ts.map +1 -0
- package/dist/services/brapi-client/index.js +7 -0
- package/dist/services/brapi-client/index.js.map +1 -0
- package/dist/services/brapi-client/types.d.ts +82 -0
- package/dist/services/brapi-client/types.d.ts.map +1 -0
- package/dist/services/brapi-client/types.js +8 -0
- package/dist/services/brapi-client/types.js.map +1 -0
- package/dist/services/brapi-filters/catalog.d.ts +14 -0
- package/dist/services/brapi-filters/catalog.d.ts.map +1 -0
- package/dist/services/brapi-filters/catalog.js +490 -0
- package/dist/services/brapi-filters/catalog.js.map +1 -0
- package/dist/services/brapi-filters/index.d.ts +8 -0
- package/dist/services/brapi-filters/index.d.ts.map +1 -0
- package/dist/services/brapi-filters/index.js +7 -0
- package/dist/services/brapi-filters/index.js.map +1 -0
- package/dist/services/brapi-filters/types.d.ts +23 -0
- package/dist/services/brapi-filters/types.d.ts.map +1 -0
- package/dist/services/brapi-filters/types.js +9 -0
- package/dist/services/brapi-filters/types.js.map +1 -0
- package/dist/services/capability-registry/capability-registry.d.ts +51 -0
- package/dist/services/capability-registry/capability-registry.d.ts.map +1 -0
- package/dist/services/capability-registry/capability-registry.js +234 -0
- package/dist/services/capability-registry/capability-registry.js.map +1 -0
- package/dist/services/capability-registry/index.d.ts +9 -0
- package/dist/services/capability-registry/index.d.ts.map +1 -0
- package/dist/services/capability-registry/index.js +7 -0
- package/dist/services/capability-registry/index.js.map +1 -0
- package/dist/services/capability-registry/types.d.ts +67 -0
- package/dist/services/capability-registry/types.d.ts.map +1 -0
- package/dist/services/capability-registry/types.js +9 -0
- package/dist/services/capability-registry/types.js.map +1 -0
- package/dist/services/dataset-store/dataset-store.d.ts +35 -0
- package/dist/services/dataset-store/dataset-store.d.ts.map +1 -0
- package/dist/services/dataset-store/dataset-store.js +190 -0
- package/dist/services/dataset-store/dataset-store.js.map +1 -0
- package/dist/services/dataset-store/index.d.ts +8 -0
- package/dist/services/dataset-store/index.d.ts.map +1 -0
- package/dist/services/dataset-store/index.js +7 -0
- package/dist/services/dataset-store/index.js.map +1 -0
- package/dist/services/dataset-store/types.d.ts +65 -0
- package/dist/services/dataset-store/types.d.ts.map +1 -0
- package/dist/services/dataset-store/types.js +8 -0
- package/dist/services/dataset-store/types.js.map +1 -0
- package/dist/services/ontology-resolver/index.d.ts +8 -0
- package/dist/services/ontology-resolver/index.d.ts.map +1 -0
- package/dist/services/ontology-resolver/index.js +7 -0
- package/dist/services/ontology-resolver/index.js.map +1 -0
- package/dist/services/ontology-resolver/ontology-resolver.d.ts +49 -0
- package/dist/services/ontology-resolver/ontology-resolver.d.ts.map +1 -0
- package/dist/services/ontology-resolver/ontology-resolver.js +99 -0
- package/dist/services/ontology-resolver/ontology-resolver.js.map +1 -0
- package/dist/services/ontology-resolver/types.d.ts +38 -0
- package/dist/services/ontology-resolver/types.d.ts.map +1 -0
- package/dist/services/ontology-resolver/types.js +8 -0
- package/dist/services/ontology-resolver/types.js.map +1 -0
- package/dist/services/reference-data-cache/index.d.ts +9 -0
- package/dist/services/reference-data-cache/index.d.ts.map +1 -0
- package/dist/services/reference-data-cache/index.js +7 -0
- package/dist/services/reference-data-cache/index.js.map +1 -0
- package/dist/services/reference-data-cache/reference-data-cache.d.ts +31 -0
- package/dist/services/reference-data-cache/reference-data-cache.d.ts.map +1 -0
- package/dist/services/reference-data-cache/reference-data-cache.js +131 -0
- package/dist/services/reference-data-cache/reference-data-cache.js.map +1 -0
- package/dist/services/reference-data-cache/types.d.ts +42 -0
- package/dist/services/reference-data-cache/types.d.ts.map +1 -0
- package/dist/services/reference-data-cache/types.js +9 -0
- package/dist/services/reference-data-cache/types.js.map +1 -0
- package/dist/services/server-registry/index.d.ts +9 -0
- package/dist/services/server-registry/index.d.ts.map +1 -0
- package/dist/services/server-registry/index.js +7 -0
- package/dist/services/server-registry/index.js.map +1 -0
- package/dist/services/server-registry/server-registry.d.ts +57 -0
- package/dist/services/server-registry/server-registry.d.ts.map +1 -0
- package/dist/services/server-registry/server-registry.js +210 -0
- package/dist/services/server-registry/server-registry.js.map +1 -0
- package/dist/services/server-registry/types.d.ts +43 -0
- package/dist/services/server-registry/types.d.ts.map +1 -0
- package/dist/services/server-registry/types.js +10 -0
- package/dist/services/server-registry/types.js.map +1 -0
- package/package.json +86 -0
- package/server.json +99 -0
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Capability profile loader + cache for BrAPI servers. Pulls
|
|
3
|
+
* `/serverinfo`, `/calls`, and `/commoncropnames` on first use (or refresh),
|
|
4
|
+
* normalizes the shape, and stores the result in tenant-scoped state. Tools
|
|
5
|
+
* consult this before routing requests — if a required endpoint isn't in the
|
|
6
|
+
* server's capability set, the service surfaces a clear `ValidationError`
|
|
7
|
+
* instead of letting the call fail downstream.
|
|
8
|
+
*
|
|
9
|
+
* @module services/capability-registry/capability-registry
|
|
10
|
+
*/
|
|
11
|
+
import { validationError } from '@cyanheads/mcp-ts-core/errors';
|
|
12
|
+
import { getBrapiClient, } from '../../services/brapi-client/index.js';
|
|
13
|
+
const STATE_KEY_PREFIX = 'brapi/capability/';
|
|
14
|
+
export class CapabilityRegistry {
|
|
15
|
+
serverConfig;
|
|
16
|
+
client;
|
|
17
|
+
constructor(serverConfig, client = getBrapiClient) {
|
|
18
|
+
this.serverConfig = serverConfig;
|
|
19
|
+
this.client = client;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Load the capability profile for a base URL. Returns the cached profile
|
|
23
|
+
* when present and not expired; otherwise fetches fresh and caches it.
|
|
24
|
+
*/
|
|
25
|
+
async profile(baseUrl, ctx, options = {}) {
|
|
26
|
+
const key = this.cacheKey(baseUrl);
|
|
27
|
+
if (!options.forceRefresh) {
|
|
28
|
+
const cached = await ctx.state.get(key);
|
|
29
|
+
if (cached)
|
|
30
|
+
return cached;
|
|
31
|
+
}
|
|
32
|
+
const fresh = await this.fetchProfile(baseUrl, ctx, options);
|
|
33
|
+
await ctx.state.set(key, fresh, {
|
|
34
|
+
ttl: this.serverConfig.referenceCacheTtlSeconds,
|
|
35
|
+
});
|
|
36
|
+
return fresh;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Throw a `ValidationError` if the requested endpoint (service + optional
|
|
40
|
+
* HTTP method) is not in the server's capability set. Tools call this
|
|
41
|
+
* before routing requests so missing-capability errors surface early with
|
|
42
|
+
* a clear recovery hint.
|
|
43
|
+
*/
|
|
44
|
+
async ensure(baseUrl, probe, ctx, options = {}) {
|
|
45
|
+
const profile = await this.profile(baseUrl, ctx, options);
|
|
46
|
+
const descriptor = profile.supported[probe.service];
|
|
47
|
+
if (!descriptor) {
|
|
48
|
+
throw validationError(`BrAPI server at ${baseUrl} does not advertise '${probe.service}' in /calls. Check brapi_server_info for the full capability list.`, {
|
|
49
|
+
baseUrl,
|
|
50
|
+
missingService: probe.service,
|
|
51
|
+
supportedCount: Object.keys(profile.supported).length,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
if (probe.method && descriptor.methods && !descriptor.methods.includes(probe.method)) {
|
|
55
|
+
throw validationError(`BrAPI server at ${baseUrl} supports '${probe.service}' but not the ${probe.method} method.`, {
|
|
56
|
+
baseUrl,
|
|
57
|
+
service: probe.service,
|
|
58
|
+
requestedMethod: probe.method,
|
|
59
|
+
supportedMethods: descriptor.methods,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
return descriptor;
|
|
63
|
+
}
|
|
64
|
+
/** Drop the cached profile for a base URL (e.g. on explicit reconnect). */
|
|
65
|
+
async invalidate(baseUrl, ctx) {
|
|
66
|
+
await ctx.state.delete(this.cacheKey(baseUrl));
|
|
67
|
+
}
|
|
68
|
+
async fetchProfile(baseUrl, ctx, options) {
|
|
69
|
+
const client = this.client();
|
|
70
|
+
const requestOptions = buildRequestOptions(options.auth);
|
|
71
|
+
const serverInfoEnv = await client.get(baseUrl, '/serverinfo', ctx, requestOptions);
|
|
72
|
+
const embeddedCalls = serverInfoEnv.result?.calls;
|
|
73
|
+
const calls = embeddedCalls?.length
|
|
74
|
+
? embeddedCalls
|
|
75
|
+
: await this.fetchCallsFallback(baseUrl, ctx, options.auth);
|
|
76
|
+
const crops = await this.fetchCrops(baseUrl, ctx, options.auth);
|
|
77
|
+
const supported = indexCalls(calls);
|
|
78
|
+
const server = normalizeIdentity(serverInfoEnv.result, calls);
|
|
79
|
+
return {
|
|
80
|
+
baseUrl,
|
|
81
|
+
server,
|
|
82
|
+
supported,
|
|
83
|
+
crops,
|
|
84
|
+
fetchedAt: new Date().toISOString(),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* `/calls` fallback — some servers don't embed calls in `/serverinfo` and
|
|
89
|
+
* expect clients to hit the dedicated endpoint. Degrades to an empty list
|
|
90
|
+
* if the server lacks this too; downstream `ensure()` will surface the
|
|
91
|
+
* missing-capability error with a useful message.
|
|
92
|
+
*/
|
|
93
|
+
async fetchCallsFallback(baseUrl, ctx, auth) {
|
|
94
|
+
try {
|
|
95
|
+
const env = await this.client().get(baseUrl, '/calls', ctx, buildRequestOptions(auth, { pageSize: 1000 }));
|
|
96
|
+
return extractDataArray(env) ?? [];
|
|
97
|
+
}
|
|
98
|
+
catch (err) {
|
|
99
|
+
ctx.log.warning('Failed to fetch /calls fallback', {
|
|
100
|
+
baseUrl,
|
|
101
|
+
error: err instanceof Error ? err.message : String(err),
|
|
102
|
+
});
|
|
103
|
+
return [];
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
async fetchCrops(baseUrl, ctx, auth) {
|
|
107
|
+
try {
|
|
108
|
+
const env = await this.client().get(baseUrl, '/commoncropnames', ctx, buildRequestOptions(auth, { pageSize: 1000 }));
|
|
109
|
+
return extractDataArray(env) ?? [];
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
ctx.log.warning('Failed to fetch /commoncropnames', {
|
|
113
|
+
baseUrl,
|
|
114
|
+
error: err instanceof Error ? err.message : String(err),
|
|
115
|
+
});
|
|
116
|
+
return [];
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
cacheKey(baseUrl) {
|
|
120
|
+
return `${STATE_KEY_PREFIX}${sanitizeKey(baseUrl)}`;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
function buildRequestOptions(auth, params) {
|
|
124
|
+
const options = {};
|
|
125
|
+
if (auth)
|
|
126
|
+
options.auth = auth;
|
|
127
|
+
if (params)
|
|
128
|
+
options.params = params;
|
|
129
|
+
return options;
|
|
130
|
+
}
|
|
131
|
+
function indexCalls(calls) {
|
|
132
|
+
const indexed = {};
|
|
133
|
+
for (const call of calls) {
|
|
134
|
+
if (!call?.service)
|
|
135
|
+
continue;
|
|
136
|
+
const existing = indexed[call.service];
|
|
137
|
+
if (!existing) {
|
|
138
|
+
indexed[call.service] = call;
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
indexed[call.service] = mergeCallDescriptors(existing, call);
|
|
142
|
+
}
|
|
143
|
+
return indexed;
|
|
144
|
+
}
|
|
145
|
+
function mergeCallDescriptors(a, b) {
|
|
146
|
+
const merged = { service: a.service };
|
|
147
|
+
const methods = unionArrays(a.methods, b.methods);
|
|
148
|
+
if (methods)
|
|
149
|
+
merged.methods = methods;
|
|
150
|
+
const dataTypes = unionArrays(a.dataTypes, b.dataTypes);
|
|
151
|
+
if (dataTypes)
|
|
152
|
+
merged.dataTypes = dataTypes;
|
|
153
|
+
const versions = unionArrays(a.versions, b.versions);
|
|
154
|
+
if (versions)
|
|
155
|
+
merged.versions = versions;
|
|
156
|
+
return merged;
|
|
157
|
+
}
|
|
158
|
+
function unionArrays(a, b) {
|
|
159
|
+
if (!a && !b)
|
|
160
|
+
return;
|
|
161
|
+
return Array.from(new Set([...(a ?? []), ...(b ?? [])]));
|
|
162
|
+
}
|
|
163
|
+
function normalizeIdentity(info, calls) {
|
|
164
|
+
const brapiVersion = highestVersion(calls);
|
|
165
|
+
const identity = {};
|
|
166
|
+
if (info?.serverName)
|
|
167
|
+
identity.name = info.serverName;
|
|
168
|
+
if (info?.serverDescription)
|
|
169
|
+
identity.description = info.serverDescription;
|
|
170
|
+
if (info?.organizationName)
|
|
171
|
+
identity.organizationName = info.organizationName;
|
|
172
|
+
if (info?.organizationURL)
|
|
173
|
+
identity.organizationURL = info.organizationURL;
|
|
174
|
+
if (info?.documentationURL)
|
|
175
|
+
identity.documentationURL = info.documentationURL;
|
|
176
|
+
if (info?.contactEmail)
|
|
177
|
+
identity.contactEmail = info.contactEmail;
|
|
178
|
+
if (brapiVersion)
|
|
179
|
+
identity.brapiVersion = brapiVersion;
|
|
180
|
+
return identity;
|
|
181
|
+
}
|
|
182
|
+
function highestVersion(calls) {
|
|
183
|
+
let best;
|
|
184
|
+
for (const call of calls) {
|
|
185
|
+
for (const version of call.versions ?? []) {
|
|
186
|
+
if (!best || compareSemver(version, best) > 0)
|
|
187
|
+
best = version;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return best;
|
|
191
|
+
}
|
|
192
|
+
/** Loose semver compare — treats missing segments as zero. */
|
|
193
|
+
function compareSemver(a, b) {
|
|
194
|
+
const parse = (s) => s.split('.').map((p) => Number.parseInt(p, 10) || 0);
|
|
195
|
+
const pa = parse(a);
|
|
196
|
+
const pb = parse(b);
|
|
197
|
+
const len = Math.max(pa.length, pb.length);
|
|
198
|
+
for (let i = 0; i < len; i++) {
|
|
199
|
+
const diff = (pa[i] ?? 0) - (pb[i] ?? 0);
|
|
200
|
+
if (diff !== 0)
|
|
201
|
+
return diff;
|
|
202
|
+
}
|
|
203
|
+
return 0;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* BrAPI envelopes wrap list payloads as either `result: T[]` or
|
|
207
|
+
* `result: { data: T[] }` depending on the endpoint and server. Handle both.
|
|
208
|
+
*/
|
|
209
|
+
function extractDataArray(envelope) {
|
|
210
|
+
const result = envelope.result;
|
|
211
|
+
if (Array.isArray(result))
|
|
212
|
+
return result;
|
|
213
|
+
if (result && typeof result === 'object' && 'data' in result && Array.isArray(result.data)) {
|
|
214
|
+
return result.data;
|
|
215
|
+
}
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
function sanitizeKey(value) {
|
|
219
|
+
return value.replace(/[^a-zA-Z0-9]/g, '-');
|
|
220
|
+
}
|
|
221
|
+
let _registry;
|
|
222
|
+
export function initCapabilityRegistry(serverConfig) {
|
|
223
|
+
_registry = new CapabilityRegistry(serverConfig);
|
|
224
|
+
}
|
|
225
|
+
export function getCapabilityRegistry() {
|
|
226
|
+
if (!_registry) {
|
|
227
|
+
throw new Error('CapabilityRegistry not initialized — call initCapabilityRegistry() in setup()');
|
|
228
|
+
}
|
|
229
|
+
return _registry;
|
|
230
|
+
}
|
|
231
|
+
export function resetCapabilityRegistry() {
|
|
232
|
+
_registry = undefined;
|
|
233
|
+
}
|
|
234
|
+
//# sourceMappingURL=capability-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability-registry.js","sourceRoot":"","sources":["../../../src/services/capability-registry/capability-registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Public API barrel for the CapabilityRegistry service.
|
|
3
|
+
*
|
|
4
|
+
* @module services/capability-registry
|
|
5
|
+
*/
|
|
6
|
+
export type { CapabilityLookupOptions } from './capability-registry.js';
|
|
7
|
+
export { CapabilityRegistry, getCapabilityRegistry, initCapabilityRegistry, resetCapabilityRegistry, } from './capability-registry.js';
|
|
8
|
+
export type { CallDescriptor, CapabilityProfile, EndpointProbe, ServerIdentity, ServerInfoPayload, } from './types.js';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/capability-registry/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,YAAY,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,iBAAiB,GAClB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Public API barrel for the CapabilityRegistry service.
|
|
3
|
+
*
|
|
4
|
+
* @module services/capability-registry
|
|
5
|
+
*/
|
|
6
|
+
export { CapabilityRegistry, getCapabilityRegistry, initCapabilityRegistry, resetCapabilityRegistry, } from './capability-registry.js';
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/services/capability-registry/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Types for the capability profile pulled from a BrAPI server
|
|
3
|
+
* on connect — what calls it supports, which crops it covers, and any
|
|
4
|
+
* notable quirks that affect downstream tooling.
|
|
5
|
+
*
|
|
6
|
+
* @module services/capability-registry/types
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* One entry in the BrAPI `/calls` response — declares a supported endpoint
|
|
10
|
+
* with the HTTP methods, data types, and spec versions the server honors.
|
|
11
|
+
*/
|
|
12
|
+
export interface CallDescriptor {
|
|
13
|
+
dataTypes?: string[];
|
|
14
|
+
methods?: ('GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH')[];
|
|
15
|
+
service: string;
|
|
16
|
+
versions?: string[];
|
|
17
|
+
}
|
|
18
|
+
/** Raw shape of `GET /serverinfo`. Fields vary wildly across implementations. */
|
|
19
|
+
export interface ServerInfoPayload {
|
|
20
|
+
calls?: CallDescriptor[];
|
|
21
|
+
contactEmail?: string;
|
|
22
|
+
documentationURL?: string;
|
|
23
|
+
location?: string;
|
|
24
|
+
organizationName?: string;
|
|
25
|
+
organizationURL?: string;
|
|
26
|
+
serverDescription?: string;
|
|
27
|
+
serverName?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Normalized server-identity fields extracted from `/serverinfo`. Every field
|
|
31
|
+
* is optional — BrAPI servers in the wild vary in what they populate.
|
|
32
|
+
*/
|
|
33
|
+
export interface ServerIdentity {
|
|
34
|
+
/** Highest BrAPI version reported across any call (e.g. "2.1"). */
|
|
35
|
+
brapiVersion?: string;
|
|
36
|
+
contactEmail?: string;
|
|
37
|
+
description?: string;
|
|
38
|
+
documentationURL?: string;
|
|
39
|
+
name?: string;
|
|
40
|
+
organizationName?: string;
|
|
41
|
+
organizationURL?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Capability profile for one connected BrAPI server, cached per-connection.
|
|
45
|
+
* Shape is fully JSON-serializable so it can live in `ctx.state`.
|
|
46
|
+
*/
|
|
47
|
+
export interface CapabilityProfile {
|
|
48
|
+
baseUrl: string;
|
|
49
|
+
crops: string[];
|
|
50
|
+
/** ISO 8601 timestamp of when this profile was fetched. */
|
|
51
|
+
fetchedAt: string;
|
|
52
|
+
server: ServerIdentity;
|
|
53
|
+
/**
|
|
54
|
+
* Map of canonical service name → descriptor. The service name is the path
|
|
55
|
+
* segment (e.g. "studies", "search/observations") per BrAPI convention.
|
|
56
|
+
*/
|
|
57
|
+
supported: Record<string, CallDescriptor>;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Loose probe of a single endpoint. Most handlers only care whether the
|
|
61
|
+
* endpoint is supported at all and optionally for a specific HTTP method.
|
|
62
|
+
*/
|
|
63
|
+
export interface EndpointProbe {
|
|
64
|
+
method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
|
|
65
|
+
service: string;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/services/capability-registry/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,CAAC,EAAE,CAAC,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAC,EAAE,CAAC;IAC1D,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,iFAAiF;AACjF,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,2DAA2D;IAC3D,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,cAAc,CAAC;IACvB;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;CAC3C;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAC;IACrD,OAAO,EAAE,MAAM,CAAC;CACjB"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Types for the capability profile pulled from a BrAPI server
|
|
3
|
+
* on connect — what calls it supports, which crops it covers, and any
|
|
4
|
+
* notable quirks that affect downstream tooling.
|
|
5
|
+
*
|
|
6
|
+
* @module services/capability-registry/types
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/services/capability-registry/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Tenant-scoped dataset lifecycle. Stores metadata and row
|
|
3
|
+
* payloads in `ctx.state` with TTL from `BRAPI_DATASET_TTL_SECONDS`. Datasets
|
|
4
|
+
* back the `brapi_manage_dataset` tool (list/summary/load/delete) and act as
|
|
5
|
+
* the spillover target for `find_*` tools when result sets exceed
|
|
6
|
+
* `BRAPI_LOAD_LIMIT`. Provenance (source, baseUrl, query) is mandatory on
|
|
7
|
+
* create — research workflows require reproducibility.
|
|
8
|
+
*
|
|
9
|
+
* @module services/dataset-store/dataset-store
|
|
10
|
+
*/
|
|
11
|
+
import type { Context } from '@cyanheads/mcp-ts-core';
|
|
12
|
+
import type { ServerConfig } from '../../config/server-config.js';
|
|
13
|
+
import type { CreateDatasetInput, DatasetListOptions, DatasetListPage, DatasetLoadOptions, DatasetMetadata, DatasetPage } from './types.js';
|
|
14
|
+
export declare class DatasetStore {
|
|
15
|
+
private readonly serverConfig;
|
|
16
|
+
constructor(serverConfig: ServerConfig);
|
|
17
|
+
/**
|
|
18
|
+
* Persist a new dataset and return its metadata. Rows and metadata are
|
|
19
|
+
* written under separate keys so `summary` / `list` can avoid paying the
|
|
20
|
+
* row-payload read cost.
|
|
21
|
+
*/
|
|
22
|
+
create(ctx: Context, input: CreateDatasetInput): Promise<DatasetMetadata>;
|
|
23
|
+
/** Return just the metadata for a dataset. Throws `NotFound` when missing. */
|
|
24
|
+
summary(ctx: Context, datasetId: string): Promise<DatasetMetadata>;
|
|
25
|
+
/** Return a paginated slice of rows, optionally projected to a subset of columns. */
|
|
26
|
+
load(ctx: Context, datasetId: string, options?: DatasetLoadOptions): Promise<DatasetPage>;
|
|
27
|
+
/** Enumerate datasets for this tenant, paginated via opaque cursor. */
|
|
28
|
+
list(ctx: Context, options?: DatasetListOptions): Promise<DatasetListPage>;
|
|
29
|
+
/** Delete a dataset's metadata and row payload. Idempotent. */
|
|
30
|
+
delete(ctx: Context, datasetId: string): Promise<void>;
|
|
31
|
+
}
|
|
32
|
+
export declare function initDatasetStore(serverConfig: ServerConfig): void;
|
|
33
|
+
export declare function getDatasetStore(): DatasetStore;
|
|
34
|
+
export declare function resetDatasetStore(): void;
|
|
35
|
+
//# sourceMappingURL=dataset-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dataset-store.d.ts","sourceRoot":"","sources":["../../../src/services/dataset-store/dataset-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAEtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EACV,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EACf,kBAAkB,EAClB,eAAe,EACf,WAAW,EACZ,MAAM,YAAY,CAAC;AAQpB,qBAAa,YAAY;IACX,OAAO,CAAC,QAAQ,CAAC,YAAY;gBAAZ,YAAY,EAAE,YAAY;IAEvD;;;;OAIG;IACG,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,eAAe,CAAC;IAkC/E,8EAA8E;IACxE,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAYxE,qFAAqF;IAC/E,IAAI,CACR,GAAG,EAAE,OAAO,EACZ,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,WAAW,CAAC;IA4CvB,uEAAuE;IACjE,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,eAAe,CAAC;IAgBpF,+DAA+D;IACzD,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAG7D;AAkED,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,YAAY,GAAG,IAAI,CAEjE;AAED,wBAAgB,eAAe,IAAI,YAAY,CAK9C;AAED,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Tenant-scoped dataset lifecycle. Stores metadata and row
|
|
3
|
+
* payloads in `ctx.state` with TTL from `BRAPI_DATASET_TTL_SECONDS`. Datasets
|
|
4
|
+
* back the `brapi_manage_dataset` tool (list/summary/load/delete) and act as
|
|
5
|
+
* the spillover target for `find_*` tools when result sets exceed
|
|
6
|
+
* `BRAPI_LOAD_LIMIT`. Provenance (source, baseUrl, query) is mandatory on
|
|
7
|
+
* create — research workflows require reproducibility.
|
|
8
|
+
*
|
|
9
|
+
* @module services/dataset-store/dataset-store
|
|
10
|
+
*/
|
|
11
|
+
import { notFound, validationError } from '@cyanheads/mcp-ts-core/errors';
|
|
12
|
+
const META_PREFIX = 'brapi/ds/meta/';
|
|
13
|
+
const ROWS_PREFIX = 'brapi/ds/rows/';
|
|
14
|
+
const DEFAULT_PAGE_SIZE = 100;
|
|
15
|
+
const MAX_PAGE_SIZE = 1_000;
|
|
16
|
+
export class DatasetStore {
|
|
17
|
+
serverConfig;
|
|
18
|
+
constructor(serverConfig) {
|
|
19
|
+
this.serverConfig = serverConfig;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Persist a new dataset and return its metadata. Rows and metadata are
|
|
23
|
+
* written under separate keys so `summary` / `list` can avoid paying the
|
|
24
|
+
* row-payload read cost.
|
|
25
|
+
*/
|
|
26
|
+
async create(ctx, input) {
|
|
27
|
+
if (!input.source)
|
|
28
|
+
throw validationError('Dataset source is required.');
|
|
29
|
+
if (!input.baseUrl)
|
|
30
|
+
throw validationError('Dataset baseUrl is required.');
|
|
31
|
+
const datasetId = crypto.randomUUID();
|
|
32
|
+
const columns = input.columns?.length ? [...input.columns] : inferColumns(input.rows);
|
|
33
|
+
const payloadJson = JSON.stringify(input.rows);
|
|
34
|
+
const sizeBytes = byteLength(payloadJson);
|
|
35
|
+
const ttl = this.serverConfig.datasetTtlSeconds;
|
|
36
|
+
const now = new Date();
|
|
37
|
+
const expiresAt = new Date(now.getTime() + ttl * 1000);
|
|
38
|
+
const metadata = {
|
|
39
|
+
datasetId,
|
|
40
|
+
source: input.source,
|
|
41
|
+
baseUrl: input.baseUrl,
|
|
42
|
+
query: input.query,
|
|
43
|
+
rowCount: input.rows.length,
|
|
44
|
+
columns,
|
|
45
|
+
sizeBytes,
|
|
46
|
+
createdAt: now.toISOString(),
|
|
47
|
+
expiresAt: expiresAt.toISOString(),
|
|
48
|
+
};
|
|
49
|
+
if (input.truncated)
|
|
50
|
+
metadata.truncated = true;
|
|
51
|
+
if (typeof input.maxRows === 'number')
|
|
52
|
+
metadata.maxRows = input.maxRows;
|
|
53
|
+
await Promise.all([
|
|
54
|
+
ctx.state.set(metaKey(datasetId), metadata, { ttl }),
|
|
55
|
+
ctx.state.set(rowsKey(datasetId), input.rows, { ttl }),
|
|
56
|
+
]);
|
|
57
|
+
return metadata;
|
|
58
|
+
}
|
|
59
|
+
/** Return just the metadata for a dataset. Throws `NotFound` when missing. */
|
|
60
|
+
async summary(ctx, datasetId) {
|
|
61
|
+
const meta = await ctx.state.get(metaKey(datasetId));
|
|
62
|
+
if (!meta) {
|
|
63
|
+
throw notFound(`Dataset ${datasetId} not found or expired.`, {
|
|
64
|
+
datasetId,
|
|
65
|
+
reason: 'dataset_not_found',
|
|
66
|
+
...ctx.recoveryFor('dataset_not_found'),
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
return meta;
|
|
70
|
+
}
|
|
71
|
+
/** Return a paginated slice of rows, optionally projected to a subset of columns. */
|
|
72
|
+
async load(ctx, datasetId, options = {}) {
|
|
73
|
+
const meta = await this.summary(ctx, datasetId);
|
|
74
|
+
const rows = await ctx.state.get(rowsKey(datasetId));
|
|
75
|
+
if (!rows) {
|
|
76
|
+
throw notFound(`Dataset ${datasetId} metadata exists but rows are missing (storage inconsistency or partial expiry).`, {
|
|
77
|
+
datasetId,
|
|
78
|
+
reason: 'dataset_rows_missing',
|
|
79
|
+
...ctx.recoveryFor('dataset_rows_missing'),
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
const pageSize = clampPageSize(options.pageSize);
|
|
83
|
+
const page = Math.max(1, options.page ?? 1);
|
|
84
|
+
const totalRows = rows.length;
|
|
85
|
+
const totalPages = Math.max(1, Math.ceil(totalRows / pageSize));
|
|
86
|
+
if (page > totalPages && totalRows > 0) {
|
|
87
|
+
throw validationError(`Dataset ${datasetId} has ${totalPages} page(s) at pageSize=${pageSize}; requested page ${page} is out of range.`, { datasetId, requestedPage: page, totalPages });
|
|
88
|
+
}
|
|
89
|
+
const start = (page - 1) * pageSize;
|
|
90
|
+
const end = start + pageSize;
|
|
91
|
+
const slice = rows.slice(start, end);
|
|
92
|
+
if (options.columns?.length) {
|
|
93
|
+
validateColumns(options.columns, meta.columns);
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
datasetId,
|
|
97
|
+
rows: options.columns?.length ? projectColumns(slice, options.columns) : slice,
|
|
98
|
+
page,
|
|
99
|
+
pageSize,
|
|
100
|
+
totalRows,
|
|
101
|
+
totalPages,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/** Enumerate datasets for this tenant, paginated via opaque cursor. */
|
|
105
|
+
async list(ctx, options = {}) {
|
|
106
|
+
const listOpts = {
|
|
107
|
+
limit: options.limit ?? 50,
|
|
108
|
+
};
|
|
109
|
+
if (options.cursor !== undefined)
|
|
110
|
+
listOpts.cursor = options.cursor;
|
|
111
|
+
const page = await ctx.state.list(META_PREFIX, listOpts);
|
|
112
|
+
const datasets = [];
|
|
113
|
+
for (const item of page.items) {
|
|
114
|
+
if (isDatasetMetadata(item.value))
|
|
115
|
+
datasets.push(item.value);
|
|
116
|
+
}
|
|
117
|
+
const result = { datasets };
|
|
118
|
+
if (page.cursor !== undefined)
|
|
119
|
+
result.cursor = page.cursor;
|
|
120
|
+
return result;
|
|
121
|
+
}
|
|
122
|
+
/** Delete a dataset's metadata and row payload. Idempotent. */
|
|
123
|
+
async delete(ctx, datasetId) {
|
|
124
|
+
await ctx.state.deleteMany([metaKey(datasetId), rowsKey(datasetId)]);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
function metaKey(id) {
|
|
128
|
+
return `${META_PREFIX}${id}`;
|
|
129
|
+
}
|
|
130
|
+
function rowsKey(id) {
|
|
131
|
+
return `${ROWS_PREFIX}${id}`;
|
|
132
|
+
}
|
|
133
|
+
function inferColumns(rows) {
|
|
134
|
+
const seen = new Set();
|
|
135
|
+
for (const row of rows) {
|
|
136
|
+
for (const key of Object.keys(row))
|
|
137
|
+
seen.add(key);
|
|
138
|
+
if (seen.size > 256)
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
return Array.from(seen);
|
|
142
|
+
}
|
|
143
|
+
function projectColumns(rows, columns) {
|
|
144
|
+
return rows.map((row) => {
|
|
145
|
+
const projected = {};
|
|
146
|
+
for (const col of columns) {
|
|
147
|
+
if (col in row)
|
|
148
|
+
projected[col] = row[col];
|
|
149
|
+
}
|
|
150
|
+
return projected;
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
function validateColumns(requested, available) {
|
|
154
|
+
const availableSet = new Set(available);
|
|
155
|
+
const unknown = requested.filter((c) => !availableSet.has(c));
|
|
156
|
+
if (unknown.length > 0) {
|
|
157
|
+
throw validationError(`Unknown column(s): ${unknown.join(', ')}. Available columns: ${available.join(', ')}.`, { unknownColumns: unknown, availableColumns: available });
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
function clampPageSize(value) {
|
|
161
|
+
if (typeof value !== 'number' || !Number.isFinite(value) || value <= 0) {
|
|
162
|
+
return DEFAULT_PAGE_SIZE;
|
|
163
|
+
}
|
|
164
|
+
return Math.min(Math.floor(value), MAX_PAGE_SIZE);
|
|
165
|
+
}
|
|
166
|
+
function byteLength(value) {
|
|
167
|
+
if (typeof Buffer !== 'undefined')
|
|
168
|
+
return Buffer.byteLength(value, 'utf8');
|
|
169
|
+
return new TextEncoder().encode(value).byteLength;
|
|
170
|
+
}
|
|
171
|
+
function isDatasetMetadata(value) {
|
|
172
|
+
return (typeof value === 'object' &&
|
|
173
|
+
value !== null &&
|
|
174
|
+
'datasetId' in value &&
|
|
175
|
+
typeof value.datasetId === 'string');
|
|
176
|
+
}
|
|
177
|
+
let _store;
|
|
178
|
+
export function initDatasetStore(serverConfig) {
|
|
179
|
+
_store = new DatasetStore(serverConfig);
|
|
180
|
+
}
|
|
181
|
+
export function getDatasetStore() {
|
|
182
|
+
if (!_store) {
|
|
183
|
+
throw new Error('DatasetStore not initialized — call initDatasetStore() in setup()');
|
|
184
|
+
}
|
|
185
|
+
return _store;
|
|
186
|
+
}
|
|
187
|
+
export function resetDatasetStore() {
|
|
188
|
+
_store = undefined;
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=dataset-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dataset-store.js","sourceRoot":"","sources":["../../../src/services/dataset-store/dataset-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Public API barrel for the DatasetStore service.
|
|
3
|
+
*
|
|
4
|
+
* @module services/dataset-store
|
|
5
|
+
*/
|
|
6
|
+
export { DatasetStore, getDatasetStore, initDatasetStore, resetDatasetStore, } from './dataset-store.js';
|
|
7
|
+
export type { CreateDatasetInput, DatasetListOptions, DatasetListPage, DatasetLoadOptions, DatasetMetadata, DatasetPage, } from './types.js';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/dataset-store/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EACf,kBAAkB,EAClB,eAAe,EACf,WAAW,GACZ,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/services/dataset-store/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,oBAAoB,CAAC"}
|