npm.io
1.0.4 • Published yesterday

@ruvyxa/core

Licence
MIT
Version
1.0.4
Deps
0
Size
33 kB
Vulns
0
Weekly
0
Stars
1

@ruvyxa/core

Typed primitives shared by the Ruvyxa runtime, CLI package, and first-party adapters.

Install

Most apps import these APIs through ruvyxa. Install this package directly only when writing adapters or low-level integrations.

npm install @ruvyxa/core

Exports

import { defineConfig } from "@ruvyxa/core/config"
import { action, cache, invalidateCache, json, loader, notFound, redirect } from "@ruvyxa/core/server"
import type {
  Adapter,
  AdapterOutput,
  BuildContext,
  PluginContext,
  RuvyxaConfig,
  RuvyxaPlugin,
  TransformResult,
} from "@ruvyxa/core"

Server APIs

Loader with caching
import { loader } from "@ruvyxa/core/server"

export const getPosts = loader(async ({ cache }) => {
  return cache("posts").ttl("5m").get(async () => {
    return await db.posts.findMany()
  })
})
Action with validation
import { action } from "@ruvyxa/core/server"

export const createPost = action
  .input({ parse: (v) => ({ title: String(v.title) }) })
  .handler(async ({ input, invalidate }) => {
    invalidate("posts")
    return await db.posts.create(input)
  })
Cache utility

The cache() function provides real in-memory TTL caching:

import { cache, invalidateCache } from "@ruvyxa/core/server"

// Cache with TTL (supports "30s", "5m", "1h", "1d")
const data = await cache("key").ttl("10m").get(async () => fetchExpensiveData())

// Invalidate by key or prefix
invalidateCache("key")       // exact match
invalidateCache("posts")     // also clears "posts:123"
invalidateCache()            // clear all

Config Shape

import { defineConfig } from "@ruvyxa/core/config"

export default defineConfig({
  appDir: "app",
  outDir: ".ruvyxa",
  server: {
    host: "localhost",
    port: 3000,
  },
  build: {
    minify: true,
    sourcemap: false,
    splitStrategy: "route",
    parallelism: 4,
  },
  cache: {
    routeManifest: true,
    css: true,
  },
})

Adapter Contract

Adapters return metadata describing how a platform should consume .ruvyxa/ output:

import type { Adapter } from "@ruvyxa/core"

export function customAdapter(): Adapter {
  return {
    name: "custom",
    target: "node",
    build(ctx) {
      return {
        name: "custom",
        target: "node",
        platform: "node",
        entry: `${ctx.outDir}/server/app`,
        assetsDir: `${ctx.outDir}/assets`,
      }
    },
  }
}

Plugin Contract

Custom build plugins use the exported RuvyxaPlugin, PluginContext, and TransformResult types:

import type { RuvyxaPlugin } from "@ruvyxa/core"

export function bannerPlugin(): RuvyxaPlugin {
  return {
    name: "banner",
    transform(code, id, ctx) {
      if (ctx.environment !== "client" || !id.endsWith(".tsx")) {
        return null
      }

      return {
        code: `/* client bundle */\n${code}`,
      }
    },
  }
}

This package is published as ESM with generated TypeScript declarations.