One foundation for Node and the browser
CKN Core puts the repetitive work of business software in one place: tables, API calls, real-time messaging, calculations and security, with no third-party runtime dependency. Every other CKN package builds on it, so your team writes less code, audits less code and owns the whole stack.
What CKN Core does
Tables and models
Work with tabular data in memory almost like light SQL, and turn it into models for your API and your database.
- Table: where, join, groupBy, pivot, aggregate
- Export to CSV, Markdown and HTML in chunks
- Model with audit fields, camelCase and snake_case mapping
- CSV and XML readers and JSON Schema validation built in
Network clients
HTTP and WebSocket clients with timeouts, retries and size caps, so your service does not hang when a partner system misbehaves.
- Api: GET, POST, PUT, PATCH, DELETE with bearer tokens
- Retry with backoff and Retry-After support
- Socket: automatic reconnect and a bounded message queue
- Streaming responses and server-sent events
Secure by default
Common risks are handled at the lowest layer: unsafe URLs, and secrets leaking into logs.
- assertSafeUrl blocks private networks and disallowed protocols
- redactSecrets masks tokens and passwords in logs
- sha256, hmacSha256 and UUID via the standard crypto API
- Semaphore, Mutex and RateLimiter to control concurrency
Business calculation and Thai-ready formats
Calculation tools that manufacturing, accounting and logistics use often, with date, currency and text formatting that handles Thai.
- Matrices, regression, BOM explosion and reciprocal cost allocation
- Unit conversion with createUnitConverter
- formatCurrency and formatDate with th-TH and time zones
- Cron expressions with time zones and DST handling
Search, analytics and binary data
Data structures for large-scale search and analytics, built in-house with no outside library.
- Similar-item search with VectorBatch and HnswIndex
- Thai and English keyword search with BM25 (InvertedIndex)
- Graph for routes and dependencies, ColumnFrame for millions of rows
- RunningStats, StreamingQuantile and the CKNB binary format
Real-time collaborative editing
A CRDT document model lets many people edit one document at once, even offline, and every copy converges to the same result.
- DocumentModel: text, list, map, register and counter fields
- Rich text through marks such as bold
- Per-field write permission with canWrite
- Convergence checked by randomised fuzz tests
Measured, not promised
All figures were measured on Node 24 and come from the package's own documentation. Results vary with your hardware and data.
Figures come from CKN's own test suites and benchmarks. Real results depend on each system's hardware and data volume.
What your business gets
Cost and ownership
No third-party runtime dependencies means no recurring licence from hidden libraries, no waiting on someone else's bug fix and no risk of an abandoned package. The source is ours, so we can extend it for you.
Faster delivery
The work teams rewrite on every project, such as tables, reports, API calls and retries, is ready to use, and the same code runs on the server and in the browser. Your team spends its time on your business rules, not on plumbing.
Lower risk
Timeouts, size caps and URL and secret protection are built in, backed by 43 test files and guide examples that are run on every check. The result is a system that is harder to hang and harder to leak from.
Example: call an API, then total sales by region
In use across the CKN stack
- The base of every other CKN Technology package: data, server, ui, ai and providers
- Used inside CKN's business services and platform services
- Powers apps that need shared editing and large-scale search
import { Api, Table } from "@ckn-technology/core";
const api = new Api("https://api.example.com/v1/orders", { cache: false, timeoutMs: 10_000, retries: 2 });
api.setBearerToken(token).setQuery({ status: "open" });
const result = await api.get();
if (!result.ok) throw new Error(`HTTP ${result.status}`);
const orders = Table.toTable(result.data);
for (const [region, group] of orders.groupBy("region")) {
console.log(region, group.count(), group.sum("amount"));
}
const page = orders.query().where((r) => r.amount > 1000).orderByDesc("amount").take(20).toTable();
