@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.
Files changed (152) hide show
  1. package/dist/chunk-0y2fy5en.js +166 -0
  2. package/dist/chunk-3ctaaseb.js +1456 -0
  3. package/dist/chunk-4ggr8af6.js +30 -0
  4. package/dist/chunk-5zsavw98.js +91 -0
  5. package/dist/chunk-63f90zky.js +39 -0
  6. package/dist/chunk-700xe701.js +100 -0
  7. package/dist/chunk-ar6hcj1r.js +35 -0
  8. package/dist/chunk-cdanncng.js +74 -0
  9. package/dist/chunk-dp86pa6m.js +68 -0
  10. package/dist/chunk-e1h021kq.js +86 -0
  11. package/dist/chunk-gds7w7zh.js +330 -0
  12. package/dist/chunk-k4y5qt4y.js +14 -0
  13. package/dist/chunk-mz53r914.js +300 -0
  14. package/dist/chunk-ngy1fdcx.js +57 -0
  15. package/dist/chunk-p7yrcmqm.js +322 -0
  16. package/dist/chunk-rt9tq4j6.js +116 -0
  17. package/dist/chunk-skzxcba3.js +14282 -0
  18. package/dist/chunk-vfeytkqx.js +1687 -0
  19. package/dist/chunk-y2pv8d6a.js +162 -0
  20. package/dist/chunk-y64skrwp.js +17 -0
  21. package/dist/chunk-yjtaq94c.js +1094 -0
  22. package/dist/chunk-zm72ksz0.js +256 -0
  23. package/dist/client.d.ts +4 -0
  24. package/dist/client.js +58 -0
  25. package/dist/contracts/artifact-markers.d.ts +42 -0
  26. package/dist/contracts/artifact-markers.js +16 -0
  27. package/dist/contracts/artifacts.d.ts +67 -0
  28. package/dist/contracts/artifacts.js +27 -0
  29. package/dist/contracts/pipeline-document/built-ins.d.ts +23 -0
  30. package/dist/contracts/pipeline-document/conditions/operators.d.ts +8 -0
  31. package/dist/contracts/pipeline-document/index.d.ts +11 -0
  32. package/dist/contracts/pipeline-document/index.js +99 -0
  33. package/dist/contracts/pipeline-document/json.d.ts +35 -0
  34. package/dist/contracts/pipeline-document/routes.d.ts +16 -0
  35. package/dist/contracts/pipeline-document/schema.d.ts +780 -0
  36. package/dist/contracts/pipeline-document/step-contract.d.ts +11 -0
  37. package/dist/contracts/step-artifact-submissions.d.ts +71 -0
  38. package/dist/contracts/step-artifact-submissions.js +171 -0
  39. package/dist/defaults/atomic-json-file.d.ts +10 -0
  40. package/dist/defaults/auth-file.d.ts +14 -0
  41. package/dist/defaults/base-url.d.ts +1 -0
  42. package/dist/defaults/config-file.d.ts +46 -0
  43. package/dist/defaults/home-dir.d.ts +3 -0
  44. package/dist/defaults/index.d.ts +12 -0
  45. package/dist/defaults/index.js +1240 -0
  46. package/dist/defaults/legacy-config-migration.d.ts +27 -0
  47. package/dist/defaults/load-push-defaults.d.ts +25 -0
  48. package/dist/defaults/project-config.d.ts +32 -0
  49. package/dist/defaults/project-ref.d.ts +34 -0
  50. package/dist/definitions/artifacts/artifact.d.ts +62 -0
  51. package/dist/definitions/artifacts/index.d.ts +1 -0
  52. package/dist/definitions/pipelines/define-default-pipeline-assignment.d.ts +263 -0
  53. package/dist/definitions/pipelines/index.d.ts +3 -0
  54. package/dist/definitions/pipelines/index.js +26 -0
  55. package/dist/definitions/pipelines/pipeline-definitions-client.d.ts +208 -0
  56. package/dist/definitions/pipelines/work-item-fields.d.ts +93 -0
  57. package/dist/definitions/steps/compile-mcps.d.ts +34 -0
  58. package/dist/definitions/steps/define-code-step.d.ts +84 -0
  59. package/dist/definitions/steps/define-mcp.d.ts +79 -0
  60. package/dist/definitions/steps/define-step.d.ts +137 -0
  61. package/dist/definitions/steps/env.d.ts +136 -0
  62. package/dist/definitions/steps/index.d.ts +14 -0
  63. package/dist/definitions/steps/index.js +76 -0
  64. package/dist/definitions/steps/mcp-server-config.d.ts +102 -0
  65. package/dist/definitions/steps/prompt-template.d.ts +24 -0
  66. package/dist/definitions/steps/repo.d.ts +67 -0
  67. package/dist/definitions/steps/runtime.d.ts +115 -0
  68. package/dist/definitions/steps/step-definitions-client.d.ts +400 -0
  69. package/dist/definitions/steps/step-features.d.ts +109 -0
  70. package/dist/definitions/steps/step-handle.d.ts +25 -0
  71. package/dist/definitions/steps/step-ref.d.ts +19 -0
  72. package/dist/definitions/validation/index.d.ts +2 -0
  73. package/dist/definitions/validation/index.js +19 -0
  74. package/dist/definitions/validation/validate-artifact-markers.d.ts +3 -0
  75. package/dist/definitions/validation/validate-artifacts.d.ts +7 -0
  76. package/dist/definitions/validation/validate-definition-specs.d.ts +16 -0
  77. package/dist/definitions/validation/validate-env.d.ts +15 -0
  78. package/dist/definitions/validation/validate-repo.d.ts +13 -0
  79. package/dist/definitions/validation/validate-runtime.d.ts +12 -0
  80. package/dist/definitions/validation/validation-issue.d.ts +11 -0
  81. package/dist/devcontainer-config-path.d.ts +21 -0
  82. package/dist/devcontainer-config-path.js +15 -0
  83. package/dist/env-vars.d.ts +136 -0
  84. package/dist/env-vars.js +37 -0
  85. package/dist/eslint.d.ts +42 -0
  86. package/dist/eslint.js +127 -0
  87. package/dist/generated/client/client.gen.d.ts +2 -0
  88. package/dist/generated/client/index.d.ts +8 -0
  89. package/dist/generated/client/types.gen.d.ts +117 -0
  90. package/dist/generated/client/utils.gen.d.ts +33 -0
  91. package/dist/generated/client.gen.d.ts +12 -0
  92. package/dist/generated/core/auth.gen.d.ts +18 -0
  93. package/dist/generated/core/bodySerializer.gen.d.ts +25 -0
  94. package/dist/generated/core/params.gen.d.ts +43 -0
  95. package/dist/generated/core/pathSerializer.gen.d.ts +33 -0
  96. package/dist/generated/core/queryKeySerializer.gen.d.ts +18 -0
  97. package/dist/generated/core/serverSentEvents.gen.d.ts +71 -0
  98. package/dist/generated/core/types.gen.d.ts +78 -0
  99. package/dist/generated/core/utils.gen.d.ts +19 -0
  100. package/dist/generated/index.d.ts +2 -0
  101. package/dist/generated/sdk.gen.d.ts +302 -0
  102. package/dist/generated/types.gen.d.ts +18375 -0
  103. package/dist/git-url/git-remote.d.ts +30 -0
  104. package/dist/git-url/git-repo-identity.d.ts +44 -0
  105. package/dist/git-url/git-repo-identity.js +161 -0
  106. package/dist/git-url/parse-git-host.d.ts +23 -0
  107. package/dist/health-checks.d.ts +169 -0
  108. package/dist/health-checks.js +21 -0
  109. package/dist/index.d.ts +11 -0
  110. package/dist/index.js +296 -0
  111. package/dist/jsonc.d.ts +3 -0
  112. package/dist/jsonc.js +12 -0
  113. package/dist/managed-runtimes.d.ts +20 -0
  114. package/dist/managed-runtimes.js +15 -0
  115. package/dist/opencode-mcp.d.ts +313 -0
  116. package/dist/opencode-mcp.js +31 -0
  117. package/dist/pipelines/chain.d.ts +7 -0
  118. package/dist/pipelines/compile-args.d.ts +12 -0
  119. package/dist/pipelines/compile-chain.d.ts +9 -0
  120. package/dist/pipelines/compile-checks.d.ts +16 -0
  121. package/dist/pipelines/compile-state.d.ts +30 -0
  122. package/dist/pipelines/condition-data.d.ts +78 -0
  123. package/dist/pipelines/conditions.d.ts +47 -0
  124. package/dist/pipelines/context.d.ts +16 -0
  125. package/dist/pipelines/define-pipeline.d.ts +32 -0
  126. package/dist/pipelines/each.d.ts +5 -0
  127. package/dist/pipelines/errors.d.ts +26 -0
  128. package/dist/pipelines/handles.d.ts +29 -0
  129. package/dist/pipelines/index.d.ts +18 -0
  130. package/dist/pipelines/index.js +83 -0
  131. package/dist/pipelines/model.d.ts +103 -0
  132. package/dist/pipelines/nodes.d.ts +54 -0
  133. package/dist/pipelines/ref-types.d.ts +54 -0
  134. package/dist/pipelines/refs.d.ts +80 -0
  135. package/dist/pipelines/registry.d.ts +12 -0
  136. package/dist/pipelines/source.d.ts +17 -0
  137. package/dist/pipelines/types.d.ts +160 -0
  138. package/dist/push/code-step-lookup.d.ts +32 -0
  139. package/dist/push/code-step-lookup.js +12 -0
  140. package/dist/push/collect-definitions.d.ts +70 -0
  141. package/dist/push/collect-pipeline-documents.d.ts +14 -0
  142. package/dist/push/index.d.ts +6 -0
  143. package/dist/push/index.js +327 -0
  144. package/dist/push/push-from-directory.d.ts +37 -0
  145. package/dist/repo-config.d.ts +80 -0
  146. package/dist/repo-config.js +25 -0
  147. package/dist/scarn-config-parser.d.ts +29 -0
  148. package/dist/scarn-config-parser.js +10 -0
  149. package/dist/task-plane-client.d.ts +489 -0
  150. package/dist/z.d.ts +7 -0
  151. package/package.json +132 -4
  152. package/README.md +0 -3
@@ -0,0 +1,327 @@
1
+ // @bun
2
+ import {
3
+ assertValidDefinitionSpecs
4
+ } from "../chunk-gds7w7zh.js";
5
+ import {
6
+ isStepDefinitionSpec,
7
+ stepsInModule
8
+ } from "../chunk-ar6hcj1r.js";
9
+ import {
10
+ createStepDefinitionsClient,
11
+ toStepSpec
12
+ } from "../chunk-3ctaaseb.js";
13
+ import"../chunk-mz53r914.js";
14
+ import"../chunk-5zsavw98.js";
15
+ import"../chunk-4ggr8af6.js";
16
+ import"../chunk-k4y5qt4y.js";
17
+ import"../chunk-cdanncng.js";
18
+ import"../chunk-e1h021kq.js";
19
+ import"../chunk-63f90zky.js";
20
+ import"../chunk-ngy1fdcx.js";
21
+ import"../chunk-y2pv8d6a.js";
22
+ import"../chunk-dp86pa6m.js";
23
+ import {
24
+ DEFAULT_PIPELINE_ASSIGNMENT_FILENAME,
25
+ PipelineDefinitionsApiError,
26
+ createPipelineDefinitionsClient,
27
+ isDefaultPipelineAssignmentSpec,
28
+ serializeDefaultPipelineAssignment
29
+ } from "../chunk-zm72ksz0.js";
30
+ import {
31
+ Projects,
32
+ createClient
33
+ } from "../chunk-vfeytkqx.js";
34
+ import {
35
+ exports_external
36
+ } from "../chunk-skzxcba3.js";
37
+ import"../chunk-y64skrwp.js";
38
+
39
+ // src/push/collect-definitions.ts
40
+ import { existsSync, readdirSync } from "fs";
41
+ import { join, relative, resolve } from "path";
42
+ import { pathToFileURL } from "url";
43
+ var INTERNAL_SCRIPT_NAMES = new Set([
44
+ "push.ts",
45
+ "push.mjs",
46
+ "push.js",
47
+ ".scarn-studio-collect.mjs",
48
+ ".scarn-build.ts"
49
+ ]);
50
+ var PIPELINE_BUILDER_DIR = ".scarn/pipeline-builder";
51
+ function createCollectionState() {
52
+ return { stepMap: new Map, codeSteps: new Map };
53
+ }
54
+ function registerCodeStep(state, spec, sourceFile) {
55
+ const fn = spec.entrypoint?.fn;
56
+ if (spec.kind !== "code" || !fn)
57
+ return;
58
+ const existing = state.codeSteps.get(spec.key);
59
+ if (!existing) {
60
+ state.codeSteps.set(spec.key, { version: spec.version, fn, sourceFile });
61
+ return;
62
+ }
63
+ if (existing.version !== spec.version) {
64
+ throw new Error(`Code step "${spec.key}" is defined with different versions ` + `(v${String(existing.version)} in ${existing.sourceFile}, v${String(spec.version)} in ${sourceFile}). ` + `A code step is found by key alone, so give each code step a unique key.`);
65
+ }
66
+ if (existing.fn !== fn) {
67
+ throw new Error(`Code step "${spec.key}" is defined with different fn references ` + `(${existing.sourceFile} and ${sourceFile}). ` + `A code step is found by key alone, so give each code step a unique key.`);
68
+ }
69
+ }
70
+ function resolveCodeStepEntrypoint(spec, absoluteFilePath, absDir) {
71
+ if (spec.kind !== "code")
72
+ return toStepSpec(spec);
73
+ if (!spec.entrypoint?.fn) {
74
+ throw new Error(`Code step "${spec.key}" (kind: "code") has no entrypoint.fn. ` + `Build it with codeStep({ fn, ... }) from "@scarn/sdk/definitions/steps".`);
75
+ }
76
+ const resolved = toStepSpec(spec);
77
+ delete resolved.entrypoint;
78
+ resolved.entrypointJson = {
79
+ sourceFile: join(PIPELINE_BUILDER_DIR, relative(absDir, absoluteFilePath))
80
+ };
81
+ return resolved;
82
+ }
83
+ async function importModule(path) {
84
+ return await import(pathToFileURL(path).href);
85
+ }
86
+ function listSourceFiles(absDir) {
87
+ const allFiles = readdirSync(absDir).filter((file) => file.endsWith(".ts") || file.endsWith(".js"));
88
+ return allFiles.filter((file) => !INTERNAL_SCRIPT_NAMES.has(file) && file !== DEFAULT_PIPELINE_ASSIGNMENT_FILENAME);
89
+ }
90
+ function fileNameWithoutExtension(file) {
91
+ return file.replace(/\.(ts|js)$/, "");
92
+ }
93
+ async function collectFile(absoluteFilePath, absDir, state) {
94
+ const mod = await importModule(absoluteFilePath);
95
+ for (const step of stepsInModule(mod)) {
96
+ registerCodeStep(state, step, absoluteFilePath);
97
+ }
98
+ for (const [exportName, value] of Object.entries(mod)) {
99
+ if (exportName === "default" || !isStepDefinitionSpec(value))
100
+ continue;
101
+ const resolved = resolveCodeStepEntrypoint(value, absoluteFilePath, absDir);
102
+ state.stepMap.set(`${resolved.key}@v${String(resolved.version)}`, resolved);
103
+ }
104
+ }
105
+ async function collectDefinitionsFromDirectory(dir) {
106
+ const absDir = resolve(dir);
107
+ const sourceFiles = listSourceFiles(absDir);
108
+ const state = createCollectionState();
109
+ for (const file of sourceFiles) {
110
+ await collectFile(join(absDir, file), absDir, state);
111
+ }
112
+ return {
113
+ steps: [...state.stepMap.values()],
114
+ defaultPipelineAssignment: await collectDefaultPipelineAssignment(absDir)
115
+ };
116
+ }
117
+ async function collectDefinitionsFromDirectoryTolerant(dir) {
118
+ const absDir = resolve(dir);
119
+ const sourceFiles = listSourceFiles(absDir);
120
+ const state = createCollectionState();
121
+ const brokenPipelines = [];
122
+ for (const file of sourceFiles) {
123
+ try {
124
+ await collectFile(join(absDir, file), absDir, state);
125
+ } catch (error) {
126
+ brokenPipelines.push({
127
+ key: fileNameWithoutExtension(file),
128
+ message: error instanceof Error ? error.message : String(error)
129
+ });
130
+ }
131
+ }
132
+ let defaultPipelineAssignment = null;
133
+ try {
134
+ defaultPipelineAssignment = await collectDefaultPipelineAssignment(absDir);
135
+ } catch (error) {
136
+ brokenPipelines.push({
137
+ key: fileNameWithoutExtension(DEFAULT_PIPELINE_ASSIGNMENT_FILENAME),
138
+ message: error instanceof Error ? error.message : String(error)
139
+ });
140
+ }
141
+ return {
142
+ steps: [...state.stepMap.values()],
143
+ defaultPipelineAssignment,
144
+ brokenPipelines
145
+ };
146
+ }
147
+ async function collectDefaultPipelineAssignment(absDir) {
148
+ const path = join(absDir, DEFAULT_PIPELINE_ASSIGNMENT_FILENAME);
149
+ if (!existsSync(path))
150
+ return null;
151
+ const mod = await importModule(path);
152
+ const spec = mod["default"];
153
+ if (!isDefaultPipelineAssignmentSpec(spec)) {
154
+ throw new Error(`${DEFAULT_PIPELINE_ASSIGNMENT_FILENAME} must have a default export produced by defaultPipelineAssignment(({ assign, skip, ... }) => ({ default: ..., rules: [...] })). Got: ${typeof spec}`);
155
+ }
156
+ return spec;
157
+ }
158
+ // src/push/collect-pipeline-documents.ts
159
+ import { readdirSync as readdirSync2, readFileSync } from "fs";
160
+ import { join as join2, resolve as resolve2 } from "path";
161
+ var NON_PIPELINE_JSON = new Set([
162
+ "package.json",
163
+ "package-lock.json",
164
+ "tsconfig.json",
165
+ "jsconfig.json",
166
+ "deno.json"
167
+ ]);
168
+ var pipelineDocumentSchema = exports_external.looseObject({ nodes: exports_external.unknown() });
169
+ var documentHeaderSchema = exports_external.object({
170
+ key: exports_external.string().min(1),
171
+ title: exports_external.string().optional()
172
+ });
173
+ function collectPipelineDocuments(dir) {
174
+ const absDir = resolve2(dir);
175
+ const files = readdirSync2(absDir).filter((file) => file.endsWith(".json") && !NON_PIPELINE_JSON.has(file)).sort();
176
+ const byKey = new Map;
177
+ for (const file of files) {
178
+ const parsed = pipelineDocumentSchema.safeParse(parseJsonFile(join2(absDir, file), file));
179
+ if (!parsed.success)
180
+ continue;
181
+ const document = parsed.data;
182
+ const header = documentHeaderSchema.safeParse(document);
183
+ if (!header.success) {
184
+ throw new Error(`${file} has no "key": every pipeline document names the pipeline it publishes to.`);
185
+ }
186
+ const { key, title } = header.data;
187
+ const existing = byKey.get(key);
188
+ if (existing) {
189
+ throw new Error(`${existing.file} and ${file} are both pipeline "${key}". Delete the stale one and build again.`);
190
+ }
191
+ byKey.set(key, { file, key, title, document });
192
+ }
193
+ return [...byKey.values()];
194
+ }
195
+ function parseJsonFile(path, file) {
196
+ try {
197
+ return JSON.parse(readFileSync(path, "utf8"));
198
+ } catch (error) {
199
+ throw new Error(`${file} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
200
+ }
201
+ }
202
+ // src/push/push-from-directory.ts
203
+ async function pushFromDirectory(dir, opts) {
204
+ const log = opts.log ?? ((msg) => {
205
+ console.warn(msg);
206
+ });
207
+ const headers = { Authorization: `Bearer ${opts.accessToken}` };
208
+ const collected = await collectDefinitionsFromDirectory(dir);
209
+ const { steps } = collected;
210
+ const documents = collectPipelineDocuments(dir);
211
+ log(`Found ${String(steps.length)} step(s) and ${String(documents.length)} pipeline document(s).`);
212
+ assertValidDefinitionSpecs(steps);
213
+ const stepsClient = createStepDefinitionsClient(opts.baseUrl);
214
+ for (const spec of steps) {
215
+ await stepsClient.upsertFromSpec(opts.projectId, spec, { headers });
216
+ log(`\u2713 step ${spec.key} v${String(spec.version)} \u2192 upserted`);
217
+ }
218
+ const pipelinesClient = createPipelineDefinitionsClient(opts.baseUrl);
219
+ const publishedPipelines = [];
220
+ const unchangedPipelines = [];
221
+ if (documents.length > 0) {
222
+ const serverPipelines = await pipelinesClient.listByProjectId(opts.projectId, { headers });
223
+ const idByKey = new Map(serverPipelines.map((p) => [p.key, p.id]));
224
+ for (const document of documents) {
225
+ const published = await publishPipelineDocument(document, idByKey.get(document.key), opts.projectId, headers, pipelinesClient, log);
226
+ (published ? publishedPipelines : unchangedPipelines).push(document.key);
227
+ }
228
+ }
229
+ const syncedDefaultPipelineAssignment = collected.defaultPipelineAssignment ? await syncDefaultPipelineAssignment(collected.defaultPipelineAssignment, opts, headers, pipelinesClient, log) : false;
230
+ return {
231
+ pushedSteps: steps.length,
232
+ publishedPipelines,
233
+ unchangedPipelines,
234
+ syncedDefaultPipelineAssignment
235
+ };
236
+ }
237
+ async function publishPipelineDocument({ file, key, title, document }, pipelineDefinitionId, projectId, headers, pipelinesClient, log) {
238
+ try {
239
+ if (pipelineDefinitionId === undefined) {
240
+ await pipelinesClient.create({ projectId, key, name: title ?? key, document }, { headers });
241
+ log(`\u2713 pipeline ${key} \u2192 created and published (${file})`);
242
+ return true;
243
+ }
244
+ const result = await pipelinesClient.publishVersion(pipelineDefinitionId, document, { headers });
245
+ const version = String(result.version.version);
246
+ log(result.published ? `\u2713 pipeline ${key} v${version} \u2192 published (${file})` : `\u2713 pipeline ${key} v${version} \u2192 unchanged (${file})`);
247
+ return result.published;
248
+ } catch (error) {
249
+ if (error instanceof PipelineDefinitionsApiError) {
250
+ const issues = error.issues.map((issue) => issue.hint === undefined ? ` ${issue.path || "/"}: ${issue.message}` : ` ${issue.path || "/"}: ${issue.message}. ${issue.hint}`);
251
+ throw new Error([`Could not publish ${file}: ${error.message}`, ...issues].join(`
252
+ `), { cause: error });
253
+ }
254
+ throw error;
255
+ }
256
+ }
257
+ async function syncDefaultPipelineAssignment(spec, opts, headers, pipelinesClient, log) {
258
+ const serialized = serializeDefaultPipelineAssignment(spec);
259
+ const serverPipelines = await pipelinesClient.listByProjectId(opts.projectId, {
260
+ headers
261
+ });
262
+ const pipelineKeyToId = new Map(serverPipelines.map((p) => [p.key, p.id]));
263
+ const referencedKeys = new Set;
264
+ referencedKeys.add(serialized.pipelineDefinitionKey);
265
+ for (const rule of serialized.rulesJson.rules) {
266
+ if (rule.event.type === "assign" && typeof rule.event.params?.["pipelineKey"] === "string") {
267
+ referencedKeys.add(rule.event.params["pipelineKey"]);
268
+ }
269
+ }
270
+ for (const key of referencedKeys) {
271
+ if (!pipelineKeyToId.has(key)) {
272
+ throw new Error(`${DEFAULT_PIPELINE_ASSIGNMENT_FILENAME} references pipeline "${key}", ` + `but no pipeline with that key was found on the server. ` + `Run \`scarn pipelines build\` to write ${key}.json next to its source, then push again.`);
273
+ }
274
+ }
275
+ const pipelineDefinitionId = pipelineKeyToId.get(serialized.pipelineDefinitionKey);
276
+ if (!pipelineDefinitionId) {
277
+ throw new Error(`Pipeline key "${serialized.pipelineDefinitionKey}" was not found on the server.`);
278
+ }
279
+ const resolvedRules = serialized.rulesJson.rules.map((rule) => {
280
+ if (rule.event.type === "assign" && typeof rule.event.params?.["pipelineKey"] === "string") {
281
+ const pKey = rule.event.params["pipelineKey"];
282
+ const pId = pipelineKeyToId.get(pKey);
283
+ if (!pId) {
284
+ throw new Error(`${DEFAULT_PIPELINE_ASSIGNMENT_FILENAME} assign() references pipeline "${pKey}" ` + `which was not found on the server.`);
285
+ }
286
+ return {
287
+ ...rule,
288
+ event: {
289
+ ...rule.event,
290
+ params: {
291
+ ...rule.event.params,
292
+ pipelineDefinitionId: pId
293
+ }
294
+ }
295
+ };
296
+ }
297
+ return rule;
298
+ });
299
+ const projectsClient = new Projects({
300
+ client: createClient({ baseUrl: opts.baseUrl })
301
+ });
302
+ const result = await projectsClient.updateProjectDefaultPipelineAssignment({
303
+ path: { projectId: opts.projectId },
304
+ body: {
305
+ defaultPipelineAssignment: {
306
+ pipelineDefinitionId,
307
+ rulesJson: { rules: resolvedRules },
308
+ defaultEventType: serialized.defaultEventType,
309
+ defaultEventParamsJson: serialized.defaultEventParamsJson,
310
+ allowedEventTypes: serialized.allowedEventTypes
311
+ }
312
+ },
313
+ headers
314
+ });
315
+ if (result.error) {
316
+ throw new Error(`Failed to update project default pipeline assignment: ${JSON.stringify(result.error)}`);
317
+ }
318
+ log(`\u2713 default pipeline assignment \u2192 synced (primary pipeline: ${serialized.pipelineDefinitionKey})`);
319
+ return true;
320
+ }
321
+ export {
322
+ PIPELINE_BUILDER_DIR,
323
+ collectDefinitionsFromDirectory,
324
+ collectDefinitionsFromDirectoryTolerant,
325
+ collectPipelineDocuments,
326
+ pushFromDirectory
327
+ };
@@ -0,0 +1,37 @@
1
+ export interface PushFromDirectoryOptions {
2
+ baseUrl: string;
3
+ projectId: string;
4
+ accessToken: string;
5
+ /** Override the logger; defaults to console.log. */
6
+ log?: (message: string) => void;
7
+ }
8
+ export interface PushFromDirectoryResult {
9
+ pushedSteps: number;
10
+ /** Keys of the pipelines that got a new active version. */
11
+ publishedPipelines: string[];
12
+ /** Keys of the pipelines whose document matched their latest version. */
13
+ unchangedPipelines: string[];
14
+ /** true if the default pipeline assignment was synced to the server. */
15
+ syncedDefaultPipelineAssignment: boolean;
16
+ }
17
+ /**
18
+ * Pushes a pipeline-builder directory to the server, in three passes:
19
+ *
20
+ * 1. Upserts every step exported from the `.ts`/`.js` files (except the push
21
+ * script itself and `default-pipeline-assignment.ts`).
22
+ * 2. Publishes every built pipeline document (`<key>.json`, from
23
+ * `scarn pipelines build`), creating the pipeline when its key is new.
24
+ * The server pins each document to the steps just pushed; a document
25
+ * identical to its latest version publishes nothing.
26
+ * 3. Syncs `default-pipeline-assignment.ts`, when present, as the project
27
+ * default pipeline assignment. Every pipeline it assigns must exist by now.
28
+ *
29
+ * Collection (`collectDefinitionsFromDirectory`, `collectPipelineDocuments`)
30
+ * and step validation (`validateDefinitionSpecs`) are offline and run before
31
+ * the first mutating request, so an invalid batch fails without half-pushing.
32
+ *
33
+ * Designed to run on the user's native runtime (bun, node-with-tsx, deno),
34
+ * NOT inside a `bun --compile`'d binary — that runtime can't resolve scoped
35
+ * package `exports` field remappings from external user files.
36
+ */
37
+ export declare function pushFromDirectory(dir: string, opts: PushFromDirectoryOptions): Promise<PushFromDirectoryResult>;
@@ -0,0 +1,80 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Wire schema for a step's repository access (`repo`): what the worker does
4
+ * with the clone.
5
+ *
6
+ * - `none`: no repository. The worker does not clone, branch, commit or push.
7
+ * - `readOnly`: clones and checks out the base branch, but creates no work
8
+ * branch, commits nothing and pushes nothing.
9
+ * - `readWrite`: creates a work branch, commits and pushes. `message` is the
10
+ * commit message template (`{{input.…}}` and `{{result.…}}` tokens only) and
11
+ * `onPushFailure` picks whether a failed push fails the step.
12
+ *
13
+ * Two shapes of the same data. `RepoConfigInput` is what an author or API client
14
+ * sends and may leave things out; `RepoConfig` is what is stored, returned and
15
+ * handed to the worker, fully resolved by `resolveRepoConfig`. A resolved
16
+ * `RepoConfig` is also a valid `RepoConfigInput`, so a client can send back what
17
+ * it read (hence a `null` message is accepted on input).
18
+ *
19
+ * Which modes each runtime accepts is `REPO_RUNTIME_SUPPORT`; a new runtime adds
20
+ * a row there instead of changing the schema.
21
+ */
22
+ export declare const MAX_REPO_COMMIT_MESSAGE_LENGTH = 500;
23
+ export declare const REPO_COMMIT_MESSAGE_TOKEN_ROOTS: readonly string[];
24
+ export type RepoMode = "none" | "readOnly" | "readWrite";
25
+ export type RepoOnPushFailure = "fail" | "warn";
26
+ export type RepoExecutionMode = "workspace" | "no_workspace";
27
+ /**
28
+ * The root segment of every `{{…}}` token in `message` that is not one of
29
+ * `REPO_COMMIT_MESSAGE_TOKEN_ROOTS`, in order of appearance. Tokens are parsed
30
+ * the way `renderPromptTemplate` renders them.
31
+ */
32
+ export declare function findDisallowedCommitMessageTokenRoots(message: string): string[];
33
+ export declare const repoCommitMessageSchema: z.ZodString;
34
+ export declare const repoConfigInputSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
35
+ mode: z.ZodLiteral<"none">;
36
+ }, z.core.$strict>, z.ZodObject<{
37
+ mode: z.ZodLiteral<"readOnly">;
38
+ }, z.core.$strict>, z.ZodObject<{
39
+ mode: z.ZodLiteral<"readWrite">;
40
+ message: z.ZodOptional<z.ZodNullable<z.ZodString>>;
41
+ onPushFailure: z.ZodOptional<z.ZodEnum<{
42
+ warn: "warn";
43
+ fail: "fail";
44
+ }>>;
45
+ }, z.core.$strict>], "mode">;
46
+ export declare const repoConfigSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
47
+ mode: z.ZodLiteral<"none">;
48
+ }, z.core.$strict>, z.ZodObject<{
49
+ mode: z.ZodLiteral<"readOnly">;
50
+ }, z.core.$strict>, z.ZodObject<{
51
+ mode: z.ZodLiteral<"readWrite">;
52
+ message: z.ZodNullable<z.ZodString>;
53
+ onPushFailure: z.ZodEnum<{
54
+ warn: "warn";
55
+ fail: "fail";
56
+ }>;
57
+ }, z.core.$strict>], "mode">;
58
+ export type RepoConfigInput = z.input<typeof repoConfigInputSchema>;
59
+ export type RepoConfig = z.output<typeof repoConfigSchema>;
60
+ type RepoRuntimeSupport = {
61
+ readonly modes: readonly RepoMode[];
62
+ readonly default: RepoMode;
63
+ /** Why the modes outside `modes` are rejected. */
64
+ readonly unsupportedBecause: string;
65
+ };
66
+ /** Which `repo` modes each execution mode accepts, and its default. */
67
+ export declare const REPO_RUNTIME_SUPPORT: Record<RepoExecutionMode, RepoRuntimeSupport>;
68
+ /**
69
+ * Why `mode` cannot be used with `executionMode`, or `null` when the pair is
70
+ * valid.
71
+ */
72
+ export declare function repoRuntimeMismatch(executionMode: RepoExecutionMode, mode: RepoMode): string | null;
73
+ /**
74
+ * Fills what an author left out: an omitted `repo` becomes the runtime's default
75
+ * (`readWrite` for `workspace`, `none` for `no_workspace`), an omitted
76
+ * `onPushFailure` becomes `"fail"` and an omitted `message` becomes `null`.
77
+ * Does not check the runtime pairing; that is the caller's invariant.
78
+ */
79
+ export declare function resolveRepoConfig(executionMode: RepoExecutionMode, input?: RepoConfigInput | null): RepoConfig;
80
+ export {};
@@ -0,0 +1,25 @@
1
+ // @bun
2
+ import {
3
+ MAX_REPO_COMMIT_MESSAGE_LENGTH,
4
+ REPO_COMMIT_MESSAGE_TOKEN_ROOTS,
5
+ REPO_RUNTIME_SUPPORT,
6
+ findDisallowedCommitMessageTokenRoots,
7
+ repoCommitMessageSchema,
8
+ repoConfigInputSchema,
9
+ repoConfigSchema,
10
+ repoRuntimeMismatch,
11
+ resolveRepoConfig
12
+ } from "./chunk-cdanncng.js";
13
+ import"./chunk-skzxcba3.js";
14
+ import"./chunk-y64skrwp.js";
15
+ export {
16
+ MAX_REPO_COMMIT_MESSAGE_LENGTH,
17
+ REPO_COMMIT_MESSAGE_TOKEN_ROOTS,
18
+ REPO_RUNTIME_SUPPORT,
19
+ findDisallowedCommitMessageTokenRoots,
20
+ repoCommitMessageSchema,
21
+ repoConfigInputSchema,
22
+ repoConfigSchema,
23
+ repoRuntimeMismatch,
24
+ resolveRepoConfig
25
+ };
@@ -0,0 +1,29 @@
1
+ export declare const SCARN_CONFIG_RELATIVE_PATH = ".scarn/scarn.jsonc";
2
+ export type ScarnCommandDefinition = {
3
+ name: string;
4
+ description: string;
5
+ run: string;
6
+ cwd: string | null;
7
+ };
8
+ export type ScarnServiceDefinition = {
9
+ name: string;
10
+ description: string;
11
+ run: string;
12
+ cwd: string | null;
13
+ dependsOn: string[];
14
+ expose: {
15
+ targetPort: number;
16
+ protocol: string;
17
+ };
18
+ };
19
+ export type ScarnConfig = {
20
+ commands: ScarnCommandDefinition[];
21
+ services: ScarnServiceDefinition[];
22
+ };
23
+ export type ParseScarnConfigResult = {
24
+ found: false;
25
+ } | {
26
+ found: true;
27
+ config: ScarnConfig;
28
+ };
29
+ export declare function parseScarnConfig(workspacePath: string): Promise<ParseScarnConfigResult>;
@@ -0,0 +1,10 @@
1
+ // @bun
2
+ import {
3
+ SCARN_CONFIG_RELATIVE_PATH,
4
+ parseScarnConfig
5
+ } from "./chunk-0y2fy5en.js";
6
+ import"./chunk-y64skrwp.js";
7
+ export {
8
+ SCARN_CONFIG_RELATIVE_PATH,
9
+ parseScarnConfig
10
+ };