@kici-dev/sdk 0.0.0 → 0.1.1

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.
Files changed (112) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +1 -6
  3. package/dist/api-types.d.ts +47 -0
  4. package/dist/api-types.js +15 -0
  5. package/dist/chunk-gOLHoazu.js +4 -0
  6. package/dist/context.d.ts +185 -0
  7. package/dist/context.js +2 -0
  8. package/dist/dynamic-group.d.ts +29 -0
  9. package/dist/dynamic-group.js +34 -0
  10. package/dist/errors.d.ts +9 -0
  11. package/dist/errors.js +17 -0
  12. package/dist/events/define-event.d.ts +32 -0
  13. package/dist/events/define-event.js +29 -0
  14. package/dist/events/event-payloads.d.ts +396 -0
  15. package/dist/events/event-payloads.js +21 -0
  16. package/dist/events/index.d.ts +6 -0
  17. package/dist/events/index.js +4 -0
  18. package/dist/events/types.d.ts +13 -0
  19. package/dist/events/types.js +2 -0
  20. package/dist/fixture.d.ts +50 -0
  21. package/dist/fixture.js +35 -0
  22. package/dist/hooks/index.d.ts +33 -0
  23. package/dist/hooks/index.js +94 -0
  24. package/dist/hooks/types.d.ts +35 -0
  25. package/dist/hooks/types.js +2 -0
  26. package/dist/idempotent.d.ts +71 -0
  27. package/dist/idempotent.js +77 -0
  28. package/dist/index.d.ts +40 -0
  29. package/dist/index.js +50 -0
  30. package/dist/job.d.ts +31 -0
  31. package/dist/job.js +46 -0
  32. package/dist/matrix/expand.d.ts +32 -0
  33. package/dist/matrix/expand.js +77 -0
  34. package/dist/matrix/index.d.ts +4 -0
  35. package/dist/matrix/index.js +4 -0
  36. package/dist/matrix/types.d.ts +60 -0
  37. package/dist/matrix/types.js +18 -0
  38. package/dist/outputs.d.ts +86 -0
  39. package/dist/outputs.js +180 -0
  40. package/dist/rules/evaluator.d.ts +24 -0
  41. package/dist/rules/evaluator.js +52 -0
  42. package/dist/rules/index.d.ts +6 -0
  43. package/dist/rules/index.js +5 -0
  44. package/dist/rules/rule.d.ts +34 -0
  45. package/dist/rules/rule.js +37 -0
  46. package/dist/rules/types.d.ts +42 -0
  47. package/dist/rules/types.js +2 -0
  48. package/dist/secrets.d.ts +192 -0
  49. package/dist/secrets.js +132 -0
  50. package/dist/step.d.ts +50 -0
  51. package/dist/step.js +78 -0
  52. package/dist/triggers/comment.d.ts +20 -0
  53. package/dist/triggers/comment.js +47 -0
  54. package/dist/triggers/create.d.ts +20 -0
  55. package/dist/triggers/create.js +32 -0
  56. package/dist/triggers/delete.d.ts +20 -0
  57. package/dist/triggers/delete.js +29 -0
  58. package/dist/triggers/dispatch.d.ts +17 -0
  59. package/dist/triggers/dispatch.js +27 -0
  60. package/dist/triggers/fork.d.ts +17 -0
  61. package/dist/triggers/fork.js +26 -0
  62. package/dist/triggers/generic-webhook.d.ts +32 -0
  63. package/dist/triggers/generic-webhook.js +45 -0
  64. package/dist/triggers/index.d.ts +28 -0
  65. package/dist/triggers/index.js +25 -0
  66. package/dist/triggers/job-complete.d.ts +23 -0
  67. package/dist/triggers/job-complete.js +33 -0
  68. package/dist/triggers/kici-event.d.ts +23 -0
  69. package/dist/triggers/kici-event.js +34 -0
  70. package/dist/triggers/lifecycle.d.ts +20 -0
  71. package/dist/triggers/lifecycle.js +29 -0
  72. package/dist/triggers/pr.d.ts +27 -0
  73. package/dist/triggers/pr.js +48 -0
  74. package/dist/triggers/push.d.ts +29 -0
  75. package/dist/triggers/push.js +48 -0
  76. package/dist/triggers/release.d.ts +17 -0
  77. package/dist/triggers/release.js +27 -0
  78. package/dist/triggers/review-comment.d.ts +17 -0
  79. package/dist/triggers/review-comment.js +27 -0
  80. package/dist/triggers/review.d.ts +17 -0
  81. package/dist/triggers/review.js +28 -0
  82. package/dist/triggers/schedule.d.ts +20 -0
  83. package/dist/triggers/schedule.js +29 -0
  84. package/dist/triggers/star.d.ts +17 -0
  85. package/dist/triggers/star.js +27 -0
  86. package/dist/triggers/status.d.ts +17 -0
  87. package/dist/triggers/status.js +28 -0
  88. package/dist/triggers/tag.d.ts +20 -0
  89. package/dist/triggers/tag.js +31 -0
  90. package/dist/triggers/types.d.ts +529 -0
  91. package/dist/triggers/types.js +36 -0
  92. package/dist/triggers/watch.d.ts +17 -0
  93. package/dist/triggers/watch.js +27 -0
  94. package/dist/triggers/webhook.d.ts +19 -0
  95. package/dist/triggers/webhook.js +29 -0
  96. package/dist/triggers/workflow-complete.d.ts +23 -0
  97. package/dist/triggers/workflow-complete.js +32 -0
  98. package/dist/triggers/workflow-run.d.ts +17 -0
  99. package/dist/triggers/workflow-run.js +29 -0
  100. package/dist/types.d.ts +483 -0
  101. package/dist/types.js +35 -0
  102. package/dist/validation/dag.d.ts +42 -0
  103. package/dist/validation/dag.js +70 -0
  104. package/dist/validation/index.d.ts +3 -0
  105. package/dist/validation/index.js +3 -0
  106. package/dist/wait-for.d.ts +109 -0
  107. package/dist/wait-for.js +144 -0
  108. package/dist/workflow.d.ts +3 -0
  109. package/dist/workflow.js +83 -0
  110. package/package.json +42 -5
  111. package/sbom.spdx.json +9150 -0
  112. package/index.js +0 -3
@@ -0,0 +1,70 @@
1
+ import "../chunk-gOLHoazu.js";
2
+ //#region src/validation/dag.ts
3
+ /**
4
+ * Validate a DAG for common issues: self-references, missing dependencies, and cycles.
5
+ *
6
+ * Validation order:
7
+ * 1. Check for self-references (node depends on itself)
8
+ * 2. Check for missing dependencies (depends on non-existent node)
9
+ * 3. Check for cycles using Kahn's algorithm
10
+ *
11
+ * @param nodes - Array of DAG nodes to validate
12
+ * @returns Validation result with error details or sorted order
13
+ */
14
+ function validateDag(nodes) {
15
+ if (nodes.length === 0) return {
16
+ valid: true,
17
+ sortedOrder: []
18
+ };
19
+ const nodeIds = new Set(nodes.map((n) => n.id));
20
+ for (const node of nodes) if (node.needs.includes(node.id)) return {
21
+ valid: false,
22
+ error: "self-reference",
23
+ nodeId: node.id
24
+ };
25
+ for (const node of nodes) for (const dep of node.needs) if (!nodeIds.has(dep)) return {
26
+ valid: false,
27
+ error: "missing-dependency",
28
+ nodeId: node.id,
29
+ missingDep: dep
30
+ };
31
+ const adjacencyList = /* @__PURE__ */ new Map();
32
+ const inDegree = /* @__PURE__ */ new Map();
33
+ for (const node of nodes) {
34
+ adjacencyList.set(node.id, []);
35
+ inDegree.set(node.id, 0);
36
+ }
37
+ for (const node of nodes) for (const dep of node.needs) {
38
+ adjacencyList.get(dep).push(node.id);
39
+ inDegree.set(node.id, (inDegree.get(node.id) ?? 0) + 1);
40
+ }
41
+ const queue = [];
42
+ for (const [id, degree] of inDegree) if (degree === 0) queue.push(id);
43
+ const sortedOrder = [];
44
+ while (queue.length > 0) {
45
+ const current = queue.shift();
46
+ sortedOrder.push(current);
47
+ for (const neighbor of adjacencyList.get(current) ?? []) {
48
+ const newDegree = (inDegree.get(neighbor) ?? 0) - 1;
49
+ inDegree.set(neighbor, newDegree);
50
+ if (newDegree === 0) queue.push(neighbor);
51
+ }
52
+ }
53
+ if (sortedOrder.length !== nodes.length) {
54
+ const cycleNodes = [];
55
+ for (const [id, degree] of inDegree) if (degree > 0) cycleNodes.push(id);
56
+ return {
57
+ valid: false,
58
+ error: "cycle",
59
+ nodesInCycle: cycleNodes
60
+ };
61
+ }
62
+ return {
63
+ valid: true,
64
+ sortedOrder
65
+ };
66
+ }
67
+ //#endregion
68
+ export { validateDag };
69
+
70
+ //# sourceMappingURL=dag.js.map
@@ -0,0 +1,3 @@
1
+ export { validateDag } from './dag.js';
2
+ export type { DagNode, DagValidationResult } from './dag.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,3 @@
1
+ import "../chunk-gOLHoazu.js";
2
+ import { validateDag } from "./dag.js";
3
+ export { validateDag };
@@ -0,0 +1,109 @@
1
+ /**
2
+ * SDK wait-for helpers for workflow authors.
3
+ *
4
+ * Workflows often need to pause until an external condition becomes
5
+ * true — a resource finishes provisioning, a file appears on disk, an
6
+ * HTTP endpoint returns a healthy response, an external job reaches a
7
+ * terminal state. The helpers in this file express that pattern with
8
+ * the same shape as `idempotent` / `idempotentStep`:
9
+ *
10
+ * - `check()` returns the resolved value when the condition is met, or
11
+ * `null` to keep polling.
12
+ * - Optional `onSuccess(value)` runs once after the wait succeeds; its
13
+ * return value becomes the step result.
14
+ * - Optional `onTimeout({ elapsedMs, attempts })` runs if the deadline
15
+ * is exceeded; its return value becomes the step result. If absent,
16
+ * the helper throws a typed `WaitForTimeoutError` so the step fails.
17
+ * - Errors thrown by `check()` are swallowed by default (matching the
18
+ * "poll-until-healthy" pattern). Opt out via `swallowErrors: false`.
19
+ *
20
+ * Cancellation: the helper has no `AbortSignal` plumbing. A `check()`
21
+ * that takes longer than `intervalMs` is not aborted mid-flight; the
22
+ * loop only inspects the deadline at the top of each iteration. The
23
+ * step's own `timeout` field is the hard kill.
24
+ *
25
+ * Two entry points:
26
+ *
27
+ * - `waitFor(options)` — generic helper callable from any step, hook,
28
+ * or bare async function. Resolves to the discriminated result.
29
+ * - `waitForStep(name, options)` — factory returning an SDK `Step`
30
+ * whose run function executes `waitFor(...)` and propagates status
31
+ * lines into `ctx.log.info`.
32
+ */
33
+ import type { Step } from './types.js';
34
+ export interface WaitForOptions<TValue, TSuccess = void, TTimeout = void> {
35
+ /** Optional name surfaced in status lines and the timeout error. */
36
+ name?: string;
37
+ /** Polled inspection. Return the resolved value when the condition
38
+ * is met, or `null` to keep polling. */
39
+ check: () => Promise<TValue | null>;
40
+ /** Time between successive `check()` invocations, in milliseconds.
41
+ * Defaults to 2000. */
42
+ intervalMs?: number;
43
+ /** Total time budget for the wait, in milliseconds. Defaults to
44
+ * 60000. The deadline is inspected at the top of each iteration. */
45
+ timeoutMs?: number;
46
+ /** Time to wait before the first `check()` invocation, in
47
+ * milliseconds. Defaults to 0. */
48
+ initialDelayMs?: number;
49
+ /** Optional success action. Runs once after `check()` returns a
50
+ * non-null value. Its return value is surfaced as `result` on the
51
+ * 'succeeded' outcome. */
52
+ onSuccess?: (value: TValue) => Promise<TSuccess>;
53
+ /** Optional timeout action. Runs when the deadline is exceeded. Its
54
+ * return value is surfaced as `result` on the 'timed-out' outcome.
55
+ * When omitted, the helper throws a `WaitForTimeoutError` instead. */
56
+ onTimeout?: (info: {
57
+ elapsedMs: number;
58
+ attempts: number;
59
+ }) => Promise<TTimeout>;
60
+ /** When `true` (default), errors thrown by `check()` are logged and
61
+ * swallowed so polling continues. When `false`, the first error
62
+ * propagates out of the helper. */
63
+ swallowErrors?: boolean;
64
+ /** Sink for status lines. Defaults to console.log. */
65
+ log?: (line: string) => void;
66
+ }
67
+ /**
68
+ * The discriminated result of a `waitFor` invocation. Narrow on
69
+ * `outcome` to read the correct branch.
70
+ */
71
+ export type WaitForResult<TValue, TSuccess = void, TTimeout = void> = {
72
+ outcome: 'succeeded';
73
+ value: TValue;
74
+ elapsedMs: number;
75
+ attempts: number;
76
+ result: TSuccess;
77
+ } | {
78
+ outcome: 'timed-out';
79
+ elapsedMs: number;
80
+ attempts: number;
81
+ result: TTimeout;
82
+ };
83
+ /**
84
+ * Thrown by `waitFor` when the deadline is exceeded and no
85
+ * `onTimeout` callback was supplied. The instance fields expose the
86
+ * wait stats so callers can branch on them in a catch block.
87
+ */
88
+ export declare class WaitForTimeoutError extends Error {
89
+ /** The step name supplied via `WaitForOptions.name` (or 'waitFor'). */
90
+ readonly stepName: string;
91
+ /** Wall-clock duration of the wait, in milliseconds. */
92
+ readonly elapsedMs: number;
93
+ /** Number of `check()` invocations that ran before the timeout. */
94
+ readonly attempts: number;
95
+ constructor(stepName: string, elapsedMs: number, attempts: number);
96
+ }
97
+ /**
98
+ * Generic wait-for helper for use inside any step, hook, or bare
99
+ * async function. Polls `check()` on a fixed interval until it returns
100
+ * a non-null value or the deadline is exceeded.
101
+ */
102
+ export declare function waitFor<TValue, TSuccess = void, TTimeout = void>(opts: WaitForOptions<TValue, TSuccess, TTimeout>): Promise<WaitForResult<TValue, TSuccess, TTimeout>>;
103
+ /**
104
+ * Factory returning an SDK Step whose run function executes
105
+ * `waitFor(...)`. Status lines are routed through `ctx.log.info`.
106
+ * The step's typed return value is the WaitForResult union.
107
+ */
108
+ export declare function waitForStep<TValue, TSuccess = void, TTimeout = void>(name: string, opts: Omit<WaitForOptions<TValue, TSuccess, TTimeout>, 'name' | 'log'>): Step<WaitForResult<TValue, TSuccess, TTimeout>>;
109
+ //# sourceMappingURL=wait-for.d.ts.map
@@ -0,0 +1,144 @@
1
+ import "./chunk-gOLHoazu.js";
2
+ import { step } from "./step.js";
3
+ //#region src/wait-for.ts
4
+ /**
5
+ * SDK wait-for helpers for workflow authors.
6
+ *
7
+ * Workflows often need to pause until an external condition becomes
8
+ * true — a resource finishes provisioning, a file appears on disk, an
9
+ * HTTP endpoint returns a healthy response, an external job reaches a
10
+ * terminal state. The helpers in this file express that pattern with
11
+ * the same shape as `idempotent` / `idempotentStep`:
12
+ *
13
+ * - `check()` returns the resolved value when the condition is met, or
14
+ * `null` to keep polling.
15
+ * - Optional `onSuccess(value)` runs once after the wait succeeds; its
16
+ * return value becomes the step result.
17
+ * - Optional `onTimeout({ elapsedMs, attempts })` runs if the deadline
18
+ * is exceeded; its return value becomes the step result. If absent,
19
+ * the helper throws a typed `WaitForTimeoutError` so the step fails.
20
+ * - Errors thrown by `check()` are swallowed by default (matching the
21
+ * "poll-until-healthy" pattern). Opt out via `swallowErrors: false`.
22
+ *
23
+ * Cancellation: the helper has no `AbortSignal` plumbing. A `check()`
24
+ * that takes longer than `intervalMs` is not aborted mid-flight; the
25
+ * loop only inspects the deadline at the top of each iteration. The
26
+ * step's own `timeout` field is the hard kill.
27
+ *
28
+ * Two entry points:
29
+ *
30
+ * - `waitFor(options)` — generic helper callable from any step, hook,
31
+ * or bare async function. Resolves to the discriminated result.
32
+ * - `waitForStep(name, options)` — factory returning an SDK `Step`
33
+ * whose run function executes `waitFor(...)` and propagates status
34
+ * lines into `ctx.log.info`.
35
+ */
36
+ /**
37
+ * Thrown by `waitFor` when the deadline is exceeded and no
38
+ * `onTimeout` callback was supplied. The instance fields expose the
39
+ * wait stats so callers can branch on them in a catch block.
40
+ */
41
+ var WaitForTimeoutError = class extends Error {
42
+ /** The step name supplied via `WaitForOptions.name` (or 'waitFor'). */
43
+ stepName;
44
+ /** Wall-clock duration of the wait, in milliseconds. */
45
+ elapsedMs;
46
+ /** Number of `check()` invocations that ran before the timeout. */
47
+ attempts;
48
+ constructor(stepName, elapsedMs, attempts) {
49
+ super(`${stepName}: timed out after ${elapsedMs}ms (attempts=${attempts})`);
50
+ this.name = "WaitForTimeoutError";
51
+ this.stepName = stepName;
52
+ this.elapsedMs = elapsedMs;
53
+ this.attempts = attempts;
54
+ }
55
+ };
56
+ const DEFAULT_NAME = "waitFor";
57
+ const DEFAULT_INTERVAL_MS = 2e3;
58
+ const DEFAULT_TIMEOUT_MS = 6e4;
59
+ function sleep(ms) {
60
+ return new Promise((resolve) => setTimeout(resolve, ms));
61
+ }
62
+ async function runCheckOnce(check, swallowErrors, log, name, attempt) {
63
+ try {
64
+ return { value: await check() };
65
+ } catch (err) {
66
+ if (!swallowErrors) throw err;
67
+ log(`! ${name} — attempt ${attempt} error swallowed: ${err instanceof Error ? err.message : String(err)}`);
68
+ return { value: null };
69
+ }
70
+ }
71
+ /**
72
+ * Generic wait-for helper for use inside any step, hook, or bare
73
+ * async function. Polls `check()` on a fixed interval until it returns
74
+ * a non-null value or the deadline is exceeded.
75
+ */
76
+ async function waitFor(opts) {
77
+ const name = opts.name ?? DEFAULT_NAME;
78
+ const intervalMs = opts.intervalMs ?? DEFAULT_INTERVAL_MS;
79
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
80
+ const initialDelayMs = opts.initialDelayMs ?? 0;
81
+ const swallowErrors = opts.swallowErrors ?? true;
82
+ const log = opts.log ?? ((line) => console.log(line));
83
+ log(`→ ${name} — waiting (timeout=${timeoutMs}ms, interval=${intervalMs}ms)`);
84
+ const startedAt = Date.now();
85
+ const deadline = startedAt + timeoutMs;
86
+ if (initialDelayMs > 0) await sleep(initialDelayMs);
87
+ let attempts = 0;
88
+ while (Date.now() < deadline) {
89
+ attempts += 1;
90
+ const { value } = await runCheckOnce(opts.check, swallowErrors, log, name, attempts);
91
+ if (value !== null) {
92
+ const elapsedMs = Date.now() - startedAt;
93
+ log(`✓ ${name} — succeeded after ${elapsedMs}ms (attempts=${attempts})`);
94
+ const result = opts.onSuccess ? await opts.onSuccess(value) : void 0;
95
+ return {
96
+ outcome: "succeeded",
97
+ value,
98
+ elapsedMs,
99
+ attempts,
100
+ result
101
+ };
102
+ }
103
+ const remaining = deadline - Date.now();
104
+ if (remaining <= 0) break;
105
+ await sleep(Math.min(intervalMs, remaining));
106
+ }
107
+ const elapsedMs = Date.now() - startedAt;
108
+ log(`✗ ${name} — timed out after ${elapsedMs}ms (attempts=${attempts})`);
109
+ if (opts.onTimeout) {
110
+ const result = await opts.onTimeout({
111
+ elapsedMs,
112
+ attempts
113
+ });
114
+ return {
115
+ outcome: "timed-out",
116
+ elapsedMs,
117
+ attempts,
118
+ result
119
+ };
120
+ }
121
+ throw new WaitForTimeoutError(name, elapsedMs, attempts);
122
+ }
123
+ /**
124
+ * Factory returning an SDK Step whose run function executes
125
+ * `waitFor(...)`. Status lines are routed through `ctx.log.info`.
126
+ * The step's typed return value is the WaitForResult union.
127
+ */
128
+ function waitForStep(name, opts) {
129
+ return step(name, { run: async (ctx) => waitFor({
130
+ name,
131
+ check: opts.check,
132
+ intervalMs: opts.intervalMs,
133
+ timeoutMs: opts.timeoutMs,
134
+ initialDelayMs: opts.initialDelayMs,
135
+ onSuccess: opts.onSuccess,
136
+ onTimeout: opts.onTimeout,
137
+ swallowErrors: opts.swallowErrors,
138
+ log: (line) => ctx.log.info(line)
139
+ }) });
140
+ }
141
+ //#endregion
142
+ export { WaitForTimeoutError, waitFor, waitForStep };
143
+
144
+ //# sourceMappingURL=wait-for.js.map
@@ -0,0 +1,3 @@
1
+ import type { Workflow, WorkflowOptions } from './types.js';
2
+ export declare function workflow(name: string, options: WorkflowOptions): Workflow;
3
+ //# sourceMappingURL=workflow.d.ts.map
@@ -0,0 +1,83 @@
1
+ import "./chunk-gOLHoazu.js";
2
+ //#region src/workflow.ts
3
+ /**
4
+ * Normalize triggers to array.
5
+ * Handles single trigger config or array of trigger configs.
6
+ */
7
+ function normalizeTriggers(on) {
8
+ if (!on) return void 0;
9
+ return Array.isArray(on) ? on : [on];
10
+ }
11
+ /**
12
+ * Create a workflow containing jobs.
13
+ *
14
+ * @example
15
+ * // Simple workflow
16
+ * export default workflow('ci', {
17
+ * jobs: [build, test, deploy],
18
+ * });
19
+ *
20
+ * @example
21
+ * // Workflow with triggers and rules
22
+ * export default workflow('ci', {
23
+ * on: [pr({ target: 'main' }), push({ branches: 'main' })],
24
+ * jobs: [build, test, deploy],
25
+ * rules: [rule('has src changes')],
26
+ * description: 'Main CI pipeline',
27
+ * });
28
+ */
29
+ /**
30
+ * Validates a `<environment>:<secret-name>` qualified secret reference.
31
+ * Both halves must be non-empty and free of additional colons.
32
+ */
33
+ function isQualifiedSecretRef(value) {
34
+ const idx = value.indexOf(":");
35
+ if (idx <= 0 || idx >= value.length - 1) return false;
36
+ const env = value.slice(0, idx);
37
+ const name = value.slice(idx + 1);
38
+ return env.length > 0 && name.length > 0 && !name.includes(":");
39
+ }
40
+ function workflow(name, options) {
41
+ if (options.registries) {
42
+ const seenScopes = /* @__PURE__ */ new Set();
43
+ let defaultCount = 0;
44
+ for (const [i, reg] of options.registries.entries()) {
45
+ try {
46
+ new URL(reg.url);
47
+ } catch {
48
+ throw new Error(`workflow('${name}'): registries[${i}].url is not a valid URL: ${reg.url}`);
49
+ }
50
+ if (!isQualifiedSecretRef(reg.tokenSecret)) throw new Error(`workflow('${name}'): registries[${i}].tokenSecret must use qualified <environment>:<secret-name> syntax (got: ${reg.tokenSecret})`);
51
+ if (reg.scope === void 0) defaultCount += 1;
52
+ else {
53
+ if (!/^@[a-z0-9][a-z0-9-]*$/i.test(reg.scope)) throw new Error(`workflow('${name}'): registries[${i}].scope must match @<package-scope> (got: ${reg.scope})`);
54
+ if (seenScopes.has(reg.scope)) throw new Error(`workflow('${name}'): registries declares scope ${reg.scope} more than once`);
55
+ seenScopes.add(reg.scope);
56
+ }
57
+ }
58
+ if (defaultCount > 1) throw new Error(`workflow('${name}'): at most one registries entry may omit \`scope\` (default registry); got ${defaultCount}`);
59
+ }
60
+ if (options.installEnv) {
61
+ for (const [i, ref] of options.installEnv.entries()) if (!isQualifiedSecretRef(ref)) throw new Error(`workflow('${name}'): installEnv[${i}] must use qualified <environment>:<secret-name> syntax (got: ${ref})`);
62
+ }
63
+ return {
64
+ _tag: "Workflow",
65
+ name,
66
+ jobs: options.jobs,
67
+ on: normalizeTriggers(options.on),
68
+ rules: options.rules,
69
+ description: options.description,
70
+ hashFiles: options.hashFiles,
71
+ registries: options.registries,
72
+ installEnv: options.installEnv,
73
+ onCancel: options.onCancel,
74
+ cleanup: options.cleanup,
75
+ onSuccess: options.onSuccess,
76
+ onFailure: options.onFailure,
77
+ concurrency: options.concurrency
78
+ };
79
+ }
80
+ //#endregion
81
+ export { workflow };
82
+
83
+ //# sourceMappingURL=workflow.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kici-dev/sdk",
3
- "version": "0.0.0",
3
+ "version": "0.1.1",
4
4
  "description": "TypeScript SDK for defining KiCI workflows. Import into `.kici/workflows/*.ts` to declare workflows, jobs, steps, triggers, rules, and matrix configurations.",
5
5
  "keywords": [
6
6
  "kici",
@@ -9,7 +9,9 @@
9
9
  "ci-cd",
10
10
  "typescript",
11
11
  "workflows",
12
- "devops"
12
+ "devops",
13
+ "sdk",
14
+ "dsl"
13
15
  ],
14
16
  "homepage": "https://kici.dev",
15
17
  "author": {
@@ -17,9 +19,44 @@
17
19
  "email": "hello@kici.dev"
18
20
  },
19
21
  "license": "Apache-2.0",
20
- "main": "index.js",
22
+ "engines": {
23
+ "node": ">=24"
24
+ },
25
+ "type": "module",
26
+ "files": [
27
+ "dist",
28
+ "!dist/**/*.map",
29
+ "sbom.spdx.json"
30
+ ],
21
31
  "publishConfig": {
22
- "access": "public",
23
- "registry": "https://registry.npmjs.org/"
32
+ "registry": "https://registry.npmjs.org/",
33
+ "access": "public"
34
+ },
35
+ "main": "dist/index.js",
36
+ "types": "dist/index.d.ts",
37
+ "exports": {
38
+ ".": {
39
+ "types": "./dist/index.d.ts",
40
+ "import": "./dist/index.js",
41
+ "default": "./dist/index.js"
42
+ }
43
+ },
44
+ "scripts": {
45
+ "build": "node ../../scripts/build-ts.mjs && tsc --emitDeclarationOnly",
46
+ "typecheck": "tsc --noEmit",
47
+ "test": "vitest run",
48
+ "test:watch": "vitest",
49
+ "prepublishOnly": "npx tsx ../../hack/generate-sbom.ts --package packages/sdk --name @kici-dev/sdk"
50
+ },
51
+ "dependencies": {
52
+ "@kici-dev/engine": "workspace:*",
53
+ "@kici-dev/shared": "workspace:*",
54
+ "fast-cartesian": "^9.0.1",
55
+ "micromatch": "^4.0.8",
56
+ "zod": "^4.3.6",
57
+ "zx": "^8.8.5"
58
+ },
59
+ "devDependencies": {
60
+ "@types/micromatch": "^4.0.10"
24
61
  }
25
62
  }