@critical-path/server 0.15.0 → 0.17.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/CHANGELOG.md +60 -0
- package/README.md +22 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/index.test.js +93 -24
- package/dist/index.test.js.map +1 -1
- package/dist/openapi.d.ts +30 -0
- package/dist/openapi.d.ts.map +1 -0
- package/dist/openapi.js +139 -0
- package/dist/openapi.js.map +1 -0
- package/dist/openapi.test.d.ts +2 -0
- package/dist/openapi.test.d.ts.map +1 -0
- package/dist/openapi.test.js +86 -0
- package/dist/openapi.test.js.map +1 -0
- package/dist/router.d.ts +19 -3
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +60 -51
- package/dist/router.js.map +1 -1
- package/package.json +3 -2
- package/src/index.test.ts +116 -24
- package/src/index.ts +1 -0
- package/src/openapi.test.ts +95 -0
- package/src/openapi.ts +178 -0
- package/src/router.ts +76 -53
- package/tsconfig.tsbuildinfo +1 -1
package/dist/openapi.js
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { zodToJsonSchema } from 'zod-to-json-schema';
|
|
2
|
+
import * as schemas from '@critical-path/core/schemas';
|
|
3
|
+
/** Every route served by `CriticalPathRouter`. Kept in sync by the route drift test. */
|
|
4
|
+
export const ROUTES = [
|
|
5
|
+
{ method: 'get', path: '/workflows', summary: 'List workflows', tag: 'Workflows', responseKey: 'workflows' },
|
|
6
|
+
{ method: 'post', path: '/workflows', summary: 'Create a workflow', tag: 'Workflows', body: schemas.CreateWorkflowSchema, responseKey: 'workflow', status: 201 },
|
|
7
|
+
{ method: 'get', path: '/workflows/{workflowId}', summary: 'Get a workflow', tag: 'Workflows', responseKey: 'workflow' },
|
|
8
|
+
{ method: 'patch', path: '/workflows/{workflowId}', summary: 'Update a workflow', tag: 'Workflows', body: schemas.UpdateWorkflowSchema, responseKey: 'workflow' },
|
|
9
|
+
{ method: 'delete', path: '/workflows/{workflowId}', summary: 'Delete a workflow', tag: 'Workflows' },
|
|
10
|
+
{ method: 'get', path: '/projects', summary: 'List projects', tag: 'Projects', responseKey: 'projects' },
|
|
11
|
+
{ method: 'post', path: '/projects', summary: 'Create a project', tag: 'Projects', body: schemas.CreateProjectSchema, responseKey: 'project', status: 201 },
|
|
12
|
+
{ method: 'get', path: '/projects/{projectId}', summary: 'Get a project', tag: 'Projects', responseKey: 'project' },
|
|
13
|
+
{ method: 'patch', path: '/projects/{projectId}', summary: 'Update a project', tag: 'Projects', body: schemas.UpdateProjectSchema, responseKey: 'project' },
|
|
14
|
+
{ method: 'delete', path: '/projects/{projectId}', summary: 'Delete a project and its tasks', tag: 'Projects' },
|
|
15
|
+
{ method: 'get', path: '/projects/{projectId}/critical-path', summary: 'Critical path (CPM) analysis', tag: 'Analysis', responseKey: 'analysis' },
|
|
16
|
+
{ method: 'get', path: '/projects/{projectId}/ladder', summary: 'Timeline ladder of abstraction', tag: 'Analysis', query: ['level', 'containerId', 'iterationId'], responseKey: 'ladder' },
|
|
17
|
+
{ method: 'get', path: '/projects/{projectId}/workload', summary: 'Project workload distribution', tag: 'Analysis', query: ['startDate', 'endDate', 'interval', 'groupBy', 'metric', 'defaultWeeklyCapacityHours'], responseKey: 'workload' },
|
|
18
|
+
{ method: 'get', path: '/tasks', summary: 'List tasks', tag: 'Tasks', query: ['projectId'], responseKey: 'tasks' },
|
|
19
|
+
{ method: 'post', path: '/tasks', summary: 'Create a task', tag: 'Tasks', body: schemas.CreateTaskSchema, responseKey: 'task', status: 201 },
|
|
20
|
+
{ method: 'get', path: '/tasks/{taskId}', summary: 'Get a task', tag: 'Tasks', responseKey: 'task' },
|
|
21
|
+
{ method: 'patch', path: '/tasks/{taskId}', summary: 'Update a task (enforces workflow transitions)', tag: 'Tasks', body: schemas.UpdateTaskSchema, responseKey: 'task' },
|
|
22
|
+
{ method: 'delete', path: '/tasks/{taskId}', summary: 'Delete a task', tag: 'Tasks' },
|
|
23
|
+
{ method: 'get', path: '/tasks/{taskId}/comments', summary: 'List task comments', tag: 'Comments', responseKey: 'comments' },
|
|
24
|
+
{ method: 'post', path: '/tasks/{taskId}/comments', summary: 'Comment on a task', tag: 'Comments', body: schemas.CreateCommentSchema.omit({ taskId: true }), responseKey: 'comment', status: 201 },
|
|
25
|
+
{ method: 'get', path: '/tasks/{taskId}/attachments', summary: 'List task attachments', tag: 'Attachments', responseKey: 'attachments' },
|
|
26
|
+
{ method: 'post', path: '/tasks/{taskId}/attachments', summary: 'Attach a file link to a task', tag: 'Attachments', body: schemas.CreateAttachmentSchema.omit({ taskId: true }), responseKey: 'attachment', status: 201 },
|
|
27
|
+
{ method: 'get', path: '/tasks/{taskId}/dependencies', summary: 'Task dependency graph', tag: 'Dependencies', responseKey: 'graph' },
|
|
28
|
+
{ method: 'post', path: '/tasks/{taskId}/dependencies', summary: 'Add a dependency (409 on cycles)', tag: 'Dependencies', body: schemas.CreateDependencySchema, responseKey: 'dependency', status: 201 },
|
|
29
|
+
{ method: 'get', path: '/tasks/{taskId}/lifecycle', summary: 'Derived lifecycle state', tag: 'Tasks', responseKey: 'state' },
|
|
30
|
+
{ method: 'get', path: '/tasks/{taskId}/transitions', summary: 'Allowed status transitions', tag: 'Tasks' },
|
|
31
|
+
{ method: 'get', path: '/tasks/{taskId}/ladder', summary: 'Single-task ladder view', tag: 'Analysis', responseKey: 'taskLadder' },
|
|
32
|
+
{ method: 'get', path: '/tasks/{taskId}/metrics', summary: 'Task metrics and EVM', tag: 'Analysis', responseKey: 'metrics' },
|
|
33
|
+
{ method: 'get', path: '/tasks/{taskId}/progress-history', summary: 'Reconstructed progress history', tag: 'Analysis', responseKey: 'progressHistory' },
|
|
34
|
+
{ method: 'get', path: '/teams', summary: 'List teams', tag: 'Teams', responseKey: 'teams' },
|
|
35
|
+
{ method: 'post', path: '/teams', summary: 'Create a team', tag: 'Teams', body: schemas.CreateTeamSchema, responseKey: 'team', status: 201 },
|
|
36
|
+
{ method: 'get', path: '/teams/{teamId}', summary: 'Get a team', tag: 'Teams', responseKey: 'team' },
|
|
37
|
+
{ method: 'patch', path: '/teams/{teamId}', summary: 'Update a team', tag: 'Teams', body: schemas.UpdateTeamSchema, responseKey: 'team' },
|
|
38
|
+
{ method: 'delete', path: '/teams/{teamId}', summary: 'Delete a team', tag: 'Teams' },
|
|
39
|
+
{ method: 'get', path: '/containers', summary: 'List containers', tag: 'Containers', query: ['projectId!'], responseKey: 'containers' },
|
|
40
|
+
{ method: 'post', path: '/containers', summary: 'Create a container', tag: 'Containers', body: schemas.CreateContainerSchema, responseKey: 'container', status: 201 },
|
|
41
|
+
{ method: 'get', path: '/containers/{containerId}', summary: 'Get a container', tag: 'Containers', responseKey: 'container' },
|
|
42
|
+
{ method: 'patch', path: '/containers/{containerId}', summary: 'Update a container', tag: 'Containers', body: schemas.UpdateContainerSchema, responseKey: 'container' },
|
|
43
|
+
{ method: 'delete', path: '/containers/{containerId}', summary: 'Delete a container', tag: 'Containers' },
|
|
44
|
+
{ method: 'get', path: '/deliverables', summary: 'List deliverables', tag: 'Deliverables', query: ['projectId!'], responseKey: 'deliverables' },
|
|
45
|
+
{ method: 'post', path: '/deliverables', summary: 'Create a deliverable', tag: 'Deliverables', body: schemas.CreateDeliverableSchema, responseKey: 'deliverable', status: 201 },
|
|
46
|
+
{ method: 'get', path: '/deliverables/{deliverableId}', summary: 'Get a deliverable', tag: 'Deliverables', responseKey: 'deliverable' },
|
|
47
|
+
{ method: 'get', path: '/deliverables/{deliverableId}/summary', summary: 'Deliverable rollup summary', tag: 'Deliverables', responseKey: 'summary' },
|
|
48
|
+
{ method: 'patch', path: '/deliverables/{deliverableId}', summary: 'Update a deliverable', tag: 'Deliverables', body: schemas.UpdateDeliverableSchema, responseKey: 'deliverable' },
|
|
49
|
+
{ method: 'delete', path: '/deliverables/{deliverableId}', summary: 'Delete a deliverable', tag: 'Deliverables' },
|
|
50
|
+
{ method: 'get', path: '/iterations', summary: 'List iterations', tag: 'Iterations', query: ['projectId!'], responseKey: 'iterations' },
|
|
51
|
+
{ method: 'post', path: '/iterations', summary: 'Create an iteration', tag: 'Iterations', body: schemas.CreateIterationSchema, responseKey: 'iteration', status: 201 },
|
|
52
|
+
{ method: 'get', path: '/iterations/{iterationId}', summary: 'Get an iteration', tag: 'Iterations', responseKey: 'iteration' },
|
|
53
|
+
{ method: 'patch', path: '/iterations/{iterationId}', summary: 'Update an iteration', tag: 'Iterations', body: schemas.UpdateIterationSchema, responseKey: 'iteration' },
|
|
54
|
+
{ method: 'delete', path: '/iterations/{iterationId}', summary: 'Delete an iteration', tag: 'Iterations' },
|
|
55
|
+
{ method: 'get', path: '/activities', summary: 'Activity (audit) stream', tag: 'Activity', query: ['projectId', 'taskId'], responseKey: 'activities' },
|
|
56
|
+
{ method: 'get', path: '/comments', summary: 'List comments for a task', tag: 'Comments', query: ['taskId!'], responseKey: 'comments' },
|
|
57
|
+
{ method: 'post', path: '/comments', summary: 'Create a comment', tag: 'Comments', body: schemas.CreateCommentSchema, responseKey: 'comment', status: 201 },
|
|
58
|
+
{ method: 'get', path: '/comments/{commentId}', summary: 'Get a comment', tag: 'Comments', responseKey: 'comment' },
|
|
59
|
+
{ method: 'patch', path: '/comments/{commentId}', summary: 'Update a comment', tag: 'Comments', body: schemas.UpdateCommentSchema, responseKey: 'comment' },
|
|
60
|
+
{ method: 'delete', path: '/comments/{commentId}', summary: 'Delete a comment', tag: 'Comments' },
|
|
61
|
+
{ method: 'post', path: '/comments/{commentId}/reactions', summary: 'Add a reaction', tag: 'Comments', body: schemas.CommentReactionSchema, responseKey: 'comment' },
|
|
62
|
+
{ method: 'delete', path: '/comments/{commentId}/reactions', summary: 'Remove a reaction', tag: 'Comments', query: ['emoji!'], responseKey: 'comment' },
|
|
63
|
+
{ method: 'get', path: '/attachments', summary: 'List attachments', tag: 'Attachments', query: ['taskId', 'projectId', 'commentId'], responseKey: 'attachments' },
|
|
64
|
+
{ method: 'post', path: '/attachments', summary: 'Register an attachment', tag: 'Attachments', body: schemas.CreateAttachmentSchema, responseKey: 'attachment', status: 201 },
|
|
65
|
+
{ method: 'post', path: '/attachments/upload', summary: 'Upload a file through the configured FileStorageAdapter', tag: 'Attachments', body: schemas.UploadAttachmentSchema, responseKey: 'attachment', status: 201 },
|
|
66
|
+
{ method: 'post', path: '/attachments/presign', summary: 'Request a presigned upload URL', tag: 'Attachments', body: schemas.PresignAttachmentSchema, responseKey: 'presigned' },
|
|
67
|
+
{ method: 'get', path: '/attachments/{attachmentId}', summary: 'Get an attachment', tag: 'Attachments', responseKey: 'attachment' },
|
|
68
|
+
{ method: 'delete', path: '/attachments/{attachmentId}', summary: 'Delete an attachment', tag: 'Attachments' },
|
|
69
|
+
{ method: 'get', path: '/time-entries', summary: 'List time entries for a task', tag: 'Time Tracking', query: ['taskId!'], responseKey: 'timeEntries' },
|
|
70
|
+
{ method: 'post', path: '/time-entries', summary: 'Log time against a task', tag: 'Time Tracking', body: schemas.LogTimeSchema, responseKey: 'timeEntry', status: 201 },
|
|
71
|
+
{ method: 'get', path: '/workload', summary: 'Workload distribution across projects', tag: 'Analysis', query: ['projectId', 'startDate', 'endDate', 'interval', 'groupBy', 'metric', 'defaultWeeklyCapacityHours'], responseKey: 'workload' },
|
|
72
|
+
{ method: 'post', path: '/status', summary: 'Publish an agent status update', tag: 'Agents' }
|
|
73
|
+
];
|
|
74
|
+
const errorResponse = {
|
|
75
|
+
description: 'Error',
|
|
76
|
+
content: {
|
|
77
|
+
'application/json': {
|
|
78
|
+
schema: {
|
|
79
|
+
type: 'object',
|
|
80
|
+
properties: {
|
|
81
|
+
error: { type: 'string' },
|
|
82
|
+
issues: { type: 'array', items: { type: 'object', properties: { path: { type: 'string' }, message: { type: 'string' } } } }
|
|
83
|
+
},
|
|
84
|
+
required: ['error']
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
function toJsonSchema(schema) {
|
|
90
|
+
const { $schema: _ignored, ...json } = zodToJsonSchema(schema, { $refStrategy: 'none' });
|
|
91
|
+
return json;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Builds an OpenAPI 3.1 document for the router. Request bodies are generated from the same zod
|
|
95
|
+
* schemas the router validates with, so the contract cannot drift from enforcement.
|
|
96
|
+
*/
|
|
97
|
+
export function buildOpenApiDocument(options = {}) {
|
|
98
|
+
const paths = {};
|
|
99
|
+
for (const route of ROUTES) {
|
|
100
|
+
const pathParams = [...route.path.matchAll(/\{(\w+)\}/g)].map((m) => m[1]);
|
|
101
|
+
const parameters = [
|
|
102
|
+
...pathParams.map((name) => ({ name, in: 'path', required: true, schema: { type: 'string' } })),
|
|
103
|
+
...(route.query ?? []).map((q) => ({
|
|
104
|
+
name: q.replace(/!$/, ''),
|
|
105
|
+
in: 'query',
|
|
106
|
+
required: q.endsWith('!'),
|
|
107
|
+
schema: { type: 'string' }
|
|
108
|
+
}))
|
|
109
|
+
];
|
|
110
|
+
const status = String(route.status ?? 200);
|
|
111
|
+
const successSchema = route.responseKey
|
|
112
|
+
? { type: 'object', properties: { [route.responseKey]: {} }, required: [route.responseKey] }
|
|
113
|
+
: { type: 'object' };
|
|
114
|
+
paths[route.path] ??= {};
|
|
115
|
+
paths[route.path][route.method] = {
|
|
116
|
+
summary: route.summary,
|
|
117
|
+
tags: [route.tag],
|
|
118
|
+
...(parameters.length ? { parameters } : {}),
|
|
119
|
+
...(route.body
|
|
120
|
+
? { requestBody: { required: true, content: { 'application/json': { schema: toJsonSchema(route.body) } } } }
|
|
121
|
+
: {}),
|
|
122
|
+
responses: {
|
|
123
|
+
[status]: { description: 'Success', content: { 'application/json': { schema: successSchema } } },
|
|
124
|
+
'400': errorResponse,
|
|
125
|
+
'401': errorResponse,
|
|
126
|
+
'404': errorResponse,
|
|
127
|
+
...(route.path.endsWith('/dependencies') && route.method === 'post' ? { '409': errorResponse } : {}),
|
|
128
|
+
'500': errorResponse
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
return {
|
|
133
|
+
openapi: '3.1.0',
|
|
134
|
+
info: { title: options.title ?? 'Critical Path API', version: options.version ?? '1.0.0' },
|
|
135
|
+
...(options.serverUrl ? { servers: [{ url: options.serverUrl }] } : {}),
|
|
136
|
+
paths
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=openapi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openapi.js","sourceRoot":"","sources":["../src/openapi.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openapi.test.d.ts","sourceRoot":"","sources":["../src/openapi.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { CriticalPathRouter } from './router.js';
|
|
3
|
+
import { ROUTES, buildOpenApiDocument } from './openapi.js';
|
|
4
|
+
const base = 'http://localhost:3000/api/critical-path';
|
|
5
|
+
describe('OpenAPI document', () => {
|
|
6
|
+
it('documents every route the router serves, with matching response envelopes', async () => {
|
|
7
|
+
const router = new CriticalPathRouter();
|
|
8
|
+
const engine = router.engine;
|
|
9
|
+
const project = await engine.createProject({ key: 'OAS', name: 'OpenAPI' });
|
|
10
|
+
const task = await engine.createTask({ projectId: project.id, title: 'Task' });
|
|
11
|
+
const workflow = await engine.createWorkflow({ name: 'WF', statuses: [], transitions: [] });
|
|
12
|
+
const team = await engine.createTeam({ name: 'Team', memberIds: [] });
|
|
13
|
+
const container = await engine.createContainer({ projectId: project.id, name: 'Epic' });
|
|
14
|
+
const deliverable = await engine.createDeliverable({ projectId: project.id, title: 'Cut' });
|
|
15
|
+
const iteration = await engine.createIteration({ projectId: project.id, name: 'S1', status: 'planning' });
|
|
16
|
+
const comment = await engine.addComment({ taskId: task.id, content: 'hi', authorId: 'u1' });
|
|
17
|
+
const attachment = await engine.createAttachment({
|
|
18
|
+
taskId: task.id,
|
|
19
|
+
uploaderId: 'u1',
|
|
20
|
+
filename: 'a.md',
|
|
21
|
+
mimeType: 'text/markdown',
|
|
22
|
+
sizeBytes: 1,
|
|
23
|
+
url: 'https://example.com/a.md'
|
|
24
|
+
});
|
|
25
|
+
const ids = {
|
|
26
|
+
projectId: project.id,
|
|
27
|
+
taskId: task.id,
|
|
28
|
+
workflowId: workflow.id,
|
|
29
|
+
teamId: team.id,
|
|
30
|
+
containerId: container.id,
|
|
31
|
+
deliverableId: deliverable.id,
|
|
32
|
+
iterationId: iteration.id,
|
|
33
|
+
commentId: comment.id,
|
|
34
|
+
attachmentId: attachment.id
|
|
35
|
+
};
|
|
36
|
+
const query = { projectId: project.id, taskId: task.id, emoji: '👍', userId: 'u1' };
|
|
37
|
+
// Deletes run last so earlier routes still have data; the project goes last of all.
|
|
38
|
+
const ordered = [...ROUTES].sort((a, b) => {
|
|
39
|
+
const rank = (r) => (r.method === 'delete' ? (r.path === '/projects/{projectId}' ? 2 : 1) : 0);
|
|
40
|
+
return rank(a) - rank(b);
|
|
41
|
+
});
|
|
42
|
+
for (const route of ordered) {
|
|
43
|
+
const path = route.path.replace(/\{(\w+)\}/g, (_, name) => ids[name]);
|
|
44
|
+
const params = new URLSearchParams();
|
|
45
|
+
for (const q of route.query ?? []) {
|
|
46
|
+
const name = q.replace(/!$/, '');
|
|
47
|
+
if (query[name])
|
|
48
|
+
params.set(name, query[name]);
|
|
49
|
+
}
|
|
50
|
+
const res = await router.handleRequest(new Request(`${base}${path}${params.size ? `?${params}` : ''}`, {
|
|
51
|
+
method: route.method.toUpperCase(),
|
|
52
|
+
headers: { 'Content-Type': 'application/json' },
|
|
53
|
+
...(route.method === 'post' || route.method === 'patch' ? { body: '{}' } : {})
|
|
54
|
+
}));
|
|
55
|
+
const body = await res.json();
|
|
56
|
+
const label = `${route.method.toUpperCase()} ${route.path}`;
|
|
57
|
+
expect(String(body.error ?? ''), label).not.toMatch(/^Route not found/);
|
|
58
|
+
if (res.status < 300 && route.responseKey) {
|
|
59
|
+
expect(body, label).toHaveProperty(route.responseKey);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
it('serves the document at /openapi.json with request bodies from the validation schemas', async () => {
|
|
64
|
+
const router = new CriticalPathRouter();
|
|
65
|
+
const res = await router.handleRequest(new Request(`${base}/openapi.json`));
|
|
66
|
+
expect(res.status).toBe(200);
|
|
67
|
+
const doc = await res.json();
|
|
68
|
+
expect(doc.openapi).toBe('3.1.0');
|
|
69
|
+
expect(doc.servers[0].url).toBe('http://localhost:3000/api/critical-path');
|
|
70
|
+
const createTask = doc.paths['/tasks'].post.requestBody.content['application/json'].schema;
|
|
71
|
+
expect(createTask.required).toEqual(expect.arrayContaining(['projectId', 'title']));
|
|
72
|
+
expect(createTask.properties).not.toHaveProperty('id');
|
|
73
|
+
expect(doc.paths['/tasks/{taskId}/dependencies'].post.responses).toHaveProperty('409');
|
|
74
|
+
});
|
|
75
|
+
it('respects requireAuth', async () => {
|
|
76
|
+
const router = new CriticalPathRouter(undefined, { requireAuth: true });
|
|
77
|
+
const res = await router.handleRequest(new Request(`${base}/openapi.json`));
|
|
78
|
+
expect(res.status).toBe(401);
|
|
79
|
+
});
|
|
80
|
+
it('can be built without a router for static publishing', () => {
|
|
81
|
+
const doc = buildOpenApiDocument({ serverUrl: 'https://api.example.com/pm', version: '2.0.0' });
|
|
82
|
+
expect(doc.info.version).toBe('2.0.0');
|
|
83
|
+
expect(Object.keys(doc.paths).length).toBeGreaterThan(30);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
//# sourceMappingURL=openapi.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openapi.test.js","sourceRoot":"","sources":["../src/openapi.test.ts"],"names":[],"mappings":"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"}
|
package/dist/router.d.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import { CriticalPathEngine, type AuthorType, type CriticalPathConfig } from '@critical-path/core';
|
|
2
|
+
/** Actor for requests when no `getContext` is configured or it resolves no user. */
|
|
3
|
+
export declare const ANONYMOUS_ACTOR: Readonly<{
|
|
4
|
+
userId: "anonymous";
|
|
5
|
+
username: "Anonymous";
|
|
6
|
+
actorType: "user";
|
|
7
|
+
}>;
|
|
2
8
|
/**
|
|
3
9
|
* Per-request identity resolved by `getContext`. `userId` becomes the actor every mutation in
|
|
4
10
|
* the request is attributed to. Extra fields (e.g. `tenantId`, `roles`) are carried for
|
|
@@ -37,8 +43,8 @@ export interface CriticalPathRouterOptions {
|
|
|
37
43
|
exposeErrors?: boolean;
|
|
38
44
|
/**
|
|
39
45
|
* Resolves the caller's identity from the request (session cookie, bearer token, etc.).
|
|
40
|
-
* When it returns a `userId`, all mutations in the request are attributed to that user
|
|
41
|
-
*
|
|
46
|
+
* When it returns a `userId`, all mutations in the request are attributed to that user;
|
|
47
|
+
* otherwise they are attributed to `ANONYMOUS_ACTOR`. Request bodies never carry identity.
|
|
42
48
|
*/
|
|
43
49
|
getContext?: (request: Request) => RequestContext | null | undefined | Promise<RequestContext | null | undefined>;
|
|
44
50
|
/** Reject requests with `401` unless `getContext` returns a `userId`. Defaults to `false`. */
|
|
@@ -48,7 +54,10 @@ export interface CriticalPathRouterOptions {
|
|
|
48
54
|
* When omitted, everything up to the first `/critical-path` segment is stripped.
|
|
49
55
|
*/
|
|
50
56
|
basePath?: string;
|
|
51
|
-
/**
|
|
57
|
+
/**
|
|
58
|
+
* CORS policy. Defaults to `false` (no CORS headers, so only same-origin browsers can call the
|
|
59
|
+
* API). Set `{ origins: [...] }` to allow specific sites, or `{ origins: '*' }` for any site.
|
|
60
|
+
*/
|
|
52
61
|
cors?: CorsOptions | false;
|
|
53
62
|
}
|
|
54
63
|
export declare class CriticalPathRouter {
|
|
@@ -70,6 +79,13 @@ export declare class CriticalPathRouter {
|
|
|
70
79
|
private resolveSubpath;
|
|
71
80
|
private applyCors;
|
|
72
81
|
private dispatch;
|
|
82
|
+
/**
|
|
83
|
+
* Reads and validates a JSON body. `overrides` (e.g. a `taskId` from the URL) are applied before
|
|
84
|
+
* validation so path parameters always win over body fields.
|
|
85
|
+
*/
|
|
86
|
+
private readBody;
|
|
87
|
+
/** The API root as seen by this request, e.g. `https://host/api/critical-path`. */
|
|
88
|
+
private openApiServerUrl;
|
|
73
89
|
private readJson;
|
|
74
90
|
private errorResponse;
|
|
75
91
|
private jsonResponse;
|
package/dist/router.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,KAAK,UAAU,EAAE,KAAK,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,KAAK,UAAU,EAAE,KAAK,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAInG,oFAAoF;AACpF,eAAO,MAAM,eAAe;;;;EAA4F,CAAC;AAKzH;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,UAAU,CAAC;IACvB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,CAAC,EAAE,yBAAyB,CAAC,YAAY,CAAC,CAAC;CACtD;AAED,MAAM,WAAW,WAAW;IAC1B,4FAA4F;IAC5F,OAAO,EAAE,GAAG,GAAG,MAAM,EAAE,CAAC;IACxB,yEAAyE;IACzE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,yFAAyF;IACzF,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,oDAAoD;IACpD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AASD,MAAM,WAAW,yBAAyB;IACxC;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,QAAQ,GAAG,OAAO,CAAC,IAAI,GAAG,QAAQ,CAAC,CAAC;IAC3F;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;OAIG;IACH,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,cAAc,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IAClH,8FAA8F;IAC9F,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,IAAI,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC;CAC5B;AAMD,qBAAa,kBAAkB;IACtB,MAAM,EAAE,kBAAkB,CAAC;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAuC;IAChE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAU;IACvC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAA0C;IACtE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAU;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAsB;gBAE/B,cAAc,CAAC,EAAE,kBAAkB,GAAG,kBAAkB,EAAE,OAAO,GAAE,yBAA8B;IAiB7G;;;;OAIG;IACG,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,GAAE,kBAAuB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAKvF,gGAAgG;IAChG,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,SAAS;YA0BH,QAAQ;IAijBtB;;;OAGG;YACW,QAAQ;IAUtB,mFAAmF;IACnF,OAAO,CAAC,gBAAgB;YAKV,QAAQ;YAQR,aAAa;IAqC3B,OAAO,CAAC,YAAY;CAQrB"}
|