@ontrails/trails 1.0.0-beta.3 → 1.0.0-beta.4

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 (35) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/dist/src/trails/add-surface.js +9 -9
  3. package/dist/src/trails/add-surface.js.map +1 -1
  4. package/dist/src/trails/add-trail.d.ts +1 -2
  5. package/dist/src/trails/add-trail.d.ts.map +1 -1
  6. package/dist/src/trails/add-trail.js +16 -24
  7. package/dist/src/trails/add-trail.js.map +1 -1
  8. package/dist/src/trails/add-verify.js +9 -9
  9. package/dist/src/trails/add-verify.js.map +1 -1
  10. package/dist/src/trails/create-scaffold.js +25 -25
  11. package/dist/src/trails/create-scaffold.js.map +1 -1
  12. package/dist/src/trails/create.d.ts +1 -1
  13. package/dist/src/trails/create.js +10 -10
  14. package/dist/src/trails/create.js.map +1 -1
  15. package/dist/src/trails/guide.js +12 -12
  16. package/dist/src/trails/guide.js.map +1 -1
  17. package/dist/src/trails/survey.d.ts +0 -2
  18. package/dist/src/trails/survey.d.ts.map +1 -1
  19. package/dist/src/trails/survey.js +21 -25
  20. package/dist/src/trails/survey.js.map +1 -1
  21. package/dist/src/trails/warden.js +28 -28
  22. package/dist/src/trails/warden.js.map +1 -1
  23. package/package.json +1 -1
  24. package/src/__tests__/create.test.ts +7 -7
  25. package/src/__tests__/guide.test.ts +4 -4
  26. package/src/__tests__/survey.test.ts +6 -8
  27. package/src/__tests__/warden.test.ts +2 -2
  28. package/src/trails/add-surface.ts +9 -9
  29. package/src/trails/add-trail.ts +16 -25
  30. package/src/trails/add-verify.ts +9 -9
  31. package/src/trails/create-scaffold.ts +27 -27
  32. package/src/trails/create.ts +10 -10
  33. package/src/trails/guide.ts +14 -14
  34. package/src/trails/survey.ts +29 -36
  35. package/src/trails/warden.ts +33 -33
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import type { FollowFn } from '@ontrails/core';
9
- import { Result, hike } from '@ontrails/core';
9
+ import { Result, trail } from '@ontrails/core';
10
10
  import { z } from 'zod';
11
11
 
12
12
  // ---------------------------------------------------------------------------
@@ -146,7 +146,7 @@ const runCreate = async (
146
146
  // Route definition
147
147
  // ---------------------------------------------------------------------------
148
148
 
149
- export const createRoute = hike('create', {
149
+ export const createRoute = trail('create', {
150
150
  description: 'Create a new Trails project',
151
151
  fields: {
152
152
  starter: {
@@ -157,7 +157,7 @@ export const createRoute = hike('create', {
157
157
  value: 'hello',
158
158
  },
159
159
  {
160
- hint: '4 trails, hike, event, store',
160
+ hint: '4 trails, event, store',
161
161
  label: 'Entity CRUD',
162
162
  value: 'entity',
163
163
  },
@@ -175,13 +175,7 @@ export const createRoute = hike('create', {
175
175
  ],
176
176
  },
177
177
  },
178
- follows: ['create.scaffold', 'add.surface', 'add.verify'],
179
- implementation: async (input: BlazeInput, ctx) => {
180
- if (!ctx.follow) {
181
- return Result.err(new Error('create route requires ctx.follow'));
182
- }
183
- return await runCreate(ctx.follow, input);
184
- },
178
+ follow: ['create.scaffold', 'add.surface', 'add.verify'],
185
179
  input: z.object({
186
180
  dir: z.string().optional().describe('Parent directory'),
187
181
  name: z.string().describe('Project name'),
@@ -200,4 +194,10 @@ export const createRoute = hike('create', {
200
194
  dir: z.string(),
201
195
  name: z.string(),
202
196
  }),
197
+ run: async (input: BlazeInput, ctx) => {
198
+ if (!ctx.follow) {
199
+ return Result.err(new Error('create route requires ctx.follow'));
200
+ }
201
+ return await runCreate(ctx.follow, input);
202
+ },
203
203
  });
@@ -63,19 +63,6 @@ export const guideTrail = trail('guide', {
63
63
  name: 'List trail guidance',
64
64
  },
65
65
  ],
66
- implementation: async (input, ctx) => {
67
- const app = await loadApp(input.module, ctx.cwd ?? '.');
68
-
69
- if (input.trailId) {
70
- const item = app.get(input.trailId);
71
- if (!item) {
72
- return Result.err(new Error(`Trail not found: ${input.trailId}`));
73
- }
74
- return Result.ok(toGuideDetail(item as Trail<unknown, unknown>));
75
- }
76
-
77
- return Result.ok(toGuideEntries(app));
78
- },
79
66
  input: z.object({
80
67
  module: z
81
68
  .string()
@@ -83,6 +70,7 @@ export const guideTrail = trail('guide', {
83
70
  .describe('Path to the app module'),
84
71
  trailId: z.string().optional().describe('Trail ID for detailed guidance'),
85
72
  }),
73
+ intent: 'read',
86
74
  output: z.union([
87
75
  z.array(
88
76
  z.object({
@@ -100,5 +88,17 @@ export const guideTrail = trail('guide', {
100
88
  kind: z.string(),
101
89
  }),
102
90
  ]),
103
- readOnly: true,
91
+ run: async (input, ctx) => {
92
+ const app = await loadApp(input.module, ctx.cwd ?? '.');
93
+
94
+ if (input.trailId) {
95
+ const item = app.get(input.trailId);
96
+ if (!item) {
97
+ return Result.err(new Error(`Trail not found: ${input.trailId}`));
98
+ }
99
+ return Result.ok(toGuideDetail(item as Trail<unknown, unknown>));
100
+ }
101
+
102
+ return Result.ok(toGuideEntries(app));
103
+ },
104
104
  });
@@ -32,11 +32,9 @@ export interface BriefReport {
32
32
  readonly outputSchemas: boolean;
33
33
  readonly examples: boolean;
34
34
  readonly detours: boolean;
35
- readonly hikes: boolean;
36
35
  readonly events: boolean;
37
36
  };
38
37
  readonly trails: number;
39
- readonly hikes: number;
40
38
  readonly events: number;
41
39
  }
42
40
 
@@ -73,10 +71,8 @@ export const generateBriefReport = (app: Topo): BriefReport => {
73
71
  detours: hasDetours,
74
72
  events: app.events.size > 0,
75
73
  examples: hasExamples,
76
- hikes: app.hikes.size > 0,
77
74
  outputSchemas: hasOutputSchemas,
78
75
  },
79
- hikes: app.hikes.size,
80
76
  name: app.name,
81
77
  trails: app.trails.size,
82
78
  version: '0.1.0',
@@ -88,14 +84,13 @@ export const generateBriefReport = (app: Topo): BriefReport => {
88
84
  // ---------------------------------------------------------------------------
89
85
 
90
86
  const safetyLabel = (entry: {
91
- readOnly?: boolean;
92
- destructive?: boolean;
87
+ intent?: 'read' | 'write' | 'destroy';
93
88
  }): string => {
94
- if (entry.destructive) {
95
- return 'destructive';
89
+ if (entry.intent === 'destroy') {
90
+ return 'destroy';
96
91
  }
97
- if (entry.readOnly) {
98
- return 'readOnly';
92
+ if (entry.intent === 'read') {
93
+ return 'read';
99
94
  }
100
95
  return '-';
101
96
  };
@@ -104,7 +99,7 @@ const formatTrailList = (app: Topo): object => {
104
99
  const items = app.list();
105
100
  const entries = items.map((item) => {
106
101
  const safety = safetyLabel(
107
- item as unknown as { readOnly?: boolean; destructive?: boolean }
102
+ item as unknown as { intent?: 'read' | 'write' | 'destroy' }
108
103
  );
109
104
  const examples = Array.isArray(
110
105
  (item as unknown as { examples?: unknown[] }).examples
@@ -132,7 +127,7 @@ const formatTrailList = (app: Topo): object => {
132
127
  */
133
128
  const formatTrailDetail = (item: Trail<unknown, unknown>): object => {
134
129
  const safety = safetyLabel(
135
- item as unknown as { readOnly?: boolean; destructive?: boolean }
130
+ item as unknown as { intent?: 'read' | 'write' | 'destroy' }
136
131
  );
137
132
 
138
133
  return {
@@ -218,27 +213,6 @@ export const surveyTrail = trail('survey', {
218
213
  name: 'Brief capability report',
219
214
  },
220
215
  ],
221
- implementation: async (input, ctx) => {
222
- const app = await loadApp(input.module, ctx.cwd ?? '.');
223
-
224
- if (input.brief) {
225
- return Result.ok(generateBriefReport(app));
226
- }
227
-
228
- if (input.diff) {
229
- return await buildSurveyDiff(app, input.breakingOnly);
230
- }
231
-
232
- if (input.trailId) {
233
- return buildSurveyDetail(app, input.trailId);
234
- }
235
-
236
- if (input.generate) {
237
- return await buildSurveyGenerate(app);
238
- }
239
-
240
- return Result.ok(formatTrailList(app));
241
- },
242
216
  input: z.object({
243
217
  breakingOnly: z
244
218
  .boolean()
@@ -256,6 +230,7 @@ export const surveyTrail = trail('survey', {
256
230
  .describe('Path to the app module'),
257
231
  trailId: z.string().optional().describe('Trail ID for detail view'),
258
232
  }),
233
+ intent: 'read',
259
234
  output: z.union([
260
235
  z.object({
261
236
  count: z.number(),
@@ -275,10 +250,8 @@ export const surveyTrail = trail('survey', {
275
250
  detours: z.boolean(),
276
251
  events: z.boolean(),
277
252
  examples: z.boolean(),
278
- hikes: z.boolean(),
279
253
  outputSchemas: z.boolean(),
280
254
  }),
281
- hikes: z.number(),
282
255
  name: z.string(),
283
256
  trails: z.number(),
284
257
  version: z.string(),
@@ -303,5 +276,25 @@ export const surveyTrail = trail('survey', {
303
276
  mapPath: z.string(),
304
277
  }),
305
278
  ]),
306
- readOnly: true,
279
+ run: async (input, ctx) => {
280
+ const app = await loadApp(input.module, ctx.cwd ?? '.');
281
+
282
+ if (input.brief) {
283
+ return Result.ok(generateBriefReport(app));
284
+ }
285
+
286
+ if (input.diff) {
287
+ return await buildSurveyDiff(app, input.breakingOnly);
288
+ }
289
+
290
+ if (input.trailId) {
291
+ return buildSurveyDetail(app, input.trailId);
292
+ }
293
+
294
+ if (input.generate) {
295
+ return await buildSurveyGenerate(app);
296
+ }
297
+
298
+ return Result.ok(formatTrailList(app));
299
+ },
307
300
  });
@@ -37,38 +37,6 @@ export const wardenTrail = trail('warden', {
37
37
  name: 'GitHub Actions annotations',
38
38
  },
39
39
  ],
40
- implementation: async (input, ctx) => {
41
- const rootDir = input.rootDir ?? ctx.cwd ?? process.cwd();
42
- // oxlint-disable-next-line prefer-await-to-then -- catch converts rejection to undefined cleanly
43
- const topo = await loadApp('./src/app.ts', rootDir).catch(
44
- (): undefined => undefined
45
- );
46
-
47
- const report = await runWarden({
48
- driftOnly: input.driftOnly,
49
- lintOnly: input.lintOnly,
50
- rootDir,
51
- topo,
52
- });
53
-
54
- const formatters: Record<string, (r: typeof report) => string> = {
55
- github: formatGitHubAnnotations,
56
- json: formatJson,
57
- summary: formatSummary,
58
- text: formatWardenReport,
59
- };
60
- const formatter = formatters[input.format] ?? formatWardenReport;
61
- const formatted = formatter(report);
62
-
63
- return Result.ok({
64
- diagnostics: report.diagnostics,
65
- drift: report.drift,
66
- errorCount: report.errorCount,
67
- formatted,
68
- passed: report.passed,
69
- warnCount: report.warnCount,
70
- });
71
- },
72
40
  input: z.object({
73
41
  driftOnly: z.boolean().default(false).describe('Only run drift detection'),
74
42
  format: z
@@ -78,6 +46,7 @@ export const wardenTrail = trail('warden', {
78
46
  lintOnly: z.boolean().default(false).describe('Only run lint rules'),
79
47
  rootDir: z.string().optional().describe('Root directory to scan'),
80
48
  }),
49
+ intent: 'read',
81
50
  output: z.object({
82
51
  diagnostics: z.array(
83
52
  z.object({
@@ -100,5 +69,36 @@ export const wardenTrail = trail('warden', {
100
69
  passed: z.boolean(),
101
70
  warnCount: z.number(),
102
71
  }),
103
- readOnly: true,
72
+ run: async (input, ctx) => {
73
+ const rootDir = input.rootDir ?? ctx.cwd ?? process.cwd();
74
+ // oxlint-disable-next-line prefer-await-to-then -- catch converts rejection to undefined cleanly
75
+ const topo = await loadApp('./src/app.ts', rootDir).catch(
76
+ (): undefined => undefined
77
+ );
78
+
79
+ const report = await runWarden({
80
+ driftOnly: input.driftOnly,
81
+ lintOnly: input.lintOnly,
82
+ rootDir,
83
+ topo,
84
+ });
85
+
86
+ const formatters: Record<string, (r: typeof report) => string> = {
87
+ github: formatGitHubAnnotations,
88
+ json: formatJson,
89
+ summary: formatSummary,
90
+ text: formatWardenReport,
91
+ };
92
+ const formatter = formatters[input.format] ?? formatWardenReport;
93
+ const formatted = formatter(report);
94
+
95
+ return Result.ok({
96
+ diagnostics: report.diagnostics,
97
+ drift: report.drift,
98
+ errorCount: report.errorCount,
99
+ formatted,
100
+ passed: report.passed,
101
+ warnCount: report.warnCount,
102
+ });
103
+ },
104
104
  });