mcpField
A
atscript

atscript

github.com/moostjsDevelopment244 installsUpdated 2w ago
Repository

About atscript

atscript is a language-agnostic schema language and toolchain for defining types, metadata, and validation in `.as` files. Its TypeScript compiler generates declarations and runtime metadata for validation, JSON Schema, serialization, and related consumers.

Key features

  1. 01Single-source `.as` definitions
  2. 02TypeScript declarations and runtime code generation
  3. 03Metadata and validation support
  4. 04JSON Schema and serialization helpers
  5. 05Plugin-based annotation namespaces
  6. 06CLI and editor integrations

Use cases

  1. 01Define shared types and metadata
  2. 02Generate TypeScript declarations from `.as` files
  3. 03Validate data and produce JSON Schema
  4. 04Integrate `.as` models into build workflows

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/moostjs/atscript --skill atscript

After installing, type/atscriptin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

references/
annotations.md
as-syntax.md
asc-cli.md
codegen.md
config.md
getting-started.md
moost-validator.md
plugin-development.md
primitives.md
runtime.md
unplugin.md
validation.md
vscode.md

Details

From the project README

atscript

.as = single source of truth for types + metadata + validation. @atscript/typescript compiles .as → .d.ts (types) + .js (runtime metadata). Consumers use those for validation, JSON Schema, serialization, ORM mapping.

Language-agnostic. Core ships @meta.*, @expect.*, @emit.*; @db.*, @ui.*, and custom namespaces come from plugins.

Quick start

npm install @atscript/typescript @atscript/core

atscript.config.{ts,mts,cts,js,mjs,cjs} at project root:

import { defineConfig } from '@atscript/core'
import ts from '@atscript/typescript'

export default defineConfig({
  rootDir: './src',
  plugins: [ts()],
})

Build:

npx asc            # emits .d.ts (default) + project-wide atscript.d.ts
npx asc -f js      # emits runtime .js metadata

Full walkthrough with a first .as file, consume snippet, and troubleshooting → getting-started.md.

Key imports

// Config
import { defineConfig, AnnotationSpec } from '@atscript/core'
import type { TAtscriptPlugin, TAtscriptConfig } from '@atscript/core'

// Plugin factory (build-time only)
import ts from '@atscript/typescript'

// Runtime helpers (used by generated .as.js — also available to consumers)
import {
  defineAnnotatedType,             // fluent builder (in generated code)
  forAnnotatedType,                // kind-dispatched walker
  Validator, ValidatorError,
  buildJsonSchema, fromJsonSchema, mergeJsonSchemas, detectDiscriminator,
  serializeAnnotatedType, deserializeAnnotatedType, SERIALIZE_VERSION,
  isAnnotatedType, isAnnotatedTypeOfPrimitive,
} from '@atscript/typescript/utils'
import type { TAtscriptAnnotatedType, TValidatorPlugin } from '@atscript/typescript/utils'

// Test fixtures (compile .as at test-time, inject tsPlugin automatically)
import { prepareFixtures } from '@atscript/typescript/test-utils'

// Moost HTTP integration
import { coercionPipe, validatorPipe, validationErrorTransform } from '@atscript/moost-validator'

// Bundler integration (pick one)
import atscript from 'unplugin-atscript/vite'      // or /rollup /rolldown /webpack /esbuild /rspack /farm

Invariants

  1. @meta.id takes no arguments. Multiple @meta.id on different props = composite PK. Never @meta.id(...).
  2. Generated files (*.as.d.ts, *.as.js, atscript.d.ts) are never hand-edited. Fix the .as source or plugin. Regenerate with npx asc -f dts.
  3. Core ships @meta.*, @expect.*, @emit.* only. All other namespaces come from plugins.
  4. asc without -f runs every plugin's default output (TS plugin emits .d.ts). Pass -f js for runtime .js (or let unplugin-atscript produce it at bundle time).
  5. @atscript/typescript/utils is the runtime entry; @atscript/typescript default export is tsPlugin() (build-time factory).
  6. Never import type a compiled .as artifact. .as exports are classes — value AND type in one name — consumed at runtime (.validator(), .metadata, decorators, DI by param type via design:paramtypes). A type-only import elides the value: decorator metadata emits Object and validation/DI/form binding break silently. Keep lint rules that force type-only imports (typescript/consistent-type-imports and equivalents) off in projects importing .as files — the create-moost preset and ecosystem repos already disable it.

Dependency chain

@atscript/core          parser, AST, plugin system, diagnostics
  └─ @atscript/typescript    codegen + runtime + asc CLI
       ├─ @atscript/moost-validator   Moost pipe + error transform
       └─ unplugin-atscript           Vite/Rollup/Rolldown/Webpack/esbuild/Rspack/Farm
  └─ @atscript/vscode     LSP, syntax, completions, go-to-def

DB layer (@atscript/db, db-sqlite, db-mongo, db-mysql, moost-db, @db.*, schema sync, relations, views): separate repo at https://db.atscript.dev. UI layer (@atscript/ui, vue-form, vue-table, Moost workflow, @ui.*): separate repo.

Companion skills:

npx skills add moostjs/atscript      # this skill (core/typescript/unplugin/vscode/moost-validator)
npx skills add moostjs/atscript-db   # DB layer
npx skills add moostjs/atscript-ui   # UI layer

References — load only what's needed

DomainFileWhen
First contactgetting-started.mdInstall, first .as, first codegen run, consume snippet, troubleshooting
.as syntaxas-syntax.mdinterface/type, unions, intersections, tuples, arrays, imports, pattern properties, annotate blocks
Annotationsannotations.md@meta.*, @expect.*, merge, custom AnnotationSpec, query / expr / order args (backtick expressions, arithmetic, orderings, operators inside parentheses, "Expected operator after field reference"), editor hooks on args (fieldScope, refFilter — completion/hover/F12 inside args)
Primitivesprimitives.mdBuilt-ins, semantic extensions, decimal, phantom, extending via config
Configconfig.mdatscript.config.*, defineConfig, entries/globs, plugin wiring, output, models (packaged models for db sync, models: () => import(...))
asc CLIasc-cli.mdasc, -f, -c, --noEmit, --skipDiag, scripts, "Nothing emitted" / errors block the emit, atomic writes, db sync flags (--check, --format), complete-inventory rule ("Could not load N compiled model module(s)", ERR_MODULE_NOT_FOUND, nested .as imports) + pointer
Codegencodegen.md.as → .d.ts/.js, atscript.d.ts global AtscriptMetadata
Runtimeruntime.mddefineAnnotatedType, TAtscriptAnnotatedType, forAnnotatedType, serialize, refDepth
Validationvalidation.mdValidator, ValidatorError, coerceForType, JSON Schema helpers, plugins
Build integrationunplugin.mdVite/Rollup/Rolldown/Webpack/esbuild/Rspack/Farm, HMR, strict, root (config discovered from the wrong cwd, pnpm -C, unknown @db.*/@ui.* annotations), optimizeDeps prebundling of @atscript/typescript/utils ("optimized dependencies changed. reloading"), stale .as import after moving/retyping a model (dev server keeps the old field type, "requires string" on reload while asc/tsc pass, watchChange cache invalidation), dts bundling of .as re-exports (tsdown/rolldown-plugin-dts)
Moost integrationmoost-validator.mdMoost pipes (validation + param/query coercion), error transform
VSCodevscode.mdExtension, LSP features, config autodiscovery
Plugin authoringplugin-development.mdTAtscriptPlugin, AnnotationSpec, render/buildEnd

Full docs: https://atscript.dev.

Comments

Markdown supported