chore(quality): resolve SonarQube code smells across website
Clears the 124 CODE_SMELL findings from the SonarQube scan (server, client, and bot). All changes are behaviour-preserving refactors — no route, protocol, schema, or config changes — verified against the full server (381) and client (43) test suites plus a clean client build. By rule: - S3776 (20, cognitive complexity): extract helpers/handlers so each function drops under the threshold — shard model upsert builders, page/wiki update, block validation, notification stream mapping (dispatch table), SSO mobile login, shard ingest deps, uo-link socket backfill/connect, the bot slash- command dispatchers + discord manager, and the Shard/UserDetail/HeroEditor/ CharacterStats React components. - S4624 (34, nested template literals): pull inner templates into locals / a withQs() helper; rewrite shardEvents.describe() as a formatter table. - S3358 (35, nested ternaries): lift to if/else vars, lookup maps, small components, or guarded JSX expressions. - S6479 (12, array-index React keys): key by stable content instead of index (two in-editor lists left as-is; index matches their by-index edit model). - S6353 (6): [0-9]/[^0-9] -> \d/\D. S125 (5): reword state-shape comments that parsed as code. S3800/S3782 (botScore): JSDoc-type PATH_WEIGHTS tuples. - S6481 (2): memoize Auth/Site context values (and SiteContext brand). - S4144: dedupe HeroEditor upload handler into useImageUpload(). - S1126 (2), S6035, S5869 (redundant A-Z under /i), S5843 (town-name regex -> prefix list): assorted one-liners. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,10 @@
|
||||
// same-origin API (/api/v1) — proxied to the Express server in dev.
|
||||
const BASE = '/api/v1'
|
||||
|
||||
// Prefix a non-empty query string with "?" (and nothing when it is empty), so
|
||||
// callers can append it to a path without a dangling "?".
|
||||
const withQs = (s) => (s ? `?${s}` : '')
|
||||
|
||||
class ApiError extends Error {
|
||||
constructor(status, message, body) {
|
||||
super(message)
|
||||
@@ -84,7 +88,7 @@ export const api = {
|
||||
if (opts.tag) qs.set('tag', opts.tag)
|
||||
if (opts.q) qs.set('q', opts.q)
|
||||
const s = qs.toString()
|
||||
return req(`/public/wiki${s ? `?${s}` : ''}`)
|
||||
return req(`/public/wiki${withQs(s)}`)
|
||||
},
|
||||
wikiCategories: () => req('/public/wiki/categories'),
|
||||
wikiTags: () => req('/public/wiki/tags'),
|
||||
@@ -105,17 +109,22 @@ export const api = {
|
||||
if (opts.kind) qs.set('kind', opts.kind)
|
||||
if (opts.limit) qs.set('limit', opts.limit)
|
||||
const s = qs.toString()
|
||||
return req(`/public/shard/feed${s ? `?${s}` : ''}`)
|
||||
return req(`/public/shard/feed${withQs(s)}`)
|
||||
},
|
||||
economy: (limit) => {
|
||||
const q = limit ? `limit=${limit}` : ''
|
||||
return req(`/public/shard/economy${withQs(q)}`)
|
||||
},
|
||||
economy: (limit) => req(`/public/shard/economy${limit ? `?limit=${limit}` : ''}`),
|
||||
online: () => req('/public/shard/online'),
|
||||
idoc: () => req('/public/shard/idoc'),
|
||||
champs: () => req('/public/shard/champs'),
|
||||
// Protocol 2.0 boards.
|
||||
guilds: () => req('/public/shard/guilds'),
|
||||
governors: () => req('/public/shard/governors'),
|
||||
governorHistory: (city, limit) =>
|
||||
req(`/public/shard/governors/${encodeURIComponent(city)}/history${limit ? `?limit=${limit}` : ''}`),
|
||||
governorHistory: (city, limit) => {
|
||||
const q = limit ? `limit=${limit}` : ''
|
||||
return req(`/public/shard/governors/${encodeURIComponent(city)}/history${withQs(q)}`)
|
||||
},
|
||||
presence: () => req('/public/shard/presence'),
|
||||
houses: () => req('/public/shard/houses'),
|
||||
},
|
||||
@@ -129,7 +138,10 @@ export const api = {
|
||||
admin: {
|
||||
dashboard: () => req('/admin/dashboard'),
|
||||
setSiteMode: (mode) => req('/admin/site-mode', { method: 'PUT', body: { mode } }),
|
||||
listPosts: (category) => req(`/admin/posts${category ? `?category=${category}` : ''}`),
|
||||
listPosts: (category) => {
|
||||
const q = category ? `category=${category}` : ''
|
||||
return req(`/admin/posts${withQs(q)}`)
|
||||
},
|
||||
getPost: (id) => req(`/admin/posts/${id}`),
|
||||
createPost: (data) => req('/admin/posts', { method: 'POST', body: data }),
|
||||
updatePost: (id, data) => req(`/admin/posts/${id}`, { method: 'PUT', body: data }),
|
||||
@@ -216,7 +228,7 @@ export const api = {
|
||||
if (params.limit) qs.set('limit', params.limit)
|
||||
if (params.offset) qs.set('offset', params.offset)
|
||||
const s = qs.toString()
|
||||
return req(`/admin/moderation/recent${s ? `?${s}` : ''}`)
|
||||
return req(`/admin/moderation/recent${withQs(s)}`)
|
||||
},
|
||||
modSearch: (q) => req(`/admin/moderation/search?q=${encodeURIComponent(q)}`),
|
||||
modMembers: (params = {}) => {
|
||||
@@ -225,21 +237,21 @@ export const api = {
|
||||
if (params.limit) qs.set('limit', params.limit)
|
||||
if (params.offset) qs.set('offset', params.offset)
|
||||
const s = qs.toString()
|
||||
return req(`/admin/moderation/members${s ? `?${s}` : ''}`)
|
||||
return req(`/admin/moderation/members${withQs(s)}`)
|
||||
},
|
||||
modFilterHits: (params = {}) => {
|
||||
const qs = new URLSearchParams()
|
||||
if (params.limit) qs.set('limit', params.limit)
|
||||
if (params.offset) qs.set('offset', params.offset)
|
||||
const s = qs.toString()
|
||||
return req(`/admin/moderation/filter-hits${s ? `?${s}` : ''}`)
|
||||
return req(`/admin/moderation/filter-hits${withQs(s)}`)
|
||||
},
|
||||
modSpamHits: (params = {}) => {
|
||||
const qs = new URLSearchParams()
|
||||
if (params.limit) qs.set('limit', params.limit)
|
||||
if (params.offset) qs.set('offset', params.offset)
|
||||
const s = qs.toString()
|
||||
return req(`/admin/moderation/spam-hits${s ? `?${s}` : ''}`)
|
||||
return req(`/admin/moderation/spam-hits${withQs(s)}`)
|
||||
},
|
||||
modUser: (discordId) => req(`/admin/moderation/user/${discordId}`),
|
||||
modUserActions: (discordId, params = {}) => {
|
||||
@@ -248,7 +260,7 @@ export const api = {
|
||||
if (params.limit) qs.set('limit', params.limit)
|
||||
if (params.offset) qs.set('offset', params.offset)
|
||||
const s = qs.toString()
|
||||
return req(`/admin/moderation/user/${discordId}/actions${s ? `?${s}` : ''}`)
|
||||
return req(`/admin/moderation/user/${discordId}/actions${withQs(s)}`)
|
||||
},
|
||||
modUserNotes: (discordId) => req(`/admin/moderation/user/${discordId}/notes`),
|
||||
addModNote: (discordId, data) =>
|
||||
@@ -261,7 +273,7 @@ export const api = {
|
||||
if (params.limit) qs.set('limit', params.limit)
|
||||
if (params.offset) qs.set('offset', params.offset)
|
||||
const s = qs.toString()
|
||||
return req(`/admin/moderation/appeals${s ? `?${s}` : ''}`)
|
||||
return req(`/admin/moderation/appeals${withQs(s)}`)
|
||||
},
|
||||
getAppeal: (id) => req(`/admin/moderation/appeals/${id}`),
|
||||
claimAppeal: (id) => req(`/admin/moderation/appeals/${id}/claim`, { method: 'POST' }),
|
||||
|
||||
Reference in New Issue
Block a user