@boboddy/sdk 0.4.2 → 0.4.3
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/definitions/pipelines/builder-helpers.d.ts +33 -4
- package/dist/definitions/pipelines/define-default-pipeline-assignment.d.ts +64 -14
- package/dist/definitions/pipelines/index.d.ts +1 -0
- package/dist/definitions/pipelines/index.js +55 -10
- package/dist/definitions/pipelines/pipeline-definitions-client.d.ts +24 -8
- package/dist/definitions/pipelines/work-item-fields.d.ts +98 -0
- package/dist/definitions/steps/define-step.d.ts +19 -8
- package/dist/definitions/steps/step-definitions-client.d.ts +18 -6
- package/dist/generated/types.gen.d.ts +264 -88
- package/dist/index.js +55 -10
- package/dist/push/index.js +52 -10
- package/package.json +1 -1
|
@@ -2,6 +2,7 @@ import { z, type ZodType } from "zod";
|
|
|
2
2
|
import { type AdditionalStepInputBinding, type TypedStepDefinitionSpec } from "../steps/define-step";
|
|
3
3
|
import { type AnyBinding, type FanOutItemBinding, type LiteralBinding, type SignalsListBinding, type StepOutputBinding, type StepSignalBinding, type WorkItemBinding } from "./define-pipeline";
|
|
4
4
|
import { type InputAccessor } from "./input-accessor";
|
|
5
|
+
import { type WorkItemTopLevelField } from "./work-item-fields";
|
|
5
6
|
export type AnyTypedStep = TypedStepDefinitionSpec<any, any, any, any>;
|
|
6
7
|
type ElementOf<T extends ReadonlyArray<unknown>> = T extends ReadonlyArray<infer U> ? U : never;
|
|
7
8
|
export type LastStep<T extends ReadonlyArray<AnyTypedStep>> = T extends readonly [...AnyTypedStep[], infer L] ? L extends AnyTypedStep ? L : never : never;
|
|
@@ -30,10 +31,31 @@ export type FanOutInputCtx<TInput extends ZodType, TSteps extends ReadonlyArray<
|
|
|
30
31
|
item: FanOutItemBinding & FanOutItemType<TSteps, K>;
|
|
31
32
|
});
|
|
32
33
|
export type IsAny<T> = 0 extends 1 & T ? true : false;
|
|
34
|
+
/**
|
|
35
|
+
* Work-item accessor for `additionalPipelineInput.bindings(({ workItem }) => ...)`:
|
|
36
|
+
* a top-level property (`workItem.title`, `workItem.platform`,
|
|
37
|
+
* `workItem.url`, ...) for every member of `WORK_ITEM_TOP_LEVEL_FIELDS`, plus
|
|
38
|
+
* `workItem.field(name)` for the platform-specific `fields` bag.
|
|
39
|
+
*
|
|
40
|
+
* Mirrors the default-pipeline-assignment DSL's `WorkItemAssignmentAccessor`
|
|
41
|
+
* (`define-default-pipeline-assignment.ts`) in which properties it exposes —
|
|
42
|
+
* both are generated off the same `WORK_ITEM_TOP_LEVEL_FIELDS` list — but
|
|
43
|
+
* returns a plain `WorkItemBinding` per property rather than a
|
|
44
|
+
* comparator-bound `AssignmentFieldRef`: a regular pipeline input binding
|
|
45
|
+
* has no conditions to compare against, it's just "read this work-item
|
|
46
|
+
* property into this input field."
|
|
47
|
+
*
|
|
48
|
+
* `field`'s optional `TName` type parameter accepts a literal union of known
|
|
49
|
+
* field names (e.g. the `WorkItemFieldName` type `boboddy pipelines pull`
|
|
50
|
+
* generates into `work-item-fields.ts`) for compile-time validation and
|
|
51
|
+
* autocomplete on the field name, exactly like the assignment DSL's
|
|
52
|
+
* `workItem.field<TName>(...)`. Defaults to permissive `string`, so
|
|
53
|
+
* `workItem.field(name)` with no type argument keeps working as before.
|
|
54
|
+
*/
|
|
33
55
|
export type WorkItemAccessor = {
|
|
34
|
-
readonly
|
|
35
|
-
|
|
36
|
-
|
|
56
|
+
readonly [K in WorkItemTopLevelField]: WorkItemBinding;
|
|
57
|
+
} & {
|
|
58
|
+
field<TName extends string = string>(fieldName: TName): WorkItemBinding;
|
|
37
59
|
};
|
|
38
60
|
export type PinnedWorkItemComment = {
|
|
39
61
|
createdAt: string;
|
|
@@ -91,7 +113,14 @@ export type PipelineMeta<TInput extends ZodType = z.ZodUnknown> = {
|
|
|
91
113
|
additionalStepInput?: {
|
|
92
114
|
schema: ZodType;
|
|
93
115
|
bindings: (ctx: {
|
|
94
|
-
|
|
116
|
+
/**
|
|
117
|
+
* References a platform-specific field (Jira custom field, GitHub
|
|
118
|
+
* label, etc.) in the work item's `fields` bag. `TName` optionally
|
|
119
|
+
* accepts a literal union of known field names (e.g. the generated
|
|
120
|
+
* `WorkItemFieldName`) for compile-time validation and autocomplete,
|
|
121
|
+
* exactly like `WorkItemAccessor.field` above.
|
|
122
|
+
*/
|
|
123
|
+
workItemField: <TName extends string = string>(fieldName: TName) => WorkItemBinding;
|
|
95
124
|
literal: (value: unknown) => LiteralBinding;
|
|
96
125
|
}) => Partial<Record<string, AdditionalStepInputBinding>>;
|
|
97
126
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { PipelineDefinitionSpec } from "./define-pipeline";
|
|
2
|
+
import { type WorkItemTopLevelField, type WorkItemTopLevelFieldTypeMap } from "./work-item-fields";
|
|
2
3
|
/**
|
|
3
4
|
* The reserved filename for the default pipeline assignment file.
|
|
4
5
|
* This file is NOT treated as a pipeline definition by the push scanner.
|
|
@@ -47,31 +48,80 @@ export interface AssignmentGroup {
|
|
|
47
48
|
readonly _condition: AssignmentCondition;
|
|
48
49
|
}
|
|
49
50
|
type AssignmentNestable = AssignmentLeaf | AssignmentGroup;
|
|
50
|
-
/**
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
/**
|
|
52
|
+
* `.gt`/`.gte`/`.lt`/`.lte` are only ever meaningful for numeric fields.
|
|
53
|
+
* Intersected onto `AssignmentFieldRef<T>` only when `T` is (or includes)
|
|
54
|
+
* `number`, so e.g. `workItem.title.gt(...)` doesn't even type-check, let
|
|
55
|
+
* alone appear in autocomplete.
|
|
56
|
+
*/
|
|
57
|
+
type NumericComparators = {
|
|
54
58
|
gt(value: number): AssignmentLeaf;
|
|
55
59
|
gte(value: number): AssignmentLeaf;
|
|
56
60
|
lt(value: number): AssignmentLeaf;
|
|
57
61
|
lte(value: number): AssignmentLeaf;
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Comparator-bound reference to a work-item field or context fact.
|
|
65
|
+
*
|
|
66
|
+
* `T` is the field's value type (defaulting to `unknown`, which preserves
|
|
67
|
+
* the pre-generic behavior for any caller that doesn't otherwise constrain
|
|
68
|
+
* it). `.contains`/`.doesNotContain` narrow to the array element type when
|
|
69
|
+
* `T` is an array — json-rules-engine's `contains`/`doesNotContain`
|
|
70
|
+
* operators check array-membership (or substring-membership for strings)
|
|
71
|
+
* against the fact's actual runtime shape, so an array-typed field's
|
|
72
|
+
* `.contains(...)` should accept one element, not the whole array.
|
|
73
|
+
*/
|
|
74
|
+
export type AssignmentFieldRef<T = unknown> = {
|
|
75
|
+
eq(value: T): AssignmentLeaf;
|
|
76
|
+
ne(value: T): AssignmentLeaf;
|
|
77
|
+
in(values: ReadonlyArray<T>): AssignmentLeaf;
|
|
78
|
+
notIn(values: ReadonlyArray<T>): AssignmentLeaf;
|
|
79
|
+
contains(value: T extends ReadonlyArray<infer U> ? U : T): AssignmentLeaf;
|
|
80
|
+
doesNotContain(value: T extends ReadonlyArray<infer U> ? U : T): AssignmentLeaf;
|
|
81
|
+
} & (T extends number ? NumericComparators : Record<string, never>);
|
|
82
|
+
/** Comparator-bound accessor for the work item passed to `defaultPipelineAssignment`. */
|
|
83
|
+
export type WorkItemAssignmentAccessor = {
|
|
84
|
+
[K in WorkItemTopLevelField]: AssignmentFieldRef<WorkItemTopLevelFieldTypeMap[K]>;
|
|
85
|
+
} & {
|
|
86
|
+
/**
|
|
87
|
+
* Accessor for a platform-specific field (Jira custom field, GitHub label,
|
|
88
|
+
* etc.) stored in the work item's `fields` bag. Since `fields` keys and
|
|
89
|
+
* value shapes are platform- and project-dependent, there is no static
|
|
90
|
+
* schema to check either against by default.
|
|
91
|
+
*
|
|
92
|
+
* Two independent, optional type parameters:
|
|
93
|
+
* - `TName` constrains the `name` argument itself — pass a literal union
|
|
94
|
+
* of known field names (e.g. the `WorkItemFieldName` type
|
|
95
|
+
* `boboddy pipelines pull` generates into `work-item-fields.ts`) to get
|
|
96
|
+
* compile-time validation and autocomplete on the field name.
|
|
97
|
+
* - `TValue` types the comparator (`.eq`/`.gte`/etc.) argument, exactly
|
|
98
|
+
* like the top-level accessors above — pass it for a known-shaped
|
|
99
|
+
* custom field (e.g. a numeric one).
|
|
100
|
+
* Both default to permissive types, so `workItem.field(name)` with no
|
|
101
|
+
* type arguments keeps working exactly as before.
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* workItem.field("issueType").eq("bug")
|
|
105
|
+
* workItem.field("labels").contains("regression")
|
|
106
|
+
* workItem.field<WorkItemFieldName>("issueType").eq("bug")
|
|
107
|
+
* workItem.field<WorkItemFieldName, number>("storyPoints").gte(3)
|
|
108
|
+
*/
|
|
109
|
+
field<TName extends string = string, TValue = unknown>(name: TName): AssignmentFieldRef<TValue>;
|
|
110
|
+
};
|
|
63
111
|
export type DefaultPipelineAssignmentCtx = {
|
|
64
112
|
/**
|
|
65
|
-
* Work-item
|
|
113
|
+
* Work-item accessor: top-level properties (`workItem.title`,
|
|
114
|
+
* `workItem.platform`, `workItem.url`, ...) plus `workItem.field(name)`
|
|
115
|
+
* for the platform-specific `fields` bag.
|
|
66
116
|
*
|
|
67
117
|
* @example
|
|
68
118
|
* workItem.field("issueType").eq("bug").then(assign(bugTriage))
|
|
69
119
|
* workItem.field("labels").contains("regression").then(assign(regressionReview))
|
|
70
120
|
* workItem.field("status").eq("resolved").then(skip())
|
|
121
|
+
* workItem.platform.eq("github").then(assign(githubTriage))
|
|
122
|
+
* workItem.title.contains("[urgent]").then(assign(urgentTriage))
|
|
71
123
|
*/
|
|
72
|
-
workItem:
|
|
73
|
-
field(name: string): AssignmentFieldRef;
|
|
74
|
-
};
|
|
124
|
+
workItem: WorkItemAssignmentAccessor;
|
|
75
125
|
/**
|
|
76
126
|
* Context facts for the current ingestion event.
|
|
77
127
|
* `context.isNew` is `true` when the work item is being created for the first time.
|
|
@@ -80,7 +130,7 @@ export type DefaultPipelineAssignmentCtx = {
|
|
|
80
130
|
* context.isNew.eq(true).then(assign(onboarding))
|
|
81
131
|
*/
|
|
82
132
|
context: {
|
|
83
|
-
isNew: AssignmentFieldRef
|
|
133
|
+
isNew: AssignmentFieldRef<boolean>;
|
|
84
134
|
};
|
|
85
135
|
/**
|
|
86
136
|
* Outcome: assign the work item to the given pipeline.
|
|
@@ -14821,14 +14821,48 @@ function materializeAccessor(accessor) {
|
|
|
14821
14821
|
};
|
|
14822
14822
|
}
|
|
14823
14823
|
|
|
14824
|
+
// src/definitions/pipelines/work-item-fields.ts
|
|
14825
|
+
var WORK_ITEM_TOP_LEVEL_FIELDS = [
|
|
14826
|
+
"id",
|
|
14827
|
+
"projectId",
|
|
14828
|
+
"platform",
|
|
14829
|
+
"platformId",
|
|
14830
|
+
"platformKey",
|
|
14831
|
+
"url",
|
|
14832
|
+
"title",
|
|
14833
|
+
"description",
|
|
14834
|
+
"sourceCreatedAt",
|
|
14835
|
+
"sourceUpdatedAt",
|
|
14836
|
+
"createdByUserId",
|
|
14837
|
+
"parentWorkItemId",
|
|
14838
|
+
"createdAt",
|
|
14839
|
+
"updatedAt"
|
|
14840
|
+
];
|
|
14841
|
+
var WORK_ITEM_FIELDS_PATH_PREFIX = "fields.";
|
|
14842
|
+
function resolveWorkItemFieldPath(record2, path) {
|
|
14843
|
+
if (typeof record2 !== "object" || record2 === null)
|
|
14844
|
+
return;
|
|
14845
|
+
const asRecord = record2;
|
|
14846
|
+
if (path.startsWith(WORK_ITEM_FIELDS_PATH_PREFIX)) {
|
|
14847
|
+
const fieldName = path.slice(WORK_ITEM_FIELDS_PATH_PREFIX.length);
|
|
14848
|
+
const fields = asRecord["fields"];
|
|
14849
|
+
if (typeof fields !== "object" || fields === null)
|
|
14850
|
+
return;
|
|
14851
|
+
return fields[fieldName];
|
|
14852
|
+
}
|
|
14853
|
+
return asRecord[path];
|
|
14854
|
+
}
|
|
14855
|
+
|
|
14824
14856
|
// src/definitions/pipelines/builder-helpers.ts
|
|
14825
14857
|
var WORK_ITEM_ACCESSOR = Object.freeze({
|
|
14826
|
-
|
|
14827
|
-
|
|
14858
|
+
...Object.fromEntries(WORK_ITEM_TOP_LEVEL_FIELDS.map((field) => [
|
|
14859
|
+
field,
|
|
14860
|
+
Object.freeze({ source: "work_item", field })
|
|
14861
|
+
])),
|
|
14862
|
+
field: (fieldName) => Object.freeze({
|
|
14828
14863
|
source: "work_item",
|
|
14829
|
-
field:
|
|
14830
|
-
})
|
|
14831
|
-
field: (fieldName) => Object.freeze({ source: "work_item", field: `fields.${fieldName}` })
|
|
14864
|
+
field: `${WORK_ITEM_FIELDS_PATH_PREFIX}${fieldName}`
|
|
14865
|
+
})
|
|
14832
14866
|
});
|
|
14833
14867
|
var WORK_ITEM_FIELD_BINDINGS = {
|
|
14834
14868
|
workItemTitle: { source: "work_item", field: "title" },
|
|
@@ -14879,7 +14913,7 @@ function resolveAdditionalStepInputBindings(label, definition) {
|
|
|
14879
14913
|
const raw = definition.bindings({
|
|
14880
14914
|
workItemField: (fieldName) => ({
|
|
14881
14915
|
source: "work_item",
|
|
14882
|
-
field:
|
|
14916
|
+
field: `${WORK_ITEM_FIELDS_PATH_PREFIX}${fieldName}`
|
|
14883
14917
|
}),
|
|
14884
14918
|
literal: literal2
|
|
14885
14919
|
});
|
|
@@ -16892,7 +16926,7 @@ function makeLeaf(fact, path, operator, value) {
|
|
|
16892
16926
|
};
|
|
16893
16927
|
}
|
|
16894
16928
|
function makeFieldRef(fact, path) {
|
|
16895
|
-
|
|
16929
|
+
const untyped = {
|
|
16896
16930
|
eq: (v) => makeLeaf(fact, path, "equal", v),
|
|
16897
16931
|
ne: (v) => makeLeaf(fact, path, "notEqual", v),
|
|
16898
16932
|
gt: (v) => makeLeaf(fact, path, "greaterThan", v),
|
|
@@ -16904,6 +16938,16 @@ function makeFieldRef(fact, path) {
|
|
|
16904
16938
|
contains: (v) => makeLeaf(fact, path, "contains", v),
|
|
16905
16939
|
doesNotContain: (v) => makeLeaf(fact, path, "doesNotContain", v)
|
|
16906
16940
|
};
|
|
16941
|
+
return untyped;
|
|
16942
|
+
}
|
|
16943
|
+
function buildWorkItemAccessor() {
|
|
16944
|
+
const accessor = {
|
|
16945
|
+
field: (name) => makeFieldRef("workItem", `$.${WORK_ITEM_FIELDS_PATH_PREFIX}${name}`)
|
|
16946
|
+
};
|
|
16947
|
+
for (const key of WORK_ITEM_TOP_LEVEL_FIELDS) {
|
|
16948
|
+
accessor[key] = makeFieldRef("workItem", `$.${key}`);
|
|
16949
|
+
}
|
|
16950
|
+
return accessor;
|
|
16907
16951
|
}
|
|
16908
16952
|
function makeAssign(pipeline2) {
|
|
16909
16953
|
if (typeof pipeline2 !== "object" || typeof pipeline2["key"] !== "string" || !Array.isArray(pipeline2["nodeDefinitions"])) {
|
|
@@ -16926,9 +16970,7 @@ function makeGroup(mode, refs) {
|
|
|
16926
16970
|
}
|
|
16927
16971
|
function buildCtx() {
|
|
16928
16972
|
return {
|
|
16929
|
-
workItem:
|
|
16930
|
-
field: (name) => makeFieldRef("workItem", `$.fields.${name}`)
|
|
16931
|
-
},
|
|
16973
|
+
workItem: buildWorkItemAccessor(),
|
|
16932
16974
|
context: {
|
|
16933
16975
|
isNew: makeFieldRef("context", "$.isNew")
|
|
16934
16976
|
},
|
|
@@ -17008,6 +17050,7 @@ function isDefaultPipelineAssignmentSpec(value) {
|
|
|
17008
17050
|
}
|
|
17009
17051
|
export {
|
|
17010
17052
|
serializeDefaultPipelineAssignment,
|
|
17053
|
+
resolveWorkItemFieldPath,
|
|
17011
17054
|
pipeline,
|
|
17012
17055
|
materializeAccessor,
|
|
17013
17056
|
literal2 as literal,
|
|
@@ -17017,6 +17060,8 @@ export {
|
|
|
17017
17060
|
createPipelineDefinitionsClient,
|
|
17018
17061
|
createInputAccessor,
|
|
17019
17062
|
buildPipelineSpec,
|
|
17063
|
+
WORK_ITEM_TOP_LEVEL_FIELDS,
|
|
17064
|
+
WORK_ITEM_FIELDS_PATH_PREFIX,
|
|
17020
17065
|
Rule,
|
|
17021
17066
|
PipelineStepBuilder,
|
|
17022
17067
|
PipelineBuilder,
|
|
@@ -20,7 +20,9 @@ declare const buildPipelineDefinitionsClient: (pipelineDefinitions: PipelineDefi
|
|
|
20
20
|
description: string | unknown;
|
|
21
21
|
status: "draft" | "active" | "archived";
|
|
22
22
|
archivedAt: string | unknown;
|
|
23
|
-
inputSchemaJson:
|
|
23
|
+
inputSchemaJson: {
|
|
24
|
+
[key: string]: unknown;
|
|
25
|
+
} | unknown;
|
|
24
26
|
stepDefinitions: Array<{
|
|
25
27
|
id: string;
|
|
26
28
|
pipelineDefinitionId: string;
|
|
@@ -51,7 +53,9 @@ declare const buildPipelineDefinitionsClient: (pipelineDefinitions: PipelineDefi
|
|
|
51
53
|
};
|
|
52
54
|
} | unknown;
|
|
53
55
|
timeoutSeconds: number | unknown;
|
|
54
|
-
retryPolicyJson:
|
|
56
|
+
retryPolicyJson: {
|
|
57
|
+
[key: string]: unknown;
|
|
58
|
+
} | unknown;
|
|
55
59
|
advancementPolicyDefinition: {
|
|
56
60
|
id: string;
|
|
57
61
|
pipelineStepDefinitionId: string;
|
|
@@ -100,7 +104,9 @@ declare const buildPipelineDefinitionsClient: (pipelineDefinitions: PipelineDefi
|
|
|
100
104
|
}>;
|
|
101
105
|
};
|
|
102
106
|
defaultEventType: "continue" | "block" | "complete" | "route";
|
|
103
|
-
defaultEventParamsJson:
|
|
107
|
+
defaultEventParamsJson: {
|
|
108
|
+
[key: string]: unknown;
|
|
109
|
+
} | unknown;
|
|
104
110
|
allowedEventTypes: Array<"continue" | "block" | "complete" | "route">;
|
|
105
111
|
createdAt: string;
|
|
106
112
|
updatedAt: string;
|
|
@@ -110,7 +116,9 @@ declare const buildPipelineDefinitionsClient: (pipelineDefinitions: PipelineDefi
|
|
|
110
116
|
key: string;
|
|
111
117
|
type: "average" | "weighted_average" | "sum" | "min" | "max" | "count" | "boolean_any" | "boolean_all";
|
|
112
118
|
inputSignalKeys: Array<string>;
|
|
113
|
-
configJson:
|
|
119
|
+
configJson: {
|
|
120
|
+
[key: string]: unknown;
|
|
121
|
+
} | unknown;
|
|
114
122
|
availableWhenResultStatusIn: Array<string> | unknown;
|
|
115
123
|
createdAt: string;
|
|
116
124
|
updatedAt: string;
|
|
@@ -138,7 +146,9 @@ declare const buildPipelineDefinitionsClient: (pipelineDefinitions: PipelineDefi
|
|
|
138
146
|
description: string | unknown;
|
|
139
147
|
status: "draft" | "active" | "archived";
|
|
140
148
|
archivedAt: string | unknown;
|
|
141
|
-
inputSchemaJson:
|
|
149
|
+
inputSchemaJson: {
|
|
150
|
+
[key: string]: unknown;
|
|
151
|
+
} | unknown;
|
|
142
152
|
stepDefinitions: Array<{
|
|
143
153
|
id: string;
|
|
144
154
|
pipelineDefinitionId: string;
|
|
@@ -169,7 +179,9 @@ declare const buildPipelineDefinitionsClient: (pipelineDefinitions: PipelineDefi
|
|
|
169
179
|
};
|
|
170
180
|
} | unknown;
|
|
171
181
|
timeoutSeconds: number | unknown;
|
|
172
|
-
retryPolicyJson:
|
|
182
|
+
retryPolicyJson: {
|
|
183
|
+
[key: string]: unknown;
|
|
184
|
+
} | unknown;
|
|
173
185
|
advancementPolicyDefinition: {
|
|
174
186
|
id: string;
|
|
175
187
|
pipelineStepDefinitionId: string;
|
|
@@ -218,7 +230,9 @@ declare const buildPipelineDefinitionsClient: (pipelineDefinitions: PipelineDefi
|
|
|
218
230
|
}>;
|
|
219
231
|
};
|
|
220
232
|
defaultEventType: "continue" | "block" | "complete" | "route";
|
|
221
|
-
defaultEventParamsJson:
|
|
233
|
+
defaultEventParamsJson: {
|
|
234
|
+
[key: string]: unknown;
|
|
235
|
+
} | unknown;
|
|
222
236
|
allowedEventTypes: Array<"continue" | "block" | "complete" | "route">;
|
|
223
237
|
createdAt: string;
|
|
224
238
|
updatedAt: string;
|
|
@@ -228,7 +242,9 @@ declare const buildPipelineDefinitionsClient: (pipelineDefinitions: PipelineDefi
|
|
|
228
242
|
key: string;
|
|
229
243
|
type: "average" | "weighted_average" | "sum" | "min" | "max" | "count" | "boolean_any" | "boolean_all";
|
|
230
244
|
inputSignalKeys: Array<string>;
|
|
231
|
-
configJson:
|
|
245
|
+
configJson: {
|
|
246
|
+
[key: string]: unknown;
|
|
247
|
+
} | unknown;
|
|
232
248
|
availableWhenResultStatusIn: Array<string> | unknown;
|
|
233
249
|
createdAt: string;
|
|
234
250
|
updatedAt: string;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import type { GetApiWorkItemsByWorkItemIdResponses } from "../../generated/types.gen";
|
|
2
|
+
/**
|
|
3
|
+
* Top-level work-item properties addressable by every work-item binding
|
|
4
|
+
* mechanism in the SDK: the default-pipeline-assignment DSL's
|
|
5
|
+
* `workItem.<field>` accessor (`define-default-pipeline-assignment.ts`) and
|
|
6
|
+
* the regular pipeline/step `workItem.<field>` accessor
|
|
7
|
+
* (`builder-helpers.ts`'s `WorkItemAccessor`) — and, reversed, both
|
|
8
|
+
* `boboddy pipelines pull` file generators
|
|
9
|
+
* (`default-pipeline-assignment-file-generator.ts`,
|
|
10
|
+
* `pipeline-file-generator.ts`). `fields` is deliberately excluded from this
|
|
11
|
+
* list: it's reached via `.field(name)` on every one of those accessors, not
|
|
12
|
+
* as a top-level property.
|
|
13
|
+
*
|
|
14
|
+
* This is the single source of truth for the list — it must stay in sync
|
|
15
|
+
* with the `workItem` fact/context shape every corresponding server-side
|
|
16
|
+
* resolver publishes (`buildFacts` in
|
|
17
|
+
* `evaluate-default-pipeline-assignment.ts`; `buildResolvedWorkItemContext`
|
|
18
|
+
* in `resolve-node-input.ts`).
|
|
19
|
+
*/
|
|
20
|
+
export declare const WORK_ITEM_TOP_LEVEL_FIELDS: readonly ["id", "projectId", "platform", "platformId", "platformKey", "url", "title", "description", "sourceCreatedAt", "sourceUpdatedAt", "createdByUserId", "parentWorkItemId", "createdAt", "updatedAt"];
|
|
21
|
+
export type WorkItemTopLevelField = (typeof WORK_ITEM_TOP_LEVEL_FIELDS)[number];
|
|
22
|
+
/**
|
|
23
|
+
* The literal union of valid work-item platforms, sourced from the generated
|
|
24
|
+
* OpenAPI response type (`GetApiWorkItemsByWorkItemIdResponses[200]["platform"]`)
|
|
25
|
+
* rather than hand-duplicated, so it cannot drift from the API contract. It
|
|
26
|
+
* must mirror `WorkItemPlatform` in
|
|
27
|
+
* `packages/core/src/work-items/work-item/domain/work-item-platform.ts`.
|
|
28
|
+
*/
|
|
29
|
+
type WorkItemPlatformLiteral = GetApiWorkItemsByWorkItemIdResponses[200]["platform"];
|
|
30
|
+
/**
|
|
31
|
+
* Per-field value types for every member of `WORK_ITEM_TOP_LEVEL_FIELDS`,
|
|
32
|
+
* mirroring exactly what the server-side resolvers publish at evaluation/
|
|
33
|
+
* resolution time (`buildFacts` for default-pipeline-assignment;
|
|
34
|
+
* `buildResolvedWorkItemContext` for regular pipeline/step input bindings).
|
|
35
|
+
* Notably, `sourceCreatedAt`/`sourceUpdatedAt`/`createdAt`/`updatedAt` are
|
|
36
|
+
* serialized as ISO date strings (or `null`), never `Date` objects.
|
|
37
|
+
*/
|
|
38
|
+
export type WorkItemTopLevelFieldTypeMap = {
|
|
39
|
+
id: string;
|
|
40
|
+
projectId: string;
|
|
41
|
+
platform: WorkItemPlatformLiteral;
|
|
42
|
+
platformId: string | null;
|
|
43
|
+
platformKey: string;
|
|
44
|
+
url: string | null;
|
|
45
|
+
title: string;
|
|
46
|
+
description: string | null;
|
|
47
|
+
sourceCreatedAt: string | null;
|
|
48
|
+
sourceUpdatedAt: string | null;
|
|
49
|
+
createdByUserId: string | null;
|
|
50
|
+
parentWorkItemId: string | null;
|
|
51
|
+
createdAt: string | null;
|
|
52
|
+
updatedAt: string | null;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* The path prefix marking a reference into a work item's platform-specific
|
|
56
|
+
* `fields` bag (a Jira custom field, a GitHub label, etc.), as opposed to a
|
|
57
|
+
* `WorkItemTopLevelField`. Shared by every accessor that authors these paths
|
|
58
|
+
* (`workItem.field(name)` in both the default-pipeline-assignment DSL and
|
|
59
|
+
* the regular pipeline/step `WorkItemAccessor`) and every resolver that
|
|
60
|
+
* reads them back (`resolveWorkItemFieldPath` below; the JSONPath-rooted
|
|
61
|
+
* variant in `evaluate-default-pipeline-assignment.ts`, which layers a `$.`
|
|
62
|
+
* prefix on top of this same convention).
|
|
63
|
+
*/
|
|
64
|
+
export declare const WORK_ITEM_FIELDS_PATH_PREFIX = "fields.";
|
|
65
|
+
/**
|
|
66
|
+
* Resolves a work-item path — either a `WorkItemTopLevelField` name (a
|
|
67
|
+
* single, code-controlled segment) or a `fields.<name>` reference into the
|
|
68
|
+
* platform-specific `fields` bag — against a plain object shaped like
|
|
69
|
+
* `WorkItemTopLevelFieldTypeMap & { fields: ... }`.
|
|
70
|
+
*
|
|
71
|
+
* `<name>` in `fields.<name>` is an arbitrary, unescaped, platform-supplied
|
|
72
|
+
* field name (a Jira custom field label, a GitHub key, etc.) that may
|
|
73
|
+
* contain any character, including `.`, `[`, `]`, `~`, `^`, `;`, or even be
|
|
74
|
+
* the empty string. A naive dot-splitting path walker would silently
|
|
75
|
+
* misresolve a field literally named `"a.b"` as nested property access
|
|
76
|
+
* (`fields.a.b`) instead of the flat key `fields["a.b"]` — a silent-wrong-
|
|
77
|
+
* match hazard, not a visible error, since the walker degrades to "no
|
|
78
|
+
* match"/"wrong match" rather than throwing.
|
|
79
|
+
*
|
|
80
|
+
* This resolver sidesteps that hazard entirely: everything after `fields.`
|
|
81
|
+
* is treated as one atomic, unsplit key. Every work-item path resolver in
|
|
82
|
+
* the codebase must use this same convention for a field name to round-trip
|
|
83
|
+
* correctly — see `evaluate-default-pipeline-assignment.ts`'s
|
|
84
|
+
* `resolveWorkItemAssignmentPath` (which layers `$.` path-rooting on top of
|
|
85
|
+
* this function) and `resolve-node-input.ts`'s `work_item` binding
|
|
86
|
+
* resolution (which calls this function directly, replacing what used to be
|
|
87
|
+
* a dot-splitting walker shared with unrelated binding sources and
|
|
88
|
+
* susceptible to the exact hazard described above).
|
|
89
|
+
*
|
|
90
|
+
* `path` is untyped (`string`, not `WorkItemTopLevelField | \`fields.${string}\``)
|
|
91
|
+
* because callers validate membership separately
|
|
92
|
+
* (`WORK_ITEM_TOP_LEVEL_FIELDS`/`isSupportedWorkItemField`) before ever
|
|
93
|
+
* reaching a resolver — this function's contract is purely "resolve
|
|
94
|
+
* whatever path string you hand it, treating `fields.` as atomic," not
|
|
95
|
+
* "validate the path."
|
|
96
|
+
*/
|
|
97
|
+
export declare function resolveWorkItemFieldPath(record: unknown, path: string): unknown;
|
|
98
|
+
export {};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ZodType } from "zod";
|
|
2
2
|
import type { AnyStepFeature, FeatureResultExtensions, FeatureSignalKeys } from "./step-features";
|
|
3
3
|
import { type PromptTemplateContext } from "./prompt-template";
|
|
4
|
+
import type { LiteralBinding, WorkItemBinding } from "../pipelines/define-pipeline";
|
|
4
5
|
type OpenCodeMcpServers = Record<string, {
|
|
5
6
|
type: "local";
|
|
6
7
|
command: string[];
|
|
@@ -89,14 +90,24 @@ export type DefineStepInput<TInput extends ZodType = ZodType, TResult extends Zo
|
|
|
89
90
|
status?: "draft" | "active";
|
|
90
91
|
executionMode?: "workspace" | "no_workspace";
|
|
91
92
|
};
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
93
|
+
/**
|
|
94
|
+
* @deprecated Alias for `LiteralBinding` (`define-pipeline.ts`) — the two
|
|
95
|
+
* used to be independently declared, structurally-identical types. Kept
|
|
96
|
+
* only so existing imports of this name keep working.
|
|
97
|
+
*/
|
|
98
|
+
export type AdditionalStepInputLiteralBinding = LiteralBinding;
|
|
99
|
+
/**
|
|
100
|
+
* The binding sources available to `PipelineMeta.additionalStepInput`'s
|
|
101
|
+
* `bindings` callback (`workItemField(...)`/`literal(...)` in
|
|
102
|
+
* `builder-helpers.ts`'s `resolveAdditionalStepInputBindings`) — the same
|
|
103
|
+
* `WorkItemBinding`/`LiteralBinding` shapes `.step()`'s own `input` mapper
|
|
104
|
+
* uses (`define-pipeline.ts`'s `AnyBinding`), restricted to the subset
|
|
105
|
+
* `resolveAdditionalStepInputBindings` can actually produce. Previously an
|
|
106
|
+
* independently-declared `{ source: "work_item"; field: string }` union
|
|
107
|
+
* member that had drifted apart from `WorkItemBinding` in shape only by
|
|
108
|
+
* coincidence, not by design.
|
|
109
|
+
*/
|
|
110
|
+
export type AdditionalStepInputBinding = WorkItemBinding | LiteralBinding;
|
|
100
111
|
export type StepDefinitionSpec = {
|
|
101
112
|
key: string;
|
|
102
113
|
name: string;
|
|
@@ -18,8 +18,12 @@ declare const buildStepDefinitionsClient: (stepDefinitions: StepDefinitions) =>
|
|
|
18
18
|
version: number;
|
|
19
19
|
kind: "built_in" | "user_defined";
|
|
20
20
|
executionMode: "workspace" | "no_workspace";
|
|
21
|
-
inputSchemaJson:
|
|
22
|
-
|
|
21
|
+
inputSchemaJson: {
|
|
22
|
+
[key: string]: unknown;
|
|
23
|
+
} | unknown;
|
|
24
|
+
resultSchemaJson: {
|
|
25
|
+
[key: string]: unknown;
|
|
26
|
+
} | unknown;
|
|
23
27
|
opencodeMcpJson: {
|
|
24
28
|
[key: string]: {
|
|
25
29
|
type: string;
|
|
@@ -82,8 +86,12 @@ declare const buildStepDefinitionsClient: (stepDefinitions: StepDefinitions) =>
|
|
|
82
86
|
version: number;
|
|
83
87
|
kind: "built_in" | "user_defined";
|
|
84
88
|
executionMode: "workspace" | "no_workspace";
|
|
85
|
-
inputSchemaJson:
|
|
86
|
-
|
|
89
|
+
inputSchemaJson: {
|
|
90
|
+
[key: string]: unknown;
|
|
91
|
+
} | unknown;
|
|
92
|
+
resultSchemaJson: {
|
|
93
|
+
[key: string]: unknown;
|
|
94
|
+
} | unknown;
|
|
87
95
|
opencodeMcpJson: {
|
|
88
96
|
[key: string]: {
|
|
89
97
|
type: string;
|
|
@@ -151,8 +159,12 @@ declare const buildStepDefinitionsClient: (stepDefinitions: StepDefinitions) =>
|
|
|
151
159
|
version: number;
|
|
152
160
|
kind: "built_in" | "user_defined";
|
|
153
161
|
executionMode: "workspace" | "no_workspace";
|
|
154
|
-
inputSchemaJson:
|
|
155
|
-
|
|
162
|
+
inputSchemaJson: {
|
|
163
|
+
[key: string]: unknown;
|
|
164
|
+
} | unknown;
|
|
165
|
+
resultSchemaJson: {
|
|
166
|
+
[key: string]: unknown;
|
|
167
|
+
} | unknown;
|
|
156
168
|
opencodeMcpJson: {
|
|
157
169
|
[key: string]: {
|
|
158
170
|
type: string;
|