Phase 1: Add ESLint/Prettier config + baseline auto-fixes

This commit is contained in:
Krystie
2026-03-22 11:00:25 +01:00
parent 41a0cdee7e
commit e2c67a8fe8
90 changed files with 4008 additions and 3066 deletions

View File

@@ -38,16 +38,16 @@ module.exports = function(ctx) {
const templateImage = template.docker.image.split(':')[0];
for (const container of containers) {
const containerImage = container.Image.split(':')[0];
if (containerImage === templateImage || containerImage.endsWith('/' + templateImage)) {
if (containerImage === templateImage || containerImage.endsWith(`/${ templateImage}`)) {
const ports = container.Ports.filter(p => p.PublicPort).map(p => ({
hostPort: p.PublicPort, containerPort: p.PrivatePort, protocol: p.Type
hostPort: p.PublicPort, containerPort: p.PrivatePort, protocol: p.Type,
}));
return {
id: container.Id, shortId: container.Id.slice(0, 12),
name: container.Names[0]?.replace(/^\//, '') || 'unknown',
image: container.Image, status: container.Status, state: container.State,
ports, primaryPort: ports.length > 0 ? ports[0].hostPort : null,
labels: container.Labels || {}
labels: container.Labels || {},
};
}
}
@@ -72,7 +72,7 @@ module.exports = function(ctx) {
'{{PORT}}': config.port || template.defaultPort,
'{{MEDIA_PATH}}': mediaPaths[0] || '/media',
'{{TIMEZONE}}': ctx.siteConfig.timezone || 'UTC',
'{{GENERATED_SECRET}}': crypto.randomBytes(32).toString('hex')
'{{GENERATED_SECRET}}': crypto.randomBytes(32).toString('hex'),
};
function replaceInObject(obj) {
@@ -117,7 +117,7 @@ module.exports = function(ctx) {
const basePath = `/${config.subdomain}`;
// Some apps need the full URL, not just the path
if (['GF_SERVER_ROOT_URL', 'GITEA__server__ROOT_URL'].includes(template.urlBaseEnv)) {
processed.docker.environment[template.urlBaseEnv] = ctx.buildServiceUrl(config.subdomain) + '/';
processed.docker.environment[template.urlBaseEnv] = `${ctx.buildServiceUrl(config.subdomain) }/`;
} else {
processed.docker.environment[template.urlBaseEnv] = basePath;
}
@@ -137,7 +137,7 @@ module.exports = function(ctx) {
config.mediaPath.split(',').map(p => p.trim()).filter(Boolean).forEach(p => allowedRoots.push(path.resolve(p)));
}
const isAllowed = allowedRoots.some(root =>
normalizedHost === root || normalizedHost.startsWith(root + path.sep)
normalizedHost === root || normalizedHost.startsWith(root + path.sep),
);
if (!isAllowed) {
ctx.log.warn('deploy', 'Custom volume host path rejected', { hostPath: override.hostPath, allowed: allowedRoots });
@@ -162,76 +162,76 @@ module.exports = function(ctx) {
c += ` root * ${sitePath}\n\n`;
if (tailscaleOnly) {
c += ` @blocked not remote_ip 100.64.0.0/10\n`;
c += ` respond @blocked "Access denied. Tailscale connection required." 403\n\n`;
c += ' @blocked not remote_ip 100.64.0.0/10\n';
c += ' respond @blocked "Access denied. Tailscale connection required." 403\n\n';
}
if (apiProxy) {
c += ` handle /api/* {\n`;
c += ' handle /api/* {\n';
c += ` reverse_proxy ${apiProxy}\n`;
c += ` }\n\n`;
c += ' }\n\n';
}
c += ` @crt path *.crt\n`;
c += ` handle @crt {\n`;
c += ` header Content-Type application/x-x509-ca-cert\n`;
c += ` header Content-Disposition "attachment; filename=\\"{file}\\""\n`;
c += ` header Cache-Control "public, max-age=86400"\n`;
c += ` file_server\n`;
c += ` }\n\n`;
c += ` @der path *.der\n`;
c += ` handle @der {\n`;
c += ` header Content-Type application/x-x509-ca-cert\n`;
c += ` header Content-Disposition "attachment; filename=\\"{file}\\""\n`;
c += ` header Cache-Control "public, max-age=86400"\n`;
c += ` file_server\n`;
c += ` }\n\n`;
c += ` @mobileconfig path *.mobileconfig\n`;
c += ` handle @mobileconfig {\n`;
c += ` header Content-Type application/x-apple-aspen-config\n`;
c += ` header Content-Disposition "attachment; filename=\\"{file}\\""\n`;
c += ` header Cache-Control "public, max-age=86400"\n`;
c += ` file_server\n`;
c += ` }\n\n`;
c += ` @ps1 path *.ps1\n`;
c += ` handle @ps1 {\n`;
c += ` header Content-Type text/plain\n`;
c += ` header Content-Disposition "attachment; filename=\\"{file}\\""\n`;
c += ` file_server\n`;
c += ` }\n\n`;
c += ` @sh path *.sh\n`;
c += ` handle @sh {\n`;
c += ` header Content-Type text/x-shellscript\n`;
c += ` header Content-Disposition "attachment; filename=\\"{file}\\""\n`;
c += ` file_server\n`;
c += ` }\n\n`;
c += ` # Static site with SPA fallback\n`;
c += ` handle {\n`;
c += ` @notFile not file {path}\n`;
c += ` rewrite @notFile /index.html\n`;
c += ` file_server\n`;
c += ` }\n\n`;
c += ` # No cache for HTML\n`;
c += ` @htmlfiles {\n`;
c += ` path *.html\n`;
c += ` path /\n`;
c += ` }\n`;
c += ` header @htmlfiles Cache-Control "no-store"\n`;
c += ' @crt path *.crt\n';
c += ' handle @crt {\n';
c += ' header Content-Type application/x-x509-ca-cert\n';
c += ' header Content-Disposition "attachment; filename=\\"{file}\\""\n';
c += ' header Cache-Control "public, max-age=86400"\n';
c += ' file_server\n';
c += ' }\n\n';
c += ' @der path *.der\n';
c += ' handle @der {\n';
c += ' header Content-Type application/x-x509-ca-cert\n';
c += ' header Content-Disposition "attachment; filename=\\"{file}\\""\n';
c += ' header Cache-Control "public, max-age=86400"\n';
c += ' file_server\n';
c += ' }\n\n';
c += ' @mobileconfig path *.mobileconfig\n';
c += ' handle @mobileconfig {\n';
c += ' header Content-Type application/x-apple-aspen-config\n';
c += ' header Content-Disposition "attachment; filename=\\"{file}\\""\n';
c += ' header Cache-Control "public, max-age=86400"\n';
c += ' file_server\n';
c += ' }\n\n';
c += ' @ps1 path *.ps1\n';
c += ' handle @ps1 {\n';
c += ' header Content-Type text/plain\n';
c += ' header Content-Disposition "attachment; filename=\\"{file}\\""\n';
c += ' file_server\n';
c += ' }\n\n';
c += ' @sh path *.sh\n';
c += ' handle @sh {\n';
c += ' header Content-Type text/x-shellscript\n';
c += ' header Content-Disposition "attachment; filename=\\"{file}\\""\n';
c += ' file_server\n';
c += ' }\n\n';
c += ' # Static site with SPA fallback\n';
c += ' handle {\n';
c += ' @notFile not file {path}\n';
c += ' rewrite @notFile /index.html\n';
c += ' file_server\n';
c += ' }\n\n';
c += ' # No cache for HTML\n';
c += ' @htmlfiles {\n';
c += ' path *.html\n';
c += ' path /\n';
c += ' }\n';
c += ' header @htmlfiles Cache-Control "no-store"\n';
return c;
}
// HTTPS block
let config = `${domain} {\n`;
config += ` tls internal\n\n`;
config += ' tls internal\n\n';
config += siteBlockContent();
config += `}`;
config += '}';
// HTTP companion block for devices that haven't trusted the CA yet
if (httpAccess) {
config += `\n\n# HTTP access for first-time certificate installation\n`;
config += '\n\n# HTTP access for first-time certificate installation\n';
config += `http://${domain} {\n`;
config += siteBlockContent();
config += `}`;
config += '}';
}
return config;
@@ -254,7 +254,7 @@ module.exports = function(ctx) {
} else if (healthPath && port && httpCheckFailed < 5) {
try {
const response = await ctx.fetchT(`http://localhost:${port}${healthPath}`, {
signal: AbortSignal.timeout(3000), redirect: 'manual'
signal: AbortSignal.timeout(3000), redirect: 'manual',
});
if (response.ok || (response.status >= 300 && response.status < 400)) {
ctx.log.info('docker', 'Health check passed', { containerId, status: response.status });
@@ -290,7 +290,7 @@ module.exports = function(ctx) {
await ctx.caddy.reload(existing);
return;
}
const result = await ctx.caddy.modify(c => c + `\n${config}\n`);
const result = await ctx.caddy.modify(c => `${c }\n${config}\n`);
if (!result.success) throw new Error(`[DC-303] Failed to add Caddy config for ${domain}: ${result.error}`);
await ctx.caddy.verifySite(domain);
}
@@ -405,6 +405,6 @@ module.exports = function(ctx) {
removeSubpathConfig,
ensureMainDomainBlock,
RESERVED_SUBPATHS,
generateStaticSiteConfig
generateStaticSiteConfig,
};
};