@h-rig/task-sources-plugin 0.0.6-alpha.157 → 0.0.6-alpha.159
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/dist/src/control-plane/native/github-token-env.d.ts +3 -0
- package/dist/src/control-plane/native/github-token-env.js +26 -0
- package/dist/src/control-plane/native/native-git.d.ts +18 -0
- package/dist/src/control-plane/native/native-git.js +291 -0
- package/dist/src/control-plane/native/runtime-binary-build.d.ts +9 -0
- package/dist/src/control-plane/native/runtime-binary-build.js +107 -0
- package/dist/src/control-plane/native/task-ops.d.ts +52 -0
- package/dist/src/control-plane/native/task-ops.js +3192 -0
- package/dist/src/control-plane/native/task-state.d.ts +30 -0
- package/dist/src/control-plane/native/task-state.js +944 -0
- package/dist/src/control-plane/native/utils.d.ts +7 -0
- package/dist/src/control-plane/native/utils.js +110 -0
- package/dist/src/control-plane/native/validator-binaries.d.ts +3 -0
- package/dist/src/control-plane/native/validator-binaries.js +175 -0
- package/dist/src/control-plane/native/validator.d.ts +44 -0
- package/dist/src/control-plane/native/validator.js +979 -0
- package/dist/src/control-plane/state-sync/index.d.ts +4 -0
- package/dist/src/control-plane/state-sync/index.js +1205 -0
- package/dist/src/control-plane/state-sync/native-git.d.ts +1 -0
- package/dist/src/control-plane/state-sync/native-git.js +281 -0
- package/dist/src/control-plane/state-sync/read.d.ts +46 -0
- package/dist/src/control-plane/state-sync/read.js +564 -0
- package/dist/src/control-plane/state-sync/reconcile.d.ts +28 -0
- package/dist/src/control-plane/state-sync/reconcile.js +260 -0
- package/dist/src/control-plane/state-sync/repo.d.ts +1 -0
- package/dist/src/control-plane/state-sync/repo.js +42 -0
- package/dist/src/control-plane/state-sync/types.d.ts +28 -0
- package/dist/src/control-plane/state-sync/types.js +111 -0
- package/dist/src/control-plane/state-sync/write.d.ts +83 -0
- package/dist/src/control-plane/state-sync/write.js +1165 -0
- package/dist/src/control-plane/task-data-service.d.ts +17 -0
- package/dist/src/control-plane/task-data-service.js +3653 -0
- package/dist/src/control-plane/task-fields.d.ts +1 -0
- package/dist/src/control-plane/task-fields.js +6 -0
- package/dist/src/control-plane/task-io-service.d.ts +6 -0
- package/dist/src/control-plane/task-io-service.js +108 -0
- package/dist/src/control-plane/task-source-bootstrap.d.ts +1 -0
- package/dist/src/control-plane/task-source-bootstrap.js +6 -0
- package/dist/src/control-plane/task-source.d.ts +2 -0
- package/dist/src/control-plane/task-source.js +6 -0
- package/dist/src/control-plane/tasks/legacy-task-config-source.d.ts +19 -0
- package/dist/src/control-plane/tasks/legacy-task-config-source.js +124 -0
- package/dist/src/control-plane/tasks/plugin-task-source.d.ts +30 -0
- package/dist/src/control-plane/tasks/plugin-task-source.js +99 -0
- package/dist/src/control-plane/tasks/source-aware-task-config-source.d.ts +28 -0
- package/dist/src/control-plane/tasks/source-aware-task-config-source.js +642 -0
- package/dist/src/control-plane/tasks/source-lifecycle.d.ts +56 -0
- package/dist/src/control-plane/tasks/source-lifecycle.js +834 -0
- package/dist/src/plugin.d.ts +1 -1
- package/dist/src/plugin.js +3927 -64
- package/package.json +57 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { createTaskFieldRegistry, type TaskFieldRegistry } from "@rig/core/plugin-host-registries";
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/task-sources-plugin/src/control-plane/task-io-service.ts
|
|
3
|
+
import { resolvePluginHost } from "@rig/core/project-plugins";
|
|
4
|
+
function isRecord(value) {
|
|
5
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6
|
+
}
|
|
7
|
+
function taskText(value) {
|
|
8
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
|
|
9
|
+
}
|
|
10
|
+
function taskUrl(record) {
|
|
11
|
+
const metadata = record;
|
|
12
|
+
return taskText(metadata.url) ?? taskText(metadata.html_url) ?? taskText(metadata.webUrl);
|
|
13
|
+
}
|
|
14
|
+
function taskBody(record) {
|
|
15
|
+
const metadata = record;
|
|
16
|
+
return taskText(metadata.body) ?? taskText(metadata.description);
|
|
17
|
+
}
|
|
18
|
+
function taskTitle(record) {
|
|
19
|
+
const metadata = record;
|
|
20
|
+
return taskText(metadata.title) ?? taskText(metadata.name) ?? record.id;
|
|
21
|
+
}
|
|
22
|
+
function taskStringList(value) {
|
|
23
|
+
return Array.isArray(value) ? value.filter((entry) => typeof entry === "string" && entry.trim().length > 0) : [];
|
|
24
|
+
}
|
|
25
|
+
function taskDependencies(record) {
|
|
26
|
+
const raw = record;
|
|
27
|
+
const dependencies = taskStringList(raw.dependencies);
|
|
28
|
+
if (dependencies.length > 0)
|
|
29
|
+
return dependencies;
|
|
30
|
+
const deps = taskStringList(raw.deps);
|
|
31
|
+
return deps.length > 0 ? deps : null;
|
|
32
|
+
}
|
|
33
|
+
function taskParentChildDeps(record) {
|
|
34
|
+
const raw = record;
|
|
35
|
+
const parentChildDeps = taskStringList(raw.parentChildDeps);
|
|
36
|
+
if (parentChildDeps.length > 0)
|
|
37
|
+
return parentChildDeps;
|
|
38
|
+
const parents = taskStringList(raw.parents);
|
|
39
|
+
return parents.length > 0 ? parents : null;
|
|
40
|
+
}
|
|
41
|
+
function taskCreateInput(task) {
|
|
42
|
+
const deps = Array.isArray(task.dependencies) ? task.dependencies.filter((entry) => typeof entry === "string") : Array.isArray(task.deps) ? task.deps.filter((entry) => typeof entry === "string") : [];
|
|
43
|
+
const parents = Array.isArray(task.parents) ? task.parents.filter((entry) => typeof entry === "string") : [];
|
|
44
|
+
return {
|
|
45
|
+
title: taskText(task.title) ?? taskText(task.name) ?? "Untitled task",
|
|
46
|
+
body: taskText(task.body) ?? taskText(task.description) ?? "",
|
|
47
|
+
...deps.length > 0 ? { deps } : {},
|
|
48
|
+
...parents.length > 0 ? { parents } : {},
|
|
49
|
+
metadata: { ...task }
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function toRigTask(record, sourceKind) {
|
|
53
|
+
const dependencies = taskDependencies(record);
|
|
54
|
+
const parentChildDeps = taskParentChildDeps(record);
|
|
55
|
+
return {
|
|
56
|
+
...record,
|
|
57
|
+
id: record.id,
|
|
58
|
+
title: taskTitle(record),
|
|
59
|
+
status: typeof record.status === "string" ? record.status : null,
|
|
60
|
+
source: sourceKind,
|
|
61
|
+
url: taskUrl(record),
|
|
62
|
+
body: taskBody(record),
|
|
63
|
+
...dependencies ? { dependencies } : {},
|
|
64
|
+
...parentChildDeps ? { parentChildDeps } : {}
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
async function loadTaskSource(projectRoot) {
|
|
68
|
+
const { config, host: pluginHost } = await resolvePluginHost(projectRoot);
|
|
69
|
+
const factory = pluginHost.resolveTaskSourceFactoryByKind(config.taskSource.kind);
|
|
70
|
+
if (!factory) {
|
|
71
|
+
const kinds = pluginHost.listExecutableTaskSources().map((entry) => entry.kind).join(", ") || "none";
|
|
72
|
+
throw new Error(`No task source factory registered for kind ${config.taskSource.kind}. Registered task sources: ${kinds}.`);
|
|
73
|
+
}
|
|
74
|
+
return { kind: config.taskSource.kind, source: factory.factory(config.taskSource, { projectRoot }) };
|
|
75
|
+
}
|
|
76
|
+
function getTaskCreator(source) {
|
|
77
|
+
const record = source;
|
|
78
|
+
if (typeof record.createTask === "function")
|
|
79
|
+
return record.createTask.bind(source);
|
|
80
|
+
if (typeof record.create === "function")
|
|
81
|
+
return (task) => record.create?.(taskCreateInput(task));
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
function createTaskIoService() {
|
|
85
|
+
return {
|
|
86
|
+
async listTasks(projectRoot) {
|
|
87
|
+
const { kind, source } = await loadTaskSource(projectRoot);
|
|
88
|
+
return (await source.list()).map((task) => toRigTask(task, kind));
|
|
89
|
+
},
|
|
90
|
+
async getTask(projectRoot, taskId) {
|
|
91
|
+
const { kind, source } = await loadTaskSource(projectRoot);
|
|
92
|
+
const task = source.get ? await source.get(taskId) ?? null : (await source.list()).find((entry) => entry.id === taskId) ?? null;
|
|
93
|
+
return task ? toRigTask(task, kind) : null;
|
|
94
|
+
},
|
|
95
|
+
async createTask(projectRoot, task) {
|
|
96
|
+
const { kind, source } = await loadTaskSource(projectRoot);
|
|
97
|
+
const creator = getTaskCreator(source);
|
|
98
|
+
if (!creator)
|
|
99
|
+
throw new Error(`The configured ${kind} task source does not expose a task creation API.`);
|
|
100
|
+
const result = await creator(task);
|
|
101
|
+
const taskId = typeof result === "string" ? result : isRecord(result) && typeof result.id === "string" ? result.id : null;
|
|
102
|
+
return { taskId, source: kind, result };
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
export {
|
|
107
|
+
createTaskIoService
|
|
108
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { buildTaskSourceRegistry } from "@rig/core/plugin-host-registries";
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { TaskRecord } from "@rig/contracts";
|
|
2
|
+
import { type TaskRecordReader } from "@rig/core/task-record-reader";
|
|
3
|
+
export type LegacyTaskConfigReaderOptions = {
|
|
4
|
+
configPath?: string;
|
|
5
|
+
};
|
|
6
|
+
export declare class LegacyTaskConfigReadError extends Error {
|
|
7
|
+
readonly code = "LEGACY_TASK_CONFIG_READ_FAILED";
|
|
8
|
+
readonly projectRoot: string;
|
|
9
|
+
readonly configPath: string;
|
|
10
|
+
readonly cause: unknown;
|
|
11
|
+
constructor(input: {
|
|
12
|
+
projectRoot: string;
|
|
13
|
+
configPath: string;
|
|
14
|
+
message: string;
|
|
15
|
+
cause?: unknown;
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
export declare function createLegacyTaskConfigRecordReader(projectRoot: string, options?: LegacyTaskConfigReaderOptions): TaskRecordReader;
|
|
19
|
+
export declare function readLegacyTaskRecords(projectRoot: string, configPath?: string): readonly TaskRecord[];
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/task-sources-plugin/src/control-plane/tasks/legacy-task-config-source.ts
|
|
3
|
+
import { existsSync, readFileSync } from "fs";
|
|
4
|
+
import { resolve } from "path";
|
|
5
|
+
import { findTaskById } from "@rig/core/task-record-reader";
|
|
6
|
+
|
|
7
|
+
class LegacyTaskConfigReadError extends Error {
|
|
8
|
+
code = "LEGACY_TASK_CONFIG_READ_FAILED";
|
|
9
|
+
projectRoot;
|
|
10
|
+
configPath;
|
|
11
|
+
cause;
|
|
12
|
+
constructor(input) {
|
|
13
|
+
super(input.message, { cause: input.cause });
|
|
14
|
+
this.name = "LegacyTaskConfigReadError";
|
|
15
|
+
this.projectRoot = input.projectRoot;
|
|
16
|
+
this.configPath = input.configPath;
|
|
17
|
+
this.cause = input.cause;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function createLegacyTaskConfigRecordReader(projectRoot, options = {}) {
|
|
21
|
+
const configPath = options.configPath ?? resolve(projectRoot, ".rig", "task-config.json");
|
|
22
|
+
const reader = {
|
|
23
|
+
async listTasks() {
|
|
24
|
+
return readLegacyTaskRecords(projectRoot, configPath);
|
|
25
|
+
},
|
|
26
|
+
async getTask(id) {
|
|
27
|
+
return findTaskById(reader, id);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
return reader;
|
|
31
|
+
}
|
|
32
|
+
function readLegacyTaskRecords(projectRoot, configPath = resolve(projectRoot, ".rig", "task-config.json")) {
|
|
33
|
+
if (!existsSync(configPath)) {
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
const rawConfig = readLegacyTaskConfigJson(projectRoot, configPath);
|
|
37
|
+
return Object.entries(stripLegacyTaskConfigMetadata(rawConfig)).map(([id, entry]) => legacyTaskConfigEntryToRecord(id, entry)).filter((record) => record !== null);
|
|
38
|
+
}
|
|
39
|
+
function readLegacyTaskConfigJson(projectRoot, configPath) {
|
|
40
|
+
try {
|
|
41
|
+
const parsed = JSON.parse(readFileSync(configPath, "utf8"));
|
|
42
|
+
if (isPlainRecord(parsed)) {
|
|
43
|
+
return parsed;
|
|
44
|
+
}
|
|
45
|
+
throw new Error("task config root must be a JSON object");
|
|
46
|
+
} catch (cause) {
|
|
47
|
+
throw new LegacyTaskConfigReadError({
|
|
48
|
+
projectRoot,
|
|
49
|
+
configPath,
|
|
50
|
+
message: `Could not read legacy task config at ${configPath} for project ${projectRoot}: ${cause instanceof Error ? cause.message : String(cause)}`,
|
|
51
|
+
cause
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function stripLegacyTaskConfigMetadata(raw) {
|
|
56
|
+
const { validation_descriptions: _legacyDescriptions, _meta, ...tasks } = raw;
|
|
57
|
+
return tasks;
|
|
58
|
+
}
|
|
59
|
+
function legacyTaskConfigEntryToRecord(id, entry) {
|
|
60
|
+
if (!isPlainRecord(entry)) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
const deps = firstStringList(entry.deps, entry.dependencies, entry.validation_deps, entry.validationDeps);
|
|
64
|
+
const validation = readStringList(entry.validation);
|
|
65
|
+
const validators = readStringList(entry.validators);
|
|
66
|
+
const scope = readStringList(entry.scope);
|
|
67
|
+
const status = typeof entry.status === "string" ? entry.status : "open";
|
|
68
|
+
const title = typeof entry.title === "string" ? entry.title : undefined;
|
|
69
|
+
const description = typeof entry.description === "string" ? entry.description : undefined;
|
|
70
|
+
const acceptanceCriteria = typeof entry.acceptance_criteria === "string" ? entry.acceptance_criteria : typeof entry.acceptanceCriteria === "string" ? entry.acceptanceCriteria : undefined;
|
|
71
|
+
return {
|
|
72
|
+
id,
|
|
73
|
+
deps,
|
|
74
|
+
status,
|
|
75
|
+
source: "legacy-task-config",
|
|
76
|
+
...title ? { title } : {},
|
|
77
|
+
...description ? { description } : {},
|
|
78
|
+
...acceptanceCriteria ? { acceptanceCriteria } : {},
|
|
79
|
+
...scope.length > 0 ? { scope } : {},
|
|
80
|
+
...validation.length > 0 ? { validation } : {},
|
|
81
|
+
...validators.length > 0 ? { validators } : {},
|
|
82
|
+
...preservedLegacyFields(entry)
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function preservedLegacyFields(entry) {
|
|
86
|
+
const preserved = {};
|
|
87
|
+
for (const key of [
|
|
88
|
+
"role",
|
|
89
|
+
"browser",
|
|
90
|
+
"repo_pins",
|
|
91
|
+
"criticality",
|
|
92
|
+
"queue_weight",
|
|
93
|
+
"creates_repo",
|
|
94
|
+
"auto_synced"
|
|
95
|
+
]) {
|
|
96
|
+
if (entry[key] !== undefined) {
|
|
97
|
+
preserved[key] = entry[key];
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return preserved;
|
|
101
|
+
}
|
|
102
|
+
function firstStringList(...candidates) {
|
|
103
|
+
for (const candidate of candidates) {
|
|
104
|
+
const list = readStringList(candidate);
|
|
105
|
+
if (list.length > 0) {
|
|
106
|
+
return list;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return [];
|
|
110
|
+
}
|
|
111
|
+
function readStringList(candidate) {
|
|
112
|
+
if (!Array.isArray(candidate)) {
|
|
113
|
+
return [];
|
|
114
|
+
}
|
|
115
|
+
return candidate.filter((value) => typeof value === "string");
|
|
116
|
+
}
|
|
117
|
+
function isPlainRecord(candidate) {
|
|
118
|
+
return typeof candidate === "object" && candidate !== null && !Array.isArray(candidate);
|
|
119
|
+
}
|
|
120
|
+
export {
|
|
121
|
+
readLegacyTaskRecords,
|
|
122
|
+
createLegacyTaskConfigRecordReader,
|
|
123
|
+
LegacyTaskConfigReadError
|
|
124
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { TaskSourceRegistry } from "../task-source";
|
|
2
|
+
import { type TaskRecordReader } from "@rig/core/task-record-reader";
|
|
3
|
+
export type PluginTaskRecordReaderContext = {
|
|
4
|
+
taskSourceRegistry: Pick<TaskSourceRegistry, "list" | "resolveById" | "resolveByKind">;
|
|
5
|
+
};
|
|
6
|
+
export type PluginTaskRecordReaderOptions = {
|
|
7
|
+
projectRoot: string;
|
|
8
|
+
sourceId?: string;
|
|
9
|
+
sourceKind?: string;
|
|
10
|
+
};
|
|
11
|
+
export type TaskRecordSourceErrorCode = "TASK_SOURCE_NOT_CONFIGURED" | "TASK_SOURCE_READ_FAILED";
|
|
12
|
+
export type TaskRecordSourceOperation = "select" | "list" | "get";
|
|
13
|
+
export declare class TaskRecordSourceError extends Error {
|
|
14
|
+
readonly code: TaskRecordSourceErrorCode;
|
|
15
|
+
readonly projectRoot: string;
|
|
16
|
+
readonly sourceId: string | null;
|
|
17
|
+
readonly sourceKind: string | null;
|
|
18
|
+
readonly operation: TaskRecordSourceOperation;
|
|
19
|
+
readonly cause: unknown;
|
|
20
|
+
constructor(input: {
|
|
21
|
+
code: TaskRecordSourceErrorCode;
|
|
22
|
+
message: string;
|
|
23
|
+
projectRoot: string;
|
|
24
|
+
operation: TaskRecordSourceOperation;
|
|
25
|
+
sourceId?: string | null;
|
|
26
|
+
sourceKind?: string | null;
|
|
27
|
+
cause?: unknown;
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
export declare function createPluginTaskRecordReader(context: PluginTaskRecordReaderContext, options: PluginTaskRecordReaderOptions): TaskRecordReader;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/task-sources-plugin/src/control-plane/tasks/plugin-task-source.ts
|
|
3
|
+
import { findTaskById } from "@rig/core/task-record-reader";
|
|
4
|
+
|
|
5
|
+
class TaskRecordSourceError extends Error {
|
|
6
|
+
code;
|
|
7
|
+
projectRoot;
|
|
8
|
+
sourceId;
|
|
9
|
+
sourceKind;
|
|
10
|
+
operation;
|
|
11
|
+
cause;
|
|
12
|
+
constructor(input) {
|
|
13
|
+
super(input.message, { cause: input.cause });
|
|
14
|
+
this.name = "TaskRecordSourceError";
|
|
15
|
+
this.code = input.code;
|
|
16
|
+
this.projectRoot = input.projectRoot;
|
|
17
|
+
this.operation = input.operation;
|
|
18
|
+
this.sourceId = input.sourceId ?? null;
|
|
19
|
+
this.sourceKind = input.sourceKind ?? null;
|
|
20
|
+
this.cause = input.cause;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function createPluginTaskRecordReader(context, options) {
|
|
24
|
+
const source = selectTaskSource(context.taskSourceRegistry, options);
|
|
25
|
+
return {
|
|
26
|
+
async listTasks() {
|
|
27
|
+
try {
|
|
28
|
+
return await source.list();
|
|
29
|
+
} catch (cause) {
|
|
30
|
+
throw readFailedError(source, options, "list", cause);
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
async getTask(id) {
|
|
34
|
+
try {
|
|
35
|
+
if (source.get) {
|
|
36
|
+
return await source.get(id) ?? null;
|
|
37
|
+
}
|
|
38
|
+
return findTaskById({
|
|
39
|
+
listTasks: () => source.list(),
|
|
40
|
+
getTask: async () => null
|
|
41
|
+
}, id);
|
|
42
|
+
} catch (cause) {
|
|
43
|
+
throw readFailedError(source, options, "get", cause);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function selectTaskSource(registry, options) {
|
|
49
|
+
try {
|
|
50
|
+
if (options.sourceId) {
|
|
51
|
+
return registry.resolveById(options.sourceId);
|
|
52
|
+
}
|
|
53
|
+
if (options.sourceKind) {
|
|
54
|
+
return registry.resolveByKind(options.sourceKind);
|
|
55
|
+
}
|
|
56
|
+
const [source] = registry.list();
|
|
57
|
+
if (source) {
|
|
58
|
+
return source;
|
|
59
|
+
}
|
|
60
|
+
} catch (cause) {
|
|
61
|
+
throw new TaskRecordSourceError({
|
|
62
|
+
code: "TASK_SOURCE_NOT_CONFIGURED",
|
|
63
|
+
message: taskSourceSelectionMessage(options),
|
|
64
|
+
projectRoot: options.projectRoot,
|
|
65
|
+
operation: "select",
|
|
66
|
+
sourceId: options.sourceId ?? null,
|
|
67
|
+
sourceKind: options.sourceKind ?? null,
|
|
68
|
+
cause
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
throw new TaskRecordSourceError({
|
|
72
|
+
code: "TASK_SOURCE_NOT_CONFIGURED",
|
|
73
|
+
message: taskSourceSelectionMessage(options),
|
|
74
|
+
projectRoot: options.projectRoot,
|
|
75
|
+
operation: "select",
|
|
76
|
+
sourceId: options.sourceId ?? null,
|
|
77
|
+
sourceKind: options.sourceKind ?? null
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
function taskSourceSelectionMessage(options) {
|
|
81
|
+
const selector = options.sourceId ? `id "${options.sourceId}"` : options.sourceKind ? `kind "${options.sourceKind}"` : "the configured plugin task source";
|
|
82
|
+
return `No task source registered for ${selector} in project ${options.projectRoot}. Check rig.config.ts taskSource and loaded plugins.`;
|
|
83
|
+
}
|
|
84
|
+
function readFailedError(source, options, operation, cause) {
|
|
85
|
+
const causeMessage = cause instanceof Error ? cause.message : String(cause);
|
|
86
|
+
return new TaskRecordSourceError({
|
|
87
|
+
code: "TASK_SOURCE_READ_FAILED",
|
|
88
|
+
message: `Task source ${source.kind} (${source.id}) failed to ${operation} tasks for project ${options.projectRoot}: ${causeMessage}`,
|
|
89
|
+
projectRoot: options.projectRoot,
|
|
90
|
+
operation,
|
|
91
|
+
sourceId: source.id,
|
|
92
|
+
sourceKind: source.kind,
|
|
93
|
+
cause
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
export {
|
|
97
|
+
createPluginTaskRecordReader,
|
|
98
|
+
TaskRecordSourceError
|
|
99
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import type { TaskSourceUpdate } from "@rig/contracts";
|
|
3
|
+
import type { TaskRecordReader } from "@rig/core/task-record-reader";
|
|
4
|
+
export type MaterializedTaskSourceMetadata = {
|
|
5
|
+
kind: string;
|
|
6
|
+
path?: string;
|
|
7
|
+
owner?: string;
|
|
8
|
+
repo?: string;
|
|
9
|
+
labels?: readonly string[];
|
|
10
|
+
state?: "open" | "closed" | "all";
|
|
11
|
+
};
|
|
12
|
+
export type MaterializedTaskMetadata = {
|
|
13
|
+
taskSource?: MaterializedTaskSourceMetadata;
|
|
14
|
+
sourceIssueId?: string;
|
|
15
|
+
};
|
|
16
|
+
export type SourceAwareTaskConfigOptions = {
|
|
17
|
+
configPath?: string;
|
|
18
|
+
ghBinary?: string;
|
|
19
|
+
spawn?: typeof spawnSync;
|
|
20
|
+
allowLocalTaskConfigStatusFallback?: boolean;
|
|
21
|
+
};
|
|
22
|
+
type RawTaskEntry = Record<string, unknown>;
|
|
23
|
+
export declare function createSourceAwareTaskConfigRecordReader(projectRoot: string, options?: SourceAwareTaskConfigOptions): TaskRecordReader;
|
|
24
|
+
export declare function readSourceAwareTaskStatus(projectRoot: string, taskId: string, options?: SourceAwareTaskConfigOptions): Promise<unknown>;
|
|
25
|
+
export declare function updateGithubIssueTaskBySourceIssueId(sourceIssueId: string | null | undefined, taskId: string, update: TaskSourceUpdate, options?: SourceAwareTaskConfigOptions): boolean;
|
|
26
|
+
export declare function updateSourceAwareTaskConfigTask(projectRoot: string, taskId: string, update: TaskSourceUpdate, options?: SourceAwareTaskConfigOptions): boolean;
|
|
27
|
+
export declare function readMaterializedTaskMetadata(entry: RawTaskEntry): MaterializedTaskMetadata;
|
|
28
|
+
export {};
|