@dunx/dashboard 2.5.0 → 3.0.1

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/dist/options.d.ts CHANGED
@@ -1,131 +1,80 @@
1
1
  import type { BunRequest } from 'bun';
2
2
  import type { ConfigValues, DashboardProbe, QueueSource, RedisProbe } from './contracts.js';
3
3
  /**
4
- * Decides whether a request may see the dashboard at all.
4
+ * Decides whether a request may see the dashboard at all. It receives the raw
5
+ * `Request`: the middleware must be registered ahead of any session guard, so
6
+ * there is nothing upstream to have written a context and this has to ask the
7
+ * auth library itself.
5
8
  *
6
- * It receives the **raw `Request`**, not an `AuthContext` some earlier middleware
7
- * wrote, and that is load bearing rather than incidental. The dashboard middleware
8
- * has to be registered ahead of any session guard - measured in `dunx-template`,
9
- * where a guard running first answered every dashboard request `401` before
10
- * `authorize` was reached, which defeats the 404 contract below entirely. Running
11
- * first means there is nothing upstream to have written a context, so this has to
12
- * be able to ask the auth library itself.
13
- *
14
- * A rejected request gets **404, not 403**. A dashboard that announces itself to
15
- * an unauthenticated caller has told them where to keep knocking.
9
+ * A rejected request gets 404, not 403.
16
10
  */
17
11
  export type Authorize = (req: BunRequest) => boolean | Promise<boolean>;
18
12
  /**
19
- * Whether a config value may be shown.
20
- *
21
- * **The default reveals nothing**, and that is the answer to the open question the
22
- * design left. `ConfigService` holds whatever the app's `validate` returned, which
23
- * includes every secret it has; a deny-list of the usual suspects - `SECRET`,
24
- * `PASSWORD`, `TOKEN` - looks careful and leaks the first key nobody thought of.
25
- * A deny-list that quietly misses one is worse than no config panel at all.
26
- *
27
- * So the panel shows **keys and types** by default, which is most of what it was
28
- * wanted for ("is FEATURE_X actually set here"), and a value appears only when this
29
- * predicate says so:
13
+ * Whether a config value may be shown. The default reveals nothing: a deny-list
14
+ * of the usual suspects leaks the first key nobody thought of. The panel shows
15
+ * keys and types, and a value appears only when this says so:
30
16
  *
31
17
  * ```ts
32
18
  * reveal: (key) => key.startsWith('PUBLIC_') || key === 'NODE_ENV'
33
19
  * ```
34
20
  *
35
- * There is no "reveal" affordance on the page. Redaction is decided at boot by the
36
- * app, not per click by whoever reached the page.
21
+ * There is no reveal affordance on the page; redaction is decided at boot.
37
22
  */
38
23
  export type Reveal = (key: string, value: unknown) => boolean;
39
24
  export interface DashboardOptionsInit {
40
25
  /**
41
- * Where the page is mounted. `/_dunx` by default - the underscore keeps it
42
- * clear of an app's own routes, and the name is the framework's rather than
43
- * `/queues`, because queues are one panel of six.
44
- *
45
- * **`app.setGlobalPrefix('api')` does not move it.** That prefixes the routes
46
- * discovered from controllers, and this is not one of those - it is a middleware
47
- * matching a path, which is the whole reason the dashboard needs no controllers
48
- * for a table handed over at runtime. An app with a global prefix that wants the
49
- * page beside its routes writes `path: '/api/_dunx'` here.
26
+ * Where the page is mounted, `/_dunx` by default. `app.setGlobalPrefix('api')`
27
+ * does not move it: that prefixes discovered routes, and this is a middleware
28
+ * matching a path. Write `path: '/api/_dunx'` to put it beside them.
50
29
  */
51
30
  readonly path?: string;
52
31
  /**
53
- * **There is no default, and leaving it out serves the page to anyone who can
54
- * reach the port.** That is fine behind a private network and bad everywhere
55
- * else, so it is stated either way rather than guessed: omitting it logs a
56
- * warning naming the mount path at boot.
32
+ * No default: leaving it out serves the page to anyone who can reach the port,
33
+ * and logs a warning naming the mount path at boot.
57
34
  */
58
35
  readonly authorize?: Authorize;
59
36
  /** Shown in the header and the `<title>`. @default 'dunx' */
60
37
  readonly title?: string;
61
- /**
62
- * `JobPublisher` goes here. Absent means the queues panel says this process has
63
- * no queue source rather than that it has no queues.
64
- */
38
+ /** `JobPublisher` goes here. Absent means the panel reports no queue source. */
65
39
  readonly queues?: QueueSource;
66
- /**
67
- * Queues to show beyond the ones the source has opened. A process that
68
- * **consumes** a queue never publishes to it, so the publisher has never opened
69
- * it and it would otherwise be invisible on the page that exists to show it.
70
- */
40
+ /** Queues beyond the ones the source has opened. A consume-only process never
41
+ * publishes, so its queues would otherwise be invisible. */
71
42
  readonly queueNames?: readonly string[];
72
43
  /** `RedisConnection` goes here; it drives the Redis panel and one probe. */
73
44
  readonly redis?: RedisProbe;
74
45
  /** Anything else worth a light: a database, an upstream, a leader lease. */
75
46
  readonly probes?: readonly DashboardProbe[];
76
- /**
77
- * `ConfigService` goes here, and the panel is absent without it - showing an
78
- * app's configuration is something the app says yes to, not something this
79
- * package reaches into the container for.
80
- */
47
+ /** `ConfigService` goes here; the panel is absent without it. */
81
48
  readonly config?: ConfigValues;
82
49
  /** See {@link Reveal}. The default reveals nothing, even with `config` set. */
83
50
  readonly reveal?: Reveal;
84
- /**
85
- * Where `@dunx/openapi` serves its explorer, so the routes panel can link a row
86
- * to the operation that documents it. A string, not a dependency: the two
87
- * packages describe the same routes for different audiences and a link is free,
88
- * where importing one into the other is not.
89
- */
51
+ /** Where `@dunx/openapi` serves its explorer, so a routes row can link to the
52
+ * operation documenting it. A string rather than a dependency. */
90
53
  readonly openApiPath?: string;
91
54
  /**
92
- * How often the live panels re-fetch, in milliseconds. `0` turns polling off and
93
- * leaves the refresh button.
94
- *
95
- * Polling rather than a websocket, deliberately: the page is stateless, a gateway
96
- * would put the dashboard in the app's own upgrade table, and 5 s is well inside
97
- * what "how many jobs are failing" needs.
55
+ * How often the live panels re-fetch, in milliseconds. `0` turns polling off
56
+ * and leaves the refresh button. Polling rather than a websocket, which would
57
+ * put the dashboard in the app's own upgrade table.
98
58
  *
99
59
  * @default 5000
100
60
  */
101
61
  readonly pollMs?: number;
102
62
  /**
103
- * How long a probe may take before it is reported `unknown`. A hung probe must
104
- * cost one light, not the page.
63
+ * How long a probe may take before it is reported `unknown`.
105
64
  *
106
65
  * @default 2000
107
66
  */
108
67
  readonly probeTimeoutMs?: number;
109
68
  /**
110
- * Whether the queue board may change anything.
111
- *
112
- * Passed through to **bull-board's own `readOnlyMode`** rather than enforced
113
- * here: it already has the switch, and a second implementation would disagree
114
- * with it the moment bull-board grew an operation dunx had not heard of.
115
- *
116
- * The rest of the dashboard is read-only regardless - it reports on the process
117
- * and never acts on it - so this is entirely about the queues page. `authorize`
118
- * gates who reaches the mount; this gates what they can do once there.
69
+ * Whether the queue board may change anything, passed through to bull-board's
70
+ * own `readOnlyMode`. The rest of the dashboard is read-only regardless.
119
71
  *
120
72
  * @default true
121
73
  */
122
74
  readonly commands?: boolean;
123
75
  }
124
- /**
125
- * A class, not an interface, so it is a runtime value and can therefore be a
126
- * constructor parameter type that `@dunx/transform` records - the same reason
127
- * `QueueOptions` and `RedisOptions` are classes.
128
- */
76
+ /** A class rather than an interface, so it is a runtime value the transform can
77
+ * record as a constructor parameter type. */
129
78
  export declare class DashboardOptions {
130
79
  readonly path: string;
131
80
  readonly authorize: Authorize | undefined;
@@ -144,9 +93,6 @@ export declare class DashboardOptions {
144
93
  }
145
94
  /**
146
95
  * A leading slash and no trailing one, so `${path}/api/...` is never `//api`.
147
- *
148
- * `/` itself is rejected: mounting the dashboard at the root would swallow every
149
- * unmatched path in the app, and the middleware's whole contract is that anything
150
- * outside its mount falls through untouched.
96
+ * `/` is rejected: mounting at the root would swallow every unmatched path.
151
97
  */
152
98
  export declare const normalizeMount: (path: string) => string;
package/dist/ui.d.ts CHANGED
@@ -1,20 +1,14 @@
1
1
  import type { DashboardOptions } from './options.js';
2
2
  import { FAVICON, UI } from './ui-bundle.js';
3
3
  /**
4
- * The page, behind its own entrypoint.
4
+ * The page, behind its own entrypoint. `ui-bundle.ts` is the inlined Vite output,
5
+ * reached with `await import('./ui.js')` on the first request for the page, so an
6
+ * app that mounts the module and never opens it pays nothing at boot.
5
7
  *
6
- * `ui-bundle.ts` is the inlined Vite output, and importing it costs a few
7
- * milliseconds and its full size in parsed source. `DashboardMiddleware` reaches
8
- * this with `await import('./ui.js')` on the **first request for the page**, so an
9
- * app that mounts the module and never opens it - a worker process, a service
10
- * whose dashboard nobody visits this week - pays nothing at boot.
8
+ * `html.ts` must not import `ui-bundle.ts`, or the split silently reverts; it
9
+ * takes the bundle as an argument for that reason.
11
10
  *
12
- * `html.ts` therefore must not import `ui-bundle.ts`, or the split silently
13
- * reverts. It takes the bundle as an argument for exactly that reason.
14
- *
15
- * This is `@dunx/dashboard/ui` in the manifest, and it is an entrypoint rather than
16
- * a plain module so the build emits it as its own file - see
17
- * `scripts/build-package.ts`, which derives entrypoints from `exports`.
11
+ * `@dunx/dashboard/ui` in the manifest, so the build emits it as its own file.
18
12
  */
19
13
  export declare const renderPage: (options: DashboardOptions) => string;
20
14
  export { FAVICON, UI };