ensure-running 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +355 -0
- package/dist/bin/ensure-running.js +959 -0
- package/dist/bin/ensure-running.js.map +1 -0
- package/dist/index.cjs +1184 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +356 -0
- package/dist/index.d.ts +356 -0
- package/dist/index.js +1112 -0
- package/dist/index.js.map +1 -0
- package/package.json +72 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ensure-docker-running contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# ensure-running
|
|
4
|
+
|
|
5
|
+
> Chainable CLI to ensure local services are ready before running commands
|
|
6
|
+
|
|
7
|
+
**`er docker postgres -- vite dev` - ensure services, then run your script.**
|
|
8
|
+
|
|
9
|
+
[](#)
|
|
10
|
+
[](./LICENSE)
|
|
11
|
+
[](#)
|
|
12
|
+
[](#)
|
|
13
|
+
[](#)
|
|
14
|
+
[](#)
|
|
15
|
+
|
|
16
|
+
[Get Started](#get-started) • [Features](#features) • [CLI](#cli) • [Services](#services) • [Development](#development)
|
|
17
|
+
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## What Is ensure-running?
|
|
23
|
+
|
|
24
|
+
`ensure-running` is a CLI and library for **chaining readiness checks** before a command runs. Instead of one-off shell scripts per dependency, you compose services on the command line or in `package.json` scripts.
|
|
25
|
+
|
|
26
|
+
```text
|
|
27
|
+
package.json script
|
|
28
|
+
|
|
|
29
|
+
v
|
|
30
|
+
er docker postgres -- vite dev
|
|
31
|
+
|
|
|
32
|
+
+----+----+
|
|
33
|
+
| |
|
|
34
|
+
v v
|
|
35
|
+
docker postgres
|
|
36
|
+
(built-in) (.er/services)
|
|
37
|
+
| |
|
|
38
|
+
+----+----+
|
|
39
|
+
v
|
|
40
|
+
vite dev (spawned with inherited stdio)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
The first built-in service is **Docker**. More built-ins (Postgres, Redis, etc.) can be added under `src/services/`. Projects can also define custom services in `.er/services/`.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Features
|
|
48
|
+
|
|
49
|
+
- **Chainable CLI:** `er docker`, `er docker -- vite dev`, `er docker postgres -- npm test`.
|
|
50
|
+
- **Docker service:** install detection via `docker --version`, daemon checks via `docker info`, cross-platform auto-start.
|
|
51
|
+
- **Custom services:** drop files in `.er/services/` with `export default defineEnsureService({ ... })`.
|
|
52
|
+
- **Library API:** `ensureRunning`, `ensureDocker`, `ensureDockerRunning`, and typed Docker errors from one package.
|
|
53
|
+
- **Service registry:** extensible core with parse/run contracts.
|
|
54
|
+
- **package.json friendly:** one command prefix instead of nested shell scripts.
|
|
55
|
+
- **Fully tested:** mocked `child_process` in unit tests - no real Docker required in CI.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Get Started
|
|
60
|
+
|
|
61
|
+
### Install
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
npm install ensure-running
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### CLI
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
er docker
|
|
71
|
+
er docker --check
|
|
72
|
+
er docker -- vite dev
|
|
73
|
+
ensure-running docker --timeout 60000 -- npm test
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
| Invocation | Behavior |
|
|
77
|
+
|------------|----------|
|
|
78
|
+
| `er docker` | Ensure Docker is installed, started, and ready |
|
|
79
|
+
| `er docker --check` | Exit 0 only when the daemon responds; never auto-start |
|
|
80
|
+
| `er docker -- vite dev` | Ensure Docker, then run `vite dev` |
|
|
81
|
+
| `er docker postgres -- npm test` | Chain services, then run command (postgres = custom or future built-in) |
|
|
82
|
+
|
|
83
|
+
`--` is **required** before the command. Without it, `er docker vite dev` is an error.
|
|
84
|
+
|
|
85
|
+
### Custom services (`.er/services`)
|
|
86
|
+
|
|
87
|
+
Create project-local services that the CLI discovers automatically:
|
|
88
|
+
|
|
89
|
+
```text
|
|
90
|
+
.er/
|
|
91
|
+
services/
|
|
92
|
+
postgres.ts
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
import { defineEnsureService } from "ensure-running";
|
|
97
|
+
|
|
98
|
+
export default defineEnsureService({
|
|
99
|
+
id: "postgres",
|
|
100
|
+
parseArgs(argv) {
|
|
101
|
+
return { options: {}, remaining: argv };
|
|
102
|
+
},
|
|
103
|
+
async run() {
|
|
104
|
+
// wait for postgres, return 0 or 1
|
|
105
|
+
return 0;
|
|
106
|
+
},
|
|
107
|
+
printHelp() {
|
|
108
|
+
console.log("postgres - ensure local Postgres is ready");
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Then chain it like a built-in service:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
er docker postgres -- npm run migrate
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### package.json
|
|
120
|
+
|
|
121
|
+
```json
|
|
122
|
+
{
|
|
123
|
+
"scripts": {
|
|
124
|
+
"dev": "er docker -- vite dev",
|
|
125
|
+
"test:integration": "er docker -- vitest run --config vitest.integration.ts",
|
|
126
|
+
"db:up": "er docker postgres -- npm run migrate"
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Use `--` to separate services from the command. It is required when running a trailing command.
|
|
132
|
+
|
|
133
|
+
### API
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
import {
|
|
137
|
+
ensureRunning,
|
|
138
|
+
runEnsureRunning,
|
|
139
|
+
ensureDocker,
|
|
140
|
+
ensure
|
|
141
|
+
} from "ensure-running";
|
|
142
|
+
|
|
143
|
+
// Chain services (same model as the CLI)
|
|
144
|
+
await ensureRunning(["docker"]);
|
|
145
|
+
|
|
146
|
+
await ensureRunning({
|
|
147
|
+
services: [
|
|
148
|
+
{ service: "docker", options: { timeout: 60_000 } }
|
|
149
|
+
]
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// Ensure, then spawn a command (like `er docker -- vite dev`)
|
|
153
|
+
const exitCode = await runEnsureRunning({
|
|
154
|
+
services: ["docker"],
|
|
155
|
+
command: ["vite", "dev"]
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// Docker shorthand with typed errors
|
|
159
|
+
await ensureDocker();
|
|
160
|
+
await ensure.docker({ check: true });
|
|
161
|
+
|
|
162
|
+
// Low-level docker helpers (re-exported from ensure-running)
|
|
163
|
+
import { ensureDockerRunning, detectDocker } from "ensure-running";
|
|
164
|
+
await ensureDockerRunning({ autoStart: true });
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
| API | Description |
|
|
168
|
+
|-----|-------------|
|
|
169
|
+
| `ensureRunning(services)` | Ensure one or more services; throws `EnsureRunningError` |
|
|
170
|
+
| `ensureRunning({ services, command? })` | Same, with optional structured request |
|
|
171
|
+
| `runEnsureRunning({ services, command? })` | Ensure services, then spawn `command`; returns exit code |
|
|
172
|
+
| `ensureDocker(options?)` | Docker-only helper; throws `DockerError` subclasses |
|
|
173
|
+
| `ensure.docker()` / `ensure.running()` | Namespaced aliases |
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## CLI
|
|
178
|
+
|
|
179
|
+
### Global options
|
|
180
|
+
|
|
181
|
+
| Flag | Description |
|
|
182
|
+
|------|-------------|
|
|
183
|
+
| `-h`, `--help` | Show top-level help |
|
|
184
|
+
| `-v`, `--version` | Print CLI version |
|
|
185
|
+
| `er docker --help` | Docker service help |
|
|
186
|
+
|
|
187
|
+
### Docker service flags
|
|
188
|
+
|
|
189
|
+
| Flag | Description |
|
|
190
|
+
|------|-------------|
|
|
191
|
+
| `--check` | Exit 0 when daemon is reachable; never auto-start |
|
|
192
|
+
| `--timeout <ms>` | Max wait for readiness (default: `120000`) |
|
|
193
|
+
| `--interval <ms>` | Poll interval (default: `1000`) |
|
|
194
|
+
| `--no-auto-start` | Fail when daemon is down |
|
|
195
|
+
| `-q`, `--quiet` | Suppress progress output |
|
|
196
|
+
|
|
197
|
+
### Bin names
|
|
198
|
+
|
|
199
|
+
| Command | Package |
|
|
200
|
+
|---------|---------|
|
|
201
|
+
| `er` | `ensure-running` |
|
|
202
|
+
| `ensure-running` | `ensure-running` |
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## Services
|
|
207
|
+
|
|
208
|
+
Built-in services ship inside `ensure-running`. Custom services live in `.er/services/`.
|
|
209
|
+
|
|
210
|
+
| Service | Source | Description |
|
|
211
|
+
|---------|--------|-------------|
|
|
212
|
+
| `docker` | built-in (`src/services/docker`) | Docker detection, auto-start, polling, typed errors |
|
|
213
|
+
| `*` | `.er/services/*` | Project-local `export default` services |
|
|
214
|
+
|
|
215
|
+
### Public exports
|
|
216
|
+
|
|
217
|
+
| Export | Description |
|
|
218
|
+
|--------|-------------|
|
|
219
|
+
| `ensureRunning(services)` | Chain services programmatically |
|
|
220
|
+
| `runEnsureRunning(request)` | Ensure services, then run a command |
|
|
221
|
+
| `ensureDocker(options?)` | Docker shorthand with typed errors |
|
|
222
|
+
| `ensure` | `{ docker, running }` namespace |
|
|
223
|
+
| `runCli(argv)` | Programmatic CLI entry (returns exit code) |
|
|
224
|
+
| `createServiceRegistry()` | Built-in + `.er/services` registry |
|
|
225
|
+
| `createBuiltInServiceRegistry()` | Built-in services only |
|
|
226
|
+
| `defineEnsureService(service)` | Define a custom or built-in service with type checking |
|
|
227
|
+
| `EnsureService` | Service contract type |
|
|
228
|
+
| `EnsureRunningError` | Service failure with `serviceId` and `exitCode` |
|
|
229
|
+
| `ensureDockerRunning(options?)` | Full Docker install + daemon + readiness flow |
|
|
230
|
+
| `isDockerRunning()` | Returns `true` when daemon is reachable; never throws |
|
|
231
|
+
| `detectDocker()` | `{ installed, running, version?, executable? }` |
|
|
232
|
+
| `dockerService` | CLI service object for custom registries |
|
|
233
|
+
| `DockerError` subclasses | Typed errors with stable `code` values |
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## Architecture
|
|
238
|
+
|
|
239
|
+
```text
|
|
240
|
+
src/
|
|
241
|
+
cli/ -> core (parseInvocation) + services (registry)
|
|
242
|
+
api/ -> core + services/docker
|
|
243
|
+
services/
|
|
244
|
+
docker/ -> ensure / detect / wait / platforms / commands / utils
|
|
245
|
+
LoadCustomServices.ts -> .er/services/*
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
See [ARCHITECTURE.md](./ARCHITECTURE.md) for module graphs, platform start order, and how to add services.
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## FAQ
|
|
253
|
+
|
|
254
|
+
**How is this different from `ensure-docker-running`?**
|
|
255
|
+
|
|
256
|
+
This repo ships Docker as a built-in service. The CLI is `ensure-running` / `er` with service names as the first tokens.
|
|
257
|
+
|
|
258
|
+
**Does `er docker -- vite` run vite on PATH?**
|
|
259
|
+
|
|
260
|
+
Yes. Tokens after `--` are spawned as a command with inherited stdio (`shell: true` on Windows).
|
|
261
|
+
|
|
262
|
+
**WSL2 / Colima / Rancher Desktop**
|
|
263
|
+
|
|
264
|
+
Works when `docker info` succeeds in the same environment as the Node process. WSL bridging is not automatic.
|
|
265
|
+
|
|
266
|
+
**Linux permissions**
|
|
267
|
+
|
|
268
|
+
If `docker info` fails with permission denied, add your user to the `docker` group. This tool does not change system permissions.
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
## Development
|
|
273
|
+
|
|
274
|
+
From `Pacotes/ensure-running/`:
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
npm ci
|
|
278
|
+
npm test
|
|
279
|
+
npm run lint
|
|
280
|
+
npm run typecheck
|
|
281
|
+
npm run build
|
|
282
|
+
npm run test:coverage
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
Run the CLI from source:
|
|
286
|
+
|
|
287
|
+
```bash
|
|
288
|
+
yarn dev docker
|
|
289
|
+
yarn dev docker --check
|
|
290
|
+
yarn dev docker -- vite --version
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
Link the published bins:
|
|
294
|
+
|
|
295
|
+
```bash
|
|
296
|
+
npm run build
|
|
297
|
+
npm link
|
|
298
|
+
er docker --version
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
| Script | Purpose |
|
|
302
|
+
|--------|---------|
|
|
303
|
+
| `yarn dev docker ...` | Run CLI via `tsx` without building |
|
|
304
|
+
| `npm run build` | Build library + bin |
|
|
305
|
+
| `npm test` | Vitest unit tests |
|
|
306
|
+
| `npm run ci` | Lint, typecheck, coverage, and build (same gate as release) |
|
|
307
|
+
| `yarn deploy` | Local publish (prefer CI tag releases) |
|
|
308
|
+
|
|
309
|
+
### Publish (GitHub Actions + npm Trusted Publishing)
|
|
310
|
+
|
|
311
|
+
Releases are published from CI when you push a `v*` tag. No `NPM_TOKEN` secret is required - npm authenticates the workflow via OIDC.
|
|
312
|
+
|
|
313
|
+
**One-time setup on npmjs.com:**
|
|
314
|
+
|
|
315
|
+
1. Package settings -> **Trusted publishing** -> GitHub Actions
|
|
316
|
+
2. Owner `callmeteus`, repo `ensure-running`, workflow `publish.yml`
|
|
317
|
+
3. Allow action `npm publish`
|
|
318
|
+
|
|
319
|
+
**Release:**
|
|
320
|
+
|
|
321
|
+
```bash
|
|
322
|
+
# bump version in package.json first
|
|
323
|
+
git tag v1.0.1
|
|
324
|
+
git push origin v1.0.1
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
CI validates lint/tests/build, checks that the tag matches `package.json`, then runs `npm publish` with provenance.
|
|
328
|
+
|
|
329
|
+
See [docs/PUBLISHING.md](./docs/PUBLISHING.md) for full setup, npm requirements, and troubleshooting.
|
|
330
|
+
|
|
331
|
+
### Local publish (fallback)
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
npm run deploy
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
Requires `npm login` against `registry.npmjs.org`. If you use Yarn globally, this repo pins npm via `.npmrc` and `publishConfig.registry` so `yarn deploy` does not target `registry.yarnpkg.com`. Prefer tag-based CI releases.
|
|
338
|
+
|
|
339
|
+
Requires Node.js >= 20.
|
|
340
|
+
|
|
341
|
+
---
|
|
342
|
+
|
|
343
|
+
## Documentation
|
|
344
|
+
|
|
345
|
+
| Document | Contents |
|
|
346
|
+
|----------|----------|
|
|
347
|
+
| [docs/PUBLISHING.md](./docs/PUBLISHING.md) | npm Trusted Publishing, tags, CI release flow |
|
|
348
|
+
| [ARCHITECTURE.md](./ARCHITECTURE.md) | Package layout, service contract, Docker internals, custom services |
|
|
349
|
+
| [LICENSE](./LICENSE) | MIT |
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
353
|
+
## License
|
|
354
|
+
|
|
355
|
+
MIT
|