Skip to content

v0.2.6

Choose a tag to compare

@github-actions github-actions released this 28 Aug 15:18
· 114 commits to main since this release

Drop the README paragraph for an option that no longer exists

japaPlugins: true was removed from the rc file in 0.2.1 and its wiring
is gone from the runner's CLI. The README still explained how to turn it
on and what it would do.

The remaining mentions of the upstream runner are rewritten to name what
ream actually hands its suites to.

Reject any unknown tests option, and name the runner helix

The rc file used to swallow an option nobody reads. TypeScript's
excess-property check only fires on an object literal, so a key arriving
through a variable or a spread — renamed between versions, removed, or
simply mistyped — sat there doing nothing while the run behaved as if it
had never been written. defineConfig now names every unrecognised key
and lists what the block accepts, which is also the answer to "then
where did my option go".

That replaces the previous attempt, which declared the one removed
option by name to carry a migration hint. Naming another framework's
runner in ream's public types is exactly what the surface is not
supposed to do, and a general check answers the same question without
it.

The rest is naming: the runner named throughout the test-client comments
is helix.

Key the is namespace the way AdonisJS keys it

AdonisJS re-exports @sindresorhus/is, whose members read is.string(v),
is.plainObject(v), is.nonEmptyArray(v). This object mirrored the
standalone function names instead — is.isString(v) — which stutters,
and which turns is.string(value) ported from an Adonis app into
"is.string is not a function" at runtime rather than a compile error.
Same shape of trap as compose: a name that exists on both sides and
means something else here.

The keys are renamed, not aliased. Keeping both would keep the stutter
alive, and the standalone isX functions are untouched — they read
correctly on their own, and this object is the namespace form.

Five members the AdonisJS documentation uses in its own examples were
missing and are added: nonEmptyString, nonEmptyArray, integer,
positive, hasProperty. hasProperty reports OWN properties only —
an inherited toString is not something the caller put there, and
treating it as present is how a prototype member gets read as data.

empty stays a named deviation: @sindresorhus/is has emptyString /
emptyArray / emptyObject / emptyMap / emptySet and no umbrella.

Point at the replacement when an rc file still carries japaPlugins

tests.japaPlugins existed in 0.2.0 and went away in 0.2.1, when the
ream↔helix bridge moved to @c9up/helix-plugin-ream and ream stopped
knowing about its test runner. It went away with no signpost: an rc file
carrying it simply stopped compiling, with an excess-property error that
names the key and nothing else.

The key is declared again, typed
RemovedIn_0_2_1_MovedToHelixPluginReamnever under a name that
says why, because "Type 'boolean' is not assignable to type 'never'"
tells nobody where the option went. The @deprecated tag carries the
migration on hover.

defineConfig also refuses it at runtime, for the value that reached it
through a variable, a spread, or plain JavaScript, where the type never
fires and a removed option would silently do nothing.

Stop compose meaning two opposite things

In AdonisJS compose is mixin composition — compose(BaseModel, SoftDeletes) — exported from @adonisjs/core/helpers. Here the name was
taken on the main barrel by the middleware pipeline composer, so that
line ported from an Adonis app resolved to something with an entirely
different meaning and failed somewhere unrelated.

helpers/compose is now the mixin one, at Adonis's location and with
its semantics. It was the only member missing from the helpers barrel
against @adonisjs/core/helpers.

The middleware composer becomes composeMiddleware. Nothing outside
this package imported it — three internal call sites and one barrel
export — so the rename costs nothing and the two can no longer be one
import away from each other.

The overloads carry the return type of the LAST mixin rather than the
base class; without them a composed class loses every member the mixins
added, statics included, which the test asserts in both directions.
There is deliberately no Constructor bound: the mixin's own parameter
type already constrains what can be passed, and the bound could only be
written with any.

Add the service accessors for bindings that already existed

config, encryption and the URL helpers were in the container and in
ContainerBindings, but there was no services/* module to reach them
by — so a route file or a controller had to go through
app.container.make(), which is async, to read something the framework
had already built.

services/config keeps no instance: the store IS app.config, so it
reads through the app locator. A second copy would survive a re-boot
that replaced the app and hand out a store nothing else is writing to.

services/encryption is registered only when APP_KEY is set — that is
its normal absent state, not a boot-ordering mistake — so it names the
key rather than the boot phase. The Ignitor now holds the signer so
stop() can release the locator against the exact instance it
installed; an unguarded clear would tear down a newer Ignitor's binding.

services/urlBuilder exports urlFor and signedUrlFor as functions
rather than a proxy, because that is all the URL builder is. Both
delegate to the router, so a renamed route cannot mean two things.

Both export maps carry the three subpaths — the src/dist pair the
export-map test exists to keep in step.


Changes since v0.2.5.