@warren-dean/code-kit 0.8.1 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14,6 +14,8 @@ const STORY_HEADING = /^###\s+(ST-\d+)\b\s*(.*)$/;
14
14
  const REQUIREMENT_HEADING = /^###\s+((?!ST-)[A-Z][A-Z0-9]*-\d+)\b\s*(.*)$/;
15
15
  export const STATES = ['todo', 'in progress', 'review', 'done'];
16
16
  export const LEAD = 'lead';
17
+ /** ONB-2: the pseudo-lane for design stories, which the lead designs with the person before any screen is built. */
18
+ export const DESIGN = 'design';
17
19
  // Test files, by the usual conventions. Tests name the requirement IDs they prove.
18
20
  const TEST =
19
21
  /(^|\/)(tests?|__tests__|e2e)\/|\.(test|spec)\.[^/]+$|_test\.(go|py)$|(^|\/)test_[^/]+\.py$/;
@@ -185,7 +187,7 @@ export function traceProblems(requirements, stories, lanes) {
185
187
  if (storyIds.has(s.id)) problems.push(`${s.id} is in the plan more than once`);
186
188
  storyIds.add(s.id);
187
189
  if (!s.lane) problems.push(`${s.id} has no **Lane:**`);
188
- else if (s.lane !== LEAD && !lanes.includes(s.lane))
190
+ else if (s.lane !== LEAD && s.lane !== DESIGN && !lanes.includes(s.lane))
189
191
  problems.push(`${s.id} names an unknown lane "${s.lane}"`);
190
192
  if (!s.requirements.length && !s.noRequirements)
191
193
  problems.push(`${s.id} cites no requirements (write "none" if it delivers none)`);
@@ -153,3 +153,65 @@ export function trail(root, status, from) {
153
153
  };
154
154
  });
155
155
  }
156
+
157
+ /** The code map of no story in particular: the whole project. */
158
+ export const PROJECT = 'project';
159
+
160
+ /**
161
+ * MAP-5: the whole project's code, for when no story is at work: its folders (`depth` deep, shallower
162
+ * when that makes more than `most`) by the layer most of their files sit in, with the imports between
163
+ * folders. The same shape as a story's map, each node a folder with its file count.
164
+ */
165
+ export function projectMap(root, config, tracked, { depth = 3, most = 60 } = {}) {
166
+ const code = tracked.filter(isCode);
167
+ const set = new Set(code);
168
+ const aliases = config.importAliases ?? {};
169
+ const folderAt = (d) => (rel) => {
170
+ const parts = rel.split('/');
171
+ return parts.length === 1 ? '.' : parts.slice(0, Math.min(d, parts.length - 1)).join('/');
172
+ };
173
+ let d = depth;
174
+ while (d > 1 && new Set(code.map(folderAt(d))).size > most) d -= 1;
175
+ const folderOf = folderAt(d);
176
+ const nodes = new Map();
177
+ for (const rel of code) {
178
+ const path = folderOf(rel);
179
+ const node = nodes.get(path) ?? {
180
+ path,
181
+ lane: laneOfFile(rel, config),
182
+ layers: new Map(),
183
+ imports: new Set(),
184
+ files: 0,
185
+ };
186
+ nodes.set(path, node);
187
+ const layer = TEST.test(rel) ? 'tests' : (layerOf(rel, config.layers)?.name ?? 'other');
188
+ node.layers.set(layer, (node.layers.get(layer) ?? 0) + 1);
189
+ node.files += 1;
190
+ let source = '';
191
+ try {
192
+ source = readFileSync(join(root, rel), 'utf8');
193
+ } catch {
194
+ // unreadable: no imports
195
+ }
196
+ for (const spec of importsOf(source)) {
197
+ const target = resolveIn(spec, rel, aliases, set);
198
+ if (target && folderOf(target) !== path) node.imports.add(folderOf(target));
199
+ }
200
+ }
201
+ const files = [...nodes.values()]
202
+ .map((n) => ({
203
+ path: n.path,
204
+ layer: [...n.layers.entries()].sort((a, b) => b[1] - a[1])[0][0],
205
+ lane: n.lane,
206
+ imports: [...n.imports].sort(),
207
+ files: n.files,
208
+ }))
209
+ .sort((a, b) => a.path.localeCompare(b.path));
210
+ const used = new Set(files.map((f) => f.layer));
211
+ const layers = [...config.layers.map((l) => l.name), 'tests', 'other'].filter((l) => used.has(l));
212
+ return {
213
+ story: { id: PROJECT, title: 'The whole project', lane: null, state: null },
214
+ layers,
215
+ files,
216
+ };
217
+ }