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.
235 lines
6.0 KiB
JavaScript
235 lines
6.0 KiB
JavaScript
'use strict';
|
|
|
|
var common = require('./common');
|
|
var EventEmitter = require('../').EventEmitter;
|
|
var once = require('../').once;
|
|
var has = require('has');
|
|
var assert = require('assert');
|
|
|
|
function Event(type) {
|
|
this.type = type;
|
|
}
|
|
|
|
function EventTargetMock() {
|
|
this.events = {};
|
|
|
|
this.addEventListener = common.mustCall(this.addEventListener);
|
|
this.removeEventListener = common.mustCall(this.removeEventListener);
|
|
}
|
|
|
|
EventTargetMock.prototype.addEventListener = function addEventListener(name, listener, options) {
|
|
if (!(name in this.events)) {
|
|
this.events[name] = { listeners: [], options: options || {} }
|
|
}
|
|
this.events[name].listeners.push(listener);
|
|
};
|
|
|
|
EventTargetMock.prototype.removeEventListener = function removeEventListener(name, callback) {
|
|
if (!(name in this.events)) {
|
|
return;
|
|
}
|
|
var event = this.events[name];
|
|
var stack = event.listeners;
|
|
|
|
for (var i = 0, l = stack.length; i < l; i++) {
|
|
if (stack[i] === callback) {
|
|
stack.splice(i, 1);
|
|
if (stack.length === 0) {
|
|
delete this.events[name];
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
};
|
|
|
|
EventTargetMock.prototype.dispatchEvent = function dispatchEvent(arg) {
|
|
if (!(arg.type in this.events)) {
|
|
return true;
|
|
}
|
|
|
|
var event = this.events[arg.type];
|
|
var stack = event.listeners.slice();
|
|
|
|
for (var i = 0, l = stack.length; i < l; i++) {
|
|
stack[i].call(null, arg);
|
|
if (event.options.once) {
|
|
this.removeEventListener(arg.type, stack[i]);
|
|
}
|
|
}
|
|
return !arg.defaultPrevented;
|
|
};
|
|
|
|
function onceAnEvent() {
|
|
var ee = new EventEmitter();
|
|
|
|
process.nextTick(function () {
|
|
ee.emit('myevent', 42);
|
|
});
|
|
|
|
return once(ee, 'myevent').then(function (args) {
|
|
var value = args[0]
|
|
assert.strictEqual(value, 42);
|
|
assert.strictEqual(ee.listenerCount('error'), 0);
|
|
assert.strictEqual(ee.listenerCount('myevent'), 0);
|
|
});
|
|
}
|
|
|
|
function onceAnEventWithTwoArgs() {
|
|
var ee = new EventEmitter();
|
|
|
|
process.nextTick(function () {
|
|
ee.emit('myevent', 42, 24);
|
|
});
|
|
|
|
return once(ee, 'myevent').then(function (value) {
|
|
assert.strictEqual(value.length, 2);
|
|
assert.strictEqual(value[0], 42);
|
|
assert.strictEqual(value[1], 24);
|
|
});
|
|
}
|
|
|
|
function catchesErrors() {
|
|
var ee = new EventEmitter();
|
|
|
|
var expected = new Error('kaboom');
|
|
var err;
|
|
process.nextTick(function () {
|
|
ee.emit('error', expected);
|
|
});
|
|
|
|
return once(ee, 'myevent').then(function () {
|
|
throw new Error('should reject')
|
|
}, function (err) {
|
|
assert.strictEqual(err, expected);
|
|
assert.strictEqual(ee.listenerCount('error'), 0);
|
|
assert.strictEqual(ee.listenerCount('myevent'), 0);
|
|
});
|
|
}
|
|
|
|
function stopListeningAfterCatchingError() {
|
|
var ee = new EventEmitter();
|
|
|
|
var expected = new Error('kaboom');
|
|
var err;
|
|
process.nextTick(function () {
|
|
ee.emit('error', expected);
|
|
ee.emit('myevent', 42, 24);
|
|
});
|
|
|
|
// process.on('multipleResolves', common.mustNotCall());
|
|
|
|
return once(ee, 'myevent').then(common.mustNotCall, function (err) {
|
|
// process.removeAllListeners('multipleResolves');
|
|
assert.strictEqual(err, expected);
|
|
assert.strictEqual(ee.listenerCount('error'), 0);
|
|
assert.strictEqual(ee.listenerCount('myevent'), 0);
|
|
});
|
|
}
|
|
|
|
function onceError() {
|
|
var ee = new EventEmitter();
|
|
|
|
var expected = new Error('kaboom');
|
|
process.nextTick(function () {
|
|
ee.emit('error', expected);
|
|
});
|
|
|
|
var promise = once(ee, 'error');
|
|
assert.strictEqual(ee.listenerCount('error'), 1);
|
|
return promise.then(function (args) {
|
|
var err = args[0]
|
|
assert.strictEqual(err, expected);
|
|
assert.strictEqual(ee.listenerCount('error'), 0);
|
|
assert.strictEqual(ee.listenerCount('myevent'), 0);
|
|
});
|
|
}
|
|
|
|
function onceWithEventTarget() {
|
|
var et = new EventTargetMock();
|
|
var event = new Event('myevent');
|
|
process.nextTick(function () {
|
|
et.dispatchEvent(event);
|
|
});
|
|
return once(et, 'myevent').then(function (args) {
|
|
var value = args[0];
|
|
assert.strictEqual(value, event);
|
|
assert.strictEqual(has(et.events, 'myevent'), false);
|
|
});
|
|
}
|
|
|
|
function onceWithEventTargetError() {
|
|
var et = new EventTargetMock();
|
|
var error = new Event('error');
|
|
process.nextTick(function () {
|
|
et.dispatchEvent(error);
|
|
});
|
|
return once(et, 'error').then(function (args) {
|
|
var err = args[0];
|
|
assert.strictEqual(err, error);
|
|
assert.strictEqual(has(et.events, 'error'), false);
|
|
});
|
|
}
|
|
|
|
function prioritizesEventEmitter() {
|
|
var ee = new EventEmitter();
|
|
ee.addEventListener = assert.fail;
|
|
ee.removeAllListeners = assert.fail;
|
|
process.nextTick(function () {
|
|
ee.emit('foo');
|
|
});
|
|
return once(ee, 'foo');
|
|
}
|
|
|
|
var allTests = [
|
|
onceAnEvent(),
|
|
onceAnEventWithTwoArgs(),
|
|
catchesErrors(),
|
|
stopListeningAfterCatchingError(),
|
|
onceError(),
|
|
onceWithEventTarget(),
|
|
onceWithEventTargetError(),
|
|
prioritizesEventEmitter()
|
|
];
|
|
|
|
var hasBrowserEventTarget = false;
|
|
try {
|
|
hasBrowserEventTarget = typeof (new window.EventTarget().addEventListener) === 'function' &&
|
|
new window.Event('xyz').type === 'xyz';
|
|
} catch (err) {}
|
|
|
|
if (hasBrowserEventTarget) {
|
|
var onceWithBrowserEventTarget = function onceWithBrowserEventTarget() {
|
|
var et = new window.EventTarget();
|
|
var event = new window.Event('myevent');
|
|
process.nextTick(function () {
|
|
et.dispatchEvent(event);
|
|
});
|
|
return once(et, 'myevent').then(function (args) {
|
|
var value = args[0];
|
|
assert.strictEqual(value, event);
|
|
assert.strictEqual(has(et.events, 'myevent'), false);
|
|
});
|
|
}
|
|
|
|
var onceWithBrowserEventTargetError = function onceWithBrowserEventTargetError() {
|
|
var et = new window.EventTarget();
|
|
var error = new window.Event('error');
|
|
process.nextTick(function () {
|
|
et.dispatchEvent(error);
|
|
});
|
|
return once(et, 'error').then(function (args) {
|
|
var err = args[0];
|
|
assert.strictEqual(err, error);
|
|
assert.strictEqual(has(et.events, 'error'), false);
|
|
});
|
|
}
|
|
|
|
common.test.comment('Testing with browser built-in EventTarget');
|
|
allTests.push([
|
|
onceWithBrowserEventTarget(),
|
|
onceWithBrowserEventTargetError()
|
|
]);
|
|
}
|
|
|
|
module.exports = Promise.all(allTests);
|