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

@arkts/vfs

v1.1.5

Published

A Map based ArkTS Virtual File System.

Downloads

19

Readme

ArkTS VFS

A Map based ArkTS Virtual File System.

Useful when you need to:

  • Run ArkTS in the browser
  • Run virtual ArkTS environments where files on disk aren't the source of truth

⚠️ Different from TypeScript VFS

This package is different from TypeScript VFS in the following ways:

  • When the source file fileName ends with .ets, it will be treated as an ArkTS file, the ScriptKind will be 8 (ets.ScriptKind.ETS).
  • The ets.createSourceFile has the sixth parameter options (the compiler options), when the user uses the createVirtualTypeScriptEnvironment function and sets the compilerOptions parameter, the compilerOptions will be passed to the ets.createSourceFile function.

Usage

You start with creating a map which represents all the files in the virtual ts.System:

import { createSystem } from '@arkts/vfs'

const fsMap = new Map<string, string>()
fsMap.set('index.ts', 'const a = "Hello World"')

const system = createSystem(fsMap)

Then you can create a virtual ArkTS Environment:

import { createSystem, createVirtualTypeScriptEnvironment } from '@arkts/vfs'
import ts from 'ohos-typescript'

const fsMap = new Map<string, string>()
const system = createSystem(fsMap)

const compilerOpts = {}
const env = createVirtualTypeScriptEnvironment(system, ['index.ts'], ts, compilerOpts)

// You can then interact with the languageService to introspect the code
env.languageService.getDocumentHighlights('index.ts', 0, ['index.ts'])

When working in tests, or in environments with file system access, you can switch your virtual system with ts.sys to use the real filesystem with the virtual environment.

API

You're most likely interested in the API available in env.languageService, here it is as of 3.7.4:

interface LanguageService {
  cleanupSemanticCache(): void
  getSyntacticDiagnostics(fileName: string): DiagnosticWithLocation[]
  getSemanticDiagnostics(fileName: string): Diagnostic[]
  getSuggestionDiagnostics(fileName: string): DiagnosticWithLocation[]
  getCompilerOptionsDiagnostics(): Diagnostic[]
  getEncodedSyntacticClassifications(fileName: string, span: TextSpan): Classifications
  getEncodedSemanticClassifications(fileName: string, span: TextSpan): Classifications
  getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions | undefined): WithMetadata<CompletionInfo> | undefined
  getCompletionEntryDetails(fileName: string, position: number, name: string, formatOptions: FormatCodeOptions | FormatCodeSettings | undefined, source: string | undefined, preferences: UserPreferences | undefined): CompletionEntryDetails | undefined
  getCompletionEntrySymbol(fileName: string, position: number, name: string, source: string | undefined): symbol | undefined
  getQuickInfoAtPosition(fileName: string, position: number): QuickInfo | undefined
  getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan | undefined
  getBreakpointStatementAtPosition(fileName: string, position: number): TextSpan | undefined
  getSignatureHelpItems(fileName: string, position: number, options: SignatureHelpItemsOptions | undefined): SignatureHelpItems | undefined
  getRenameInfo(fileName: string, position: number, options?: RenameInfoOptions): RenameInfo
  findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, providePrefixAndSuffixTextForRename?: boolean): readonly RenameLocation[] | undefined
  getSmartSelectionRange(fileName: string, position: number): SelectionRange
  getDefinitionAtPosition(fileName: string, position: number): readonly DefinitionInfo[] | undefined
  getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan | undefined
  getTypeDefinitionAtPosition(fileName: string, position: number): readonly DefinitionInfo[] | undefined
  getImplementationAtPosition(fileName: string, position: number): readonly ImplementationLocation[] | undefined
  getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] | undefined
  findReferences(fileName: string, position: number): ReferencedSymbol[] | undefined
  getDocumentHighlights(fileName: string, position: number, filesToSearch: string[]): DocumentHighlights[] | undefined
  getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string, excludeDtsFiles?: boolean): NavigateToItem[]
  getNavigationBarItems(fileName: string): NavigationBarItem[]
  getNavigationTree(fileName: string): NavigationTree
  getOutliningSpans(fileName: string): OutliningSpan[]
  getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[]
  getBraceMatchingAtPosition(fileName: string, position: number): TextSpan[]
  getIndentationAtPosition(fileName: string, position: number, options: EditorOptions | EditorSettings): number
  getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions | FormatCodeSettings): TextChange[]
  getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[]
  getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[]
  getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion | undefined
  isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean
  getJsxClosingTagAtPosition(fileName: string, position: number): JsxClosingTagInfo | undefined
  getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan | undefined
  toLineColumnOffset(fileName: string, position: number): LineAndCharacter
  getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: readonly number[], formatOptions: FormatCodeSettings, preferences: UserPreferences): readonly CodeFixAction[]
  getCombinedCodeFix(scope: CombinedCodeFixScope, fixId: object, formatOptions: FormatCodeSettings, preferences: UserPreferences): CombinedCodeActions
  applyCodeActionCommand(action: CodeActionCommand, formatSettings?: FormatCodeSettings): Promise<ApplyCodeActionCommandResult>
  applyCodeActionCommand(action: CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise<ApplyCodeActionCommandResult[]>
  applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]>
  getApplicableRefactors(fileName: string, positionOrRange: number | TextRange, preferences: UserPreferences | undefined): ApplicableRefactorInfo[]
  getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string, preferences: UserPreferences | undefined): RefactorEditInfo | undefined
  organizeImports(scope: OrganizeImportsScope, formatOptions: FormatCodeSettings, preferences: UserPreferences | undefined): readonly FileTextChanges[]
  getEditsForFileRename(oldFilePath: string, newFilePath: string, formatOptions: FormatCodeSettings, preferences: UserPreferences | undefined): readonly FileTextChanges[]
  getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean, forceDtsEmit?: boolean): EmitOutput
  getProgram(): Program | undefined
}

Usage

When working with Web

It's very likely that you will need to set up your lib *.d.ts files to use this.

If you are running in an environment where you have access to the node_modules folder, then you can can write some code like this:

function getLib(name: string) {
  const lib = dirname(require.resolve('ohos-typescript'))
  return readFileSync(join(lib, name), 'utf8')
}

function addLib(name: string, map: Map<string, string>) {
  map.set(`/${name}`, getLib(name))
}

function createDefaultMap2015() {
  const fsMap = new Map<string, string>()
  addLib('lib.es2015.d.ts', fsMap)
  addLib('lib.es2015.collection.d.ts', fsMap)
  addLib('lib.es2015.core.d.ts', fsMap)
  addLib('lib.es2015.generator.d.ts', fsMap)
  addLib('lib.es2015.iterable.d.ts', fsMap)
  addLib('lib.es2015.promise.d.ts', fsMap)
  addLib('lib.es2015.proxy.d.ts', fsMap)
  addLib('lib.es2015.reflect.d.ts', fsMap)
  addLib('lib.es2015.symbol.d.ts', fsMap)
  addLib('lib.es2015.symbol.wellknown.d.ts', fsMap)
  addLib('lib.es5.d.ts', fsMap)
  return fsMap
}

This list is the default set of definitions (it's important to note that different options for target or lib will affect what this list looks like) and you are grabbing the library's content from the local dependency of ArkTS.

Keeping on top of this list is quite a lot of work, so this library ships functions for generating a map with with these pre-filled from a version of ArkTS available on disk.

Note: it's possible for this list to get out of sync with ArkTS over time. It was last synced with ArkTS 3.8.0-rc.

import { createDefaultMapFromNodeModules } from '@arkts/vfs'
import ts from 'ohos-typescript'

const fsMap = createDefaultMapFromNodeModules({ target: ts.ScriptTarget.ES2015 })
fsMap.set('index.ts', 'const hello = \'hi\'')
// ...

If you don't have access to node_modules, then you can use the ArkTS CDN or unpkg to fetch the lib files. This could be up to about 1.5MB, and you should probably store the values in localStorage so that users only have to grab it once.

This is handled for you via createDefaultMapFromCDN.

import { createDefaultMapFromCDN } from '@arkts/vfs'
import lzstring from 'lz-string'
import ts from 'ohos-typescript'

async function start() {
  const shouldCache = true
  // This caches the lib files in the site's localStorage
  const fsMap = await createDefaultMapFromCDN({ target: ts.ScriptTarget.ES2015 }, '3.7.3', shouldCache, ts)

  // This stores the lib files as a zipped string to save space in the cache
  const otherMap = await createDefaultMapFromCDN({ target: ts.ScriptTarget.ES2015 }, '3.7.3', shouldCache, ts, lzstring)

  fsMap.set('index.ts', 'const hello = \'hi\'')
  // ...
}

start()

The CDN cache:

  • Automatically purges items which use a different version of ArkTS to save space
  • Can use a copy of the lz-string module for compressing/decompressing the lib files

When working with node

If you can reliably access the file-system, then you can have a simpler time:

const compilerOpts: ts.CompilerOptions = { target: ts.ScriptTarget.ES2016, esModuleInterop: true }
const fsMap = new Map<string, string>()

// If using imports where the types don't directly match up to their FS representation (like the
// imports for node) then use triple-slash directives to make sure globals are set up first.
const content = `/// <reference types="node" />\nimport * as path from 'path';\npath.`
fsMap.set('index.ts', content)

// By providing a project root, then the system knows how to resolve node_modules correctly
const projectRoot = path.join(__dirname, '..')
const system = createFSBackedSystem(fsMap, projectRoot)
const env = createVirtualTypeScriptEnvironment(system, ['index.ts'], ts, compilerOpts)

// Requests auto-completions at `path.|`
const completions = env.languageService.getCompletionsAtPosition('index.ts', content.length, {})

createFSBackedSystem will let you hover a virtual environment on top of the file system at a particular path.

A full example

What does a full example look like? This comes basically verbatim from the ArkTS Sandbox codebase:

import tsvfs from '@arkts/vfs'
import lzstring from 'lz-string'
import ts from 'ohos-typescript'

const fsMap = await tsvfs.createDefaultMapFromCDN(compilerOptions, ts.version, true, ts, lzstring)
fsMap.set('index.ts', '// main ArkTS file content')

const system = tsvfs.createSystem(fsMap)
const host = tsvfs.createVirtualCompilerHost(system, compilerOptions, ts)

const program = ts.createProgram({
  rootNames: [...fsMap.keys()],
  options: compilerOptions,
  host: host.compilerHost,
})

// This will update the fsMap with new files
// for the .d.ts and .js files
program.emit()

// Now I can look at the AST for the .ts file too
const index = program.getSourceFile('index.ts')

Using this Dependency

This package can be used as a commonjs import, an esmodule and directly via a script tag which edits the global namespace. All of these files are embedded inside the released packages.