@checkstack/frontend 0.4.2 → 0.5.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/CHANGELOG.md CHANGED
@@ -1,5 +1,234 @@
1
1
  # @checkstack/frontend
2
2
 
3
+ ## 0.5.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [42abfff]
8
+ - Updated dependencies [3547670]
9
+ - Updated dependencies [f6f9a5c]
10
+ - Updated dependencies [f6f9a5c]
11
+ - Updated dependencies [1ef2e79]
12
+ - Updated dependencies [aa89bc5]
13
+ - Updated dependencies [950d6ec]
14
+ - Updated dependencies [3547670]
15
+ - Updated dependencies [3547670]
16
+ - @checkstack/common@0.9.0
17
+ - @checkstack/ui@1.8.0
18
+ - @checkstack/catalog-frontend@0.10.0
19
+ - @checkstack/dependency-frontend@0.4.0
20
+ - @checkstack/frontend-api@0.5.0
21
+ - @checkstack/auth-frontend@0.6.0
22
+ - @checkstack/announcement-frontend@0.3.0
23
+ - @checkstack/about-frontend@0.2.16
24
+ - @checkstack/command-frontend@0.2.35
25
+ - @checkstack/signal-common@0.2.2
26
+ - @checkstack/signal-frontend@0.1.2
27
+
28
+ ## 0.5.0
29
+
30
+ ### Minor Changes
31
+
32
+ - 50e5f5f: Add `bunx @checkstack/scripts dev` — a local Checkstack dev server for
33
+ plugin authors that runs from the plugin's own repo without a monorepo
34
+ checkout.
35
+
36
+ Mechanics:
37
+
38
+ - The dev command spawns `core/backend`'s production entry as a child
39
+ process with three env vars wired in:
40
+ - `CHECKSTACK_DEV_PLUGIN_PATH=<cwd>` — backend skips filesystem
41
+ discovery and imports the plugin at this path as a manual plugin.
42
+ - `CHECKSTACK_DEV_EXTRA_PLUGIN_PATHS=<JSON array>` — additional
43
+ backend plugins co-loaded as manual plugins. The dev command walks
44
+ the plugin under dev's `package.json#dependencies` recursively to
45
+ discover every `@checkstack/*-backend` package and pass their
46
+ module paths through. Auto-includes
47
+ `@checkstack/queue-memory-backend` +
48
+ `@checkstack/cache-memory-backend` when no other queue/cache
49
+ provider is in the dep graph, so `coreServices.queueManager` /
50
+ `coreServices.cacheManager` always have a registered strategy on
51
+ boot. Without this co-loading, plugins that depend on
52
+ `healthcheck-backend`, `notification-backend`, etc. would hit
53
+ unregistered services and the boot would deadlock.
54
+ - `CHECKSTACK_DEV_AUTH=true` — backend registers a synthetic
55
+ `AuthService` that auto-grants every registered access rule.
56
+ Refused when `NODE_ENV=production` so accidental misuse is loud.
57
+ - A file watcher under the plugin's `./src` triggers a full backend
58
+ restart (debounced) on save. Bun's startup is sub-second for a single
59
+ plugin, so the loop stays tight.
60
+ - For frontend plugins (or bundle primaries with a `-frontend`
61
+ sibling), the dev command additionally spawns a Vite dev server on
62
+ port 5173 (configurable via `--frontend-port`). Vite serves
63
+ `core/frontend`'s new `dev-main.tsx` shell — the same App.tsx,
64
+ loadPlugins(), ThemeProvider, etc. that ship in production. The
65
+ plugin module is mounted via a `virtual:checkstack-dev-plugin` alias
66
+ Vite resolves at config time. React Fast Refresh works for component
67
+ edits.
68
+ - On boot, the dev command validates the plugin's `package.json`
69
+ against the same `installPackageMetadataSchema` the runtime install
70
+ pipeline uses, so missing required fields fail fast.
71
+
72
+ Reuses 100% of the production boot code path — no parallel dev backend
73
+ to drift from. New code surfaces:
74
+
75
+ - `core/backend/src/services/dev-auth.ts` — the synthetic auth service.
76
+ Inert unless `CHECKSTACK_DEV_AUTH=true`.
77
+ - `core/scripts/src/commands/dev-server.ts` — the CLI command.
78
+ - `core/scripts/src/commands/dev-deps-resolver.ts` — pure function that
79
+ walks the plugin's deps and resolves the co-load set; covered by 8
80
+ unit tests.
81
+ - `core/scripts/src/commands/dev-frontend.ts` — Vite spawn helper.
82
+ - `core/frontend/src/dev-main.tsx` — frontend dev-shell entry.
83
+
84
+ `@checkstack/scripts` now depends on `@checkstack/backend`,
85
+ `@checkstack/frontend`, `@checkstack/frontend-api`, `@checkstack/ui`,
86
+ `vite`, and `@vitejs/plugin-react` so a `bunx` invocation pulls in
87
+ everything needed for the dev server in one shot.
88
+
89
+ Replaces the previous "three patterns" plugin-development guide with a
90
+ single `bun run dev` workflow.
91
+
92
+ A new ESLint rule branch in `no-extraneous-runtime-deps` ignores
93
+ `virtual:` module specifiers (resolved by bundler aliases at runtime,
94
+ not installed from npm).
95
+
96
+ Scaffold templates updated for one-click compatibility — `bun run create`
97
+ now produces plugin packages that pass the dev-server's
98
+ `installPackageMetadataSchema` gate and ship `dev` / `pack` scripts plus
99
+ `@checkstack/scripts` in devDependencies, so a freshly scaffolded plugin
100
+ runs `bun run dev` without any further file edits. Required metadata
101
+ (`description`, `author`, `license: "Elastic-2.0"`, `checkstack.pluginId`)
102
+ is filled in by the scaffold; `@checkstack/scripts plugin-pack
103
+ --validate-only` accepts the rendered package.json directly. Templates
104
+ also reformatted from one-line JSON-in-handlebars to readable
105
+ multi-line.
106
+
107
+ New scaffold tests in `core/scripts/src/templates.test.ts` render each
108
+ template type and assert: dev-server validation passes, `dev` script
109
+ present (backend/frontend), `pack` script present, `@checkstack/scripts`
110
+ in devDependencies.
111
+
112
+ In addition, the new `dev-internals.ts`, `dev-lifecycle.ts`,
113
+ `dev-deps-resolver.ts`, and refactored `dev-frontend.ts` ship 58
114
+ unit tests covering arg parsing, package.json validation, backend
115
+ entry resolution, frontend-spawn decision, child env construction,
116
+ the debounce watcher, the spawn → restart → shutdown lifecycle (with
117
+ hard-kill SIGKILL fallback), the dev-auth service, and the bundle
118
+ sibling resolver — all driven through injectable seams so no real
119
+ process / Postgres / Vite is needed at test time.
120
+
121
+ - 50e5f5f: Runtime plugin system: install + uninstall plugins from npm, GitHub releases
122
+ (including private GitHub Enterprise instances), or tarball uploads at
123
+ runtime, with multi-package bundles, dependency-derived compatibility checks,
124
+ multi-instance coordination via a Postgres artifact store, and
125
+ single-coordinator destructive cleanup.
126
+
127
+ Highlights:
128
+
129
+ - New `PluginSource` discriminated union and `PluginInstaller` /
130
+ `PluginInstallerRegistry` interfaces in `@checkstack/backend-api`. The
131
+ GitHub variant accepts an optional `apiBaseUrl` so deployments backed by
132
+ GitHub Enterprise can install from `https://ghe.example.com/api/v3`
133
+ instead of `api.github.com`.
134
+ - New `installPackageMetadataSchema` (Zod) in `@checkstack/common` validates
135
+ every plugin's `package.json` at install time. Required fields: `name`,
136
+ `version`, `description`, `author`, `license`, `checkstack.type`,
137
+ `checkstack.pluginId`. Optional: `checkstack.bundle`,
138
+ `checkstack.usageInstructions`, `checkstack.allowInstallScripts`.
139
+ - New `pluginManagerContract` in `@checkstack/pluginmanager-common` with
140
+ `list`, `previewInstall`, `install`, `previewUninstall`, `uninstall`, and
141
+ `events` procedures.
142
+ - New `@checkstack/pluginmanager-frontend` admin UI: installed-plugins list
143
+ with per-row uninstall (typed-confirmation modal, schema/configs/cascade
144
+ toggles), install page with NPM / Tarball Upload / GitHub Release tabs
145
+ (Catalog tab disabled — coming soon), and an events page surfacing the
146
+ install/uninstall audit log.
147
+ - New `bunx @checkstack/scripts plugin-pack` CLI for plugin authors —
148
+ per-package mode produces an npm-shaped tarball; `--bundle` mode produces
149
+ an outer tarball containing every sibling declared in
150
+ `package.json#checkstack.bundle`. Published to npm so external authors
151
+ can `bunx` it directly without a workspace checkout.
152
+ - Compatibility derived from `package.json#dependencies` ranges
153
+ (`semver.satisfies` against the platform's loaded `@checkstack/*`
154
+ versions) — no separate `compatibility` field.
155
+ - Multi-instance: originator persists artifacts + `plugins` rows + broadcasts
156
+ install/uninstall; receiving instances do in-process register/unregister
157
+ only. Destructive ops (drop schema, delete plugin_configs, delete
158
+ artifacts, delete `plugins` rows) run exactly once on the originator.
159
+ - Fresh-instance bootstrap: `loadPlugins()` hydrates any
160
+ `is_uninstallable=true` plugin missing from `node_modules` from the
161
+ artifact store before normal Phase 1 register.
162
+ - New schema: `plugin_artifacts` (tarball storage), `plugin_install_events`
163
+ (audit/error log). `plugins` extended with `version`, `metadata`,
164
+ `source`, `bundle_id`, `is_primary`. Local plugin sync now writes
165
+ `version` from each plugin's `package.json` so the admin UI shows real
166
+ versions instead of `—`.
167
+ - Tarball-upload endpoint (`POST /api/pluginmanager/upload-tarball`) for
168
+ the install UI; access-gated by `pluginmanager.plugin.manage`.
169
+ - Plugin Manager menu link added to the user menu (main grid, alongside
170
+ Profile / Notification Settings / etc.).
171
+
172
+ Cross-cutting changes:
173
+
174
+ - Backend request/response logging now flows through `rootLogger` (winston)
175
+ instead of `hono/logger`. 5xx responses include the response body inline
176
+ so swallowed early-return errors are visible in the log.
177
+ - The `/api/:pluginId/*` dispatcher now logs which core service is missing
178
+ or which `pluginId` had no metadata when it 500s.
179
+ - New `registerCorePluginMetadata` on `PluginManager` for core routers
180
+ (like the plugin manager itself) that need their metadata visible to the
181
+ RPC dispatcher without going through the full plugin lifecycle.
182
+ - ESLint: `unicorn/no-null` is now disabled globally. Drizzle distinguishes
183
+ between `null` (writes a real SQL NULL) and `undefined` (skip the column
184
+ on insert), so treating them as interchangeable produced latent bugs at
185
+ the persistence boundary. The bulk of the patch-bumped packages above
186
+ reflect lint-fix touches that landed when this rule was relaxed.
187
+ - Workspace-wide license normalization to `Elastic-2.0` (matches
188
+ `LICENSE.md`). Every `package.json` in the workspace now declares the
189
+ same SPDX identifier; the patch bumps capture this.
190
+
191
+ Plugin packages (every `plugins/*`): added a `pack` npm script
192
+ (`bunx @checkstack/scripts plugin-pack`), mirrored each plugin's
193
+ `pluginId` from `plugin-metadata.ts` into `package.json#checkstack.pluginId`
194
+ so install-time validation passes, stubbed any missing required metadata
195
+ fields (`description`, `author`, `license`), and added
196
+ `checkstack.bundle` to multi-package plugin primaries (telegram, rcon, ssh,
197
+ jira, queue-bullmq, queue-memory, cache-memory).
198
+
199
+ Breaking changes:
200
+
201
+ - The legacy single-method `PluginInstaller` interface (`install(packageName)`)
202
+ is removed. Callers must use `coreServices.pluginInstallerRegistry`.
203
+ - The old `pluginAdminContract` and `createPluginAdminRouter` are removed.
204
+ Replaced by `pluginManagerContract` in `@checkstack/pluginmanager-common`
205
+ and `createPluginManagerRouter` in `core/backend`.
206
+ - `@checkstack/test-utils-backend` no longer exports
207
+ `createMockPluginInstaller` / `MockPluginInstaller` (the legacy interface
208
+ it shimmed is gone).
209
+
210
+ Note: bumps are limited to `minor` (for packages with new public API
211
+ surface) and `patch` (for downstream consumers, license normalization,
212
+ and lint fixes). No `major` bumps despite the `PluginInstaller` removal —
213
+ the legacy interface had no third-party consumers in the wild before this
214
+ runtime plugin system landed, and the contract surface is the same shape
215
+ modulo the rename.
216
+
217
+ ### Patch Changes
218
+
219
+ - Updated dependencies [50e5f5f]
220
+ - @checkstack/about-frontend@0.2.15
221
+ - @checkstack/catalog-frontend@0.9.1
222
+ - @checkstack/common@0.8.0
223
+ - @checkstack/signal-frontend@0.1.1
224
+ - @checkstack/ui@1.7.1
225
+ - @checkstack/announcement-frontend@0.2.16
226
+ - @checkstack/auth-frontend@0.5.33
227
+ - @checkstack/command-frontend@0.2.34
228
+ - @checkstack/dependency-frontend@0.3.5
229
+ - @checkstack/frontend-api@0.4.2
230
+ - @checkstack/signal-common@0.2.1
231
+
3
232
  ## 0.4.2
4
233
 
5
234
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@checkstack/frontend",
3
- "version": "0.4.2",
3
+ "version": "0.5.1",
4
+ "license": "Elastic-2.0",
4
5
  "checkstack": {
5
6
  "type": "frontend"
6
7
  },
@@ -15,17 +16,17 @@
15
16
  "lint:code": "eslint . --max-warnings 0"
16
17
  },
17
18
  "dependencies": {
18
- "@checkstack/about-frontend": "0.2.14",
19
- "@checkstack/announcement-frontend": "0.2.15",
20
- "@checkstack/auth-frontend": "0.5.32",
21
- "@checkstack/catalog-frontend": "0.9.0",
22
- "@checkstack/command-frontend": "0.2.33",
23
- "@checkstack/common": "0.7.0",
24
- "@checkstack/dependency-frontend": "0.3.4",
25
- "@checkstack/frontend-api": "0.4.1",
26
- "@checkstack/signal-common": "0.2.0",
27
- "@checkstack/signal-frontend": "0.1.0",
28
- "@checkstack/ui": "1.7.0",
19
+ "@checkstack/about-frontend": "0.2.15",
20
+ "@checkstack/announcement-frontend": "0.2.16",
21
+ "@checkstack/auth-frontend": "0.5.33",
22
+ "@checkstack/catalog-frontend": "0.9.1",
23
+ "@checkstack/command-frontend": "0.2.34",
24
+ "@checkstack/common": "0.8.0",
25
+ "@checkstack/dependency-frontend": "0.3.5",
26
+ "@checkstack/frontend-api": "0.4.2",
27
+ "@checkstack/signal-common": "0.2.1",
28
+ "@checkstack/signal-frontend": "0.1.1",
29
+ "@checkstack/ui": "1.7.1",
29
30
  "@orpc/client": "^1.13.14",
30
31
  "@tanstack/react-query": "^5.64.0",
31
32
  "@tanstack/react-query-devtools": "^5.64.0",
@@ -39,8 +40,8 @@
39
40
  "tailwind-merge": "^2.2.0"
40
41
  },
41
42
  "devDependencies": {
42
- "@checkstack/scripts": "0.1.2",
43
- "@checkstack/tsconfig": "0.0.5",
43
+ "@checkstack/scripts": "0.3.0",
44
+ "@checkstack/tsconfig": "0.0.7",
44
45
  "@types/react": "^18.2.64",
45
46
  "@types/react-dom": "^18.2.21",
46
47
  "@vitejs/plugin-react": "^6.0.1",
@@ -29,7 +29,7 @@ export function SignalAutoInvalidator(): React.ReactNode {
29
29
  }
30
30
  });
31
31
 
32
- // eslint-disable-next-line unicorn/no-null
32
+
33
33
  return null;
34
34
  }
35
35
 
@@ -0,0 +1,34 @@
1
+ import React from "react";
2
+ import ReactDOM from "react-dom/client";
3
+ import App from "./App.tsx";
4
+ import "./index.css";
5
+ import { loadPlugins } from "./plugin-loader.ts";
6
+ import { ThemeProvider } from "@checkstack/ui";
7
+
8
+ /**
9
+ * Dev-shell entry point used by `bunx @checkstack/scripts dev` for
10
+ * frontend (or bundle-primary) plugins. It re-uses the production
11
+ * `loadPlugins` flow but sources the plugin module from a Vite alias
12
+ * `virtual:checkstack-dev-plugin` configured by the dev-server's Vite
13
+ * setup.
14
+ *
15
+ * `loadPlugins` accepts an `overrideModules` map; we pass our single
16
+ * imported plugin under a synthetic path. Phase 2 of `loadPlugins`
17
+ * (remote plugin discovery via `/api/plugins`) still runs against the
18
+ * dev backend on :3000 — but Phase 1 has already registered our plugin,
19
+ * so the duplicate is skipped via `registeredNames`.
20
+ */
21
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
22
+ // @ts-ignore — `virtual:checkstack-dev-plugin` is provided by the Vite
23
+ // alias the dev-server creates at runtime; TS can't see it.
24
+ import * as devPlugin from "virtual:checkstack-dev-plugin";
25
+
26
+ await loadPlugins({ "virtual:checkstack-dev-plugin": devPlugin });
27
+
28
+ ReactDOM.createRoot(document.querySelector("#root")!).render(
29
+ <React.StrictMode>
30
+ <ThemeProvider defaultTheme="system" storageKey="checkstack-ui-theme">
31
+ <App />
32
+ </ThemeProvider>
33
+ </React.StrictMode>,
34
+ );