Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/allow-astrometry-dependency.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@observerly/orderly': minor
---

Add @observerly/astrometry 0.69.0 as orderly's one runtime dependency, observerly's own library with no runtime dependencies of its own, ahead of the sun schedules built on it; the dependency guard now admits exactly that name and fails the package checks on any other.
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ Single file, no pushing. Type-safe middleware that brings a little bit of order

orderly removes the two failure modes every raw queue consumer carries: messages that are never
decided, and one bad message crashing a whole batch. Every message resolves to exactly one explicit
outcome, every outcome is recorded as an event, and the consumer never rejects. Zero runtime
dependencies.
outcome, every outcome is recorded as an event, and the consumer never rejects. Zero third-party
runtime dependencies.

## Installation

Expand Down Expand Up @@ -358,8 +358,9 @@ subtract(deadline, { days: 1 });
## Requirements

orderly runs on [workerd](https://github.com/cloudflare/workerd) and is tested inside it. It ships
as ESM with TypeScript declarations, requires nothing at runtime, and follows Standard Schema
rather than depending on any validation library.
as ESM with TypeScript declarations and follows Standard Schema rather than depending on any
validation library. Its one runtime dependency is observerly's own `@observerly/astrometry`, which
itself depends on nothing at runtime; a guard fails the package checks should another ever appear.

## Contributing

Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@
"test:watch": "vitest",
"typecheck": "tsc --noEmit && tsc --noEmit -p tests/tsconfig.json && tsc --noEmit -p scripts/tsconfig.json"
},
"dependencies": {
"@observerly/astrometry": "0.69.0"
},
"devDependencies": {
"@arethetypeswrong/cli": "0.18.5",
"@changesets/changelog-github": "1.0.0",
Expand Down
16 changes: 16 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

45 changes: 40 additions & 5 deletions scripts/guard-dependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,51 @@ import process from 'node:process';

/*****************************************************************************************************************/

// orderly ships with zero runtime dependencies, and that is a guarantee rather than a habit. This guard makes the
// guarantee structural: the moment a dependencies key appears in the manifest, the package checks fail, in CI and
// locally alike. devDependencies remain allowed, as they are toolchain-only and never ship.
// orderly ships with no third party runtime dependencies, and that is a guarantee rather than a habit. This guard
// makes the guarantee structural: a dependency outside the one name allowed below fails the package checks, in
// CI and locally alike. devDependencies remain allowed, as they are toolchain-only and never ship.

/*****************************************************************************************************************/

// The one runtime dependency orderly allows itself: observerly's own astrometry, which the sun schedules are
// built on. It carries no runtime dependencies of its own; the types-only package its manifest names ships no
// code. Nothing else may appear here without changing this line and the README sentence that promises it.
const ALLOWED = new Set(['@observerly/astrometry']);

/*****************************************************************************************************************/

const manifest: unknown = JSON.parse(
readFileSync(new URL('../package.json', import.meta.url), 'utf8'),
);

if (typeof manifest === 'object' && manifest !== null && 'dependencies' in manifest) {
/*****************************************************************************************************************/

// The names under dependencies, or none when the key is absent. Anything the key holds that is not a plain
// object of names is refused too, rather than read as nothing.
const dependenciesOf = (candidate: unknown): string[] => {
if (typeof candidate !== 'object' || candidate === null || !('dependencies' in candidate)) {
return [];
}

const { dependencies } = candidate;

if (typeof dependencies !== 'object' || dependencies === null || Array.isArray(dependencies)) {
console.error('package.json declares dependencies that are not a map of names to versions.');

process.exit(1);
}

return Object.keys(dependencies);
};

/*****************************************************************************************************************/

const strangers = dependenciesOf(manifest).filter(name => !ALLOWED.has(name));

if (strangers.length > 0) {
console.error(
'package.json declares a dependencies key: @observerly/orderly ships with zero runtime dependencies.',
`package.json declares runtime dependencies @observerly/orderly does not allow: ${strangers.join(', ')}. ` +
`The only runtime dependency permitted is ${[...ALLOWED].join(', ')}.`,
);

process.exit(1);
Expand Down
Loading