Merge branch 'main' into init-3

This commit is contained in:
Jesse Winton
2025-04-24 09:40:24 -04:00
6 changed files with 166 additions and 68 deletions

View File

@@ -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
View File

@@ -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.8(eslint@9.24.0(jiti@2.4.2)) version: 1.2.8(eslint@9.24.0(jiti@2.4.2))
@@ -287,8 +287,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
'@asamuzakjp/css-color@3.1.2': '@asamuzakjp/css-color@3.1.2':
@@ -4238,7 +4238,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': {}
'@asamuzakjp/css-color@3.1.2': '@asamuzakjp/css-color@3.1.2':
dependencies: dependencies:

View File

@@ -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;
} }

View File

@@ -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);
}; };

View File

@@ -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,7 +44,6 @@
for (const key in n) { for (const key in n) {
if (n[key].visible) { if (n[key].visible) {
selected = key; selected = key;
break;
} }
} }
}); });
@@ -127,6 +128,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 +299,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 +386,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 +427,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>

View File

@@ -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: [