feat: remote docker engine init
This commit is contained in:
parent
0a8fd0516d
commit
537209d3fb
@ -16,7 +16,7 @@
|
||||
"dependencies": {
|
||||
"@breejs/ts-worker": "2.0.0",
|
||||
"@fastify/autoload": "5.1.0",
|
||||
"@fastify/cookie": "7.1.0",
|
||||
"@fastify/cookie": "7.2.0",
|
||||
"@fastify/cors": "8.0.0",
|
||||
"@fastify/env": "4.0.0",
|
||||
"@fastify/jwt": "6.3.1",
|
||||
@ -43,16 +43,17 @@
|
||||
"node-forge": "1.3.1",
|
||||
"node-os-utils": "1.3.7",
|
||||
"p-queue": "7.2.0",
|
||||
"ssh-config": "4.1.6",
|
||||
"strip-ansi": "7.0.1",
|
||||
"unique-names-generator": "4.7.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "18.0.4",
|
||||
"@types/node": "18.0.6",
|
||||
"@types/node-os-utils": "1.3.0",
|
||||
"@typescript-eslint/eslint-plugin": "5.30.6",
|
||||
"@typescript-eslint/parser": "5.30.6",
|
||||
"esbuild": "0.14.49",
|
||||
"eslint": "8.19.0",
|
||||
"eslint": "8.20.0",
|
||||
"eslint-config-prettier": "8.5.0",
|
||||
"eslint-plugin-prettier": "4.2.1",
|
||||
"nodemon": "2.0.19",
|
||||
|
@ -0,0 +1,21 @@
|
||||
-- RedefineTables
|
||||
PRAGMA foreign_keys=OFF;
|
||||
CREATE TABLE "new_DestinationDocker" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"network" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"engine" TEXT,
|
||||
"remoteEngine" BOOLEAN NOT NULL DEFAULT false,
|
||||
"remoteIpAddress" TEXT,
|
||||
"remoteUser" TEXT,
|
||||
"remotePort" INTEGER,
|
||||
"isCoolifyProxyUsed" BOOLEAN DEFAULT false,
|
||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" DATETIME NOT NULL
|
||||
);
|
||||
INSERT INTO "new_DestinationDocker" ("createdAt", "engine", "id", "isCoolifyProxyUsed", "name", "network", "remoteEngine", "updatedAt") SELECT "createdAt", "engine", "id", "isCoolifyProxyUsed", "name", "network", "remoteEngine", "updatedAt" FROM "DestinationDocker";
|
||||
DROP TABLE "DestinationDocker";
|
||||
ALTER TABLE "new_DestinationDocker" RENAME TO "DestinationDocker";
|
||||
CREATE UNIQUE INDEX "DestinationDocker_network_key" ON "DestinationDocker"("network");
|
||||
PRAGMA foreign_key_check;
|
||||
PRAGMA foreign_keys=ON;
|
@ -0,0 +1,36 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "SshKey" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"name" TEXT NOT NULL,
|
||||
"privateKey" TEXT NOT NULL,
|
||||
"destinationDockerId" TEXT,
|
||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" DATETIME NOT NULL,
|
||||
CONSTRAINT "SshKey_destinationDockerId_fkey" FOREIGN KEY ("destinationDockerId") REFERENCES "DestinationDocker" ("id") ON DELETE SET NULL ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- RedefineTables
|
||||
PRAGMA foreign_keys=OFF;
|
||||
CREATE TABLE "new_DestinationDocker" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"network" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"engine" TEXT,
|
||||
"remoteEngine" BOOLEAN NOT NULL DEFAULT false,
|
||||
"remoteIpAddress" TEXT,
|
||||
"remoteUser" TEXT,
|
||||
"remotePort" INTEGER,
|
||||
"remoteVerified" BOOLEAN NOT NULL DEFAULT false,
|
||||
"isCoolifyProxyUsed" BOOLEAN DEFAULT false,
|
||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" DATETIME NOT NULL
|
||||
);
|
||||
INSERT INTO "new_DestinationDocker" ("createdAt", "engine", "id", "isCoolifyProxyUsed", "name", "network", "remoteEngine", "remoteIpAddress", "remotePort", "remoteUser", "updatedAt") SELECT "createdAt", "engine", "id", "isCoolifyProxyUsed", "name", "network", "remoteEngine", "remoteIpAddress", "remotePort", "remoteUser", "updatedAt" FROM "DestinationDocker";
|
||||
DROP TABLE "DestinationDocker";
|
||||
ALTER TABLE "new_DestinationDocker" RENAME TO "DestinationDocker";
|
||||
CREATE UNIQUE INDEX "DestinationDocker_network_key" ON "DestinationDocker"("network");
|
||||
PRAGMA foreign_key_check;
|
||||
PRAGMA foreign_keys=ON;
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "SshKey_destinationDockerId_key" ON "SshKey"("destinationDockerId");
|
@ -200,8 +200,12 @@ model DestinationDocker {
|
||||
id String @id @default(cuid())
|
||||
network String @unique
|
||||
name String
|
||||
engine String
|
||||
engine String?
|
||||
remoteEngine Boolean @default(false)
|
||||
remoteIpAddress String?
|
||||
remoteUser String?
|
||||
remotePort Int?
|
||||
remoteVerified Boolean @default(false)
|
||||
isCoolifyProxyUsed Boolean? @default(false)
|
||||
teams Team[]
|
||||
application Application[]
|
||||
@ -209,6 +213,17 @@ model DestinationDocker {
|
||||
updatedAt DateTime @updatedAt
|
||||
database Database[]
|
||||
service Service[]
|
||||
sshKey SshKey?
|
||||
}
|
||||
|
||||
model SshKey {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
privateKey String
|
||||
destinationDocker DestinationDocker? @relation(fields: [destinationDockerId], references: [id])
|
||||
destinationDockerId String? @unique
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model GitSource {
|
||||
|
@ -1,6 +1,8 @@
|
||||
import type { FastifyRequest } from 'fastify';
|
||||
import { FastifyReply } from 'fastify';
|
||||
import { asyncExecShell, errorHandler, listSettings, prisma, startCoolifyProxy, startTraefikProxy, stopTraefikProxy } from '../../../../lib/common';
|
||||
import sshConfig from 'ssh-config'
|
||||
import fs from 'fs/promises'
|
||||
import { asyncExecShell, decrypt, errorHandler, listSettings, prisma, startCoolifyProxy, startTraefikProxy, stopTraefikProxy } from '../../../../lib/common';
|
||||
import { checkContainer, dockerInstance, getEngine } from '../../../../lib/docker';
|
||||
|
||||
import type { OnlyId } from '../../../../types';
|
||||
@ -44,7 +46,8 @@ export async function getDestination(request: FastifyRequest<OnlyId>) {
|
||||
const { id } = request.params
|
||||
const teamId = request.user?.teamId;
|
||||
const destination = await prisma.destinationDocker.findFirst({
|
||||
where: { id, teams: { some: { id: teamId === '0' ? undefined : teamId } } }
|
||||
where: { id, teams: { some: { id: teamId === '0' ? undefined : teamId } } },
|
||||
include: { sshKey: true }
|
||||
});
|
||||
if (!destination && id !== 'new') {
|
||||
throw { status: 404, message: `Destination not found.` };
|
||||
@ -80,39 +83,51 @@ export async function getDestination(request: FastifyRequest<OnlyId>) {
|
||||
export async function newDestination(request: FastifyRequest<NewDestination>, reply: FastifyReply) {
|
||||
try {
|
||||
const { id } = request.params
|
||||
let { name, network, engine, isCoolifyProxyUsed } = request.body
|
||||
let { name, network, engine, isCoolifyProxyUsed, ipAddress, user, port, sshPrivateKey } = request.body
|
||||
const teamId = request.user.teamId;
|
||||
if (id === 'new') {
|
||||
const host = getEngine(engine);
|
||||
const docker = dockerInstance({ destinationDocker: { engine, network } });
|
||||
const found = await docker.engine.listNetworks({ filters: { name: [`^${network}$`] } });
|
||||
if (found.length === 0) {
|
||||
await asyncExecShell(`DOCKER_HOST=${host} docker network create --attachable ${network}`);
|
||||
}
|
||||
await prisma.destinationDocker.create({
|
||||
data: { name, teams: { connect: { id: teamId } }, engine, network, isCoolifyProxyUsed }
|
||||
});
|
||||
const destinations = await prisma.destinationDocker.findMany({ where: { engine } });
|
||||
const destination = destinations.find((destination) => destination.network === network);
|
||||
if (engine) {
|
||||
const host = getEngine(engine);
|
||||
const docker = dockerInstance({ destinationDocker: { engine, network } });
|
||||
const found = await docker.engine.listNetworks({ filters: { name: [`^${network}$`] } });
|
||||
if (found.length === 0) {
|
||||
await asyncExecShell(`DOCKER_HOST=${host} docker network create --attachable ${network}`);
|
||||
}
|
||||
await prisma.destinationDocker.create({
|
||||
data: { name, teams: { connect: { id: teamId } }, engine, network, isCoolifyProxyUsed }
|
||||
});
|
||||
const destinations = await prisma.destinationDocker.findMany({ where: { engine } });
|
||||
const destination = destinations.find((destination) => destination.network === network);
|
||||
|
||||
if (destinations.length > 0) {
|
||||
const proxyConfigured = destinations.find(
|
||||
(destination) => destination.network !== network && destination.isCoolifyProxyUsed === true
|
||||
);
|
||||
if (proxyConfigured) {
|
||||
isCoolifyProxyUsed = !!proxyConfigured.isCoolifyProxyUsed;
|
||||
if (destinations.length > 0) {
|
||||
const proxyConfigured = destinations.find(
|
||||
(destination) => destination.network !== network && destination.isCoolifyProxyUsed === true
|
||||
);
|
||||
if (proxyConfigured) {
|
||||
isCoolifyProxyUsed = !!proxyConfigured.isCoolifyProxyUsed;
|
||||
}
|
||||
await prisma.destinationDocker.updateMany({ where: { engine }, data: { isCoolifyProxyUsed } });
|
||||
}
|
||||
await prisma.destinationDocker.updateMany({ where: { engine }, data: { isCoolifyProxyUsed } });
|
||||
}
|
||||
if (isCoolifyProxyUsed) {
|
||||
const settings = await prisma.setting.findFirst();
|
||||
if (settings?.isTraefikUsed) {
|
||||
await startTraefikProxy(engine);
|
||||
} else {
|
||||
await startCoolifyProxy(engine);
|
||||
if (isCoolifyProxyUsed) {
|
||||
const settings = await prisma.setting.findFirst();
|
||||
if (settings?.isTraefikUsed) {
|
||||
await startTraefikProxy(engine);
|
||||
} else {
|
||||
await startCoolifyProxy(engine);
|
||||
}
|
||||
}
|
||||
return reply.code(201).send({ id: destination.id });
|
||||
}
|
||||
return reply.code(201).send({ id: destination.id });
|
||||
if (ipAddress) {
|
||||
await prisma.destinationDocker.create({
|
||||
data: { name, teams: { connect: { id: teamId } }, engine, network, isCoolifyProxyUsed, remoteEngine: true, remoteIpAddress: ipAddress, remoteUser: user, remotePort: port }
|
||||
});
|
||||
return reply.code(201).send()
|
||||
|
||||
}
|
||||
throw {
|
||||
message: `Cannot save Docker Engine.`
|
||||
};
|
||||
} else {
|
||||
await prisma.destinationDocker.update({ where: { id }, data: { name, engine, network } });
|
||||
return reply.code(201).send();
|
||||
@ -120,6 +135,8 @@ export async function newDestination(request: FastifyRequest<NewDestination>, re
|
||||
|
||||
} catch ({ status, message }) {
|
||||
return errorHandler({ status, message })
|
||||
} finally {
|
||||
await fs.rm('./id_rsa')
|
||||
}
|
||||
}
|
||||
export async function deleteDestination(request: FastifyRequest<OnlyId>) {
|
||||
@ -195,3 +212,45 @@ export async function restartProxy(request: FastifyRequest<Proxy>) {
|
||||
return errorHandler({ status, message })
|
||||
}
|
||||
}
|
||||
|
||||
export async function assignSSHKey(request: FastifyRequest) {
|
||||
try {
|
||||
const { id: sshKeyId } = request.body;
|
||||
const { id } = request.params;
|
||||
console.log({ id, sshKeyId })
|
||||
await prisma.destinationDocker.update({ where: { id }, data: { sshKey: { connect: { id: sshKeyId } } } })
|
||||
return {}
|
||||
} catch ({ status, message }) {
|
||||
return errorHandler({ status, message })
|
||||
}
|
||||
}
|
||||
export async function verifyRemoteDockerEngine(request: FastifyRequest, reply: FastifyReply) {
|
||||
try {
|
||||
const { id } = request.params;
|
||||
const { sshKey: { privateKey }, remoteIpAddress, remotePort, remoteUser, network } = await prisma.destinationDocker.findFirst({ where: { id }, include: { sshKey: true } })
|
||||
await fs.writeFile('./id_rsa', decrypt(privateKey) + '\n', { encoding: 'utf8', mode: 400 })
|
||||
const host = `ssh://${remoteUser}@${remoteIpAddress}`
|
||||
const config = sshConfig.parse('')
|
||||
const found = config.find({ Host: remoteIpAddress })
|
||||
if (!found) {
|
||||
config.append({
|
||||
Host: remoteIpAddress,
|
||||
Port: remotePort.toString(),
|
||||
User: remoteUser,
|
||||
IdentityFile: '/workspace/coolify/apps/api/id_rsa',
|
||||
StrictHostKeyChecking: 'no'
|
||||
})
|
||||
}
|
||||
await fs.writeFile('/home/gitpod/.ssh/config', sshConfig.stringify(config))
|
||||
const { stdout } = await asyncExecShell(`DOCKER_HOST=${host} docker network ls --filter 'name=${network}' --no-trunc --format "{{json .}}"`);
|
||||
console.log({ stdout })
|
||||
if (!stdout) {
|
||||
await asyncExecShell(`DOCKER_HOST=${host} docker network create --attachable ${network}`);
|
||||
}
|
||||
await prisma.destinationDocker.update({ where: { id }, data: { remoteVerified: true } })
|
||||
return reply.code(201).send()
|
||||
|
||||
} catch ({ status, message }) {
|
||||
return errorHandler({ status, message })
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { FastifyPluginAsync } from 'fastify';
|
||||
import { checkDestination, deleteDestination, getDestination, listDestinations, newDestination, restartProxy, saveDestinationSettings, startProxy, stopProxy } from './handlers';
|
||||
import { assignSSHKey, checkDestination, deleteDestination, getDestination, listDestinations, newDestination, restartProxy, saveDestinationSettings, startProxy, stopProxy, verifyRemoteDockerEngine } from './handlers';
|
||||
|
||||
import type { OnlyId } from '../../../../types';
|
||||
import type { CheckDestination, NewDestination, Proxy, SaveDestinationSettings } from './types';
|
||||
@ -15,10 +15,14 @@ const root: FastifyPluginAsync = async (fastify): Promise<void> => {
|
||||
fastify.post<NewDestination>('/:id', async (request, reply) => await newDestination(request, reply));
|
||||
fastify.delete<OnlyId>('/:id', async (request) => await deleteDestination(request));
|
||||
|
||||
fastify.post<SaveDestinationSettings>('/:id/settings', async (request, reply) => await saveDestinationSettings(request));
|
||||
fastify.post<Proxy>('/:id/start', async (request, reply) => await startProxy(request));
|
||||
fastify.post<Proxy>('/:id/stop', async (request, reply) => await stopProxy(request));
|
||||
fastify.post<Proxy>('/:id/restart', async (request, reply) => await restartProxy(request));
|
||||
fastify.post<SaveDestinationSettings>('/:id/settings', async (request) => await saveDestinationSettings(request));
|
||||
fastify.post<Proxy>('/:id/start', async (request,) => await startProxy(request));
|
||||
fastify.post<Proxy>('/:id/stop', async (request) => await stopProxy(request));
|
||||
fastify.post<Proxy>('/:id/restart', async (request) => await restartProxy(request));
|
||||
|
||||
fastify.post('/:id/configuration/sshKey', async (request) => await assignSSHKey(request));
|
||||
|
||||
fastify.post('/:id/verify', async (request, reply) => await verifyRemoteDockerEngine(request, reply));
|
||||
};
|
||||
|
||||
export default root;
|
||||
|
@ -1,15 +1,23 @@
|
||||
import { promises as dns } from 'dns';
|
||||
|
||||
import type { FastifyReply, FastifyRequest } from 'fastify';
|
||||
import { checkDomainsIsValidInDNS, errorHandler, getDomain, isDNSValid, isDomainConfigured, listSettings, prisma } from '../../../../lib/common';
|
||||
import { CheckDNS, CheckDomain, DeleteDomain, SaveSettings } from './types';
|
||||
import { checkDomainsIsValidInDNS, decrypt, encrypt, errorHandler, getDomain, isDNSValid, isDomainConfigured, listSettings, prisma } from '../../../../lib/common';
|
||||
import { CheckDNS, CheckDomain, DeleteDomain, DeleteSSHKey, SaveSettings, SaveSSHKey } from './types';
|
||||
|
||||
|
||||
export async function listAllSettings(request: FastifyRequest) {
|
||||
try {
|
||||
const settings = await listSettings();
|
||||
const sshKeys = await prisma.sshKey.findMany()
|
||||
const unencryptedKeys = []
|
||||
if (sshKeys.length > 0) {
|
||||
for (const key of sshKeys) {
|
||||
unencryptedKeys.push({ id: key.id, name: key.name, privateKey: decrypt(key.privateKey), createdAt: key.createdAt })
|
||||
}
|
||||
}
|
||||
return {
|
||||
settings
|
||||
settings,
|
||||
sshKeys: unencryptedKeys
|
||||
}
|
||||
} catch ({ status, message }) {
|
||||
return errorHandler({ status, message })
|
||||
@ -83,4 +91,30 @@ export async function checkDNS(request: FastifyRequest<CheckDNS>) {
|
||||
} catch ({ status, message }) {
|
||||
return errorHandler({ status, message })
|
||||
}
|
||||
}
|
||||
|
||||
export async function saveSSHKey(request: FastifyRequest<SaveSSHKey>, reply: FastifyReply) {
|
||||
try {
|
||||
const { privateKey, name } = request.body;
|
||||
const found = await prisma.sshKey.findMany({ where: { name } })
|
||||
if (found.length > 0) {
|
||||
throw {
|
||||
message: "Name already used. Choose another one please."
|
||||
}
|
||||
}
|
||||
const encryptedSSHKey = encrypt(privateKey)
|
||||
await prisma.sshKey.create({ data: { name, privateKey: encryptedSSHKey } })
|
||||
return reply.code(201).send()
|
||||
} catch ({ status, message }) {
|
||||
return errorHandler({ status, message })
|
||||
}
|
||||
}
|
||||
export async function deleteSSHKey(request: FastifyRequest<DeleteSSHKey>, reply: FastifyReply) {
|
||||
try {
|
||||
const { id } = request.body;
|
||||
await prisma.sshKey.delete({ where: { id } })
|
||||
return reply.code(201).send()
|
||||
} catch ({ status, message }) {
|
||||
return errorHandler({ status, message })
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
import { FastifyPluginAsync } from 'fastify';
|
||||
import { checkDNS, checkDomain, deleteDomain, listAllSettings, saveSettings } from './handlers';
|
||||
import { CheckDNS, CheckDomain, DeleteDomain, SaveSettings } from './types';
|
||||
import { checkDNS, checkDomain, deleteDomain, deleteSSHKey, listAllSettings, saveSettings, saveSSHKey } from './handlers';
|
||||
import { CheckDNS, CheckDomain, DeleteDomain, DeleteSSHKey, SaveSettings, SaveSSHKey } from './types';
|
||||
|
||||
|
||||
const root: FastifyPluginAsync = async (fastify): Promise<void> => {
|
||||
@ -13,6 +13,9 @@ const root: FastifyPluginAsync = async (fastify): Promise<void> => {
|
||||
|
||||
fastify.get<CheckDNS>('/check', async (request) => await checkDNS(request));
|
||||
fastify.post<CheckDomain>('/check', async (request) => await checkDomain(request));
|
||||
|
||||
fastify.post<SaveSSHKey>('/sshKey', async (request, reply) => await saveSSHKey(request, reply));
|
||||
fastify.delete<DeleteSSHKey>('/sshKey', async (request, reply) => await deleteSSHKey(request, reply));
|
||||
};
|
||||
|
||||
export default root;
|
||||
|
@ -28,4 +28,15 @@ export interface CheckDNS {
|
||||
Params: {
|
||||
domain: string,
|
||||
}
|
||||
}
|
||||
export interface SaveSSHKey {
|
||||
Body: {
|
||||
privateKey: string,
|
||||
name: string
|
||||
}
|
||||
}
|
||||
export interface DeleteSSHKey {
|
||||
Body: {
|
||||
id: string
|
||||
}
|
||||
}
|
@ -15,13 +15,13 @@
|
||||
"format": "prettier --write --plugin-search-dir=. ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "1.23.3",
|
||||
"@sveltejs/kit": "1.0.0-next.375",
|
||||
"@playwright/test": "1.23.4",
|
||||
"@sveltejs/kit": "1.0.0-next.377",
|
||||
"@types/js-cookie": "3.0.2",
|
||||
"@typescript-eslint/eslint-plugin": "5.30.6",
|
||||
"@typescript-eslint/parser": "5.30.6",
|
||||
"autoprefixer": "10.4.7",
|
||||
"eslint": "8.19.0",
|
||||
"eslint": "8.20.0",
|
||||
"eslint-config-prettier": "8.5.0",
|
||||
"eslint-plugin-svelte3": "4.0.0",
|
||||
"postcss": "8.4.14",
|
||||
@ -34,11 +34,11 @@
|
||||
"tailwindcss-scrollbar": "0.1.0",
|
||||
"tslib": "2.4.0",
|
||||
"typescript": "4.7.4",
|
||||
"vite": "^3.0.0"
|
||||
"vite": "3.0.1"
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@sveltejs/adapter-static": "1.0.0-next.36",
|
||||
"@sveltejs/adapter-static": "1.0.0-next.37",
|
||||
"@zerodevx/svelte-toast": "0.7.2",
|
||||
"cuid": "2.1.8",
|
||||
"js-cookie": "3.0.1",
|
||||
|
@ -142,9 +142,6 @@
|
||||
: $t('destination.force_restart_proxy')}</button
|
||||
>
|
||||
{/if}
|
||||
<!-- <button type="button" class="bg-coollabs hover:bg-coollabs-100" on:click={scanApps}
|
||||
>Scan for applications</button
|
||||
> -->
|
||||
</div>
|
||||
<div class="grid grid-cols-2 items-center px-10 ">
|
||||
<label for="name" class="text-base font-bold text-stone-100">{$t('forms.name')}</label>
|
||||
@ -168,10 +165,6 @@
|
||||
value={destination.engine}
|
||||
/>
|
||||
</div>
|
||||
<!-- <div class="flex items-center">
|
||||
<label for="remoteEngine">Remote Engine?</label>
|
||||
<input name="remoteEngine" type="checkbox" bind:checked={payload.remoteEngine} />
|
||||
</div> -->
|
||||
<div class="grid grid-cols-2 items-center px-10">
|
||||
<label for="network" class="text-base font-bold text-stone-100">{$t('forms.network')}</label>
|
||||
<CopyPasswordField
|
||||
|
@ -44,7 +44,7 @@
|
||||
<button class="w-32" on:click={() => setPredefined('localDocker')}
|
||||
>{$t('sources.local_docker')}</button
|
||||
>
|
||||
<!-- <button class="w-32" on:click={() => setPredefined('remoteDocker')}>Remote Docker</button> -->
|
||||
<button class="w-32" on:click={() => setPredefined('remoteDocker')}>Remote Docker</button>
|
||||
<!-- <button class="w-32" on:click={() => setPredefined('kubernetes')}>Kubernetes</button> -->
|
||||
</div>
|
||||
</div>
|
||||
|
@ -11,13 +11,19 @@
|
||||
let loading = false;
|
||||
|
||||
async function handleSubmit() {
|
||||
if (loading) return;
|
||||
try {
|
||||
const { id } = await post('/new/destination/docker', {
|
||||
loading = true;
|
||||
await post(`/destinations/check`, { network: payload.network });
|
||||
const { id } = await post(`/destinations/new`, {
|
||||
...payload
|
||||
});
|
||||
return await goto(`/destinations/${id}`);
|
||||
await goto(`/destinations/${id}`);
|
||||
window.location.reload();
|
||||
} catch (error) {
|
||||
return errorNotification(error);
|
||||
} finally {
|
||||
loading = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -64,20 +70,6 @@
|
||||
<label for="port" class="text-base font-bold text-stone-100">{$t('forms.port')}</label>
|
||||
<input required name="port" placeholder="{$t('forms.eg')}: 22" bind:value={payload.port} />
|
||||
</div>
|
||||
<div class="grid grid-cols-2 items-center px-10">
|
||||
<label for="sshPrivateKey" class="text-base font-bold text-stone-100"
|
||||
>{$t('forms.ssh_private_key')}</label
|
||||
>
|
||||
<textarea
|
||||
rows="10"
|
||||
class="resize-none"
|
||||
required
|
||||
name="sshPrivateKey"
|
||||
placeholder="{$t('forms.eg')}: -----BEGIN...."
|
||||
bind:value={payload.sshPrivateKey}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-2 items-center px-10">
|
||||
<label for="network" class="text-base font-bold text-stone-100">{$t('forms.network')}</label>
|
||||
<input
|
||||
|
@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
export let destination: any;
|
||||
export let settings: any
|
||||
export let state: any
|
||||
export let settings: any;
|
||||
export let state: any;
|
||||
|
||||
import { toast } from '@zerodevx/svelte-toast';
|
||||
import { page, session } from '$app/stores';
|
||||
@ -10,50 +10,45 @@
|
||||
import CopyPasswordField from '$lib/components/CopyPasswordField.svelte';
|
||||
import { onMount } from 'svelte';
|
||||
import { t } from '$lib/translations';
|
||||
import { errorNotification, generateRemoteEngine } from '$lib/common';
|
||||
import { appSession } from '$lib/store';
|
||||
import { errorNotification, generateRemoteEngine } from '$lib/common';
|
||||
import { appSession } from '$lib/store';
|
||||
const { id } = $page.params;
|
||||
let cannotDisable = settings.fqdn && destination.engine === '/var/run/docker.sock';
|
||||
// let scannedApps = [];
|
||||
let loading = false;
|
||||
let restarting = false;
|
||||
$: isDisabled = !$appSession.isAdmin;
|
||||
|
||||
async function handleSubmit() {
|
||||
loading = true;
|
||||
try {
|
||||
return await post(`/destinations/${id}.json`, { ...destination });
|
||||
} catch (error ) {
|
||||
return await post(`/destinations/${id}`, { ...destination });
|
||||
} catch (error) {
|
||||
return errorNotification(error);
|
||||
} finally {
|
||||
loading = false;
|
||||
}
|
||||
}
|
||||
// async function scanApps() {
|
||||
// scannedApps = [];
|
||||
// const data = await fetch(`/destinations/${id}/scan.json`);
|
||||
// const { containers } = await data.json();
|
||||
// scannedApps = containers;
|
||||
// }
|
||||
onMount(async () => {
|
||||
if (state === false && destination.isCoolifyProxyUsed === true) {
|
||||
destination.isCoolifyProxyUsed = !destination.isCoolifyProxyUsed;
|
||||
try {
|
||||
await post(`/destinations/${id}/settings.json`, {
|
||||
await post(`/destinations/${id}/settings`, {
|
||||
isCoolifyProxyUsed: destination.isCoolifyProxyUsed,
|
||||
engine: destination.engine
|
||||
});
|
||||
await stopProxy();
|
||||
} catch (error ) {
|
||||
} catch (error) {
|
||||
return errorNotification(error);
|
||||
}
|
||||
} else if (state === true && destination.isCoolifyProxyUsed === false) {
|
||||
destination.isCoolifyProxyUsed = !destination.isCoolifyProxyUsed;
|
||||
try {
|
||||
await post(`/destinations/${id}/settings.json`, {
|
||||
await post(`/destinations/${id}/settings`, {
|
||||
isCoolifyProxyUsed: destination.isCoolifyProxyUsed,
|
||||
engine: destination.engine
|
||||
});
|
||||
await startProxy();
|
||||
} catch ( error ) {
|
||||
} catch (error) {
|
||||
return errorNotification(error);
|
||||
}
|
||||
}
|
||||
@ -73,7 +68,7 @@ import { appSession } from '$lib/store';
|
||||
}
|
||||
destination.isCoolifyProxyUsed = !destination.isCoolifyProxyUsed;
|
||||
try {
|
||||
await post(`/destinations/${id}/settings.json`, {
|
||||
await post(`/destinations/${id}/settings`, {
|
||||
isCoolifyProxyUsed: destination.isCoolifyProxyUsed,
|
||||
engine: destination.engine
|
||||
});
|
||||
@ -89,8 +84,7 @@ import { appSession } from '$lib/store';
|
||||
}
|
||||
async function stopProxy() {
|
||||
try {
|
||||
const engine = generateRemoteEngine(destination);
|
||||
await post(`/destinations/${id}/stop.json`, { engine });
|
||||
await post(`/destinations/${id}/stop`, { engine: destination.engine });
|
||||
return toast.push($t('destination.coolify_proxy_stopped'));
|
||||
} catch (error) {
|
||||
return errorNotification(error);
|
||||
@ -98,8 +92,7 @@ import { appSession } from '$lib/store';
|
||||
}
|
||||
async function startProxy() {
|
||||
try {
|
||||
const engine = generateRemoteEngine(destination);
|
||||
await post(`/destinations/${id}/start.json`, { engine });
|
||||
await post(`/destinations/${id}/start`, { engine: destination.engine });
|
||||
return toast.push($t('destination.coolify_proxy_started'));
|
||||
} catch (error) {
|
||||
return errorNotification(error);
|
||||
@ -111,7 +104,7 @@ import { appSession } from '$lib/store';
|
||||
try {
|
||||
restarting = true;
|
||||
toast.push($t('destination.coolify_proxy_restarting'));
|
||||
await post(`/destinations/${id}/restart.json`, {
|
||||
await post(`/destinations/${id}/restart`, {
|
||||
engine: destination.engine,
|
||||
fqdn: settings.fqdn
|
||||
});
|
||||
@ -119,9 +112,21 @@ import { appSession } from '$lib/store';
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 5000);
|
||||
} finally {
|
||||
restarting = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
async function verifyRemoteDocker() {
|
||||
try {
|
||||
loading = true;
|
||||
return await post(`/destinations/${id}/verify`, {});
|
||||
} catch (error) {
|
||||
return errorNotification(error);
|
||||
} finally {
|
||||
loading = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<form on:submit|preventDefault={handleSubmit} class="grid grid-flow-row gap-2 py-4">
|
||||
@ -136,6 +141,11 @@ import { appSession } from '$lib/store';
|
||||
disabled={loading}
|
||||
>{loading ? $t('forms.saving') : $t('forms.save')}
|
||||
</button>
|
||||
{#if !destination.remoteVerified}
|
||||
<button on:click|preventDefault|stopPropagation={verifyRemoteDocker}
|
||||
>Verify Remote Docker Engine</button
|
||||
>
|
||||
{/if}
|
||||
<button
|
||||
class={restarting ? '' : 'bg-red-600 hover:bg-red-500'}
|
||||
disabled={restarting}
|
||||
@ -145,9 +155,6 @@ import { appSession } from '$lib/store';
|
||||
: $t('destination.force_restart_proxy')}</button
|
||||
>
|
||||
{/if}
|
||||
<!-- <button type="button" class="bg-coollabs hover:bg-coollabs-100" on:click={scanApps}
|
||||
>Scan for applications</button
|
||||
> -->
|
||||
</div>
|
||||
<div class="grid grid-cols-2 items-center px-10 ">
|
||||
<label for="name" class="text-base font-bold text-stone-100">{$t('forms.name')}</label>
|
||||
@ -159,22 +166,6 @@ import { appSession } from '$lib/store';
|
||||
bind:value={destination.name}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-2 items-center px-10">
|
||||
<label for="engine" class="text-base font-bold text-stone-100">{$t('forms.engine')}</label>
|
||||
<CopyPasswordField
|
||||
id="engine"
|
||||
readonly
|
||||
disabled
|
||||
name="engine"
|
||||
placeholder="{$t('forms.eg')}: /var/run/docker.sock"
|
||||
value={destination.engine}
|
||||
/>
|
||||
</div>
|
||||
<!-- <div class="flex items-center">
|
||||
<label for="remoteEngine">Remote Engine?</label>
|
||||
<input name="remoteEngine" type="checkbox" bind:checked={payload.remoteEngine} />
|
||||
</div> -->
|
||||
<div class="grid grid-cols-2 items-center px-10">
|
||||
<label for="network" class="text-base font-bold text-stone-100">{$t('forms.network')}</label>
|
||||
<CopyPasswordField
|
||||
@ -186,6 +177,49 @@ import { appSession } from '$lib/store';
|
||||
value={destination.network}
|
||||
/>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 items-center px-10">
|
||||
<label for="remoteIpAddress" class="text-base font-bold text-stone-100">IP Address</label>
|
||||
<CopyPasswordField
|
||||
id="remoteIpAddress"
|
||||
readonly
|
||||
disabled
|
||||
name="remoteIpAddress"
|
||||
value={destination.remoteIpAddress}
|
||||
/>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 items-center px-10">
|
||||
<label for="remoteUser" class="text-base font-bold text-stone-100">User</label>
|
||||
<CopyPasswordField
|
||||
id="remoteUser"
|
||||
readonly
|
||||
disabled
|
||||
name="remoteUser"
|
||||
value={destination.remoteUser}
|
||||
/>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 items-center px-10">
|
||||
<label for="remotePort" class="text-base font-bold text-stone-100">Port</label>
|
||||
<CopyPasswordField
|
||||
id="remotePort"
|
||||
readonly
|
||||
disabled
|
||||
name="remotePort"
|
||||
value={destination.remotePort}
|
||||
/>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 items-center px-10">
|
||||
<label for="sshKey" class="text-base font-bold text-stone-100">SSH Key</label>
|
||||
<a
|
||||
href={!isDisabled ? `/destinations/${id}/configuration/sshkey?from=/destinations/${id}` : ''}
|
||||
class="no-underline"
|
||||
><input
|
||||
value={destination.sshKey.name}
|
||||
id="sshKey"
|
||||
disabled
|
||||
class="cursor-pointer hover:bg-coolgray-500"
|
||||
/></a
|
||||
>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 items-center">
|
||||
<Setting
|
||||
disabled={cannotDisable}
|
||||
@ -200,27 +234,3 @@ import { appSession } from '$lib/store';
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
<!-- <div class="flex justify-center">
|
||||
{#if payload.isCoolifyProxyUsed}
|
||||
{#if state}
|
||||
<button on:click={stopProxy}>Stop proxy</button>
|
||||
{:else}
|
||||
<button on:click={startProxy}>Start proxy</button>
|
||||
{/if}
|
||||
{/if}
|
||||
</div> -->
|
||||
|
||||
<!-- {#if scannedApps.length > 0}
|
||||
<div class="flex justify-center px-6 pb-10">
|
||||
<div class="flex space-x-2 h-8 items-center">
|
||||
<div class="font-bold text-xl text-white">Found applications</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="max-w-4xl mx-auto px-6">
|
||||
<div class="flex space-x-2 justify-center">
|
||||
{#each scannedApps as app}
|
||||
<FoundApp {app} />
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
{/if} -->
|
||||
|
@ -1,6 +1,14 @@
|
||||
<script context="module" lang="ts">
|
||||
import type { Load } from '@sveltejs/kit';
|
||||
export const load: Load = async ({ fetch, url, params }) => {
|
||||
function checkConfiguration(destination: any): string | null {
|
||||
let configurationPhase = null;
|
||||
if (!destination?.remoteEngine) return configurationPhase;
|
||||
if (!destination?.sshKey) {
|
||||
configurationPhase = 'sshkey';
|
||||
}
|
||||
return configurationPhase;
|
||||
}
|
||||
export const load: Load = async ({ url, params }) => {
|
||||
try {
|
||||
const { id } = params;
|
||||
const response = await get(`/destinations/${id}`);
|
||||
@ -11,6 +19,17 @@
|
||||
redirect: '/destinations'
|
||||
};
|
||||
}
|
||||
const configurationPhase = checkConfiguration(destination);
|
||||
if (
|
||||
configurationPhase &&
|
||||
url.pathname !== `/destinations/${params.id}/configuration/${configurationPhase}`
|
||||
) {
|
||||
return {
|
||||
status: 302,
|
||||
redirect: `/destinations/${params.id}/configuration/${configurationPhase}`
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
props: {
|
||||
destination
|
||||
@ -22,6 +41,7 @@
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
return handlerNotFoundLoad(error, url);
|
||||
}
|
||||
};
|
||||
|
@ -0,0 +1,59 @@
|
||||
<script context="module" lang="ts">
|
||||
import type { Load } from '@sveltejs/kit';
|
||||
export const load: Load = async ({ fetch, params, url, stuff }) => {
|
||||
try {
|
||||
const response = await get(`/settings`);
|
||||
return {
|
||||
props: {
|
||||
...response
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
status: 500,
|
||||
error: new Error(`Could not load ${url}`)
|
||||
};
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { goto } from '$app/navigation';
|
||||
import { get, post } from '$lib/api';
|
||||
import { errorNotification } from '$lib/common';
|
||||
|
||||
const { id } = $page.params;
|
||||
const from = $page.url.searchParams.get('from');
|
||||
|
||||
export let sshKeys: any;
|
||||
|
||||
async function handleSubmit(sshKeyId: string) {
|
||||
try {
|
||||
await post(`/destinations/${id}/configuration/sshKey`, { id: sshKeyId });
|
||||
return await goto(from || `/destinations/${id}`);
|
||||
} catch (error) {
|
||||
return errorNotification(error);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="flex space-x-1 p-6 font-bold">
|
||||
<div class="mr-4 text-2xl tracking-tight">SSH Keys</div>
|
||||
</div>
|
||||
<div class="flex flex-col justify-center">
|
||||
<div class="flex flex-col flex-wrap justify-center px-2 md:flex-row ">
|
||||
{#each sshKeys as sshKey}
|
||||
<div class="p-2 relative">
|
||||
<form on:submit|preventDefault={() => handleSubmit(sshKey.id)}>
|
||||
<button
|
||||
type="submit"
|
||||
class="disabled:opacity-95 bg-coolgray-200 disabled:text-white box-selection hover:bg-orange-700 group"
|
||||
>
|
||||
<div class="font-bold text-xl text-center truncate">{sshKey.name}</div>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
@ -73,6 +73,9 @@
|
||||
<div class="truncate text-center">{destination.teams[0].name}</div>
|
||||
{/if}
|
||||
<div class="truncate text-center">{destination.network}</div>
|
||||
{#if $appSession.teamId === '0' && destination.remoteVerified === false && destination.remoteEngine}
|
||||
<div class="truncate text-center text-sm text-red-500">Not verified yet</div>
|
||||
{/if}
|
||||
</div>
|
||||
</a>
|
||||
{/each}
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
export let settings: any;
|
||||
|
||||
export let sshKeys: any;
|
||||
import Setting from '$lib/components/Setting.svelte';
|
||||
import Explainer from '$lib/components/Explainer.svelte';
|
||||
import { del, get, post } from '$lib/api';
|
||||
@ -51,13 +51,20 @@
|
||||
proxyMigration: false
|
||||
};
|
||||
|
||||
let subMenuActive: any = 'globalsettings';
|
||||
let isModalActive = false;
|
||||
|
||||
let newSSHKey = {
|
||||
name: null,
|
||||
privateKey: null
|
||||
};
|
||||
async function removeFqdn() {
|
||||
if (fqdn) {
|
||||
loading.remove = true;
|
||||
try {
|
||||
const { redirect } = await del(`/settings`, { fqdn });
|
||||
return redirect ? window.location.replace(redirect) : window.location.reload();
|
||||
} catch (error ) {
|
||||
} catch (error) {
|
||||
return errorNotification(error);
|
||||
} finally {
|
||||
loading.remove = false;
|
||||
@ -107,7 +114,7 @@
|
||||
settings.maxPort = maxPort;
|
||||
}
|
||||
forceSave = false;
|
||||
} catch (error ) {
|
||||
} catch (error) {
|
||||
if (error.message?.startsWith($t('application.dns_not_set_partial_error'))) {
|
||||
forceSave = true;
|
||||
if (dualCerts) {
|
||||
@ -122,7 +129,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log(error)
|
||||
console.log(error);
|
||||
return errorNotification(error);
|
||||
} finally {
|
||||
loading.save = false;
|
||||
@ -143,18 +150,23 @@
|
||||
function resetView() {
|
||||
forceSave = false;
|
||||
}
|
||||
async function migrateProxy(to: any) {
|
||||
if (loading.proxyMigration) return;
|
||||
async function saveSSHKey() {
|
||||
try {
|
||||
loading.proxyMigration = true;
|
||||
await post(`/update`, { type: to });
|
||||
const data = await get(`/settings`);
|
||||
$isTraefikUsed = data.settings.isTraefikUsed;
|
||||
return toast.push('Proxy migration started, it takes a few seconds.');
|
||||
await post(`/settings/sshKey`, { ...newSSHKey });
|
||||
return window.location.reload();
|
||||
} catch (error) {
|
||||
return errorNotification(error);
|
||||
} finally {
|
||||
loading.proxyMigration = false;
|
||||
errorNotification(error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
async function deleteSSHKey(id: string) {
|
||||
try {
|
||||
if (!id) return
|
||||
await del(`/settings/sshKey`, { id });
|
||||
return window.location.reload();
|
||||
} catch (error) {
|
||||
errorNotification(error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -162,196 +174,303 @@
|
||||
<div class="flex space-x-1 p-6 font-bold">
|
||||
<div class="mr-4 text-2xl tracking-tight">{$t('index.settings')}</div>
|
||||
</div>
|
||||
{#if $appSession.teamId === '0'}
|
||||
<div class="mx-auto max-w-4xl px-6">
|
||||
<form on:submit|preventDefault={handleSubmit} class="grid grid-flow-row gap-2 py-4">
|
||||
<div class="flex space-x-1 pb-6">
|
||||
<div class="title font-bold">{$t('index.global_settings')}</div>
|
||||
<button
|
||||
type="submit"
|
||||
class:bg-green-600={!loading.save}
|
||||
class:bg-orange-600={forceSave}
|
||||
class:hover:bg-green-500={!loading.save}
|
||||
class:hover:bg-orange-400={forceSave}
|
||||
disabled={loading.save}
|
||||
>{loading.save
|
||||
? $t('forms.saving')
|
||||
: forceSave
|
||||
? $t('forms.confirm_continue')
|
||||
: $t('forms.save')}</button
|
||||
>
|
||||
|
||||
{#if isFqdnSet}
|
||||
<button
|
||||
on:click|preventDefault={removeFqdn}
|
||||
disabled={loading.remove}
|
||||
class:bg-red-600={!loading.remove}
|
||||
class:hover:bg-red-500={!loading.remove}
|
||||
>{loading.remove ? $t('forms.removing') : $t('forms.remove_domain')}</button
|
||||
>
|
||||
{/if}
|
||||
<div class="mx-auto w-full">
|
||||
<div class="flex flex-row">
|
||||
<div class="flex flex-col pt-4 space-y-6 w-96 px-20">
|
||||
<div
|
||||
class="sub-menu"
|
||||
class:sub-menu-active={subMenuActive === 'globalsettings'}
|
||||
on:click={() => (subMenuActive = 'globalsettings')}
|
||||
>
|
||||
Global Settings
|
||||
</div>
|
||||
<div class="grid grid-flow-row gap-2 px-10">
|
||||
<!-- <Language /> -->
|
||||
<div class="grid grid-cols-2 items-start">
|
||||
<div class="flex-col">
|
||||
<div class="pt-2 text-base font-bold text-stone-100">
|
||||
{$t('application.url_fqdn')}
|
||||
</div>
|
||||
<Explainer text={$t('setting.ssl_explainer')} />
|
||||
</div>
|
||||
<div class="justify-start text-left">
|
||||
<input
|
||||
bind:value={fqdn}
|
||||
readonly={!$appSession.isAdmin || isFqdnSet}
|
||||
disabled={!$appSession.isAdmin || isFqdnSet}
|
||||
on:input={resetView}
|
||||
name="fqdn"
|
||||
id="fqdn"
|
||||
pattern="^https?://([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{'{'}2,{'}'}$"
|
||||
placeholder="{$t('forms.eg')}: https://coolify.io"
|
||||
/>
|
||||
<div
|
||||
class="sub-menu"
|
||||
class:sub-menu-active={subMenuActive === 'sshkey'}
|
||||
on:click={() => (subMenuActive = 'sshkey')}
|
||||
>
|
||||
SSH Keys
|
||||
</div>
|
||||
</div>
|
||||
<div class="pl-40">
|
||||
{#if $appSession.teamId === '0'}
|
||||
{#if subMenuActive === 'globalsettings'}
|
||||
<form on:submit|preventDefault={handleSubmit} class="grid grid-flow-row gap-2 py-4">
|
||||
<div class="flex space-x-1 pb-6">
|
||||
<div class="title font-bold">{$t('index.global_settings')}</div>
|
||||
<button
|
||||
type="submit"
|
||||
class:bg-yellow-500={!loading.save}
|
||||
class:bg-orange-600={forceSave}
|
||||
class:hover:bg-yellow-500={!loading.save}
|
||||
class:hover:bg-orange-400={forceSave}
|
||||
disabled={loading.save}
|
||||
>{loading.save
|
||||
? $t('forms.saving')
|
||||
: forceSave
|
||||
? $t('forms.confirm_continue')
|
||||
: $t('forms.save')}</button
|
||||
>
|
||||
|
||||
{#if forceSave}
|
||||
<div class="flex-col space-y-2 pt-4 text-center">
|
||||
{#if isNonWWWDomainOK}
|
||||
<button
|
||||
class="bg-green-600 hover:bg-green-500"
|
||||
on:click|preventDefault={() => isDNSValid(getDomain(nonWWWDomain), false)}
|
||||
>DNS settings for {nonWWWDomain} is OK, click to recheck.</button
|
||||
>
|
||||
{:else}
|
||||
<button
|
||||
class="bg-red-600 hover:bg-red-500"
|
||||
on:click|preventDefault={() => isDNSValid(getDomain(nonWWWDomain), false)}
|
||||
>DNS settings for {nonWWWDomain} is invalid, click to recheck.</button
|
||||
>
|
||||
{/if}
|
||||
{#if dualCerts}
|
||||
{#if isWWWDomainOK}
|
||||
<button
|
||||
class="bg-green-600 hover:bg-green-500"
|
||||
on:click|preventDefault={() =>
|
||||
isDNSValid(getDomain(`www.${nonWWWDomain}`), true)}
|
||||
>DNS settings for www.{nonWWWDomain} is OK, click to recheck.</button
|
||||
>
|
||||
{:else}
|
||||
<button
|
||||
class="bg-red-600 hover:bg-red-500"
|
||||
on:click|preventDefault={() =>
|
||||
isDNSValid(getDomain(`www.${nonWWWDomain}`), true)}
|
||||
>DNS settings for www.{nonWWWDomain} is invalid, click to recheck.</button
|
||||
>
|
||||
{#if isFqdnSet}
|
||||
<button
|
||||
on:click|preventDefault={removeFqdn}
|
||||
disabled={loading.remove}
|
||||
class:bg-red-600={!loading.remove}
|
||||
class:hover:bg-red-500={!loading.remove}
|
||||
>{loading.remove ? $t('forms.removing') : $t('forms.remove_domain')}</button
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="grid grid-flow-row gap-2 px-10">
|
||||
<!-- <Language /> -->
|
||||
<div class="grid grid-cols-2 items-start">
|
||||
<div class="flex-col">
|
||||
<div class="pt-2 text-base font-bold text-stone-100">
|
||||
{$t('application.url_fqdn')}
|
||||
</div>
|
||||
<Explainer text={$t('setting.ssl_explainer')} />
|
||||
</div>
|
||||
<div class="justify-start text-left">
|
||||
<input
|
||||
bind:value={fqdn}
|
||||
readonly={!$appSession.isAdmin || isFqdnSet}
|
||||
disabled={!$appSession.isAdmin || isFqdnSet}
|
||||
on:input={resetView}
|
||||
name="fqdn"
|
||||
id="fqdn"
|
||||
pattern="^https?://([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{'{'}2,{'}'}$"
|
||||
placeholder="{$t('forms.eg')}: https://coolify.io"
|
||||
/>
|
||||
|
||||
{#if forceSave}
|
||||
<div class="flex-col space-y-2 pt-4 text-center">
|
||||
{#if isNonWWWDomainOK}
|
||||
<button
|
||||
class="bg-green-600 hover:bg-green-500"
|
||||
on:click|preventDefault={() => isDNSValid(getDomain(nonWWWDomain), false)}
|
||||
>DNS settings for {nonWWWDomain} is OK, click to recheck.</button
|
||||
>
|
||||
{:else}
|
||||
<button
|
||||
class="bg-red-600 hover:bg-red-500"
|
||||
on:click|preventDefault={() => isDNSValid(getDomain(nonWWWDomain), false)}
|
||||
>DNS settings for {nonWWWDomain} is invalid, click to recheck.</button
|
||||
>
|
||||
{/if}
|
||||
{#if dualCerts}
|
||||
{#if isWWWDomainOK}
|
||||
<button
|
||||
class="bg-green-600 hover:bg-green-500"
|
||||
on:click|preventDefault={() =>
|
||||
isDNSValid(getDomain(`www.${nonWWWDomain}`), true)}
|
||||
>DNS settings for www.{nonWWWDomain} is OK, click to recheck.</button
|
||||
>
|
||||
{:else}
|
||||
<button
|
||||
class="bg-red-600 hover:bg-red-500"
|
||||
on:click|preventDefault={() =>
|
||||
isDNSValid(getDomain(`www.${nonWWWDomain}`), true)}
|
||||
>DNS settings for www.{nonWWWDomain} is invalid, click to recheck.</button
|
||||
>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 items-start py-6">
|
||||
<div class="flex-col">
|
||||
<div class="pt-2 text-base font-bold text-stone-100">
|
||||
{$t('forms.public_port_range')}
|
||||
<div class="grid grid-cols-2 items-start py-6">
|
||||
<div class="flex-col">
|
||||
<div class="pt-2 text-base font-bold text-stone-100">
|
||||
{$t('forms.public_port_range')}
|
||||
</div>
|
||||
<Explainer text={$t('forms.public_port_range_explainer')} />
|
||||
</div>
|
||||
<div class="mx-auto flex-row items-center justify-center space-y-2">
|
||||
<input
|
||||
class="h-8 w-20 px-2"
|
||||
type="number"
|
||||
bind:value={minPort}
|
||||
min="1024"
|
||||
max={maxPort}
|
||||
/>
|
||||
-
|
||||
<input
|
||||
class="h-8 w-20 px-2"
|
||||
type="number"
|
||||
bind:value={maxPort}
|
||||
min={minPort}
|
||||
max="65543"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 items-center">
|
||||
<Setting
|
||||
bind:setting={isDNSCheckEnabled}
|
||||
title={$t('setting.is_dns_check_enabled')}
|
||||
description={$t('setting.is_dns_check_enabled_explainer')}
|
||||
on:click={() => changeSettings('isDNSCheckEnabled')}
|
||||
/>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 items-center">
|
||||
<Setting
|
||||
dataTooltip={$t('setting.must_remove_domain_before_changing')}
|
||||
disabled={isFqdnSet}
|
||||
bind:setting={dualCerts}
|
||||
title={$t('application.ssl_www_and_non_www')}
|
||||
description={$t('setting.generate_www_non_www_ssl')}
|
||||
on:click={() => !isFqdnSet && changeSettings('dualCerts')}
|
||||
/>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 items-center">
|
||||
<Setting
|
||||
bind:setting={isRegistrationEnabled}
|
||||
title={$t('setting.registration_allowed')}
|
||||
description={$t('setting.registration_allowed_explainer')}
|
||||
on:click={() => changeSettings('isRegistrationEnabled')}
|
||||
/>
|
||||
</div>
|
||||
{#if browser && $features.beta}
|
||||
<div class="grid grid-cols-2 items-center">
|
||||
<Setting
|
||||
bind:setting={isAutoUpdateEnabled}
|
||||
title={$t('setting.auto_update_enabled')}
|
||||
description={$t('setting.auto_update_enabled_explainer')}
|
||||
on:click={() => changeSettings('isAutoUpdateEnabled')}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<Explainer text={$t('forms.public_port_range_explainer')} />
|
||||
</div>
|
||||
<div class="mx-auto flex-row items-center justify-center space-y-2">
|
||||
<input
|
||||
class="h-8 w-20 px-2"
|
||||
type="number"
|
||||
bind:value={minPort}
|
||||
min="1024"
|
||||
max={maxPort}
|
||||
/>
|
||||
-
|
||||
<input
|
||||
class="h-8 w-20 px-2"
|
||||
type="number"
|
||||
bind:value={maxPort}
|
||||
min={minPort}
|
||||
max="65543"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 items-center">
|
||||
<Setting
|
||||
bind:setting={isDNSCheckEnabled}
|
||||
title={$t('setting.is_dns_check_enabled')}
|
||||
description={$t('setting.is_dns_check_enabled_explainer')}
|
||||
on:click={() => changeSettings('isDNSCheckEnabled')}
|
||||
/>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 items-center">
|
||||
<Setting
|
||||
dataTooltip={$t('setting.must_remove_domain_before_changing')}
|
||||
disabled={isFqdnSet}
|
||||
bind:setting={dualCerts}
|
||||
title={$t('application.ssl_www_and_non_www')}
|
||||
description={$t('setting.generate_www_non_www_ssl')}
|
||||
on:click={() => !isFqdnSet && changeSettings('dualCerts')}
|
||||
/>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 items-center">
|
||||
<Setting
|
||||
bind:setting={isRegistrationEnabled}
|
||||
title={$t('setting.registration_allowed')}
|
||||
description={$t('setting.registration_allowed_explainer')}
|
||||
on:click={() => changeSettings('isRegistrationEnabled')}
|
||||
/>
|
||||
</div>
|
||||
{#if browser && $features.beta}
|
||||
<div class="grid grid-cols-2 items-center">
|
||||
<Setting
|
||||
bind:setting={isAutoUpdateEnabled}
|
||||
title={$t('setting.auto_update_enabled')}
|
||||
description={$t('setting.auto_update_enabled_explainer')}
|
||||
on:click={() => changeSettings('isAutoUpdateEnabled')}
|
||||
</form>
|
||||
{#if !settings.isTraefikUsed}
|
||||
<div class="flex space-x-1 pt-6 font-bold">
|
||||
<div class="title">{$t('setting.coolify_proxy_settings')}</div>
|
||||
</div>
|
||||
<Explainer
|
||||
text={$t('setting.credential_stat_explainer', {
|
||||
link: fqdn
|
||||
? `http://${settings.proxyUser}:${settings.proxyPassword}@` +
|
||||
getDomain(fqdn) +
|
||||
':8404'
|
||||
: browser &&
|
||||
`http://${settings.proxyUser}:${settings.proxyPassword}@` +
|
||||
window.location.hostname +
|
||||
':8404'
|
||||
})}
|
||||
/>
|
||||
<div class="space-y-2 px-10 py-5">
|
||||
<div class="grid grid-cols-2 items-center">
|
||||
<label for="proxyUser">{$t('forms.user')}</label>
|
||||
<CopyPasswordField
|
||||
readonly
|
||||
disabled
|
||||
id="proxyUser"
|
||||
name="proxyUser"
|
||||
value={settings.proxyUser}
|
||||
/>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 items-center">
|
||||
<label for="proxyPassword">{$t('forms.password')}</label>
|
||||
<CopyPasswordField
|
||||
readonly
|
||||
disabled
|
||||
id="proxyPassword"
|
||||
name="proxyPassword"
|
||||
isPasswordField
|
||||
value={settings.proxyPassword}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
{#if subMenuActive === 'sshkey'}
|
||||
<div class="grid grid-flow-row gap-2 py-4">
|
||||
<div class="flex space-x-1 pb-6">
|
||||
<div class="title font-bold">SSH Keys</div>
|
||||
<button
|
||||
on:click={() => (isModalActive = true)}
|
||||
class:bg-yellow-500={!loading.save}
|
||||
class:hover:bg-yellow-400={!loading.save}
|
||||
disabled={loading.save}>New SSH Key</button
|
||||
>
|
||||
</div>
|
||||
<div class="grid grid-flow-col gap-2 px-10">
|
||||
{#if sshKeys.length === 0}
|
||||
<div class="text-sm ">No SSH keys found</div>
|
||||
{:else}
|
||||
{#each sshKeys as key}
|
||||
<div class="box-selection group relative">
|
||||
<div class="text-xl font-bold">{key.name}</div>
|
||||
<div class="py-3 text-stone-600">Added on {key.createdAt}</div>
|
||||
<button on:click={() => deleteSSHKey(key.id)} class="bg-red-500">Delete</button>
|
||||
</div>
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</form>
|
||||
{#if !settings.isTraefikUsed}
|
||||
<div class="flex space-x-1 pt-6 font-bold">
|
||||
<div class="title">{$t('setting.coolify_proxy_settings')}</div>
|
||||
{/if}
|
||||
</div>
|
||||
<Explainer
|
||||
text={$t('setting.credential_stat_explainer', {
|
||||
link: fqdn
|
||||
? `http://${settings.proxyUser}:${settings.proxyPassword}@` + getDomain(fqdn) + ':8404'
|
||||
: browser &&
|
||||
`http://${settings.proxyUser}:${settings.proxyPassword}@` +
|
||||
window.location.hostname +
|
||||
':8404'
|
||||
})}
|
||||
/>
|
||||
<div class="space-y-2 px-10 py-5">
|
||||
<div class="grid grid-cols-2 items-center">
|
||||
<label for="proxyUser">{$t('forms.user')}</label>
|
||||
<CopyPasswordField
|
||||
readonly
|
||||
disabled
|
||||
id="proxyUser"
|
||||
name="proxyUser"
|
||||
value={settings.proxyUser}
|
||||
/>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 items-center">
|
||||
<label for="proxyPassword">{$t('forms.password')}</label>
|
||||
<CopyPasswordField
|
||||
readonly
|
||||
disabled
|
||||
id="proxyPassword"
|
||||
name="proxyPassword"
|
||||
isPasswordField
|
||||
value={settings.proxyPassword}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{:else}
|
||||
<div class="mx-auto max-w-4xl px-6">
|
||||
<!-- <Language /> -->
|
||||
</div>
|
||||
|
||||
{#if isModalActive}
|
||||
<div class="relative z-10" aria-labelledby="modal-title" role="dialog" aria-modal="true">
|
||||
<div class="fixed inset-0 bg-coolgray-500 bg-opacity-75 transition-opacity" />
|
||||
|
||||
<div class="fixed z-10 inset-0 overflow-y-auto text-white">
|
||||
<div class="flex items-end sm:items-center justify-center min-h-full p-4 text-center sm:p-0">
|
||||
<div
|
||||
class="relative bg-coolblack rounded-lg px-4 pt-5 pb-4 text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:max-w-lg sm:w-full sm:p-6 border border-coolgray-500"
|
||||
>
|
||||
<div class="hidden sm:block absolute top-0 right-0 pt-4 pr-4">
|
||||
<button
|
||||
on:click={() => (isModalActive = false)}
|
||||
type="button"
|
||||
class=" rounded-md text-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
|
||||
>
|
||||
<span class="sr-only">Close</span>
|
||||
<svg
|
||||
class="h-6 w-6"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="2"
|
||||
stroke="currentColor"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="sm:flex sm:items-start">
|
||||
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
||||
<h3 class="text-lg leading-6 font-medium pb-4" id="modal-title">New SSH Key</h3>
|
||||
<div class="text-xs text-stone-400">Add an SSH key to your Coolify instance.</div>
|
||||
<div class="mt-2">
|
||||
<label for="privateKey" class="pb-2">Key</label>
|
||||
<textarea
|
||||
id="privateKey"
|
||||
required
|
||||
bind:value={newSSHKey.privateKey}
|
||||
class="w-full"
|
||||
rows={15}
|
||||
/>
|
||||
</div>
|
||||
<div class="mt-2">
|
||||
<label for="name" class="pb-2">Name</label>
|
||||
<input id="name" required bind:value={newSSHKey.name} class="w-full" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-5 flex space-x-4 justify-end">
|
||||
<button on:click={saveSSHKey} type="button" class="bg-green-600 hover:bg-green-500"
|
||||
>Save</button
|
||||
>
|
||||
<button on:click={() => (isModalActive = false)} type="button" class="">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
@ -395,3 +395,11 @@ a {
|
||||
transform: scale(0.9);
|
||||
}
|
||||
}
|
||||
|
||||
.sub-menu {
|
||||
@apply text-xl font-bold hover:bg-coolgray-500 rounded p-2 hover:text-white text-stone-200 cursor-pointer;
|
||||
}
|
||||
|
||||
.sub-menu-active {
|
||||
@apply bg-coolgray-500 text-white;
|
||||
}
|
182
pnpm-lock.yaml
generated
182
pnpm-lock.yaml
generated
@ -14,14 +14,14 @@ importers:
|
||||
specifiers:
|
||||
'@breejs/ts-worker': 2.0.0
|
||||
'@fastify/autoload': 5.1.0
|
||||
'@fastify/cookie': 7.1.0
|
||||
'@fastify/cookie': 7.2.0
|
||||
'@fastify/cors': 8.0.0
|
||||
'@fastify/env': 4.0.0
|
||||
'@fastify/jwt': 6.3.1
|
||||
'@fastify/static': 6.4.0
|
||||
'@iarna/toml': 2.2.5
|
||||
'@prisma/client': 3.15.2
|
||||
'@types/node': 18.0.4
|
||||
'@types/node': 18.0.6
|
||||
'@types/node-os-utils': 1.3.0
|
||||
'@typescript-eslint/eslint-plugin': 5.30.6
|
||||
'@typescript-eslint/parser': 5.30.6
|
||||
@ -35,7 +35,7 @@ importers:
|
||||
dockerode: 3.3.2
|
||||
dotenv-extended: 2.9.0
|
||||
esbuild: 0.14.49
|
||||
eslint: 8.19.0
|
||||
eslint: 8.20.0
|
||||
eslint-config-prettier: 8.5.0
|
||||
eslint-plugin-prettier: 4.2.1
|
||||
fastify: 4.2.1
|
||||
@ -53,15 +53,15 @@ importers:
|
||||
prettier: 2.7.1
|
||||
prisma: 3.15.2
|
||||
rimraf: 3.0.2
|
||||
shared: workspace:*
|
||||
ssh-config: ^4.1.6
|
||||
strip-ansi: 7.0.1
|
||||
tsconfig-paths: 4.0.0
|
||||
typescript: 4.7.4
|
||||
unique-names-generator: 4.7.1
|
||||
dependencies:
|
||||
'@breejs/ts-worker': 2.0.0_t3dw2jfpvj5qtbx4qztd4nt754
|
||||
'@breejs/ts-worker': 2.0.0_25g7irgsr6ywin2g3nrhhgteo4
|
||||
'@fastify/autoload': 5.1.0
|
||||
'@fastify/cookie': 7.1.0
|
||||
'@fastify/cookie': 7.2.0
|
||||
'@fastify/cors': 8.0.0
|
||||
'@fastify/env': 4.0.0
|
||||
'@fastify/jwt': 6.3.1
|
||||
@ -88,18 +88,18 @@ importers:
|
||||
node-forge: 1.3.1
|
||||
node-os-utils: 1.3.7
|
||||
p-queue: 7.2.0
|
||||
shared: link:../shared
|
||||
ssh-config: 4.1.6
|
||||
strip-ansi: 7.0.1
|
||||
unique-names-generator: 4.7.1
|
||||
devDependencies:
|
||||
'@types/node': 18.0.4
|
||||
'@types/node': 18.0.6
|
||||
'@types/node-os-utils': 1.3.0
|
||||
'@typescript-eslint/eslint-plugin': 5.30.6_2vt5mtrqleafs33qg2bhpmbaqm
|
||||
'@typescript-eslint/parser': 5.30.6_4x5o4skxv6sl53vpwefgt23khm
|
||||
'@typescript-eslint/eslint-plugin': 5.30.6_b7n364ggt6o4xlkgyoaww3ph3q
|
||||
'@typescript-eslint/parser': 5.30.6_he2ccbldppg44uulnyq4rwocfa
|
||||
esbuild: 0.14.49
|
||||
eslint: 8.19.0
|
||||
eslint-config-prettier: 8.5.0_eslint@8.19.0
|
||||
eslint-plugin-prettier: 4.2.1_7uxdfn2xinezdgvmbammh6ev5i
|
||||
eslint: 8.20.0
|
||||
eslint-config-prettier: 8.5.0_eslint@8.20.0
|
||||
eslint-plugin-prettier: 4.2.1_g4fztgbwjyq2fvmcscny2sj6fy
|
||||
nodemon: 2.0.19
|
||||
prettier: 2.7.1
|
||||
prisma: 3.15.2
|
||||
@ -107,28 +107,18 @@ importers:
|
||||
tsconfig-paths: 4.0.0
|
||||
typescript: 4.7.4
|
||||
|
||||
apps/shared:
|
||||
specifiers:
|
||||
esbuild: 0.14.49
|
||||
nodemon: 2.0.19
|
||||
rimraf: 3.0.2
|
||||
devDependencies:
|
||||
esbuild: 0.14.49
|
||||
nodemon: 2.0.19
|
||||
rimraf: 3.0.2
|
||||
|
||||
apps/ui:
|
||||
specifiers:
|
||||
'@playwright/test': 1.23.3
|
||||
'@sveltejs/adapter-static': 1.0.0-next.36
|
||||
'@sveltejs/kit': 1.0.0-next.375
|
||||
'@playwright/test': 1.23.4
|
||||
'@sveltejs/adapter-static': 1.0.0-next.37
|
||||
'@sveltejs/kit': 1.0.0-next.377
|
||||
'@types/js-cookie': 3.0.2
|
||||
'@typescript-eslint/eslint-plugin': 5.30.6
|
||||
'@typescript-eslint/parser': 5.30.6
|
||||
'@zerodevx/svelte-toast': 0.7.2
|
||||
autoprefixer: 10.4.7
|
||||
cuid: 2.1.8
|
||||
eslint: 8.19.0
|
||||
eslint: 8.20.0
|
||||
eslint-config-prettier: 8.5.0
|
||||
eslint-plugin-svelte3: 4.0.0
|
||||
js-cookie: 3.0.1
|
||||
@ -136,7 +126,6 @@ importers:
|
||||
postcss: 8.4.14
|
||||
prettier: 2.7.1
|
||||
prettier-plugin-svelte: 2.7.0
|
||||
shared: workspace:*
|
||||
svelte: 3.49.0
|
||||
svelte-check: 2.8.0
|
||||
svelte-preprocess: 4.10.7
|
||||
@ -146,26 +135,25 @@ importers:
|
||||
tailwindcss-scrollbar: 0.1.0
|
||||
tslib: 2.4.0
|
||||
typescript: 4.7.4
|
||||
vite: ^3.0.0
|
||||
vite: 3.0.1
|
||||
dependencies:
|
||||
'@sveltejs/adapter-static': 1.0.0-next.36
|
||||
'@sveltejs/adapter-static': 1.0.0-next.37
|
||||
'@zerodevx/svelte-toast': 0.7.2
|
||||
cuid: 2.1.8
|
||||
js-cookie: 3.0.1
|
||||
p-limit: 4.0.0
|
||||
shared: link:../shared
|
||||
svelte-select: 4.4.7
|
||||
sveltekit-i18n: 2.2.2_svelte@3.49.0
|
||||
devDependencies:
|
||||
'@playwright/test': 1.23.3
|
||||
'@sveltejs/kit': 1.0.0-next.375_svelte@3.49.0+vite@3.0.0
|
||||
'@playwright/test': 1.23.4
|
||||
'@sveltejs/kit': 1.0.0-next.377_svelte@3.49.0+vite@3.0.1
|
||||
'@types/js-cookie': 3.0.2
|
||||
'@typescript-eslint/eslint-plugin': 5.30.6_2vt5mtrqleafs33qg2bhpmbaqm
|
||||
'@typescript-eslint/parser': 5.30.6_4x5o4skxv6sl53vpwefgt23khm
|
||||
'@typescript-eslint/eslint-plugin': 5.30.6_b7n364ggt6o4xlkgyoaww3ph3q
|
||||
'@typescript-eslint/parser': 5.30.6_he2ccbldppg44uulnyq4rwocfa
|
||||
autoprefixer: 10.4.7_postcss@8.4.14
|
||||
eslint: 8.19.0
|
||||
eslint-config-prettier: 8.5.0_eslint@8.19.0
|
||||
eslint-plugin-svelte3: 4.0.0_jxmmfmurkts274jdspwh3cyqve
|
||||
eslint: 8.20.0
|
||||
eslint-config-prettier: 8.5.0_eslint@8.20.0
|
||||
eslint-plugin-svelte3: 4.0.0_piwa6j2njmnknm35bh3wz5v52y
|
||||
postcss: 8.4.14
|
||||
prettier: 2.7.1
|
||||
prettier-plugin-svelte: 2.7.0_o3ioganyptcsrh6x4hnxvjkpqi
|
||||
@ -176,7 +164,7 @@ importers:
|
||||
tailwindcss-scrollbar: 0.1.0_tailwindcss@3.1.6
|
||||
tslib: 2.4.0
|
||||
typescript: 4.7.4
|
||||
vite: 3.0.0
|
||||
vite: 3.0.1
|
||||
|
||||
packages:
|
||||
|
||||
@ -213,14 +201,14 @@ packages:
|
||||
engines: {node: '>= 10'}
|
||||
dev: false
|
||||
|
||||
/@breejs/ts-worker/2.0.0_t3dw2jfpvj5qtbx4qztd4nt754:
|
||||
/@breejs/ts-worker/2.0.0_25g7irgsr6ywin2g3nrhhgteo4:
|
||||
resolution: {integrity: sha512-6anHRcmgYlF7mrm/YVRn6rx2cegLuiY3VBxkkimOTWC/dVQeH336imVSuIKEGKTwiuNTPr2hswVdDSneNuXg3A==}
|
||||
engines: {node: '>= 12.11'}
|
||||
peerDependencies:
|
||||
bree: '>=9.0.0'
|
||||
dependencies:
|
||||
bree: 9.1.1
|
||||
ts-node: 10.8.2_2zqz24ol5yhbv2blv4fh7akzrq
|
||||
ts-node: 10.8.2_tdn3ypgnfy6bmey2q4hu5jonwi
|
||||
tsconfig-paths: 4.0.0
|
||||
transitivePeerDependencies:
|
||||
- '@swc/core'
|
||||
@ -267,8 +255,8 @@ packages:
|
||||
pkg-up: 3.1.0
|
||||
dev: false
|
||||
|
||||
/@fastify/cookie/7.1.0:
|
||||
resolution: {integrity: sha512-ofAlIthvJ2aWOrzdbUen1Lx09AKk2zvdaUrWh2+0aNt+gajRA7KyR8bzwCD2AwS+2nacjEuSRIyckotMHG95hQ==}
|
||||
/@fastify/cookie/7.2.0:
|
||||
resolution: {integrity: sha512-eM/OoTPEW/83uTEWVVZhVVQCtwRx3vmMs7J68U1DFNf42Ar4nTTZ7qGNYXvJPLUQqGKYS/gxML2soNMmZD8z0Q==}
|
||||
dependencies:
|
||||
cookie: 0.5.0
|
||||
cookie-signature: 1.2.0
|
||||
@ -385,13 +373,13 @@ packages:
|
||||
fastq: 1.13.0
|
||||
dev: true
|
||||
|
||||
/@playwright/test/1.23.3:
|
||||
resolution: {integrity: sha512-kR4vo2UGHC84DGqE6EwvAeaehj3xCAK6LoC1P1eu6ZGdC79rlqRKf8cFDx6q6c9T8MQSL1O9eOlup0BpwqNF0w==}
|
||||
/@playwright/test/1.23.4:
|
||||
resolution: {integrity: sha512-iIsoMJDS/lyuhw82FtcV/B3PXikgVD3hNe5hyvOpRM0uRr1OIpN3LgPeRbBjhzBWmyf6RgRg5fqK5sVcpA03yA==}
|
||||
engines: {node: '>=14'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
'@types/node': 18.0.3
|
||||
playwright-core: 1.23.3
|
||||
'@types/node': 18.0.4
|
||||
playwright-core: 1.23.4
|
||||
dev: true
|
||||
|
||||
/@prisma/client/3.15.2_prisma@3.15.2:
|
||||
@ -429,31 +417,31 @@ packages:
|
||||
engines: {node: '>=10'}
|
||||
dev: false
|
||||
|
||||
/@sveltejs/adapter-static/1.0.0-next.36:
|
||||
resolution: {integrity: sha512-1g3W4wHPyBtUGy5zCDBA2nMG3mM36FKTP1zb0vNRBpoUmtNuzVFF74UVsHCpMC1GpPyrgOq9idfjkm4gRabisw==}
|
||||
/@sveltejs/adapter-static/1.0.0-next.37:
|
||||
resolution: {integrity: sha512-BDFkx4CGAd6pG4e3+zYjy/eM9UDbhkRgXqavUzCO5oT8xXao5TeprY1AIbdzjMTmFjsWdeSXE9TbIsT0iikpyQ==}
|
||||
dependencies:
|
||||
tiny-glob: 0.2.9
|
||||
dev: false
|
||||
|
||||
/@sveltejs/kit/1.0.0-next.375_svelte@3.49.0+vite@3.0.0:
|
||||
resolution: {integrity: sha512-9+gKm97TW/xIz6DfWOqdsIwGY4yckUkmMFlsJmEGkjcTy60Q6ZCfrQhMULzL/fILLydF0wZcD/fWE/urAbp2nw==}
|
||||
/@sveltejs/kit/1.0.0-next.377_svelte@3.49.0+vite@3.0.1:
|
||||
resolution: {integrity: sha512-DH2v2yUBUuDZ7vzjPXUd/yt1AMR3BIkZN0ubLAvS2C+q5Wbvk7ZvAJhfPZ3OYc3ZpQXe4ZGEcptOjvEYvd1lLA==}
|
||||
engines: {node: '>=16.9'}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
svelte: ^3.44.0
|
||||
vite: ^3.0.0
|
||||
dependencies:
|
||||
'@sveltejs/vite-plugin-svelte': 1.0.1_svelte@3.49.0+vite@3.0.0
|
||||
'@sveltejs/vite-plugin-svelte': 1.0.1_svelte@3.49.0+vite@3.0.1
|
||||
chokidar: 3.5.3
|
||||
sade: 1.8.1
|
||||
svelte: 3.49.0
|
||||
vite: 3.0.0
|
||||
vite: 3.0.1
|
||||
transitivePeerDependencies:
|
||||
- diff-match-patch
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@sveltejs/vite-plugin-svelte/1.0.1_svelte@3.49.0+vite@3.0.0:
|
||||
/@sveltejs/vite-plugin-svelte/1.0.1_svelte@3.49.0+vite@3.0.1:
|
||||
resolution: {integrity: sha512-PorCgUounn0VXcpeJu+hOweZODKmGuLHsLomwqSj+p26IwjjGffmYQfVHtiTWq+NqaUuuHWWG7vPge6UFw4Aeg==}
|
||||
engines: {node: ^14.18.0 || >= 16}
|
||||
peerDependencies:
|
||||
@ -471,7 +459,7 @@ packages:
|
||||
magic-string: 0.26.2
|
||||
svelte: 3.49.0
|
||||
svelte-hmr: 0.14.12_svelte@3.49.0
|
||||
vite: 3.0.0
|
||||
vite: 3.0.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
@ -518,7 +506,7 @@ packages:
|
||||
dependencies:
|
||||
'@types/http-cache-semantics': 4.0.1
|
||||
'@types/keyv': 3.1.4
|
||||
'@types/node': 18.0.4
|
||||
'@types/node': 18.0.6
|
||||
'@types/responselike': 1.0.0
|
||||
dev: false
|
||||
|
||||
@ -541,7 +529,7 @@ packages:
|
||||
/@types/keyv/3.1.4:
|
||||
resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==}
|
||||
dependencies:
|
||||
'@types/node': 18.0.4
|
||||
'@types/node': 18.0.6
|
||||
dev: false
|
||||
|
||||
/@types/lodash/4.14.182:
|
||||
@ -552,12 +540,12 @@ packages:
|
||||
resolution: {integrity: sha512-XwVteWQx/XkfRPyaGkw8dEbrCAkoRZ73pI3XznUYIpzbCfpQB3UnDlR5TnmdhetlT889tUJGF8QWo9xrgTpsiA==}
|
||||
dev: true
|
||||
|
||||
/@types/node/18.0.3:
|
||||
resolution: {integrity: sha512-HzNRZtp4eepNitP+BD6k2L6DROIDG4Q0fm4x+dwfsr6LGmROENnok75VGw40628xf+iR24WeMFcHuuBDUAzzsQ==}
|
||||
dev: true
|
||||
|
||||
/@types/node/18.0.4:
|
||||
resolution: {integrity: sha512-M0+G6V0Y4YV8cqzHssZpaNCqvYwlCiulmm0PwpNLF55r/+cT8Ol42CHRU1SEaYFH2rTwiiE1aYg/2g2rrtGdPA==}
|
||||
dev: true
|
||||
|
||||
/@types/node/18.0.6:
|
||||
resolution: {integrity: sha512-/xUq6H2aQm261exT6iZTMifUySEt4GR5KX8eYyY+C4MSNPqSh9oNIP7tz2GLKTlFaiBbgZNxffoR3CVRG+cljw==}
|
||||
|
||||
/@types/normalize-package-data/2.4.1:
|
||||
resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==}
|
||||
@ -570,16 +558,16 @@ packages:
|
||||
/@types/responselike/1.0.0:
|
||||
resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==}
|
||||
dependencies:
|
||||
'@types/node': 18.0.4
|
||||
'@types/node': 18.0.6
|
||||
dev: false
|
||||
|
||||
/@types/sass/1.43.1:
|
||||
resolution: {integrity: sha512-BPdoIt1lfJ6B7rw35ncdwBZrAssjcwzI5LByIrYs+tpXlj/CAkuVdRsgZDdP4lq5EjyWzwxZCqAoFyHKFwp32g==}
|
||||
dependencies:
|
||||
'@types/node': 18.0.3
|
||||
'@types/node': 18.0.4
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/eslint-plugin/5.30.6_2vt5mtrqleafs33qg2bhpmbaqm:
|
||||
/@typescript-eslint/eslint-plugin/5.30.6_b7n364ggt6o4xlkgyoaww3ph3q:
|
||||
resolution: {integrity: sha512-J4zYMIhgrx4MgnZrSDD7sEnQp7FmhKNOaqaOpaoQ/SfdMfRB/0yvK74hTnvH+VQxndZynqs5/Hn4t+2/j9bADg==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
@ -590,12 +578,12 @@ packages:
|
||||
typescript:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/parser': 5.30.6_4x5o4skxv6sl53vpwefgt23khm
|
||||
'@typescript-eslint/parser': 5.30.6_he2ccbldppg44uulnyq4rwocfa
|
||||
'@typescript-eslint/scope-manager': 5.30.6
|
||||
'@typescript-eslint/type-utils': 5.30.6_4x5o4skxv6sl53vpwefgt23khm
|
||||
'@typescript-eslint/utils': 5.30.6_4x5o4skxv6sl53vpwefgt23khm
|
||||
'@typescript-eslint/type-utils': 5.30.6_he2ccbldppg44uulnyq4rwocfa
|
||||
'@typescript-eslint/utils': 5.30.6_he2ccbldppg44uulnyq4rwocfa
|
||||
debug: 4.3.4
|
||||
eslint: 8.19.0
|
||||
eslint: 8.20.0
|
||||
functional-red-black-tree: 1.0.1
|
||||
ignore: 5.2.0
|
||||
regexpp: 3.2.0
|
||||
@ -606,7 +594,7 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/parser/5.30.6_4x5o4skxv6sl53vpwefgt23khm:
|
||||
/@typescript-eslint/parser/5.30.6_he2ccbldppg44uulnyq4rwocfa:
|
||||
resolution: {integrity: sha512-gfF9lZjT0p2ZSdxO70Xbw8w9sPPJGfAdjK7WikEjB3fcUI/yr9maUVEdqigBjKincUYNKOmf7QBMiTf719kbrA==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
@ -620,7 +608,7 @@ packages:
|
||||
'@typescript-eslint/types': 5.30.6
|
||||
'@typescript-eslint/typescript-estree': 5.30.6_typescript@4.7.4
|
||||
debug: 4.3.4
|
||||
eslint: 8.19.0
|
||||
eslint: 8.20.0
|
||||
typescript: 4.7.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@ -634,7 +622,7 @@ packages:
|
||||
'@typescript-eslint/visitor-keys': 5.30.6
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/type-utils/5.30.6_4x5o4skxv6sl53vpwefgt23khm:
|
||||
/@typescript-eslint/type-utils/5.30.6_he2ccbldppg44uulnyq4rwocfa:
|
||||
resolution: {integrity: sha512-GFVVzs2j0QPpM+NTDMXtNmJKlF842lkZKDSanIxf+ArJsGeZUIaeT4jGg+gAgHt7AcQSFwW7htzF/rbAh2jaVA==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
@ -644,9 +632,9 @@ packages:
|
||||
typescript:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/utils': 5.30.6_4x5o4skxv6sl53vpwefgt23khm
|
||||
'@typescript-eslint/utils': 5.30.6_he2ccbldppg44uulnyq4rwocfa
|
||||
debug: 4.3.4
|
||||
eslint: 8.19.0
|
||||
eslint: 8.20.0
|
||||
tsutils: 3.21.0_typescript@4.7.4
|
||||
typescript: 4.7.4
|
||||
transitivePeerDependencies:
|
||||
@ -679,7 +667,7 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/utils/5.30.6_4x5o4skxv6sl53vpwefgt23khm:
|
||||
/@typescript-eslint/utils/5.30.6_he2ccbldppg44uulnyq4rwocfa:
|
||||
resolution: {integrity: sha512-xFBLc/esUbLOJLk9jKv0E9gD/OH966M40aY9jJ8GiqpSkP2xOV908cokJqqhVd85WoIvHVHYXxSFE4cCSDzVvA==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
@ -689,9 +677,9 @@ packages:
|
||||
'@typescript-eslint/scope-manager': 5.30.6
|
||||
'@typescript-eslint/types': 5.30.6
|
||||
'@typescript-eslint/typescript-estree': 5.30.6_typescript@4.7.4
|
||||
eslint: 8.19.0
|
||||
eslint: 8.20.0
|
||||
eslint-scope: 5.1.1
|
||||
eslint-utils: 3.0.0_eslint@8.19.0
|
||||
eslint-utils: 3.0.0_eslint@8.20.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
- typescript
|
||||
@ -2531,16 +2519,16 @@ packages:
|
||||
engines: {node: '>=10'}
|
||||
dev: true
|
||||
|
||||
/eslint-config-prettier/8.5.0_eslint@8.19.0:
|
||||
/eslint-config-prettier/8.5.0_eslint@8.20.0:
|
||||
resolution: {integrity: sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
eslint: '>=7.0.0'
|
||||
dependencies:
|
||||
eslint: 8.19.0
|
||||
eslint: 8.20.0
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-prettier/4.2.1_7uxdfn2xinezdgvmbammh6ev5i:
|
||||
/eslint-plugin-prettier/4.2.1_g4fztgbwjyq2fvmcscny2sj6fy:
|
||||
resolution: {integrity: sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
peerDependencies:
|
||||
@ -2551,19 +2539,19 @@ packages:
|
||||
eslint-config-prettier:
|
||||
optional: true
|
||||
dependencies:
|
||||
eslint: 8.19.0
|
||||
eslint-config-prettier: 8.5.0_eslint@8.19.0
|
||||
eslint: 8.20.0
|
||||
eslint-config-prettier: 8.5.0_eslint@8.20.0
|
||||
prettier: 2.7.1
|
||||
prettier-linter-helpers: 1.0.0
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-svelte3/4.0.0_jxmmfmurkts274jdspwh3cyqve:
|
||||
/eslint-plugin-svelte3/4.0.0_piwa6j2njmnknm35bh3wz5v52y:
|
||||
resolution: {integrity: sha512-OIx9lgaNzD02+MDFNLw0GEUbuovNcglg+wnd/UY0fbZmlQSz7GlQiQ1f+yX0XvC07XPcDOnFcichqI3xCwp71g==}
|
||||
peerDependencies:
|
||||
eslint: '>=8.0.0'
|
||||
svelte: ^3.2.0
|
||||
dependencies:
|
||||
eslint: 8.19.0
|
||||
eslint: 8.20.0
|
||||
svelte: 3.49.0
|
||||
dev: true
|
||||
|
||||
@ -2583,13 +2571,13 @@ packages:
|
||||
estraverse: 5.3.0
|
||||
dev: true
|
||||
|
||||
/eslint-utils/3.0.0_eslint@8.19.0:
|
||||
/eslint-utils/3.0.0_eslint@8.20.0:
|
||||
resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==}
|
||||
engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0}
|
||||
peerDependencies:
|
||||
eslint: '>=5'
|
||||
dependencies:
|
||||
eslint: 8.19.0
|
||||
eslint: 8.20.0
|
||||
eslint-visitor-keys: 2.1.0
|
||||
dev: true
|
||||
|
||||
@ -2603,8 +2591,8 @@ packages:
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
dev: true
|
||||
|
||||
/eslint/8.19.0:
|
||||
resolution: {integrity: sha512-SXOPj3x9VKvPe81TjjUJCYlV4oJjQw68Uek+AM0X4p+33dj2HY5bpTZOgnQHcG2eAm1mtCU9uNMnJi7exU/kYw==}
|
||||
/eslint/8.20.0:
|
||||
resolution: {integrity: sha512-d4ixhz5SKCa1D6SCPrivP7yYVi7nyD6A4vs6HIAul9ujBzcEmZVM3/0NN/yu5nKhmO1wjp5xQ46iRfmDGlOviA==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
@ -2617,7 +2605,7 @@ packages:
|
||||
doctrine: 3.0.0
|
||||
escape-string-regexp: 4.0.0
|
||||
eslint-scope: 7.1.1
|
||||
eslint-utils: 3.0.0_eslint@8.19.0
|
||||
eslint-utils: 3.0.0_eslint@8.20.0
|
||||
eslint-visitor-keys: 3.3.0
|
||||
espree: 9.3.2
|
||||
esquery: 1.4.0
|
||||
@ -4259,8 +4247,8 @@ packages:
|
||||
find-up: 3.0.0
|
||||
dev: false
|
||||
|
||||
/playwright-core/1.23.3:
|
||||
resolution: {integrity: sha512-x35yzsXDyo0BIXYimLnUFNyb42c//NadUNH6IPGOteZm96oTGA1kn4Hq6qJTI1/f9wEc1F9O1DsznXIgXMil7A==}
|
||||
/playwright-core/1.23.4:
|
||||
resolution: {integrity: sha512-h5V2yw7d8xIwotjyNrkLF13nV9RiiZLHdXeHo+nVJIYGVlZ8U2qV0pMxNJKNTvfQVT0N8/A4CW6/4EW2cOcTiA==}
|
||||
engines: {node: '>=14'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
@ -4860,6 +4848,10 @@ packages:
|
||||
engines: {node: '>= 10.x'}
|
||||
dev: false
|
||||
|
||||
/ssh-config/4.1.6:
|
||||
resolution: {integrity: sha512-YdPYn/2afoBonSFoMSvC1FraA/LKKrvy8UvbvAFGJ8gdlKuANvufLLkf8ynF2uq7Tl5+DQBIFyN37//09nAgNQ==}
|
||||
dev: false
|
||||
|
||||
/ssh2/1.10.0:
|
||||
resolution: {integrity: sha512-OnKAAmf4j8wCRrXXZv3Tp5lCZkLJZtgZbn45ELiShCg27djDQ3XFGvIzuGsIsf4hdHslP+VdhA9BhUQdTdfd9w==}
|
||||
engines: {node: '>=10.16.0'}
|
||||
@ -5217,7 +5209,7 @@ packages:
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/ts-node/10.8.2_2zqz24ol5yhbv2blv4fh7akzrq:
|
||||
/ts-node/10.8.2_tdn3ypgnfy6bmey2q4hu5jonwi:
|
||||
resolution: {integrity: sha512-LYdGnoGddf1D6v8REPtIH+5iq/gTDuZqv2/UJUU7tKjuEU8xVZorBM+buCGNjj+pGEud+sOoM4CX3/YzINpENA==}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
@ -5236,7 +5228,7 @@ packages:
|
||||
'@tsconfig/node12': 1.0.9
|
||||
'@tsconfig/node14': 1.0.1
|
||||
'@tsconfig/node16': 1.0.2
|
||||
'@types/node': 18.0.4
|
||||
'@types/node': 18.0.6
|
||||
acorn: 8.7.1
|
||||
acorn-walk: 8.2.0
|
||||
arg: 4.1.3
|
||||
@ -5373,9 +5365,9 @@ packages:
|
||||
engines: {node: '>= 0.8'}
|
||||
dev: false
|
||||
|
||||
/vite/3.0.0:
|
||||
resolution: {integrity: sha512-M7phQhY3+fRZa0H+1WzI6N+/onruwPTBTMvaj7TzgZ0v2TE+N2sdLKxJOfOv9CckDWt5C4HmyQP81xB4dwRKzA==}
|
||||
engines: {node: '>=14.18.0'}
|
||||
/vite/3.0.1:
|
||||
resolution: {integrity: sha512-nefKSglkoEsDpYUkBuT2++L04ktcP8fz8dxLtmZdDdMyhubFSOLFw6BTh/46Fc6tIX/cibs/NVYWNrsqn0k6pQ==}
|
||||
engines: {node: ^14.18.0 || >=16.0.0}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
less: '*'
|
||||
|
Loading…
x
Reference in New Issue
Block a user