posha-api-mcp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +150 -0
- package/dist/api-client.d.ts +28 -0
- package/dist/api-client.d.ts.map +1 -0
- package/dist/api-client.js +106 -0
- package/dist/api-client.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +65 -0
- package/dist/index.js.map +1 -0
- package/dist/resource-metadata.d.ts +29 -0
- package/dist/resource-metadata.d.ts.map +1 -0
- package/dist/resource-metadata.js +277 -0
- package/dist/resource-metadata.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +20 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/image-tools.d.ts +3 -0
- package/dist/tools/image-tools.d.ts.map +1 -0
- package/dist/tools/image-tools.js +205 -0
- package/dist/tools/image-tools.js.map +1 -0
- package/dist/tools/machine-tools.d.ts +3 -0
- package/dist/tools/machine-tools.d.ts.map +1 -0
- package/dist/tools/machine-tools.js +59 -0
- package/dist/tools/machine-tools.js.map +1 -0
- package/dist/tools/resource-tools.d.ts +3 -0
- package/dist/tools/resource-tools.d.ts.map +1 -0
- package/dist/tools/resource-tools.js +181 -0
- package/dist/tools/resource-tools.js.map +1 -0
- package/dist/tools/session-tools.d.ts +3 -0
- package/dist/tools/session-tools.d.ts.map +1 -0
- package/dist/tools/session-tools.js +117 -0
- package/dist/tools/session-tools.js.map +1 -0
- package/package.json +37 -0
package/README.md
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# Posha API MCP Server
|
|
2
|
+
|
|
3
|
+
MCP (Model Context Protocol) server that provides AI assistants with read-only access to the Posha API. Supports 13 tools covering all 45 endpoints across 17 resources.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
cd resource-api-mcp
|
|
9
|
+
npm install
|
|
10
|
+
npm run build
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Configuration
|
|
14
|
+
|
|
15
|
+
| Variable | Required | Default | Description |
|
|
16
|
+
|----------|----------|---------|-------------|
|
|
17
|
+
| `RESOURCE_API_BASE_URL` | Yes | — | Posha API base URL (e.g. `http://localhost:8080/servicekit/api/v1`) |
|
|
18
|
+
| `RESOURCE_API_KEY` | Yes | — | API key for `X-API-Key` header |
|
|
19
|
+
| `RESOURCE_API_BEARER_TOKEN` | No | — | Firebase JWT for endpoints protected by Spring Security (e.g. `/recipes/**`) |
|
|
20
|
+
| `MCP_TRANSPORT` | No | `stdio` | Transport: `stdio` or `sse` |
|
|
21
|
+
| `MCP_PORT` | No | `3001` | SSE server port (only when `MCP_TRANSPORT=sse`) |
|
|
22
|
+
|
|
23
|
+
## Setup
|
|
24
|
+
|
|
25
|
+
### Install via npm
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install -g posha-api-mcp
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Cursor
|
|
32
|
+
|
|
33
|
+
Add to `.cursor/mcp.json` (global) or project-level:
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"mcpServers": {
|
|
38
|
+
"posha-api": {
|
|
39
|
+
"command": "npx",
|
|
40
|
+
"args": ["-y", "posha-api-mcp"],
|
|
41
|
+
"env": {
|
|
42
|
+
"RESOURCE_API_BASE_URL": "https://your-api-host/servicekit/api/v1",
|
|
43
|
+
"RESOURCE_API_KEY": "<your-api-key>",
|
|
44
|
+
"RESOURCE_API_BEARER_TOKEN": "<optional-firebase-jwt-for-recipes>"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Claude Desktop
|
|
52
|
+
|
|
53
|
+
Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"mcpServers": {
|
|
58
|
+
"posha-api": {
|
|
59
|
+
"command": "npx",
|
|
60
|
+
"args": ["-y", "posha-api-mcp"],
|
|
61
|
+
"env": {
|
|
62
|
+
"RESOURCE_API_BASE_URL": "https://your-api-host/servicekit/api/v1",
|
|
63
|
+
"RESOURCE_API_KEY": "<your-api-key>",
|
|
64
|
+
"RESOURCE_API_BEARER_TOKEN": "<optional-firebase-jwt-for-recipes>"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Claude Code
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
claude mcp add posha-api -- npx -y posha-api-mcp
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Then set environment variables in your shell or `.env` file.
|
|
78
|
+
|
|
79
|
+
## Available Tools
|
|
80
|
+
|
|
81
|
+
### Generic Resource Tools
|
|
82
|
+
|
|
83
|
+
| Tool | Description |
|
|
84
|
+
|------|-------------|
|
|
85
|
+
| `list_available_resources` | Lists all 17 resource types with filterable fields, operators, and sort options |
|
|
86
|
+
| `get_resource` | Get any resource by ID (user, session, recipe, machine, etc.) |
|
|
87
|
+
| `query_resources` | Query any resource with filters, sorting, pagination, and projection |
|
|
88
|
+
|
|
89
|
+
### Session Tools
|
|
90
|
+
|
|
91
|
+
| Tool | Description |
|
|
92
|
+
|------|-------------|
|
|
93
|
+
| `get_session_feedback` | Get feedback for a cooking session |
|
|
94
|
+
| `get_session_customisations` | Get pre-cooking customisations |
|
|
95
|
+
| `get_session_metadata` | Get session timing and step metadata |
|
|
96
|
+
| `query_session_logs` | Query session log entries (logs, images, or instructions) |
|
|
97
|
+
|
|
98
|
+
### Image Tools
|
|
99
|
+
|
|
100
|
+
| Tool | Description |
|
|
101
|
+
|------|-------------|
|
|
102
|
+
| `list_session_images` | List all images for a session |
|
|
103
|
+
| `get_session_instruction_images` | Get images for a specific instruction |
|
|
104
|
+
| `get_session_image_detail` | Get full metadata for an image |
|
|
105
|
+
| `search_images` | Cross-session image search with time range |
|
|
106
|
+
|
|
107
|
+
### Machine Tools
|
|
108
|
+
|
|
109
|
+
| Tool | Description |
|
|
110
|
+
|------|-------------|
|
|
111
|
+
| `get_machine_storage` | Get machine on-device storage snapshot |
|
|
112
|
+
| `get_machine_details` | Get machine users and/or crash dump files |
|
|
113
|
+
|
|
114
|
+
## Query Examples
|
|
115
|
+
|
|
116
|
+
### Find a user by email
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
Use get_resource with resourceType "users" and id "user@example.com"
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Query recent sessions for a user
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
Use query_resources with resourceType "sessions", filter by cookedBy.uid equals "<uid>",
|
|
126
|
+
sort by createdOn desc, limit 10
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Search images across sessions
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
Use search_images with startTime "2026-03-01T00:00:00Z", endTime "2026-03-31T00:00:00Z",
|
|
133
|
+
machineId "g3.33", containerTypes ["Macro"]
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## AWS Deployment (SSE mode)
|
|
137
|
+
|
|
138
|
+
Build and deploy the Docker image:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
docker build -t posha-api-mcp .
|
|
142
|
+
docker run -p 3001:3001 \
|
|
143
|
+
-e RESOURCE_API_BASE_URL=http://resource-api:8080/servicekit/api/v1 \
|
|
144
|
+
-e RESOURCE_API_KEY=your-key \
|
|
145
|
+
posha-api-mcp
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Clients connect via `http://<host>:3001/sse`.
|
|
149
|
+
|
|
150
|
+
Health check: `GET http://<host>:3001/health`
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP client for the Posha API. Handles authentication, timeouts,
|
|
3
|
+
* and structured error mapping for all REST calls.
|
|
4
|
+
*/
|
|
5
|
+
export interface ApiClientConfig {
|
|
6
|
+
baseUrl: string;
|
|
7
|
+
apiKey: string;
|
|
8
|
+
bearerToken?: string;
|
|
9
|
+
timeoutMs?: number;
|
|
10
|
+
}
|
|
11
|
+
export interface ApiError {
|
|
12
|
+
code: string;
|
|
13
|
+
message: string;
|
|
14
|
+
details?: unknown;
|
|
15
|
+
requestId?: string;
|
|
16
|
+
}
|
|
17
|
+
export declare class PoshaApiClient {
|
|
18
|
+
private baseUrl;
|
|
19
|
+
private apiKey;
|
|
20
|
+
private bearerToken?;
|
|
21
|
+
private timeoutMs;
|
|
22
|
+
constructor(config: ApiClientConfig);
|
|
23
|
+
get<T>(path: string, params?: Record<string, string>): Promise<T>;
|
|
24
|
+
post<T>(path: string, body: unknown): Promise<T>;
|
|
25
|
+
private request;
|
|
26
|
+
}
|
|
27
|
+
export declare function getClient(): PoshaApiClient;
|
|
28
|
+
//# sourceMappingURL=api-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,WAAW,CAAC,CAAS;IAC7B,OAAO,CAAC,SAAS,CAAS;gBAEd,MAAM,EAAE,eAAe;IAO7B,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAYjE,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;YAQxC,OAAO;CA0DtB;AAID,wBAAgB,SAAS,IAAI,cAAc,CAkB1C"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP client for the Posha API. Handles authentication, timeouts,
|
|
3
|
+
* and structured error mapping for all REST calls.
|
|
4
|
+
*/
|
|
5
|
+
export class PoshaApiClient {
|
|
6
|
+
baseUrl;
|
|
7
|
+
apiKey;
|
|
8
|
+
bearerToken;
|
|
9
|
+
timeoutMs;
|
|
10
|
+
constructor(config) {
|
|
11
|
+
this.baseUrl = config.baseUrl.replace(/\/+$/, "");
|
|
12
|
+
this.apiKey = config.apiKey;
|
|
13
|
+
this.bearerToken = config.bearerToken;
|
|
14
|
+
this.timeoutMs = config.timeoutMs ?? 15_000;
|
|
15
|
+
}
|
|
16
|
+
async get(path, params) {
|
|
17
|
+
const url = new URL(`${this.baseUrl}${path}`);
|
|
18
|
+
if (params) {
|
|
19
|
+
for (const [key, value] of Object.entries(params)) {
|
|
20
|
+
if (value !== undefined && value !== null) {
|
|
21
|
+
url.searchParams.set(key, value);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return this.request(url.toString(), { method: "GET" });
|
|
26
|
+
}
|
|
27
|
+
async post(path, body) {
|
|
28
|
+
return this.request(`${this.baseUrl}${path}`, {
|
|
29
|
+
method: "POST",
|
|
30
|
+
headers: { "Content-Type": "application/json" },
|
|
31
|
+
body: JSON.stringify(body),
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
async request(url, init) {
|
|
35
|
+
const controller = new AbortController();
|
|
36
|
+
const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
37
|
+
try {
|
|
38
|
+
const response = await fetch(url, {
|
|
39
|
+
...init,
|
|
40
|
+
signal: controller.signal,
|
|
41
|
+
headers: {
|
|
42
|
+
...init.headers,
|
|
43
|
+
"X-API-Key": this.apiKey,
|
|
44
|
+
...(this.bearerToken && { Authorization: `Bearer ${this.bearerToken}` }),
|
|
45
|
+
Accept: "application/json",
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
if (!response.ok) {
|
|
49
|
+
const errorBody = await response.text();
|
|
50
|
+
let apiError;
|
|
51
|
+
try {
|
|
52
|
+
const parsed = JSON.parse(errorBody);
|
|
53
|
+
apiError = {
|
|
54
|
+
code: parsed.error?.code ?? `HTTP_${response.status}`,
|
|
55
|
+
message: parsed.error?.message ?? response.statusText,
|
|
56
|
+
details: parsed.error?.details,
|
|
57
|
+
requestId: parsed.requestId,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
apiError = {
|
|
62
|
+
code: `HTTP_${response.status}`,
|
|
63
|
+
message: `${response.statusText}: ${errorBody.slice(0, 500)}`,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
throw apiError;
|
|
67
|
+
}
|
|
68
|
+
return (await response.json());
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
if (err && typeof err === "object" && "code" in err) {
|
|
72
|
+
throw err; // already an ApiError
|
|
73
|
+
}
|
|
74
|
+
if (err instanceof DOMException && err.name === "AbortError") {
|
|
75
|
+
throw {
|
|
76
|
+
code: "TIMEOUT",
|
|
77
|
+
message: `Request timed out after ${this.timeoutMs}ms`,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
throw {
|
|
81
|
+
code: "CONNECTION_ERROR",
|
|
82
|
+
message: `Failed to connect to Posha API: ${err instanceof Error ? err.message : String(err)}`,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
finally {
|
|
86
|
+
clearTimeout(timeout);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
let _client = null;
|
|
91
|
+
export function getClient() {
|
|
92
|
+
if (!_client) {
|
|
93
|
+
const baseUrl = process.env.RESOURCE_API_BASE_URL;
|
|
94
|
+
const apiKey = process.env.RESOURCE_API_KEY;
|
|
95
|
+
if (!baseUrl) {
|
|
96
|
+
throw new Error("RESOURCE_API_BASE_URL environment variable is required");
|
|
97
|
+
}
|
|
98
|
+
if (!apiKey) {
|
|
99
|
+
throw new Error("RESOURCE_API_KEY environment variable is required");
|
|
100
|
+
}
|
|
101
|
+
const bearerToken = process.env.RESOURCE_API_BEARER_TOKEN;
|
|
102
|
+
_client = new PoshaApiClient({ baseUrl, apiKey, bearerToken });
|
|
103
|
+
}
|
|
104
|
+
return _client;
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=api-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.js","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
+
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
|
4
|
+
import { createServer } from "./server.js";
|
|
5
|
+
import http from "node:http";
|
|
6
|
+
const transport = process.env.MCP_TRANSPORT ?? "stdio";
|
|
7
|
+
async function main() {
|
|
8
|
+
const server = createServer();
|
|
9
|
+
if (transport === "sse") {
|
|
10
|
+
await startSSE(server);
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
await startStdio(server);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
async function startStdio(server) {
|
|
17
|
+
const transport = new StdioServerTransport();
|
|
18
|
+
await server.connect(transport);
|
|
19
|
+
console.error("Posha API MCP server running on stdio");
|
|
20
|
+
}
|
|
21
|
+
async function startSSE(server) {
|
|
22
|
+
const port = parseInt(process.env.MCP_PORT ?? "3001", 10);
|
|
23
|
+
let sseTransport = null;
|
|
24
|
+
const httpServer = http.createServer(async (req, res) => {
|
|
25
|
+
const url = new URL(req.url ?? "/", `http://localhost:${port}`);
|
|
26
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
27
|
+
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
|
28
|
+
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
|
|
29
|
+
if (req.method === "OPTIONS") {
|
|
30
|
+
res.writeHead(204);
|
|
31
|
+
res.end();
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (url.pathname === "/sse" && req.method === "GET") {
|
|
35
|
+
sseTransport = new SSEServerTransport("/messages", res);
|
|
36
|
+
await server.connect(sseTransport);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (url.pathname === "/messages" && req.method === "POST") {
|
|
40
|
+
if (!sseTransport) {
|
|
41
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
42
|
+
res.end(JSON.stringify({ error: "No SSE connection established. Connect to /sse first." }));
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
await sseTransport.handlePostMessage(req, res);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (url.pathname === "/health") {
|
|
49
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
50
|
+
res.end(JSON.stringify({ status: "ok", transport: "sse" }));
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
54
|
+
res.end(JSON.stringify({ error: "Not found" }));
|
|
55
|
+
});
|
|
56
|
+
httpServer.listen(port, () => {
|
|
57
|
+
console.error(`Posha API MCP server running on SSE at http://0.0.0.0:${port}/sse`);
|
|
58
|
+
console.error(`Health check: http://0.0.0.0:${port}/health`);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
main().catch((err) => {
|
|
62
|
+
console.error("Fatal error:", err);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
});
|
|
65
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAC7E,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,OAAO,CAAC;AAEvD,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAE9B,IAAI,SAAS,KAAK,KAAK,EAAE,CAAC;QACxB,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC;IACzB,CAAC;SAAM,CAAC;QACN,MAAM,UAAU,CAAC,MAAM,CAAC,CAAC;IAC3B,CAAC;AACH,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,MAAuC;IAC/D,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;AACzD,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,MAAuC;IAC7D,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;IAE1D,IAAI,YAAY,GAA8B,IAAI,CAAC;IAEnD,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;QACtD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,oBAAoB,IAAI,EAAE,CAAC,CAAC;QAEhE,GAAG,CAAC,SAAS,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC;QAClD,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,oBAAoB,CAAC,CAAC;QACpE,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,cAAc,CAAC,CAAC;QAE9D,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC7B,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YACnB,GAAG,CAAC,GAAG,EAAE,CAAC;YACV,OAAO;QACT,CAAC;QAED,IAAI,GAAG,CAAC,QAAQ,KAAK,MAAM,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;YACpD,YAAY,GAAG,IAAI,kBAAkB,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;YACxD,MAAM,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;YACnC,OAAO;QACT,CAAC;QAED,IAAI,GAAG,CAAC,QAAQ,KAAK,WAAW,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC1D,IAAI,CAAC,YAAY,EAAE,CAAC;gBAClB,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;gBAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,uDAAuD,EAAE,CAAC,CAAC,CAAC;gBAC5F,OAAO;YACT,CAAC;YACD,MAAM,YAAY,CAAC,iBAAiB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YAC/C,OAAO;QACT,CAAC;QAED,IAAI,GAAG,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC/B,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;YAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;YAC5D,OAAO;QACT,CAAC;QAED,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;QAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;QAC3B,OAAO,CAAC,KAAK,CAAC,yDAAyD,IAAI,MAAM,CAAC,CAAC;QACnF,OAAO,CAAC,KAAK,CAAC,gCAAgC,IAAI,SAAS,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;AACL,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;IACnC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Static metadata for all 17 resources, derived from the Java FieldRegistry
|
|
3
|
+
* implementations. Each entry describes the filterable/sortable fields,
|
|
4
|
+
* their types, tiers, and allowed operators.
|
|
5
|
+
*/
|
|
6
|
+
export type FieldType = "STRING" | "INTEGER" | "LONG" | "DOUBLE" | "BOOLEAN" | "DATETIME";
|
|
7
|
+
export type FieldTier = "TIER_1" | "TIER_2" | "TIER_3";
|
|
8
|
+
export type FilterOperator = "eq" | "ne" | "gt" | "gte" | "lt" | "lte" | "in" | "nin" | "regex" | "exists";
|
|
9
|
+
export interface FieldDef {
|
|
10
|
+
name: string;
|
|
11
|
+
type: FieldType;
|
|
12
|
+
tier: FieldTier;
|
|
13
|
+
sortable: boolean;
|
|
14
|
+
operators: FilterOperator[];
|
|
15
|
+
}
|
|
16
|
+
export interface ResourceDef {
|
|
17
|
+
resourceName: string;
|
|
18
|
+
slug: string;
|
|
19
|
+
collectionName: string;
|
|
20
|
+
idField: string;
|
|
21
|
+
approximateDocCount: string;
|
|
22
|
+
fields: FieldDef[];
|
|
23
|
+
}
|
|
24
|
+
export declare const RESOURCES: ResourceDef[];
|
|
25
|
+
export declare const RESOURCE_SLUGS: string[];
|
|
26
|
+
export declare function getResourceBySlug(slug: string): ResourceDef | undefined;
|
|
27
|
+
export declare function getFilterableFields(resource: ResourceDef): FieldDef[];
|
|
28
|
+
export declare function getSortableFields(resource: ResourceDef): FieldDef[];
|
|
29
|
+
//# sourceMappingURL=resource-metadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-metadata.d.ts","sourceRoot":"","sources":["../src/resource-metadata.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,UAAU,CAAC;AAC1F,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AACvD,MAAM,MAAM,cAAc,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE3G,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,cAAc,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,MAAM,EAAE,QAAQ,EAAE,CAAC;CACpB;AAYD,eAAO,MAAM,SAAS,EAAE,WAAW,EAiQlC,CAAC;AAEF,eAAO,MAAM,cAAc,UAA+B,CAAC;AAE3D,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAEvE;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,WAAW,GAAG,QAAQ,EAAE,CAErE;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,WAAW,GAAG,QAAQ,EAAE,CAEnE"}
|