feat: Phase 1 — extract the client (web SPA + desktop) to dtoro/oikos-web
Problem: the hexagonal refactor churns the backend tree for nine more phases; the UI delivery stack (web/ SPA, cmd/desktop Wails wrapper, compose/web image) must move to its own repo first so doc/layout rewrites land once on a backend-only tree. Change: - New repo git.hubris.network/dtoro/oikos-web (v0.33.0): web/, desktop/ (updateURL repointed to oikos-web releases), compose/, own CI (web + desktop jobs), own deploy script (CI-green gate, TOCTOU guard, version-tagged images, prune-to-3), own webhook receiver on :9798 + launchd unit, own compose project publishing the same 8091:80. - Cutover executed on mac-mini in order: oikos stack's web service stopped+removed, oikos-web project brought up on 8091; outer Caddy untouched (targets the published port) — serving + Authentik flow + /wails 404 quirk verified post-cutover. - Stripped from oikos: web/, cmd/desktop/, compose/web/, desktop CI workflow, ci.yml web job, Makefile ui/desktop/desktop-package/install targets, the compose web service, oikos-web from deploy.sh's fallback prune list; wails + go-keyring dropped from go.mod, vendor synced. - README / CONTRIBUTING / AGENTS.md / .agents dev+operations docs now point at the new repo; mbse + mascot design docs carry a path note. Risk: production SPA serving depends on the new pipeline now; rollback is versioned-image re-up of the old web service from a pre-split checkout (port 8091). Desktop builds installed before the split still check dtoro/oikos releases — one manual reinstall, noted in the oikos-web release notes. Verification: go vet, make test (race), make generate-check, golangci (no new findings; baseline down 400→365); post-cutover curls — localhost:8091 200, /wails/runtime.js 404, outer Caddy 302 Authentik.
This commit is contained in:
13
web/node_modules/d3-timer/src/index.js
generated
vendored
Normal file
13
web/node_modules/d3-timer/src/index.js
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
export {
|
||||
now,
|
||||
timer,
|
||||
timerFlush
|
||||
} from "./timer.js";
|
||||
|
||||
export {
|
||||
default as timeout
|
||||
} from "./timeout.js";
|
||||
|
||||
export {
|
||||
default as interval
|
||||
} from "./interval.js";
|
||||
17
web/node_modules/d3-timer/src/interval.js
generated
vendored
Normal file
17
web/node_modules/d3-timer/src/interval.js
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
import {Timer, now} from "./timer.js";
|
||||
|
||||
export default function(callback, delay, time) {
|
||||
var t = new Timer, total = delay;
|
||||
if (delay == null) return t.restart(callback, delay, time), t;
|
||||
t._restart = t.restart;
|
||||
t.restart = function(callback, delay, time) {
|
||||
delay = +delay, time = time == null ? now() : +time;
|
||||
t._restart(function tick(elapsed) {
|
||||
elapsed += total;
|
||||
t._restart(tick, total += delay, time);
|
||||
callback(elapsed);
|
||||
}, delay, time);
|
||||
}
|
||||
t.restart(callback, delay, time);
|
||||
return t;
|
||||
}
|
||||
11
web/node_modules/d3-timer/src/timeout.js
generated
vendored
Normal file
11
web/node_modules/d3-timer/src/timeout.js
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
import {Timer} from "./timer.js";
|
||||
|
||||
export default function(callback, delay, time) {
|
||||
var t = new Timer;
|
||||
delay = delay == null ? 0 : +delay;
|
||||
t.restart(elapsed => {
|
||||
t.stop();
|
||||
callback(elapsed + delay);
|
||||
}, delay, time);
|
||||
return t;
|
||||
}
|
||||
110
web/node_modules/d3-timer/src/timer.js
generated
vendored
Normal file
110
web/node_modules/d3-timer/src/timer.js
generated
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
var frame = 0, // is an animation frame pending?
|
||||
timeout = 0, // is a timeout pending?
|
||||
interval = 0, // are any timers active?
|
||||
pokeDelay = 1000, // how frequently we check for clock skew
|
||||
taskHead,
|
||||
taskTail,
|
||||
clockLast = 0,
|
||||
clockNow = 0,
|
||||
clockSkew = 0,
|
||||
clock = typeof performance === "object" && performance.now ? performance : Date,
|
||||
setFrame = typeof window === "object" && window.requestAnimationFrame ? window.requestAnimationFrame.bind(window) : function(f) { setTimeout(f, 17); };
|
||||
|
||||
export function now() {
|
||||
return clockNow || (setFrame(clearNow), clockNow = clock.now() + clockSkew);
|
||||
}
|
||||
|
||||
function clearNow() {
|
||||
clockNow = 0;
|
||||
}
|
||||
|
||||
export function Timer() {
|
||||
this._call =
|
||||
this._time =
|
||||
this._next = null;
|
||||
}
|
||||
|
||||
Timer.prototype = timer.prototype = {
|
||||
constructor: Timer,
|
||||
restart: function(callback, delay, time) {
|
||||
if (typeof callback !== "function") throw new TypeError("callback is not a function");
|
||||
time = (time == null ? now() : +time) + (delay == null ? 0 : +delay);
|
||||
if (!this._next && taskTail !== this) {
|
||||
if (taskTail) taskTail._next = this;
|
||||
else taskHead = this;
|
||||
taskTail = this;
|
||||
}
|
||||
this._call = callback;
|
||||
this._time = time;
|
||||
sleep();
|
||||
},
|
||||
stop: function() {
|
||||
if (this._call) {
|
||||
this._call = null;
|
||||
this._time = Infinity;
|
||||
sleep();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export function timer(callback, delay, time) {
|
||||
var t = new Timer;
|
||||
t.restart(callback, delay, time);
|
||||
return t;
|
||||
}
|
||||
|
||||
export function timerFlush() {
|
||||
now(); // Get the current time, if not already set.
|
||||
++frame; // Pretend we’ve set an alarm, if we haven’t already.
|
||||
var t = taskHead, e;
|
||||
while (t) {
|
||||
if ((e = clockNow - t._time) >= 0) t._call.call(undefined, e);
|
||||
t = t._next;
|
||||
}
|
||||
--frame;
|
||||
}
|
||||
|
||||
function wake() {
|
||||
clockNow = (clockLast = clock.now()) + clockSkew;
|
||||
frame = timeout = 0;
|
||||
try {
|
||||
timerFlush();
|
||||
} finally {
|
||||
frame = 0;
|
||||
nap();
|
||||
clockNow = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function poke() {
|
||||
var now = clock.now(), delay = now - clockLast;
|
||||
if (delay > pokeDelay) clockSkew -= delay, clockLast = now;
|
||||
}
|
||||
|
||||
function nap() {
|
||||
var t0, t1 = taskHead, t2, time = Infinity;
|
||||
while (t1) {
|
||||
if (t1._call) {
|
||||
if (time > t1._time) time = t1._time;
|
||||
t0 = t1, t1 = t1._next;
|
||||
} else {
|
||||
t2 = t1._next, t1._next = null;
|
||||
t1 = t0 ? t0._next = t2 : taskHead = t2;
|
||||
}
|
||||
}
|
||||
taskTail = t0;
|
||||
sleep(time);
|
||||
}
|
||||
|
||||
function sleep(time) {
|
||||
if (frame) return; // Soonest alarm already set, or will be.
|
||||
if (timeout) timeout = clearTimeout(timeout);
|
||||
var delay = time - clockNow; // Strictly less than if we recomputed clockNow.
|
||||
if (delay > 24) {
|
||||
if (time < Infinity) timeout = setTimeout(wake, time - clock.now() - clockSkew);
|
||||
if (interval) interval = clearInterval(interval);
|
||||
} else {
|
||||
if (!interval) clockLast = clock.now(), interval = setInterval(poke, pokeDelay);
|
||||
frame = 1, setFrame(wake);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user