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.
135 lines
4.2 KiB
JavaScript
135 lines
4.2 KiB
JavaScript
'use strict';
|
|
|
|
var identity = require('./nodes/identity.js');
|
|
var publicApi = require('./public-api.js');
|
|
var visit = require('./visit.js');
|
|
|
|
const scalarChar = {
|
|
BLOCK_FOLDED: '>',
|
|
BLOCK_LITERAL: '|',
|
|
PLAIN: ':',
|
|
QUOTE_DOUBLE: '"',
|
|
QUOTE_SINGLE: "'"
|
|
};
|
|
function anchorExists(doc, anchor) {
|
|
let found = false;
|
|
visit.visit(doc, {
|
|
Value(_key, node) {
|
|
if (node.anchor === anchor) {
|
|
found = true;
|
|
return visit.visit.BREAK;
|
|
}
|
|
}
|
|
});
|
|
return found;
|
|
}
|
|
// test harness for yaml-test-suite event tests
|
|
function testEvents(src) {
|
|
const docs = publicApi.parseAllDocuments(src);
|
|
const errDoc = docs.find(doc => doc.errors.length > 0);
|
|
const error = errDoc ? errDoc.errors[0].message : null;
|
|
const events = ['+STR'];
|
|
try {
|
|
for (let i = 0; i < docs.length; ++i) {
|
|
const doc = docs[i];
|
|
let root = doc.contents;
|
|
if (Array.isArray(root))
|
|
root = root[0];
|
|
const [rootStart] = doc.range || [0];
|
|
const error = doc.errors[0];
|
|
if (error && (!error.pos || error.pos[0] < rootStart))
|
|
throw new Error();
|
|
let docStart = '+DOC';
|
|
if (doc.directives.docStart)
|
|
docStart += ' ---';
|
|
else if (doc.contents &&
|
|
doc.contents.range[2] === doc.contents.range[0] &&
|
|
!doc.contents.anchor &&
|
|
!doc.contents.tag)
|
|
continue;
|
|
events.push(docStart);
|
|
addEvents(events, doc, error?.pos[0] ?? -1, root);
|
|
let docEnd = '-DOC';
|
|
if (doc.directives.docEnd)
|
|
docEnd += ' ...';
|
|
events.push(docEnd);
|
|
}
|
|
}
|
|
catch (e) {
|
|
return { events, error: error ?? e };
|
|
}
|
|
events.push('-STR');
|
|
return { events, error };
|
|
}
|
|
function addEvents(events, doc, errPos, node) {
|
|
if (!node) {
|
|
events.push('=VAL :');
|
|
return;
|
|
}
|
|
if (errPos !== -1 && identity.isNode(node) && node.range[0] >= errPos)
|
|
throw new Error();
|
|
let props = '';
|
|
let anchor = identity.isScalar(node) || identity.isCollection(node) ? node.anchor : undefined;
|
|
if (anchor) {
|
|
if (/\d$/.test(anchor)) {
|
|
const alt = anchor.replace(/\d$/, '');
|
|
if (anchorExists(doc, alt))
|
|
anchor = alt;
|
|
}
|
|
props = ` &${anchor}`;
|
|
}
|
|
if (identity.isNode(node) && node.tag)
|
|
props += ` <${node.tag}>`;
|
|
if (identity.isMap(node)) {
|
|
const ev = node.flow ? '+MAP {}' : '+MAP';
|
|
events.push(`${ev}${props}`);
|
|
node.items.forEach(({ key, value }) => {
|
|
addEvents(events, doc, errPos, key);
|
|
addEvents(events, doc, errPos, value);
|
|
});
|
|
events.push('-MAP');
|
|
}
|
|
else if (identity.isSeq(node)) {
|
|
const ev = node.flow ? '+SEQ []' : '+SEQ';
|
|
events.push(`${ev}${props}`);
|
|
node.items.forEach(item => {
|
|
addEvents(events, doc, errPos, item);
|
|
});
|
|
events.push('-SEQ');
|
|
}
|
|
else if (identity.isPair(node)) {
|
|
events.push(`+MAP${props}`);
|
|
addEvents(events, doc, errPos, node.key);
|
|
addEvents(events, doc, errPos, node.value);
|
|
events.push('-MAP');
|
|
}
|
|
else if (identity.isAlias(node)) {
|
|
let alias = node.source;
|
|
if (alias && /\d$/.test(alias)) {
|
|
const alt = alias.replace(/\d$/, '');
|
|
if (anchorExists(doc, alt))
|
|
alias = alt;
|
|
}
|
|
events.push(`=ALI${props} *${alias}`);
|
|
}
|
|
else {
|
|
const scalar = scalarChar[String(node.type)];
|
|
if (!scalar)
|
|
throw new Error(`Unexpected node type ${node.type}`);
|
|
const value = node.source
|
|
.replace(/\\/g, '\\\\')
|
|
.replace(/\0/g, '\\0')
|
|
.replace(/\x07/g, '\\a')
|
|
.replace(/\x08/g, '\\b')
|
|
.replace(/\t/g, '\\t')
|
|
.replace(/\n/g, '\\n')
|
|
.replace(/\v/g, '\\v')
|
|
.replace(/\f/g, '\\f')
|
|
.replace(/\r/g, '\\r')
|
|
.replace(/\x1b/g, '\\e');
|
|
events.push(`=VAL${props} ${scalar}${value}`);
|
|
}
|
|
}
|
|
|
|
exports.testEvents = testEvents;
|