Skip to content

Commit 92d7bd5

Browse files
feat(tasks): add operationId fields to OpenAPI operations for Redoc deep-linking
Promotes operationId fields from trawl_node to devkit. Every operation in modules/tasks/doc/tasks.yml now has a unique camelCase operationId (getTaskStats, listTasks, createTask, getTask, updateTask, deleteTask), enabling stable per-operation deep links in Redoc and compatibility with API doc generators. Purely additive — no behavior change. Adds tasks.openapi-operationid.unit.tests.js to assert every operation has a defined, unique operationId. Part of infra plan 2026-06-01-trawl-promote-up-followups.md Task 3.
1 parent 7ed5291 commit 92d7bd5

2 files changed

Lines changed: 35 additions & 0 deletions

File tree

modules/tasks/doc/tasks.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ paths:
77
get:
88
tags:
99
- Tasks
10+
operationId: getTaskStats
1011
summary: Get task statistics
1112
description: Returns the estimated total number of tasks. Public endpoint — no authentication required.
1213
responses:
@@ -29,6 +30,7 @@ paths:
2930
get:
3031
tags:
3132
- Tasks
33+
operationId: listTasks
3234
summary: List tasks
3335
description: Returns all tasks scoped to the current organization. Requires authentication.
3436
security:
@@ -59,6 +61,7 @@ paths:
5961
post:
6062
tags:
6163
- Tasks
64+
operationId: createTask
6265
summary: Create a task
6366
description: Creates a new task scoped to the current organization. The requesting user is set as the task owner.
6467
security:
@@ -94,6 +97,7 @@ paths:
9497
get:
9598
tags:
9699
- Tasks
100+
operationId: getTask
97101
summary: Get a task
98102
description: Returns a single task by ID. Ownership is enforced by CASL policy.
99103
security:
@@ -123,6 +127,7 @@ paths:
123127
put:
124128
tags:
125129
- Tasks
130+
operationId: updateTask
126131
summary: Update a task
127132
description: Updates an existing task. All fields are optional — only provided fields are updated. Ownership is enforced by CASL policy.
128133
security:
@@ -160,6 +165,7 @@ paths:
160165
delete:
161166
tags:
162167
- Tasks
168+
operationId: deleteTask
163169
summary: Delete a task
164170
description: Deletes a task by ID. Ownership is enforced by CASL policy.
165171
security:
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { describe, test, expect } from '@jest/globals';
2+
import yaml from 'js-yaml';
3+
import fs from 'fs';
4+
import path from 'path';
5+
import { fileURLToPath } from 'url';
6+
7+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
8+
9+
describe('modules/tasks/doc/tasks.yml — OpenAPI operationIds:', () => {
10+
const specPath = path.resolve(__dirname, '../doc/tasks.yml');
11+
const spec = yaml.load(fs.readFileSync(specPath, 'utf8'));
12+
13+
test('every operation has a unique operationId', () => {
14+
const operationIds = [];
15+
for (const [, pathItem] of Object.entries(spec.paths ?? {})) {
16+
for (const [method, operation] of Object.entries(pathItem)) {
17+
if (['get', 'post', 'put', 'patch', 'delete'].includes(method)) {
18+
expect(operation.operationId).toBeDefined();
19+
expect(typeof operation.operationId).toBe('string');
20+
operationIds.push(operation.operationId);
21+
}
22+
}
23+
}
24+
// Uniqueness check
25+
expect(new Set(operationIds).size).toBe(operationIds.length);
26+
// At least one operationId (tasks.yml is not empty)
27+
expect(operationIds.length).toBeGreaterThan(0);
28+
});
29+
});

0 commit comments

Comments
 (0)