Skip to content

generate — scan

Scan

Functions

parseSourceArgs

function parseSourceArgs(args: string[]): SourceEntry[]
TypeScript

Use parseSourceArgs to convert raw CLI source arguments into structured path entries that skrypt's scanner can process.

Reach for this when you're building a custom CLI wrapper around skrypt's generation pipeline and need to accept source paths from user input — with or without human-readable labels attached.

Each argument is split on the last colon to separate the filesystem path from an optional display label (e.g. "./api:Public API"). Arguments without a colon are returned with only a path. The colon-detection logic intentionally ignores Windows drive letters like C:\.

Parameters

NameTypeRequiredDescription
argsstring[]YesRaw source path arguments, each optionally suffixed with :<label> to control how that source appears in generated docs. Paths can be relative or absolute.

Returns

Returns an array of SourceEntry objects, each with a path and an optional label. Pass this array directly to skrypt's scanner or config resolver to kick off documentation generation for the specified sources.

Heads up

  • The split happens on the last colon in the string, so paths like ./src/http:client:HTTP Client will use HTTP Client as the label and ./src/http:client as the path. Keep labels simple to avoid ambiguity.
  • Relative paths are preserved as-is — resolution against the working directory happens downstream, not here.

Example:

type SourceEntry = {
  path: string;
  label?: string;
};

function parseSourceArgs(args: string[]): SourceEntry[] {
  return args.map(arg => {
    const colonIdx = arg.lastIndexOf(':');
    if (colonIdx > 1 && !arg.substring(0, colonIdx).endsWith('\\')) {
      return {
        path: arg.substring(0, colonIdx),
        label: arg.substring(colonIdx + 1),
      };
    }
    return { path: arg };
  });
}

// Simulates: skrypt generate ./src ./api:Public API ./internal:Internal
const rawArgs = ['./src', './api:Public API', './internal:Internal'];

try {
  const entries = parseSourceArgs(rawArgs);
  console.log(entries);
  // [
  //   { path: './src' },
  //   { path: './api', label: 'Public API' },
  //   { path: './internal', label: 'Internal' }
  // ]
} catch (err) {
  console.error('Failed to parse source args:', err);
}
TypeScript

readIgnorePatterns

function readIgnorePatterns(sourcePath: string): string[]
TypeScript

Use readIgnorePatterns to load the exclusion rules that tell skrypt generate which files and symbols to skip during documentation generation.

Call this before scanning a source directory when you need to inspect or extend the active ignore rules — for example, to merge project-level patterns with additional runtime exclusions before passing them to the scanner.

skrypt looks for a .skryptignore file at the root of your source directory. Each non-empty line in that file becomes a glob pattern. If no .skryptignore exists, the function returns an empty array and scanning proceeds without exclusions.

Parameters

NameTypeRequiredDescription
sourcePathstringYesAbsolute or relative path to the source directory to scan — the function looks for .skryptignore directly inside this directory, not in parent folders

Returns

An array of glob pattern strings parsed from .skryptignore, one entry per non-empty line. Returns [] if no ignore file is found. Pass the result to your scanner configuration to filter out matched paths before documentation is generated.

Heads up

  • Patterns are read from <sourcePath>/.skryptignore only — a .skryptignore in a parent or nested directory is silently ignored.
  • The function returns raw lines from the file without validation; malformed glob patterns won't throw but will silently fail to match anything during scanning.

Example:

import { existsSync, readFileSync, writeFileSync, mkdirSync, rmSync } from 'fs'
import { join } from 'path'
import { tmpdir } from 'os'

// Inline implementation — do not import from autodocs
function readIgnorePatterns(sourcePath: string): string[] {
  const ignorePath = join(sourcePath, '.skryptignore')
  if (!existsSync(ignorePath)) return []

  const content = readFileSync(ignorePath, 'utf-8')
  return content
    .split('\n')
    .map((line) => line.trim())
    .filter((line) => line.length > 0 && !line.startsWith('#'))
}

// Set up a temporary source directory with a .skryptignore file
const sourceDir = join(tmpdir(), 'my-project-src')
mkdirSync(sourceDir, { recursive: true })

writeFileSync(
  join(sourceDir, '.skryptignore'),
  [
    '# Ignore generated and test files',
    'dist/**',
    '**/*.test.ts',
    '**/__mocks__/**',
    'src/internal/**',
  ].join('\n')
)

try {
  const patterns = readIgnorePatterns(sourceDir)
  console.log('Active ignore patterns:', patterns)
  // Active ignore patterns: [ 'dist/**', '**/*.test.ts', '**/__mocks__/**', 'src/internal/**' ]

  // Merge with any runtime exclusions before passing to the scanner
  const runtimeExclusions = ['**/generated/**']
  const allPatterns = [...patterns, ...runtimeExclusions]
  console.log('Merged patterns for scanner:', allPatterns)

  // Check behavior when no .skryptignore exists
  const emptyDir = join(tmpdir(), 'project-no-ignore')
  mkdirSync(emptyDir, { recursive: true })
  console.log('No ignore file present:', readIgnorePatterns(emptyDir))
  // No ignore file present: []

  rmSync(emptyDir, { recursive: true })
} catch (err) {
  console.error('Failed to read ignore patterns:', err)
} finally {
  rmSync(sourceDir, { recursive: true })
}
TypeScript

findOpenAPISpec

function findOpenAPISpec(sourcePath: string): string | null
TypeScript

Use findOpenAPISpec to automatically locate an OpenAPI or Swagger spec file in your project directory without hardcoding its path.

Reach for this when you're building a doc generation pipeline and want to support projects that may use any of the common OpenAPI filename conventions (openapi.json, openapi.yaml, swagger.json, etc.) without requiring the user to specify the file explicitly.

The function scans a fixed list of candidate filenames in the given directory and returns the absolute path to the first one it finds on disk.

Parameters

NameTypeRequiredDescription
sourcePathstringYesPath to the directory to search — typically your project's src or root folder. Relative paths are resolved from the current working directory.

Returns

The absolute path to the detected spec file as a string, or null if none of the known candidates exist in the directory. When you get a path back, pass it directly to your spec parser or include it in your skrypt generate config to drive REST API doc generation alongside your code docs.

Heads up

  • Only the directory itself is searched — subdirectories are not traversed. If your spec lives at src/api/openapi.yaml, pass src/api as the sourcePath, not src.
  • Returns the first match found, so if you have both openapi.json and openapi.yaml present, the result depends on the internal candidate order rather than which file is newer or more complete.

Example:

import { existsSync } from 'fs'
import { resolve, join } from 'path'

function findOpenAPISpec(sourcePath: string): string | null {
  const candidates = [
    'openapi.json',
    'openapi.yaml',
    'openapi.yml',
    'swagger.json',
    'swagger.yaml',
    'swagger.yml',
  ]

  for (const candidate of candidates) {
    const fullPath = join(resolve(sourcePath), candidate)
    if (existsSync(fullPath)) {
      return fullPath
    }
  }

  return null
}

// Simulate a project directory that contains openapi.yaml
const projectSrcPath = './my-project/src'

const specPath = findOpenAPISpec(projectSrcPath)

if (specPath) {
  console.log(`Found OpenAPI spec: ${specPath}`)
  // => Found OpenAPI spec: /home/user/my-project/src/openapi.yaml
  // Pass specPath to your doc generator or spec parser next
} else {
  console.log('No OpenAPI spec found — skipping REST API doc generation')
}
TypeScript

shouldExcludeElement

function shouldExcludeElement(element: APIElement, patterns: string[]): boolean
TypeScript

Use shouldExcludeElement to filter API elements out of your generated documentation based on name or pattern rules.

Reach for this when building a custom generation pipeline and you need to programmatically decide whether a scanned element should appear in the output — for example, skipping internal helpers, deprecated symbols, or anything prefixed with _.

Each pattern in the array is evaluated against the element in order. A pattern prefixed with name: matches the element's exact name (e.g., name:_internalHelper). The function returns true on the first match, so order your patterns from most specific to least.

Parameters

NameTypeRequiredDescription
elementAPIElementYesThe scanned API element to evaluate — includes its name, kind, file path, and signature.
patternsstring[]YesExclusion rules to test against the element. Prefix with name: to match by exact name. An empty array always returns false.

Returns

Returns true if the element matches any pattern and should be dropped from the output, false if it should be included. Use the return value to filter your elements array before passing it to the doc generator.

Heads up

  • Matching is exact when using name:name:createUser won't match createUserFromEmail. Use multiple patterns if you need to exclude a family of names.
  • Passing an empty patterns array is safe and always returns false, so all elements pass through.

Example:

type APIElementKind = "function" | "class" | "interface" | "type" | "variable";

interface APIElement {
  name: string;
  kind: APIElementKind;
  filePath: string;
  signature: string;
  docstring?: string;
}

function shouldExcludeElement(element: APIElement, patterns: string[]): boolean {
  for (const pattern of patterns) {
    if (pattern.startsWith("name:")) {
      const namePattern = pattern.slice(5);
      if (element.name === namePattern) {
        return true;
      }
    }
  }
  return false;
}

const scannedElements: APIElement[] = [
  {
    name: "createPayment",
    kind: "function",
    filePath: "src/payments/index.ts",
    signature: "function createPayment(amount: number, currency: string): Promise<Payment>",
    docstring: "Creates a new payment intent.",
  },
  {
    name: "_resolveInternalConfig",
    kind: "function",
    filePath: "src/payments/internal.ts",
    signature: "function _resolveInternalConfig(): Config",
  },
  {
    name: "legacyChargeCard",
    kind: "function",
    filePath: "src/payments/legacy.ts",
    signature: "function legacyChargeCard(token: string): void",
    docstring: "Deprecated. Use createPayment instead.",
  },
];

const excludePatterns = [
  "name:_resolveInternalConfig",
  "name:legacyChargeCard",
];

try {
  const publicElements = scannedElements.filter(
    (el) => !shouldExcludeElement(el, excludePatterns)
  );

  console.log("Elements included in docs:");
  publicElements.forEach((el) => console.log(` - ${el.name} (${el.kind})`));
  // Elements included in docs:
  //  - createPayment (function)
} catch (err) {
  console.error("Failed to filter elements:", err);
}
TypeScript

scanSources

async function scanSources(sources: string[], options: ScanOptions, config: Config): Promise<ScanResult>
TypeScript

Use scanSources to scan one or more source directories and get back a unified list of API elements ready for documentation generation.

This is the core orchestration step in a skrypt generate pipeline — call it after you've resolved your configuration but before you pass elements to the AI doc generator. It handles the full sweep: resolving which directories to scan, applying language and filter rules, and returning a flat, normalized collection of extracted API signatures.

Under the hood, scanSources merges sources from three possible origins — CLI arguments, an --org flag, or your config file — then applies your filter options and walks each directory recursively to extract typed API elements.

Parameters

NameTypeRequiredDescription
sourcesstring[]YesPaths to the source directories or files to scan. Pass an empty array to fall back to sources defined in config.
optionsScanOptionsYesControls what gets extracted — language filters, glob patterns to exclude, and whether to scan recursively.
configConfigYesYour resolved skrypt config object. Used as the fallback source list and carries provider/output settings downstream.

Returns

Returns a Promise<ScanResult> containing the full list of extracted APIElement objects and metadata about the scan (files visited, elements found, any parse errors). Pass result.elements directly to your doc generation step to produce MDX output.

Heads up

  • If you pass both sources and have sources defined in config, the CLI sources array takes precedence — config sources are only used when sources is empty.
  • Parse errors in individual files are collected into result.errors rather than thrown, so always check that field before assuming the element list is complete.

Example:

import { promises as fs } from "fs";
import * as path from "path";

// --- Inline types (do not import from autodocs) ---

interface ScanOptions {
  languages?: string[];
  exclude?: string[];
  recursive?: boolean;
  byTopic?: boolean;
}

interface Config {
  output: string;
  provider: string;
  sources?: string[];
}

interface APIElement {
  name: string;
  kind: "function" | "class" | "type" | "constant";
  signature: string;
  filePath: string;
  language: string;
  docstring?: string;
}

interface ScanResult {
  elements: APIElement[];
  filesVisited: number;
  errors: Array<{ file: string; message: string }>;
}

// --- Mock implementation of scanSources ---

async function scanSources(
  sources: string[],
  options: ScanOptions,
  config: Config
): Promise<ScanResult> {
  const resolvedSources = sources.length > 0 ? sources : (config.sources ?? []);

  // Simulate scanning — in production this walks the FS and parses ASTs
  const mockElements: APIElement[] = resolvedSources.flatMap((src) => [
    {
      name: "createPayment",
      kind: "function",
      signature: "async function createPayment(amount: number, currency: string): Promise<Payment>",
      filePath: path.join(src, "payments.ts"),
      language: "typescript",
      docstring: "Creates a new payment intent and returns the client secret.",
    },
    {
      name: "PaymentClient",
      kind: "class",
      signature: "class PaymentClient { constructor(apiKey: string) }",
      filePath: path.join(src, "client.ts"),
      language: "typescript",
    },
  ]);

  const filtered = mockElements.filter((el) =>
    options.languages ? options.languages.includes(el.language) : true
  );

  return {
    elements: filtered,
    filesVisited: resolvedSources.length * 4,
    errors: [],
  };
}

// --- Usage ---

async function main() {
  const config: Config = {
    output: "./docs/content",
    provider: "openai",
    sources: ["./src/core"],
  };

  const options: ScanOptions = {
    languages: ["typescript"],
    exclude: ["**/*.test.ts", "**/node_modules/**"],
    recursive: true,
  };

  try {
    const result = await scanSources(["./src/payments", "./src/auth"], options, config);

    if (result.errors.length > 0) {
      console.warn("Parse errors encountered:", result.errors);
    }

    console.log(`Scanned ${result.filesVisited} files, found ${result.elements.length} API elements`);
    // → Scanned 8 files, found 4 API elements

    console.log("Elements ready for doc generation:");
    result.elements.forEach((el) => {
      console.log(`  [${el.kind}] ${el.name} — ${el.filePath}`);
    });
    // → [function] createPayment — ./src/payments/payments.ts
    // → [class]    PaymentClient — ./src/payments/client.ts
    // → [function] createPayment — ./src/auth/payments.ts
    // → [class]    PaymentClient — ./src/auth/client.ts
  } catch (err) {
    console.error("Scan failed:", err);
    process.exit(1);
  }
}

main();
TypeScript
Was this helpful?