laymos 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/lint/lint.d.ts.map +1 -1
- package/dist/cli/lint/lint.js +11 -1
- package/dist/cli/lint/stories/index.d.ts +2 -0
- package/dist/cli/lint/stories/index.d.ts.map +1 -0
- package/dist/cli/lint/stories/index.js +2 -0
- package/dist/cli/lint/stories/report.d.ts +4 -0
- package/dist/cli/lint/stories/report.d.ts.map +1 -0
- package/dist/cli/lint/stories/report.js +24 -0
- package/dist/orchestrator/run-stories/run-stories.d.ts.map +1 -1
- package/dist/orchestrator/run-stories/run-stories.js +87 -3
- package/dist/story/schema/index.d.ts +2 -2
- package/dist/story/schema/index.d.ts.map +1 -1
- package/dist/story/schema/index.js +1 -1
- package/dist/story/schema/story-tree-schema.d.ts +13 -0
- package/dist/story/schema/story-tree-schema.d.ts.map +1 -1
- package/dist/story/schema/story-tree-schema.js +14 -2
- package/dist/story/story.d.ts +9 -2
- package/dist/story/story.d.ts.map +1 -1
- package/dist/story/story.js +8 -4
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../../../src/cli/lint/lint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,MAAM,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../../../src/cli/lint/lint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,MAAM,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAa9C,wBAAgB,eAAe,CAAC,CAAC,EAC/B,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,+QAW5C"}
|
package/dist/cli/lint/lint.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { Console, Effect } from 'effect';
|
|
2
2
|
import { Command } from 'effect/unstable/cli';
|
|
3
3
|
import { analyzeProject } from '../../orchestrator/analyze-project/index.js';
|
|
4
|
+
import { getStoryTree } from '../../orchestrator/run-stories/index.js';
|
|
4
5
|
import { makeLayersCommand } from './layers/index.js';
|
|
5
6
|
import { renderLayerReport } from './layers/report.js';
|
|
6
7
|
import { makeModulesCommand } from './modules/index.js';
|
|
7
8
|
import { renderModuleReport } from './modules/report.js';
|
|
9
|
+
import { countGroupsWithoutPage, renderStoriesReport, } from './stories/index.js';
|
|
8
10
|
export function makeLintCommand(configPath) {
|
|
9
11
|
return Command.make('lint', {}, () => configPath.pipe(Effect.flatMap(runLint))).pipe(Command.withDescription('Check every configured architectural rule.'), Command.withSubcommands([
|
|
10
12
|
makeLayersCommand(configPath),
|
|
@@ -16,11 +18,19 @@ function runLint(configPath) {
|
|
|
16
18
|
const result = yield* analyzeProject(configPath);
|
|
17
19
|
yield* Console.log(renderLayerReport(result.layerAnalysis));
|
|
18
20
|
yield* Console.log(renderModuleReport(result.moduleAnalysis));
|
|
21
|
+
const missingPages = yield* lintStories(configPath);
|
|
19
22
|
if (result.layerAnalysis.unassignedFiles.length > 0 ||
|
|
20
23
|
result.layerAnalysis.forbiddenImports.length > 0 ||
|
|
21
24
|
result.layerAnalysis.layersWithoutModules.length > 0 ||
|
|
22
|
-
result.moduleAnalysis.violations.length > 0
|
|
25
|
+
result.moduleAnalysis.violations.length > 0 ||
|
|
26
|
+
missingPages > 0) {
|
|
23
27
|
process.exitCode = 1;
|
|
24
28
|
}
|
|
25
29
|
});
|
|
26
30
|
}
|
|
31
|
+
// A project without a Stories path has no Story Groups to lint.
|
|
32
|
+
function lintStories(configPath) {
|
|
33
|
+
return getStoryTree(configPath).pipe(Effect.flatMap((tree) => Console.log(renderStoriesReport(tree)).pipe(Effect.as(countGroupsWithoutPage(tree)))), Effect.catchTag('StoriesError', (error) => error.reason === 'no-stories-path'
|
|
34
|
+
? Effect.succeed(0)
|
|
35
|
+
: Effect.die(error)));
|
|
36
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/cli/lint/stories/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../../../src/cli/lint/stories/report.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAkB,MAAM,gCAAgC,CAAC;AAEhF,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAY3D;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAE9D"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as colors from 'yoctocolors';
|
|
2
|
+
export function renderStoriesReport(tree) {
|
|
3
|
+
const missing = groupsWithoutPage(tree, []);
|
|
4
|
+
if (missing.length === 0) {
|
|
5
|
+
return colors.green('✓ Every Story Group has a page');
|
|
6
|
+
}
|
|
7
|
+
return [
|
|
8
|
+
colors.red('Story Groups without a page'),
|
|
9
|
+
'',
|
|
10
|
+
...missing.map((id) => ` ${colors.yellow('✕')} ${id}`),
|
|
11
|
+
'',
|
|
12
|
+
`${missing.length} ${missing.length === 1 ? 'group' : 'groups'}`,
|
|
13
|
+
].join('\n');
|
|
14
|
+
}
|
|
15
|
+
export function countGroupsWithoutPage(tree) {
|
|
16
|
+
return groupsWithoutPage(tree, []).length;
|
|
17
|
+
}
|
|
18
|
+
function groupsWithoutPage(group, path) {
|
|
19
|
+
const id = [...path, group.title];
|
|
20
|
+
return [
|
|
21
|
+
...(group.page === null ? [id.join('/')] : []),
|
|
22
|
+
...group.groups.flatMap((child) => groupsWithoutPage(child, id)),
|
|
23
|
+
];
|
|
24
|
+
}
|
|
@@ -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,
|
|
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,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;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"}
|
|
@@ -65,11 +65,17 @@ function loadRoot(configPath) {
|
|
|
65
65
|
cause: null,
|
|
66
66
|
});
|
|
67
67
|
}
|
|
68
|
-
|
|
68
|
+
const options = {
|
|
69
69
|
projectRoot: dirname(absoluteConfigPath),
|
|
70
70
|
storiesRoot,
|
|
71
71
|
supportCache: new Map(),
|
|
72
|
-
|
|
72
|
+
groupDirectories: new Map(),
|
|
73
|
+
};
|
|
74
|
+
const indexed = yield* indexGroup(root, [root.title], entryPoint, options);
|
|
75
|
+
return {
|
|
76
|
+
...indexed,
|
|
77
|
+
tree: attachGroupPages(indexed.tree, indexed.directory, options.projectRoot, options.groupDirectories),
|
|
78
|
+
};
|
|
73
79
|
}).pipe(Effect.provide(ConfigServiceLive), Effect.provide(NodeServices.layer));
|
|
74
80
|
}
|
|
75
81
|
function indexGroup(group, path, entryPoint, options) {
|
|
@@ -78,6 +84,7 @@ function indexGroup(group, path, entryPoint, options) {
|
|
|
78
84
|
const groups = [];
|
|
79
85
|
const leaves = [];
|
|
80
86
|
const stories = [];
|
|
87
|
+
const directories = [];
|
|
81
88
|
for (const child of group.children) {
|
|
82
89
|
const id = [...path, child.title].join('/');
|
|
83
90
|
if (isStory(child)) {
|
|
@@ -87,25 +94,102 @@ function indexGroup(group, path, entryPoint, options) {
|
|
|
87
94
|
leaves.push({
|
|
88
95
|
id,
|
|
89
96
|
title: child.title,
|
|
97
|
+
description: child.description,
|
|
98
|
+
spine: child.spine,
|
|
99
|
+
page: resolveStoryPage(child, options.projectRoot),
|
|
90
100
|
setup: snippets.setup,
|
|
91
101
|
questions,
|
|
92
102
|
source,
|
|
93
103
|
support: resolveSupport(child, options),
|
|
94
104
|
});
|
|
95
105
|
stories.push({ id, story: child });
|
|
106
|
+
const directory = storyDirectory(child);
|
|
107
|
+
if (directory !== null)
|
|
108
|
+
directories.push(directory);
|
|
96
109
|
}
|
|
97
110
|
else {
|
|
98
111
|
const indexed = yield* indexGroup(child, [...path, child.title], entryPoint, options);
|
|
99
112
|
groups.push(indexed.tree);
|
|
113
|
+
options.groupDirectories.set(indexed.tree, indexed.directory);
|
|
100
114
|
stories.push(...indexed.stories);
|
|
115
|
+
directories.push(...indexed.directories);
|
|
101
116
|
}
|
|
102
117
|
}
|
|
103
118
|
return {
|
|
104
|
-
tree: {
|
|
119
|
+
tree: {
|
|
120
|
+
title: group.title,
|
|
121
|
+
description: group.description,
|
|
122
|
+
page: null,
|
|
123
|
+
groups,
|
|
124
|
+
stories: leaves,
|
|
125
|
+
},
|
|
105
126
|
stories,
|
|
127
|
+
directories,
|
|
128
|
+
directory: commonDirectory(directories),
|
|
106
129
|
};
|
|
107
130
|
});
|
|
108
131
|
}
|
|
132
|
+
function storyDirectory(story) {
|
|
133
|
+
try {
|
|
134
|
+
return dirname(fileURLToPath(story.sourceUrl));
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
function readPage(filePath, projectRoot) {
|
|
141
|
+
if (!existsSync(filePath))
|
|
142
|
+
return null;
|
|
143
|
+
return {
|
|
144
|
+
path: relative(projectRoot, filePath),
|
|
145
|
+
content: readFileSync(filePath, 'utf8'),
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
function resolveStoryPage(story, projectRoot) {
|
|
149
|
+
let filePath;
|
|
150
|
+
try {
|
|
151
|
+
filePath = fileURLToPath(story.sourceUrl);
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
if (!filePath.endsWith('.ts'))
|
|
157
|
+
return null;
|
|
158
|
+
return readPage(`${filePath.slice(0, -3)}.md`, projectRoot);
|
|
159
|
+
}
|
|
160
|
+
// A Story Group owns the folder its descendant Stories share, and its page sits
|
|
161
|
+
// there under the group's own title. Two groups can span one folder — a Learn
|
|
162
|
+
// and a Reference trunk over the same Stories — so the title, not `index`, is
|
|
163
|
+
// what keeps their pages apart.
|
|
164
|
+
function groupPage(group, directory, projectRoot) {
|
|
165
|
+
if (directory === null)
|
|
166
|
+
return null;
|
|
167
|
+
return readPage(join(directory, `${slugifyQuestion(group.title)}.md`), projectRoot);
|
|
168
|
+
}
|
|
169
|
+
function attachGroupPages(group, directory, projectRoot, directoriesById) {
|
|
170
|
+
return {
|
|
171
|
+
...group,
|
|
172
|
+
page: groupPage(group, directory, projectRoot),
|
|
173
|
+
groups: group.groups.map((child) => attachGroupPages(child, directoriesById.get(child) ?? null, projectRoot, directoriesById)),
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
function commonDirectory(directories) {
|
|
177
|
+
const [first, ...rest] = directories;
|
|
178
|
+
if (first === undefined)
|
|
179
|
+
return null;
|
|
180
|
+
let shared = first.split(sep);
|
|
181
|
+
for (const directory of rest) {
|
|
182
|
+
const segments = directory.split(sep);
|
|
183
|
+
let index = 0;
|
|
184
|
+
while (index < shared.length &&
|
|
185
|
+
index < segments.length &&
|
|
186
|
+
shared[index] === segments[index]) {
|
|
187
|
+
index += 1;
|
|
188
|
+
}
|
|
189
|
+
shared = shared.slice(0, index);
|
|
190
|
+
}
|
|
191
|
+
return shared.length === 0 ? null : shared.join(sep);
|
|
192
|
+
}
|
|
109
193
|
function indexQuestions(story, source, snippets) {
|
|
110
194
|
return Effect.gen(function* () {
|
|
111
195
|
const seen = new Set();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { CapturedTraceSchema, QuestionReportSchema, QuestionSectionSchema, RecordedFlowSchema, StoryAssertionSchema, StoryReportSchema, StoryVerdictSchema, } from './story-report-schema.js';
|
|
2
2
|
export type { CapturedTrace, JsonValue, QuestionReport, QuestionSection, RecordedFlow, StoryAssertion, StoryReport, StoryVerdict, } from './story-report-schema.js';
|
|
3
3
|
export { slugifyQuestion } from './slug.js';
|
|
4
|
-
export { QuestionLeafSchema, StoryLeafSchema, StorySourceSchema, StoryTreeGroupSchema, StoryTreeSchema, } from './story-tree-schema.js';
|
|
5
|
-
export type { QuestionLeaf, StoryLeaf, StorySource, StoryTree, StoryTreeGroup, } from './story-tree-schema.js';
|
|
4
|
+
export { QuestionLeafSchema, StoryLeafSchema, StoryPageSchema, StorySourceSchema, StoryTreeGroupSchema, StoryTreeSchema, } from './story-tree-schema.js';
|
|
5
|
+
export type { QuestionLeaf, StoryLeaf, StoryPage, StorySource, StoryTree, StoryTreeGroup, } from './story-tree-schema.js';
|
|
6
6
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/story/schema/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,qBAAqB,EACrB,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,aAAa,EACb,SAAS,EACT,cAAc,EACd,eAAe,EACf,YAAY,EACZ,cAAc,EACd,WAAW,EACX,YAAY,GACb,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,oBAAoB,EACpB,eAAe,GAChB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EACV,YAAY,EACZ,SAAS,EACT,WAAW,EACX,SAAS,EACT,cAAc,GACf,MAAM,wBAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/story/schema/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,qBAAqB,EACrB,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,aAAa,EACb,SAAS,EACT,cAAc,EACd,eAAe,EACf,YAAY,EACZ,cAAc,EACd,WAAW,EACX,YAAY,GACb,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,oBAAoB,EACpB,eAAe,GAChB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EACV,YAAY,EACZ,SAAS,EACT,SAAS,EACT,WAAW,EACX,SAAS,EACT,cAAc,GACf,MAAM,wBAAwB,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// RPC transports and renderers use this browser-safe Story report contract.
|
|
2
2
|
export { CapturedTraceSchema, QuestionReportSchema, QuestionSectionSchema, RecordedFlowSchema, StoryAssertionSchema, StoryReportSchema, StoryVerdictSchema, } from './story-report-schema.js';
|
|
3
3
|
export { slugifyQuestion } from './slug.js';
|
|
4
|
-
export { QuestionLeafSchema, StoryLeafSchema, StorySourceSchema, StoryTreeGroupSchema, StoryTreeSchema, } from './story-tree-schema.js';
|
|
4
|
+
export { QuestionLeafSchema, StoryLeafSchema, StoryPageSchema, StorySourceSchema, StoryTreeGroupSchema, StoryTreeSchema, } from './story-tree-schema.js';
|
|
@@ -3,6 +3,10 @@ export declare const StorySourceSchema: Schema.Struct<{
|
|
|
3
3
|
readonly path: Schema.String;
|
|
4
4
|
readonly content: Schema.String;
|
|
5
5
|
}>;
|
|
6
|
+
export declare const StoryPageSchema: Schema.Struct<{
|
|
7
|
+
readonly path: Schema.String;
|
|
8
|
+
readonly content: Schema.String;
|
|
9
|
+
}>;
|
|
6
10
|
export declare const QuestionLeafSchema: Schema.Struct<{
|
|
7
11
|
readonly slug: Schema.String;
|
|
8
12
|
readonly question: Schema.String;
|
|
@@ -12,6 +16,12 @@ export declare const QuestionLeafSchema: Schema.Struct<{
|
|
|
12
16
|
export declare const StoryLeafSchema: Schema.Struct<{
|
|
13
17
|
readonly id: Schema.String;
|
|
14
18
|
readonly title: Schema.String;
|
|
19
|
+
readonly description: Schema.String;
|
|
20
|
+
readonly spine: Schema.Boolean;
|
|
21
|
+
readonly page: Schema.NullOr<Schema.Struct<{
|
|
22
|
+
readonly path: Schema.String;
|
|
23
|
+
readonly content: Schema.String;
|
|
24
|
+
}>>;
|
|
15
25
|
readonly setup: Schema.NullOr<Schema.String>;
|
|
16
26
|
readonly questions: Schema.$Array<Schema.Struct<{
|
|
17
27
|
readonly slug: Schema.String;
|
|
@@ -30,6 +40,8 @@ export declare const StoryLeafSchema: Schema.Struct<{
|
|
|
30
40
|
}>;
|
|
31
41
|
export interface StoryTreeGroup {
|
|
32
42
|
readonly title: string;
|
|
43
|
+
readonly description: string;
|
|
44
|
+
readonly page: typeof StoryPageSchema.Type | null;
|
|
33
45
|
readonly groups: readonly StoryTreeGroup[];
|
|
34
46
|
readonly stories: readonly (typeof StoryLeafSchema.Type)[];
|
|
35
47
|
}
|
|
@@ -38,5 +50,6 @@ export declare const StoryTreeSchema: Schema.Codec<StoryTreeGroup, StoryTreeGrou
|
|
|
38
50
|
export type QuestionLeaf = typeof QuestionLeafSchema.Type;
|
|
39
51
|
export type StoryLeaf = typeof StoryLeafSchema.Type;
|
|
40
52
|
export type StorySource = typeof StorySourceSchema.Type;
|
|
53
|
+
export type StoryPage = typeof StoryPageSchema.Type;
|
|
41
54
|
export type StoryTree = StoryTreeGroup;
|
|
42
55
|
//# sourceMappingURL=story-tree-schema.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"story-tree-schema.d.ts","sourceRoot":"","sources":["../../../src/story/schema/story-tree-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,eAAO,MAAM,iBAAiB;;;EAO5B,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;EAS7B,CAAC;AAEH,eAAO,MAAM,eAAe
|
|
1
|
+
{"version":3,"file":"story-tree-schema.d.ts","sourceRoot":"","sources":["../../../src/story/schema/story-tree-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,eAAO,MAAM,iBAAiB;;;EAO5B,CAAC;AAEH,eAAO,MAAM,eAAe;;;EAO1B,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;EAS7B,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;EAc1B,CAAC;AAEH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,OAAO,eAAe,CAAC,IAAI,GAAG,IAAI,CAAC;IAClD,QAAQ,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,CAAC;IAC3C,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC,OAAO,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;CAC5D;AAED,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,KAAK,CAAC,cAAc,CAYjB,CAAC;AAE9C,eAAO,MAAM,eAAe,4DAI1B,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,OAAO,kBAAkB,CAAC,IAAI,CAAC;AAC1D,MAAM,MAAM,SAAS,GAAG,OAAO,eAAe,CAAC,IAAI,CAAC;AACpD,MAAM,MAAM,WAAW,GAAG,OAAO,iBAAiB,CAAC,IAAI,CAAC;AACxD,MAAM,MAAM,SAAS,GAAG,OAAO,eAAe,CAAC,IAAI,CAAC;AACpD,MAAM,MAAM,SAAS,GAAG,cAAc,CAAC"}
|
|
@@ -6,6 +6,13 @@ export const StorySourceSchema = Schema.Struct({
|
|
|
6
6
|
title: 'Story Source',
|
|
7
7
|
description: 'The full text of a project file backing a Story: the file the Story was authored in, or the support file its proofs import.',
|
|
8
8
|
});
|
|
9
|
+
export const StoryPageSchema = Schema.Struct({
|
|
10
|
+
path: Schema.String,
|
|
11
|
+
content: Schema.String,
|
|
12
|
+
}).annotate({
|
|
13
|
+
title: 'Story Page',
|
|
14
|
+
description: "The markdown page narrating a Story or a Story Group: a Story's sibling `.md` file, or a Story Group's `index.md`. Null when the author wrote none.",
|
|
15
|
+
});
|
|
9
16
|
export const QuestionLeafSchema = Schema.Struct({
|
|
10
17
|
slug: Schema.String,
|
|
11
18
|
question: Schema.String,
|
|
@@ -18,21 +25,26 @@ export const QuestionLeafSchema = Schema.Struct({
|
|
|
18
25
|
export const StoryLeafSchema = Schema.Struct({
|
|
19
26
|
id: Schema.String,
|
|
20
27
|
title: Schema.String,
|
|
28
|
+
description: Schema.String,
|
|
29
|
+
spine: Schema.Boolean,
|
|
30
|
+
page: Schema.NullOr(StoryPageSchema),
|
|
21
31
|
setup: Schema.NullOr(Schema.String),
|
|
22
32
|
questions: Schema.Array(QuestionLeafSchema),
|
|
23
33
|
source: StorySourceSchema,
|
|
24
34
|
support: Schema.NullOr(StorySourceSchema),
|
|
25
35
|
}).annotate({
|
|
26
36
|
title: 'Story Leaf',
|
|
27
|
-
description: 'One Story in the Story tree: its derived id, the shared setup snippet, its Questions in authored order, and the support file its proofs import. Never carries results.',
|
|
37
|
+
description: 'One Story in the Story tree: its derived id, its one-line description, whether it sits on the spine, its markdown page, the shared setup snippet, its Questions in authored order, and the support file its proofs import. Never carries results.',
|
|
28
38
|
});
|
|
29
39
|
export const StoryTreeGroupSchema = Schema.Struct({
|
|
30
40
|
title: Schema.String,
|
|
41
|
+
description: Schema.String,
|
|
42
|
+
page: Schema.NullOr(StoryPageSchema),
|
|
31
43
|
groups: Schema.Array(Schema.suspend(() => StoryTreeGroupSchema)),
|
|
32
44
|
stories: Schema.Array(StoryLeafSchema),
|
|
33
45
|
}).annotate({
|
|
34
46
|
title: 'Story Group',
|
|
35
|
-
description: 'One node of the Story tree: a title over any mix of subgroups and Story leaves.',
|
|
47
|
+
description: 'One node of the Story tree: a title, a one-line description, its markdown page, over any mix of subgroups and Story leaves.',
|
|
36
48
|
});
|
|
37
49
|
export const StoryTreeSchema = StoryTreeGroupSchema.annotate({
|
|
38
50
|
title: 'Story Tree',
|
package/dist/story/story.d.ts
CHANGED
|
@@ -13,21 +13,28 @@ export interface StoryQuestion {
|
|
|
13
13
|
}
|
|
14
14
|
export interface Story {
|
|
15
15
|
readonly title: string;
|
|
16
|
+
readonly description: string;
|
|
17
|
+
readonly spine: boolean;
|
|
16
18
|
readonly sourceUrl: string;
|
|
17
19
|
readonly questions: readonly StoryQuestion[];
|
|
18
20
|
}
|
|
19
21
|
export interface StoryGroup {
|
|
20
22
|
readonly title: string;
|
|
23
|
+
readonly description: string;
|
|
21
24
|
readonly children: readonly StoryNode[];
|
|
22
25
|
}
|
|
23
26
|
export type StoryNode = Story | StoryGroup;
|
|
24
27
|
export declare const Story: {
|
|
25
|
-
make(story: Story
|
|
28
|
+
make(story: Omit<Story, 'spine'> & {
|
|
29
|
+
readonly spine?: boolean;
|
|
30
|
+
}): Story;
|
|
26
31
|
question(question: string, options: {
|
|
27
32
|
readonly answer: string;
|
|
28
33
|
readonly proof: Effect.Effect<unknown, unknown, StoryContext>;
|
|
29
34
|
}): StoryQuestion;
|
|
30
|
-
group(title: string,
|
|
35
|
+
group(title: string, options: {
|
|
36
|
+
readonly description: string;
|
|
37
|
+
}, children: readonly StoryNode[]): StoryGroup;
|
|
31
38
|
trace<A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R | StoryContext>;
|
|
32
39
|
flow<A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R | StoryContext>;
|
|
33
40
|
assert(description: string, passed: boolean): Effect.Effect<void, never, StoryContext>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"story.d.ts","sourceRoot":"","sources":["../../src/story/story.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGzC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;;2BAK9B,CAAC,OAAO,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;qBACvD,CACf,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,OAAO,KACZ,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;;AAP5B,qBAAa,YAAa,SAAQ,iBASf;CAAG;AAEtB,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;CAC/D;AAED,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,SAAS,aAAa,EAAE,CAAC;CAC9C;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,SAAS,SAAS,EAAE,CAAC;CACzC;AAED,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,UAAU,CAAC;AAE3C,eAAO,MAAM,KAAK;IAChB,IAAI,QAAQ,KAAK,GAAG,KAAK;
|
|
1
|
+
{"version":3,"file":"story.d.ts","sourceRoot":"","sources":["../../src/story/story.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGzC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;;2BAK9B,CAAC,OAAO,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;qBACvD,CACf,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,OAAO,KACZ,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;;AAP5B,qBAAa,YAAa,SAAQ,iBASf;CAAG;AAEtB,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;CAC/D;AAED,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,SAAS,aAAa,EAAE,CAAC;CAC9C;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,SAAS,SAAS,EAAE,CAAC;CACzC;AAED,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,UAAU,CAAC;AAE3C,eAAO,MAAM,KAAK;IAChB,IAAI,QAAQ,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG;QAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,KAAK;IAIvE,QAAQ,WACI,MAAM,WACP;QACP,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;KAC/D,GACA,aAAa;IAIhB,KAAK,QACI,MAAM,WACJ;QAAE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;KAAE,YAC/B,SAAS,SAAS,EAAE,GAC7B,UAAU;IAIb,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UACH,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAC7B,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC;IAcxC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UACF,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAC7B,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC;IAgBxC,MAAM,cACS,MAAM,UACX,OAAO,GACd,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,YAAY,CAAC;CAK5C,CAAC;AAEF,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,KAAK,CAgBtD;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,UAAU,CAWhE"}
|
package/dist/story/story.js
CHANGED
|
@@ -4,13 +4,13 @@ export class StoryContext extends Context.Service()('StoryContext') {
|
|
|
4
4
|
}
|
|
5
5
|
export const Story = {
|
|
6
6
|
make(story) {
|
|
7
|
-
return story;
|
|
7
|
+
return { ...story, spine: story.spine ?? false };
|
|
8
8
|
},
|
|
9
9
|
question(question, options) {
|
|
10
10
|
return { question, answer: options.answer, proof: options.proof };
|
|
11
11
|
},
|
|
12
|
-
group(title, children) {
|
|
13
|
-
return { title, children };
|
|
12
|
+
group(title, options, children) {
|
|
13
|
+
return { title, description: options.description, children };
|
|
14
14
|
},
|
|
15
15
|
trace(effect) {
|
|
16
16
|
return Effect.gen(function* () {
|
|
@@ -39,6 +39,8 @@ export function isStory(value) {
|
|
|
39
39
|
return false;
|
|
40
40
|
const story = value;
|
|
41
41
|
return (typeof story.title === 'string' &&
|
|
42
|
+
typeof story.description === 'string' &&
|
|
43
|
+
typeof story.spine === 'boolean' &&
|
|
42
44
|
typeof story.sourceUrl === 'string' &&
|
|
43
45
|
Array.isArray(story.questions) &&
|
|
44
46
|
story.questions.every((question) => typeof question.question === 'string' &&
|
|
@@ -49,7 +51,9 @@ export function isStoryGroup(value) {
|
|
|
49
51
|
if (typeof value !== 'object' || value === null)
|
|
50
52
|
return false;
|
|
51
53
|
const group = value;
|
|
52
|
-
if (typeof group.title !== 'string' ||
|
|
54
|
+
if (typeof group.title !== 'string' ||
|
|
55
|
+
typeof group.description !== 'string' ||
|
|
56
|
+
!Array.isArray(group.children)) {
|
|
53
57
|
return false;
|
|
54
58
|
}
|
|
55
59
|
return group.children.every((child) => isStory(child) || isStoryGroup(child));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "laymos",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Enforces architectural dependency rules and explores source dependencies.",
|
|
6
6
|
"repository": {
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"oxc-resolver": "11.24.2",
|
|
54
54
|
"tsx": "4.23.12",
|
|
55
55
|
"yoctocolors": "2.2.0",
|
|
56
|
-
"@pkishorez/effect-tracer": "0.0.
|
|
56
|
+
"@pkishorez/effect-tracer": "0.0.7"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"@types/node": "26.2.0",
|