laymos 0.0.6 → 0.0.8

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 (84) hide show
  1. package/dist/architecture-analysis-schema/architecture-analysis-schema.d.ts +4 -0
  2. package/dist/architecture-analysis-schema/architecture-analysis-schema.d.ts.map +1 -1
  3. package/dist/architecture-analysis-schema/documentation-schema.d.ts +36 -0
  4. package/dist/architecture-analysis-schema/documentation-schema.d.ts.map +1 -0
  5. package/dist/architecture-analysis-schema/documentation-schema.js +19 -0
  6. package/dist/architecture-analysis-schema/index.d.ts +2 -0
  7. package/dist/architecture-analysis-schema/index.d.ts.map +1 -1
  8. package/dist/architecture-analysis-schema/index.js +1 -0
  9. package/dist/architecture-analysis-schema/project-config-schema.d.ts +9 -0
  10. package/dist/architecture-analysis-schema/project-config-schema.d.ts.map +1 -1
  11. package/dist/architecture-analysis-schema/project-config-schema.js +13 -0
  12. package/dist/change-set-schema/change-set-schema.d.ts +6 -0
  13. package/dist/change-set-schema/change-set-schema.d.ts.map +1 -1
  14. package/dist/change-set-schema/change-set-schema.js +8 -0
  15. package/dist/change-set-schema/index.d.ts +2 -2
  16. package/dist/change-set-schema/index.d.ts.map +1 -1
  17. package/dist/change-set-schema/index.js +1 -1
  18. package/dist/cli/lint/lint.d.ts.map +1 -1
  19. package/dist/cli/lint/lint.js +11 -1
  20. package/dist/cli/lint/stories/index.d.ts +2 -0
  21. package/dist/cli/lint/stories/index.d.ts.map +1 -0
  22. package/dist/cli/lint/stories/index.js +2 -0
  23. package/dist/cli/lint/stories/report.d.ts +4 -0
  24. package/dist/cli/lint/stories/report.d.ts.map +1 -0
  25. package/dist/cli/lint/stories/report.js +24 -0
  26. package/dist/domain/project-config/project-config.d.ts +4 -0
  27. package/dist/domain/project-config/project-config.d.ts.map +1 -1
  28. package/dist/domain/project-config/validation/paths.js +20 -4
  29. package/dist/index.d.ts +7 -3
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +7 -2
  32. package/dist/orchestrator/analyze-project/analyze-project.d.ts +4 -0
  33. package/dist/orchestrator/analyze-project/analyze-project.d.ts.map +1 -1
  34. package/dist/orchestrator/inspect/inspect.d.ts +6 -0
  35. package/dist/orchestrator/inspect/inspect.d.ts.map +1 -1
  36. package/dist/orchestrator/load-changes/index.d.ts +1 -1
  37. package/dist/orchestrator/load-changes/index.d.ts.map +1 -1
  38. package/dist/orchestrator/load-changes/index.js +1 -1
  39. package/dist/orchestrator/load-changes/load-changes.d.ts +2 -1
  40. package/dist/orchestrator/load-changes/load-changes.d.ts.map +1 -1
  41. package/dist/orchestrator/load-changes/load-changes.js +6 -0
  42. package/dist/orchestrator/load-documentation/errors.d.ts +18 -0
  43. package/dist/orchestrator/load-documentation/errors.d.ts.map +1 -0
  44. package/dist/orchestrator/load-documentation/errors.js +5 -0
  45. package/dist/orchestrator/load-documentation/index.d.ts +2 -0
  46. package/dist/orchestrator/load-documentation/index.d.ts.map +1 -0
  47. package/dist/orchestrator/load-documentation/index.js +1 -0
  48. package/dist/orchestrator/load-documentation/load-documentation.d.ts +23 -0
  49. package/dist/orchestrator/load-documentation/load-documentation.d.ts.map +1 -0
  50. package/dist/orchestrator/load-documentation/load-documentation.js +66 -0
  51. package/dist/orchestrator/load-project/load-project.d.ts +4 -0
  52. package/dist/orchestrator/load-project/load-project.d.ts.map +1 -1
  53. package/dist/orchestrator/load-source-files/errors.d.ts +10 -0
  54. package/dist/orchestrator/load-source-files/errors.d.ts.map +1 -0
  55. package/dist/orchestrator/load-source-files/errors.js +3 -0
  56. package/dist/orchestrator/load-source-files/index.d.ts +2 -0
  57. package/dist/orchestrator/load-source-files/index.d.ts.map +1 -0
  58. package/dist/orchestrator/load-source-files/index.js +1 -0
  59. package/dist/orchestrator/load-source-files/load-source-files.d.ts +16 -0
  60. package/dist/orchestrator/load-source-files/load-source-files.d.ts.map +1 -0
  61. package/dist/orchestrator/load-source-files/load-source-files.js +30 -0
  62. package/dist/orchestrator/run-stories/errors.d.ts +1 -1
  63. package/dist/orchestrator/run-stories/errors.d.ts.map +1 -1
  64. package/dist/orchestrator/run-stories/run-stories.d.ts.map +1 -1
  65. package/dist/orchestrator/run-stories/run-stories.js +128 -13
  66. package/dist/services/git/changed-paths.d.ts +2 -1
  67. package/dist/services/git/changed-paths.d.ts.map +1 -1
  68. package/dist/services/git/changed-paths.js +16 -1
  69. package/dist/services/git/git.d.ts +2 -1
  70. package/dist/services/git/git.d.ts.map +1 -1
  71. package/dist/services/git/git.js +5 -1
  72. package/dist/story/schema/index.d.ts +2 -2
  73. package/dist/story/schema/index.d.ts.map +1 -1
  74. package/dist/story/schema/index.js +1 -1
  75. package/dist/story/schema/story-report-schema.d.ts +0 -30
  76. package/dist/story/schema/story-report-schema.d.ts.map +1 -1
  77. package/dist/story/schema/story-tree-schema.d.ts +13 -0
  78. package/dist/story/schema/story-tree-schema.d.ts.map +1 -1
  79. package/dist/story/schema/story-tree-schema.js +14 -2
  80. package/dist/story/story.d.ts +12 -3
  81. package/dist/story/story.d.ts.map +1 -1
  82. package/dist/story/story.js +8 -4
  83. package/package.json +2 -2
  84. package/schema.json +31 -0
@@ -1 +1 @@
1
- {"version":3,"file":"inspect.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/inspect/inspect.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"inspect.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/inspect/inspect.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- export { loadChangeSet, loadFileDiff } from './load-changes.js';
1
+ export { loadBranches, loadChangeSet, loadFileDiff } from './load-changes.js';
2
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/load-changes/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/load-changes/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
@@ -1,2 +1,2 @@
1
1
  // Node consumers use this high-level capability to report what a Base ref changed.
2
- export { loadChangeSet, loadFileDiff } from './load-changes.js';
2
+ export { loadBranches, loadChangeSet, loadFileDiff } from './load-changes.js';
@@ -1,6 +1,7 @@
1
1
  import { Effect } from 'effect';
2
- import type { ChangeSet, FileDiff } from '../../change-set-schema/index.js';
2
+ import type { Branch, ChangeSet, FileDiff } from '../../change-set-schema/index.js';
3
3
  import { type GitError } from '../../services/git/index.js';
4
4
  export declare function loadChangeSet(configPath: string, baseRef?: string): Effect.Effect<ChangeSet, GitError>;
5
5
  export declare function loadFileDiff(configPath: string, path: string, baseRef?: string): Effect.Effect<FileDiff, GitError>;
6
+ export declare function loadBranches(configPath: string): Effect.Effect<readonly Branch[], GitError>;
6
7
  //# sourceMappingURL=load-changes.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"load-changes.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/load-changes/load-changes.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAC5E,OAAO,EAAgB,KAAK,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAE1E,wBAAgB,aAAa,CAC3B,UAAU,EAAE,MAAM,EAClB,OAAO,SAAS,GACf,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,CAKpC;AAED,wBAAgB,YAAY,CAC1B,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,OAAO,SAAS,GACf,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAKnC"}
1
+ {"version":3,"file":"load-changes.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/load-changes/load-changes.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,KAAK,EACV,MAAM,EACN,SAAS,EACT,QAAQ,EACT,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAgB,KAAK,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAE1E,wBAAgB,aAAa,CAC3B,UAAU,EAAE,MAAM,EAClB,OAAO,SAAS,GACf,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,CAKpC;AAED,wBAAgB,YAAY,CAC1B,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,OAAO,SAAS,GACf,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAKnC;AAED,wBAAgB,YAAY,CAC1B,UAAU,EAAE,MAAM,GACjB,MAAM,CAAC,MAAM,CAAC,SAAS,MAAM,EAAE,EAAE,QAAQ,CAAC,CAK5C"}
@@ -13,6 +13,12 @@ export function loadFileDiff(configPath, path, baseRef = 'HEAD') {
13
13
  return yield* git.fileDiff(projectDir(configPath), baseRef, path);
14
14
  }).pipe(Effect.provide(GitLive));
15
15
  }
16
+ export function loadBranches(configPath) {
17
+ return Effect.gen(function* () {
18
+ const git = yield* Git;
19
+ return yield* git.branches(projectDir(configPath));
20
+ }).pipe(Effect.provide(GitLive));
21
+ }
16
22
  function projectDir(configPath) {
17
23
  return dirname(resolve(configPath));
18
24
  }
@@ -0,0 +1,18 @@
1
+ import type { DocumentationScope } from '../../architecture-analysis-schema/index.js';
2
+ declare const DocumentationScopeNotFound_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
3
+ readonly _tag: "DocumentationScopeNotFound";
4
+ } & Readonly<A>;
5
+ export declare class DocumentationScopeNotFound extends DocumentationScopeNotFound_base<{
6
+ readonly scope: DocumentationScope;
7
+ }> {
8
+ }
9
+ declare const DocumentationReadError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
10
+ readonly _tag: "DocumentationReadError";
11
+ } & Readonly<A>;
12
+ export declare class DocumentationReadError extends DocumentationReadError_base<{
13
+ readonly path: string;
14
+ readonly cause: unknown;
15
+ }> {
16
+ }
17
+ export {};
18
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/load-documentation/errors.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,6CAA6C,CAAC;;;;AAEtF,qBAAa,0BAA2B,SAAQ,gCAE9C;IACA,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAC;CACpC,CAAC;CAAG;;;;AAEL,qBAAa,sBAAuB,SAAQ,4BAE1C;IACA,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB,CAAC;CAAG"}
@@ -0,0 +1,5 @@
1
+ import { Data } from 'effect';
2
+ export class DocumentationScopeNotFound extends Data.TaggedError('DocumentationScopeNotFound') {
3
+ }
4
+ export class DocumentationReadError extends Data.TaggedError('DocumentationReadError') {
5
+ }
@@ -0,0 +1,2 @@
1
+ export { loadDocumentation, DocumentationReadError, DocumentationScopeNotFound, } from './load-documentation.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/load-documentation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EACtB,0BAA0B,GAC3B,MAAM,yBAAyB,CAAC"}
@@ -0,0 +1 @@
1
+ export { loadDocumentation, DocumentationReadError, DocumentationScopeNotFound, } from './load-documentation.js';
@@ -0,0 +1,23 @@
1
+ import { Effect } from 'effect';
2
+ import type { DocumentationScope } from '../../architecture-analysis-schema/index.js';
3
+ import { DocumentationReadError, DocumentationScopeNotFound } from './errors.js';
4
+ export { DocumentationReadError, DocumentationScopeNotFound, } from './errors.js';
5
+ export declare function loadDocumentation(configPath: string, scope: DocumentationScope): Effect.Effect<{
6
+ scope: {
7
+ readonly kind: "module";
8
+ readonly modulePath: string;
9
+ } | {
10
+ readonly kind: "module-graph";
11
+ readonly layerId: string;
12
+ readonly graphId: string;
13
+ } | {
14
+ readonly kind: "layer";
15
+ readonly layerId: string;
16
+ } | {
17
+ readonly kind: "layer-graph";
18
+ readonly graphId: string;
19
+ };
20
+ path: string | undefined;
21
+ content: string | undefined;
22
+ }, import("../../services/config/errors.js").ConfigError | import("../../services/file-cruiser/errors.js").CruiseError | DocumentationReadError | DocumentationScopeNotFound, never>;
23
+ //# sourceMappingURL=load-documentation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-documentation.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/load-documentation/load-documentation.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAc,MAAM,QAAQ,CAAC;AAE5C,OAAO,KAAK,EAIV,kBAAkB,EACnB,MAAM,6CAA6C,CAAC;AAKrD,OAAO,EACL,sBAAsB,EACtB,0BAA0B,EAC3B,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,sBAAsB,EACtB,0BAA0B,GAC3B,MAAM,aAAa,CAAC;AAErB,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,kBAAkB;;;;;;;;;;;;;;;;;qLA0C1B"}
@@ -0,0 +1,66 @@
1
+ import { dirname, resolve } from 'node:path';
2
+ import { NodeServices } from '@effect/platform-node';
3
+ import { Effect, FileSystem } from 'effect';
4
+ import { analyzeArchitecture } from '../../domain/architecture-analysis/index.js';
5
+ import { ConfigServiceLive } from '../../services/config/index.js';
6
+ import { CruiserLive } from '../../services/file-cruiser/index.js';
7
+ import { loadProject } from '../load-project/index.js';
8
+ import { DocumentationReadError, DocumentationScopeNotFound, } from './errors.js';
9
+ export { DocumentationReadError, DocumentationScopeNotFound, } from './errors.js';
10
+ export function loadDocumentation(configPath, scope) {
11
+ const absoluteConfigPath = resolve(configPath);
12
+ const baseDir = dirname(absoluteConfigPath);
13
+ return Effect.gen(function* () {
14
+ const { config, fileGraph } = yield* loadProject(absoluteConfigPath);
15
+ const analysis = analyzeArchitecture(fileGraph, config);
16
+ const fileSystem = yield* FileSystem.FileSystem;
17
+ const declaredPath = yield* resolveDeclaredPath(config, scope, analysis);
18
+ if (declaredPath === undefined) {
19
+ return {
20
+ scope,
21
+ path: undefined,
22
+ content: undefined,
23
+ };
24
+ }
25
+ const content = yield* fileSystem
26
+ .readFileString(resolve(baseDir, declaredPath))
27
+ .pipe(Effect.catchIf((cause) => scope.kind === 'module' && cause.reason._tag === 'NotFound', () => Effect.succeed(undefined)), Effect.mapError((cause) => new DocumentationReadError({ path: declaredPath, cause })));
28
+ return {
29
+ scope,
30
+ path: content === undefined ? undefined : declaredPath,
31
+ content,
32
+ };
33
+ }).pipe(Effect.provide(ConfigServiceLive), Effect.provide(CruiserLive), Effect.provide(NodeServices.layer));
34
+ }
35
+ function resolveDeclaredPath(config, scope, analysis) {
36
+ switch (scope.kind) {
37
+ case 'module': {
38
+ const module = analysis.moduleAnalysis.modules.find(({ path }) => path === scope.modulePath);
39
+ if (module === undefined) {
40
+ return Effect.fail(new DocumentationScopeNotFound({ scope }));
41
+ }
42
+ return Effect.succeed(module.shape === 'directory' ? `${module.path}/README.md` : undefined);
43
+ }
44
+ case 'module-graph': {
45
+ const graph = config.layers[scope.layerId]?.moduleGraphs[scope.graphId];
46
+ if (graph === undefined) {
47
+ return Effect.fail(new DocumentationScopeNotFound({ scope }));
48
+ }
49
+ return Effect.succeed(graph.docsPath);
50
+ }
51
+ case 'layer': {
52
+ const layer = config.layers[scope.layerId];
53
+ if (layer === undefined) {
54
+ return Effect.fail(new DocumentationScopeNotFound({ scope }));
55
+ }
56
+ return Effect.succeed(layer.docsPath);
57
+ }
58
+ case 'layer-graph': {
59
+ const layerGraph = config.layerGraphs[scope.graphId];
60
+ if (layerGraph === undefined) {
61
+ return Effect.fail(new DocumentationScopeNotFound({ scope }));
62
+ }
63
+ return Effect.succeed(layerGraph.docsPath);
64
+ }
65
+ }
66
+ }
@@ -13,10 +13,12 @@ export declare function loadProject(configPath: string): Effect.Effect<{
13
13
  readonly sourceRoots: readonly string[];
14
14
  readonly ignoredPaths: readonly string[];
15
15
  readonly storiesPath?: string | undefined;
16
+ readonly storyTimeout?: string | undefined;
16
17
  readonly layers: {
17
18
  readonly [x: string]: {
18
19
  readonly paths: readonly string[];
19
20
  readonly description?: string | undefined;
21
+ readonly docsPath?: string | undefined;
20
22
  readonly modules: {
21
23
  readonly [x: string]: {
22
24
  readonly shared: boolean;
@@ -27,6 +29,7 @@ export declare function loadProject(configPath: string): Effect.Effect<{
27
29
  readonly [x: string]: {
28
30
  readonly description?: string | undefined;
29
31
  readonly path: string;
32
+ readonly docsPath?: string | undefined;
30
33
  readonly modules: {
31
34
  readonly [x: string]: {
32
35
  readonly shared: boolean;
@@ -43,6 +46,7 @@ export declare function loadProject(configPath: string): Effect.Effect<{
43
46
  readonly layerGraphs: {
44
47
  readonly [x: string]: {
45
48
  readonly description?: string | undefined;
49
+ readonly docsPath?: string | undefined;
46
50
  readonly rules: {
47
51
  readonly [x: string]: readonly string[];
48
52
  };
@@ -1 +1 @@
1
- {"version":3,"file":"load-project.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/load-project/load-project.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EACL,KAAK,MAAM,EAEZ,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC5E,OAAO,EAAE,OAAO,EAAE,MAAM,sCAAsC,CAAC;AAE/D,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;CAC/B;AAED,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uGA4B7C"}
1
+ {"version":3,"file":"load-project.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/load-project/load-project.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EACL,KAAK,MAAM,EAEZ,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC5E,OAAO,EAAE,OAAO,EAAE,MAAM,sCAAsC,CAAC;AAE/D,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;CAC/B;AAED,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uGA4B7C"}
@@ -0,0 +1,10 @@
1
+ declare const SourceFileReadError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
2
+ readonly _tag: "SourceFileReadError";
3
+ } & Readonly<A>;
4
+ export declare class SourceFileReadError extends SourceFileReadError_base<{
5
+ readonly filePath: string;
6
+ readonly cause: unknown;
7
+ }> {
8
+ }
9
+ export {};
10
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/load-source-files/errors.ts"],"names":[],"mappings":";;;AAEA,qBAAa,mBAAoB,SAAQ,yBAEvC;IACA,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB,CAAC;CAAG"}
@@ -0,0 +1,3 @@
1
+ import { Data } from 'effect';
2
+ export class SourceFileReadError extends Data.TaggedError('SourceFileReadError') {
3
+ }
@@ -0,0 +1,2 @@
1
+ export { loadSourceFiles, SourceFileReadError } from './load-source-files.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/load-source-files/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1 @@
1
+ export { loadSourceFiles, SourceFileReadError } from './load-source-files.js';
@@ -0,0 +1,16 @@
1
+ import { Effect } from 'effect';
2
+ import { SourceFileReadError } from './errors.js';
3
+ export { SourceFileReadError } from './errors.js';
4
+ /**
5
+ * Reads every analyzed file at or below one of the given project-relative
6
+ * path prefixes — a Configured Module's, Module Graph's, or Layer scope's
7
+ * own root. A prefix outside the analysis universe matches nothing, so a
8
+ * caller can never use this to read a file outside the Project.
9
+ */
10
+ export declare function loadSourceFiles(configPath: string, pathPrefixes: readonly string[]): Effect.Effect<{
11
+ files: {
12
+ readonly path: string;
13
+ readonly content: string;
14
+ }[];
15
+ }, import("../../services/config/errors.js").ConfigError | import("../../services/file-cruiser/errors.js").CruiseError | SourceFileReadError, never>;
16
+ //# sourceMappingURL=load-source-files.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-source-files.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/load-source-files/load-source-files.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAc,MAAM,QAAQ,CAAC;AAM5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,SAAS,MAAM,EAAE;;;;;qJA2BhC"}
@@ -0,0 +1,30 @@
1
+ import { dirname, resolve } from 'node:path';
2
+ import { NodeServices } from '@effect/platform-node';
3
+ import { Effect, FileSystem } from 'effect';
4
+ import { ConfigServiceLive } from '../../services/config/index.js';
5
+ import { CruiserLive } from '../../services/file-cruiser/index.js';
6
+ import { loadProject } from '../load-project/index.js';
7
+ import { SourceFileReadError } from './errors.js';
8
+ export { SourceFileReadError } from './errors.js';
9
+ /**
10
+ * Reads every analyzed file at or below one of the given project-relative
11
+ * path prefixes — a Configured Module's, Module Graph's, or Layer scope's
12
+ * own root. A prefix outside the analysis universe matches nothing, so a
13
+ * caller can never use this to read a file outside the Project.
14
+ */
15
+ export function loadSourceFiles(configPath, pathPrefixes) {
16
+ const absoluteConfigPath = resolve(configPath);
17
+ const baseDir = dirname(absoluteConfigPath);
18
+ return Effect.gen(function* () {
19
+ const { fileGraph } = yield* loadProject(absoluteConfigPath);
20
+ const paths = [...fileGraph.keys()]
21
+ .filter((path) => underAnyPrefix(path, pathPrefixes))
22
+ .sort((left, right) => left.localeCompare(right));
23
+ const fileSystem = yield* FileSystem.FileSystem;
24
+ const files = yield* Effect.forEach(paths, (path) => fileSystem.readFileString(resolve(baseDir, path)).pipe(Effect.map((content) => ({ path, content })), Effect.mapError((cause) => new SourceFileReadError({ filePath: path, cause }))));
25
+ return { files };
26
+ }).pipe(Effect.provide(ConfigServiceLive), Effect.provide(CruiserLive), Effect.provide(NodeServices.layer));
27
+ }
28
+ function underAnyPrefix(path, pathPrefixes) {
29
+ return pathPrefixes.some((prefix) => prefix === '.' || path === prefix || path.startsWith(`${prefix}/`));
30
+ }
@@ -2,7 +2,7 @@ declare const StoriesError_base: new <A extends Record<string, any> = {}>(args:
2
2
  readonly _tag: "StoriesError";
3
3
  } & Readonly<A>;
4
4
  export declare class StoriesError extends StoriesError_base<{
5
- readonly reason: 'no-stories-path' | 'load' | 'invalid-root' | 'duplicate-title' | 'duplicate-question' | 'snippet-extraction' | 'unknown-scope';
5
+ readonly reason: 'no-stories-path' | 'load' | 'invalid-root' | 'duplicate-title' | 'duplicate-question' | 'snippet-extraction' | 'unknown-scope' | 'invalid-timeout';
6
6
  readonly path: string;
7
7
  readonly cause: unknown;
8
8
  }> {
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/run-stories/errors.ts"],"names":[],"mappings":";;;AAEA,qBAAa,YAAa,SAAQ,kBAAiC;IACjE,QAAQ,CAAC,MAAM,EACX,iBAAiB,GACjB,MAAM,GACN,cAAc,GACd,iBAAiB,GACjB,oBAAoB,GACpB,oBAAoB,GACpB,eAAe,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB,CAAC;CAAG"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/run-stories/errors.ts"],"names":[],"mappings":";;;AAEA,qBAAa,YAAa,SAAQ,kBAAiC;IACjE,QAAQ,CAAC,MAAM,EACX,iBAAiB,GACjB,MAAM,GACN,cAAc,GACd,iBAAiB,GACjB,oBAAoB,GACpB,oBAAoB,GACpB,eAAe,GACf,iBAAiB,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB,CAAC;CAAG"}
@@ -1 +1 @@
1
- {"version":3,"file":"run-stories.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/run-stories/run-stories.ts"],"names":[],"mappings":"AAIA,OAAO,EAAS,MAAM,EAAQ,MAAM,EAAE,MAAM,QAAQ,CAAC;AAWrD,OAAO,KAAK,EAOV,WAAW,EAEX,SAAS,EAEV,MAAM,6BAA6B,CAAC;AAErC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAUlE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAO3C,wBAAgB,YAAY,CAC1B,UAAU,EAAE,MAAM,GACjB,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,WAAW,GAAG,YAAY,CAAC,CAEtD;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3C;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;CAC9C;AAID,wBAAgB,WAAW,CACzB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,WAAW,GAAG,YAAY,CAAC,CAYvD;AAED,wBAAgB,UAAU,CACxB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,WAAW,GAAG,YAAY,CAAC,CAIxD"}
1
+ {"version":3,"file":"run-stories.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/run-stories/run-stories.ts"],"names":[],"mappings":"AAIA,OAAO,EAGL,MAAM,EAKN,MAAM,EACP,MAAM,QAAQ,CAAC;AAWhB,OAAO,KAAK,EAQV,WAAW,EAEX,SAAS,EAEV,MAAM,6BAA6B,CAAC;AAErC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAUlE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAO3C,wBAAgB,YAAY,CAC1B,UAAU,EAAE,MAAM,GACjB,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,WAAW,GAAG,YAAY,CAAC,CAEtD;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3C;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;CAC9C;AAmBD,wBAAgB,WAAW,CACzB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,WAAW,GAAG,YAAY,CAAC,CAkBvD;AAED,wBAAgB,UAAU,CACxB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,WAAW,GAAG,YAAY,CAAC,CAIxD"}
@@ -1,7 +1,7 @@
1
1
  import { existsSync, readFileSync } from 'node:fs';
2
2
  import { dirname, join, relative, resolve, sep } from 'node:path';
3
3
  import { fileURLToPath } from 'node:url';
4
- import { Cause, Effect, Exit, Stream } from 'effect';
4
+ import { Cause, Duration, Effect, Exit, Logger, Option, References, Stream, } from 'effect';
5
5
  import { NodeServices } from '@effect/platform-node';
6
6
  import { tsImport } from 'tsx/esm/api';
7
7
  import { isStory, isStoryGroup, StoryContext, } from '../../story/index.js';
@@ -13,22 +13,34 @@ export function getStoryTree(configPath) {
13
13
  return Effect.map(loadRoot(configPath), ({ tree }) => tree);
14
14
  }
15
15
  const DEFAULT_CONCURRENCY = 16;
16
+ const DEFAULT_STORY_TIMEOUT = Duration.seconds(10);
17
+ // The config names a Duration as text; a Story carries a typed DurationInput.
18
+ function resolveTimeout(input, fallback, path) {
19
+ if (input === undefined)
20
+ return Effect.succeed(fallback);
21
+ return Option.match(Duration.fromInput(input), {
22
+ onNone: () => new StoriesError({ reason: 'invalid-timeout', path, cause: input }),
23
+ onSome: Effect.succeed,
24
+ });
25
+ }
16
26
  export function planStories(configPath, options) {
17
27
  return Effect.gen(function* () {
18
- const { stories } = yield* loadRoot(configPath);
28
+ const { stories, storyTimeout } = yield* loadRoot(configPath);
29
+ const timeout = yield* resolveTimeout(storyTimeout, DEFAULT_STORY_TIMEOUT, configPath);
19
30
  const planned = yield* scopeStories(stories, options?.scope);
20
31
  return {
21
32
  total: planned.length,
22
- reports: runEachStory(planned, options?.concurrency ?? DEFAULT_CONCURRENCY),
33
+ reports: yield* runEachStory(planned, options?.concurrency ?? DEFAULT_CONCURRENCY, timeout),
23
34
  };
24
35
  });
25
36
  }
26
37
  export function runStories(configPath, options) {
27
38
  return Stream.unwrap(Effect.map(planStories(configPath, options), ({ reports }) => reports));
28
39
  }
29
- function runEachStory(stories, concurrency) {
40
+ function runEachStory(stories, concurrency, timeout) {
41
+ return Effect.map(Effect.forEach(stories, (indexed) => Effect.map(resolveTimeout(indexed.story.timeout, timeout, indexed.id), (budget) => ({ indexed, budget }))), (planned) =>
30
42
  // Ordered concurrent mapping needs three slots; anything less runs one at a time.
31
- return Stream.fromArray(stories).pipe(Stream.mapEffect(runStory, concurrency >= 3 ? { concurrency } : undefined));
43
+ Stream.fromArray(planned).pipe(Stream.mapEffect(({ indexed, budget }) => runStory(indexed, budget), concurrency >= 3 ? { concurrency } : undefined)));
32
44
  }
33
45
  function scopeStories(stories, scope) {
34
46
  if (scope === undefined)
@@ -65,11 +77,18 @@ function loadRoot(configPath) {
65
77
  cause: null,
66
78
  });
67
79
  }
68
- return yield* indexGroup(root, [root.title], entryPoint, {
80
+ const options = {
69
81
  projectRoot: dirname(absoluteConfigPath),
70
82
  storiesRoot,
71
83
  supportCache: new Map(),
72
- });
84
+ groupDirectories: new Map(),
85
+ };
86
+ const indexed = yield* indexGroup(root, [root.title], entryPoint, options);
87
+ return {
88
+ ...indexed,
89
+ storyTimeout: config.storyTimeout,
90
+ tree: attachGroupPages(indexed.tree, indexed.directory, options.projectRoot, options.groupDirectories),
91
+ };
73
92
  }).pipe(Effect.provide(ConfigServiceLive), Effect.provide(NodeServices.layer));
74
93
  }
75
94
  function indexGroup(group, path, entryPoint, options) {
@@ -78,6 +97,7 @@ function indexGroup(group, path, entryPoint, options) {
78
97
  const groups = [];
79
98
  const leaves = [];
80
99
  const stories = [];
100
+ const directories = [];
81
101
  for (const child of group.children) {
82
102
  const id = [...path, child.title].join('/');
83
103
  if (isStory(child)) {
@@ -87,25 +107,102 @@ function indexGroup(group, path, entryPoint, options) {
87
107
  leaves.push({
88
108
  id,
89
109
  title: child.title,
110
+ description: child.description,
111
+ spine: child.spine,
112
+ page: resolveStoryPage(child, options.projectRoot),
90
113
  setup: snippets.setup,
91
114
  questions,
92
115
  source,
93
116
  support: resolveSupport(child, options),
94
117
  });
95
118
  stories.push({ id, story: child });
119
+ const directory = storyDirectory(child);
120
+ if (directory !== null)
121
+ directories.push(directory);
96
122
  }
97
123
  else {
98
124
  const indexed = yield* indexGroup(child, [...path, child.title], entryPoint, options);
99
125
  groups.push(indexed.tree);
126
+ options.groupDirectories.set(indexed.tree, indexed.directory);
100
127
  stories.push(...indexed.stories);
128
+ directories.push(...indexed.directories);
101
129
  }
102
130
  }
103
131
  return {
104
- tree: { title: group.title, groups, stories: leaves },
132
+ tree: {
133
+ title: group.title,
134
+ description: group.description,
135
+ page: null,
136
+ groups,
137
+ stories: leaves,
138
+ },
105
139
  stories,
140
+ directories,
141
+ directory: commonDirectory(directories),
106
142
  };
107
143
  });
108
144
  }
145
+ function storyDirectory(story) {
146
+ try {
147
+ return dirname(fileURLToPath(story.sourceUrl));
148
+ }
149
+ catch {
150
+ return null;
151
+ }
152
+ }
153
+ function readPage(filePath, projectRoot) {
154
+ if (!existsSync(filePath))
155
+ return null;
156
+ return {
157
+ path: relative(projectRoot, filePath),
158
+ content: readFileSync(filePath, 'utf8'),
159
+ };
160
+ }
161
+ function resolveStoryPage(story, projectRoot) {
162
+ let filePath;
163
+ try {
164
+ filePath = fileURLToPath(story.sourceUrl);
165
+ }
166
+ catch {
167
+ return null;
168
+ }
169
+ if (!filePath.endsWith('.ts'))
170
+ return null;
171
+ return readPage(`${filePath.slice(0, -3)}.md`, projectRoot);
172
+ }
173
+ // A Story Group owns the folder its descendant Stories share, and its page sits
174
+ // there under the group's own title. Two groups can span one folder — a Learn
175
+ // and a Reference trunk over the same Stories — so the title, not `index`, is
176
+ // what keeps their pages apart.
177
+ function groupPage(group, directory, projectRoot) {
178
+ if (directory === null)
179
+ return null;
180
+ return readPage(join(directory, `${slugifyQuestion(group.title)}.md`), projectRoot);
181
+ }
182
+ function attachGroupPages(group, directory, projectRoot, directoriesById) {
183
+ return {
184
+ ...group,
185
+ page: groupPage(group, directory, projectRoot),
186
+ groups: group.groups.map((child) => attachGroupPages(child, directoriesById.get(child) ?? null, projectRoot, directoriesById)),
187
+ };
188
+ }
189
+ function commonDirectory(directories) {
190
+ const [first, ...rest] = directories;
191
+ if (first === undefined)
192
+ return null;
193
+ let shared = first.split(sep);
194
+ for (const directory of rest) {
195
+ const segments = directory.split(sep);
196
+ let index = 0;
197
+ while (index < shared.length &&
198
+ index < segments.length &&
199
+ shared[index] === segments[index]) {
200
+ index += 1;
201
+ }
202
+ shared = shared.slice(0, index);
203
+ }
204
+ return shared.length === 0 ? null : shared.join(sep);
205
+ }
109
206
  function indexQuestions(story, source, snippets) {
110
207
  return Effect.gen(function* () {
111
208
  const seen = new Set();
@@ -199,12 +296,27 @@ function checkUniqueTitles(children, path, entryPoint) {
199
296
  }
200
297
  return Effect.void;
201
298
  }
202
- function runStory({ id, story }) {
299
+ function runStory({ id, story }, timeout) {
203
300
  return Effect.gen(function* () {
204
301
  const questions = [];
205
- for (const question of story.questions) {
206
- questions.push(yield* runQuestion(question));
207
- }
302
+ // One budget for the whole Story: a hanging proof becomes an errored
303
+ // verdict instead of wedging the run.
304
+ yield* Effect.gen(function* () {
305
+ for (const question of story.questions) {
306
+ questions.push(yield* runQuestion(question));
307
+ }
308
+ }).pipe(Effect.timeout(timeout), Effect.catchTag('TimeoutError', () => Effect.sync(() => {
309
+ const interrupted = story.questions[questions.length];
310
+ if (interrupted !== undefined) {
311
+ questions.push({
312
+ slug: slugifyQuestion(interrupted.question),
313
+ verdict: 'errored',
314
+ error: `Story timed out after ${Duration.format(timeout)}`,
315
+ assertions: [],
316
+ sections: [],
317
+ });
318
+ }
319
+ })));
208
320
  const verdict = questions.some(({ verdict }) => verdict === 'errored')
209
321
  ? 'errored'
210
322
  : questions.some(({ verdict }) => verdict === 'failed')
@@ -224,7 +336,10 @@ function runQuestion(question) {
224
336
  assert: (description, passed) => Effect.sync(() => {
225
337
  assertions.push({ description, passed });
226
338
  }),
227
- }), Effect.exit);
339
+ }),
340
+ // A proof must see the same logging whatever host runs it: a Story
341
+ // that captures its own logs cannot depend on the host's log level.
342
+ Effect.provideService(References.MinimumLogLevel, 'Info'), Effect.provide(Logger.layer([])), Effect.exit);
228
343
  const slug = slugifyQuestion(question.question);
229
344
  if (Exit.isFailure(exit)) {
230
345
  return {
@@ -1,4 +1,5 @@
1
- import type { ChangeSet, DiffHunk } from '../../change-set-schema/index.js';
1
+ import type { Branch, ChangeSet, DiffHunk } from '../../change-set-schema/index.js';
2
2
  export declare function readChangeSet(baseDir: string, baseRef: string): Promise<ChangeSet>;
3
3
  export declare function readFileDiff(baseDir: string, baseRef: string, path: string): Promise<readonly DiffHunk[]>;
4
+ export declare function listBranches(baseDir: string): Promise<Branch[]>;
4
5
  //# sourceMappingURL=changed-paths.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"changed-paths.d.ts","sourceRoot":"","sources":["../../../src/services/git/changed-paths.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,SAAS,EAET,QAAQ,EACT,MAAM,kCAAkC,CAAC;AAY1C,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,SAAS,CAAC,CA+BpB;AA8CD,wBAAsB,YAAY,CAChC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,SAAS,QAAQ,EAAE,CAAC,CAiB9B"}
1
+ {"version":3,"file":"changed-paths.d.ts","sourceRoot":"","sources":["../../../src/services/git/changed-paths.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,MAAM,EAEN,SAAS,EAET,QAAQ,EACT,MAAM,kCAAkC,CAAC;AAY1C,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,SAAS,CAAC,CA+BpB;AA8CD,wBAAsB,YAAY,CAChC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,SAAS,QAAQ,EAAE,CAAC,CAiB9B;AAYD,wBAAsB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAyBrE"}
@@ -1,5 +1,5 @@
1
1
  import { parsePatch } from './parse-patch.js';
2
- import { requireGit, splitNul } from './run-git.js';
2
+ import { requireGit, runGit, splitNul } from './run-git.js';
3
3
  const wholeFileContext = 1000000;
4
4
  export async function readChangeSet(baseDir, baseRef) {
5
5
  await requireGit(baseDir, ['rev-parse', '--show-toplevel'], 'not-a-repo');
@@ -71,6 +71,21 @@ async function resolveBase(baseDir, baseRef) {
71
71
  const mergeBase = await requireGit(baseDir, ['merge-base', baseRef, 'HEAD'], 'unknown-ref');
72
72
  return mergeBase.trim();
73
73
  }
74
+ export async function listBranches(baseDir) {
75
+ await requireGit(baseDir, ['rev-parse', '--show-toplevel'], 'not-a-repo');
76
+ const current = (await runGit(baseDir, ['symbolic-ref', '--short', 'HEAD'])).stdout.trim();
77
+ const local = splitLines(await requireGit(baseDir, ['for-each-ref', '--format=%(refname:short)', 'refs/heads'], 'command-failed')).map((name) => ({ name, remote: false, current: name === current }));
78
+ const remote = splitLines(await requireGit(baseDir, ['for-each-ref', '--format=%(refname:short)', 'refs/remotes'], 'command-failed'))
79
+ .filter((name) => !name.endsWith('/HEAD'))
80
+ .map((name) => ({ name, remote: true, current: false }));
81
+ return [...local, ...remote];
82
+ }
83
+ function splitLines(stdout) {
84
+ return stdout
85
+ .split('\n')
86
+ .map((line) => line.trim())
87
+ .filter((line) => line !== '');
88
+ }
74
89
  function trackedStatus(code) {
75
90
  switch (code.charAt(0)) {
76
91
  case 'A':
@@ -1,9 +1,10 @@
1
1
  import { Context, Effect, Layer } from 'effect';
2
- import type { ChangeSet, FileDiff } from '../../change-set-schema/index.js';
2
+ import type { Branch, ChangeSet, FileDiff } from '../../change-set-schema/index.js';
3
3
  import { GitError } from './errors.js';
4
4
  declare const Git_base: Context.ServiceClass<Git, "Git", {
5
5
  readonly changeSet: (baseDir: string, baseRef: string) => Effect.Effect<ChangeSet, GitError>;
6
6
  readonly fileDiff: (baseDir: string, baseRef: string, path: string) => Effect.Effect<FileDiff, GitError>;
7
+ readonly branches: (baseDir: string) => Effect.Effect<readonly Branch[], GitError>;
7
8
  }>;
8
9
  export declare class Git extends Git_base {
9
10
  }
@@ -1 +1 @@
1
- {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../../src/services/git/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAEhD,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAE5E,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;;wBAKf,CAClB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,KACZ,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC;uBACpB,CACjB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,KACT,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC;;AAX1C,qBAAa,GAAI,SAAQ,QAaf;CAAG;AAEb,eAAO,MAAM,OAAO,gCAclB,CAAC"}
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../../src/services/git/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAEhD,OAAO,KAAK,EACV,MAAM,EACN,SAAS,EACT,QAAQ,EACT,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;;wBAKf,CAClB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,KACZ,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC;uBACpB,CACjB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,KACT,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC;uBACnB,CACjB,OAAO,EAAE,MAAM,KACZ,MAAM,CAAC,MAAM,CAAC,SAAS,MAAM,EAAE,EAAE,QAAQ,CAAC;;AAdnD,qBAAa,GAAI,SAAQ,QAgBf;CAAG;AAEb,eAAO,MAAM,OAAO,gCAmBlB,CAAC"}