@treeseed/sdk 0.6.1 → 0.6.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.
Files changed (33) hide show
  1. package/dist/operations/services/bootstrap-runner.d.ts +33 -0
  2. package/dist/operations/services/bootstrap-runner.js +136 -0
  3. package/dist/operations/services/config-runtime.d.ts +27 -8
  4. package/dist/operations/services/config-runtime.js +303 -127
  5. package/dist/operations/services/github-api.d.ts +34 -0
  6. package/dist/operations/services/github-api.js +187 -4
  7. package/dist/operations/services/github-automation.d.ts +30 -0
  8. package/dist/operations/services/github-automation.js +107 -1
  9. package/dist/operations/services/project-platform.d.ts +38 -2
  10. package/dist/operations/services/project-platform.js +319 -15
  11. package/dist/operations/services/railway-deploy.d.ts +6 -2
  12. package/dist/operations/services/railway-deploy.js +26 -18
  13. package/dist/operations/services/runtime-tools.d.ts +0 -2
  14. package/dist/operations/services/runtime-tools.js +0 -2
  15. package/dist/platform/env.yaml +71 -96
  16. package/dist/platform/environment.d.ts +4 -0
  17. package/dist/platform/environment.js +54 -0
  18. package/dist/reconcile/bootstrap-systems.d.ts +32 -0
  19. package/dist/reconcile/bootstrap-systems.js +175 -0
  20. package/dist/reconcile/builtin-adapters.js +1 -9
  21. package/dist/reconcile/desired-state.js +16 -14
  22. package/dist/reconcile/engine.d.ts +9 -4
  23. package/dist/reconcile/engine.js +57 -14
  24. package/dist/reconcile/index.d.ts +1 -0
  25. package/dist/reconcile/index.js +1 -0
  26. package/dist/scripts/config-treeseed.js +30 -0
  27. package/dist/scripts/package-tools.js +0 -2
  28. package/dist/scripts/tenant-deploy.js +16 -36
  29. package/dist/scripts/test-cloudflare-local.js +0 -2
  30. package/dist/workflow/operations.js +23 -4
  31. package/dist/workflow.d.ts +5 -0
  32. package/package.json +1 -1
  33. package/templates/github/deploy.workflow.yml +15 -15
@@ -0,0 +1,33 @@
1
+ export type TreeseedBootstrapExecution = 'parallel' | 'sequential';
2
+ export type TreeseedBootstrapStream = 'stdout' | 'stderr';
3
+ export type TreeseedBootstrapWriter = (line: string, stream?: TreeseedBootstrapStream) => void;
4
+ export type TreeseedBootstrapTaskPrefix = {
5
+ scope: string;
6
+ system: string;
7
+ task: string;
8
+ stage: string;
9
+ };
10
+ export type TreeseedBootstrapDagNode<TResult = unknown> = {
11
+ id: string;
12
+ dependencies?: string[];
13
+ run: () => Promise<TResult> | TResult;
14
+ };
15
+ export declare function formatTreeseedBootstrapPrefix(prefix: TreeseedBootstrapTaskPrefix): string;
16
+ export declare function formatTreeseedBootstrapLine(prefix: TreeseedBootstrapTaskPrefix, line: string): string;
17
+ export declare function writeTreeseedBootstrapLine(write: TreeseedBootstrapWriter | undefined, prefix: TreeseedBootstrapTaskPrefix, line: string, stream?: TreeseedBootstrapStream): void;
18
+ export declare function runTreeseedBootstrapDag<TResult = unknown>({ nodes, execution, }: {
19
+ nodes: Array<TreeseedBootstrapDagNode<TResult>>;
20
+ execution?: TreeseedBootstrapExecution;
21
+ }): Promise<Map<string, TResult>>;
22
+ export declare function sleep(milliseconds: number): Promise<void>;
23
+ export declare function runPrefixedCommand(command: string, args: string[], { cwd, env, input, write, prefix, }: {
24
+ cwd: string;
25
+ env?: NodeJS.ProcessEnv | Record<string, string | undefined>;
26
+ input?: string;
27
+ write?: TreeseedBootstrapWriter;
28
+ prefix: TreeseedBootstrapTaskPrefix;
29
+ }): Promise<{
30
+ status: number | null;
31
+ stdout: string;
32
+ stderr: string;
33
+ }>;
@@ -0,0 +1,136 @@
1
+ import { spawn } from "node:child_process";
2
+ function formatTreeseedBootstrapPrefix(prefix) {
3
+ return `[${prefix.scope}][${prefix.system}][${prefix.task}][${prefix.stage}]`;
4
+ }
5
+ function formatTreeseedBootstrapLine(prefix, line) {
6
+ return `${formatTreeseedBootstrapPrefix(prefix)} ${line}`;
7
+ }
8
+ function writeTreeseedBootstrapLine(write, prefix, line, stream = "stdout") {
9
+ const formatted = formatTreeseedBootstrapLine(prefix, line);
10
+ if (write) {
11
+ write(formatted, stream);
12
+ return;
13
+ }
14
+ (stream === "stderr" ? process.stderr : process.stdout).write(`${formatted}
15
+ `);
16
+ }
17
+ function dependencyLevels(nodes) {
18
+ const byId = new Map(nodes.map((node) => [node.id, node]));
19
+ const remaining = new Map(byId);
20
+ const completed = /* @__PURE__ */ new Set();
21
+ const levels = [];
22
+ for (const node of nodes) {
23
+ for (const dependency of node.dependencies ?? []) {
24
+ if (!byId.has(dependency)) {
25
+ throw new Error(`Bootstrap DAG node "${node.id}" depends on missing node "${dependency}".`);
26
+ }
27
+ }
28
+ }
29
+ while (remaining.size > 0) {
30
+ const ready = [...remaining.values()].filter(
31
+ (node) => (node.dependencies ?? []).every((dependency) => completed.has(dependency))
32
+ );
33
+ if (ready.length === 0) {
34
+ throw new Error("Bootstrap DAG contains a dependency cycle.");
35
+ }
36
+ for (const node of ready) {
37
+ remaining.delete(node.id);
38
+ completed.add(node.id);
39
+ }
40
+ levels.push(ready);
41
+ }
42
+ return levels;
43
+ }
44
+ async function runTreeseedBootstrapDag({
45
+ nodes,
46
+ execution = "parallel"
47
+ }) {
48
+ const results = /* @__PURE__ */ new Map();
49
+ for (const level of dependencyLevels(nodes)) {
50
+ if (execution === "sequential") {
51
+ for (const node of level) {
52
+ results.set(node.id, await Promise.resolve(node.run()));
53
+ }
54
+ continue;
55
+ }
56
+ await Promise.all(level.map(async (node) => {
57
+ results.set(node.id, await Promise.resolve(node.run()));
58
+ }));
59
+ }
60
+ return results;
61
+ }
62
+ async function sleep(milliseconds) {
63
+ if (!Number.isFinite(milliseconds) || milliseconds <= 0) {
64
+ return;
65
+ }
66
+ await new Promise((resolve) => setTimeout(resolve, milliseconds));
67
+ }
68
+ async function runPrefixedCommand(command, args, {
69
+ cwd,
70
+ env = process.env,
71
+ input,
72
+ write,
73
+ prefix
74
+ }) {
75
+ return await new Promise((resolvePromise, reject) => {
76
+ const child = spawn(command, args, {
77
+ cwd,
78
+ env: { ...process.env, ...env },
79
+ stdio: ["pipe", "pipe", "pipe"]
80
+ });
81
+ let stdout = "";
82
+ let stderr = "";
83
+ let stdoutBuffer = "";
84
+ let stderrBuffer = "";
85
+ const flush = (stream, force = false) => {
86
+ let buffer = stream === "stdout" ? stdoutBuffer : stderrBuffer;
87
+ let newlineIndex = buffer.search(/\r?\n/u);
88
+ while (newlineIndex >= 0) {
89
+ const line = buffer.slice(0, newlineIndex).replace(/\r$/u, "");
90
+ writeTreeseedBootstrapLine(write, prefix, line, stream);
91
+ buffer = buffer.slice(buffer[newlineIndex] === "\r" && buffer[newlineIndex + 1] === "\n" ? newlineIndex + 2 : newlineIndex + 1);
92
+ newlineIndex = buffer.search(/\r?\n/u);
93
+ }
94
+ if (force && buffer.length > 0) {
95
+ writeTreeseedBootstrapLine(write, prefix, buffer.replace(/\r$/u, ""), stream);
96
+ buffer = "";
97
+ }
98
+ if (stream === "stdout") {
99
+ stdoutBuffer = buffer;
100
+ } else {
101
+ stderrBuffer = buffer;
102
+ }
103
+ };
104
+ child.stdout.on("data", (chunk) => {
105
+ const text = String(chunk);
106
+ stdout += text;
107
+ stdoutBuffer += text;
108
+ flush("stdout");
109
+ });
110
+ child.stderr.on("data", (chunk) => {
111
+ const text = String(chunk);
112
+ stderr += text;
113
+ stderrBuffer += text;
114
+ flush("stderr");
115
+ });
116
+ child.on("error", reject);
117
+ child.on("close", (status) => {
118
+ flush("stdout", true);
119
+ flush("stderr", true);
120
+ resolvePromise({ status, stdout, stderr });
121
+ });
122
+ if (input !== void 0) {
123
+ child.stdin.end(input);
124
+ } else {
125
+ child.stdin.end();
126
+ }
127
+ });
128
+ }
129
+ export {
130
+ formatTreeseedBootstrapLine,
131
+ formatTreeseedBootstrapPrefix,
132
+ runPrefixedCommand,
133
+ runTreeseedBootstrapDag,
134
+ sleep,
135
+ writeTreeseedBootstrapLine
136
+ };
@@ -1,5 +1,6 @@
1
1
  import type { RemoteTreeseedConfig } from '../../remote.ts';
2
2
  import { TREESEED_ENVIRONMENT_SCOPES, type TreeseedEnvironmentValidation, validateTreeseedEnvironmentValues } from '../../platform/environment.ts';
3
+ import { resolveTreeseedBootstrapSelection, type TreeseedBootstrapSystem } from '../../reconcile/index.ts';
3
4
  import { type TreeseedKeyAgentStatus } from './key-agent.ts';
4
5
  export { TREESEED_MACHINE_KEY_PASSPHRASE_ENV, TreeseedKeyAgentError } from './key-agent.ts';
5
6
  export declare const DEFAULT_TREESEED_API_BASE_URL = "https://api.treeseed.ai";
@@ -312,14 +313,26 @@ export declare function checkTreeseedProviderConnections({ tenantRoot, scope, en
312
313
  issues: any[];
313
314
  }>;
314
315
  export declare function formatTreeseedProviderConnectionReport(report: any): string;
315
- export declare function syncTreeseedGitHubEnvironment({ tenantRoot, scope, dryRun }?: {
316
- scope?: string | undefined;
317
- dryRun?: boolean | undefined;
316
+ export declare function syncTreeseedGitHubEnvironment({ tenantRoot, scope, dryRun, repository: repositoryInput, execution, concurrency, onProgress, }: {
317
+ tenantRoot: string;
318
+ scope?: TreeseedConfigScope;
319
+ dryRun?: boolean;
320
+ repository?: string | null;
321
+ execution?: 'parallel' | 'sequential';
322
+ concurrency?: number;
323
+ onProgress?: (message: string, stream?: 'stdout' | 'stderr') => void;
318
324
  }): Promise<{
319
- secrets: never[];
320
- variables: never[];
325
+ secrets: Array<{
326
+ name: string;
327
+ existed: boolean;
328
+ }>;
329
+ variables: Array<{
330
+ name: string;
331
+ existed: boolean;
332
+ }>;
321
333
  repository: string;
322
- scope: string;
334
+ scope: "local" | "staging" | "prod";
335
+ environment: string;
323
336
  }>;
324
337
  export declare function syncTreeseedCloudflareEnvironment({ tenantRoot, scope, dryRun }?: {
325
338
  scope?: string | undefined;
@@ -404,14 +417,17 @@ export declare function applyTreeseedConfigValues({ tenantRoot, updates, applyLo
404
417
  }[];
405
418
  sharedStorageMigrations: TreeseedSharedStorageMigrationNotice[];
406
419
  };
407
- export declare function finalizeTreeseedConfig({ tenantRoot, scopes, sync, env, checkConnections, initializePersistent, onProgress, }: {
420
+ export declare function finalizeTreeseedConfig({ tenantRoot, scopes, sync, env, checkConnections, initializePersistent, systems, skipUnavailable, bootstrapExecution, onProgress, }: {
408
421
  tenantRoot: string;
409
422
  scopes?: TreeseedConfigScope[];
410
423
  sync?: 'none' | 'github' | 'cloudflare' | 'railway' | 'all';
411
424
  env?: NodeJS.ProcessEnv;
412
425
  checkConnections?: boolean;
413
426
  initializePersistent?: boolean;
414
- onProgress?: (message: string) => void;
427
+ systems?: TreeseedBootstrapSystem[] | TreeseedBootstrapSystem;
428
+ skipUnavailable?: boolean;
429
+ bootstrapExecution?: 'parallel' | 'sequential';
430
+ onProgress?: (message: string, stream?: 'stdout' | 'stderr') => void;
415
431
  }): Promise<{
416
432
  scopes: ("local" | "staging" | "prod")[];
417
433
  synced: Record<string, unknown>;
@@ -437,6 +453,8 @@ export declare function finalizeTreeseedConfig({ tenantRoot, scopes, sync, env,
437
453
  resourceInventoryByScope: Record<TreeseedConfigScope, Record<string, unknown>>;
438
454
  connectionChecks: ReturnType<typeof checkTreeseedProviderConnections>[];
439
455
  validationByScope: Record<TreeseedConfigScope, ReturnType<typeof validateTreeseedEnvironmentValues>>;
456
+ bootstrapSystemsByScope: Record<TreeseedConfigScope, ReturnType<typeof resolveTreeseedBootstrapSelection>>;
457
+ githubRepository: Record<string, unknown> | null;
440
458
  readinessByScope: Record<TreeseedConfigScope, {
441
459
  phase: string;
442
460
  configured: boolean;
@@ -446,6 +464,7 @@ export declare function finalizeTreeseedConfig({ tenantRoot, scopes, sync, env,
446
464
  warnings: string[];
447
465
  checks: Record<string, unknown>;
448
466
  }>;
467
+ bootstrapExecution: "parallel" | "sequential";
449
468
  }>;
450
469
  export declare function collectTreeseedPrintEnvReport({ tenantRoot, scope, env, revealSecrets, }: {
451
470
  tenantRoot: string;