Skip to content
Open
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
17 changes: 0 additions & 17 deletions apps/web/client/public/onlook-preload-script.js

This file was deleted.

54 changes: 39 additions & 15 deletions apps/web/client/src/server/api/routers/domain/adapters/freestyle.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,66 @@
import type { FreestyleDeployWebSuccessResponseV2 } from 'freestyle-sandboxes';
import { initializeFreestyleSdk } from '../freestyle';
import type {
HostingProviderAdapter,
DeploymentRequest,
DeploymentResponse
import {
type HostingProviderAdapter,
type DeploymentRequest,
type DeploymentResponse,
} from '@onlook/models';

export class FreestyleAdapter implements HostingProviderAdapter {
async deploy(request: DeploymentRequest): Promise<DeploymentResponse> {
const sdk = initializeFreestyleSdk();


if (request.type === 'url') {
const res = await sdk.deployWeb(
{ kind: 'tar', url: request.sourceUrl },
request.config,
);

const freestyleResponse = res as {
message?: string;
error?: { message: string };
data?: FreestyleDeployWebSuccessResponseV2;
};

if (freestyleResponse.error) {
throw new Error(
freestyleResponse.error.message ?? freestyleResponse.message ?? 'Unknown error',
);
}

return {
deploymentId: freestyleResponse.data?.deploymentId ?? '',
success: true,
message: freestyleResponse.message,
};
}

const res = await sdk.deployWeb(
{
files: request.files,
files: request.files ?? {},
kind: 'files',
},
request.config
request.config,
);

const freestyleResponse = res as {
message?: string;
error?: {
message: string;
};
data?: FreestyleDeployWebSuccessResponseV2;
};

if (freestyleResponse.error) {
throw new Error(
freestyleResponse.error.message ||
freestyleResponse.message ||
'Unknown error'
freestyleResponse.error.message ?? freestyleResponse.message ?? 'Unknown error',
);
}

return {
deploymentId: freestyleResponse.data?.deploymentId ?? '',
success: true
success: true,
message: freestyleResponse.message,
};
}
}
}
65 changes: 40 additions & 25 deletions apps/web/client/src/server/api/routers/publish/helpers/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import { trackEvent } from '@/utils/analytics/server.ts';
import { deployments, type Deployment } from '@onlook/db';
import type { DrizzleDb } from '@onlook/db/src/client';
import {
type DeploymentResponse,
DeploymentStatus,
DeploymentType,
type DeploymentType,
HostingProvider
} from '@onlook/models';
import { TRPCError } from '@trpc/server';
Expand All @@ -14,37 +15,51 @@ import {
import { HostingProviderFactory } from '../../domain/hosting-factory.ts';

export const deployFreestyle = async (
{
files,
urls,
envVars,
}: {
files: Record<string, FreestyleFile>,
urls: string[],
envVars?: Record<string, string>,
args: (
{ files: Record<string, FreestyleFile>; sourceUrl?: undefined } |
{ files?: undefined; sourceUrl: string }
) & {
urls: string[];
envVars?: Record<string, string>;
type: "url" | "files";
}
): Promise<{
success: boolean;
message?: string;
}> => {
const entrypoint = 'server.js';
const adapter = HostingProviderFactory.create(HostingProvider.FREESTYLE);
const deploymentFiles: Record<string, { content: string; encoding?: 'utf-8' | 'base64' }> = {};
for (const [path, file] of Object.entries(files)) {
deploymentFiles[path] = {
content: file.content,
encoding: (file.encoding === 'base64' ? 'base64' : 'utf-8')
};
}
const adapter = HostingProviderFactory.create(HostingProvider.FREESTYLE)

const result = await adapter.deploy({
files: deploymentFiles,
config: {
domains: urls,
entrypoint,
envVars,
},
});
let result: DeploymentResponse;

if(args.type === 'url' && args.sourceUrl) {
result = await adapter.deploy({
type: 'url',
sourceUrl: args.sourceUrl,
config: {
domains: args.urls,
entrypoint,
envVars: args.envVars,
},
});
} else if(args.type === 'files' && args.files) {
result = await adapter.deploy({
type: 'files',
files: Object.fromEntries(
Object.entries(args.files).map(([path, file]) => [
path,
{ content: file.content, encoding: file.encoding as 'utf-8' | 'base64' },
]),
),
config: {
domains: args.urls,
entrypoint,
envVars: args.envVars,
},
});
} else {
throw new Error('Invalid deployment request');
}

if (!result.success) {
throw new Error(result.message ?? 'Failed to deploy project');
Expand Down
85 changes: 62 additions & 23 deletions apps/web/client/src/server/api/routers/publish/helpers/publish.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,34 +56,73 @@ export async function publish({ db, deployment }: { db: DrizzleDb; deployment: D
}

const publishManager = new PublishManager(provider);
const files = await publishManager.publish({
skipBadge: type === DeploymentType.CUSTOM,
buildScript: buildScript ?? DefaultSettings.COMMANDS.build,
buildFlags: buildFlags ?? DefaultSettings.EDITOR_SETTINGS.buildFlags,
updateDeployment: (deployment) => updateDeployment(db, deploymentId, deployment),
});

const updateDeploymentResult3 = await updateDeployment(db, deploymentId, {
status: DeploymentStatus.IN_PROGRESS,
message: 'Deploying build...',
progress: 80,
});
if (!updateDeploymentResult3) {
throw new TRPCError({
code: 'BAD_REQUEST',
message: 'Update deployment failed',
let deployed = false;
try {
const artifactUrl = await publishManager.buildAndUploadArtifact({
skipBadge: type === DeploymentType.CUSTOM,
buildScript: buildScript ?? DefaultSettings.COMMANDS.build,
buildFlags: buildFlags ?? DefaultSettings.EDITOR_SETTINGS.buildFlags,
updateDeployment: (deployment) => updateDeployment(db, deploymentId, deployment),
});

const updateDeploymentResult3 = await updateDeployment(db, deploymentId, {
status: DeploymentStatus.IN_PROGRESS,
message: 'Deploying build...',
progress: 80,
});
if (!updateDeploymentResult3) {
throw new TRPCError({
code: 'BAD_REQUEST',
message: 'Update deployment failed',
});
}

// Note: Prefer user provided env vars over sandbox env vars
const sandboxEnvVars = await extractEnvVarsFromSandbox(provider);
const mergedEnvVars = { ...sandboxEnvVars, ...(envVars ?? {}) };

await deployFreestyle({
sourceUrl: artifactUrl,
urls: deploymentUrls,
envVars: mergedEnvVars,
type: 'url',
});
deployed = true;
} catch (artifactError) {
console.warn('[publish] Artifact path failed, falling back to file deployment', artifactError);
}

// Note: Prefer user provided env vars over sandbox env vars
const sandboxEnvVars = await extractEnvVarsFromSandbox(provider);
const mergedEnvVars = { ...sandboxEnvVars, ...(envVars ?? {}) };
if (!deployed) {
const files = await publishManager.buildFiles({
skipBadge: type === DeploymentType.CUSTOM,
buildScript: buildScript ?? DefaultSettings.COMMANDS.build,
buildFlags: buildFlags ?? DefaultSettings.EDITOR_SETTINGS.buildFlags,
updateDeployment: (deployment) => updateDeployment(db, deploymentId, deployment),
});

await deployFreestyle({
files,
urls: deploymentUrls,
envVars: mergedEnvVars,
});
const updateDeploymentResult3 = await updateDeployment(db, deploymentId, {
status: DeploymentStatus.IN_PROGRESS,
message: 'Deploying build...',
progress: 80,
});
if (!updateDeploymentResult3) {
throw new TRPCError({
code: 'BAD_REQUEST',
message: 'Update deployment failed',
});
}

const sandboxEnvVars = await extractEnvVarsFromSandbox(provider);
const mergedEnvVars = { ...sandboxEnvVars, ...(envVars ?? {}) };

await deployFreestyle({
files,
urls: deploymentUrls,
envVars: mergedEnvVars,
type: 'files',
});
}
} finally {
await provider.destroy();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export const unpublish = async (db: DrizzleDb, deployment: Deployment, urls: str

try {
await deployFreestyle({
type: 'files',
files: {},
urls,
envVars: {},
Expand Down
Loading