Compare commits

..

2 Commits

Author SHA1 Message Date
pluja
9a68112e24 Release 202505311113 2025-05-31 11:13:24 +00:00
pluja
0c40d8eec5 Release 202505311002 2025-05-31 10:02:50 +00:00
4 changed files with 81 additions and 21 deletions

View File

@@ -15,26 +15,18 @@ const links = [
icon: 'ri:git-repository-line', icon: 'ri:git-repository-line',
external: true, external: true,
}, },
...(Astro.url.origin !== new URL(ONION_ADDRESS).origin {
? [ href: ONION_ADDRESS,
{ label: 'Tor',
href: ONION_ADDRESS, icon: 'onion',
label: 'Tor', external: true,
icon: 'onion', },
external: true, {
}, href: I2P_ADDRESS,
] label: 'I2P',
: []), icon: 'i2p',
...(Astro.url.origin !== new URL(I2P_ADDRESS).origin external: true,
? [ },
{
href: I2P_ADDRESS,
label: 'I2P',
icon: 'i2p',
external: true,
},
]
: []),
{ {
href: '/docs/api', href: '/docs/api',
label: 'API', label: 'API',

View File

@@ -114,7 +114,13 @@ export class ErrorBanners {
return result return result
} catch (error) { } catch (error) {
this.handler(uiMessage)(error) this.handler(uiMessage)(error)
return fallback as F return fallback as F extends never[]
? T extends [infer _First, ...infer _Rest]
? []
: T extends unknown[]
? T[number][]
: F
: F
} }
} }

View File

@@ -0,0 +1,27 @@
import type { Misc } from 'ts-toolbelt'
export async function makeAdminApiCallInfo<T extends Misc.JSON.Object>({
method,
path,
input,
baseUrl,
}: {
method: 'POST' | 'QUERY'
path: `/${string}`
input: T
baseUrl: URL | string
}) {
const fullPath = new URL(`/api/v1${path}`, baseUrl).href
return {
method,
path,
fullPath,
input,
output: await fetch(fullPath, {
method,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(input),
}).then((res) => res.json() as Promise<Misc.JSON.Value>),
}
}

View File

@@ -33,6 +33,7 @@ import {
verificationStepStatuses, verificationStepStatuses,
} from '../../../../constants/verificationStepStatus' } from '../../../../constants/verificationStepStatus'
import BaseLayout from '../../../../layouts/BaseLayout.astro' import BaseLayout from '../../../../layouts/BaseLayout.astro'
import { makeAdminApiCallInfo } from '../../../../lib/makeAdminApiCallInfo'
import { pluralize } from '../../../../lib/pluralize' import { pluralize } from '../../../../lib/pluralize'
import { prisma } from '../../../../lib/prisma' import { prisma } from '../../../../lib/prisma'
@@ -181,6 +182,20 @@ const [service, categories, attributes] = await Astro.locals.banners.tryMany([
]) ])
if (!service) return Astro.rewrite('/404') if (!service) return Astro.rewrite('/404')
const apiCalls = await Astro.locals.banners.try(
'Error fetching api calls',
() =>
Promise.all([
makeAdminApiCallInfo({
method: 'QUERY',
path: '/service/get',
input: { slug: service.slug },
baseUrl: Astro.url,
}),
]),
[]
)
--- ---
<BaseLayout pageTitle={`Edit Service: ${service.name}`}> <BaseLayout pageTitle={`Edit Service: ${service.name}`}>
@@ -1100,5 +1115,25 @@ if (!service) return Astro.rewrite('/404')
</form> </form>
</FormSubSection> </FormSubSection>
</FormSection> </FormSection>
<FormSection title="API">
{
apiCalls.map((call) => (
<FormSubSection title={`${call.method} ${call.path}`}>
<p class="text-day-400 text-sm">Input:</p>
<pre
class="bg-night-800 border-night-500 text-day-300 overflow-x-auto rounded-md border p-3"
set:text={JSON.stringify(call.input, null, 2)}
/>
<p class="text-day-400 text-sm">Output:</p>
<pre
class="bg-night-800 border-night-500 text-day-300 overflow-x-auto rounded-md border p-3"
set:text={JSON.stringify(call.output, null, 2)}
/>
</FormSubSection>
))
}
</FormSection>
</div> </div>
</BaseLayout> </BaseLayout>