diff --git a/package.json b/package.json
index 07410cb2a..bd56ed8db 100644
--- a/package.json
+++ b/package.json
@@ -19,7 +19,7 @@
"e2e:ui": "playwright test tests/e2e --ui"
},
"dependencies": {
- "@appwrite.io/console": "https://pkg.pr.new/appwrite/appwrite/@appwrite.io/console@74f9464",
+ "@appwrite.io/console": "https://pkg.pr.new/appwrite/appwrite/@appwrite.io/console@08b7400",
"@appwrite.io/pink-icons": "0.25.0",
"@appwrite.io/pink-icons-svelte": "https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@64948b6 ",
"@appwrite.io/pink-legacy": "^1.0.3",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 1cad1bcf0..9043c803f 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -9,8 +9,8 @@ importers:
.:
dependencies:
'@appwrite.io/console':
- specifier: https://pkg.pr.new/appwrite/appwrite/@appwrite.io/console@74f9464
- version: https://pkg.pr.new/appwrite/appwrite/@appwrite.io/console@74f9464
+ specifier: https://pkg.pr.new/appwrite/appwrite/@appwrite.io/console@08b7400
+ version: https://pkg.pr.new/appwrite/appwrite/@appwrite.io/console@08b7400
'@appwrite.io/pink-icons':
specifier: 0.25.0
version: 0.25.0
@@ -211,8 +211,8 @@ packages:
'@analytics/type-utils@0.6.2':
resolution: {integrity: sha512-TD+xbmsBLyYy/IxFimW/YL/9L2IEnM7/EoV9Aeh56U64Ify8o27HJcKjo38XY9Tcn0uOq1AX3thkKgvtWvwFQg==}
- '@appwrite.io/console@https://pkg.pr.new/appwrite/appwrite/@appwrite.io/console@74f9464':
- resolution: {tarball: https://pkg.pr.new/appwrite/appwrite/@appwrite.io/console@74f9464}
+ '@appwrite.io/console@https://pkg.pr.new/appwrite/appwrite/@appwrite.io/console@08b7400':
+ resolution: {tarball: https://pkg.pr.new/appwrite/appwrite/@appwrite.io/console@08b7400}
version: 1.2.1
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@11e065399ceac01b462887282f593271ec8b29a4':
@@ -4241,7 +4241,7 @@ snapshots:
'@analytics/type-utils@0.6.2': {}
- '@appwrite.io/console@https://pkg.pr.new/appwrite/appwrite/@appwrite.io/console@74f9464': {}
+ '@appwrite.io/console@https://pkg.pr.new/appwrite/appwrite/@appwrite.io/console@08b7400': {}
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@11e065399ceac01b462887282f593271ec8b29a4(svelte@4.2.19)':
dependencies:
diff --git a/src/lib/helpers/timeConversion.ts b/src/lib/helpers/timeConversion.ts
index 330a38c2f..a0cdf725e 100644
--- a/src/lib/helpers/timeConversion.ts
+++ b/src/lib/helpers/timeConversion.ts
@@ -114,3 +114,29 @@ export function formatTimeDetailed(time: number): string {
return parts.join(' ');
}
+
+/**
+ * Calculates the time difference between a starting date/time and the current time.
+ * Returns the difference formatted in seconds, minutes, or hours depending on the magnitude.
+ *
+ * @export
+ * @param {Date | number | string} startTime - The starting date/time, timestamp in milliseconds, or ISO date string (e.g., '2025-03-20T15:50:43.495+00:00')
+ * @returns {string} The formatted time difference
+ */
+export function timer(startTime: Date | number | string): string {
+ let start: number;
+
+ if (startTime instanceof Date) {
+ start = startTime.getTime();
+ } else if (typeof startTime === 'number') {
+ start = startTime;
+ } else {
+ // Handle ISO date string format
+ start = new Date(startTime).getTime();
+ }
+
+ const now = new Date().getTime();
+ const diffInSeconds = (now - start) / 1000;
+
+ return calculateTime(diffInSeconds);
+}
diff --git a/src/routes/(console)/project-[project]/functions/function-[function]/executions/(components)/LogsRequest.svelte b/src/routes/(console)/project-[project]/functions/function-[function]/executions/(components)/LogsRequest.svelte
index d6d65981e..85bd2482a 100644
--- a/src/routes/(console)/project-[project]/functions/function-[function]/executions/(components)/LogsRequest.svelte
+++ b/src/routes/(console)/project-[project]/functions/function-[function]/executions/(components)/LogsRequest.svelte
@@ -67,7 +67,17 @@
{#if requestTab === 'parameters'}
{#if parameters?.length}
-
+
Key
Value
@@ -86,7 +96,17 @@
{/if}
{:else if requestTab === 'headers'}
{#if selectedLog.requestHeaders?.length}
-
+
Key
Value
diff --git a/src/routes/(console)/project-[project]/functions/function-[function]/executions/(components)/LogsResponse.svelte b/src/routes/(console)/project-[project]/functions/function-[function]/executions/(components)/LogsResponse.svelte
index 566ea1816..9a082779d 100644
--- a/src/routes/(console)/project-[project]/functions/function-[function]/executions/(components)/LogsResponse.svelte
+++ b/src/routes/(console)/project-[project]/functions/function-[function]/executions/(components)/LogsResponse.svelte
@@ -81,7 +81,17 @@
{/if}
{:else if responseTab === 'headers'}
{#if selectedLog.responseHeaders?.length}
-
+
Key
Value
diff --git a/src/routes/(console)/project-[project]/functions/function-[function]/executions/store.ts b/src/routes/(console)/project-[project]/functions/function-[function]/executions/store.ts
index 397a1d822..fa5843428 100644
--- a/src/routes/(console)/project-[project]/functions/function-[function]/executions/store.ts
+++ b/src/routes/(console)/project-[project]/functions/function-[function]/executions/store.ts
@@ -2,12 +2,12 @@ import type { Column } from '$lib/helpers/types';
import { writable } from 'svelte/store';
export const columns = writable([
- { id: '$id', title: 'Execution ID', type: 'string', width: 200 },
+ { id: '$id', title: 'Execution ID', type: 'string', width: { min: 200, max: 250 } },
{
id: 'requestPath',
title: 'Path',
type: 'string',
- width: 90,
+ width: { min: 100, max: 200 },
format: 'string'
},
@@ -16,7 +16,7 @@ export const columns = writable([
title: 'Trigger',
type: 'string',
hide: true,
- width: 90,
+ width: { min: 90, max: 200 },
array: true,
format: 'enum',
elements: [
@@ -30,7 +30,7 @@ export const columns = writable([
title: 'Method',
type: 'string',
hide: true,
- width: 70,
+ width: { min: 90, max: 200 },
array: true,
format: 'enum',
elements: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']
@@ -40,7 +40,7 @@ export const columns = writable([
title: 'Status code',
type: 'integer',
hide: true,
- width: 100,
+ width: { min: 100, max: 200 },
format: 'integer',
elements: [
{
@@ -66,7 +66,7 @@ export const columns = writable([
id: 'status',
title: 'Status',
type: 'enum',
- width: 130,
+ width: { min: 130, max: 200 },
array: true,
format: 'enum',
elements: ['completed', 'failed', 'waiting', 'scheduled', 'processing', 'cancelled']
@@ -75,7 +75,8 @@ export const columns = writable([
id: 'duration',
title: 'Duration',
type: 'integer',
- width: 80,
+ width: { min: 80, max: 200 },
+
format: 'integer',
elements: [
{
@@ -96,7 +97,7 @@ export const columns = writable([
id: '$createdAt',
title: 'Created',
type: 'datetime',
- width: 120,
+ width: { min: 120, max: 200 },
format: 'datetime',
elements: [
{
diff --git a/src/routes/(console)/project-[project]/sites/+page.svelte b/src/routes/(console)/project-[project]/sites/+page.svelte
index 58864b1c0..4025cc497 100644
--- a/src/routes/(console)/project-[project]/sites/+page.svelte
+++ b/src/routes/(console)/project-[project]/sites/+page.svelte
@@ -22,6 +22,10 @@
import { columns } from './store';
import { View } from '$lib/helpers/load';
import Table from './table.svelte';
+ import { onMount } from 'svelte';
+ import { invalidate } from '$app/navigation';
+ import { Dependencies } from '$lib/constants';
+ import { sdk } from '$lib/stores/sdk';
export let data;
let show = false;
@@ -41,6 +45,14 @@
]);
$updateCommandGroupRanks({ sites: 1000 });
+
+ onMount(() => {
+ return sdk.forConsole.client.subscribe('console', (response) => {
+ if (response.events.includes(`sites.*`)) {
+ invalidate(Dependencies.SITES);
+ }
+ });
+ });
@@ -60,7 +72,7 @@
{#if data.siteList.total}
{#if data.view === View.Grid}
-
+
{:else}
{/if}
diff --git a/src/routes/(console)/project-[project]/sites/+page.ts b/src/routes/(console)/project-[project]/sites/+page.ts
index 1525d8c9e..73c610a59 100644
--- a/src/routes/(console)/project-[project]/sites/+page.ts
+++ b/src/routes/(console)/project-[project]/sites/+page.ts
@@ -17,35 +17,11 @@ export const load = async ({ url, depends, route }) => {
search || undefined
);
- // TODO: @Meldiron Discuss better solution for getting screnshot IDs
- const deployments: Models.Deployment[] = [];
- await Promise.all(
- siteList.sites.map(async (site) => {
- if (!site.deploymentId) {
- return;
- }
-
- // TODO: @Meldiron Tripple-check if this can ever happened
- // It happened to me but on QA that might have corrupted data
- try {
- const deployment = await sdk.forProject.sites.getDeployment(
- site.$id,
- site.deploymentId
- );
- deployments.push(deployment);
- } catch (err) {
- // Active deployment no longer available (deleted?)
- console.warn(err);
- }
- })
- );
-
return {
offset,
limit,
search,
siteList,
- deployments,
view
};
};
diff --git a/src/routes/(console)/project-[project]/sites/create-site/configuration.svelte b/src/routes/(console)/project-[project]/sites/create-site/configuration.svelte
index eaf9ca1bb..548b66be2 100644
--- a/src/routes/(console)/project-[project]/sites/create-site/configuration.svelte
+++ b/src/routes/(console)/project-[project]/sites/create-site/configuration.svelte
@@ -37,6 +37,7 @@
export let frameworks: Models.Framework[];
export let selectedFramework: Models.Framework;
$: frameworkData = frameworks.find((framework) => framework.key === selectedFramework?.key);
+ $: ssr = frameworkData?.adapters.find((adapter) => adapter.key === 'ssr');
export let variables: Partial[] = [];
export let installCommand = '';
@@ -54,9 +55,9 @@
let frameworkId = selectedFramework.key;
$: if (!installCommand || !buildCommand || !outputDirectory) {
- installCommand ||= frameworkData?.adapters?.ssr?.installCommand;
- buildCommand ||= frameworkData?.adapters?.ssr?.buildCommand;
- outputDirectory ||= frameworkData?.adapters?.ssr?.outputDirectory;
+ installCommand ||= ssr?.installCommand;
+ buildCommand ||= ssr?.buildCommand;
+ outputDirectory ||= ssr?.outputDirectory;
}
@@ -86,15 +87,12 @@
id="installCommand"
label="Install command"
bind:value={installCommand}
- placeholder={frameworkData?.adapters?.ssr?.installCommand} />
+ placeholder={ssr?.installCommand} />
@@ -103,14 +101,12 @@
id="buildCommand"
label="Build command"
bind:value={buildCommand}
- placeholder={frameworkData?.adapters?.ssr?.buildCommand} />
+ placeholder={ssr?.buildCommand} />
@@ -119,15 +115,12 @@
id="outputDirectory"
label="Output directory"
bind:value={outputDirectory}
- placeholder={frameworkData?.adapters?.ssr?.outputDirectory} />
+ placeholder={ssr?.outputDirectory} />
diff --git a/src/routes/(console)/project-[project]/sites/grid.svelte b/src/routes/(console)/project-[project]/sites/grid.svelte
index 8bf682b60..5e0c12e5e 100644
--- a/src/routes/(console)/project-[project]/sites/grid.svelte
+++ b/src/routes/(console)/project-[project]/sites/grid.svelte
@@ -3,7 +3,7 @@
import { page } from '$app/stores';
import { timeFromNow } from '$lib/helpers/date';
import type { Models } from '@appwrite.io/console';
- import { Card, Layout, Tooltip } from '@appwrite.io/pink-svelte';
+ import { Card, Icon, Layout, Popover, Tooltip, Typography } from '@appwrite.io/pink-svelte';
import { getFrameworkIcon } from './store';
import { SvgIcon } from '$lib/components';
import { app } from '$lib/stores/app';
@@ -11,25 +11,24 @@
import AddCollaboratorModal from './(components)/addCollaboratorModal.svelte';
import SitesActionMenu from './sitesActionMenu.svelte';
import { capitalize } from '$lib/helpers/string';
+ import { timer } from '$lib/helpers/timeConversion';
+ import { IconExclamation } from '@appwrite.io/pink-icons-svelte';
+ import { Link } from '$lib/elements';
export let siteList: Models.SiteList;
- export let deployments: Models.Deployment[];
let showAddCollaborator = false;
let selectedSite: Models.Site = null;
function getScreenshot(theme: string, site: Models.Site) {
- const deployment =
- deployments.find((d) => site.deploymentId && d.$id === site.deploymentId) ?? null;
-
if (theme === 'dark') {
- return deployment?.screenshotDark
- ? getFilePreview(deployment.screenshotDark)
+ return site?.deploymentScreenshotDark
+ ? getFilePreview(site?.deploymentScreenshotDark)
: `${base}/images/sites/screenshot-placeholder-dark.svg`;
}
- return deployment?.screenshotLight
- ? getFilePreview(deployment.screenshotLight)
+ return site?.deploymentScreenshotLight
+ ? getFilePreview(site?.deploymentScreenshotLight)
: `${base}/images/sites/screenshot-placeholder-light.svg`;
}
@@ -38,6 +37,14 @@
const endpoint = getApiEndpoint();
return endpoint + `/storage/buckets/screenshots/files/${fileId}/view?project=console`;
}
+
+ function generateDesc(site: Models.Site) {
+ if (site.latestDeploymentStatus === 'building') {
+ return `Deployment building ${timer(site.latestDeploymentCreatedAt)}`;
+ } else {
+ return `Deployed ${timeFromNow(site.deploymentCreatedAt)}`;
+ }
+ }
@@ -47,7 +54,7 @@
padding="xxs">
@@ -60,6 +67,31 @@
+
+
+ {#if site.latestDeploymentStatus === 'failed'}
+
+
+
+
+ Last deployment failed {timeFromNow(
+ site.latestDeploymentCreatedAt
+ )}.
+ View logs
+
+
+
+
+ {/if}
+
{/each}
diff --git a/src/routes/(console)/project-[project]/sites/site-[site]/deployments/+layout.svelte b/src/routes/(console)/project-[project]/sites/site-[site]/deployments/+layout.svelte
index 12b32e0fb..dcd79f94a 100644
--- a/src/routes/(console)/project-[project]/sites/site-[site]/deployments/+layout.svelte
+++ b/src/routes/(console)/project-[project]/sites/site-[site]/deployments/+layout.svelte
@@ -25,8 +25,8 @@
}
if (message.events.includes('sites.*.deployments.*.update')) {
invalidate(Dependencies.DEPLOYMENTS);
- invalidate(Dependencies.FUNCTION);
-
+ invalidate(Dependencies.SITE);
+ console.log(message);
return;
}
if (message.events.includes('sites.*.deployments.*.delete')) {
diff --git a/src/routes/(console)/project-[project]/sites/site-[site]/deployments/store.ts b/src/routes/(console)/project-[project]/sites/site-[site]/deployments/store.ts
index c0da6dbc3..853decfdf 100644
--- a/src/routes/(console)/project-[project]/sites/site-[site]/deployments/store.ts
+++ b/src/routes/(console)/project-[project]/sites/site-[site]/deployments/store.ts
@@ -19,7 +19,7 @@ export const columns = writable([
id: 'buildDuration',
title: 'Build duration',
type: 'integer',
- width: { min: 110, max: 170 },
+ width: { min: 110, max: 190 },
elements: [
{
@@ -37,12 +37,32 @@ export const columns = writable([
],
filter: false
},
+ {
+ id: 'totalSize',
+ title: 'Total size',
+ type: 'integer',
+ width: { min: 110, max: 190 },
+ elements: [
+ {
+ value: 2 * 1000 * 1000,
+ label: 'more than 2MB'
+ },
+ {
+ value: 10 * 1000 * 1000,
+ label: 'more than 10MB'
+ },
+ {
+ value: 50 * 1000 * 1000,
+ label: 'more than 50MB'
+ }
+ ]
+ },
{
id: 'sourceSize',
title: 'Source size',
type: 'integer',
hide: true,
- width: { min: 110, max: 170 },
+ width: { min: 110, max: 190 },
elements: [
{
value: 2 * 1000 * 1000,
@@ -62,14 +82,15 @@ export const columns = writable([
id: 'buildSize',
title: 'Build size',
type: 'integer',
+ hide: true,
filter: false,
- width: { min: 90, max: 140 }
+ width: { min: 90, max: 190 }
},
{
id: 'type',
title: 'Source',
type: 'string',
- width: { min: 90, max: 140 },
+ width: { min: 90, max: 160 },
array: true,
format: 'enum',
elements: [
diff --git a/src/routes/(console)/project-[project]/sites/site-[site]/deployments/table.svelte b/src/routes/(console)/project-[project]/sites/site-[site]/deployments/table.svelte
index 505614071..5692c2e05 100644
--- a/src/routes/(console)/project-[project]/sites/site-[site]/deployments/table.svelte
+++ b/src/routes/(console)/project-[project]/sites/site-[site]/deployments/table.svelte
@@ -68,6 +68,8 @@
{:else}
{formatTimeDetailed(deployment.buildDuration)}
{/if}
+ {:else if column.id === 'totalSize'}
+ {calculateSize(deployment.totalSize)}
{:else if column.id === 'sourceSize'}
{calculateSize(deployment.sourceSize)}
{:else if column.id === 'buildSize'}
diff --git a/src/routes/(console)/project-[project]/sites/site-[site]/deploymentsOverview.svelte b/src/routes/(console)/project-[project]/sites/site-[site]/deploymentsOverview.svelte
index c62c89f89..bd209195b 100644
--- a/src/routes/(console)/project-[project]/sites/site-[site]/deploymentsOverview.svelte
+++ b/src/routes/(console)/project-[project]/sites/site-[site]/deploymentsOverview.svelte
@@ -43,7 +43,15 @@
{#if deploymentList?.total}
-
+
Deployment ID
Status
diff --git a/src/routes/(console)/project-[project]/sites/site-[site]/domains/store.ts b/src/routes/(console)/project-[project]/sites/site-[site]/domains/store.ts
index b9a352d6e..8d7cb0d66 100644
--- a/src/routes/(console)/project-[project]/sites/site-[site]/domains/store.ts
+++ b/src/routes/(console)/project-[project]/sites/site-[site]/domains/store.ts
@@ -7,19 +7,19 @@ export const columns = writable([
title: 'Domain',
type: 'string',
format: 'string',
- width: { min: 200, max: 700 }
+ width: { min: 200, max: 550 }
},
{
id: 'redirectUrl',
title: 'Redirect to',
type: 'string',
- width: { min: 120, max: 300 }
+ width: { min: 120, max: 400 }
},
{
id: 'deploymentVcsProviderBranch',
title: 'Production branch',
type: 'string',
- width: { min: 90, max: 200 }
+ width: { min: 90, max: 220 }
}
]);
diff --git a/src/routes/(console)/project-[project]/sites/site-[site]/logs/(components)/LogsRequest.svelte b/src/routes/(console)/project-[project]/sites/site-[site]/logs/(components)/LogsRequest.svelte
index d6d65981e..2c6ff7f40 100644
--- a/src/routes/(console)/project-[project]/sites/site-[site]/logs/(components)/LogsRequest.svelte
+++ b/src/routes/(console)/project-[project]/sites/site-[site]/logs/(components)/LogsRequest.svelte
@@ -86,7 +86,17 @@
{/if}
{:else if requestTab === 'headers'}
{#if selectedLog.requestHeaders?.length}
-
+
Key
Value
diff --git a/src/routes/(console)/project-[project]/sites/site-[site]/logs/(components)/LogsResponse.svelte b/src/routes/(console)/project-[project]/sites/site-[site]/logs/(components)/LogsResponse.svelte
index c43f1b225..94cd2b55e 100644
--- a/src/routes/(console)/project-[project]/sites/site-[site]/logs/(components)/LogsResponse.svelte
+++ b/src/routes/(console)/project-[project]/sites/site-[site]/logs/(components)/LogsResponse.svelte
@@ -73,7 +73,17 @@
{/if}
{:else if responseTab === 'headers'}
{#if selectedLog.responseHeaders?.length}
-
+
Key
Value
diff --git a/src/routes/(console)/project-[project]/sites/site-[site]/settings/+page.svelte b/src/routes/(console)/project-[project]/sites/site-[site]/settings/+page.svelte
index d83bb7a02..676d1c3a0 100644
--- a/src/routes/(console)/project-[project]/sites/site-[site]/settings/+page.svelte
+++ b/src/routes/(console)/project-[project]/sites/site-[site]/settings/+page.svelte
@@ -52,8 +52,6 @@
showConnectRepo.set(true);
}
});
-
- $: console.log(data);
diff --git a/src/routes/(console)/project-[project]/sites/site-[site]/settings/updateBuildSettings.svelte b/src/routes/(console)/project-[project]/sites/site-[site]/settings/updateBuildSettings.svelte
index 07f4f783a..23896d171 100644
--- a/src/routes/(console)/project-[project]/sites/site-[site]/settings/updateBuildSettings.svelte
+++ b/src/routes/(console)/project-[project]/sites/site-[site]/settings/updateBuildSettings.svelte
@@ -28,15 +28,12 @@
let fallback = site.fallbackFile;
let isButtonDisabled = true;
let showFallback = site.adapter === Adapter.Static;
+ $: frameworkAdapterData = selectedFramework.adapters.find((a) => a.key === adapter);
onMount(async () => {
- installCommand =
- site?.installCommand ?? selectedFramework.adapters[site.adapter].defaultInstallCommand;
- buildCommand =
- site?.buildCommand ?? selectedFramework.adapters[site.adapter].defaultBuildCommand;
- outputDirectory =
- site?.outputDirectory ??
- selectedFramework.adapters[site.adapter].defaultOutputDirectory;
+ installCommand = site?.installCommand ?? frameworkAdapterData?.installCommand;
+ buildCommand = site?.buildCommand ?? frameworkAdapterData?.buildCommand;
+ outputDirectory = site?.outputDirectory ?? frameworkAdapterData?.outputDirectory;
});
async function updateName() {
@@ -89,8 +86,7 @@
$: if (adapter === Adapter.Static) {
showFallback = true;
- fallback ||= selectedFramework.adapters.static.fallbackFile;
- console.log(fallback, selectedFramework.adapters.static);
+ fallback ||= selectedFramework.adapters.find((a) => a.key === Adapter.Static).fallbackFile;
} else {
showFallback = false;
fallback = undefined;
@@ -100,15 +96,12 @@
fallback = null;
}
- $: frameworkDataAdapter = selectedFramework.adapters?.length
- ? selectedFramework.adapters[site.adapter]
- : frameworks[0].adapters[site.adapter];
-
- //TODO: fix after backend type is fixed
- $: if (selectedFramework?.adapters?.length <= 1 || !selectedFramework?.adapters?.ssr?.key) {
+ $: hasSSR = selectedFramework?.adapters?.some((a) => a?.key === Adapter.Ssr);
+ $: hasStatic = selectedFramework?.adapters?.some((a) => a?.key === Adapter.Static);
+ $: if (selectedFramework?.adapters?.length <= 1 || !hasSSR) {
adapter = Adapter.Static;
}
- $: if (selectedFramework?.adapters?.length <= 1 || !selectedFramework?.adapters?.static?.key) {
+ $: if (selectedFramework?.adapters?.length <= 1 || !hasStatic) {
adapter = Adapter.Ssr;
}
@@ -139,7 +132,7 @@
(framework) => framework.key === frameworkKey
);
}} />
- {#if selectedFramework.adapters?.length || (selectedFramework.adapters?.ssr?.key && selectedFramework.adapters?.static?.key)}
+ {#if selectedFramework.adapters?.length > 2}
+ placeholder={frameworkAdapterData?.installCommand} />
+ placeholder={frameworkAdapterData?.buildCommand} />
+ placeholder={frameworkAdapterData?.outputDirectory} />