Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4,217 changes: 4,217 additions & 0 deletions frontend/package-lock.json

Large diffs are not rendered by default.

6 changes: 1 addition & 5 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,11 @@
},
"dependencies": {
"bits-ui": "^2.18.1",
"formsnap": "^2.0.1",
"lucide-svelte": "^1.0.1",
"marked": "^18.0.4",
"marked-gfm-heading-id": "^4.1.4",
"mode-watcher": "^1.1.0",
"svelte-dnd-action": "^0.9.69",
"svelte-i18n": "^4.0.1",
"svelte-sonner": "^1.1.1",
"sveltekit-superforms": "^2.30.1",
"zod": "^4.4.3"
"svelte-sonner": "^1.1.1"
}
}
2 changes: 1 addition & 1 deletion frontend/src/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@
<DocViewer apiData={selectedApi} onDataChange={handleDataChange} onStructuralChange={handleStructuralChange} />
{:else}
<div class="flex h-full items-center justify-center text-muted-foreground">
Select an API to view details
{$_('common.selectApiPrompt')}
</div>
{/if}
</main>
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/lib/components/DocViewer.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
let {
apiData,
onDataChange,
onStructuralChange,
}: {
apiData: ApiData
onDataChange?: () => void
Expand All @@ -22,7 +23,7 @@
* Generate example JSON from parameters with nested support
* Handles primitives, objects, and arrays with proper nesting
*/
function generateExampleJson(parameters: ParameterWithChildren[]): Record<string, unknown> | unknown[] {
function generateExampleJson(parameters: ParameterWithChildren[]): Record<string, unknown> {
const result: Record<string, unknown> = {}

parameters.forEach((param) => {
Expand Down
7 changes: 4 additions & 3 deletions frontend/src/lib/components/LanguageSwitcher.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script lang="ts">
import { Globe } from 'lucide-svelte'
import { Globe } from '@lucide/svelte'
import { locale } from 'svelte-i18n'
import { setCookie } from '$lib/cookie'
import Button from './ui/button.svelte'

let isPending = $state(false)
Expand All @@ -13,8 +14,8 @@
// Set the locale directly
locale.set(newLocale)

// Also set cookie for persistence
document.cookie = `locale=${newLocale}; path=/; max-age=31536000`
// Also set cookie for persistence (secure)
setCookie('locale', newLocale, 365)
}
</script>

Expand Down
8 changes: 4 additions & 4 deletions frontend/src/lib/components/Sidebar.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts">
import { ChevronDown, ChevronRight, GripVertical, MoreVertical, Pencil, Trash2, Search, X, ArrowUp, ArrowDown, Copy, Share2 } from 'lucide-svelte'
import { ChevronDown, ChevronRight, GripVertical, MoreVertical, Pencil, Trash2, Search, X, ArrowUp, ArrowDown, Copy, Share2 } from '@lucide/svelte'
import { dndzone } from 'svelte-dnd-action'
import { toast } from 'svelte-sonner'
import { _ } from 'svelte-i18n'
Expand Down Expand Up @@ -210,7 +210,7 @@

const result = await updateApiOrders(apiOrders)
if (!result.success) {
toast.error(result.error || 'Failed to update API order')
toast.error(result.error || $_('api.orderUpdateError'))
localGroups = [...groups]
} else {
onDataChange?.()
Expand Down Expand Up @@ -244,15 +244,15 @@

const result = await updateGroupOrders(groupOrders)
if (!result.success) {
toast.error(result.error || 'Failed to update group order')
toast.error(result.error || $_('group.orderUpdateError'))
localGroups = [...groups]
} else {
onDataChange?.()
}
}

function closeOpenDropdown() {
document.querySelector('.fixed.inset-0.z-40')?.click()
(document.querySelector('.fixed.inset-0.z-40') as HTMLElement | null)?.click()
}

async function handleApiDuplicate(apiId: number) {
Expand Down
79 changes: 40 additions & 39 deletions frontend/src/lib/components/dialogs/CreateApiDialog.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script lang="ts">
import { Plus, X } from 'lucide-svelte'
import { Plus, X } from '@lucide/svelte'
import { toast } from 'svelte-sonner'
import { _ } from 'svelte-i18n'
import Button from '../ui/button.svelte'
import Dialog from '../ui/dialog.svelte'
import Input from '../ui/input.svelte'
Expand Down Expand Up @@ -55,7 +56,7 @@
requestParams = [
...requestParams,
{
id: Math.random().toString(36).substr(2, 9),
id: Math.random().toString(36).substring(2, 11),
name: '',
type: 'string',
description: '',
Expand All @@ -68,7 +69,7 @@
responseParams = [
...responseParams,
{
id: Math.random().toString(36).substr(2, 9),
id: Math.random().toString(36).substring(2, 11),
name: '',
type: 'string',
description: '',
Expand Down Expand Up @@ -107,12 +108,12 @@

// Validation
if (!apiName.trim()) {
toast.error('API name is required')
toast.error($_('createApi.nameRequired'))
return
}

if (!selectedGroupId) {
toast.error('Please select a group')
toast.error($_('createApi.groupRequired'))
return
}

Expand All @@ -121,7 +122,7 @@
const emptyResParams = responseParams.filter((p) => !p.name.trim())

if (emptyReqParams.length > 0 || emptyResParams.length > 0) {
toast.error('All parameter names must be filled in')
toast.error($_('createApi.paramNamesRequired'))
return
}

Expand All @@ -147,7 +148,7 @@
resetForm()
onSuccess?.()
} else {
toast.error(result.error || 'Failed to create API')
toast.error(result.error || $_('createApi.createError'))
}
loading = false
}
Expand Down Expand Up @@ -177,74 +178,74 @@
<Dialog bind:open class="max-w-5xl max-h-[90vh] overflow-y-auto">
{#snippet trigger()}
<Button variant="ghost" size="sm" class="w-full justify-start text-muted-foreground h-8 px-2">
<Plus class="h-3 w-3 mr-2" /> New API
<Plus class="h-3 w-3 mr-2" /> {$_('createApi.newApi')}
</Button>
{/snippet}

<div class="space-y-4">
<div class="space-y-2">
<h2 class="text-lg font-semibold">Create New API</h2>
<h2 class="text-lg font-semibold">{$_('createApi.title')}</h2>
</div>

<form onsubmit={handleSubmit} class="space-y-6">
<!-- Basic Info -->
<div class="grid grid-cols-3 gap-4">
<div class="space-y-2">
<Label for="apiName">API Name*</Label>
<Label for="apiName">{$_('createApi.apiNameLabel')}</Label>
<Input
id="apiName"
bind:value={apiName}
placeholder="e.g. Get Balance"
placeholder={$_('createApi.apiNamePlaceholder')}
required
/>
</div>
<div class="space-y-2">
<Label for="type">Type</Label>
<Label for="type">{$_('createApi.typeLabel')}</Label>
<Select bind:value={type} options={apiTypeOptions} />
</div>
{#if type === 'HTTP'}
<div class="space-y-2">
<Label for="method">Method</Label>
<Label for="method">{$_('createApi.methodLabel')}</Label>
<Select bind:value={method} options={methodOptions} />
</div>
{/if}
</div>

<div class="space-y-2">
<Label for="endpoint">Endpoint*</Label>
<Label for="endpoint">{$_('createApi.endpointLabel')}</Label>
<Input
id="endpoint"
bind:value={endpoint}
placeholder="e.g. /api/v1/resource"
placeholder={$_('createApi.endpointPlaceholder')}
required
/>
</div>

<!-- Request Parameters -->
<div class="space-y-3">
<div class="flex items-center justify-between">
<Label class="text-base font-semibold">Request Parameters</Label>
<Label class="text-base font-semibold">{$_('createApi.requestParams')}</Label>
<Button type="button" onclick={addRequestParam} size="sm" variant="outline">
<Plus class="h-4 w-4 mr-1" /> Add Parameter
<Plus class="h-4 w-4 mr-1" /> {$_('createApi.addParameter')}
</Button>
</div>

{#if requestParams.length > 0}
<div class="space-y-2">
<div class="grid grid-cols-12 gap-2 px-3 text-xs font-medium text-muted-foreground">
<div class="col-span-3">Name</div>
<div class="col-span-2">Type</div>
<div class="col-span-5">Description</div>
<div class="col-span-1 text-center">Required</div>
<div class="col-span-3">{$_('createApi.columnName')}</div>
<div class="col-span-2">{$_('createApi.columnType')}</div>
<div class="col-span-5">{$_('createApi.columnDescription')}</div>
<div class="col-span-1 text-center">{$_('createApi.columnRequired')}</div>
<div class="col-span-1"></div>
</div>
{#each requestParams as param (param.id)}
<div class="grid grid-cols-12 gap-2 items-start p-3 bg-muted/50 rounded-md">
<div class="col-span-3">
<Input
value={param.name}
oninput={(e) => updateRequestParam(param.id, 'name', e.currentTarget.value)}
placeholder="Parameter name"
oninput={(e: Event & { currentTarget: HTMLInputElement }) => updateRequestParam(param.id, 'name', e.currentTarget.value)}
placeholder={$_('createApi.paramNamePlaceholder')}
class="h-9"
/>
</div>
Expand All @@ -259,8 +260,8 @@
<div class="col-span-5">
<Textarea
value={param.description}
oninput={(e) => updateRequestParam(param.id, 'description', e.currentTarget.value)}
placeholder="Description (optional)"
oninput={(e: Event & { currentTarget: HTMLTextAreaElement }) => updateRequestParam(param.id, 'description', e.currentTarget.value)}
placeholder={$_('createApi.paramDescPlaceholder')}
class="h-9 min-h-9 resize-none"
rows={1}
/>
Expand Down Expand Up @@ -289,36 +290,36 @@

{#if requestParams.length === 0}
<p class="text-sm text-muted-foreground italic">
No request parameters. Click "Add Parameter" to add one.
{$_('createApi.noRequestParams')}
</p>
{/if}
</div>

<!-- Response Parameters -->
<div class="space-y-3">
<div class="flex items-center justify-between">
<Label class="text-base font-semibold">Response Parameters</Label>
<Label class="text-base font-semibold">{$_('createApi.responseParams')}</Label>
<Button type="button" onclick={addResponseParam} size="sm" variant="outline">
<Plus class="h-4 w-4 mr-1" /> Add Parameter
<Plus class="h-4 w-4 mr-1" /> {$_('createApi.addParameter')}
</Button>
</div>

{#if responseParams.length > 0}
<div class="space-y-2">
<div class="grid grid-cols-12 gap-2 px-3 text-xs font-medium text-muted-foreground">
<div class="col-span-3">Name</div>
<div class="col-span-2">Type</div>
<div class="col-span-5">Description</div>
<div class="col-span-1 text-center">Required</div>
<div class="col-span-3">{$_('createApi.columnName')}</div>
<div class="col-span-2">{$_('createApi.columnType')}</div>
<div class="col-span-5">{$_('createApi.columnDescription')}</div>
<div class="col-span-1 text-center">{$_('createApi.columnRequired')}</div>
<div class="col-span-1"></div>
</div>
{#each responseParams as param (param.id)}
<div class="grid grid-cols-12 gap-2 items-start p-3 bg-muted/50 rounded-md">
<div class="col-span-3">
<Input
value={param.name}
oninput={(e) => updateResponseParam(param.id, 'name', e.currentTarget.value)}
placeholder="Parameter name"
oninput={(e: Event & { currentTarget: HTMLInputElement }) => updateResponseParam(param.id, 'name', e.currentTarget.value)}
placeholder={$_('createApi.paramNamePlaceholder')}
class="h-9"
/>
</div>
Expand All @@ -333,8 +334,8 @@
<div class="col-span-5">
<Textarea
value={param.description}
oninput={(e) => updateResponseParam(param.id, 'description', e.currentTarget.value)}
placeholder="Description (optional)"
oninput={(e: Event & { currentTarget: HTMLTextAreaElement }) => updateResponseParam(param.id, 'description', e.currentTarget.value)}
placeholder={$_('createApi.paramDescPlaceholder')}
class="h-9 min-h-9 resize-none"
rows={1}
/>
Expand Down Expand Up @@ -363,17 +364,17 @@

{#if responseParams.length === 0}
<p class="text-sm text-muted-foreground italic">
No response parameters. Click "Add Parameter" to add one.
{$_('createApi.noResponseParams')}
</p>
{/if}
</div>

<div class="flex justify-end gap-2 pt-4 border-t">
<Button type="button" variant="outline" onclick={() => (open = false)}>
Cancel
{$_('common.cancel')}
</Button>
<Button type="submit" disabled={loading}>
{loading ? 'Creating...' : 'Create API'}
{loading ? $_('common.creating') : $_('api.create')}
</Button>
</div>
</form>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts">
import { Plus } from 'lucide-svelte'
import { Plus } from '@lucide/svelte'
import { toast } from 'svelte-sonner'
import { _ } from 'svelte-i18n'
import Button from '../ui/button.svelte'
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/lib/components/dialogs/ExportDialog.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts">
import { ChevronDown, ChevronRight, Download, FileDown } from 'lucide-svelte'
import { ChevronDown, ChevronRight, Download, FileDown } from '@lucide/svelte'
import { toast } from 'svelte-sonner'
import { _ } from 'svelte-i18n'
import Button from '../ui/button.svelte'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts">
import { Loader2 } from 'lucide-svelte'
import { Loader2 } from '@lucide/svelte'
import { toast } from 'svelte-sonner'
import { _ } from 'svelte-i18n'
import Button from '../ui/button.svelte'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts">
import { _ } from 'svelte-i18n'
import { toast } from 'svelte-sonner'
import { Trash2 } from 'lucide-svelte'
import { Trash2 } from '@lucide/svelte'
import Button from '../ui/button.svelte'
import AlertDialog from '../ui/alert-dialog.svelte'
import { deleteApi } from '$lib/api'
Expand Down
Loading