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 changes: 2 additions & 2 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
},
"dependencies": {
"@ai-sdk/svelte": "^1.1.24",
"@appwrite.io/console": "https://pkg.vc/-/@appwrite/@appwrite.io/console@33968aa",
"@appwrite.io/console": "https://pkg.vc/-/@appwrite/@appwrite.io/console@93d2dfa",
"@appwrite.io/pink-icons": "0.25.0",
"@appwrite.io/pink-icons-svelte": "https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@bfe7ce3",
"@appwrite.io/pink-legacy": "^1.0.3",
Expand Down
16 changes: 15 additions & 1 deletion src/lib/stores/runtimes.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
export function getIconFromRuntime(runtime: string) {
export function getIconFromRuntime(runtime?: string) {
switch (true) {
case !runtime:
return undefined;
case runtime.includes('node'):
return 'node';
case runtime.includes('php'):
Expand All @@ -18,6 +20,18 @@ export function getIconFromRuntime(runtime: string) {
return 'deno';
case runtime.includes('flutter'):
return 'flutter';
case runtime.includes('dotnet'):
return 'dotnet';
case runtime.includes('java'):
return 'java';
case runtime.includes('swift'):
return 'swift';
case runtime.includes('kotlin'):
return 'kotlin';
case runtime.includes('cpp'):
return 'cpp';
case runtime.includes('rust'):
return 'rust';
default:
return undefined;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import Wizard from '$lib/layout/wizard.svelte';
import { Link } from '$lib/elements';
import { Button } from '$lib/elements/forms';
import { getIconFromRuntime } from '$lib/stores/runtimes';
import { regionalConsoleVariables } from '../../store';

export let data;
Expand All @@ -36,17 +37,17 @@

const starterTemplate = data.templates.find((template) => template.id === 'starter');

const baseRuntimesList = [
...new Map(
data.runtimesList.runtimes.map((runtime) => {
const base = runtime.name.split('-')[0];
return [base, runtime];
})
).values()
];

const starterTemplateRuntimes = starterTemplate.runtimes.filter((r) =>
baseRuntimesList.some((base) => base.$id === r.name)
const latestRuntimesByKey = new Map<string, Models.Runtime>();
for (const runtime of data.runtimesList.runtimes) {
latestRuntimesByKey.set(runtime.key, runtime);
}

const starterTemplateRuntimeIds = new Set<string>(
starterTemplate?.runtimes.map((runtime) => runtime.name) ?? []
);

const starterTemplateRuntimes = [...latestRuntimesByKey.values()].filter((runtime) =>
starterTemplateRuntimeIds.has(runtime.$id)
);

function connect(e: Models.ProviderRepository) {
Expand Down Expand Up @@ -131,11 +132,8 @@
<Layout.Stack gap="xl">
<Typography.Title size="s">Quick start</Typography.Title>
<Layout.Grid columnsXXS={1} columnsXS={2} columnsS={3} columns={4} gap="s">
{#each starterTemplateRuntimes.slice(0, 6) as template}
{@const iconName = template.name.split('-')[0]}
{@const runtimeDetail = baseRuntimesList.find(
(runtime) => runtime.$id === template.name
)}
{#each starterTemplateRuntimes as runtime}
{@const iconName = getIconFromRuntime(runtime.key)}
<Card.Link
variant="secondary"
radius="s"
Expand All @@ -144,7 +142,7 @@
trackEvent('click_connect_template', {
from: 'cover',
template: starterTemplate.id,
runtime: template.name
runtime: runtime.$id
});
}}
href={resolveRoute(
Expand All @@ -153,14 +151,16 @@
...page.params,
template: starterTemplate.id
}
) + `?runtime=${runtimeDetail.$id}`}>
) + `?runtime=${runtime.$id}`}>
<Layout.Stack direction="row" gap="s" alignItems="center">
<Avatar size="xs" alt={template.name} empty={!template.name}>
<SvgIcon name={iconName} iconSize="small" />
<Avatar size="xs" alt={runtime.name} empty={!iconName}>
{#if iconName}
<SvgIcon name={iconName} iconSize="small" />
{/if}
</Avatar>
<Typography.Text color="--fgcolor-neutral-primary">
<Layout.Stack direction="row" gap="xs" alignItems="center">
{runtimeDetail?.name}
{runtime.name}
<!--{#if runtimeDetail?.name?.toLowerCase() === 'deno'}-->
<!-- <Badge-->
<!-- variant="secondary"-->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,16 @@
data.runtimesList?.runtimes?.map((r) => ({
value: r.$id,
label: `${r.name} - ${r.version}`,
leadingHtml: `<img src='${$iconPath(getIconFromRuntime(r.$id), 'color')}' style='inline-size: var(--icon-size-m)' />`
leadingHtml: `<img src='${$iconPath(getIconFromRuntime(r.key) ?? 'empty', 'color')}' style='inline-size: var(--icon-size-m)' />`
})) || []
);

onMount(() => {
const runtimeParam = data.runtime || page.url.searchParams.get('runtime') || 'node-18.0';
runtime = runtimeParam as Runtime;
const runtimeParam = data.runtime || page.url.searchParams.get('runtime');
const runtimeOption = data.runtimesList.runtimes.find(
(runtime) => runtime.$id === runtimeParam
);
runtime = (runtimeOption?.$id ?? data.runtimesList.runtimes[0]?.$id) as Runtime;

entrypoint = page.url.searchParams.get('entrypoint') || '';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
const runtimeOptions = data.runtimesList.runtimes.map((runtime) => {
const { $id: value, name, version, key } = runtime;
const label = `${name} - ${version}`;
const iconName = getIconFromRuntime(key);
const iconName = getIconFromRuntime(key) ?? 'empty';
const iconSrc = iconFor(iconName, 'color');
const leadingHtml = `<img src='${iconSrc}' alt='${iconName}' style='inline-size: var(--icon-size-m)' />`;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
return {
value: runtime.$id,
label: `${runtime.name} - ${runtime.version}`,
leadingHtml: `<img src='${$iconPath(getIconFromRuntime(runtime.key), 'color')}' style='inline-size: var(--icon-size-m)' />`
leadingHtml: `<img src='${$iconPath(getIconFromRuntime(runtime.key) ?? 'empty', 'color')}' style='inline-size: var(--icon-size-m)' />`
};
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import { installation, repository } from '$lib/stores/vcs';
import { Fieldset, Layout, Icon, Divider, Empty, Typography } from '@appwrite.io/pink-svelte';
import { IconGithub } from '@appwrite.io/pink-icons-svelte';
import { onMount } from 'svelte';
import { onMount, untrack } from 'svelte';
import { writable } from 'svelte/store';
import ProductionBranch from '$lib/components/git/productionBranchFieldset.svelte';
import Configuration from './configuration.svelte';
Expand All @@ -37,64 +37,83 @@
import { Dependencies } from '$lib/constants';
import { getIconFromRuntime } from '$lib/stores/runtimes';
import { regionalConsoleVariables } from '$routes/(console)/project-[region]-[project]/store';
import type { PageData } from './$types';

export let data;
let { data }: { data: PageData } = $props();

const specificationOptions = (data.specificationsList?.specifications ?? []).map((size) => ({
label:
`${size.cpus} CPU, ${size.memory} MB RAM` +
(!size.enabled ? ` (Upgrade to use this)` : ''),
value: size.slug,
disabled: !size.enabled
}));
const specificationOptions = $derived(
(data.specificationsList?.specifications ?? []).map((size) => ({
label:
`${size.cpus} CPU, ${size.memory} MB RAM` +
(!size.enabled ? ` (Upgrade to use this)` : ''),
value: size.slug,
disabled: !size.enabled
}))
);

let showExitModal = $state(false);
let isCreatingRepository = $state(false);

let formComponent = $state<Form>();
let isSubmitting = $state(writable(false));

let name = $state(untrack(() => data.template.name));
let id = $state<string | null>(null);
let runtime = $state<Runtime>();
let branch = $state('main');
let rootDir = $state('./');
let connectBehaviour = $state<'now' | 'later'>('now');
let repositoryBehaviour = $state<'new' | 'existing'>('new');
let repositoryName = $state<string | undefined>();
let repositoryPrivate = $state(true);
let selectedInstallationId = $state('');
let selectedRepository = $state<string | null>('');
let showConfig = $state(false);
let silentMode = $state(false);
let entrypoint = $state('');
let selectedScopes = $state<Scopes[]>([]);
let execute = $state(true);
let variables = $state<Partial<Models.TemplateVariable>[]>([]);
let specification = $state(untrack(() => specificationOptions[0]?.value || ''));

const availableRuntimes: Models.Runtime[] = $derived(
data.runtimesList.runtimes.filter((runtime) =>
data.template.runtimes.some((templateRuntime) => templateRuntime.name === runtime.$id)
)
);

let showExitModal = false;
let isCreatingRepository = false;
function sortRuntimesByVersionDesc(a: Models.Runtime, b: Models.Runtime) {
return b.version.localeCompare(a.version, undefined, { numeric: true });
}

function selectInitialRuntime() {
const runtimeParam = page.url.searchParams.get('runtime');
const requestedRuntime = availableRuntimes.find((runtime) => runtime.$id === runtimeParam);

if (requestedRuntime) {
return requestedRuntime.$id as Runtime;
}

let formComponent: Form;
let isSubmitting = writable(false);
const runtimeById = new Map(
data.runtimesList.runtimes.map((runtime) => [runtime.$id, runtime])
);
const preferredRuntime = data.template.runtimes
.map((runtime) => runtimeById.get(runtime.name))
.find(Boolean);
const preferredRuntimes = preferredRuntime
? availableRuntimes.filter((runtime) => runtime.key === preferredRuntime.key)
: [];
const runtimes = preferredRuntimes.length ? preferredRuntimes : availableRuntimes;

let name = data.template.name;
let id: string | null = null;
let runtime: Runtime;
let branch = 'main';
let rootDir = './';
let connectBehaviour: 'now' | 'later' = 'now';
let repositoryBehaviour: 'new' | 'existing' = 'new';
let repositoryName = undefined;
let repositoryPrivate = true;
let selectedInstallationId = '';
let selectedRepository = '';
let showConfig = false;
let silentMode = false;
let entrypoint = '';
let selectedScopes: Scopes[] = [];
let execute = true;
let variables: Partial<Models.TemplateVariable>[] = [];
let specification = specificationOptions[0]?.value || '';
return [...runtimes].sort(sortRuntimesByVersionDesc)[0]?.$id as Runtime;
}

onMount(async () => {
if (!$installation?.$id) {
$installation = data.installations.installations[0];
}
selectedInstallationId = $installation?.$id;
if (data.template.runtimes && data.template.runtimes.length > 0) {
const targetRuntime = data.template.runtimes[0].name;
const matchingRuntimes = Object.values(Runtime).filter((r) =>
r.startsWith(targetRuntime.split('-')[0])
);

matchingRuntimes.sort((a, b) => {
const versionA = a.split('-')[1];
const versionB = b.split('-')[1];
return versionB.localeCompare(versionA, undefined, { numeric: true });
});
if (page.url.searchParams.has('runtime')) {
runtime = page.url.searchParams.get('runtime') as Runtime;
} else {
runtime = matchingRuntimes[0] as Runtime;
}
}
runtime = selectInitialRuntime();
});

async function createRepository() {
Expand Down Expand Up @@ -210,18 +229,18 @@
}
}

$: if (repositoryBehaviour === 'new') {
selectedInstallationId ??= $installation?.$id;
repositoryName ??= name.split(' ').join('-').toLowerCase();
}

$: if (connectBehaviour === 'later') {
selectedRepository = null;
}
$effect(() => {
if (repositoryBehaviour === 'new') {
selectedInstallationId ??= $installation?.$id;
repositoryName ??= name.split(' ').join('-').toLowerCase();
}
});

$: availableRuntimes = data.runtimesList.runtimes.filter((runtime) =>
data.template.runtimes.some((templateRuntime) => templateRuntime.name === runtime.$id)
);
$effect(() => {
if (connectBehaviour === 'later') {
selectedRepository = null;
}
});
</script>

<svelte:head>
Expand Down Expand Up @@ -259,7 +278,7 @@
return {
value: runtime.$id,
label: `${runtime.name} - ${runtime.version}`,
leadingHtml: `<img src='${$iconPath(getIconFromRuntime(runtime.$id), 'color')}' style='inline-size: var(--icon-size-m)' />`
leadingHtml: `<img src='${$iconPath(getIconFromRuntime(runtime.key) ?? 'empty', 'color')}' style='inline-size: var(--icon-size-m)' />`
};
})}

Expand Down
15 changes: 11 additions & 4 deletions src/routes/(public)/functions/deploy/+page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,16 @@ export const load: PageLoad = async ({ parent, url }) => {
const envParam = url.searchParams.get('env');
const envKeys = envParam ? envParam.split(',').map((key: string) => key.trim()) : [];

// Get available runtimes
const runtimesList = await sdk.forConsole.functions.listRuntimes();

const runtimeOption = runtimesList.runtimes.find((option) => option.$id === runtime);
const runtimeId = runtimeOption?.$id ?? runtimesList.runtimes[0]?.$id;

if (!runtimeId) {
redirect(302, base + '/');
}

const deploymentData: {
type: 'repo';
repository: {
Expand All @@ -48,12 +58,9 @@ export const load: PageLoad = async ({ parent, url }) => {
rootDirectory: null
},
name: name || '',
runtime: runtime || 'node-18.0'
runtime: runtimeId
};

// Get available runtimes
const runtimesList = await sdk.forConsole.functions.listRuntimes();

const info = getRepositoryInfo(repository);
if (!info) {
redirect(302, base + '/');
Expand Down
Loading
Loading