v1.0.13 (#46)
This commit is contained in:
parent
23a4ebb74a
commit
adcd68c1ab
19
README.md
19
README.md
@ -1,4 +1,3 @@
|
||||
|
||||
# Coolify
|
||||
|
||||
An open-source, hassle-free, self-hostable Heroku & Netlify alternative.
|
||||
@ -7,8 +6,7 @@ An open-source, hassle-free, self-hostable Heroku & Netlify alternative.
|
||||
|
||||
[Small video](https://cdn.coollabs.io/assets/coolify/video/coolify.webm)
|
||||
|
||||
|
||||
## Installation
|
||||
## Installation
|
||||
|
||||
Installation is automated with the following command:
|
||||
|
||||
@ -16,37 +14,41 @@ Installation is automated with the following command:
|
||||
/bin/bash -c "$(curl -fsSL https://get.coollabs.io/coolify/install.sh)"
|
||||
```
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
You can deploy any of the following applications, databases and services easily.
|
||||
|
||||
(constantly growing lists)
|
||||
|
||||
### Applications
|
||||
|
||||
With Github integration
|
||||
|
||||
- Static sites
|
||||
- NodeJS
|
||||
- VueJS
|
||||
- NuxtJS
|
||||
- NextJS
|
||||
- React/Preact
|
||||
- NextJS
|
||||
- Gatsby
|
||||
- Svelte
|
||||
- PHP
|
||||
- Rust
|
||||
- Rust
|
||||
- or any custom dockerfile
|
||||
|
||||
### Databases
|
||||
|
||||
- MongoDB
|
||||
- MySQL
|
||||
- PostgreSQL
|
||||
- CouchDB
|
||||
- Redis
|
||||
|
||||
### Services
|
||||
|
||||
- [Plausible Analytics](https://plausible.io)
|
||||
|
||||
|
||||
## Support
|
||||
|
||||
- Twitter: [@andrasbacsai](https://twitter.com/andrasbacsai)
|
||||
@ -55,10 +57,9 @@ With Github integration
|
||||
- Discord: [Invitation](https://discord.com/invite/bvS3WhR)
|
||||
|
||||
## Roadmap
|
||||
|
||||
[See the Roadmap here](https://github.com/coollabsio/coolify/projects/1)
|
||||
|
||||
|
||||
## License
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Please see the [LICENSE](/LICENSE) file in our repository for the full text.
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "coolify",
|
||||
"description": "An open-source, hassle-free, self-hostable Heroku & Netlify alternative.",
|
||||
"version": "1.0.12",
|
||||
"version": "1.0.13",
|
||||
"license": "AGPL-3.0",
|
||||
"scripts": {
|
||||
"dev:docker:start": "docker-compose -f docker-compose-dev.yml up -d",
|
||||
@ -31,7 +31,7 @@
|
||||
"prettier-plugin-svelte": "^2.3.0",
|
||||
"svelte": "^3.38.2",
|
||||
"svelte-preprocess": "^4.7.3",
|
||||
"tailwindcss": "canary",
|
||||
"tailwindcss": "2.2.0-canary.8",
|
||||
"tslib": "^2.2.0",
|
||||
"typescript": "^4.2.4",
|
||||
"vite": "^2.3.2"
|
||||
|
2716
pnpm-lock.yaml
generated
2716
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -9,77 +9,96 @@
|
||||
active: false,
|
||||
number: 80
|
||||
},
|
||||
build: true
|
||||
build: true,
|
||||
start: false
|
||||
},
|
||||
nodejs: {
|
||||
port: {
|
||||
active: true,
|
||||
number: 3000
|
||||
},
|
||||
build: true
|
||||
build: true,
|
||||
start: true
|
||||
},
|
||||
nestjs: {
|
||||
port: {
|
||||
active: true,
|
||||
number: 3000
|
||||
},
|
||||
build: true,
|
||||
start: true
|
||||
},
|
||||
vuejs: {
|
||||
port: {
|
||||
active: false,
|
||||
number: 80
|
||||
},
|
||||
build: true
|
||||
build: true,
|
||||
start: false
|
||||
},
|
||||
nuxtjs: {
|
||||
port: {
|
||||
active: true,
|
||||
number: 3000
|
||||
},
|
||||
build: true
|
||||
build: true,
|
||||
start: true
|
||||
},
|
||||
react: {
|
||||
port: {
|
||||
active: false,
|
||||
number: 80
|
||||
},
|
||||
build: true
|
||||
build: true,
|
||||
start: false
|
||||
},
|
||||
nextjs: {
|
||||
port: {
|
||||
active: true,
|
||||
number: 3000
|
||||
},
|
||||
build: true
|
||||
build: true,
|
||||
start: true
|
||||
},
|
||||
gatsby: {
|
||||
port: {
|
||||
active: true,
|
||||
number: 3000
|
||||
},
|
||||
build: true
|
||||
build: true,
|
||||
start: false
|
||||
},
|
||||
svelte: {
|
||||
port: {
|
||||
active: false,
|
||||
number: 80
|
||||
},
|
||||
build: true
|
||||
build: true,
|
||||
start: false
|
||||
},
|
||||
php: {
|
||||
port: {
|
||||
active: false,
|
||||
number: 80
|
||||
},
|
||||
build: false
|
||||
build: false,
|
||||
start: false
|
||||
},
|
||||
rust: {
|
||||
port: {
|
||||
active: true,
|
||||
number: 3000
|
||||
},
|
||||
build: false
|
||||
build: false,
|
||||
start: false
|
||||
},
|
||||
docker: {
|
||||
port: {
|
||||
active: true,
|
||||
number: 3000
|
||||
},
|
||||
build: false
|
||||
build: false,
|
||||
start: false
|
||||
}
|
||||
};
|
||||
function selectBuildPack(event) {
|
||||
@ -90,8 +109,9 @@
|
||||
}
|
||||
}
|
||||
onMount(() => {
|
||||
if(!$application.publish.domain) domainInput.focus();
|
||||
if (!$application.publish.domain) domainInput.focus();
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<div>
|
||||
@ -178,6 +198,14 @@
|
||||
>
|
||||
Rust
|
||||
</div>
|
||||
<div
|
||||
class={$application.build.pack === 'nestjs'
|
||||
? 'buildpack bg-red-500'
|
||||
: 'buildpack hover:border-red-500'}
|
||||
on:click={selectBuildPack}
|
||||
>
|
||||
NestJS
|
||||
</div>
|
||||
<div
|
||||
class={$application.build.pack === 'docker'
|
||||
? 'buildpack bg-purple-500'
|
||||
@ -267,7 +295,7 @@
|
||||
for="installCommand"
|
||||
class:text-warmGray-800={!buildpacks[$application.build.pack].build}
|
||||
>Install Command <TooltipInfo
|
||||
label="Command to run for installing dependencies. eg: yarn install."
|
||||
label="Command to run for installing dependencies. eg: yarn install"
|
||||
/>
|
||||
</label>
|
||||
|
||||
@ -300,6 +328,22 @@
|
||||
bind:value={$application.build.command.build}
|
||||
placeholder="eg: yarn build"
|
||||
/>
|
||||
<label
|
||||
for="startCommand"
|
||||
class:text-warmGray-800={!buildpacks[$application.build.pack].start}
|
||||
>Start Command <TooltipInfo label="Command to start the application. eg: yarn start" /></label
|
||||
>
|
||||
<input
|
||||
class="mb-6"
|
||||
class:bg-warmGray-900={!buildpacks[$application.build.pack].start}
|
||||
class:text-warmGray-900={!buildpacks[$application.build.pack].start}
|
||||
class:placeholder-warmGray-800={!buildpacks[$application.build.pack].start}
|
||||
class:hover:bg-warmGray-900={!buildpacks[$application.build.pack].start}
|
||||
class:cursor-not-allowed={!buildpacks[$application.build.pack].start}
|
||||
id="startcommand"
|
||||
bind:value={$application.build.command.start}
|
||||
placeholder="eg: yarn start"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -309,4 +353,5 @@
|
||||
.buildpack {
|
||||
@apply px-6 py-2 mx-2 my-2 bg-warmGray-800 w-48 ease-in-out transform hover:scale-105 text-center rounded border-2 border-transparent border-dashed cursor-pointer transition duration-100;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import { request } from '$lib/api/request';
|
||||
import { request } from '$lib/request';
|
||||
import { session } from '$app/stores';
|
||||
import { githubRepositories, application, githubInstallations } from '$store';
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
import { onDestroy } from 'svelte';
|
||||
import { toast } from '@zerodevx/svelte-toast';
|
||||
import Tooltip from '$components/Tooltip.svelte';
|
||||
import { request } from '$lib/api/request';
|
||||
import { request } from '$lib/request';
|
||||
import { page, session } from '$app/stores';
|
||||
import { goto } from '$app/navigation';
|
||||
import { browser } from '$app/env';
|
||||
|
@ -1,13 +1,13 @@
|
||||
<script>
|
||||
import { toast } from '@zerodevx/svelte-toast';
|
||||
import templates from '$lib/api/applications/templates';
|
||||
import templates from '$lib/api/applications/packs/templates';
|
||||
import { application, dashboard } from '$store';
|
||||
import General from '$components/Application/ActiveTab/General.svelte';
|
||||
import Secrets from '$components/Application/ActiveTab/Secrets.svelte';
|
||||
import Loading from '$components/Loading.svelte';
|
||||
import { goto } from '$app/navigation';
|
||||
import { page, session } from '$app/stores';
|
||||
import { request } from '$lib/api/request';
|
||||
import { request } from '$lib/request';
|
||||
import { browser } from '$app/env';
|
||||
|
||||
let activeTab = {
|
||||
@ -80,10 +80,18 @@
|
||||
if (checkPackageJSONContents(dep)) {
|
||||
const config = templates[dep];
|
||||
$application.build.pack = config.pack;
|
||||
if (config.installation)
|
||||
if (config.installation) {
|
||||
$application.build.command.installation = config.installation;
|
||||
if (config.port) $application.publish.port = config.port;
|
||||
if (config.directory) $application.publish.directory = config.directory;
|
||||
}
|
||||
if (config.start) {
|
||||
$application.build.command.start = config.start;
|
||||
}
|
||||
if (config.port) {
|
||||
$application.publish.port = config.port;
|
||||
}
|
||||
if (config.directory) {
|
||||
$application.publish.directory = config.directory;
|
||||
}
|
||||
|
||||
if (packageJsonContent.scripts.hasOwnProperty('build') && config.build) {
|
||||
$application.build.command.build = config.build;
|
||||
|
@ -5,16 +5,19 @@
|
||||
import Postgresql from './SVGs/Postgresql.svelte';
|
||||
import Mysql from './SVGs/Mysql.svelte';
|
||||
import CouchDb from './SVGs/CouchDb.svelte';
|
||||
import Redis from './SVGs/Redis.svelte';
|
||||
import { page, session } from '$app/stores';
|
||||
import { goto } from '$app/navigation';
|
||||
import { request } from '$lib/api/request';
|
||||
import { request } from '$lib/request';
|
||||
import { browser } from '$app/env';
|
||||
import Loading from '$components/Loading.svelte';
|
||||
|
||||
let type;
|
||||
let defaultDatabaseName;
|
||||
|
||||
let loading = false;
|
||||
async function deploy() {
|
||||
try {
|
||||
loading = true;
|
||||
await request(`/api/v1/databases/deploy`, $session, {
|
||||
body: {
|
||||
type,
|
||||
@ -28,82 +31,106 @@
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
} finally {
|
||||
loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<div class="text-center space-y-2 max-w-4xl mx-auto px-6" in:fade={{ duration: 100 }}>
|
||||
{#if $page.path === '/database/new'}
|
||||
<div class="flex justify-center space-x-4 font-bold pb-6">
|
||||
<div
|
||||
class="text-center flex-col items-center cursor-pointer ease-in-out transform hover:scale-105 duration-100 border-2 border-dashed border-transparent hover:border-green-600 p-2 rounded bg-warmGray-800 w-32"
|
||||
class:border-green-600={type === 'mongodb'}
|
||||
on:click={() => (type = 'mongodb')}
|
||||
>
|
||||
<div class="flex items-center justify-center my-2">
|
||||
<MongoDb customClass="w-6" />
|
||||
{#if loading}
|
||||
<Loading />
|
||||
{:else}
|
||||
<div class="text-center space-y-2 max-w-4xl mx-auto px-6" in:fade={{ duration: 100 }}>
|
||||
{#if $page.path === '/database/new'}
|
||||
<div class="flex justify-center space-x-4 font-bold pb-6">
|
||||
<div
|
||||
class="text-center flex-col items-center cursor-pointer ease-in-out transform hover:scale-105 duration-100 border-2 border-dashed border-transparent hover:border-green-600 p-2 rounded bg-warmGray-800 w-32"
|
||||
class:border-green-600={type === 'mongodb'}
|
||||
on:click={() => (type = 'mongodb')}
|
||||
>
|
||||
<div class="flex items-center justify-center my-2">
|
||||
<MongoDb customClass="w-6" />
|
||||
</div>
|
||||
<div class="text-white">MongoDB</div>
|
||||
</div>
|
||||
<div class="text-white">MongoDB</div>
|
||||
</div>
|
||||
<div
|
||||
class="text-center flex-col items-center cursor-pointer ease-in-out transform hover:scale-105 duration-100 border-2 border-dashed border-transparent hover:border-red-600 p-2 rounded bg-warmGray-800 w-32"
|
||||
class:border-red-600={type === 'couchdb'}
|
||||
on:click={() => (type = 'couchdb')}
|
||||
>
|
||||
<div class="flex items-center justify-center my-2">
|
||||
<CouchDb customClass="w-12 text-red-600 fill-current" />
|
||||
<div
|
||||
class="text-center flex-col items-center cursor-pointer ease-in-out transform hover:scale-105 duration-100 border-2 border-dashed border-transparent hover:border-red-600 p-2 rounded bg-warmGray-800 w-32"
|
||||
class:border-red-600={type === 'couchdb'}
|
||||
on:click={() => (type = 'couchdb')}
|
||||
>
|
||||
<div class="flex items-center justify-center my-2">
|
||||
<CouchDb customClass="w-12 text-red-600 fill-current" />
|
||||
</div>
|
||||
<div class="text-white">Couchdb</div>
|
||||
</div>
|
||||
<div class="text-white">Couchdb</div>
|
||||
</div>
|
||||
<div
|
||||
class="text-center flex-col items-center cursor-pointer ease-in-out transform hover:scale-105 duration-100 border-2 border-dashed border-transparent hover:border-blue-600 p-2 rounded bg-warmGray-800 w-32"
|
||||
class:border-blue-600={type === 'postgresql'}
|
||||
on:click={() => (type = 'postgresql')}
|
||||
>
|
||||
<div class="flex items-center justify-center my-2">
|
||||
<Postgresql customClass="w-12" />
|
||||
<div
|
||||
class="text-center flex-col items-center cursor-pointer ease-in-out transform hover:scale-105 duration-100 border-2 border-dashed border-transparent hover:border-blue-600 p-2 rounded bg-warmGray-800 w-32"
|
||||
class:border-blue-600={type === 'postgresql'}
|
||||
on:click={() => (type = 'postgresql')}
|
||||
>
|
||||
<div class="flex items-center justify-center my-2">
|
||||
<Postgresql customClass="w-12" />
|
||||
</div>
|
||||
<div class="text-white">PostgreSQL</div>
|
||||
</div>
|
||||
<div class="text-white">PostgreSQL</div>
|
||||
</div>
|
||||
<div
|
||||
class="text-center flex-col items-center cursor-pointer ease-in-out transform hover:scale-105 duration-100 border-2 border-dashed border-transparent hover:border-orange-600 p-2 rounded bg-warmGray-800 w-32"
|
||||
class:border-orange-600={type === 'mysql'}
|
||||
on:click={() => (type = 'mysql')}
|
||||
>
|
||||
<div class="flex items-center justify-center">
|
||||
<Mysql customClass="w-10" />
|
||||
<div
|
||||
class="text-center flex-col items-center cursor-pointer ease-in-out transform hover:scale-105 duration-100 border-2 border-dashed border-transparent hover:border-orange-600 p-2 rounded bg-warmGray-800 w-32"
|
||||
class:border-orange-600={type === 'mysql'}
|
||||
on:click={() => (type = 'mysql')}
|
||||
>
|
||||
<div class="flex items-center justify-center">
|
||||
<Mysql customClass="w-10" />
|
||||
</div>
|
||||
<div class="text-white">MySQL</div>
|
||||
</div>
|
||||
<div
|
||||
class="text-center flex-col items-center cursor-pointer ease-in-out transform hover:scale-105 duration-100 border-2 border-dashed border-transparent hover:border-red-600 p-2 rounded bg-warmGray-800 w-32"
|
||||
class:border-red-600={type === 'redis'}
|
||||
on:click={() => (type = 'redis')}
|
||||
>
|
||||
<div class="flex items-center justify-center">
|
||||
<Redis customClass="w-12" />
|
||||
</div>
|
||||
<div class="text-white">Redis</div>
|
||||
</div>
|
||||
<div class="text-white">MySQL</div>
|
||||
</div>
|
||||
|
||||
<!-- <button
|
||||
<!-- <button
|
||||
class="button bg-gray-500 p-2 text-white hover:bg-yellow-500 cursor-pointer w-32"
|
||||
on:click="{() => (type = 'clickhouse')}"
|
||||
class:bg-yellow-500="{type === 'clickhouse'}"
|
||||
>
|
||||
Clickhouse
|
||||
</button> -->
|
||||
</div>
|
||||
{#if type}
|
||||
<div class="flex justify-center space-x-4 items-center">
|
||||
<label for="defaultDB">Default database</label>
|
||||
<input id="defaultDB" class="w-64" placeholder="random" bind:value={defaultDatabaseName} />
|
||||
|
||||
<button
|
||||
class:bg-green-600={type === 'mongodb'}
|
||||
class:hover:bg-green-500={type === 'mongodb'}
|
||||
class:bg-blue-600={type === 'postgresql'}
|
||||
class:hover:bg-blue-500={type === 'postgresql'}
|
||||
class:bg-orange-600={type === 'mysql'}
|
||||
class:hover:bg-orange-500={type === 'mysql'}
|
||||
class:bg-red-600={type === 'couchdb'}
|
||||
class:hover:bg-red-500={type === 'couchdb'}
|
||||
class:bg-yellow-500={type === 'clickhouse'}
|
||||
class:hover:bg-yellow-400={type === 'clickhouse'}
|
||||
class="button p-2 w-32 text-white"
|
||||
on:click={deploy}>Deploy</button
|
||||
>
|
||||
</div>
|
||||
{#if type}
|
||||
<div class="flex justify-center space-x-4 items-center">
|
||||
{#if type !== 'redis'}
|
||||
<label for="defaultDB">Default database</label>
|
||||
<input
|
||||
id="defaultDB"
|
||||
class="w-64"
|
||||
placeholder="random"
|
||||
bind:value={defaultDatabaseName}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<button
|
||||
class:bg-green-600={type === 'mongodb'}
|
||||
class:hover:bg-green-500={type === 'mongodb'}
|
||||
class:bg-blue-600={type === 'postgresql'}
|
||||
class:hover:bg-blue-500={type === 'postgresql'}
|
||||
class:bg-orange-600={type === 'mysql'}
|
||||
class:hover:bg-orange-500={type === 'mysql'}
|
||||
class:bg-red-600={type === 'couchdb' || type === 'redis'}
|
||||
class:hover:bg-red-500={type === 'couchdb' || type === 'redis'}
|
||||
class:bg-yellow-500={type === 'clickhouse'}
|
||||
class:hover:bg-yellow-400={type === 'clickhouse'}
|
||||
class="button p-2 w-32 text-white"
|
||||
on:click={deploy}>Deploy</button
|
||||
>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
37
src/components/Database/SVGs/Redis.svelte
Normal file
37
src/components/Database/SVGs/Redis.svelte
Normal file
@ -0,0 +1,37 @@
|
||||
<script>
|
||||
export let customClass;
|
||||
|
||||
</script>
|
||||
|
||||
<svg
|
||||
class={customClass}
|
||||
height="64"
|
||||
viewBox="0 0 32 32"
|
||||
width="64"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
><defs
|
||||
><path
|
||||
id="a"
|
||||
d="m45.536 38.764c-2.013 1.05-12.44 5.337-14.66 6.494s-3.453 1.146-5.207.308-12.85-5.32-14.85-6.276c-1-.478-1.524-.88-1.524-1.26v-3.813s14.447-3.145 16.78-3.982 3.14-.867 5.126-.14 13.853 2.868 15.814 3.587v3.76c0 .377-.452.8-1.477 1.324z"
|
||||
/><path
|
||||
id="b"
|
||||
d="m45.536 28.733c-2.013 1.05-12.44 5.337-14.66 6.494s-3.453 1.146-5.207.308-12.85-5.32-14.85-6.276-2.04-1.613-.077-2.382l15.332-5.935c2.332-.837 3.14-.867 5.126-.14s12.35 4.853 14.312 5.57 2.037 1.31.024 2.36z"
|
||||
/></defs
|
||||
><g transform="matrix(.848327 0 0 .848327 -7.883573 -9.449691)"
|
||||
><use fill="#a41e11" xlink:href="#a" /><path
|
||||
d="m45.536 34.95c-2.013 1.05-12.44 5.337-14.66 6.494s-3.453 1.146-5.207.308-12.85-5.32-14.85-6.276-2.04-1.613-.077-2.382l15.332-5.936c2.332-.836 3.14-.867 5.126-.14s12.35 4.852 14.31 5.582 2.037 1.31.024 2.36z"
|
||||
fill="#d82c20"
|
||||
/><use fill="#a41e11" xlink:href="#a" y="-6.218" /><use fill="#d82c20" xlink:href="#b" /><path
|
||||
d="m45.536 26.098c-2.013 1.05-12.44 5.337-14.66 6.495s-3.453 1.146-5.207.308-12.85-5.32-14.85-6.276c-1-.478-1.524-.88-1.524-1.26v-3.815s14.447-3.145 16.78-3.982 3.14-.867 5.126-.14 13.853 2.868 15.814 3.587v3.76c0 .377-.452.8-1.477 1.324z"
|
||||
fill="#a41e11"
|
||||
/><use fill="#d82c20" xlink:href="#b" y="-6.449" /><g fill="#fff"
|
||||
><path
|
||||
d="m29.096 20.712-1.182-1.965-3.774-.34 2.816-1.016-.845-1.56 2.636 1.03 2.486-.814-.672 1.612 2.534.95-3.268.34zm-6.296 3.912 8.74-1.342-2.64 3.872z"
|
||||
/><ellipse cx="20.444" cy="21.402" rx="4.672" ry="1.811" /></g
|
||||
><path d="m42.132 21.138-5.17 2.042-.004-4.087z" fill="#7a0c00" /><path
|
||||
d="m36.963 23.18-.56.22-5.166-2.042 5.723-2.264z"
|
||||
fill="#ad2115"
|
||||
/></g
|
||||
></svg
|
||||
>
|
@ -3,7 +3,7 @@
|
||||
import { toast } from '@zerodevx/svelte-toast';
|
||||
import Loading from '../Loading.svelte';
|
||||
import Tooltip from '$components/Tooltip.svelte';
|
||||
import { request } from '$lib/api/request';
|
||||
import { request } from '$lib/request';
|
||||
import { page, session } from '$app/stores';
|
||||
import PasswordField from '$components/PasswordField.svelte';
|
||||
import { browser } from '$app/env';
|
||||
|
1
src/global.d.ts
vendored
1
src/global.d.ts
vendored
@ -43,6 +43,7 @@ export type Application = {
|
||||
command: {
|
||||
build: string | null;
|
||||
installation: string;
|
||||
start: string;
|
||||
};
|
||||
container: {
|
||||
name: string;
|
||||
|
@ -4,6 +4,9 @@ import { publicPages } from '$lib/consts';
|
||||
import mongoose from 'mongoose';
|
||||
import { verifyUserId } from '$lib/api/common';
|
||||
import { initializeSession } from 'svelte-kit-cookie-session';
|
||||
import { cleanupStuckedDeploymentsInDB } from '$lib/api/applications/cleanup';
|
||||
import { docker } from '$lib/api/docker';
|
||||
import Configuration from '$models/Configuration';
|
||||
|
||||
process.on('SIGINT', function () {
|
||||
mongoose.connection.close(function () {
|
||||
@ -13,6 +16,7 @@ process.on('SIGINT', function () {
|
||||
});
|
||||
|
||||
async function connectMongoDB() {
|
||||
// TODO: Save configurations on start?
|
||||
const { MONGODB_USER, MONGODB_PASSWORD, MONGODB_HOST, MONGODB_PORT, MONGODB_DB } = process.env;
|
||||
try {
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
@ -27,12 +31,65 @@ async function connectMongoDB() {
|
||||
);
|
||||
}
|
||||
console.log('Connected to mongodb.');
|
||||
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (mongoose.connection.readyState !== 1) connectMongoDB();
|
||||
(async () => {
|
||||
console.log(mongoose.connection.readyState)
|
||||
if (mongoose.connection.readyState !== 1) await connectMongoDB();
|
||||
try {
|
||||
await mongoose.connection.db.dropCollection('logs-servers');
|
||||
} catch (error) {
|
||||
//
|
||||
}
|
||||
try {
|
||||
await cleanupStuckedDeploymentsInDB();
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
try {
|
||||
const dockerServices = await docker.engine.listServices();
|
||||
let applications: any = dockerServices.filter(
|
||||
(r) =>
|
||||
r.Spec.Labels.managedBy === 'coolify' &&
|
||||
r.Spec.Labels.type === 'application' &&
|
||||
r.Spec.Labels.configuration
|
||||
);
|
||||
applications = applications.map((r) => {
|
||||
if (JSON.parse(r.Spec.Labels.configuration)) {
|
||||
return {
|
||||
configuration: JSON.parse(r.Spec.Labels.configuration),
|
||||
UpdatedAt: r.UpdatedAt
|
||||
};
|
||||
}
|
||||
return {};
|
||||
});
|
||||
applications = [
|
||||
...new Map(
|
||||
applications.map((item) => [
|
||||
item.configuration.publish.domain + item.configuration.publish.path,
|
||||
item
|
||||
])
|
||||
).values()
|
||||
];
|
||||
for (const application of applications) {
|
||||
await Configuration.findOneAndUpdate({
|
||||
'repository.name': application.configuration.repository.name,
|
||||
'repository.organization': application.configuration.repository.organization,
|
||||
'repository.branch': application.configuration.repository.branch,
|
||||
}, {
|
||||
...application.configuration
|
||||
}, { upsert: true })
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
})()
|
||||
|
||||
|
||||
export async function handle({ request, render }) {
|
||||
const { SECRETS_ENCRYPTION_KEY } = process.env;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import Deployment from '$models/Logs/Deployment';
|
||||
import Deployment from '$models/Deployment';
|
||||
import { saveAppLog } from './logging';
|
||||
import * as packs from './packs';
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { docker } from '$lib/api/docker';
|
||||
import Deployment from '$models/Deployment';
|
||||
import { execShellAsync } from '../common';
|
||||
|
||||
export async function deleteSameDeployments(configuration) {
|
||||
@ -17,29 +18,49 @@ export async function deleteSameDeployments(configuration) {
|
||||
});
|
||||
}
|
||||
|
||||
export async function cleanupStuckedDeploymentsInDB() {
|
||||
// Cleanup stucked deployments.
|
||||
await Deployment.updateMany(
|
||||
{ progress: { $in: ['queued', 'inprogress'] } },
|
||||
{ progress: 'failed' }
|
||||
);
|
||||
}
|
||||
export async function purgeImagesContainers(configuration, deleteAll = false) {
|
||||
const { name, tag } = configuration.build.container;
|
||||
await execShellAsync('docker container prune -f');
|
||||
if (deleteAll) {
|
||||
const IDsToDelete = (
|
||||
await execShellAsync(`docker images ls --filter=reference='${name}' --format '{{json .ID }}'`)
|
||||
)
|
||||
.trim()
|
||||
.replace(/"/g, '')
|
||||
.split('\n');
|
||||
if (IDsToDelete.length > 0)
|
||||
await execShellAsync(`docker rmi -f ${IDsToDelete.toString().replace(',', ' ')}`);
|
||||
} else {
|
||||
const IDsToDelete = (
|
||||
await execShellAsync(
|
||||
`docker images ls --filter=reference='${name}' --filter=before='${name}:${tag}' --format '{{json .ID }}'`
|
||||
)
|
||||
)
|
||||
.trim()
|
||||
.replace(/"/g, '')
|
||||
.split('\n');
|
||||
if (IDsToDelete.length > 1)
|
||||
await execShellAsync(`docker rmi -f ${IDsToDelete.toString().replace(',', ' ')}`);
|
||||
try {
|
||||
await execShellAsync('docker container prune -f');
|
||||
} catch (error) {
|
||||
//
|
||||
}
|
||||
try {
|
||||
if (deleteAll) {
|
||||
const IDsToDelete = (
|
||||
await execShellAsync(
|
||||
`docker images ls --filter=reference='${name}' --format '{{json .ID }}'`
|
||||
)
|
||||
)
|
||||
.trim()
|
||||
.replace(/"/g, '')
|
||||
.split('\n');
|
||||
if (IDsToDelete.length > 0) await execShellAsync(`docker rmi -f ${IDsToDelete.join(' ')}`);
|
||||
} else {
|
||||
const IDsToDelete = (
|
||||
await execShellAsync(
|
||||
`docker images ls --filter=reference='${name}' --filter=before='${name}:${tag}' --format '{{json .ID }}'`
|
||||
)
|
||||
)
|
||||
.trim()
|
||||
.replace(/"/g, '')
|
||||
.split('\n');
|
||||
if (IDsToDelete.length > 1) await execShellAsync(`docker rmi -f ${IDsToDelete.join(' ')}`);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
try {
|
||||
await execShellAsync('docker image prune -f');
|
||||
} catch (error) {
|
||||
//
|
||||
}
|
||||
await execShellAsync('docker image prune -f');
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
import Settings from '$models/Settings';
|
||||
import ServerLog from '$models/Logs/Server';
|
||||
import ApplicationLog from '$models/Logs/Application';
|
||||
import ServerLog from '$models/ServerLog';
|
||||
import ApplicationLog from '$models/ApplicationLog';
|
||||
import dayjs from 'dayjs';
|
||||
import { version } from '../../../../package.json';
|
||||
|
||||
|
||||
function generateTimestamp() {
|
||||
return `${dayjs().format('YYYY-MM-DD HH:mm:ss.SSS')} `;
|
||||
}
|
||||
|
@ -1,20 +1,21 @@
|
||||
import { docker, streamEvents } from '$lib/api/docker';
|
||||
import { promises as fs } from 'fs';
|
||||
|
||||
const buildImageNodeDocker = (configuration) => {
|
||||
const buildImageNodeDocker = (configuration, prodBuild) => {
|
||||
return [
|
||||
'FROM node:lts',
|
||||
'WORKDIR /usr/src/app',
|
||||
`COPY ${configuration.build.directory}/package*.json ./`,
|
||||
configuration.build.command.installation && `RUN ${configuration.build.command.installation}`,
|
||||
`COPY ./${configuration.build.directory} ./`,
|
||||
`RUN ${configuration.build.command.build}`
|
||||
`RUN ${configuration.build.command.build}`,
|
||||
prodBuild && `RUN rm -fr node_modules && ${configuration.build.command.installation} --prod`
|
||||
].join('\n');
|
||||
};
|
||||
export async function buildImage(configuration, cacheBuild?: boolean) {
|
||||
export async function buildImage(configuration, cacheBuild?: boolean, prodBuild?: boolean) {
|
||||
await fs.writeFile(
|
||||
`${configuration.general.workdir}/Dockerfile`,
|
||||
buildImageNodeDocker(configuration)
|
||||
buildImageNodeDocker(configuration, prodBuild)
|
||||
);
|
||||
const stream = await docker.engine.buildImage(
|
||||
{ src: ['.'], context: configuration.general.workdir },
|
||||
|
@ -7,6 +7,7 @@ import php from './php';
|
||||
import nuxtjs from './nuxtjs';
|
||||
import nodejs from './nodejs';
|
||||
import nextjs from './nextjs';
|
||||
import nestjs from './nestjs';
|
||||
import gatsby from './gatsby';
|
||||
import docker from './docker';
|
||||
|
||||
@ -20,6 +21,7 @@ export {
|
||||
nuxtjs,
|
||||
nodejs,
|
||||
nextjs,
|
||||
nestjs,
|
||||
gatsby,
|
||||
docker
|
||||
};
|
||||
|
31
src/lib/api/applications/packs/nestjs/index.ts
Normal file
31
src/lib/api/applications/packs/nestjs/index.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import { docker, streamEvents } from '$lib/api/docker';
|
||||
import { promises as fs } from 'fs';
|
||||
import { buildImage } from '../helpers';
|
||||
// `HEALTHCHECK --timeout=10s --start-period=10s --interval=5s CMD curl -I -s -f http://localhost:${configuration.publish.port}${configuration.publish.path} || exit 1`,
|
||||
const publishNodejsDocker = (configuration) => {
|
||||
return [
|
||||
'FROM node:lts',
|
||||
'WORKDIR /usr/src/app',
|
||||
configuration.build.command.build
|
||||
? `COPY --from=${configuration.build.container.name}:${configuration.build.container.tag} /usr/src/app/${configuration.publish.directory} ./`
|
||||
: `
|
||||
COPY ${configuration.build.directory}/package*.json ./
|
||||
RUN ${configuration.build.command.installation}
|
||||
COPY ./${configuration.build.directory} ./`,
|
||||
`EXPOSE ${configuration.publish.port}`,
|
||||
`CMD ${configuration.build.command.start}`
|
||||
].join('\n');
|
||||
};
|
||||
|
||||
export default async function (configuration) {
|
||||
if (configuration.build.command.build) await buildImage(configuration, false, true);
|
||||
await fs.writeFile(
|
||||
`${configuration.general.workdir}/Dockerfile`,
|
||||
publishNodejsDocker(configuration)
|
||||
);
|
||||
const stream = await docker.engine.buildImage(
|
||||
{ src: ['.'], context: configuration.general.workdir },
|
||||
{ t: `${configuration.build.container.name}:${configuration.build.container.tag}` }
|
||||
);
|
||||
await streamEvents(stream, configuration);
|
||||
}
|
@ -13,7 +13,7 @@ const publishNodejsDocker = (configuration) => {
|
||||
RUN ${configuration.build.command.installation}
|
||||
COPY ./${configuration.build.directory} ./`,
|
||||
`EXPOSE ${configuration.publish.port}`,
|
||||
'CMD [ "yarn", "start" ]'
|
||||
`CMD ${configuration.build.command.start}`
|
||||
].join('\n');
|
||||
};
|
||||
export default async function (configuration) {
|
||||
|
@ -13,7 +13,7 @@ const publishNodejsDocker = (configuration) => {
|
||||
RUN ${configuration.build.command.installation}
|
||||
COPY ./${configuration.build.directory} ./`,
|
||||
`EXPOSE ${configuration.publish.port}`,
|
||||
'CMD [ "yarn", "start" ]'
|
||||
`CMD ${configuration.build.command.start}`
|
||||
].join('\n');
|
||||
};
|
||||
|
||||
|
@ -13,7 +13,7 @@ const publishNodejsDocker = (configuration) => {
|
||||
RUN ${configuration.build.command.installation}
|
||||
COPY ./${configuration.build.directory} ./`,
|
||||
`EXPOSE ${configuration.publish.port}`,
|
||||
'CMD [ "yarn", "start" ]'
|
||||
`CMD ${configuration.build.command.start}`
|
||||
].join('\n');
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
const defaultBuildAndDeploy = {
|
||||
installation: 'yarn install',
|
||||
build: 'yarn build'
|
||||
build: 'yarn build',
|
||||
start: 'yarn start'
|
||||
};
|
||||
|
||||
const templates = {
|
||||
@ -10,6 +11,13 @@ const templates = {
|
||||
directory: 'public',
|
||||
name: 'Svelte'
|
||||
},
|
||||
'@nestjs/core': {
|
||||
pack: 'nestjs',
|
||||
...defaultBuildAndDeploy,
|
||||
start: 'yarn start:prod',
|
||||
port: 3000,
|
||||
name: 'NestJS'
|
||||
},
|
||||
next: {
|
||||
pack: 'nextjs',
|
||||
...defaultBuildAndDeploy,
|
@ -1,4 +1,5 @@
|
||||
import Deployment from '$models/Logs/Deployment';
|
||||
|
||||
import Deployment from '$models/Deployment';
|
||||
import dayjs from 'dayjs';
|
||||
import buildContainer from './buildContainer';
|
||||
import { updateServiceLabels } from './configuration';
|
||||
@ -9,23 +10,21 @@ import { saveAppLog } from './logging';
|
||||
export default async function (configuration, imageChanged) {
|
||||
const { id, organization, name, branch } = configuration.repository;
|
||||
const { domain } = configuration.publish;
|
||||
const { deployId, nickname } = configuration.general;
|
||||
await new Deployment({
|
||||
repoId: id,
|
||||
branch,
|
||||
deployId,
|
||||
domain,
|
||||
organization,
|
||||
name,
|
||||
nickname
|
||||
}).save();
|
||||
await saveAppLog(`${dayjs().format('YYYY-MM-DD HH:mm:ss.SSS')} Queued.`, configuration);
|
||||
await copyFiles(configuration);
|
||||
await buildContainer(configuration);
|
||||
await deploy(configuration, imageChanged);
|
||||
await Deployment.findOneAndUpdate(
|
||||
{ repoId: id, branch, deployId, organization, name, domain },
|
||||
{ repoId: id, branch, deployId, organization, name, domain, progress: 'done' }
|
||||
);
|
||||
await updateServiceLabels(configuration);
|
||||
const { deployId} = configuration.general;
|
||||
try {
|
||||
await saveAppLog(`${dayjs().format('YYYY-MM-DD HH:mm:ss.SSS')} Queued.`, configuration);
|
||||
await copyFiles(configuration);
|
||||
await buildContainer(configuration);
|
||||
await deploy(configuration, imageChanged);
|
||||
await Deployment.findOneAndUpdate(
|
||||
{ repoId: id, branch, deployId, organization, name, domain },
|
||||
{ repoId: id, branch, deployId, organization, name, domain, progress: 'done' }
|
||||
);
|
||||
await updateServiceLabels(configuration);
|
||||
} catch (error) {
|
||||
await Deployment.findOneAndUpdate(
|
||||
{ repoId: id, branch, deployId, organization, name, domain },
|
||||
{ repoId: id, branch, deployId, organization, name, domain, progress: 'failed' }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,17 @@
|
||||
import shell from 'shelljs';
|
||||
import User from '$models/User';
|
||||
import jsonwebtoken from 'jsonwebtoken';
|
||||
import { saveServerLog } from './applications/logging';
|
||||
|
||||
export function execShellAsync(cmd, opts = {}) {
|
||||
try {
|
||||
return new Promise(function (resolve, reject) {
|
||||
shell.config.silent = true;
|
||||
shell.exec(cmd, opts, function (code, stdout, stderr) {
|
||||
if (code !== 0) return reject(new Error(stderr));
|
||||
shell.exec(cmd, opts, async function (code, stdout, stderr) {
|
||||
if (code !== 0) {
|
||||
await saveServerLog({ message: JSON.stringify({ cmd, opts, code, stdout, stderr }) })
|
||||
return reject(new Error(stderr));
|
||||
}
|
||||
return resolve(stdout);
|
||||
});
|
||||
});
|
||||
|
23
src/lib/api/github.ts
Normal file
23
src/lib/api/github.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import type { Request } from '@sveltejs/kit';
|
||||
|
||||
export async function githubAPI(
|
||||
request: Request,
|
||||
resource: string,
|
||||
token?: string,
|
||||
data?: Record<string, unknown>
|
||||
) {
|
||||
const base = 'https://api.github.com';
|
||||
const res = await fetch(`${base}${resource}`, {
|
||||
method: request.method,
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
accept: 'application/json',
|
||||
authorization: token ? `token ${token}` : ''
|
||||
},
|
||||
body: data && JSON.stringify(data)
|
||||
});
|
||||
return {
|
||||
status: res.status,
|
||||
body: await res.json()
|
||||
};
|
||||
}
|
@ -61,7 +61,6 @@ export async function request(
|
||||
} else if (response.headers.get('content-type').match(/multipart\/form-data/)) {
|
||||
return await response.formData();
|
||||
} else {
|
||||
console.log(response);
|
||||
if (response.headers.get('content-disposition')) {
|
||||
const blob = await response.blob();
|
||||
console.log(blob);
|
||||
@ -86,10 +85,10 @@ export async function request(
|
||||
});
|
||||
} else if (response.status >= 500) {
|
||||
const error = (await response.json()).error;
|
||||
browser && toast.push(error);
|
||||
browser && toast.push(error.message || error);
|
||||
return Promise.reject({
|
||||
status: response.status,
|
||||
error: error || 'Oops, something is not okay. Are you okay?'
|
||||
error: error.message || error || 'Oops, something is not okay. Are you okay?'
|
||||
});
|
||||
} else {
|
||||
browser && toast.push(response.statusText);
|
@ -8,4 +8,4 @@ const ApplicationLogsSchema = new Schema({
|
||||
|
||||
ApplicationLogsSchema.set('timestamps', true);
|
||||
|
||||
export default mongoose.model('logs-application', ApplicationLogsSchema);
|
||||
export default mongoose.models['logs-application'] || mongoose.model('logs-application', ApplicationLogsSchema);
|
48
src/models/Configuration.ts
Normal file
48
src/models/Configuration.ts
Normal file
@ -0,0 +1,48 @@
|
||||
import mongoose from 'mongoose';
|
||||
const { Schema } = mongoose;
|
||||
const ConfigurationSchema = new Schema({
|
||||
github: {
|
||||
installation: {
|
||||
id: { type: Number, required: true }
|
||||
},
|
||||
app: {
|
||||
id: { type: Number, required: true }
|
||||
}
|
||||
},
|
||||
repository: {
|
||||
id: { type: Number, required: true },
|
||||
organization: { type: String, required: true },
|
||||
name: { type: String, required: true },
|
||||
branch: { type: String, required: true },
|
||||
},
|
||||
general: {
|
||||
deployId: { type: String, required: true },
|
||||
nickname: { type: String, required: true },
|
||||
workdir: { type: String, required: true },
|
||||
},
|
||||
build: {
|
||||
pack: { type: String, required: true },
|
||||
directory: { type: String },
|
||||
command: {
|
||||
build: { type: String },
|
||||
installation: { type: String },
|
||||
start: { type: String },
|
||||
},
|
||||
container: {
|
||||
name: { type: String, required: true },
|
||||
tag: { type: String, required: true },
|
||||
baseSHA: { type: String, required: true },
|
||||
},
|
||||
},
|
||||
publish: {
|
||||
directory: { type: String },
|
||||
domain: { type: String, required: true },
|
||||
path: { type: String },
|
||||
port: { type: Number },
|
||||
secrets: { type: Array },
|
||||
}
|
||||
});
|
||||
|
||||
ConfigurationSchema.set('timestamps', true);
|
||||
|
||||
export default mongoose.models['configuration'] || mongoose.model('configuration', ConfigurationSchema);
|
@ -14,4 +14,4 @@ const DeploymentSchema = new Schema({
|
||||
|
||||
DeploymentSchema.set('timestamps', true);
|
||||
|
||||
export default mongoose.model('deployment', DeploymentSchema);
|
||||
export default mongoose.models['deployment'] || mongoose.model('deployment', DeploymentSchema);
|
@ -1,5 +1,5 @@
|
||||
import mongoose from 'mongoose';
|
||||
import { version } from '../../../package.json';
|
||||
import { version } from '../../package.json'
|
||||
const { Schema, Document } = mongoose;
|
||||
|
||||
// export interface ILogsServer extends Document {
|
||||
@ -20,4 +20,4 @@ const LogsServerSchema = new Schema({
|
||||
|
||||
LogsServerSchema.set('timestamps', { createdAt: 'createdAt', updatedAt: false });
|
||||
|
||||
export default mongoose.model('logs-server', LogsServerSchema);
|
||||
export default mongoose.models['logs-server'] || mongoose.model('logs-server', LogsServerSchema);
|
@ -14,4 +14,4 @@ const SettingsSchema = new Schema({
|
||||
|
||||
SettingsSchema.set('timestamps', true);
|
||||
|
||||
export default mongoose.model('settings', SettingsSchema);
|
||||
export default mongoose.models['settings'] || mongoose.model('settings', SettingsSchema);
|
||||
|
@ -14,4 +14,4 @@ const UserSchema = new Schema({
|
||||
|
||||
UserSchema.set('timestamps', true);
|
||||
|
||||
export default mongoose.model('user', UserSchema);
|
||||
export default mongoose.models['user'] || mongoose.model('user', UserSchema);
|
||||
|
@ -1,6 +1,6 @@
|
||||
<script context="module" lang="ts">
|
||||
import { publicPages } from '$lib/consts';
|
||||
import { request } from '$lib/api/request';
|
||||
import { request } from '$lib/request';
|
||||
/**
|
||||
* @type {import('@sveltejs/kit').Load}
|
||||
*/
|
||||
|
@ -1,42 +0,0 @@
|
||||
import type { Request } from '@sveltejs/kit';
|
||||
|
||||
// export async function api(request: Request, resource: string, data?: {}) {
|
||||
// const base = 'https://github.com/';
|
||||
// if (!request.context.isLoggedIn) {
|
||||
// return { status: 401, body: 'Unauthorized' };
|
||||
// }
|
||||
|
||||
// const res = await fetch(`${base}${resource}`, {
|
||||
// method: request.method,
|
||||
// headers: {
|
||||
// 'content-type': 'application/json'
|
||||
// },
|
||||
// body: data && JSON.stringify(data)
|
||||
// });
|
||||
// return {
|
||||
// status: res.status,
|
||||
// body: await res.json()
|
||||
// };
|
||||
// }
|
||||
|
||||
export async function githubAPI(
|
||||
request: Request,
|
||||
resource: string,
|
||||
token?: string,
|
||||
data?: Record<string, unknown>
|
||||
) {
|
||||
const base = 'https://api.github.com';
|
||||
const res = await fetch(`${base}${resource}`, {
|
||||
method: request.method,
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
accept: 'application/json',
|
||||
authorization: token ? `token ${token}` : ''
|
||||
},
|
||||
body: data && JSON.stringify(data)
|
||||
});
|
||||
return {
|
||||
status: res.status,
|
||||
body: await res.json()
|
||||
};
|
||||
}
|
@ -44,7 +44,7 @@ export async function post(request: Request) {
|
||||
return {
|
||||
status: 500,
|
||||
body: {
|
||||
error
|
||||
error: error.message || error
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,9 +1,25 @@
|
||||
import { docker } from '$lib/api/docker';
|
||||
import Configuration from '$models/Configuration';
|
||||
import type { Request } from '@sveltejs/kit';
|
||||
|
||||
export async function post(request: Request) {
|
||||
const { name, organization, branch }: any = request.body || {};
|
||||
if (name && organization && branch) {
|
||||
const configurationFound = await Configuration.findOne({
|
||||
'repository.name': name,
|
||||
'repository.organization': organization,
|
||||
'repository.branch': branch,
|
||||
}).lean()
|
||||
if (configurationFound) {
|
||||
return {
|
||||
status: 200,
|
||||
body: {
|
||||
success: true,
|
||||
...configurationFound
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const services = await docker.engine.listServices();
|
||||
const applications = services.filter(
|
||||
(r) => r.Spec.Labels.managedBy === 'coolify' && r.Spec.Labels.type === 'application'
|
||||
@ -38,13 +54,12 @@ export async function post(request: Request) {
|
||||
...JSON.parse(found.Spec.Labels.configuration)
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
status: 500,
|
||||
body: {
|
||||
error: 'No configuration found.'
|
||||
}
|
||||
};
|
||||
}
|
||||
return {
|
||||
status: 500,
|
||||
body: {
|
||||
error: 'No configuration found.'
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
import type { Request } from '@sveltejs/kit';
|
||||
import Deployment from '$models/Logs/Deployment';
|
||||
import Deployment from '$models/Deployment';
|
||||
import { docker } from '$lib/api/docker';
|
||||
import { precheckDeployment, setDefaultConfiguration } from '$lib/api/applications/configuration';
|
||||
import cloneRepository from '$lib/api/applications/cloneRepository';
|
||||
import { cleanupTmp } from '$lib/api/common';
|
||||
import queueAndBuild from '$lib/api/applications/queueAndBuild';
|
||||
import Configuration from '$models/Configuration';
|
||||
export async function post(request: Request) {
|
||||
let configuration;
|
||||
try {
|
||||
@ -53,6 +54,27 @@ export async function post(request: Request) {
|
||||
}
|
||||
};
|
||||
}
|
||||
const { id, organization, name, branch } = configuration.repository;
|
||||
const { domain } = configuration.publish;
|
||||
const { deployId, nickname } = configuration.general;
|
||||
await new Deployment({
|
||||
repoId: id,
|
||||
branch,
|
||||
deployId,
|
||||
domain,
|
||||
organization,
|
||||
name,
|
||||
nickname
|
||||
}).save();
|
||||
await Configuration.findOneAndUpdate({
|
||||
'repository.id': id,
|
||||
'repository.organization': organization,
|
||||
'repository.name': name,
|
||||
'repository.branch': branch,
|
||||
},
|
||||
{ ...configuration },
|
||||
{ upsert: true, new: true })
|
||||
|
||||
queueAndBuild(configuration, imageChanged);
|
||||
return {
|
||||
status: 200,
|
||||
@ -70,20 +92,21 @@ export async function post(request: Request) {
|
||||
branch: configuration.repository.branch,
|
||||
organization: configuration.repository.organization,
|
||||
name: configuration.repository.name,
|
||||
domain: configuration.publish.domain,
|
||||
domain: configuration.publish.domain
|
||||
},
|
||||
{
|
||||
repoId: configuration.repository.id,
|
||||
branch: configuration.repository.branch,
|
||||
organization: configuration.repository.organization,
|
||||
name: configuration.repository.name,
|
||||
domain: configuration.publish.domain, progress: 'failed'
|
||||
domain: configuration.publish.domain,
|
||||
progress: 'failed'
|
||||
}
|
||||
);
|
||||
return {
|
||||
status: 500,
|
||||
body: {
|
||||
error
|
||||
error: error.message || error
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import type { Request } from '@sveltejs/kit';
|
||||
import ApplicationLog from '$models/Logs/Application';
|
||||
import Deployment from '$models/Logs/Deployment';
|
||||
import ApplicationLog from '$models/ApplicationLog';
|
||||
import Deployment from '$models/Deployment';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
export async function get(request: Request) {
|
||||
@ -24,11 +24,11 @@ export async function get(request: Request) {
|
||||
...finalLogs
|
||||
}
|
||||
};
|
||||
} catch (e) {
|
||||
} catch (error) {
|
||||
return {
|
||||
status: 500,
|
||||
body: {
|
||||
error: e
|
||||
error: error.message || error
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import type { Request } from '@sveltejs/kit';
|
||||
import dayjs from 'dayjs';
|
||||
import utc from 'dayjs/plugin/utc.js';
|
||||
import relativeTime from 'dayjs/plugin/relativeTime.js';
|
||||
import Deployment from '$models/Logs/Deployment';
|
||||
import Deployment from '$models/Deployment';
|
||||
dayjs.extend(utc);
|
||||
dayjs.extend(relativeTime);
|
||||
export async function get(request: Request) {
|
||||
@ -10,7 +10,6 @@ export async function get(request: Request) {
|
||||
const repoId = request.query.get('repoId');
|
||||
const branch = request.query.get('branch');
|
||||
const page = request.query.get('page');
|
||||
|
||||
const onePage = 5;
|
||||
const show = Number(page) * onePage || 5;
|
||||
const deploy: any = await Deployment.find({ repoId, branch })
|
||||
@ -20,12 +19,9 @@ export async function get(request: Request) {
|
||||
|
||||
const finalLogs = deploy.map((d) => {
|
||||
const finalLogs = { ...d._doc };
|
||||
|
||||
const updatedAt = dayjs(d.updatedAt).utc();
|
||||
|
||||
finalLogs.took = updatedAt.diff(dayjs(d.createdAt)) / 1000;
|
||||
finalLogs.since = updatedAt.fromNow();
|
||||
|
||||
return finalLogs;
|
||||
});
|
||||
return {
|
||||
@ -36,11 +32,10 @@ export async function get(request: Request) {
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
return {
|
||||
status: 500,
|
||||
body: {
|
||||
error
|
||||
error: error.message || error
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -16,11 +16,12 @@ export async function get(request: Request) {
|
||||
body: { success: true, logs }
|
||||
};
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
await saveServerLog(error);
|
||||
return {
|
||||
status: 500,
|
||||
body: {
|
||||
error
|
||||
error: 'No such service. Is it under deployment?'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { purgeImagesContainers } from '$lib/api/applications/cleanup';
|
||||
import { docker } from '$lib/api/docker';
|
||||
import Deployment from '$models/Logs/Deployment';
|
||||
import ApplicationLog from '$models/Logs/Application';
|
||||
import Deployment from '$models/Deployment';
|
||||
import ApplicationLog from '$models/ApplicationLog';
|
||||
import { delay, execShellAsync } from '$lib/api/common';
|
||||
import Configuration from '$models/Configuration';
|
||||
|
||||
async function call(found) {
|
||||
await delay(10000);
|
||||
@ -26,6 +27,11 @@ export async function post(request: Request) {
|
||||
return null;
|
||||
});
|
||||
if (found) {
|
||||
await Configuration.findOneAndRemove({
|
||||
'repository.name': name,
|
||||
'repository.organization': organization,
|
||||
'repository.branch': branch,
|
||||
})
|
||||
const deploys = await Deployment.find({ organization, branch, name });
|
||||
for (const deploy of deploys) {
|
||||
await ApplicationLog.deleteMany({ deployId: deploy.deployId });
|
||||
|
@ -1,9 +1,7 @@
|
||||
import { docker } from '$lib/api/docker';
|
||||
import LogsServer from '$models/Logs/Server';
|
||||
import type { Request } from '@sveltejs/kit';
|
||||
|
||||
export async function get(request: Request) {
|
||||
const serverLogs = await LogsServer.find();
|
||||
const dockerServices = await docker.engine.listServices();
|
||||
let applications: any = dockerServices.filter(
|
||||
(r) =>
|
||||
@ -61,7 +59,6 @@ export async function get(request: Request) {
|
||||
status: 200,
|
||||
body: {
|
||||
success: true,
|
||||
serverLogs,
|
||||
applications: {
|
||||
deployed: applications
|
||||
},
|
@ -100,6 +100,31 @@ export async function post(request: Request) {
|
||||
body: fs.readFileSync(`${fullfilename}`)
|
||||
};
|
||||
}
|
||||
} else if (type === 'redis') {
|
||||
if (databaseService) {
|
||||
const password = configuration.database.passwords[0];
|
||||
const databaseName = configuration.database.defaultDatabaseName;
|
||||
const filename = `${databaseName}_${now.getTime()}.rdb`;
|
||||
const fullfilename = `${tmpdir}/${filename}`;
|
||||
await execShellAsync(
|
||||
`docker exec -i ${containerID} /bin/bash -c "redis-cli --pass ${password} save"`
|
||||
);
|
||||
await execShellAsync(
|
||||
`docker cp ${containerID}:/bitnami/redis/data/dump.rdb ${fullfilename}`
|
||||
);
|
||||
await execShellAsync(
|
||||
`docker exec -i ${containerID} /bin/bash -c "rm -f /bitnami/redis/data/dump.rdb"`
|
||||
);
|
||||
return {
|
||||
status: 200,
|
||||
headers: {
|
||||
'Content-Type': 'application/octet-stream',
|
||||
'Content-Transfer-Encoding': 'binary',
|
||||
'Content-Disposition': `attachment; filename=${filename}`
|
||||
},
|
||||
body: fs.readFileSync(`${fullfilename}`)
|
||||
};
|
||||
}
|
||||
}
|
||||
return {
|
||||
status: 501,
|
||||
@ -108,12 +133,11 @@ export async function post(request: Request) {
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
await saveServerLog(error);
|
||||
return {
|
||||
status: 500,
|
||||
body: {
|
||||
error
|
||||
error: error.message || error
|
||||
}
|
||||
};
|
||||
} finally {
|
||||
|
@ -96,6 +96,12 @@ export async function post(request: Request) {
|
||||
hard: 262144
|
||||
}
|
||||
};
|
||||
} else if (type === 'redis') {
|
||||
image = 'bitnami/redis';
|
||||
volume = `${configuration.general.deployId}-${type}-data:/bitnami/redis/data`;
|
||||
generateEnvs = {
|
||||
REDIS_PASSWORD: passwords[0]
|
||||
};
|
||||
}
|
||||
|
||||
const stack = {
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { githubAPI } from '$api';
|
||||
import type { Request } from '@sveltejs/kit';
|
||||
import mongoose from 'mongoose';
|
||||
import User from '$models/User';
|
||||
import Settings from '$models/Settings';
|
||||
import cuid from 'cuid';
|
||||
import jsonwebtoken from 'jsonwebtoken';
|
||||
import { githubAPI } from '$lib/api/github';
|
||||
|
||||
export async function get(request: Request) {
|
||||
const code = request.query.get('code');
|
||||
@ -17,7 +17,7 @@ export async function get(request: Request) {
|
||||
{ headers: { accept: 'application/json' } }
|
||||
)
|
||||
).json();
|
||||
const { avatar_url, id } = await (await githubAPI(request, '/user', access_token)).body;
|
||||
const { avatar_url } = await (await githubAPI(request, '/user', access_token)).body;
|
||||
const email = (await githubAPI(request, '/user/emails', access_token)).body.filter(
|
||||
(e) => e.primary
|
||||
)[0].email;
|
||||
@ -41,11 +41,10 @@ export async function get(request: Request) {
|
||||
try {
|
||||
await newUser.save();
|
||||
await defaultSettings.save();
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
} catch (error) {
|
||||
return {
|
||||
status: 500,
|
||||
body: e
|
||||
error: error.message || error
|
||||
};
|
||||
}
|
||||
} else {
|
||||
@ -73,12 +72,11 @@ export async function get(request: Request) {
|
||||
});
|
||||
try {
|
||||
await newUser.save();
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
} catch (error) {
|
||||
return {
|
||||
status: 500,
|
||||
body: {
|
||||
error: e
|
||||
error: error.message || error
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -103,8 +101,6 @@ export async function get(request: Request) {
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
console.log('error happened');
|
||||
console.log(error);
|
||||
return { status: 500, body: { ...error } };
|
||||
return { status: 500, body: { error: error.message || error } };
|
||||
}
|
||||
}
|
||||
|
@ -34,12 +34,11 @@ export async function get(request: Request) {
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
return {
|
||||
status: 500,
|
||||
body: {
|
||||
success: false,
|
||||
error
|
||||
error: error.message || error
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ export async function get(request: Request) {
|
||||
return {
|
||||
status: 500,
|
||||
body: {
|
||||
error
|
||||
error: error.message || error
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -45,7 +45,7 @@ export async function post(request: Request) {
|
||||
return {
|
||||
status: 500,
|
||||
body: {
|
||||
error
|
||||
error: error.message || error
|
||||
}
|
||||
};
|
||||
}
|
@ -10,7 +10,6 @@ export async function get(request: Request) {
|
||||
execShellAsync(
|
||||
'docker run --rm -v /var/run/docker.sock:/var/run/docker.sock -u root coolify bash -c "$(curl -fsSL https://get.coollabs.io/coolify/upgrade-p2.sh)"'
|
||||
);
|
||||
// saveServerLog({ message: upgradeP2, type: 'UPGRADE-P-2' })
|
||||
return {
|
||||
status: 200,
|
||||
body: {
|
@ -1,24 +0,0 @@
|
||||
// import { deleteCookies } from '$lib/api/common';
|
||||
// import { verifyUserId } from '$lib/api/common';
|
||||
// import type { Request } from '@sveltejs/kit';
|
||||
// import * as cookie from 'cookie';
|
||||
|
||||
// export async function post(request: Request) {
|
||||
// const { coolToken } = cookie.parse(request.headers.cookie || '');
|
||||
// try {
|
||||
// await verifyUserId(coolToken);
|
||||
// return {
|
||||
// status: 200,
|
||||
// body: { success: true }
|
||||
// };
|
||||
// } catch (error) {
|
||||
// return {
|
||||
// status: 301,
|
||||
// headers: {
|
||||
// location: '/',
|
||||
// 'set-cookie': [...deleteCookies]
|
||||
// },
|
||||
// body: { error: 'Unauthorized' }
|
||||
// };
|
||||
// }
|
||||
// }
|
@ -1,6 +1,6 @@
|
||||
import type { Request } from '@sveltejs/kit';
|
||||
import crypto from 'crypto';
|
||||
import Deployment from '$models/Logs/Deployment';
|
||||
import Deployment from '$models/Deployment';
|
||||
import { docker } from '$lib/api/docker';
|
||||
import { precheckDeployment, setDefaultConfiguration } from '$lib/api/applications/configuration';
|
||||
import cloneRepository from '$lib/api/applications/cloneRepository';
|
||||
@ -106,7 +106,7 @@ export async function post(request: Request) {
|
||||
return {
|
||||
status: 500,
|
||||
body: {
|
||||
error
|
||||
error: error.message || error
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
import Loading from '$components/Loading.svelte';
|
||||
import { request } from '$lib/api/request';
|
||||
import { request } from '$lib/request';
|
||||
import { page, session } from '$app/stores';
|
||||
import { goto } from '$app/navigation';
|
||||
import { browser } from '$app/env';
|
||||
|
@ -5,7 +5,7 @@
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
|
||||
import Loading from '$components/Loading.svelte';
|
||||
import { request } from '$lib/api/request';
|
||||
import { request } from '$lib/request';
|
||||
import { session } from '$app/stores';
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
import { page, session } from '$app/stores';
|
||||
import { goto } from '$app/navigation';
|
||||
import { browser } from '$app/env';
|
||||
import { request } from '$lib/api/request';
|
||||
import { request } from '$lib/request';
|
||||
|
||||
$application.repository.organization = $page.params.organization;
|
||||
$application.repository.name = $page.params.name;
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script context="module" lang="ts">
|
||||
import { request } from '$lib/api/request';
|
||||
import { request } from '$lib/request';
|
||||
/**
|
||||
* @type {import('@sveltejs/kit').Load}
|
||||
*/
|
||||
|
File diff suppressed because one or more lines are too long
@ -7,6 +7,8 @@
|
||||
import Mysql from '$components/Database/SVGs/Mysql.svelte';
|
||||
import { dashboard } from '$store';
|
||||
import { fade } from 'svelte/transition';
|
||||
import Redis from '$components/Database/SVGs/Redis.svelte';
|
||||
|
||||
</script>
|
||||
|
||||
<div class="py-5 text-left px-6 text-3xl tracking-tight font-bold flex items-center">
|
||||
@ -56,6 +58,10 @@
|
||||
<CouchDb
|
||||
customClass="w-10 h-10 fill-current text-red-600 absolute top-0 left-0 -m-4"
|
||||
/>
|
||||
{:else if database.configuration.general.type == 'redis'}
|
||||
<Redis
|
||||
customClass="w-10 h-10 absolute top-0 left-0 -m-4"
|
||||
/>
|
||||
{:else if database.configuration.general.type == 'clickhouse'}
|
||||
<Clickhouse
|
||||
customClass="w-10 h-10 fill-current text-red-600 absolute top-0 left-0 -m-4"
|
||||
@ -79,4 +85,3 @@
|
||||
<div class="text-2xl font-bold text-center">No databases found</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<script>
|
||||
import { database } from '$store';
|
||||
import { page, session } from '$app/stores';
|
||||
import { request } from '$lib/api/request';
|
||||
import { request } from '$lib/request';
|
||||
import { fade } from 'svelte/transition';
|
||||
import { goto } from '$app/navigation';
|
||||
import MongoDb from '$components/Database/SVGs/MongoDb.svelte';
|
||||
@ -12,10 +12,11 @@
|
||||
import PasswordField from '$components/PasswordField.svelte';
|
||||
import { browser } from '$app/env';
|
||||
import { toast } from '@zerodevx/svelte-toast';
|
||||
import Redis from '$components/Database/SVGs/Redis.svelte';
|
||||
|
||||
async function backup() {
|
||||
try {
|
||||
await request(`/api/v1/databases/${$page.params.name}/backup`, $session, {body: {}});
|
||||
await request(`/api/v1/databases/${$page.params.name}/backup`, $session, { body: {} });
|
||||
|
||||
browser && toast.push(`Successfully created backup.`);
|
||||
} catch (error) {
|
||||
@ -56,6 +57,8 @@
|
||||
<Mysql customClass="w-8 h-8" />
|
||||
{:else if $database.config.general.type === 'couchdb'}
|
||||
<CouchDb customClass="w-8 h-8 fill-current text-red-600" />
|
||||
{:else if $database.config.general.type === 'redis'}
|
||||
<Redis customClass="w-8 h-8" />
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
@ -64,7 +67,9 @@
|
||||
<div class="pb-2 pt-5 space-y-4">
|
||||
<div class="text-2xl font-bold border-gradient w-32">Database</div>
|
||||
<div class="flex items-center pt-4">
|
||||
<div class="font-bold w-64 text-warmGray-400">Connection string</div>
|
||||
{#if $database.config.general.type !== 'redis'}
|
||||
<div class="font-bold w-64 text-warmGray-400">Connection string</div>
|
||||
{/if}
|
||||
{#if $database.config.general.type === 'mongodb'}
|
||||
<PasswordField
|
||||
value={`mongodb://${$database.envs.MONGODB_USERNAME}:${$database.envs.MONGODB_PASSWORD}@${$database.config.general.deployId}:27017/${$database.envs.MONGODB_DATABASE}`}
|
||||
@ -97,6 +102,12 @@
|
||||
<PasswordField value={$database.envs.MONGODB_ROOT_PASSWORD} />
|
||||
</div>
|
||||
{/if}
|
||||
{#if $database.config.general.type === 'redis'}
|
||||
<div class="flex items-center">
|
||||
<div class="font-bold w-64 text-warmGray-400">Redis password</div>
|
||||
<PasswordField value={$database.envs.REDIS_PASSWORD} />
|
||||
</div>
|
||||
{/if}
|
||||
<div class="pb-2 pt-5 space-y-4">
|
||||
<div class="text-2xl font-bold border-gradient w-32">Backup</div>
|
||||
<div class="pt-4">
|
||||
|
@ -4,7 +4,7 @@
|
||||
import { goto } from '$app/navigation';
|
||||
import { page, session } from '$app/stores';
|
||||
import Tooltip from '$components/Tooltip.svelte';
|
||||
import { request } from '$lib/api/request';
|
||||
import { request } from '$lib/request';
|
||||
import { database, initialDatabase } from '$store';
|
||||
import { toast } from '@zerodevx/svelte-toast';
|
||||
import { onDestroy } from 'svelte';
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
import { goto } from '$app/navigation';
|
||||
import { session } from '$app/stores';
|
||||
import { request } from '$lib/api/request';
|
||||
import { request } from '$lib/request';
|
||||
|
||||
async function login() {
|
||||
const left = screen.width / 2 - 1020 / 2;
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
import { page, session } from '$app/stores';
|
||||
import Tooltip from '$components/Tooltip.svelte';
|
||||
import { request } from '$lib/api/request';
|
||||
import { request } from '$lib/request';
|
||||
|
||||
import { toast } from '@zerodevx/svelte-toast';
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
import { toast } from '@zerodevx/svelte-toast';
|
||||
|
||||
import { page, session } from '$app/stores';
|
||||
import { request } from '$lib/api/request';
|
||||
import { request } from '$lib/request';
|
||||
import { goto } from '$app/navigation';
|
||||
import Loading from '$components/Loading.svelte';
|
||||
import Plausible from '$components/Service/Plausible.svelte';
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
import { page, session } from '$app/stores';
|
||||
import Loading from '$components/Loading.svelte';
|
||||
import { request } from '$lib/api/request';
|
||||
import { request } from '$lib/request';
|
||||
import { initialNewService, newService } from '$store';
|
||||
|
||||
import { toast } from '@zerodevx/svelte-toast';
|
||||
|
@ -4,7 +4,7 @@
|
||||
import { toast } from '@zerodevx/svelte-toast';
|
||||
import { newService } from '$store';
|
||||
import { page, session } from '$app/stores';
|
||||
import { request } from '$lib/api/request';
|
||||
import { request } from '$lib/request';
|
||||
import { goto } from '$app/navigation';
|
||||
import Loading from '$components/Loading.svelte';
|
||||
import TooltipInfo from '$components/TooltipInfo.svelte';
|
||||
|
@ -29,7 +29,7 @@
|
||||
import { browser } from '$app/env';
|
||||
import { session } from '$app/stores';
|
||||
|
||||
import { request } from '$lib/api/request';
|
||||
import { request } from '$lib/request';
|
||||
import { toast } from '@zerodevx/svelte-toast';
|
||||
import { fade } from 'svelte/transition';
|
||||
let settings = {
|
||||
|
@ -30,7 +30,7 @@ export default {
|
||||
alias: {
|
||||
$components: path.resolve('./src/components/'),
|
||||
$store: path.resolve('./src/store/index.ts'),
|
||||
$api: path.resolve('./src/routes/api/_index.ts'),
|
||||
$api: path.resolve('./src/routes/api/'),
|
||||
$models: path.resolve('./src/models/')
|
||||
}
|
||||
}
|
||||
|
@ -8,30 +8,6 @@ const svelteClassColonExtractor = (content) => {
|
||||
module.exports = {
|
||||
mode: 'jit',
|
||||
purge: ['./**/*.html', './src/**/*.{js,jsx,ts,tsx,svelte}'],
|
||||
// purge: {
|
||||
// enabled: process.env.NODE_ENV === 'production',
|
||||
// content: ['./src/**/*.svelte', './src/**/*.html', './src/**/*.css', './index.html'],
|
||||
// preserveHtmlElements: true,
|
||||
// options: {
|
||||
// safelist: [
|
||||
// /svelte-/,
|
||||
// 'border-green-500',
|
||||
// 'border-yellow-300',
|
||||
// 'border-red-500',
|
||||
// 'hover:border-green-500',
|
||||
// 'hover:border-red-200',
|
||||
// 'hover:bg-red-200',
|
||||
// 'hover:bg-warmGray-900',
|
||||
// 'hover:bg-transparent'
|
||||
// ],
|
||||
// defaultExtractor: (content) => {
|
||||
// // WARNING: tailwindExtractor is internal tailwind api
|
||||
// // if this breaks after a tailwind update, report to svite repo
|
||||
// return [...tailwindExtractor(content), ...svelteClassColonExtractor(content)];
|
||||
// },
|
||||
// keyframes: false
|
||||
// }
|
||||
// },
|
||||
important: true,
|
||||
theme: {
|
||||
extend: {
|
||||
|
@ -26,7 +26,7 @@
|
||||
"paths": {
|
||||
"$lib/*": ["src/lib/*"],
|
||||
"$store": ["src/store/index.ts"],
|
||||
"$api": ["src/routes/api/_index.ts"],
|
||||
"$api/*": ["src/routes/api/*"],
|
||||
"$models/*": ["src/models/*"],
|
||||
"$components/*": ["src/components/*"]
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user