1313 */
1414
1515import { routes } from "../src/app.js" ;
16+ import type {
17+ CommandInfo ,
18+ FlagInfo ,
19+ RouteInfo ,
20+ RouteMap ,
21+ } from "../src/lib/introspect.js" ;
22+ import {
23+ buildCommandInfo ,
24+ extractRouteGroupCommands ,
25+ isCommand ,
26+ isRouteMap ,
27+ } from "../src/lib/introspect.js" ;
1628
1729const OUTPUT_PATH = "plugins/sentry-cli/skills/sentry-cli/SKILL.md" ;
1830const DOCS_PATH = "docs/src/content/docs" ;
@@ -26,61 +38,9 @@ const CODE_BLOCK_REGEX = /```(\w*)\n([\s\S]*?)```/g;
2638/** Regex to extract npm command from PackageManagerCode Astro component (handles multi-line) */
2739const PACKAGE_MANAGER_REGEX = / < P a c k a g e M a n a g e r C o d e [ \s \S ] * ?n p m = " ( [ ^ " ] + ) " / ;
2840
29- // ─────────────────────────────────────────────────────────────────────────────
30- // Types for Stricli Route Introspection
31- //
32- // Note: While @stricli /core exports RouteMap and Command types, they require
33- // complex generic parameters (CommandContext) and don't export internal types
34- // like RouteMapEntry or FlagParameter. These simplified types are purpose-built
35- // for introspection and documentation generation.
36- // ─────────────────────────────────────────────────────────────────────────────
37-
38- type RouteMapEntry = {
39- name : { original : string } ;
40- target : RouteTarget ;
41- hidden : boolean ;
42- } ;
43-
44- type RouteTarget = RouteMap | Command ;
45-
46- type RouteMap = {
47- brief : string ;
48- fullDescription ?: string ;
49- getAllEntries : ( ) => RouteMapEntry [ ] ;
50- } ;
51-
52- type Command = {
53- brief : string ;
54- fullDescription ?: string ;
55- parameters : {
56- positional ?: PositionalParams ;
57- flags ?: Record < string , FlagDef > ;
58- aliases ?: Record < string , string > ;
59- } ;
60- } ;
61-
62- type PositionalParams =
63- | { kind : "tuple" ; parameters : PositionalParam [ ] }
64- | { kind : "array" ; parameter : PositionalParam } ;
65-
66- type PositionalParam = {
67- brief ?: string ;
68- placeholder ?: string ;
69- } ;
70-
71- type FlagDef = {
72- kind : "boolean" | "parsed" ;
73- brief ?: string ;
74- default ?: unknown ;
75- optional ?: boolean ;
76- variadic ?: boolean ;
77- placeholder ?: string ;
78- hidden ?: boolean ;
79- } ;
80-
81- // ─────────────────────────────────────────────────────────────────────────────
41+ // ---------------------------------------------------------------------------
8242// Markdown Parsing Utilities
83- // ─────────────────────────────────────────────────────────────────────────────
43+ // ---------------------------------------------------------------------------
8444
8545/**
8646 * Strip YAML frontmatter from markdown content
@@ -175,9 +135,9 @@ function escapeRegex(str: string): string {
175135 return str . replace ( / [ . * + ? ^ $ { } ( ) | [ \] \\ ] / g, "\\$&" ) ;
176136}
177137
178- // ─────────────────────────────────────────────────────────────────────────────
138+ // ---------------------------------------------------------------------------
179139// Documentation Loading
180- // ─────────────────────────────────────────────────────────────────────────────
140+ // ---------------------------------------------------------------------------
181141
182142/**
183143 * Load and parse a documentation file
@@ -398,132 +358,13 @@ async function loadCommandsOverview(): Promise<{
398358 } ;
399359}
400360
401- // ─────────────────────────────────────────────────────────────────────────────
402- // Route Introspection
403- // ─────────────────────────────────────────────────────────────────────────────
404-
405- function isRouteMap ( target : RouteTarget ) : target is RouteMap {
406- return "getAllEntries" in target ;
407- }
408-
409- function isCommand ( target : RouteTarget ) : target is Command {
410- return "parameters" in target && ! ( "getAllEntries" in target ) ;
411- }
412-
413- type CommandInfo = {
414- path : string ;
415- brief : string ;
416- fullDescription ?: string ;
417- flags : FlagInfo [ ] ;
418- positional : string ;
419- aliases : Record < string , string > ;
420- examples : string [ ] ;
421- } ;
422-
423- type FlagInfo = {
424- name : string ;
425- brief : string ;
426- kind : "boolean" | "parsed" ;
427- default ?: unknown ;
428- optional : boolean ;
429- variadic : boolean ;
430- hidden : boolean ;
431- } ;
432-
433- type RouteInfo = {
434- name : string ;
435- brief : string ;
436- commands : CommandInfo [ ] ;
437- } ;
438-
439- /**
440- * Extract positional parameter placeholder string
441- */
442- function getPositionalString ( params ?: PositionalParams ) : string {
443- if ( ! params ) {
444- return "" ;
445- }
446-
447- if ( params . kind === "tuple" ) {
448- return params . parameters
449- . map ( ( p , i ) => `<${ p . placeholder ?? `arg${ i } ` } >` )
450- . join ( " " ) ;
451- }
452-
453- if ( params . kind === "array" ) {
454- const placeholder = params . parameter . placeholder ?? "args" ;
455- return `<${ placeholder } ...>` ;
456- }
457-
458- return "" ;
459- }
460-
461- /**
462- * Extract flag information from a command
463- */
464- function extractFlags ( flags : Record < string , FlagDef > | undefined ) : FlagInfo [ ] {
465- if ( ! flags ) {
466- return [ ] ;
467- }
468-
469- return Object . entries ( flags ) . map ( ( [ name , def ] ) => ( {
470- name,
471- brief : def . brief ?? "" ,
472- kind : def . kind ,
473- default : def . default ,
474- optional : def . optional ?? def . kind === "boolean" ,
475- variadic : def . variadic ?? false ,
476- hidden : def . hidden ?? false ,
477- } ) ) ;
478- }
479-
480- /**
481- * Build a CommandInfo from a Command
482- */
483- function buildCommandInfo (
484- cmd : Command ,
485- path : string ,
486- examples : string [ ] = [ ]
487- ) : CommandInfo {
488- return {
489- path,
490- brief : cmd . brief ,
491- fullDescription : cmd . fullDescription ,
492- flags : extractFlags ( cmd . parameters . flags ) ,
493- positional : getPositionalString ( cmd . parameters . positional ) ,
494- aliases : cmd . parameters . aliases ?? { } ,
495- examples,
496- } ;
497- }
498-
499- /**
500- * Extract commands from a route group
501- */
502- function extractRouteGroupCommands (
503- routeMap : RouteMap ,
504- routeName : string ,
505- docExamples : Map < string , string [ ] >
506- ) : CommandInfo [ ] {
507- const commands : CommandInfo [ ] = [ ] ;
508-
509- for ( const subEntry of routeMap . getAllEntries ( ) ) {
510- if ( subEntry . hidden ) {
511- continue ;
512- }
513-
514- const subTarget = subEntry . target ;
515- if ( isCommand ( subTarget ) ) {
516- const path = `sentry ${ routeName } ${ subEntry . name . original } ` ;
517- const examples = docExamples . get ( path ) ?? [ ] ;
518- commands . push ( buildCommandInfo ( subTarget , path , examples ) ) ;
519- }
520- }
521-
522- return commands ;
523- }
361+ // ---------------------------------------------------------------------------
362+ // Route Introspection (with async doc loading)
363+ // ---------------------------------------------------------------------------
524364
525365/**
526- * Walk the route tree and extract command information
366+ * Walk the route tree and extract command information with doc examples.
367+ * This is the async version that loads documentation examples from disk.
527368 */
528369async function extractRoutes ( routeMap : RouteMap ) : Promise < RouteInfo [ ] > {
529370 const result : RouteInfo [ ] = [ ] ;
@@ -559,9 +400,9 @@ async function extractRoutes(routeMap: RouteMap): Promise<RouteInfo[]> {
559400 return result ;
560401}
561402
562- // ─────────────────────────────────────────────────────────────────────────────
403+ // ---------------------------------------------------------------------------
563404// Markdown Generation
564- // ─────────────────────────────────────────────────────────────────────────────
405+ // ---------------------------------------------------------------------------
565406
566407/**
567408 * Generate the front matter for the skill file
@@ -782,9 +623,9 @@ async function generateSkillMarkdown(routeMap: RouteMap): Promise<string> {
782623 return sections . join ( "\n" ) ;
783624}
784625
785- // ─────────────────────────────────────────────────────────────────────────────
626+ // ---------------------------------------------------------------------------
786627// Main
787- // ─────────────────────────────────────────────────────────────────────────────
628+ // ---------------------------------------------------------------------------
788629
789630const content = await generateSkillMarkdown ( routes as unknown as RouteMap ) ;
790631await Bun . write ( OUTPUT_PATH , content ) ;
0 commit comments