@crvouga/mockingbird-service-plane 1.6.0 → 1.6.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 +9 -1
- package/dist/{chunk-FNS5ZZMT.js → chunk-IO3CU5ZF.js} +2 -2
- package/dist/{chunk-X3BPHZRL.js → chunk-IVHDD2UD.js} +89 -10
- package/dist/chunk-IVHDD2UD.js.map +7 -0
- package/dist/cli.js +2 -2
- package/dist/index.js +1 -1
- package/dist/server.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-X3BPHZRL.js.map +0 -7
- /package/dist/{chunk-FNS5ZZMT.js.map → chunk-IO3CU5ZF.js.map} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
# Changelog — @crvouga/mockingbird-service-plane
|
|
2
2
|
|
|
3
|
-
## 1.6.
|
|
3
|
+
## 1.6.1 (2026-09-30)
|
|
4
|
+
|
|
5
|
+
### Fixes and improvements
|
|
6
|
+
|
|
7
|
+
- keep admin buttons pressed until the action finishes ([0aabfcb](https://github.com/crvouga/mockingbird/commit/0aabfcb5f392aa51e193f9c3f817d5877d92bc6a))
|
|
8
|
+
- size admin select fields like the text inputs beside them ([0fb3ef2](https://github.com/crvouga/mockingbird/commit/0fb3ef2ddbf43376c93a2ae6d87c6c9bf890dafc))
|
|
9
|
+
- keep admin section tabs wired when boot is renamed ([4eda25e](https://github.com/crvouga/mockingbird/commit/4eda25eacd59da048d196f7cc8369d7a02b47bfc))
|
|
10
|
+
|
|
11
|
+
## 1.6.0 (2026-09-29)
|
|
4
12
|
|
|
5
13
|
### Features
|
|
6
14
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createRuntime
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-IVHDD2UD.js";
|
|
4
4
|
|
|
5
5
|
// ../../adapters/node/dist/cli.js
|
|
6
6
|
import { readFile } from "node:fs/promises";
|
|
@@ -356,4 +356,4 @@ export {
|
|
|
356
356
|
createServer2 as createServer,
|
|
357
357
|
serveTarget
|
|
358
358
|
};
|
|
359
|
-
//# sourceMappingURL=chunk-
|
|
359
|
+
//# sourceMappingURL=chunk-IO3CU5ZF.js.map
|
|
@@ -2339,6 +2339,50 @@ function bootAdmin(config) {
|
|
|
2339
2339
|
if (render)
|
|
2340
2340
|
await render();
|
|
2341
2341
|
}
|
|
2342
|
+
const delay = (ms) => new Promise((resolve) => {
|
|
2343
|
+
window.setTimeout(resolve, ms);
|
|
2344
|
+
});
|
|
2345
|
+
const confirmAction = async (button, pending, done, work) => {
|
|
2346
|
+
if (button.dataset.pending === "1")
|
|
2347
|
+
return;
|
|
2348
|
+
const label = button.textContent ?? "";
|
|
2349
|
+
const width = button.offsetWidth;
|
|
2350
|
+
button.dataset.pending = "1";
|
|
2351
|
+
button.classList.add("pressed");
|
|
2352
|
+
button.setAttribute("aria-busy", "true");
|
|
2353
|
+
button.style.minWidth = `${width}px`;
|
|
2354
|
+
button.textContent = pending;
|
|
2355
|
+
try {
|
|
2356
|
+
await work();
|
|
2357
|
+
button.textContent = done;
|
|
2358
|
+
await delay(1e3);
|
|
2359
|
+
} catch (error) {
|
|
2360
|
+
showError(error);
|
|
2361
|
+
} finally {
|
|
2362
|
+
button.textContent = label;
|
|
2363
|
+
button.style.minWidth = "";
|
|
2364
|
+
button.classList.remove("pressed");
|
|
2365
|
+
button.removeAttribute("aria-busy");
|
|
2366
|
+
delete button.dataset.pending;
|
|
2367
|
+
}
|
|
2368
|
+
};
|
|
2369
|
+
document.addEventListener("click", (event) => {
|
|
2370
|
+
const target = event.target;
|
|
2371
|
+
if (!(target instanceof Element))
|
|
2372
|
+
return;
|
|
2373
|
+
const button = target.closest("button");
|
|
2374
|
+
if (!(button instanceof HTMLButtonElement) || button.dataset.pending === "1")
|
|
2375
|
+
return;
|
|
2376
|
+
button.classList.add("pressed");
|
|
2377
|
+
const token = String(Date.now());
|
|
2378
|
+
button.dataset.press = token;
|
|
2379
|
+
window.setTimeout(() => {
|
|
2380
|
+
if (button.dataset.press !== token || button.dataset.pending === "1")
|
|
2381
|
+
return;
|
|
2382
|
+
button.classList.remove("pressed");
|
|
2383
|
+
delete button.dataset.press;
|
|
2384
|
+
}, 450);
|
|
2385
|
+
});
|
|
2342
2386
|
el("namespace", HTMLSelectElement).addEventListener("change", () => {
|
|
2343
2387
|
state.namespace = el("namespace", HTMLSelectElement).value;
|
|
2344
2388
|
refresh().catch(showError);
|
|
@@ -2349,7 +2393,7 @@ function bootAdmin(config) {
|
|
|
2349
2393
|
refresh().catch(showError);
|
|
2350
2394
|
});
|
|
2351
2395
|
el("refresh", HTMLButtonElement).addEventListener("click", () => {
|
|
2352
|
-
refresh().catch(showError);
|
|
2396
|
+
confirmAction(el("refresh", HTMLButtonElement), "Refreshing...", "Updated", () => refresh()).catch(showError);
|
|
2353
2397
|
});
|
|
2354
2398
|
el("collections", HTMLElement).addEventListener("click", (event) => {
|
|
2355
2399
|
const target = event.target;
|
|
@@ -2472,10 +2516,10 @@ function bootAdmin(config) {
|
|
|
2472
2516
|
}).then(() => renderFaults()).catch(showError);
|
|
2473
2517
|
});
|
|
2474
2518
|
el("fault-clear", HTMLButtonElement).addEventListener("click", () => {
|
|
2475
|
-
api("DELETE", "/faults").then(() => renderFaults()).catch(showError);
|
|
2519
|
+
confirmAction(el("fault-clear", HTMLButtonElement), "Clearing...", "Cleared", () => api("DELETE", "/faults").then(() => renderFaults())).catch(showError);
|
|
2476
2520
|
});
|
|
2477
2521
|
el("journal-clear", HTMLButtonElement).addEventListener("click", () => {
|
|
2478
|
-
api("DELETE", "/requests").then(() => renderJournal()).catch(showError);
|
|
2522
|
+
confirmAction(el("journal-clear", HTMLButtonElement), "Clearing...", "Cleared", () => api("DELETE", "/requests").then(() => renderJournal())).catch(showError);
|
|
2479
2523
|
});
|
|
2480
2524
|
el("route-list", HTMLElement).addEventListener("click", (event) => {
|
|
2481
2525
|
const target = event.target;
|
|
@@ -2590,9 +2634,13 @@ function bootAdmin(config) {
|
|
|
2590
2634
|
var clientPrelude = [isRecord2, mountAdminBrand, startAdminBrand, faultPresetList, bootAdmin].map((fn) => fn.toString()).join("\n");
|
|
2591
2635
|
var adminClientSource = (config) => {
|
|
2592
2636
|
const payload = JSON.stringify(config).replace(/</g, "\\u003c");
|
|
2637
|
+
const entry = bootAdmin.name;
|
|
2638
|
+
if (!/^[A-Za-z_$][\w$]*$/.test(entry)) {
|
|
2639
|
+
throw new Error("admin client cannot call its boot function");
|
|
2640
|
+
}
|
|
2593
2641
|
return `<script>
|
|
2594
2642
|
${clientPrelude}
|
|
2595
|
-
|
|
2643
|
+
${entry}(${payload});
|
|
2596
2644
|
</script>`;
|
|
2597
2645
|
};
|
|
2598
2646
|
|
|
@@ -2806,9 +2854,24 @@ var renderAdminDocument = (service) => {
|
|
|
2806
2854
|
.controls { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
|
|
2807
2855
|
label.field { display: flex; flex-direction: column; gap: 2px; font-size: 11px; color: var(--faint); }
|
|
2808
2856
|
label.field input, label.field select, .controls input[type="password"] {
|
|
2809
|
-
background: var(--bg-inset); border: 1px solid var(--line); border-radius: 8px;
|
|
2810
|
-
padding: 7px 8px; min-height: 36px;
|
|
2811
|
-
}
|
|
2857
|
+
background-color: var(--bg-inset); border: 1px solid var(--line); border-radius: 8px;
|
|
2858
|
+
padding: 7px 8px; min-height: 36px; line-height: 1.2;
|
|
2859
|
+
}
|
|
2860
|
+
/* A native menu ignores min-height, so Preset rendered about half as tall as
|
|
2861
|
+
the text fields in the same form. Paint it like those fields. */
|
|
2862
|
+
label.field select {
|
|
2863
|
+
-webkit-appearance: none; appearance: none;
|
|
2864
|
+
padding-right: 28px;
|
|
2865
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='none' stroke='%2371717a' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' d='M2.5 4.5 6 8l3.5-3.5'/%3E%3C/svg%3E");
|
|
2866
|
+
background-repeat: no-repeat; background-position: right 10px center; background-size: 12px 12px;
|
|
2867
|
+
}
|
|
2868
|
+
.stack > .field > input,
|
|
2869
|
+
.stack > .field > select,
|
|
2870
|
+
.stack > .field > textarea,
|
|
2871
|
+
dialog .field > input,
|
|
2872
|
+
dialog .field > select,
|
|
2873
|
+
dialog .field > textarea { width: 100%; }
|
|
2874
|
+
.icon-btn, .btn, .btn-primary, .btn-quiet, .btn-danger, nav.side button { cursor: pointer; }
|
|
2812
2875
|
.icon-btn, .btn, .btn-primary, .btn-quiet, .btn-danger {
|
|
2813
2876
|
border-radius: 9px; min-height: 36px; padding: 0 12px; border: 1px solid var(--line);
|
|
2814
2877
|
background: var(--bg-elev);
|
|
@@ -2816,6 +2879,14 @@ var renderAdminDocument = (service) => {
|
|
|
2816
2879
|
.btn-primary { background: var(--accent); color: var(--accent-ink); border-color: transparent; }
|
|
2817
2880
|
.btn-quiet { background: transparent; }
|
|
2818
2881
|
.btn-danger { color: var(--err); }
|
|
2882
|
+
/* Held after mouseup. Clearing an empty journal changes nothing on screen,
|
|
2883
|
+
so the press itself has to stay visible. */
|
|
2884
|
+
.icon-btn:active, .btn:active, .btn-quiet:active, .btn-danger:active, nav.side button:active,
|
|
2885
|
+
.icon-btn.pressed, .btn.pressed, .btn-quiet.pressed, .btn-danger.pressed, nav.side button.pressed {
|
|
2886
|
+
background: var(--bg-inset); border-color: var(--line-strong); color: var(--ink);
|
|
2887
|
+
}
|
|
2888
|
+
.btn-danger:active, .btn-danger.pressed { background: var(--err-soft); color: var(--err); }
|
|
2889
|
+
.btn-primary:active, .btn-primary.pressed { filter: brightness(0.88); color: var(--accent-ink); }
|
|
2819
2890
|
/* minmax(0, 1fr): a 1fr column will not shrink below its content, so a long
|
|
2820
2891
|
record or the full nav row would widen the page past the viewport. */
|
|
2821
2892
|
.layout {
|
|
@@ -2904,8 +2975,16 @@ var renderAdminDocument = (service) => {
|
|
|
2904
2975
|
input, select, textarea { font-size: 16px; }
|
|
2905
2976
|
.brand, .vendor, .controls { width: 100%; }
|
|
2906
2977
|
label.field, label.field select, label.field input { flex: 1; min-width: 0; }
|
|
2907
|
-
|
|
2978
|
+
/* The layout fills the screen. A single-column grid stretches every auto
|
|
2979
|
+
row, so the tab bar grew with the leftover height and the buttons floated
|
|
2980
|
+
in the middle of it. The bar stays one row; the page below takes the rest. */
|
|
2981
|
+
.layout {
|
|
2982
|
+
grid-template-columns: minmax(0, 1fr);
|
|
2983
|
+
grid-template-rows: auto minmax(0, 1fr);
|
|
2984
|
+
align-content: start;
|
|
2985
|
+
}
|
|
2908
2986
|
nav.side {
|
|
2987
|
+
align-self: start; height: auto;
|
|
2909
2988
|
flex-direction: row; align-items: center; overflow-x: auto; min-width: 0;
|
|
2910
2989
|
border-right: 0; border-bottom: 1px solid var(--line);
|
|
2911
2990
|
padding: 8px;
|
|
@@ -3773,7 +3852,7 @@ var stateAdminRoutes = (routes) => {
|
|
|
3773
3852
|
};
|
|
3774
3853
|
|
|
3775
3854
|
// ../core/dist/version.js
|
|
3776
|
-
var PACKAGE_VERSION = true ? "1.6.
|
|
3855
|
+
var PACKAGE_VERSION = true ? "1.6.1" : UNRELEASED_VERSION;
|
|
3777
3856
|
|
|
3778
3857
|
// ../core/dist/webhooks.js
|
|
3779
3858
|
var json4 = (status, body) => new Response(JSON.stringify(body), { status, headers: { "content-type": "application/json" } });
|
|
@@ -5143,4 +5222,4 @@ export {
|
|
|
5143
5222
|
apiKeyCredential,
|
|
5144
5223
|
PlaneAPI
|
|
5145
5224
|
};
|
|
5146
|
-
//# sourceMappingURL=chunk-
|
|
5225
|
+
//# sourceMappingURL=chunk-IVHDD2UD.js.map
|