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.
155 lines
4.1 KiB
JavaScript
155 lines
4.1 KiB
JavaScript
/**
|
|
* @fileoverview An object that caches and applies source code fixes.
|
|
* @author Nicholas C. Zakas
|
|
*/
|
|
"use strict";
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Requirements
|
|
//------------------------------------------------------------------------------
|
|
|
|
const debug = require("debug")("eslint:source-code-fixer");
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Helpers
|
|
//------------------------------------------------------------------------------
|
|
|
|
const BOM = "\uFEFF";
|
|
|
|
/**
|
|
* Compares items in a messages array by range.
|
|
* @param {Message} a The first message.
|
|
* @param {Message} b The second message.
|
|
* @returns {number} -1 if a comes before b, 1 if a comes after b, 0 if equal.
|
|
* @private
|
|
*/
|
|
function compareMessagesByFixRange(a, b) {
|
|
return a.fix.range[0] - b.fix.range[0] || a.fix.range[1] - b.fix.range[1];
|
|
}
|
|
|
|
/**
|
|
* Compares items in a messages array by line and column.
|
|
* @param {Message} a The first message.
|
|
* @param {Message} b The second message.
|
|
* @returns {number} -1 if a comes before b, 1 if a comes after b, 0 if equal.
|
|
* @private
|
|
*/
|
|
function compareMessagesByLocation(a, b) {
|
|
return a.line - b.line || a.column - b.column;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Public Interface
|
|
//------------------------------------------------------------------------------
|
|
|
|
/**
|
|
* Utility for apply fixes to source code.
|
|
* @constructor
|
|
*/
|
|
function SourceCodeFixer() {
|
|
Object.freeze(this);
|
|
}
|
|
|
|
/**
|
|
* Applies the fixes specified by the messages to the given text. Tries to be
|
|
* smart about the fixes and won't apply fixes over the same area in the text.
|
|
* @param {string} sourceText The text to apply the changes to.
|
|
* @param {Message[]} messages The array of messages reported by ESLint.
|
|
* @param {boolean|Function} [shouldFix=true] Determines whether each message should be fixed
|
|
* @returns {Object} An object containing the fixed text and any unfixed messages.
|
|
*/
|
|
SourceCodeFixer.applyFixes = function (sourceText, messages, shouldFix) {
|
|
debug("Applying fixes");
|
|
|
|
if (shouldFix === false) {
|
|
debug("shouldFix parameter was false, not attempting fixes");
|
|
return {
|
|
fixed: false,
|
|
messages,
|
|
output: sourceText,
|
|
};
|
|
}
|
|
|
|
// clone the array
|
|
const remainingMessages = [],
|
|
fixes = [],
|
|
bom = sourceText.startsWith(BOM) ? BOM : "",
|
|
text = bom ? sourceText.slice(1) : sourceText;
|
|
let lastPos = Number.NEGATIVE_INFINITY,
|
|
output = bom;
|
|
|
|
/**
|
|
* Try to use the 'fix' from a problem.
|
|
* @param {Message} problem The message object to apply fixes from
|
|
* @returns {boolean} Whether fix was successfully applied
|
|
*/
|
|
function attemptFix(problem) {
|
|
const fix = problem.fix;
|
|
const start = fix.range[0];
|
|
const end = fix.range[1];
|
|
|
|
// Remain it as a problem if it's overlapped or it's a negative range
|
|
if (lastPos >= start || start > end) {
|
|
remainingMessages.push(problem);
|
|
return false;
|
|
}
|
|
|
|
// Remove BOM.
|
|
if (
|
|
(start < 0 && end >= 0) ||
|
|
(start === 0 && fix.text.startsWith(BOM))
|
|
) {
|
|
output = "";
|
|
}
|
|
|
|
// Make output to this fix.
|
|
output += text.slice(Math.max(0, lastPos), Math.max(0, start));
|
|
output += fix.text;
|
|
lastPos = end;
|
|
return true;
|
|
}
|
|
|
|
messages.forEach(problem => {
|
|
if (Object.hasOwn(problem, "fix") && problem.fix) {
|
|
fixes.push(problem);
|
|
} else {
|
|
remainingMessages.push(problem);
|
|
}
|
|
});
|
|
|
|
if (fixes.length) {
|
|
debug("Found fixes to apply");
|
|
let fixesWereApplied = false;
|
|
|
|
for (const problem of fixes.sort(compareMessagesByFixRange)) {
|
|
if (typeof shouldFix !== "function" || shouldFix(problem)) {
|
|
attemptFix(problem);
|
|
|
|
/*
|
|
* The only time attemptFix will fail is if a previous fix was
|
|
* applied which conflicts with it. So we can mark this as true.
|
|
*/
|
|
fixesWereApplied = true;
|
|
} else {
|
|
remainingMessages.push(problem);
|
|
}
|
|
}
|
|
output += text.slice(Math.max(0, lastPos));
|
|
|
|
return {
|
|
fixed: fixesWereApplied,
|
|
messages: remainingMessages.sort(compareMessagesByLocation),
|
|
output,
|
|
};
|
|
}
|
|
|
|
debug("No fixes to apply");
|
|
return {
|
|
fixed: false,
|
|
messages,
|
|
output: bom + text,
|
|
};
|
|
};
|
|
|
|
module.exports = SourceCodeFixer;
|