1.0.0 — Extracted into a package of its own

The first release of @bayudwiyansatria/core. The kernel that lived inside an application as src/core/system/ is now a package, so every service that wants this architecture shares one copy rather than forking it.

The extraction was anticipated. That directory's own module documentation said it was "meant to be liftable into a package the other services can share", and an ESLint boundary rule had been enforcing the constraint. It held: across all 45 files, the only import pointing outward was the one documented exception.

This repository previously held the Node.js library template. Its scaffolding was replaced with the newer generation — flat ESLint config, four Rollup outputs with an exports map, the TypeDoc gate — and its placeholder source removed.

What this package provides

Category Exports
Contracts Service, APIResponse
Capabilities Capability, the ten interfaces over it, RequestMetadata, their shapes, the Noop* four
Configuration configure, resolve, systemDefaults, the settings shapes
Observability Logger, LogContext
Security timingSafeEqual
Errors MissingCapabilityError, ConfigurationError
Utilities Signature, Text, Time

42 names in all, from a single entry point. The exports map exposes . and ./package.json and nothing else, so there are no deep import paths to depend on — src/ may be rearranged in a patch release without it being a breaking change.

What changed in the move

configure() replaces the import of src/config/

resolve() used to import the application's configuration directly. That is fine inside one repository and impossible across a package boundary — a package cannot reach into its consumer's source tree.

The application now assembles the surface and hands it over:

configure({ ...systemDefaults, ...platformDefaults }, overrides)

The merge semantics carry over exactly: per field rather than per module, and an override set explicitly to undefined is ignored.

ConfigurationError is new

resolve() throws it for a module registered nowhere, and the message names both ways that happens: configure() has not run yet, or two copies of this package are loaded. The second is the nastier one — the registry is module state, so a duplicate copy means one registry gets seeded and another gets read — and nothing about the stack trace would otherwise suggest a packaging problem.

Returning undefined instead would push the fault downstream to whichever binding first dereferenced the settings, where the message would name the cache rather than the actual cause.

Logger.fromEnv no longer names a platform

It took Env, an ambient global from the runtime it was written for. It now takes { LOG_LEVEL?: string } | null | undefined, which is all it ever needed — and which an environment object, a process.env, or a bare object literal all satisfy. This was the only real reference to a platform type in the whole kernel; every other match was prose in a doc comment.

Signature derives its key type from the runtime

CryptoKey is only an ambient global when a runtime-specific lib (DOM, WebWorker) is in scope, and this package deliberately compiles with neither so anything runtime-specific fails the build. WebCrypto itself is part of the minimum API every target runtime provides, so the value is always there — only the type name is not. The alias is derived from crypto.subtle and never reaches the public surface.

systemDefaults.logging.service

Was the name of the application this came from, now 'app'. An application-specific value had no business being a library default; the placeholder is deliberately generic so an un-overridden deployment reads as unconfigured rather than as some other project.

Kernel purity

An ESLint rule now forbids importing @cloudflare/*, hono, or cloudflare:* anywhere in src/. The boundary that made this extraction possible is worth keeping enforced now that the code has somewhere to be extracted to.

Tests

85 specs: the configure/resolve merge contract including both ConfigurationError paths, timingSafeEqual over the cases an early return would get wrong, Signature sign/verify with a case per forgeable input, Logger threshold and context handling, Service envelopes, the four Noop* capabilities, and MissingCapabilityError including the cross-package instanceof a subclass depends on.

Upgrading

Nothing to upgrade — this is the first release. A service moving off a vendored src/core/ should follow the migration guide published by its adapter package.

results matching ""

    No results matching ""