@burojs/config
v0.5.0
Published
Buro: inert JSON and YAML declaration sources
Readme
@burojs/config
Inert JSON and YAML declaration sources for buro.
Parses a raw JSON or YAML string against a host-owned SourcePolicy and
produces a portable declaration layer that carries the policy's grants — or a
list of diagnostics if the source is malformed, oversized, or requests
something its policy doesn't allow. Source here is a configuration source — a
JSON or YAML document a host loads into a layer runtime — not a screen's with
source. The output can only ever be data: no
functions, components, schemas, credentials, or provider/action/mapper bindings
survive the parse.
Install
pnpm add @burojs/configUsage
import { parseJsonLayer, type SourcePolicy } from '@burojs/config';
const policy: SourcePolicy = {
grants: {
allowedKinds: ['resource'],
allowedNamespaces: ['crm'],
allowedTransformOps: [],
maxTransformScope: 'layer',
writePaths: {},
allowedResources: [],
allowedQueries: [],
allowedFlows: [],
allowedBackends: ['company'],
allowedBlocks: [],
allowedFrames: [],
allowedInlineFlows: [],
allowedFieldImplementations: [],
priority: { min: 0, max: 0 },
},
allowedCapabilities: {},
limits: { maxBytes: 16_000, maxDeclarations: 12, maxDepth: 16, maxNodes: 1_000, maxStringLength: 1_000, maxDiagnostics: 8 },
};
const source = JSON.stringify({
id: 'static-catalog',
priority: 0,
defaultNamespace: 'crm',
revision: 'r1',
declarations: [
{ kind: 'resource', ref: 'company', schemaVersion: 2, value: { name: 'company' } },
],
});
const result = parseJsonLayer(source, policy);
if (!result.ok) throw new Error(result.diagnostics.map((d) => d.code).join(', '));
// result.value is a ParsedLayer carrying the grants of `policy`:
await runtime.publishLayer(result.value);To load a source lazily instead of publishing it up front, give
createConfigRuntimeSource the policy and a load that returns the document's
text; it parses each load under the policy, and returns the runtime source with
the trust to register it under:
const configured = createConfigRuntimeSource('catalog', {
policy,
load: async () => ({ format: 'json', text: await fetch('/config/catalog.json').then((r) => r.text()) }),
});
runtime.registerSource(configured.source, configured.trust);The parser checks keys (it refuses action, component, validator and the
other code-bearing keys), the trusted-attachment capabilities in
allowedCapabilities, and the limits; those checks are parser-only. The
compiler enforces the grants — the kinds, namespaces and transform operations
a layer uses, the paths a transform may write (writePaths, no default), its
targets, its references (allowedResources, allowedQueries,
allowedFlows), its backend bindings (allowedBackends) and its priority
band. Use a band strictly away from your code's priorities to fix whether a
parsed layer applies before or after your code. See the "Grants and trust"
section of the guide linked below.
Main exports
parseJsonLayer/parseYamlLayer— parse a source string against aSourcePolicy, returning aParseResult.createConfigRuntimeSource(id, { policy, load })— returns{ source, trust }: a coreRuntimeSourcethat loads and parses a document on demand, and the policy's grants to register it with.SourcePolicy/SourceLimits—{ grants, allowedCapabilities, limits }, what a host allows one untrusted source:grants(the coreLayerGrants) is what its parsed layers carry;SCREEN_SOURCE_LIMITSis a preset for sources that carry whole screen trees.
See docs/raw-config-manifests.md for the full source-policy boundary and how it composes with a LayerRuntime.
License
MIT
