mirror of
https://github.com/LukeHagar/website.git
synced 2025-12-06 04:22:07 +00:00
@@ -35,7 +35,7 @@
|
|||||||
"@appwrite.io/console": "^0.6.4",
|
"@appwrite.io/console": "^0.6.4",
|
||||||
"@appwrite.io/pink": "~0.26.0",
|
"@appwrite.io/pink": "~0.26.0",
|
||||||
"@appwrite.io/pink-icons": "~0.26.0",
|
"@appwrite.io/pink-icons": "~0.26.0",
|
||||||
"@appwrite.io/repo": "github:appwrite/appwrite#feat-multi-region-docs",
|
"@appwrite.io/repo": "github:appwrite/appwrite#1.6.x",
|
||||||
"@eslint/compat": "^1.2.7",
|
"@eslint/compat": "^1.2.7",
|
||||||
"@eslint/js": "^9.21.0",
|
"@eslint/js": "^9.21.0",
|
||||||
"@fingerprintjs/fingerprintjs": "^4.5.1",
|
"@fingerprintjs/fingerprintjs": "^4.5.1",
|
||||||
|
|||||||
10
pnpm-lock.yaml
generated
10
pnpm-lock.yaml
generated
@@ -31,8 +31,8 @@ importers:
|
|||||||
specifier: ~0.26.0
|
specifier: ~0.26.0
|
||||||
version: 0.26.0
|
version: 0.26.0
|
||||||
'@appwrite.io/repo':
|
'@appwrite.io/repo':
|
||||||
specifier: github:appwrite/appwrite#feat-multi-region-docs
|
specifier: github:appwrite/appwrite#1.6.x
|
||||||
version: https://codeload.github.com/appwrite/appwrite/tar.gz/4d81a901cbc48b94a720392a2611da028ea934b9
|
version: https://codeload.github.com/appwrite/appwrite/tar.gz/ed8c39f649fc05973aefcddc7aad6a427cca02d5
|
||||||
'@eslint/compat':
|
'@eslint/compat':
|
||||||
specifier: ^1.2.7
|
specifier: ^1.2.7
|
||||||
version: 1.2.7(eslint@9.22.0(jiti@2.4.2))
|
version: 1.2.7(eslint@9.22.0(jiti@2.4.2))
|
||||||
@@ -263,8 +263,8 @@ packages:
|
|||||||
'@appwrite.io/pink@0.26.0':
|
'@appwrite.io/pink@0.26.0':
|
||||||
resolution: {integrity: sha512-iPeGE56pauzxuIXt15ZswjKCErwp3QdF3XOlJZfyYY7J2nirra85JNTL+3lWuFIf8yYWL7NbvCjhf8ig79TgwA==}
|
resolution: {integrity: sha512-iPeGE56pauzxuIXt15ZswjKCErwp3QdF3XOlJZfyYY7J2nirra85JNTL+3lWuFIf8yYWL7NbvCjhf8ig79TgwA==}
|
||||||
|
|
||||||
'@appwrite.io/repo@https://codeload.github.com/appwrite/appwrite/tar.gz/4d81a901cbc48b94a720392a2611da028ea934b9':
|
'@appwrite.io/repo@https://codeload.github.com/appwrite/appwrite/tar.gz/ed8c39f649fc05973aefcddc7aad6a427cca02d5':
|
||||||
resolution: {tarball: https://codeload.github.com/appwrite/appwrite/tar.gz/4d81a901cbc48b94a720392a2611da028ea934b9}
|
resolution: {tarball: https://codeload.github.com/appwrite/appwrite/tar.gz/ed8c39f649fc05973aefcddc7aad6a427cca02d5}
|
||||||
version: 0.0.0
|
version: 0.0.0
|
||||||
|
|
||||||
'@babel/runtime@7.26.10':
|
'@babel/runtime@7.26.10':
|
||||||
@@ -3955,7 +3955,7 @@ snapshots:
|
|||||||
normalize.css: 8.0.1
|
normalize.css: 8.0.1
|
||||||
the-new-css-reset: 1.11.3
|
the-new-css-reset: 1.11.3
|
||||||
|
|
||||||
'@appwrite.io/repo@https://codeload.github.com/appwrite/appwrite/tar.gz/4d81a901cbc48b94a720392a2611da028ea934b9': {}
|
'@appwrite.io/repo@https://codeload.github.com/appwrite/appwrite/tar.gz/ed8c39f649fc05973aefcddc7aad6a427cca02d5': {}
|
||||||
|
|
||||||
'@babel/runtime@7.26.10':
|
'@babel/runtime@7.26.10':
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
import { error } from '@sveltejs/kit';
|
||||||
import { OpenAPIV3 } from 'openapi-types';
|
import { OpenAPIV3 } from 'openapi-types';
|
||||||
import { Platform, type ServiceValue } from './references';
|
import { Platform, type ServiceValue } from './references';
|
||||||
import { error } from '@sveltejs/kit';
|
|
||||||
|
|
||||||
export type SDKMethod = {
|
export type SDKMethod = {
|
||||||
'rate-limit': number;
|
'rate-limit': number;
|
||||||
@@ -10,6 +10,7 @@ export type SDKMethod = {
|
|||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
demo: string;
|
demo: string;
|
||||||
|
group?: string;
|
||||||
parameters: Array<{
|
parameters: Array<{
|
||||||
name: string;
|
name: string;
|
||||||
description: string;
|
description: string;
|
||||||
@@ -34,6 +35,7 @@ type SDKMethodModel = {
|
|||||||
type AppwriteOperationObject = OpenAPIV3.OperationObject & {
|
type AppwriteOperationObject = OpenAPIV3.OperationObject & {
|
||||||
'x-appwrite': {
|
'x-appwrite': {
|
||||||
method: string;
|
method: string;
|
||||||
|
group?: string;
|
||||||
weight: number;
|
weight: number;
|
||||||
cookies: boolean;
|
cookies: boolean;
|
||||||
type: string;
|
type: string;
|
||||||
@@ -331,7 +333,8 @@ export async function getService(
|
|||||||
|
|
||||||
data.methods.push({
|
data.methods.push({
|
||||||
id: operation['x-appwrite'].method,
|
id: operation['x-appwrite'].method,
|
||||||
demo: demo ?? '',
|
group: operation['x-appwrite'].group,
|
||||||
|
demo: typeof demo === 'string' ? demo : '',
|
||||||
title: operation.summary ?? '',
|
title: operation.summary ?? '',
|
||||||
description: operation.description ?? '',
|
description: operation.description ?? '',
|
||||||
parameters: parameters ?? [],
|
parameters: parameters ?? [],
|
||||||
@@ -344,6 +347,17 @@ export async function getService(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sort methods by weight from x-appwrite metadata
|
||||||
|
data.methods.sort((a, b) => {
|
||||||
|
const aPath = api.paths[a.url] as OpenAPIV3.PathItemObject;
|
||||||
|
const bPath = api.paths[b.url] as OpenAPIV3.PathItemObject;
|
||||||
|
const aMethod = a.method.toLowerCase() as Lowercase<OpenAPIV3.HttpMethods>;
|
||||||
|
const bMethod = b.method.toLowerCase() as Lowercase<OpenAPIV3.HttpMethods>;
|
||||||
|
const aWeight = (aPath?.[aMethod] as AppwriteOperationObject)?.['x-appwrite']?.weight ?? 0;
|
||||||
|
const bWeight = (bPath?.[bMethod] as AppwriteOperationObject)?.['x-appwrite']?.weight ?? 0;
|
||||||
|
return aWeight - bWeight;
|
||||||
|
});
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { error } from '@sveltejs/kit';
|
|
||||||
import { getService } from '$lib/utils/specs';
|
|
||||||
import type { EntryGenerator, PageServerLoad } from './$types';
|
|
||||||
import { Platform, Service, type ServiceValue, versions } from '$lib/utils/references';
|
import { Platform, Service, type ServiceValue, versions } from '$lib/utils/references';
|
||||||
|
import { getService } from '$lib/utils/specs';
|
||||||
|
import { error } from '@sveltejs/kit';
|
||||||
|
import type { EntryGenerator, PageServerLoad } from './$types';
|
||||||
|
|
||||||
const services = Object.values(Service);
|
const services = Object.values(Service);
|
||||||
const platforms = Object.values(Platform);
|
const platforms = Object.values(Platform);
|
||||||
@@ -19,8 +19,10 @@ export const entries: EntryGenerator = () => {
|
|||||||
export const load: PageServerLoad = async ({ params }) => {
|
export const load: PageServerLoad = async ({ params }) => {
|
||||||
const { platform, service } = params;
|
const { platform, service } = params;
|
||||||
const version = params.version === 'cloud' ? '1.6.x' : params.version;
|
const version = params.version === 'cloud' ? '1.6.x' : params.version;
|
||||||
|
|
||||||
if (!versions.includes(version)) error(404, 'Invalid version');
|
if (!versions.includes(version)) error(404, 'Invalid version');
|
||||||
if (!services.includes(service as ServiceValue)) error(404, 'Invalid service');
|
|
||||||
if (!platforms.includes(platform as Platform)) error(404, 'Invalid platform');
|
if (!platforms.includes(platform as Platform)) error(404, 'Invalid platform');
|
||||||
|
if (!services.includes(service as ServiceValue)) error(404, 'Invalid service');
|
||||||
|
|
||||||
return getService(version, platform, service);
|
return getService(version, platform, service);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -34,6 +34,8 @@
|
|||||||
const headings = getContext<LayoutContext>('headings');
|
const headings = getContext<LayoutContext>('headings');
|
||||||
|
|
||||||
let selected: string | undefined = $state(undefined);
|
let selected: string | undefined = $state(undefined);
|
||||||
|
let selectedMenuItem: HTMLElement;
|
||||||
|
|
||||||
headings.subscribe((n) => {
|
headings.subscribe((n) => {
|
||||||
const noVisible = Object.values(n).every((n) => !n.visible);
|
const noVisible = Object.values(n).every((n) => !n.visible);
|
||||||
if (selected && noVisible) {
|
if (selected && noVisible) {
|
||||||
@@ -42,6 +44,19 @@
|
|||||||
for (const key in n) {
|
for (const key in n) {
|
||||||
if (n[key].visible) {
|
if (n[key].visible) {
|
||||||
selected = key;
|
selected = key;
|
||||||
|
setTimeout(() => {
|
||||||
|
if (selectedMenuItem) {
|
||||||
|
selectedMenuItem.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||||
|
|
||||||
|
const menuContainer = selectedMenuItem.closest(
|
||||||
|
'.web-references-menu-content'
|
||||||
|
);
|
||||||
|
if (menuContainer) {
|
||||||
|
const offset = 100; // offset to position the item higher in the viewport
|
||||||
|
menuContainer.scrollTop = menuContainer.scrollTop - offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -127,6 +142,62 @@
|
|||||||
serviceDescription.substring(0, serviceDescription.indexOf('.') + 1)
|
serviceDescription.substring(0, serviceDescription.indexOf('.') + 1)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the order of operations based on the method title.
|
||||||
|
* For eg. Create account, Get account, List accounts, Update account, Delete account.
|
||||||
|
*/
|
||||||
|
function getOperationOrder(methodTitle: string): number {
|
||||||
|
const title = methodTitle.toLowerCase();
|
||||||
|
if (title.startsWith('create')) return 1;
|
||||||
|
if (title.startsWith('read') || title.startsWith('get') || title.startsWith('list'))
|
||||||
|
return 2;
|
||||||
|
if (title.startsWith('update')) return 3;
|
||||||
|
if (title.startsWith('delete')) return 4;
|
||||||
|
return 5; // Other operations
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sorts methods by their operation order and title
|
||||||
|
*/
|
||||||
|
function sortMethods(methods: any[]) {
|
||||||
|
return methods.sort((a, b) => {
|
||||||
|
const orderA = getOperationOrder(a.title);
|
||||||
|
const orderB = getOperationOrder(b.title);
|
||||||
|
if (orderA === orderB) {
|
||||||
|
return a.title.localeCompare(b.title);
|
||||||
|
}
|
||||||
|
return orderA - orderB;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Groups methods by their group attribute, null group goes to '' for ordering
|
||||||
|
*/
|
||||||
|
function groupMethodsByGroup(methods: any[]) {
|
||||||
|
return methods.reduce((acc, method) => {
|
||||||
|
const groupKey = method.group || '';
|
||||||
|
if (!acc[groupKey]) {
|
||||||
|
acc[groupKey] = [];
|
||||||
|
}
|
||||||
|
acc[groupKey].push(method);
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
function bindSelectedRef(node: HTMLElement, isSelected: boolean) {
|
||||||
|
if (isSelected) {
|
||||||
|
selectedMenuItem = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
update(newIsSelected: boolean) {
|
||||||
|
if (newIsSelected) {
|
||||||
|
selectedMenuItem = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
let platformBindingForSelect = $derived(page.params.platform as Platform);
|
let platformBindingForSelect = $derived(page.params.platform as Platform);
|
||||||
let platform = $derived(/**$preferredPlatform ?? */ page.params.platform as Platform);
|
let platform = $derived(/**$preferredPlatform ?? */ page.params.platform as Platform);
|
||||||
let platformType = $derived(platform.startsWith('client-') ? 'CLIENT' : 'SERVER');
|
let platformType = $derived(platform.startsWith('client-') ? 'CLIENT' : 'SERVER');
|
||||||
@@ -242,58 +313,62 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</section>
|
</section>
|
||||||
{#each data.methods as method (method.id)}
|
{#each Object.entries(groupMethodsByGroup(data.methods)) as [group, methods]}
|
||||||
<section class="web-article-content-grid-6-4">
|
{#each sortMethods(methods) as method (method.id)}
|
||||||
<div class="web-article-content-grid-6-4-column-1 flex flex-col gap-8">
|
<section class="web-article-content-grid-6-4">
|
||||||
<header class="web-article-content-header">
|
<div class="web-article-content-grid-6-4-column-1 flex flex-col gap-8">
|
||||||
<Heading id={method.id} level={2} inReferences>{method.title}</Heading>
|
<header class="web-article-content-header">
|
||||||
</header>
|
<Heading id={method.id} level={2} inReferences
|
||||||
<div class="flex flex-col gap-2">
|
>{method.title}</Heading
|
||||||
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
>
|
||||||
{@html parse(method.description)}
|
</header>
|
||||||
|
<div class="flex flex-col gap-2">
|
||||||
|
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
||||||
|
{@html parse(method.description)}
|
||||||
|
</div>
|
||||||
|
<Accordion>
|
||||||
|
{#if method.parameters.length > 0}
|
||||||
|
<AccordionItem open={true} title="Request">
|
||||||
|
<Request {method} />
|
||||||
|
</AccordionItem>
|
||||||
|
{/if}
|
||||||
|
<AccordionItem title="Response">
|
||||||
|
<Response {method} />
|
||||||
|
</AccordionItem>
|
||||||
|
{#if method?.['rate-limit'] > 0 && method?.['rate-key']?.length > 0}
|
||||||
|
<AccordionItem title="Rate limits">
|
||||||
|
<RateLimits {method} {platformType} />
|
||||||
|
</AccordionItem>
|
||||||
|
{/if}
|
||||||
|
</Accordion>
|
||||||
</div>
|
</div>
|
||||||
<Accordion>
|
<div class="web-article-content-grid-6-4-column-2 flex flex-col gap-8">
|
||||||
{#if method.parameters.length > 0}
|
<div class="dark contents">
|
||||||
<AccordionItem open={true} title="Request">
|
<div
|
||||||
<Request {method} />
|
class="sticky"
|
||||||
</AccordionItem>
|
style="--inset-block-start:var(--p-grid-huge-navs-secondary-sticky-position);"
|
||||||
{/if}
|
>
|
||||||
<AccordionItem title="Response">
|
|
||||||
<Response {method} />
|
|
||||||
</AccordionItem>
|
|
||||||
{#if method?.['rate-limit'] > 0 && method?.['rate-key']?.length > 0}
|
|
||||||
<AccordionItem title="Rate limits">
|
|
||||||
<RateLimits {method} {platformType} />
|
|
||||||
</AccordionItem>
|
|
||||||
{/if}
|
|
||||||
</Accordion>
|
|
||||||
</div>
|
|
||||||
<div class="web-article-content-grid-6-4-column-2 flex flex-col gap-8">
|
|
||||||
<div class="dark contents">
|
|
||||||
<div
|
|
||||||
class="sticky"
|
|
||||||
style="--inset-block-start:var(--p-grid-huge-navs-secondary-sticky-position);"
|
|
||||||
>
|
|
||||||
<Fence
|
|
||||||
language="text"
|
|
||||||
badge="Endpoint"
|
|
||||||
content="{method.method.toUpperCase()} {method.url}"
|
|
||||||
toCopy={method.url}
|
|
||||||
process
|
|
||||||
withLineNumbers={false}
|
|
||||||
/>
|
|
||||||
<div class="mt-6">
|
|
||||||
<Fence
|
<Fence
|
||||||
language={platform}
|
language="text"
|
||||||
content={method.demo}
|
badge="Endpoint"
|
||||||
|
content="{method.method.toUpperCase()} {method.url}"
|
||||||
|
toCopy={method.url}
|
||||||
process
|
process
|
||||||
withLineNumbers={false}
|
withLineNumbers={false}
|
||||||
/>
|
/>
|
||||||
|
<div class="mt-6">
|
||||||
|
<Fence
|
||||||
|
language={platform}
|
||||||
|
content={method.demo}
|
||||||
|
process
|
||||||
|
withLineNumbers={false}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</section>
|
||||||
</section>
|
{/each}
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
<aside
|
<aside
|
||||||
@@ -325,13 +400,27 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<ul class="web-references-menu-list">
|
<ul class="web-references-menu-list">
|
||||||
{#each data.methods as method}
|
{#each Object.entries(groupMethodsByGroup(data.methods)) as [group, methods]}
|
||||||
<li class="web-references-menu-item">
|
<li class="web-references-menu-group">
|
||||||
<a
|
{#if group !== ''}
|
||||||
href={`#${method.id}`}
|
<h6 class="text-micro text-greyscale-500 mb-2 uppercase">
|
||||||
class="web-references-menu-link text-caption"
|
{group}
|
||||||
class:is-selected={method.id === selected}>{method.title}</a
|
</h6>
|
||||||
>
|
{/if}
|
||||||
|
<ul class="flex flex-col gap-2">
|
||||||
|
{#each sortMethods(methods) as method}
|
||||||
|
<li class="web-references-menu-item">
|
||||||
|
<a
|
||||||
|
href={`#${method.id}`}
|
||||||
|
class="web-references-menu-link text-caption"
|
||||||
|
class:is-selected={method.id === selected}
|
||||||
|
use:bindSelectedRef={method.id === selected}
|
||||||
|
>
|
||||||
|
{method.title}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
@@ -352,4 +441,11 @@
|
|||||||
.web-inline-code {
|
.web-inline-code {
|
||||||
translate: 0 0.125rem;
|
translate: 0 0.125rem;
|
||||||
}
|
}
|
||||||
|
.web-references-menu-group {
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import dynamicImport from 'vite-plugin-dynamic-import';
|
|
||||||
import { sveltekit } from '@sveltejs/kit/vite';
|
|
||||||
import { defineConfig } from 'vitest/config';
|
|
||||||
import { ViteImageOptimizer } from 'vite-plugin-image-optimizer';
|
|
||||||
import { enhancedImages } from '@sveltejs/enhanced-img';
|
import { enhancedImages } from '@sveltejs/enhanced-img';
|
||||||
|
import { sveltekit } from '@sveltejs/kit/vite';
|
||||||
|
import dynamicImport from 'vite-plugin-dynamic-import';
|
||||||
|
import { ViteImageOptimizer } from 'vite-plugin-image-optimizer';
|
||||||
import manifestSRI from 'vite-plugin-manifest-sri';
|
import manifestSRI from 'vite-plugin-manifest-sri';
|
||||||
|
import { defineConfig } from 'vitest/config';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [
|
plugins: [
|
||||||
|
|||||||
Reference in New Issue
Block a user