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.
154 lines
5.4 KiB
JavaScript
154 lines
5.4 KiB
JavaScript
import { isNode, isPair } from '../nodes/identity.js';
|
|
import { stringify } from './stringify.js';
|
|
import { lineComment, indentComment } from './stringifyComment.js';
|
|
|
|
function stringifyCollection(collection, ctx, options) {
|
|
const flow = ctx.inFlow ?? collection.flow;
|
|
const stringify = flow ? stringifyFlowCollection : stringifyBlockCollection;
|
|
return stringify(collection, ctx, options);
|
|
}
|
|
function stringifyBlockCollection({ comment, items }, ctx, { blockItemPrefix, flowChars, itemIndent, onChompKeep, onComment }) {
|
|
const { indent, options: { commentString } } = ctx;
|
|
const itemCtx = Object.assign({}, ctx, { indent: itemIndent, type: null });
|
|
let chompKeep = false; // flag for the preceding node's status
|
|
const lines = [];
|
|
for (let i = 0; i < items.length; ++i) {
|
|
const item = items[i];
|
|
let comment = null;
|
|
if (isNode(item)) {
|
|
if (!chompKeep && item.spaceBefore)
|
|
lines.push('');
|
|
addCommentBefore(ctx, lines, item.commentBefore, chompKeep);
|
|
if (item.comment)
|
|
comment = item.comment;
|
|
}
|
|
else if (isPair(item)) {
|
|
const ik = isNode(item.key) ? item.key : null;
|
|
if (ik) {
|
|
if (!chompKeep && ik.spaceBefore)
|
|
lines.push('');
|
|
addCommentBefore(ctx, lines, ik.commentBefore, chompKeep);
|
|
}
|
|
}
|
|
chompKeep = false;
|
|
let str = stringify(item, itemCtx, () => (comment = null), () => (chompKeep = true));
|
|
if (comment)
|
|
str += lineComment(str, itemIndent, commentString(comment));
|
|
if (chompKeep && comment)
|
|
chompKeep = false;
|
|
lines.push(blockItemPrefix + str);
|
|
}
|
|
let str;
|
|
if (lines.length === 0) {
|
|
str = flowChars.start + flowChars.end;
|
|
}
|
|
else {
|
|
str = lines[0];
|
|
for (let i = 1; i < lines.length; ++i) {
|
|
const line = lines[i];
|
|
str += line ? `\n${indent}${line}` : '\n';
|
|
}
|
|
}
|
|
if (comment) {
|
|
str += '\n' + indentComment(commentString(comment), indent);
|
|
if (onComment)
|
|
onComment();
|
|
}
|
|
else if (chompKeep && onChompKeep)
|
|
onChompKeep();
|
|
return str;
|
|
}
|
|
function stringifyFlowCollection({ items }, ctx, { flowChars, itemIndent }) {
|
|
const { indent, indentStep, flowCollectionPadding: fcPadding, options: { commentString } } = ctx;
|
|
itemIndent += indentStep;
|
|
const itemCtx = Object.assign({}, ctx, {
|
|
indent: itemIndent,
|
|
inFlow: true,
|
|
type: null
|
|
});
|
|
let reqNewline = false;
|
|
let linesAtValue = 0;
|
|
const lines = [];
|
|
for (let i = 0; i < items.length; ++i) {
|
|
const item = items[i];
|
|
let comment = null;
|
|
if (isNode(item)) {
|
|
if (item.spaceBefore)
|
|
lines.push('');
|
|
addCommentBefore(ctx, lines, item.commentBefore, false);
|
|
if (item.comment)
|
|
comment = item.comment;
|
|
}
|
|
else if (isPair(item)) {
|
|
const ik = isNode(item.key) ? item.key : null;
|
|
if (ik) {
|
|
if (ik.spaceBefore)
|
|
lines.push('');
|
|
addCommentBefore(ctx, lines, ik.commentBefore, false);
|
|
if (ik.comment)
|
|
reqNewline = true;
|
|
}
|
|
const iv = isNode(item.value) ? item.value : null;
|
|
if (iv) {
|
|
if (iv.comment)
|
|
comment = iv.comment;
|
|
if (iv.commentBefore)
|
|
reqNewline = true;
|
|
}
|
|
else if (item.value == null && ik?.comment) {
|
|
comment = ik.comment;
|
|
}
|
|
}
|
|
if (comment)
|
|
reqNewline = true;
|
|
let str = stringify(item, itemCtx, () => (comment = null));
|
|
reqNewline || (reqNewline = lines.length > linesAtValue || str.includes('\n'));
|
|
if (i < items.length - 1) {
|
|
str += ',';
|
|
}
|
|
else if (ctx.options.trailingComma) {
|
|
if (ctx.options.lineWidth > 0) {
|
|
reqNewline || (reqNewline = lines.reduce((sum, line) => sum + line.length + 2, 2) +
|
|
(str.length + 2) >
|
|
ctx.options.lineWidth);
|
|
}
|
|
if (reqNewline) {
|
|
str += ',';
|
|
}
|
|
}
|
|
if (comment)
|
|
str += lineComment(str, itemIndent, commentString(comment));
|
|
lines.push(str);
|
|
linesAtValue = lines.length;
|
|
}
|
|
const { start, end } = flowChars;
|
|
if (lines.length === 0) {
|
|
return start + end;
|
|
}
|
|
else {
|
|
if (!reqNewline) {
|
|
const len = lines.reduce((sum, line) => sum + line.length + 2, 2);
|
|
reqNewline = ctx.options.lineWidth > 0 && len > ctx.options.lineWidth;
|
|
}
|
|
if (reqNewline) {
|
|
let str = start;
|
|
for (const line of lines)
|
|
str += line ? `\n${indentStep}${indent}${line}` : '\n';
|
|
return `${str}\n${indent}${end}`;
|
|
}
|
|
else {
|
|
return `${start}${fcPadding}${lines.join(' ')}${fcPadding}${end}`;
|
|
}
|
|
}
|
|
}
|
|
function addCommentBefore({ indent, options: { commentString } }, lines, comment, chompKeep) {
|
|
if (comment && chompKeep)
|
|
comment = comment.replace(/^\n+/, '');
|
|
if (comment) {
|
|
const ic = indentComment(commentString(comment), indent);
|
|
lines.push(ic.trimStart()); // Avoid double indent on first line
|
|
}
|
|
}
|
|
|
|
export { stringifyCollection };
|