@burojs/core
v0.2.0
Published
Buro: types, builder, registry, action dispatcher
Readme
@burojs/core
The declarative heart of buro: resource/app definitions, the field builder, the registry, and the action dispatcher.
Zero runtime dependencies, and it imports React nowhere — this package is plain data and pure functions, so it can be consumed from a server, a test, or any UI layer.
Install
pnpm add @burojs/core @burojs/field-typesUsage
A complete CRUD resource — list, show, edit, create, sidebar placement, labels, search and column selection — is a single declaration:
import { defineApp } from '@burojs/core';
import { defineResource } from '@burojs/field-types';
const company = defineResource(
'company',
{
label: { single: 'Company', plural: 'Companies' },
displayField: 'name',
fields: (f) => ({
id: f.number({ system: true, label: 'ID' }),
name: f.string({ label: 'Name' }),
created_at: f.dateTime({ system: true, label: 'Created' }),
}),
views: { list: { columns: ['id', 'name', 'created_at'], search: { fields: ['name'] } } },
},
);
const app = defineApp({ name: 'admin' });
app.use(company);Point a resource at a non-default data provider by declaring it — no wiring:
defineResource('schedules', { meta: { dataProviderName: 'temporal' } /* … */ });Portable declaration kernel
For framework-neutral configuration, register a small open kind and compile portable declarations into an immutable snapshot. Relative declaration references are installed in the layer namespace; use namespace:id when the reference is intentionally cross-namespace.
import {
compileApplicationDefinition,
createKindRegistry,
defineTrustedBundle,
} from '@burojs/core';
interface ResourceInput {
readonly label: string;
}
function parseResource(value: unknown): ResourceInput {
if (
value === null
|| typeof value !== 'object'
|| Array.isArray(value)
|| Object.keys(value).length !== 1
|| !Object.prototype.hasOwnProperty.call(value, 'label')
|| !('label' in value)
|| typeof value.label !== 'string'
) {
throw new TypeError('A resource must contain exactly one string label.');
}
return { label: value.label };
}
const resourceKind = {
kind: 'resource',
schemaVersion: 1,
schema: { parse: parseResource },
compile: (value: ResourceInput) => ({ label: value.label }),
};
const catalog = defineTrustedBundle({
defaultNamespace: 'catalog',
declarations: [{ kind: 'resource', ref: 'products', schemaVersion: 1, value: { label: 'Products' } }],
implementations: [],
handle: { source: 'catalog' },
});
const result = compileApplicationDefinition({
compilerVersion: 'my-app-v1',
kinds: createKindRegistry([resourceKind]),
layers: [{
id: 'catalog',
priority: 0,
defaultNamespace: catalog.defaultNamespace,
declarations: catalog.declarations,
}],
});
if (result.ok) {
result.snapshot.getProjection({ kind: 'resource', ref: 'catalog:products' });
}defineTrustedBundle() keeps trusted implementation definitions alongside declarations for the application runtime, but snapshot.manifest is deliberately portable: it contains no functions, components, services, credentials, or implementation objects. It can therefore be JSON-serialized safely after the application applies its own XSS-safe transport.
The runtime declaration exports are normalizeEntityRef, formatEntityRef, sameEntityRef, EntityRefError, defineTrustedBundle, isTrustedDeclarationBundle, createKindRegistry, compileApplicationDefinition, DEFAULT_COMPILER_LIMITS, createApplicationSnapshot, and explainSnapshot.
Main exports
defineApp/extendResource— the application declaration surface. Core's low-leveldefineResourceis fieldless; use@burojs/field-types' bounddefineResource, orcreateResourceFactory(builder)for a composed custom builder, when declaring fields.defineGroup/defineSection/defineCustomPage— navigation structure and non-resource pages.defineEnum/defineDocumentTemplate/defineResourceWizard— enum registries, document templates, multi-step create flows.createRegistry/createFieldBuilder/createFieldRegistry— the registry primitives the above compose.createDispatcher— turns an action invocation into anActionResult(notify / refetch / redirect / clearSelection …) that a UI layer applies.evaluateVisible— the shared predicate evaluator behind field, column and nav visibility.- Data-access ports —
ActionDataAccessandCountCapable(getCount?, the on-demand row count), declared here precisely because this package has no dependencies.
License
MIT
