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

@@ -42,7 +42,7 @@ module.exports = function(ctx) {
await ctx.docker.client.createNetwork({
Name: networkName,
Driver: recipe.network.driver || 'bridge',
Labels: { 'sami.managed': 'true', 'sami.recipe': recipeId }
Labels: { 'sami.managed': 'true', 'sami.recipe': recipeId },
});
ctx.log.info('recipe', 'Created Docker network', { networkName });
} catch (e) {
@@ -62,18 +62,18 @@ module.exports = function(ctx) {
try {
ctx.log.info('recipe', `Deploying component: ${component.id}`, {
role: component.role,
internal: component.internal || false
internal: component.internal || false,
});
const result = await deployComponent(component, recipe, config, generatedPasswords, networkName);
deployedComponents.push(result);
ctx.log.info('recipe', `Component deployed: ${component.id}`, {
containerId: result.containerId?.substring(0, 12)
containerId: result.containerId?.substring(0, 12),
});
} catch (componentError) {
ctx.log.error('recipe', `Component failed: ${component.id}`, {
error: componentError.message
error: componentError.message,
});
errors.push({ componentId: component.id, role: component.role, error: componentError.message });
// Continue deploying other components — partial success is better than total failure
@@ -96,7 +96,7 @@ module.exports = function(ctx) {
recipeId: recipeId,
recipeRole: deployed.role,
tailscaleOnly: config.sharedConfig?.tailscaleOnly || false,
deployedAt: new Date().toISOString()
deployedAt: new Date().toISOString(),
});
}
}
@@ -119,18 +119,18 @@ module.exports = function(ctx) {
role: c.role,
containerId: c.containerId?.substring(0, 12),
url: c.url,
internal: c.internal
internal: c.internal,
})),
errors: errors.length > 0 ? errors : undefined,
message: errors.length > 0
? `${recipe.name} partially deployed (${deployedComponents.length}/${componentsToDeploy.length} components)`
: `${recipe.name} deployed successfully!`,
setupInstructions: recipe.setupInstructions
setupInstructions: recipe.setupInstructions,
};
ctx.notification.send('deploymentSuccess', 'Recipe Deployed',
`**${recipe.name}** recipe deployed (${deployedComponents.length} components).`,
'success'
'success',
);
res.json(response);
@@ -146,7 +146,7 @@ module.exports = function(ctx) {
}
} catch (cleanupError) {
ctx.log.warn('recipe', 'Cleanup failed for component', {
componentId: deployed.id, error: cleanupError.message
componentId: deployed.id, error: cleanupError.message,
});
}
}
@@ -162,7 +162,7 @@ module.exports = function(ctx) {
}
ctx.notification.send('deploymentFailed', 'Recipe Failed',
`Failed to deploy **${recipe.name}**: ${error.message}`, 'error'
`Failed to deploy **${recipe.name}**: ${error.message}`, 'error',
);
ctx.errorResponse(res, 500, error.message);
@@ -254,7 +254,7 @@ module.exports = function(ctx) {
HostConfig: {
PortBindings: {},
Binds: dockerConfig.volumes || [],
RestartPolicy: { Name: 'unless-stopped' }
RestartPolicy: { Name: 'unless-stopped' },
},
Env: Object.entries(dockerConfig.environment || {}).map(([k, v]) => `${k}=${v}`),
Labels: {
@@ -264,8 +264,8 @@ module.exports = function(ctx) {
'sami.recipe.component': component.id,
'sami.recipe.role': component.role,
'sami.subdomain': subdomain,
'sami.deployed': new Date().toISOString()
}
'sami.deployed': new Date().toISOString(),
},
};
// Configure ports
@@ -288,7 +288,7 @@ module.exports = function(ctx) {
} catch (e) {
ctx.log.warn('recipe', `Pull failed, checking local: ${dockerConfig.image}`);
const images = await ctx.docker.client.listImages({
filters: { reference: [dockerConfig.image] }
filters: { reference: [dockerConfig.image] },
});
if (images.length === 0) throw new Error(`Image not found: ${dockerConfig.image}`);
}
@@ -324,7 +324,7 @@ module.exports = function(ctx) {
const primaryPort = port || dockerConfig.ports[0].split(/[:/]/)[0];
const caddyConfig = ctx.caddy.generateConfig(
subdomain, hostIp, primaryPort,
{ tailscaleOnly: sharedConfig.tailscaleOnly || false }
{ tailscaleOnly: sharedConfig.tailscaleOnly || false },
);
try {
const helpers = require('../apps/helpers')(ctx);
@@ -344,7 +344,7 @@ module.exports = function(ctx) {
internal: component.internal || false,
templateRef: component.templateRef,
logo,
url
url,
};
}

View File

@@ -29,9 +29,9 @@ module.exports = function(ctx) {
required: c.required,
internal: c.internal || false,
templateRef: c.templateRef || null,
note: c.note || null
note: c.note || null,
})),
setupInstructions: recipe.setupInstructions
setupInstructions: recipe.setupInstructions,
}));
res.json({ success: true, templates, categories: RECIPE_CATEGORIES });

View File

@@ -16,7 +16,7 @@ module.exports = function(ctx) {
if (!recipeGroups[service.recipeId]) {
recipeGroups[service.recipeId] = {
recipeId: service.recipeId,
components: []
components: [],
};
}
recipeGroups[service.recipeId].components.push({
@@ -25,7 +25,7 @@ module.exports = function(ctx) {
logo: service.logo,
containerId: service.containerId,
recipeRole: service.recipeRole,
deployedAt: service.deployedAt
deployedAt: service.deployedAt,
});
}
@@ -48,7 +48,7 @@ module.exports = function(ctx) {
// Check if this container is already listed (by containerId)
const existing = recipeGroups[recipeId].components.find(
c => c.containerId === containerInfo.Id
c => c.containerId === containerInfo.Id,
);
if (existing) continue;
@@ -59,7 +59,7 @@ module.exports = function(ctx) {
recipeRole: labels['sami.recipe.role'] || 'Unknown',
internal: true,
state: containerInfo.State,
status: containerInfo.Status
status: containerInfo.Status,
});
}
} catch (e) {
@@ -242,7 +242,7 @@ module.exports = function(ctx) {
ctx.notification.send('recipeRemoved', 'Recipe Removed',
`Removed **${recipeId}** recipe (${results.filter(r => r.status === 'removed').length} containers).`,
'info'
'info',
);
ctx.log.info('recipe', 'Recipe removed', { recipeId, results });
@@ -271,7 +271,7 @@ module.exports = function(ctx) {
Id: c.Id,
component: c.Labels['sami.recipe.component'] || c.Names[0]?.replace('/', ''),
role: c.Labels['sami.recipe.role'] || 'Unknown',
state: c.State
state: c.State,
}));
}
@@ -293,7 +293,7 @@ module.exports = function(ctx) {
*/
async function removeCaddyBlock(subdomain) {
const domain = ctx.buildDomain(subdomain);
let content = await ctx.caddy.read();
const content = await ctx.caddy.read();
// Find and remove the block for this domain
const escapedDomain = domain.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');