fix(services): resolve project identifier in queries/work packages and use results link
This commit is contained in:
@@ -32,6 +32,7 @@ test_project.description = 'Dedicated test project for openproject-mcp companion
|
||||
test_project.public = true
|
||||
test_project.workspace_type = 'project' if test_project.respond_to?(:workspace_type=)
|
||||
test_project.types = Type.all if Type.any?
|
||||
test_project.enabled_module_names = OpenProject::AccessControl.available_project_modules if defined?(OpenProject::AccessControl)
|
||||
test_project.save!(validate: false)
|
||||
puts "[Seeder] Ensured project 'MCP Test Project' (ID: #{test_project.id}, identifier: #{test_project.identifier})."
|
||||
|
||||
|
||||
+1
-3
@@ -52,10 +52,8 @@ OPENPROJECT_API_KEY=${API_KEY}
|
||||
OPENPROJECT_TEST_PROJECT=${PROJECT_IDENTIFIER}
|
||||
EOF
|
||||
|
||||
# Also update .env.local if not present or populate key
|
||||
if [ ! -f "${ROOT_DIR}/.env.local" ]; then
|
||||
# Also update .env.local
|
||||
cp "${ROOT_DIR}/.env.test" "${ROOT_DIR}/.env.local"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "[seed.sh] Success! Test environment configured."
|
||||
|
||||
@@ -12,3 +12,24 @@ import type { OpenProjectClient } from "../client/api-client.ts";
|
||||
export function resolveClient(client?: OpenProjectClient): OpenProjectClient {
|
||||
return client ?? getRequestContext().client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a numeric project ID from either a number or string identifier.
|
||||
* If the value is a number or integer string, returns the parsed integer.
|
||||
* Otherwise, queries the OpenProject API for the project by identifier to get its numeric ID.
|
||||
*/
|
||||
export async function resolveProjectId(
|
||||
projectId: number | string,
|
||||
client?: OpenProjectClient
|
||||
): Promise<number> {
|
||||
if (typeof projectId === "number") {
|
||||
return projectId;
|
||||
}
|
||||
const trimmed = projectId.trim();
|
||||
if (/^\d+$/.test(trimmed)) {
|
||||
return parseInt(trimmed, 10);
|
||||
}
|
||||
const opClient = resolveClient(client);
|
||||
const response = await opClient.get<{ id: number }>(`projects/${encodeURIComponent(trimmed)}`);
|
||||
return response.id;
|
||||
}
|
||||
|
||||
+18
-4
@@ -2,7 +2,7 @@
|
||||
* Queries Domain Service.
|
||||
*/
|
||||
|
||||
import type { OpenProjectClient } from "../client/api-client.ts";
|
||||
import { OpenProjectNotFoundError, type OpenProjectClient } from "../client/api-client.ts";
|
||||
import {
|
||||
normalizeQuery,
|
||||
normalizeQuerySummary,
|
||||
@@ -17,7 +17,7 @@ import type {
|
||||
QuerySummary,
|
||||
WorkPackageSummary,
|
||||
} from "../client/types.ts";
|
||||
import { resolveClient } from "./helper.ts";
|
||||
import { resolveClient, resolveProjectId } from "./helper.ts";
|
||||
|
||||
export interface ListQueriesParams {
|
||||
projectId?: number | string;
|
||||
@@ -43,9 +43,10 @@ export async function listQueries(
|
||||
if (params?.pageSize !== undefined) query.pageSize = params.pageSize;
|
||||
if (params?.offset !== undefined) query.offset = params.offset;
|
||||
|
||||
if (params?.projectId !== undefined) {
|
||||
if (params?.projectId !== undefined && params.projectId !== "") {
|
||||
const numericProjectId = await resolveProjectId(params.projectId, opClient);
|
||||
query.filters = JSON.stringify([
|
||||
{ project: { operator: "=", values: [String(params.projectId)] } },
|
||||
{ project: { operator: "=", values: [String(numericProjectId)] } },
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -79,9 +80,22 @@ export async function getQueryResults(
|
||||
if (params?.pageSize !== undefined) query.pageSize = params.pageSize;
|
||||
if (params?.offset !== undefined) query.offset = params.offset;
|
||||
|
||||
try {
|
||||
const response = await opClient.get<HalCollection<HalResource>>(
|
||||
`queries/${id}/results`,
|
||||
query
|
||||
);
|
||||
return unpackCollection(response, normalizeWorkPackageSummary);
|
||||
} catch (err) {
|
||||
if (err instanceof OpenProjectNotFoundError) {
|
||||
// In OpenProject API v3, query results endpoint is dynamically linked in query._links.results.href
|
||||
const queryDetail = await opClient.get<HalResource>(`queries/${id}`);
|
||||
const resultsHref = queryDetail._links?.results?.href;
|
||||
if (typeof resultsHref === "string" && resultsHref.length > 0) {
|
||||
const response = await opClient.get<HalCollection<HalResource>>(resultsHref, query);
|
||||
return unpackCollection(response, normalizeWorkPackageSummary);
|
||||
}
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ import type {
|
||||
WorkPackageFilterParams,
|
||||
WorkPackageSummary,
|
||||
} from "../client/types.ts";
|
||||
import { resolveClient } from "./helper.ts";
|
||||
import { resolveClient, resolveProjectId } from "./helper.ts";
|
||||
|
||||
export interface ListWorkPackagesParams extends WorkPackageFilterParams {
|
||||
pageSize?: number;
|
||||
@@ -46,7 +46,12 @@ export async function listWorkPackages(
|
||||
if (params?.sortBy !== undefined) query.sortBy = params.sortBy;
|
||||
|
||||
if (params) {
|
||||
const filters = buildWorkPackageFilters(params);
|
||||
let filterParams = params;
|
||||
if (params.projectId !== undefined && params.projectId !== "") {
|
||||
const numericProjectId = await resolveProjectId(params.projectId, opClient);
|
||||
filterParams = { ...params, projectId: numericProjectId };
|
||||
}
|
||||
const filters = buildWorkPackageFilters(filterParams);
|
||||
if (filters.length > 0) {
|
||||
query.filters = JSON.stringify(filters);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user