feat(ql3): establish 3.0 incubation baseline

This commit is contained in:
whyour
2026-08-12 00:25:26 +08:00
parent 4bf92dcfeb
commit c699c32461
2817 changed files with 779642 additions and 653 deletions
@@ -0,0 +1,56 @@
import {
BoundedTaskListProjectionUnavailableError,
InvalidBoundedTaskListProjectionError,
executeBoundedTaskListProjection,
type BoundedTaskListInput,
} from '@qinglong/runtime-core/bounded-task-list-projection';
import type { TaskDefinitionSource } from '@qinglong/runtime-core/task-definition';
import type { LocalApiResponse } from '../transport/contract';
export interface LocalApiTaskListRequest {
readonly projectId: string;
readonly input: Readonly<BoundedTaskListInput>;
}
export interface LocalApiTaskListRoute {
handle(request: Readonly<LocalApiTaskListRequest>): Promise<LocalApiResponse>;
}
function unavailable(): LocalApiResponse {
return Object.freeze({
statusCode: 503,
body: Object.freeze({ code: 'task_list_unavailable' }),
});
}
export function createLocalApiTaskListRoute(
tasks: Pick<TaskDefinitionSource, 'listTaskDefinitions'>,
): Readonly<LocalApiTaskListRoute> {
if (!tasks || typeof tasks.listTaskDefinitions !== 'function') {
throw new TypeError('Local API Task list repository is invalid');
}
return Object.freeze({
async handle(request: Readonly<LocalApiTaskListRequest>) {
try {
const result = await executeBoundedTaskListProjection(
tasks,
request.projectId,
request.input,
);
return Object.freeze({
statusCode: 200,
body: Object.freeze({ ...result }),
});
} catch (error) {
if (
error instanceof InvalidBoundedTaskListProjectionError ||
error instanceof BoundedTaskListProjectionUnavailableError
) {
return unavailable();
}
throw error;
}
},
});
}
@@ -0,0 +1,56 @@
import {
BoundedTaskReadProjectionUnavailableError,
InvalidBoundedTaskReadProjectionError,
executeBoundedTaskReadProjection,
} from '@qinglong/runtime-core/bounded-task-read-projection';
import type { TaskDefinitionSource } from '@qinglong/runtime-core/task-definition';
import type { LocalApiResponse } from '../transport/contract';
export interface LocalApiTaskReadRequest {
readonly projectId: string;
readonly taskId: string;
}
export interface LocalApiTaskReadRoute {
handle(request: Readonly<LocalApiTaskReadRequest>): Promise<LocalApiResponse>;
}
function response(
statusCode: number,
body: Readonly<Record<string, unknown>>,
): LocalApiResponse {
return Object.freeze({ statusCode, body: Object.freeze(body) });
}
export function createLocalApiTaskReadRoute(
tasks: Pick<TaskDefinitionSource, 'findCurrentTaskDefinition'>,
): Readonly<LocalApiTaskReadRoute> {
if (!tasks || typeof tasks.findCurrentTaskDefinition !== 'function') {
throw new TypeError('Local API Task read repository is invalid');
}
return Object.freeze({
async handle(request: Readonly<LocalApiTaskReadRequest>) {
try {
const projection = await executeBoundedTaskReadProjection(
tasks,
request.projectId,
request.taskId,
);
if (projection.found !== true) {
return response(404, { code: 'task_not_found' });
}
const { found: _found, ...task } = projection;
return response(200, { task: Object.freeze(task) });
} catch (error) {
if (
error instanceof InvalidBoundedTaskReadProjectionError ||
error instanceof BoundedTaskReadProjectionUnavailableError
) {
return response(503, { code: 'task_query_unavailable' });
}
throw error;
}
},
});
}
@@ -0,0 +1,105 @@
import {
TASK_START_SCHEMA,
InvalidTaskStartError,
TaskStartFenceRejectedError,
TaskStartNotFoundError,
TaskStartUnavailableError,
createTaskStartResponseBody,
parseTaskStartRequestBody,
type TaskStartRepository,
} from '@qinglong/runtime-core/task-start';
import type {
SecurityPolicyFence,
SecurityPrincipal,
} from '@qinglong/runtime-core/security';
import type { LocalApiResponse } from '../transport/contract';
export interface LocalApiTaskStartRequest {
readonly projectId: string;
readonly taskId: string;
readonly body: unknown | null;
readonly principal: Readonly<SecurityPrincipal>;
readonly policyFence: Readonly<SecurityPolicyFence> | null;
}
export interface LocalApiTaskStartRoute {
handle(request: Readonly<LocalApiTaskStartRequest>): Promise<LocalApiResponse>;
}
export type LocalApiTaskStartIdFactory = () => string;
function response(
statusCode: number,
body: Readonly<Record<string, unknown>>,
): LocalApiResponse {
return Object.freeze({ statusCode, body: Object.freeze(body) });
}
export function createLocalApiTaskStartRoute(
repository: TaskStartRepository,
createId: LocalApiTaskStartIdFactory,
): Readonly<LocalApiTaskStartRoute> {
if (
!repository ||
typeof repository.startTask !== 'function' ||
typeof createId !== 'function'
) {
throw new TypeError('Local API Task start route is invalid');
}
return Object.freeze({
async handle(request: Readonly<LocalApiTaskStartRequest>) {
let body;
try {
body = parseTaskStartRequestBody(request.body);
} catch (error) {
if (error instanceof InvalidTaskStartError) {
return response(400, {
code: 'invalid_task_start_request',
schema: TASK_START_SCHEMA,
});
}
return response(503, { code: 'task_start_unavailable' });
}
if (!request.policyFence || request.policyFence.bindingVersion === null) {
return response(503, { code: 'task_start_unavailable' });
}
try {
const result = await repository.startTask({
projectId: request.projectId,
taskId: request.taskId,
mutationId: body.mutationId,
expectedRevision: body.expectedRevision,
expectedContentDigest: body.expectedContentDigest,
runId: createId(),
attemptId: createId(),
createdEventId: createId(),
queuedEventId: createId(),
subject: request.principal.subject,
policyFence: request.policyFence,
});
return response(
result.status === 'accepted' ? 202 : 200,
createTaskStartResponseBody(result),
);
} catch (error) {
if (error instanceof TaskStartNotFoundError) {
return response(404, { code: 'task_not_found' });
}
if (error instanceof TaskStartFenceRejectedError) {
return response(409, {
code: 'task_start_fence_rejected',
reason: error.reason,
});
}
if (
error instanceof InvalidTaskStartError ||
error instanceof TaskStartUnavailableError
) {
return response(503, { code: 'task_start_unavailable' });
}
return response(503, { code: 'task_start_unavailable' });
}
},
});
}