@scarn/sdk 0.0.0-stage → 0.8.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/dist/chunk-0y2fy5en.js +166 -0
- package/dist/chunk-3ctaaseb.js +1456 -0
- package/dist/chunk-4ggr8af6.js +30 -0
- package/dist/chunk-5zsavw98.js +91 -0
- package/dist/chunk-63f90zky.js +39 -0
- package/dist/chunk-700xe701.js +100 -0
- package/dist/chunk-ar6hcj1r.js +35 -0
- package/dist/chunk-cdanncng.js +74 -0
- package/dist/chunk-dp86pa6m.js +68 -0
- package/dist/chunk-e1h021kq.js +86 -0
- package/dist/chunk-gds7w7zh.js +330 -0
- package/dist/chunk-k4y5qt4y.js +14 -0
- package/dist/chunk-mz53r914.js +300 -0
- package/dist/chunk-ngy1fdcx.js +57 -0
- package/dist/chunk-p7yrcmqm.js +322 -0
- package/dist/chunk-rt9tq4j6.js +116 -0
- package/dist/chunk-skzxcba3.js +14282 -0
- package/dist/chunk-vfeytkqx.js +1687 -0
- package/dist/chunk-y2pv8d6a.js +162 -0
- package/dist/chunk-y64skrwp.js +17 -0
- package/dist/chunk-yjtaq94c.js +1094 -0
- package/dist/chunk-zm72ksz0.js +256 -0
- package/dist/client.d.ts +4 -0
- package/dist/client.js +58 -0
- package/dist/contracts/artifact-markers.d.ts +42 -0
- package/dist/contracts/artifact-markers.js +16 -0
- package/dist/contracts/artifacts.d.ts +67 -0
- package/dist/contracts/artifacts.js +27 -0
- package/dist/contracts/pipeline-document/built-ins.d.ts +23 -0
- package/dist/contracts/pipeline-document/conditions/operators.d.ts +8 -0
- package/dist/contracts/pipeline-document/index.d.ts +11 -0
- package/dist/contracts/pipeline-document/index.js +99 -0
- package/dist/contracts/pipeline-document/json.d.ts +35 -0
- package/dist/contracts/pipeline-document/routes.d.ts +16 -0
- package/dist/contracts/pipeline-document/schema.d.ts +780 -0
- package/dist/contracts/pipeline-document/step-contract.d.ts +11 -0
- package/dist/contracts/step-artifact-submissions.d.ts +71 -0
- package/dist/contracts/step-artifact-submissions.js +171 -0
- package/dist/defaults/atomic-json-file.d.ts +10 -0
- package/dist/defaults/auth-file.d.ts +14 -0
- package/dist/defaults/base-url.d.ts +1 -0
- package/dist/defaults/config-file.d.ts +46 -0
- package/dist/defaults/home-dir.d.ts +3 -0
- package/dist/defaults/index.d.ts +12 -0
- package/dist/defaults/index.js +1240 -0
- package/dist/defaults/legacy-config-migration.d.ts +27 -0
- package/dist/defaults/load-push-defaults.d.ts +25 -0
- package/dist/defaults/project-config.d.ts +32 -0
- package/dist/defaults/project-ref.d.ts +34 -0
- package/dist/definitions/artifacts/artifact.d.ts +62 -0
- package/dist/definitions/artifacts/index.d.ts +1 -0
- package/dist/definitions/pipelines/define-default-pipeline-assignment.d.ts +263 -0
- package/dist/definitions/pipelines/index.d.ts +3 -0
- package/dist/definitions/pipelines/index.js +26 -0
- package/dist/definitions/pipelines/pipeline-definitions-client.d.ts +208 -0
- package/dist/definitions/pipelines/work-item-fields.d.ts +93 -0
- package/dist/definitions/steps/compile-mcps.d.ts +34 -0
- package/dist/definitions/steps/define-code-step.d.ts +84 -0
- package/dist/definitions/steps/define-mcp.d.ts +79 -0
- package/dist/definitions/steps/define-step.d.ts +137 -0
- package/dist/definitions/steps/env.d.ts +136 -0
- package/dist/definitions/steps/index.d.ts +14 -0
- package/dist/definitions/steps/index.js +76 -0
- package/dist/definitions/steps/mcp-server-config.d.ts +102 -0
- package/dist/definitions/steps/prompt-template.d.ts +24 -0
- package/dist/definitions/steps/repo.d.ts +67 -0
- package/dist/definitions/steps/runtime.d.ts +115 -0
- package/dist/definitions/steps/step-definitions-client.d.ts +400 -0
- package/dist/definitions/steps/step-features.d.ts +109 -0
- package/dist/definitions/steps/step-handle.d.ts +25 -0
- package/dist/definitions/steps/step-ref.d.ts +19 -0
- package/dist/definitions/validation/index.d.ts +2 -0
- package/dist/definitions/validation/index.js +19 -0
- package/dist/definitions/validation/validate-artifact-markers.d.ts +3 -0
- package/dist/definitions/validation/validate-artifacts.d.ts +7 -0
- package/dist/definitions/validation/validate-definition-specs.d.ts +16 -0
- package/dist/definitions/validation/validate-env.d.ts +15 -0
- package/dist/definitions/validation/validate-repo.d.ts +13 -0
- package/dist/definitions/validation/validate-runtime.d.ts +12 -0
- package/dist/definitions/validation/validation-issue.d.ts +11 -0
- package/dist/devcontainer-config-path.d.ts +21 -0
- package/dist/devcontainer-config-path.js +15 -0
- package/dist/env-vars.d.ts +136 -0
- package/dist/env-vars.js +37 -0
- package/dist/eslint.d.ts +42 -0
- package/dist/eslint.js +127 -0
- package/dist/generated/client/client.gen.d.ts +2 -0
- package/dist/generated/client/index.d.ts +8 -0
- package/dist/generated/client/types.gen.d.ts +117 -0
- package/dist/generated/client/utils.gen.d.ts +33 -0
- package/dist/generated/client.gen.d.ts +12 -0
- package/dist/generated/core/auth.gen.d.ts +18 -0
- package/dist/generated/core/bodySerializer.gen.d.ts +25 -0
- package/dist/generated/core/params.gen.d.ts +43 -0
- package/dist/generated/core/pathSerializer.gen.d.ts +33 -0
- package/dist/generated/core/queryKeySerializer.gen.d.ts +18 -0
- package/dist/generated/core/serverSentEvents.gen.d.ts +71 -0
- package/dist/generated/core/types.gen.d.ts +78 -0
- package/dist/generated/core/utils.gen.d.ts +19 -0
- package/dist/generated/index.d.ts +2 -0
- package/dist/generated/sdk.gen.d.ts +302 -0
- package/dist/generated/types.gen.d.ts +18375 -0
- package/dist/git-url/git-remote.d.ts +30 -0
- package/dist/git-url/git-repo-identity.d.ts +44 -0
- package/dist/git-url/git-repo-identity.js +161 -0
- package/dist/git-url/parse-git-host.d.ts +23 -0
- package/dist/health-checks.d.ts +169 -0
- package/dist/health-checks.js +21 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +296 -0
- package/dist/jsonc.d.ts +3 -0
- package/dist/jsonc.js +12 -0
- package/dist/managed-runtimes.d.ts +20 -0
- package/dist/managed-runtimes.js +15 -0
- package/dist/opencode-mcp.d.ts +313 -0
- package/dist/opencode-mcp.js +31 -0
- package/dist/pipelines/chain.d.ts +7 -0
- package/dist/pipelines/compile-args.d.ts +12 -0
- package/dist/pipelines/compile-chain.d.ts +9 -0
- package/dist/pipelines/compile-checks.d.ts +16 -0
- package/dist/pipelines/compile-state.d.ts +30 -0
- package/dist/pipelines/condition-data.d.ts +78 -0
- package/dist/pipelines/conditions.d.ts +47 -0
- package/dist/pipelines/context.d.ts +16 -0
- package/dist/pipelines/define-pipeline.d.ts +32 -0
- package/dist/pipelines/each.d.ts +5 -0
- package/dist/pipelines/errors.d.ts +26 -0
- package/dist/pipelines/handles.d.ts +29 -0
- package/dist/pipelines/index.d.ts +18 -0
- package/dist/pipelines/index.js +83 -0
- package/dist/pipelines/model.d.ts +103 -0
- package/dist/pipelines/nodes.d.ts +54 -0
- package/dist/pipelines/ref-types.d.ts +54 -0
- package/dist/pipelines/refs.d.ts +80 -0
- package/dist/pipelines/registry.d.ts +12 -0
- package/dist/pipelines/source.d.ts +17 -0
- package/dist/pipelines/types.d.ts +160 -0
- package/dist/push/code-step-lookup.d.ts +32 -0
- package/dist/push/code-step-lookup.js +12 -0
- package/dist/push/collect-definitions.d.ts +70 -0
- package/dist/push/collect-pipeline-documents.d.ts +14 -0
- package/dist/push/index.d.ts +6 -0
- package/dist/push/index.js +327 -0
- package/dist/push/push-from-directory.d.ts +37 -0
- package/dist/repo-config.d.ts +80 -0
- package/dist/repo-config.js +25 -0
- package/dist/scarn-config-parser.d.ts +29 -0
- package/dist/scarn-config-parser.js +10 -0
- package/dist/task-plane-client.d.ts +489 -0
- package/dist/z.d.ts +7 -0
- package/package.json +132 -4
- package/README.md +0 -3
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One-time, idempotent: if either new file is still missing, find the old
|
|
3
|
+
* combined file (`.scarn.json`, falling back to the even older bare
|
|
4
|
+
* `.scarn`), split it, and delete it. Safe to call redundantly from both
|
|
5
|
+
* `auth-file.ts` and `config-file.ts` — whichever loads first does the work;
|
|
6
|
+
* the other's own `existsSync` check on its own new path short-circuits.
|
|
7
|
+
*
|
|
8
|
+
* Only checks the outer shape of `profiles`/`anonymousId`/`telemetryDisabled`
|
|
9
|
+
* (object / string / boolean) before handing them off — it deliberately does
|
|
10
|
+
* not deep-validate individual profiles the way `auth-file.ts`'s
|
|
11
|
+
* `isAuthFile` does on every read. That deeper check already runs the next
|
|
12
|
+
* time `auth.jsonc` is loaded (corrupt/invalid content there already falls
|
|
13
|
+
* back to empty, same as today), so duplicating it here would only catch
|
|
14
|
+
* corruption one call earlier, at the cost of this module importing
|
|
15
|
+
* `auth-file.ts`'s validation — which it must not do, since both
|
|
16
|
+
* `auth-file.ts` and `config-file.ts` import this module and must not import
|
|
17
|
+
* each other.
|
|
18
|
+
*/
|
|
19
|
+
export declare function migrateLegacyConfigIfNeeded(input: {
|
|
20
|
+
authFileExists: () => boolean;
|
|
21
|
+
configFileExists: () => boolean;
|
|
22
|
+
writeAuthFile: (profiles: Record<string, unknown>) => void;
|
|
23
|
+
writeConfigFile: (fields: {
|
|
24
|
+
anonymousId?: string;
|
|
25
|
+
telemetryDisabled?: boolean;
|
|
26
|
+
}) => void;
|
|
27
|
+
}): void;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface PushDefaults {
|
|
2
|
+
baseUrl: string;
|
|
3
|
+
projectId: string | undefined;
|
|
4
|
+
accessToken: string | undefined;
|
|
5
|
+
}
|
|
6
|
+
export interface LoadPushDefaultsOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Directory the script is running from. The project config (`.scarn/scarn.jsonc`)
|
|
9
|
+
* is searched for in this directory and each ancestor directory.
|
|
10
|
+
*/
|
|
11
|
+
dir: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Reads the conventional defaults for a `scarn pipelines push` run:
|
|
15
|
+
* - `baseUrl`: from `SCARN_BASE_URL` env var or the built-in default.
|
|
16
|
+
* - `accessToken`: from `SCARN_ACCESS_TOKEN` env var or the saved auth
|
|
17
|
+
* profile for the resolved `baseUrl`.
|
|
18
|
+
* - `projectId`: from `SCARN_PROJECT_ID` env var (a project id, which
|
|
19
|
+
* `scarn pipelines push` sets after resolving the ref), or else the
|
|
20
|
+
* `"project"` ref in the nearest ancestor `.scarn/scarn.jsonc` of
|
|
21
|
+
* `opts.dir`, resolved against the server. Resolution needs `accessToken`;
|
|
22
|
+
* without one `projectId` is left undefined. A ref the server rejects throws
|
|
23
|
+
* a `ProjectRefError` naming the ref.
|
|
24
|
+
*/
|
|
25
|
+
export declare function loadPushDefaults(opts: LoadPushDefaultsOptions): Promise<PushDefaults>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export interface ProjectConfig {
|
|
2
|
+
/**
|
|
3
|
+
* The project this repo belongs to, as `<owner>/<slug>` — the owner's
|
|
4
|
+
* username and the project slug, the same pair as the project's web URL.
|
|
5
|
+
*/
|
|
6
|
+
project: string;
|
|
7
|
+
/**
|
|
8
|
+
* Optional prefix for the per-step work branch name. The worker creates
|
|
9
|
+
* branches named `<branchPrefix>/<stepKey>-<taskId>`. Defaults to
|
|
10
|
+
* `scarn` when omitted or invalid.
|
|
11
|
+
*/
|
|
12
|
+
branchPrefix?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Optional base branch the FIRST step's work branch is created off of. The
|
|
15
|
+
* worker clones the repo's default HEAD, then checks out this branch before
|
|
16
|
+
* branching. Overridden by the `SCARN_BASE_WORK_BRANCH` env var in
|
|
17
|
+
* `.scarn/.env`. Ignored for later steps, which are always created off the
|
|
18
|
+
* predecessor step's work branch. Defaults to the repo's default branch when
|
|
19
|
+
* omitted or invalid.
|
|
20
|
+
*/
|
|
21
|
+
baseWorkBranch?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface ProjectRef {
|
|
24
|
+
owner: string;
|
|
25
|
+
slug: string;
|
|
26
|
+
}
|
|
27
|
+
/** Parses `<owner>/<slug>`, or returns `null` when either half breaks the rules. */
|
|
28
|
+
export declare function parseProjectRef(ref: string): ProjectRef | null;
|
|
29
|
+
export declare function isProjectRef(ref: string): boolean;
|
|
30
|
+
export declare function formatProjectRef(ref: ProjectRef): string;
|
|
31
|
+
export declare const PROJECT_CONFIG_RELATIVE_PATH: string;
|
|
32
|
+
export declare function loadProjectConfig(rootDir?: string): Promise<ProjectConfig | null>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { ScarnClient } from "../generated";
|
|
2
|
+
export interface ResolvedProjectRef {
|
|
3
|
+
id: string;
|
|
4
|
+
owner: string;
|
|
5
|
+
slug: string;
|
|
6
|
+
}
|
|
7
|
+
export type ProjectRefErrorKind = "invalid" | "not_found" | "forbidden" | "unauthenticated" | "failed";
|
|
8
|
+
/**
|
|
9
|
+
* A failure to turn `owner/slug` into a project. The message names the ref and
|
|
10
|
+
* the denied action, never a UUID, so it can be shown as-is.
|
|
11
|
+
*/
|
|
12
|
+
export declare class ProjectRefError extends Error {
|
|
13
|
+
readonly kind: ProjectRefErrorKind;
|
|
14
|
+
readonly ref: string;
|
|
15
|
+
constructor(kind: ProjectRefErrorKind, ref: string, message: string);
|
|
16
|
+
}
|
|
17
|
+
export interface ResolveProjectRefOptions {
|
|
18
|
+
headers: {
|
|
19
|
+
Authorization: string;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* What the caller is about to do, phrased to complete "You don't have
|
|
23
|
+
* permission to …" — e.g. `"push pipelines to"`, `"run work for"`.
|
|
24
|
+
* Defaults to `"view"`.
|
|
25
|
+
*/
|
|
26
|
+
action?: string;
|
|
27
|
+
}
|
|
28
|
+
export declare const PROJECT_REF_FORMAT_HINT = "Expected \"<owner>/<project-slug>\", e.g. \"acme/web-app\".";
|
|
29
|
+
/**
|
|
30
|
+
* Resolves a `owner/slug` project ref to its id via
|
|
31
|
+
* `GET /api/projects/resolve`. Every command that takes a project calls this
|
|
32
|
+
* once, up front, and passes the id downstream.
|
|
33
|
+
*/
|
|
34
|
+
export declare function resolveProjectRef(client: ScarnClient, ref: string, { headers, action }: ResolveProjectRefOptions): Promise<ResolvedProjectRef>;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const ARTIFACT_BRAND = "ScarnArtifact";
|
|
3
|
+
export type ArtifactBrand = typeof ARTIFACT_BRAND;
|
|
4
|
+
/** The value an artifact field holds: a path relative to `artifactsDir`. */
|
|
5
|
+
export type ArtifactPath = string & z.$brand<ArtifactBrand>;
|
|
6
|
+
export type ArtifactSchema = z.core.$ZodBranded<z.ZodString, ArtifactBrand>;
|
|
7
|
+
/**
|
|
8
|
+
* Extension presets for `artifact({ accept })`. They expand to plain
|
|
9
|
+
* extension lists when the step is defined; the server never sees the names.
|
|
10
|
+
*/
|
|
11
|
+
export declare const ArtifactTypes: {
|
|
12
|
+
readonly video: readonly [".mp4", ".webm", ".mov"];
|
|
13
|
+
readonly image: readonly [".png", ".jpg", ".jpeg", ".gif", ".svg"];
|
|
14
|
+
};
|
|
15
|
+
export type ArtifactOptions = {
|
|
16
|
+
/**
|
|
17
|
+
* File extensions the field accepts, e.g. `[".mp4", ".webm"]` or
|
|
18
|
+
* `[...ArtifactTypes.video, ".gif"]`. Omitted or empty accepts any file.
|
|
19
|
+
*/
|
|
20
|
+
readonly accept?: readonly string[];
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Validates and normalises an `accept` list: every entry must be a
|
|
24
|
+
* lower-case extension with a leading dot. Duplicates are dropped and order
|
|
25
|
+
* is kept.
|
|
26
|
+
*/
|
|
27
|
+
export declare function normalizeArtifactAccept(accept: readonly string[] | undefined): string[];
|
|
28
|
+
/**
|
|
29
|
+
* A result field holding a file the step produced. The field's value is the
|
|
30
|
+
* file's path relative to `artifactsDir`; agents fill it with
|
|
31
|
+
* `scarn-submit-artifact` and code steps return `Artifact.path(...)`.
|
|
32
|
+
*
|
|
33
|
+
* Serialises to `{ "type": "string", "x-scarn-artifact": { "accept": [...] } }`.
|
|
34
|
+
*/
|
|
35
|
+
export declare function artifact(options?: ArtifactOptions): ArtifactSchema;
|
|
36
|
+
/** An artifact field in a step's result: `path` is its dotted result path. */
|
|
37
|
+
export type StepArtifactRef = {
|
|
38
|
+
readonly step: {
|
|
39
|
+
readonly key: string;
|
|
40
|
+
};
|
|
41
|
+
readonly path: string;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* What an artifact marker points at: an artifact field in a step's result
|
|
45
|
+
* (required) or a name/glob relative to `artifactsDir` (optional).
|
|
46
|
+
*/
|
|
47
|
+
export type ArtifactMarkerTarget = StepArtifactRef | string;
|
|
48
|
+
export declare const Artifact: {
|
|
49
|
+
/** Brands a path relative to `artifactsDir` for a code step's artifact field. */
|
|
50
|
+
readonly path: (relativePath: string) => ArtifactPath;
|
|
51
|
+
/**
|
|
52
|
+
* A marker that shows the artifact inline in a work item comment where the
|
|
53
|
+
* platform can, and links to it otherwise. Put it in its own paragraph.
|
|
54
|
+
*/
|
|
55
|
+
readonly embed: (target: ArtifactMarkerTarget, options: {
|
|
56
|
+
caption: string;
|
|
57
|
+
}) => string;
|
|
58
|
+
/** A marker that links to the artifact. Put it in its own paragraph. */
|
|
59
|
+
readonly link: (target: ArtifactMarkerTarget, options: {
|
|
60
|
+
label: string;
|
|
61
|
+
}) => string;
|
|
62
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./artifact";
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import type { PipelineDefinition } from "../../pipelines/define-pipeline";
|
|
2
|
+
import { type WorkItemTopLevelField, type WorkItemTopLevelFieldTypeMap } from "./work-item-fields";
|
|
3
|
+
/**
|
|
4
|
+
* The reserved filename for the default pipeline assignment file.
|
|
5
|
+
* This file is NOT treated as a pipeline definition by the push scanner.
|
|
6
|
+
*/
|
|
7
|
+
export declare const DEFAULT_PIPELINE_ASSIGNMENT_FILENAME = "default-pipeline-assignment.ts";
|
|
8
|
+
type ConditionOperator = "equal" | "notEqual" | "lessThan" | "lessThanInclusive" | "greaterThan" | "greaterThanInclusive" | "in" | "notIn" | "contains" | "doesNotContain";
|
|
9
|
+
type LeafCondition = {
|
|
10
|
+
readonly _tag: "leaf";
|
|
11
|
+
/** Top-level fact name: "workItem" or "context". */
|
|
12
|
+
readonly fact: string;
|
|
13
|
+
/** JSONPath within the fact value, e.g. "$.fields.status". */
|
|
14
|
+
readonly path?: string;
|
|
15
|
+
readonly operator: ConditionOperator;
|
|
16
|
+
readonly value: unknown;
|
|
17
|
+
};
|
|
18
|
+
type GroupCondition = {
|
|
19
|
+
readonly _tag: "group";
|
|
20
|
+
readonly mode: "all" | "any";
|
|
21
|
+
readonly conditions: AssignmentCondition[];
|
|
22
|
+
};
|
|
23
|
+
type AssignmentCondition = LeafCondition | GroupCondition;
|
|
24
|
+
export type AssignOutcome = {
|
|
25
|
+
readonly _tag: "assign";
|
|
26
|
+
readonly pipelineKey: string;
|
|
27
|
+
};
|
|
28
|
+
/** What `assign(...)` accepts: a pipeline key, or a `definePipeline` value. */
|
|
29
|
+
export type AssignablePipeline = string | Pick<PipelineDefinition, "_tag" | "key">;
|
|
30
|
+
export type SkipOutcome = {
|
|
31
|
+
readonly _tag: "skip";
|
|
32
|
+
};
|
|
33
|
+
export type DefaultPipelineAssignmentOutcome = AssignOutcome | SkipOutcome;
|
|
34
|
+
export type AssignmentRule = {
|
|
35
|
+
readonly _tag: "assignment_rule";
|
|
36
|
+
readonly conditions: AssignmentCondition[];
|
|
37
|
+
readonly mode: "all" | "any";
|
|
38
|
+
readonly outcome: DefaultPipelineAssignmentOutcome;
|
|
39
|
+
};
|
|
40
|
+
/** A leaf condition; nestable in a group or terminable with `.then()`. */
|
|
41
|
+
export interface AssignmentLeaf {
|
|
42
|
+
then(outcome: DefaultPipelineAssignmentOutcome): AssignmentRule;
|
|
43
|
+
/** @internal */
|
|
44
|
+
readonly _condition: AssignmentCondition;
|
|
45
|
+
}
|
|
46
|
+
/** A group condition (`all`/`any`); nestable or terminable with `.then()`. */
|
|
47
|
+
export interface AssignmentGroup {
|
|
48
|
+
then(outcome: DefaultPipelineAssignmentOutcome): AssignmentRule;
|
|
49
|
+
/** @internal */
|
|
50
|
+
readonly _condition: AssignmentCondition;
|
|
51
|
+
}
|
|
52
|
+
type AssignmentNestable = AssignmentLeaf | AssignmentGroup;
|
|
53
|
+
/**
|
|
54
|
+
* `.gt`/`.gte`/`.lt`/`.lte` are only ever meaningful for numeric fields.
|
|
55
|
+
* Intersected onto `AssignmentFieldRef<T>` only when `T` is (or includes)
|
|
56
|
+
* `number`, so e.g. `workItem.title.gt(...)` doesn't even type-check, let
|
|
57
|
+
* alone appear in autocomplete.
|
|
58
|
+
*/
|
|
59
|
+
type NumericComparators = {
|
|
60
|
+
gt(value: number): AssignmentLeaf;
|
|
61
|
+
gte(value: number): AssignmentLeaf;
|
|
62
|
+
lt(value: number): AssignmentLeaf;
|
|
63
|
+
lte(value: number): AssignmentLeaf;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Comparator-bound reference to a work-item field or context fact.
|
|
67
|
+
*
|
|
68
|
+
* `T` is the field's value type (defaulting to `unknown`, which preserves
|
|
69
|
+
* the pre-generic behavior for any caller that doesn't otherwise constrain
|
|
70
|
+
* it). `.contains`/`.doesNotContain` narrow to the array element type when
|
|
71
|
+
* `T` is an array — json-rules-engine's `contains`/`doesNotContain`
|
|
72
|
+
* operators check array-membership (or substring-membership for strings)
|
|
73
|
+
* against the fact's actual runtime shape, so an array-typed field's
|
|
74
|
+
* `.contains(...)` should accept one element, not the whole array.
|
|
75
|
+
*/
|
|
76
|
+
export type AssignmentFieldRef<T = unknown> = {
|
|
77
|
+
eq(value: T): AssignmentLeaf;
|
|
78
|
+
ne(value: T): AssignmentLeaf;
|
|
79
|
+
in(values: ReadonlyArray<T>): AssignmentLeaf;
|
|
80
|
+
notIn(values: ReadonlyArray<T>): AssignmentLeaf;
|
|
81
|
+
contains(value: T extends ReadonlyArray<infer U> ? U : T): AssignmentLeaf;
|
|
82
|
+
doesNotContain(value: T extends ReadonlyArray<infer U> ? U : T): AssignmentLeaf;
|
|
83
|
+
} & (T extends number ? NumericComparators : Record<string, never>);
|
|
84
|
+
/** Comparator-bound accessor for the work item passed to `defaultPipelineAssignment`. */
|
|
85
|
+
export type WorkItemAssignmentAccessor = {
|
|
86
|
+
[K in WorkItemTopLevelField]: AssignmentFieldRef<WorkItemTopLevelFieldTypeMap[K]>;
|
|
87
|
+
} & {
|
|
88
|
+
/**
|
|
89
|
+
* Accessor for a platform-specific field (Jira custom field, GitHub label,
|
|
90
|
+
* etc.) stored in the work item's `fields` bag. Since `fields` keys and
|
|
91
|
+
* value shapes are platform- and project-dependent, there is no static
|
|
92
|
+
* schema to check either against by default.
|
|
93
|
+
*
|
|
94
|
+
* Two independent, optional type parameters:
|
|
95
|
+
* - `TName` constrains the `name` argument itself — pass a literal union
|
|
96
|
+
* of known field names (e.g. the `WorkItemFieldName` type
|
|
97
|
+
* `scarn pipelines pull` generates into `work-item-fields.ts`) to get
|
|
98
|
+
* compile-time validation and autocomplete on the field name.
|
|
99
|
+
* - `TValue` types the comparator (`.eq`/`.gte`/etc.) argument, exactly
|
|
100
|
+
* like the top-level accessors above — pass it for a known-shaped
|
|
101
|
+
* custom field (e.g. a numeric one).
|
|
102
|
+
* Both default to permissive types, so `workItem.field(name)` with no
|
|
103
|
+
* type arguments keeps working exactly as before.
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* workItem.field("issueType").eq("bug")
|
|
107
|
+
* workItem.field("labels").contains("regression")
|
|
108
|
+
* workItem.field<WorkItemFieldName>("issueType").eq("bug")
|
|
109
|
+
* workItem.field<WorkItemFieldName, number>("storyPoints").gte(3)
|
|
110
|
+
*/
|
|
111
|
+
field<TName extends string = string, TValue = unknown>(name: TName): AssignmentFieldRef<TValue>;
|
|
112
|
+
};
|
|
113
|
+
export type DefaultPipelineAssignmentCtx = {
|
|
114
|
+
/**
|
|
115
|
+
* Work-item accessor: top-level properties (`workItem.title`,
|
|
116
|
+
* `workItem.platform`, `workItem.url`, ...) plus `workItem.field(name)`
|
|
117
|
+
* for the platform-specific `fields` bag.
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* workItem.field("issueType").eq("bug").then(assign("bug-triage"))
|
|
121
|
+
* workItem.field("labels").contains("regression").then(assign("regression-review"))
|
|
122
|
+
* workItem.field("status").eq("resolved").then(skip())
|
|
123
|
+
* workItem.platform.eq("github").then(assign("github-triage"))
|
|
124
|
+
* workItem.title.contains("[urgent]").then(assign("urgent-triage"))
|
|
125
|
+
*/
|
|
126
|
+
workItem: WorkItemAssignmentAccessor;
|
|
127
|
+
/**
|
|
128
|
+
* Context facts for the current ingestion event.
|
|
129
|
+
* `context.isNew` is `true` when the work item is being created for the first time.
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* context.isNew.eq(true).then(assign("onboarding"))
|
|
133
|
+
*/
|
|
134
|
+
context: {
|
|
135
|
+
isNew: AssignmentFieldRef<boolean>;
|
|
136
|
+
};
|
|
137
|
+
/**
|
|
138
|
+
* Outcome: assign the work item to the given pipeline, by key or by the
|
|
139
|
+
* `definePipeline` value a pipeline file default-exports.
|
|
140
|
+
* Used in both `rules` (via `.then(assign(...))`) and `default`.
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* workItem.field("issueType").eq("bug").then(assign("bug-triage"))
|
|
144
|
+
*/
|
|
145
|
+
assign: (pipeline: AssignablePipeline) => AssignOutcome;
|
|
146
|
+
/**
|
|
147
|
+
* Outcome: do not assign any pipeline to this work item.
|
|
148
|
+
* Used in both `rules` (via `.then(skip())`) and `default`.
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* workItem.field("status").eq("resolved").then(skip())
|
|
152
|
+
*/
|
|
153
|
+
skip: () => SkipOutcome;
|
|
154
|
+
/**
|
|
155
|
+
* All nested conditions must match.
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* all(
|
|
159
|
+
* workItem.field("issueType").eq("bug"),
|
|
160
|
+
* workItem.field("priority").eq("high"),
|
|
161
|
+
* ).then(assign("bug-triage"))
|
|
162
|
+
*/
|
|
163
|
+
all: (...refs: AssignmentNestable[]) => AssignmentGroup;
|
|
164
|
+
/**
|
|
165
|
+
* Any nested condition must match.
|
|
166
|
+
*
|
|
167
|
+
* @example
|
|
168
|
+
* any(
|
|
169
|
+
* workItem.field("status").eq("resolved"),
|
|
170
|
+
* workItem.field("status").eq("closed"),
|
|
171
|
+
* ).then(skip())
|
|
172
|
+
*/
|
|
173
|
+
any: (...refs: AssignmentNestable[]) => AssignmentGroup;
|
|
174
|
+
};
|
|
175
|
+
export type DefaultPipelineAssignmentInput = {
|
|
176
|
+
/**
|
|
177
|
+
* The outcome when no rule matches. Use `assign(pipeline)` to assign a
|
|
178
|
+
* specific pipeline, or `skip()` to do nothing.
|
|
179
|
+
*/
|
|
180
|
+
default: DefaultPipelineAssignmentOutcome;
|
|
181
|
+
/**
|
|
182
|
+
* Ordered list of rules evaluated against each incoming work item.
|
|
183
|
+
* First match wins; unmatched work items fall through to `default`.
|
|
184
|
+
*/
|
|
185
|
+
rules: AssignmentRule[];
|
|
186
|
+
};
|
|
187
|
+
export type DefaultPipelineAssignmentSpec = {
|
|
188
|
+
readonly _tag: "default_pipeline_assignment";
|
|
189
|
+
readonly default: DefaultPipelineAssignmentOutcome;
|
|
190
|
+
readonly rules: AssignmentRule[];
|
|
191
|
+
};
|
|
192
|
+
/**
|
|
193
|
+
* Define a default pipeline assignment policy for this project.
|
|
194
|
+
*
|
|
195
|
+
* Pass a callback that receives a context object with `workItem`, `context`,
|
|
196
|
+
* `assign`, `skip`, `all`, and `any`. Return an object with `default` and
|
|
197
|
+
* `rules`.
|
|
198
|
+
*
|
|
199
|
+
* `default` is the outcome when no rule matches — either `assign(key)`
|
|
200
|
+
* or `skip()`.
|
|
201
|
+
*
|
|
202
|
+
* `rules` is an ordered list; the first matching rule wins.
|
|
203
|
+
*
|
|
204
|
+
* @example
|
|
205
|
+
* import { defaultPipelineAssignment } from "@scarn/sdk/definitions/pipelines";
|
|
206
|
+
*
|
|
207
|
+
* export default defaultPipelineAssignment(({ workItem, any, assign, skip }) => ({
|
|
208
|
+
* default: assign("bug-triage"),
|
|
209
|
+
* rules: [
|
|
210
|
+
* any(
|
|
211
|
+
* workItem.field("status").eq("resolved"),
|
|
212
|
+
* workItem.field("status").eq("manual support"),
|
|
213
|
+
* ).then(skip()),
|
|
214
|
+
* workItem.field("issueType").eq("bug").then(assign("bug-triage")),
|
|
215
|
+
* ],
|
|
216
|
+
* }));
|
|
217
|
+
*/
|
|
218
|
+
export declare function defaultPipelineAssignment(callback: (ctx: DefaultPipelineAssignmentCtx) => DefaultPipelineAssignmentInput): DefaultPipelineAssignmentSpec;
|
|
219
|
+
type SerializedLeafCondition = {
|
|
220
|
+
fact: string;
|
|
221
|
+
path?: string;
|
|
222
|
+
operator: string;
|
|
223
|
+
value: unknown;
|
|
224
|
+
};
|
|
225
|
+
type SerializedConditionGroup = {
|
|
226
|
+
all?: SerializedConditionNode[];
|
|
227
|
+
any?: SerializedConditionNode[];
|
|
228
|
+
};
|
|
229
|
+
type SerializedConditionNode = SerializedLeafCondition | SerializedConditionGroup;
|
|
230
|
+
type SerializedAssignmentRule = {
|
|
231
|
+
conditions: SerializedConditionGroup;
|
|
232
|
+
event: {
|
|
233
|
+
type: string;
|
|
234
|
+
params?: Record<string, unknown>;
|
|
235
|
+
};
|
|
236
|
+
};
|
|
237
|
+
export type SerializedDefaultPipelineAssignment = {
|
|
238
|
+
/**
|
|
239
|
+
* Pipeline key for the primary assign pipeline; resolved to a
|
|
240
|
+
* `pipelineDefinitionId` by the push layer. Null when `default`
|
|
241
|
+
* is `skip()` and no rule assigns a pipeline (push will reject this).
|
|
242
|
+
*/
|
|
243
|
+
pipelineDefinitionKey: string;
|
|
244
|
+
rulesJson: {
|
|
245
|
+
rules: SerializedAssignmentRule[];
|
|
246
|
+
};
|
|
247
|
+
defaultEventType: "assign" | "skip";
|
|
248
|
+
defaultEventParamsJson: Record<string, unknown> | null;
|
|
249
|
+
allowedEventTypes: Array<"assign" | "skip">;
|
|
250
|
+
};
|
|
251
|
+
/**
|
|
252
|
+
* Serialize a `DefaultPipelineAssignmentSpec` to the wire format.
|
|
253
|
+
*
|
|
254
|
+
* `pipelineDefinitionKey` is the key of the primary assign pipeline —
|
|
255
|
+
* taken from `default` if it's `assign(...)`, otherwise from the first rule
|
|
256
|
+
* that assigns a pipeline. The push layer rejects specs with no assign outcome.
|
|
257
|
+
*/
|
|
258
|
+
export declare function serializeDefaultPipelineAssignment(spec: DefaultPipelineAssignmentSpec): SerializedDefaultPipelineAssignment;
|
|
259
|
+
/**
|
|
260
|
+
* Type guard: returns true if `value` is a `DefaultPipelineAssignmentSpec`.
|
|
261
|
+
*/
|
|
262
|
+
export declare function isDefaultPipelineAssignmentSpec(value: unknown): value is DefaultPipelineAssignmentSpec;
|
|
263
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
DEFAULT_PIPELINE_ASSIGNMENT_FILENAME,
|
|
4
|
+
PipelineDefinitionsApiError,
|
|
5
|
+
WORK_ITEM_FIELDS_PATH_PREFIX,
|
|
6
|
+
WORK_ITEM_TOP_LEVEL_FIELDS,
|
|
7
|
+
createPipelineDefinitionsClient,
|
|
8
|
+
defaultPipelineAssignment,
|
|
9
|
+
isDefaultPipelineAssignmentSpec,
|
|
10
|
+
resolveWorkItemFieldPath,
|
|
11
|
+
serializeDefaultPipelineAssignment
|
|
12
|
+
} from "../../chunk-zm72ksz0.js";
|
|
13
|
+
import"../../chunk-vfeytkqx.js";
|
|
14
|
+
import"../../chunk-skzxcba3.js";
|
|
15
|
+
import"../../chunk-y64skrwp.js";
|
|
16
|
+
export {
|
|
17
|
+
DEFAULT_PIPELINE_ASSIGNMENT_FILENAME,
|
|
18
|
+
PipelineDefinitionsApiError,
|
|
19
|
+
WORK_ITEM_FIELDS_PATH_PREFIX,
|
|
20
|
+
WORK_ITEM_TOP_LEVEL_FIELDS,
|
|
21
|
+
createPipelineDefinitionsClient,
|
|
22
|
+
defaultPipelineAssignment,
|
|
23
|
+
isDefaultPipelineAssignmentSpec,
|
|
24
|
+
resolveWorkItemFieldPath,
|
|
25
|
+
serializeDefaultPipelineAssignment
|
|
26
|
+
};
|