npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

core-ast-ts

v0.3.0

Published

Shared AST library: parse, visit, query, and generate TS/JS code — pure TypeScript, singleton cache, no native binary

Downloads

155

Readme

core-ast-ts

Shared AST library: parse, visit, query, and generate TS/JS code — pure TypeScript, singleton cache, no native binary.

Plugin system: extend core-ast-ts to parse any file format (Vue SFC, Svelte, Astro, etc.) through a unified cache. Plugins are optional — the core stays lightweight. If a plugin is missing, a clear error tells you exactly what to install.

Install

npm install core-ast-ts

Core Design: Plugin Architecture

core-ast-ts uses a plugin system to support file formats beyond JS/TS. The core package only handles .js/.jsx/.ts/.tsx — all other formats are handled by plugins that you register explicitly.

Why plugins?

  • Small core: core-ast-ts doesn't bundle @vue/compiler-sfc, svelte/compiler, etc. Each format plugin is a separate package you install only when needed.
  • Unified cache: All formats share the same singleton cache. Parse once, use everywhere.
  • Clear errors: If you try to parse a .vue file without the vue3 plugin, you get an exact install instruction — not a cryptic parse error.

Usage

import { coreAst } from 'core-ast-ts'
import vue3 from 'core-ast-ts-plugin-vue3'

// Create an AST instance with plugins
const ast = coreAst({ plugins: [vue3()] })

// Parse any file — JS/TS handled by core, .vue handled by plugin
const { ast: program, meta } = ast.get('App.vue', source)
// meta.sfcDescriptor — full Vue SFC descriptor
// meta.componentName — derived from filename
// meta.isSetup — whether <script setup> is used

// JS/TS files work without any plugins
const { ast: jsProgram } = ast.get('app.tsx', source)

// HMR: invalidate on file change
ast.invalidate('App.vue')

Plugin interface

Every plugin implements CoreAstPlugin:

interface CoreAstPlugin {
  /** Unique name, e.g. 'vue3' */
  name: string
  /** File extensions this plugin handles, e.g. ['.vue'] */
  extensions: string[]
  /** Parse source into a ParsedModule with ESTree AST */
  parse(source: string, filePath: string, config?: ParseConfig): ParsedModule
}

A plugin's parse() must return an ESTree-compatible Program node. Format-specific data (e.g. Vue SFC descriptor) is attached to meta on the returned ParsedModule.

Missing plugin error

If you try to parse a .vue file without the vue3 plugin registered:

[core-ast-ts] Cannot parse "App.vue" — no plugin for ".vue" extension.

Install and register the "core-ast-ts-plugin-vue3" plugin:

  npm install core-ast-ts-plugin-vue3

  import { coreAst } from 'core-ast-ts'
  import vue3 from 'core-ast-ts-plugin-vue3'
  const ast = coreAst({ plugins: [vue3()] })

Available plugins

| Plugin | Package | Formats | |--------|---------|---------| | Vue 3 SFC | core-ast-ts-plugin-vue3 | .vue | | Svelte 5 | core-ast-ts-plugin-svelte | .svelte | | Astro | core-ast-ts-plugin-astro | .astro (async — use getAsync()) |

Async plugins

Some compilers (e.g. @astrojs/compiler) have async parse APIs. Use AsyncCoreAstPlugin and ast.getAsync():

import type { AsyncCoreAstPlugin } from 'core-ast-ts'
import astro from 'core-ast-ts-plugin-astro'

const ast = coreAst({ plugins: [astro()] })
// Must use getAsync() for async plugins
const { ast: program, meta } = await ast.getAsync('index.astro', source)

If you call ast.get() on an async plugin, a clear error is thrown:

[core-ast-ts] Plugin "astro" has async parse(). Use ast.getAsync() instead of ast.get().

Writing a custom plugin

import type { CoreAstPlugin } from 'core-ast-ts'
import { parse as parseJsTs } from 'core-ast-ts'

const myPlugin: CoreAstPlugin = {
  name: 'custom',
  extensions: ['.custom'],
  parse(source, filePath, config) {
    // Convert your format to JS, then parse with core
    const jsSource = transformCustomToJs(source)
    const parsed = parseJsTs(jsSource, config)
    return {
      ast: parsed.ast,
      source,
      meta: { originalFormat: 'custom' },
    }
  },
}

const ast = coreAst({ plugins: [myPlugin] })

Ecosystem

These FarmFE plugins use core-ast-ts internally:

| Plugin | Package | Uses | |--------|---------|------| | Compile-time tricks | farm-plugin-tricks | Singleton API (get, invalidate, visitWithAncestors) | | Vue 3 page router | farm-plugin-vue3-pagerouter | Plugin system (coreAst() + core-ast-ts-plugin-vue3) | | Selective compilation | farm-plugin-selective | Singleton API + magic-string | | Compile-time stdlib | farm-plugin-comptime-stdlib | Singleton API + magic-string | | Static optimization | farm-plugin-static-opt | Singleton API + magic-string | | Negotiated obfuscation | farm-plugin-obfuscate | Singleton API + javascript-obfuscator | | Function overloading | farm-plugin-overload | Singleton API + magic-string | | Functional Vue components | farm-plugin-vue-reaction | Plugin system + core-ast-ts-plugin-vue3 |

Legacy API (still supported)

The original singleton cache API still works for JS/TS files:

import { get, invalidate } from 'core-ast-ts'

const { ast } = get('app.tsx', source)
invalidate('app.tsx')

For multi-format support, use the coreAst() API instead.

Full API Reference

Cache (singleton — JS/TS only)

import { get, getCached, invalidate, invalidateAll } from 'core-ast-ts'

const { ast } = get('app.tsx', source)    // parse + cache
const cached = getCached('app.tsx')        // cached only
invalidate('app.tsx')                      // HMR
invalidateAll()                            // clear all

CoreAst (plugin-aware cache)

import { coreAst } from 'core-ast-ts'
import vue3 from 'core-ast-ts-plugin-vue3'

const ast = coreAst({ plugins: [vue3()] })
ast.get('App.vue', source)    // parse + cache (any format)
ast.getCached('App.vue')       // cached only
ast.invalidate('App.vue')      // HMR
ast.invalidateAll()            // clear all
ast.registerPlugin(plugin)     // add plugin later
ast.hasPlugin('vue3')          // check if registered
ast.pluginNames()              // list all

Parse

import { parse } from 'core-ast-ts'

const { ast, source } = parse('export function hello(name: string) { return `Hello, ${name}!` }', {
  jsx: true,
  sourceType: 'module',
})

Visit

import { collectImports, collectExports, visitWithAncestors } from 'core-ast-ts'

const imports = collectImports(ast)
const exports = collectExports(ast)

// Walk with ancestor chain
visitWithAncestors(ast, {
  CallExpression(node, ancestors) {
    // node + full ancestor chain
  },
})

Query

import { ModuleQuery } from 'core-ast-ts'

const query = new ModuleQuery(ast)
query.findFunctions()          // all function declarations
query.findComponents()         // PascalCase functions (React components)
query.findCalls('compileTime') // call sites of a function
query.importsFrom('react')     // check if module imports from 'react'

Transform

import { createTransformer, replaceNode, removeNode, prependPureMarker } from 'core-ast-ts'

const { magic, result } = createTransformer(source, 'app.tsx')
prependPureMarker(magic, functionNode.start)
const { content, sourceMap, changed } = result()

Codegen

import { generateCode } from 'core-ast-ts'

const output = generateCode(ast, { compact: true })

License

MIT