fix: build queue system
This commit is contained in:
		
							parent
							
								
									f379519d40
								
							
						
					
					
						commit
						01e71958b2
					
				| @ -27,7 +27,7 @@ | ||||
|     "bcryptjs": "2.4.3", | ||||
|     "bree": "9.1.2", | ||||
|     "cabin": "9.1.2", | ||||
|     "compare-versions": "4.1.3", | ||||
|     "compare-versions": "4.1.4", | ||||
|     "cuid": "2.1.8", | ||||
|     "dayjs": "1.11.5", | ||||
|     "dockerode": "3.3.4", | ||||
| @ -43,17 +43,17 @@ | ||||
|     "jsonwebtoken": "8.5.1", | ||||
|     "node-forge": "1.3.1", | ||||
|     "node-os-utils": "1.3.7", | ||||
|     "p-queue": "7.3.0", | ||||
|     "p-all": "4.0.0", | ||||
|     "public-ip": "6.0.1", | ||||
|     "ssh-config": "4.1.6", | ||||
|     "strip-ansi": "7.0.1", | ||||
|     "unique-names-generator": "4.7.1" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "@types/node": "18.7.11", | ||||
|     "@types/node": "18.7.13", | ||||
|     "@types/node-os-utils": "1.3.0", | ||||
|     "@typescript-eslint/eslint-plugin": "5.34.0", | ||||
|     "@typescript-eslint/parser": "5.34.0", | ||||
|     "@typescript-eslint/eslint-plugin": "5.35.1", | ||||
|     "@typescript-eslint/parser": "5.35.1", | ||||
|     "esbuild": "0.15.5", | ||||
|     "eslint": "8.22.0", | ||||
|     "eslint-config-prettier": "8.5.0", | ||||
|  | ||||
| @ -0,0 +1,29 @@ | ||||
| -- RedefineTables | ||||
| PRAGMA foreign_keys=OFF; | ||||
| CREATE TABLE "new_Setting" ( | ||||
|     "id" TEXT NOT NULL PRIMARY KEY, | ||||
|     "fqdn" TEXT, | ||||
|     "isRegistrationEnabled" BOOLEAN NOT NULL DEFAULT false, | ||||
|     "dualCerts" BOOLEAN NOT NULL DEFAULT false, | ||||
|     "minPort" INTEGER NOT NULL DEFAULT 9000, | ||||
|     "maxPort" INTEGER NOT NULL DEFAULT 9100, | ||||
|     "proxyPassword" TEXT NOT NULL, | ||||
|     "proxyUser" TEXT NOT NULL, | ||||
|     "proxyHash" TEXT, | ||||
|     "isAutoUpdateEnabled" BOOLEAN NOT NULL DEFAULT false, | ||||
|     "isDNSCheckEnabled" BOOLEAN NOT NULL DEFAULT true, | ||||
|     "DNSServers" TEXT, | ||||
|     "isTraefikUsed" BOOLEAN NOT NULL DEFAULT true, | ||||
|     "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||||
|     "updatedAt" DATETIME NOT NULL, | ||||
|     "ipv4" TEXT, | ||||
|     "ipv6" TEXT, | ||||
|     "arch" TEXT, | ||||
|     "concurrentBuilds" INTEGER NOT NULL DEFAULT 1 | ||||
| ); | ||||
| INSERT INTO "new_Setting" ("DNSServers", "arch", "createdAt", "dualCerts", "fqdn", "id", "ipv4", "ipv6", "isAutoUpdateEnabled", "isDNSCheckEnabled", "isRegistrationEnabled", "isTraefikUsed", "maxPort", "minPort", "proxyHash", "proxyPassword", "proxyUser", "updatedAt") SELECT "DNSServers", "arch", "createdAt", "dualCerts", "fqdn", "id", "ipv4", "ipv6", "isAutoUpdateEnabled", "isDNSCheckEnabled", "isRegistrationEnabled", "isTraefikUsed", "maxPort", "minPort", "proxyHash", "proxyPassword", "proxyUser", "updatedAt" FROM "Setting"; | ||||
| DROP TABLE "Setting"; | ||||
| ALTER TABLE "new_Setting" RENAME TO "Setting"; | ||||
| CREATE UNIQUE INDEX "Setting_fqdn_key" ON "Setting"("fqdn"); | ||||
| PRAGMA foreign_key_check; | ||||
| PRAGMA foreign_keys=ON; | ||||
| @ -0,0 +1,24 @@ | ||||
| -- RedefineTables | ||||
| PRAGMA foreign_keys=OFF; | ||||
| CREATE TABLE "new_Build" ( | ||||
|     "id" TEXT NOT NULL PRIMARY KEY, | ||||
|     "type" TEXT NOT NULL, | ||||
|     "applicationId" TEXT, | ||||
|     "destinationDockerId" TEXT, | ||||
|     "gitSourceId" TEXT, | ||||
|     "githubAppId" TEXT, | ||||
|     "gitlabAppId" TEXT, | ||||
|     "commit" TEXT, | ||||
|     "pullmergeRequestId" TEXT, | ||||
|     "forceRebuild" BOOLEAN NOT NULL DEFAULT false, | ||||
|     "sourceBranch" TEXT, | ||||
|     "branch" TEXT, | ||||
|     "status" TEXT DEFAULT 'queued', | ||||
|     "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||||
|     "updatedAt" DATETIME NOT NULL | ||||
| ); | ||||
| INSERT INTO "new_Build" ("applicationId", "branch", "commit", "createdAt", "destinationDockerId", "gitSourceId", "githubAppId", "gitlabAppId", "id", "status", "type", "updatedAt") SELECT "applicationId", "branch", "commit", "createdAt", "destinationDockerId", "gitSourceId", "githubAppId", "gitlabAppId", "id", "status", "type", "updatedAt" FROM "Build"; | ||||
| DROP TABLE "Build"; | ||||
| ALTER TABLE "new_Build" RENAME TO "Build"; | ||||
| PRAGMA foreign_key_check; | ||||
| PRAGMA foreign_keys=ON; | ||||
| @ -27,6 +27,7 @@ model Setting { | ||||
|   ipv4                  String? | ||||
|   ipv6                  String? | ||||
|   arch                  String? | ||||
|   concurrentBuilds      Int      @default(1) | ||||
| } | ||||
| 
 | ||||
| model User { | ||||
| @ -197,6 +198,9 @@ model Build { | ||||
|   githubAppId         String? | ||||
|   gitlabAppId         String? | ||||
|   commit              String? | ||||
|   pullmergeRequestId  String? | ||||
|   forceRebuild        Boolean  @default(false) | ||||
|   sourceBranch        String?   | ||||
|   branch              String? | ||||
|   status              String?  @default("queued") | ||||
|   createdAt           DateTime @default(now()) | ||||
|  | ||||
| @ -5,7 +5,7 @@ import env from '@fastify/env'; | ||||
| import cookie from '@fastify/cookie'; | ||||
| import path, { join } from 'path'; | ||||
| import autoLoad from '@fastify/autoload'; | ||||
| import { asyncExecShell, isDev, listSettings, prisma, version } from './lib/common'; | ||||
| import { asyncExecShell, asyncSleep, isDev, listSettings, prisma, version } from './lib/common'; | ||||
| import { scheduler } from './lib/scheduler'; | ||||
| import axios from 'axios'; | ||||
| import compareVersions from 'compare-versions'; | ||||
| @ -104,14 +104,16 @@ fastify.listen({ port, host }, async (err: any, address: any) => { | ||||
| 	} | ||||
| 	console.log(`Coolify's API is listening on ${host}:${port}`); | ||||
| 	await initServer(); | ||||
| 	await scheduler.start('deployApplication'); | ||||
| 	await scheduler.start('cleanupStorage'); | ||||
| 	await scheduler.start('cleanupPrismaEngines'); | ||||
| 	await scheduler.start('checkProxies'); | ||||
| 
 | ||||
| 	// Check if no build is running
 | ||||
| 	setInterval(async () => { | ||||
| 		if (!scheduler.workers.has('deployApplication')) { | ||||
| 			scheduler.run('deployApplication'); | ||||
| 		} | ||||
| 	}, 2000) | ||||
| 
 | ||||
| 	// Check for update
 | ||||
| 	// Check for update & if no build is running
 | ||||
| 	setInterval(async () => { | ||||
| 		const { isAutoUpdateEnabled } = await prisma.setting.findFirst(); | ||||
| 		if (isAutoUpdateEnabled) { | ||||
| @ -128,8 +130,8 @@ fastify.listen({ port, host }, async (err: any, address: any) => { | ||||
| 			const latestVersion = versions['coolify'].main.version; | ||||
| 			const isUpdateAvailable = compareVersions(latestVersion, currentVersion); | ||||
| 			if (isUpdateAvailable === 1) { | ||||
| 				if (scheduler.workers.has('deployApplication')) { | ||||
| 					scheduler.workers.get('deployApplication').postMessage("status:autoUpdater"); | ||||
| 				if (!scheduler.workers.has('deployApplication')) { | ||||
| 					await scheduler.run('autoUpdater') | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| @ -137,16 +139,11 @@ fastify.listen({ port, host }, async (err: any, address: any) => { | ||||
| 
 | ||||
| 	// Cleanup storage
 | ||||
| 	setInterval(async () => { | ||||
| 		if (scheduler.workers.has('deployApplication')) { | ||||
| 			scheduler.workers.get('deployApplication').postMessage("status:cleanupStorage"); | ||||
| 		if (!scheduler.workers.has('deployApplication') && !scheduler.workers.has('cleanupStorage')) { | ||||
| 			await scheduler.run('cleanupStorage') | ||||
| 		} | ||||
| 	}, isDev ? 5000 : 60000 * 10) | ||||
| 
 | ||||
| 	scheduler.on('worker deleted', async (name) => { | ||||
| 		if (name === 'autoUpdater' || name === 'cleanupStorage') { | ||||
| 			if (!scheduler.workers.has('deployApplication')) await scheduler.start('deployApplication'); | ||||
| 		} | ||||
| 	}); | ||||
| 	await getArch(); | ||||
| 	await getIPAddress(); | ||||
| }); | ||||
| @ -170,6 +167,12 @@ async function initServer() { | ||||
| 	try { | ||||
| 		await asyncExecShell(`docker network create --attachable coolify`); | ||||
| 	} catch (error) { } | ||||
| 	try { | ||||
| 		const isOlder = compareVersions('3.8.1', version); | ||||
| 		if (isOlder === -1) { | ||||
| 			await prisma.build.updateMany({ where: { status: { in: ['running', 'queued'] } }, data: { status: 'failed' } }); | ||||
| 		} | ||||
| 	} catch (error) { } | ||||
| } | ||||
| async function getArch() { | ||||
| 	try { | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| import { parentPort } from 'node:worker_threads'; | ||||
| import { asyncExecShell, cleanupDockerStorage, executeDockerCmd, isDev, prisma, version } from '../lib/common'; | ||||
| import { asyncExecShell, cleanupDockerStorage, executeDockerCmd, isDev, prisma } from '../lib/common'; | ||||
| 
 | ||||
| (async () => { | ||||
|     if (parentPort) { | ||||
| @ -9,7 +9,7 @@ import { asyncExecShell, cleanupDockerStorage, executeDockerCmd, isDev, prisma, | ||||
|             if (enginesDone.has(destination.engine) || enginesDone.has(destination.remoteIpAddress)) return | ||||
|             if (destination.engine) enginesDone.add(destination.engine) | ||||
|             if (destination.remoteIpAddress) enginesDone.add(destination.remoteIpAddress) | ||||
|              | ||||
| 
 | ||||
|             let lowDiskSpace = false; | ||||
|             try { | ||||
|                 let stdout = null | ||||
|  | ||||
							
								
								
									
										366
									
								
								apps/api/src/jobs/deployApplication-old.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										366
									
								
								apps/api/src/jobs/deployApplication-old.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,366 @@ | ||||
| import { parentPort } from 'node:worker_threads'; | ||||
| import crypto from 'crypto'; | ||||
| import fs from 'fs/promises'; | ||||
| import yaml from 'js-yaml'; | ||||
| 
 | ||||
| import { copyBaseConfigurationFiles, makeLabelForStandaloneApplication, saveBuildLog, setDefaultConfiguration } from '../lib/buildPacks/common'; | ||||
| import { createDirectories, decrypt, defaultComposeConfiguration, executeDockerCmd, getDomain, prisma } from '../lib/common'; | ||||
| import * as importers from '../lib/importers'; | ||||
| import * as buildpacks from '../lib/buildPacks'; | ||||
| 
 | ||||
| (async () => { | ||||
| 	if (parentPort) { | ||||
| 		const concurrency = 1 | ||||
| 		const PQueue = await import('p-queue'); | ||||
| 		const queue = new PQueue.default({ concurrency }); | ||||
| 		parentPort.on('message', async (message) => { | ||||
| 			if (parentPort) { | ||||
| 				if (message === 'error') throw new Error('oops'); | ||||
| 				if (message === 'cancel') { | ||||
| 					parentPort.postMessage('cancelled'); | ||||
| 					return; | ||||
| 				} | ||||
| 				if (message === 'status:autoUpdater') { | ||||
| 					parentPort.postMessage({ size: queue.size, pending: queue.pending, caller: 'autoUpdater' }); | ||||
| 					return; | ||||
| 				} | ||||
| 				if (message === 'status:cleanupStorage') { | ||||
| 					parentPort.postMessage({ size: queue.size, pending: queue.pending, caller: 'cleanupStorage' }); | ||||
| 					return; | ||||
| 				} | ||||
| 				if (message === 'action:flushQueue') { | ||||
| 					queue.clear() | ||||
| 					return; | ||||
| 				} | ||||
| 
 | ||||
| 				await queue.add(async () => { | ||||
| 					const { | ||||
| 						id: applicationId, | ||||
| 						repository, | ||||
| 						name, | ||||
| 						destinationDocker, | ||||
| 						destinationDockerId, | ||||
| 						gitSource, | ||||
| 						build_id: buildId, | ||||
| 						configHash, | ||||
| 						fqdn, | ||||
| 						projectId, | ||||
| 						secrets, | ||||
| 						phpModules, | ||||
| 						type, | ||||
| 						pullmergeRequestId = null, | ||||
| 						sourceBranch = null, | ||||
| 						settings, | ||||
| 						persistentStorage, | ||||
| 						pythonWSGI, | ||||
| 						pythonModule, | ||||
| 						pythonVariable, | ||||
| 						denoOptions, | ||||
| 						exposePort, | ||||
| 						baseImage, | ||||
| 						baseBuildImage, | ||||
| 						deploymentType, | ||||
| 						forceRebuild | ||||
| 					} = message | ||||
| 					let { | ||||
| 						branch, | ||||
| 						buildPack, | ||||
| 						port, | ||||
| 						installCommand, | ||||
| 						buildCommand, | ||||
| 						startCommand, | ||||
| 						baseDirectory, | ||||
| 						publishDirectory, | ||||
| 						dockerFileLocation, | ||||
| 						denoMainFile | ||||
| 					} = message | ||||
| 					const currentHash = crypto | ||||
| 						.createHash('sha256') | ||||
| 						.update( | ||||
| 							JSON.stringify({ | ||||
| 								pythonWSGI, | ||||
| 								pythonModule, | ||||
| 								pythonVariable, | ||||
| 								deploymentType, | ||||
| 								denoOptions, | ||||
| 								baseImage, | ||||
| 								baseBuildImage, | ||||
| 								buildPack, | ||||
| 								port, | ||||
| 								exposePort, | ||||
| 								installCommand, | ||||
| 								buildCommand, | ||||
| 								startCommand, | ||||
| 								secrets, | ||||
| 								branch, | ||||
| 								repository, | ||||
| 								fqdn | ||||
| 							}) | ||||
| 						) | ||||
| 						.digest('hex'); | ||||
| 					try { | ||||
| 						const { debug } = settings; | ||||
| 						if (concurrency === 1) { | ||||
| 							await prisma.build.updateMany({ | ||||
| 								where: { | ||||
| 									status: { in: ['queued', 'running'] }, | ||||
| 									id: { not: buildId }, | ||||
| 									applicationId, | ||||
| 									createdAt: { lt: new Date(new Date().getTime() - 10 * 1000) } | ||||
| 								}, | ||||
| 								data: { status: 'failed' } | ||||
| 							}); | ||||
| 						} | ||||
| 						let imageId = applicationId; | ||||
| 						let domain = getDomain(fqdn); | ||||
| 						const volumes = | ||||
| 							persistentStorage?.map((storage) => { | ||||
| 								return `${applicationId}${storage.path.replace(/\//gi, '-')}:${buildPack !== 'docker' ? '/app' : '' | ||||
| 									}${storage.path}`;
 | ||||
| 							}) || []; | ||||
| 						// Previews, we need to get the source branch and set subdomain
 | ||||
| 						if (pullmergeRequestId) { | ||||
| 							branch = sourceBranch; | ||||
| 							domain = `${pullmergeRequestId}.${domain}`; | ||||
| 							imageId = `${applicationId}-${pullmergeRequestId}`; | ||||
| 						} | ||||
| 
 | ||||
| 						let deployNeeded = true; | ||||
| 						let destinationType; | ||||
| 
 | ||||
| 						if (destinationDockerId) { | ||||
| 							destinationType = 'docker'; | ||||
| 						} | ||||
| 						if (destinationType === 'docker') { | ||||
| 							await prisma.build.update({ where: { id: buildId }, data: { status: 'running' } }); | ||||
| 							const { workdir, repodir } = await createDirectories({ repository, buildId }); | ||||
| 							const configuration = await setDefaultConfiguration(message); | ||||
| 
 | ||||
| 							buildPack = configuration.buildPack; | ||||
| 							port = configuration.port; | ||||
| 							installCommand = configuration.installCommand; | ||||
| 							startCommand = configuration.startCommand; | ||||
| 							buildCommand = configuration.buildCommand; | ||||
| 							publishDirectory = configuration.publishDirectory; | ||||
| 							baseDirectory = configuration.baseDirectory; | ||||
| 							dockerFileLocation = configuration.dockerFileLocation; | ||||
| 							denoMainFile = configuration.denoMainFile; | ||||
| 							const commit = await importers[gitSource.type]({ | ||||
| 								applicationId, | ||||
| 								debug, | ||||
| 								workdir, | ||||
| 								repodir, | ||||
| 								githubAppId: gitSource.githubApp?.id, | ||||
| 								gitlabAppId: gitSource.gitlabApp?.id, | ||||
| 								customPort: gitSource.customPort, | ||||
| 								repository, | ||||
| 								branch, | ||||
| 								buildId, | ||||
| 								apiUrl: gitSource.apiUrl, | ||||
| 								htmlUrl: gitSource.htmlUrl, | ||||
| 								projectId, | ||||
| 								deployKeyId: gitSource.gitlabApp?.deployKeyId || null, | ||||
| 								privateSshKey: decrypt(gitSource.gitlabApp?.privateSshKey) || null, | ||||
| 								forPublic: gitSource.forPublic | ||||
| 							}); | ||||
| 							if (!commit) { | ||||
| 								throw new Error('No commit found?'); | ||||
| 							} | ||||
| 							let tag = commit.slice(0, 7); | ||||
| 							if (pullmergeRequestId) { | ||||
| 								tag = `${commit.slice(0, 7)}-${pullmergeRequestId}`; | ||||
| 							} | ||||
| 
 | ||||
| 							try { | ||||
| 								await prisma.build.update({ where: { id: buildId }, data: { commit } }); | ||||
| 							} catch (err) { | ||||
| 								console.log(err); | ||||
| 							} | ||||
| 
 | ||||
| 							if (!pullmergeRequestId) { | ||||
| 
 | ||||
| 								if (configHash !== currentHash) { | ||||
| 									deployNeeded = true; | ||||
| 									if (configHash) { | ||||
| 										await saveBuildLog({ line: 'Configuration changed.', buildId, applicationId }); | ||||
| 									} | ||||
| 								} else { | ||||
| 									deployNeeded = false; | ||||
| 								} | ||||
| 							} else { | ||||
| 								deployNeeded = true; | ||||
| 							} | ||||
| 
 | ||||
| 							let imageFound = false; | ||||
| 							try { | ||||
| 								await executeDockerCmd({ | ||||
| 									dockerId: destinationDocker.id, | ||||
| 									command: `docker image inspect ${applicationId}:${tag}` | ||||
| 								}) | ||||
| 								imageFound = true; | ||||
| 							} catch (error) { | ||||
| 								//
 | ||||
| 							} | ||||
| 							await copyBaseConfigurationFiles(buildPack, workdir, buildId, applicationId, baseImage); | ||||
| 
 | ||||
| 							if (forceRebuild) deployNeeded = true | ||||
| 							if (!imageFound || deployNeeded) { | ||||
| 								// if (true) {
 | ||||
| 								if (buildpacks[buildPack]) | ||||
| 									await buildpacks[buildPack]({ | ||||
| 										dockerId: destinationDocker.id, | ||||
| 										buildId, | ||||
| 										applicationId, | ||||
| 										domain, | ||||
| 										name, | ||||
| 										type, | ||||
| 										pullmergeRequestId, | ||||
| 										buildPack, | ||||
| 										repository, | ||||
| 										branch, | ||||
| 										projectId, | ||||
| 										publishDirectory, | ||||
| 										debug, | ||||
| 										commit, | ||||
| 										tag, | ||||
| 										workdir, | ||||
| 										port: exposePort ? `${exposePort}:${port}` : port, | ||||
| 										installCommand, | ||||
| 										buildCommand, | ||||
| 										startCommand, | ||||
| 										baseDirectory, | ||||
| 										secrets, | ||||
| 										phpModules, | ||||
| 										pythonWSGI, | ||||
| 										pythonModule, | ||||
| 										pythonVariable, | ||||
| 										dockerFileLocation, | ||||
| 										denoMainFile, | ||||
| 										denoOptions, | ||||
| 										baseImage, | ||||
| 										baseBuildImage, | ||||
| 										deploymentType | ||||
| 									}); | ||||
| 								else { | ||||
| 									await saveBuildLog({ line: `Build pack ${buildPack} not found`, buildId, applicationId }); | ||||
| 									throw new Error(`Build pack ${buildPack} not found.`); | ||||
| 								} | ||||
| 							} else { | ||||
| 								await saveBuildLog({ line: 'Build image already available - no rebuild required.', buildId, applicationId }); | ||||
| 							} | ||||
| 							try { | ||||
| 								await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker stop -t 0 ${imageId}` }) | ||||
| 								await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker rm ${imageId}` }) | ||||
| 							} catch (error) { | ||||
| 								//
 | ||||
| 							} | ||||
| 							const envs = [ | ||||
| 								`PORT=${port}` | ||||
| 							]; | ||||
| 							if (secrets.length > 0) { | ||||
| 								secrets.forEach((secret) => { | ||||
| 									if (pullmergeRequestId) { | ||||
| 										if (secret.isPRMRSecret) { | ||||
| 											envs.push(`${secret.name}=${secret.value}`); | ||||
| 										} | ||||
| 									} else { | ||||
| 										if (!secret.isPRMRSecret) { | ||||
| 											envs.push(`${secret.name}=${secret.value}`); | ||||
| 										} | ||||
| 									} | ||||
| 								}); | ||||
| 							} | ||||
| 							await fs.writeFile(`${workdir}/.env`, envs.join('\n')); | ||||
| 							const labels = makeLabelForStandaloneApplication({ | ||||
| 								applicationId, | ||||
| 								fqdn, | ||||
| 								name, | ||||
| 								type, | ||||
| 								pullmergeRequestId, | ||||
| 								buildPack, | ||||
| 								repository, | ||||
| 								branch, | ||||
| 								projectId, | ||||
| 								port: exposePort ? `${exposePort}:${port}` : port, | ||||
| 								commit, | ||||
| 								installCommand, | ||||
| 								buildCommand, | ||||
| 								startCommand, | ||||
| 								baseDirectory, | ||||
| 								publishDirectory | ||||
| 							}); | ||||
| 							let envFound = false; | ||||
| 							try { | ||||
| 								envFound = !!(await fs.stat(`${workdir}/.env`)); | ||||
| 							} catch (error) { | ||||
| 								//
 | ||||
| 							} | ||||
| 							try { | ||||
| 								await saveBuildLog({ line: 'Deployment started.', buildId, applicationId }); | ||||
| 								const composeVolumes = volumes.map((volume) => { | ||||
| 									return { | ||||
| 										[`${volume.split(':')[0]}`]: { | ||||
| 											name: volume.split(':')[0] | ||||
| 										} | ||||
| 									}; | ||||
| 								}); | ||||
| 								const composeFile = { | ||||
| 									version: '3.8', | ||||
| 									services: { | ||||
| 										[imageId]: { | ||||
| 											image: `${applicationId}:${tag}`, | ||||
| 											container_name: imageId, | ||||
| 											volumes, | ||||
| 											env_file: envFound ? [`${workdir}/.env`] : [], | ||||
| 											labels, | ||||
| 											depends_on: [], | ||||
| 											expose: [port], | ||||
| 											...(exposePort ? { ports: [`${exposePort}:${port}`] } : {}), | ||||
| 											// logging: {
 | ||||
| 											// 	driver: 'fluentd',
 | ||||
| 											// },
 | ||||
| 											...defaultComposeConfiguration(destinationDocker.network), | ||||
| 										} | ||||
| 									}, | ||||
| 									networks: { | ||||
| 										[destinationDocker.network]: { | ||||
| 											external: true | ||||
| 										} | ||||
| 									}, | ||||
| 									volumes: Object.assign({}, ...composeVolumes) | ||||
| 								}; | ||||
| 								await fs.writeFile(`${workdir}/docker-compose.yml`, yaml.dump(composeFile)); | ||||
| 								await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose --project-directory ${workdir} up -d` }) | ||||
| 								await saveBuildLog({ line: 'Deployment successful!', buildId, applicationId }); | ||||
| 							} catch (error) { | ||||
| 								await saveBuildLog({ line: error, buildId, applicationId }); | ||||
| 								await prisma.build.updateMany({ | ||||
| 									where: { id: message.build_id, status: { in: ['queued', 'running'] } }, | ||||
| 									data: { status: 'failed' } | ||||
| 								}); | ||||
| 								throw new Error(error); | ||||
| 							} | ||||
| 							await saveBuildLog({ line: 'Proxy will be updated shortly.', buildId, applicationId }); | ||||
| 							await prisma.build.update({ where: { id: message.build_id }, data: { status: 'success' } }); | ||||
| 							if (!pullmergeRequestId) await prisma.application.update({ | ||||
| 								where: { id: applicationId }, | ||||
| 								data: { configHash: currentHash } | ||||
| 							}); | ||||
| 						} | ||||
| 
 | ||||
| 					} | ||||
| 					catch (error) { | ||||
| 						await prisma.build.updateMany({ | ||||
| 							where: { id: message.build_id, status: { in: ['queued', 'running'] } }, | ||||
| 							data: { status: 'failed' } | ||||
| 						}); | ||||
| 						await saveBuildLog({ line: error, buildId, applicationId }); | ||||
| 					} finally { | ||||
| 						await prisma.$disconnect(); | ||||
| 					} | ||||
| 				}); | ||||
| 				await prisma.$disconnect(); | ||||
| 			} | ||||
| 		}); | ||||
| 	} else process.exit(0); | ||||
| })(); | ||||
| @ -10,357 +10,353 @@ import * as buildpacks from '../lib/buildPacks'; | ||||
| 
 | ||||
| (async () => { | ||||
| 	if (parentPort) { | ||||
| 		const concurrency = 1 | ||||
| 		const PQueue = await import('p-queue'); | ||||
| 		const queue = new PQueue.default({ concurrency }); | ||||
| 		parentPort.on('message', async (message) => { | ||||
| 			if (parentPort) { | ||||
| 				if (message === 'error') throw new Error('oops'); | ||||
| 				if (message === 'cancel') { | ||||
| 					parentPort.postMessage('cancelled'); | ||||
| 					return; | ||||
| 				} | ||||
| 				if (message === 'status:autoUpdater') { | ||||
| 					parentPort.postMessage({ size: queue.size, pending: queue.pending, caller: 'autoUpdater' }); | ||||
| 					return; | ||||
| 				} | ||||
| 				if (message === 'status:cleanupStorage') { | ||||
| 					parentPort.postMessage({ size: queue.size, pending: queue.pending, caller: 'cleanupStorage' }); | ||||
| 					return; | ||||
| 				} | ||||
| 				if (message === 'action:flushQueue') { | ||||
| 					queue.clear() | ||||
| 					return; | ||||
| 				} | ||||
| 
 | ||||
| 				await queue.add(async () => { | ||||
| 					const { | ||||
| 						id: applicationId, | ||||
| 						repository, | ||||
| 						name, | ||||
| 						destinationDocker, | ||||
| 						destinationDockerId, | ||||
| 						gitSource, | ||||
| 						build_id: buildId, | ||||
| 						configHash, | ||||
| 						fqdn, | ||||
| 						projectId, | ||||
| 						secrets, | ||||
| 						phpModules, | ||||
| 						type, | ||||
| 						pullmergeRequestId = null, | ||||
| 						sourceBranch = null, | ||||
| 						settings, | ||||
| 						persistentStorage, | ||||
| 						pythonWSGI, | ||||
| 						pythonModule, | ||||
| 						pythonVariable, | ||||
| 						denoOptions, | ||||
| 						exposePort, | ||||
| 						baseImage, | ||||
| 						baseBuildImage, | ||||
| 						deploymentType, | ||||
| 						forceRebuild | ||||
| 					} = message | ||||
| 					let { | ||||
| 						branch, | ||||
| 						buildPack, | ||||
| 						port, | ||||
| 						installCommand, | ||||
| 						buildCommand, | ||||
| 						startCommand, | ||||
| 						baseDirectory, | ||||
| 						publishDirectory, | ||||
| 						dockerFileLocation, | ||||
| 						denoMainFile | ||||
| 					} = message | ||||
| 					const currentHash = crypto | ||||
| 						.createHash('sha256') | ||||
| 						.update( | ||||
| 							JSON.stringify({ | ||||
| 								pythonWSGI, | ||||
| 								pythonModule, | ||||
| 								pythonVariable, | ||||
| 								deploymentType, | ||||
| 								denoOptions, | ||||
| 								baseImage, | ||||
| 								baseBuildImage, | ||||
| 								buildPack, | ||||
| 								port, | ||||
| 								exposePort, | ||||
| 								installCommand, | ||||
| 								buildCommand, | ||||
| 								startCommand, | ||||
| 								secrets, | ||||
| 								branch, | ||||
| 								repository, | ||||
| 								fqdn | ||||
| 							}) | ||||
| 						) | ||||
| 						.digest('hex'); | ||||
| 					try { | ||||
| 						const { debug } = settings; | ||||
| 						if (concurrency === 1) { | ||||
| 							await prisma.build.updateMany({ | ||||
| 								where: { | ||||
| 									status: { in: ['queued', 'running'] }, | ||||
| 									id: { not: buildId }, | ||||
| 									applicationId, | ||||
| 									createdAt: { lt: new Date(new Date().getTime() - 10 * 1000) } | ||||
| 								}, | ||||
| 								data: { status: 'failed' } | ||||
| 							}); | ||||
| 						} | ||||
| 						let imageId = applicationId; | ||||
| 						let domain = getDomain(fqdn); | ||||
| 						const volumes = | ||||
| 							persistentStorage?.map((storage) => { | ||||
| 								return `${applicationId}${storage.path.replace(/\//gi, '-')}:${buildPack !== 'docker' ? '/app' : '' | ||||
| 									}${storage.path}`;
 | ||||
| 							}) || []; | ||||
| 						// Previews, we need to get the source branch and set subdomain
 | ||||
| 						if (pullmergeRequestId) { | ||||
| 							branch = sourceBranch; | ||||
| 							domain = `${pullmergeRequestId}.${domain}`; | ||||
| 							imageId = `${applicationId}-${pullmergeRequestId}`; | ||||
| 						} | ||||
| 
 | ||||
| 						let deployNeeded = true; | ||||
| 						let destinationType; | ||||
| 
 | ||||
| 						if (destinationDockerId) { | ||||
| 							destinationType = 'docker'; | ||||
| 						} | ||||
| 						if (destinationType === 'docker') { | ||||
| 							await prisma.build.update({ where: { id: buildId }, data: { status: 'running' } }); | ||||
| 							const { workdir, repodir } = await createDirectories({ repository, buildId }); | ||||
| 							const configuration = await setDefaultConfiguration(message); | ||||
| 
 | ||||
| 							buildPack = configuration.buildPack; | ||||
| 							port = configuration.port; | ||||
| 							installCommand = configuration.installCommand; | ||||
| 							startCommand = configuration.startCommand; | ||||
| 							buildCommand = configuration.buildCommand; | ||||
| 							publishDirectory = configuration.publishDirectory; | ||||
| 							baseDirectory = configuration.baseDirectory; | ||||
| 							dockerFileLocation = configuration.dockerFileLocation; | ||||
| 							denoMainFile = configuration.denoMainFile; | ||||
| 							const commit = await importers[gitSource.type]({ | ||||
| 								applicationId, | ||||
| 								debug, | ||||
| 								workdir, | ||||
| 								repodir, | ||||
| 								githubAppId: gitSource.githubApp?.id, | ||||
| 								gitlabAppId: gitSource.gitlabApp?.id, | ||||
| 								customPort: gitSource.customPort, | ||||
| 								repository, | ||||
| 								branch, | ||||
| 								buildId, | ||||
| 								apiUrl: gitSource.apiUrl, | ||||
| 								htmlUrl: gitSource.htmlUrl, | ||||
| 								projectId, | ||||
| 								deployKeyId: gitSource.gitlabApp?.deployKeyId || null, | ||||
| 								privateSshKey: decrypt(gitSource.gitlabApp?.privateSshKey) || null, | ||||
| 								forPublic: gitSource.forPublic | ||||
| 							}); | ||||
| 							if (!commit) { | ||||
| 								throw new Error('No commit found?'); | ||||
| 							} | ||||
| 							let tag = commit.slice(0, 7); | ||||
| 							if (pullmergeRequestId) { | ||||
| 								tag = `${commit.slice(0, 7)}-${pullmergeRequestId}`; | ||||
| 							} | ||||
| 
 | ||||
| 							try { | ||||
| 								await prisma.build.update({ where: { id: buildId }, data: { commit } }); | ||||
| 							} catch (err) { | ||||
| 								console.log(err); | ||||
| 							} | ||||
| 
 | ||||
| 							if (!pullmergeRequestId) { | ||||
| 
 | ||||
| 								if (configHash !== currentHash) { | ||||
| 									deployNeeded = true; | ||||
| 									if (configHash) { | ||||
| 										await saveBuildLog({ line: 'Configuration changed.', buildId, applicationId }); | ||||
| 									} | ||||
| 								} else { | ||||
| 									deployNeeded = false; | ||||
| 								} | ||||
| 							} else { | ||||
| 								deployNeeded = true; | ||||
| 							} | ||||
| 
 | ||||
| 							let imageFound = false; | ||||
| 							try { | ||||
| 								await executeDockerCmd({ | ||||
| 									dockerId: destinationDocker.id, | ||||
| 									command: `docker image inspect ${applicationId}:${tag}` | ||||
| 								}) | ||||
| 								imageFound = true; | ||||
| 							} catch (error) { | ||||
| 								//
 | ||||
| 							} | ||||
| 							await copyBaseConfigurationFiles(buildPack, workdir, buildId, applicationId, baseImage); | ||||
| 
 | ||||
| 							if (forceRebuild) deployNeeded = true | ||||
| 							if (!imageFound || deployNeeded) { | ||||
| 								// if (true) {
 | ||||
| 								if (buildpacks[buildPack]) | ||||
| 									await buildpacks[buildPack]({ | ||||
| 										dockerId: destinationDocker.id, | ||||
| 										buildId, | ||||
| 										applicationId, | ||||
| 										domain, | ||||
| 										name, | ||||
| 										type, | ||||
| 										pullmergeRequestId, | ||||
| 										buildPack, | ||||
| 										repository, | ||||
| 										branch, | ||||
| 										projectId, | ||||
| 										publishDirectory, | ||||
| 										debug, | ||||
| 										commit, | ||||
| 										tag, | ||||
| 										workdir, | ||||
| 										port: exposePort ? `${exposePort}:${port}` : port, | ||||
| 										installCommand, | ||||
| 										buildCommand, | ||||
| 										startCommand, | ||||
| 										baseDirectory, | ||||
| 										secrets, | ||||
| 										phpModules, | ||||
| 										pythonWSGI, | ||||
| 										pythonModule, | ||||
| 										pythonVariable, | ||||
| 										dockerFileLocation, | ||||
| 										denoMainFile, | ||||
| 										denoOptions, | ||||
| 										baseImage, | ||||
| 										baseBuildImage, | ||||
| 										deploymentType | ||||
| 									}); | ||||
| 								else { | ||||
| 									await saveBuildLog({ line: `Build pack ${buildPack} not found`, buildId, applicationId }); | ||||
| 									throw new Error(`Build pack ${buildPack} not found.`); | ||||
| 								} | ||||
| 							} else { | ||||
| 								await saveBuildLog({ line: 'Build image already available - no rebuild required.', buildId, applicationId }); | ||||
| 							} | ||||
| 							try { | ||||
| 								await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker stop -t 0 ${imageId}` }) | ||||
| 								await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker rm ${imageId}` }) | ||||
| 							} catch (error) { | ||||
| 								//
 | ||||
| 							} | ||||
| 							const envs = [ | ||||
| 								`PORT=${port}` | ||||
| 							]; | ||||
| 							if (secrets.length > 0) { | ||||
| 								secrets.forEach((secret) => { | ||||
| 									if (pullmergeRequestId) { | ||||
| 										if (secret.isPRMRSecret) { | ||||
| 											envs.push(`${secret.name}=${secret.value}`); | ||||
| 										} | ||||
| 									} else { | ||||
| 										if (!secret.isPRMRSecret) { | ||||
| 											envs.push(`${secret.name}=${secret.value}`); | ||||
| 										} | ||||
| 									} | ||||
| 								}); | ||||
| 							} | ||||
| 							await fs.writeFile(`${workdir}/.env`, envs.join('\n')); | ||||
| 							const labels = makeLabelForStandaloneApplication({ | ||||
| 								applicationId, | ||||
| 								fqdn, | ||||
| 								name, | ||||
| 								type, | ||||
| 								pullmergeRequestId, | ||||
| 								buildPack, | ||||
| 								repository, | ||||
| 								branch, | ||||
| 								projectId, | ||||
| 								port: exposePort ? `${exposePort}:${port}` : port, | ||||
| 								commit, | ||||
| 								installCommand, | ||||
| 								buildCommand, | ||||
| 								startCommand, | ||||
| 								baseDirectory, | ||||
| 								publishDirectory | ||||
| 							}); | ||||
| 							let envFound = false; | ||||
| 							try { | ||||
| 								envFound = !!(await fs.stat(`${workdir}/.env`)); | ||||
| 							} catch (error) { | ||||
| 								//
 | ||||
| 							} | ||||
| 							try { | ||||
| 								await saveBuildLog({ line: 'Deployment started.', buildId, applicationId }); | ||||
| 								const composeVolumes = volumes.map((volume) => { | ||||
| 									return { | ||||
| 										[`${volume.split(':')[0]}`]: { | ||||
| 											name: volume.split(':')[0] | ||||
| 										} | ||||
| 									}; | ||||
| 								}); | ||||
| 								const composeFile = { | ||||
| 									version: '3.8', | ||||
| 									services: { | ||||
| 										[imageId]: { | ||||
| 											image: `${applicationId}:${tag}`, | ||||
| 											container_name: imageId, | ||||
| 											volumes, | ||||
| 											env_file: envFound ? [`${workdir}/.env`] : [], | ||||
| 											labels, | ||||
| 											depends_on: [], | ||||
| 											expose: [port], | ||||
| 											...(exposePort ? { ports: [`${exposePort}:${port}`] } : {}), | ||||
| 											// logging: {
 | ||||
| 											// 	driver: 'fluentd',
 | ||||
| 											// },
 | ||||
| 											...defaultComposeConfiguration(destinationDocker.network), | ||||
| 										} | ||||
| 									}, | ||||
| 									networks: { | ||||
| 										[destinationDocker.network]: { | ||||
| 											external: true | ||||
| 										} | ||||
| 									}, | ||||
| 									volumes: Object.assign({}, ...composeVolumes) | ||||
| 								}; | ||||
| 								await fs.writeFile(`${workdir}/docker-compose.yml`, yaml.dump(composeFile)); | ||||
| 								await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose --project-directory ${workdir} up -d` }) | ||||
| 								await saveBuildLog({ line: 'Deployment successful!', buildId, applicationId }); | ||||
| 							} catch (error) { | ||||
| 								await saveBuildLog({ line: error, buildId, applicationId }); | ||||
| 								await prisma.build.updateMany({ | ||||
| 									where: { id: message.build_id, status: { in: ['queued', 'running'] } }, | ||||
| 									data: { status: 'failed' } | ||||
| 								}); | ||||
| 								throw new Error(error); | ||||
| 							} | ||||
| 							await saveBuildLog({ line: 'Proxy will be updated shortly.', buildId, applicationId }); | ||||
| 							await prisma.build.update({ where: { id: message.build_id }, data: { status: 'success' } }); | ||||
| 							if (!pullmergeRequestId) await prisma.application.update({ | ||||
| 								where: { id: applicationId }, | ||||
| 								data: { configHash: currentHash } | ||||
| 							}); | ||||
| 						} | ||||
| 
 | ||||
| 					} | ||||
| 					catch (error) { | ||||
| 						await prisma.build.updateMany({ | ||||
| 							where: { id: message.build_id, status: { in: ['queued', 'running'] } }, | ||||
| 							data: { status: 'failed' } | ||||
| 						}); | ||||
| 						await saveBuildLog({ line: error, buildId, applicationId }); | ||||
| 					} finally { | ||||
| 						await prisma.$disconnect(); | ||||
| 					} | ||||
| 				}); | ||||
| 				await prisma.$disconnect(); | ||||
| 			if (message === 'error') throw new Error('oops'); | ||||
| 			if (message === 'cancel') { | ||||
| 				parentPort.postMessage('cancelled'); | ||||
| 				process.exit(0); | ||||
| 			} | ||||
| 		}); | ||||
| 		try { | ||||
| 			parentPort.postMessage({ deploying: true }); | ||||
| 			const queuedBuilds = await prisma.build.findMany({ where: { status: 'queued' }, orderBy: { createdAt: 'asc' } }); | ||||
| 			const { concurrentBuilds } = await prisma.setting.findFirst({}) | ||||
| 			if (queuedBuilds.length > 0) { | ||||
| 				const concurrency = concurrentBuilds; | ||||
| 				const pAll = await import('p-all'); | ||||
| 				const actions = [] | ||||
| 
 | ||||
| 				for (const queueBuild of queuedBuilds) { | ||||
| 					actions.push(async () => { | ||||
| 						const application = await prisma.application.findUnique({ where: { id: queueBuild.applicationId }, include: { destinationDocker: true, gitSource: { include: { githubApp: true, gitlabApp: true } }, persistentStorage: true, secrets: true, settings: true, teams: true } }) | ||||
| 						const { id: buildId, type, sourceBranch = null, pullmergeRequestId = null, forceRebuild } = queueBuild | ||||
| 						const { | ||||
| 							id: applicationId, | ||||
| 							repository, | ||||
| 							name, | ||||
| 							destinationDocker, | ||||
| 							destinationDockerId, | ||||
| 							gitSource, | ||||
| 							configHash, | ||||
| 							fqdn, | ||||
| 							projectId, | ||||
| 							secrets, | ||||
| 							phpModules, | ||||
| 							settings, | ||||
| 							persistentStorage, | ||||
| 							pythonWSGI, | ||||
| 							pythonModule, | ||||
| 							pythonVariable, | ||||
| 							denoOptions, | ||||
| 							exposePort, | ||||
| 							baseImage, | ||||
| 							baseBuildImage, | ||||
| 							deploymentType, | ||||
| 						} = application | ||||
| 						let { | ||||
| 							branch, | ||||
| 							buildPack, | ||||
| 							port, | ||||
| 							installCommand, | ||||
| 							buildCommand, | ||||
| 							startCommand, | ||||
| 							baseDirectory, | ||||
| 							publishDirectory, | ||||
| 							dockerFileLocation, | ||||
| 							denoMainFile | ||||
| 						} = application | ||||
| 						const currentHash = crypto | ||||
| 							.createHash('sha256') | ||||
| 							.update( | ||||
| 								JSON.stringify({ | ||||
| 									pythonWSGI, | ||||
| 									pythonModule, | ||||
| 									pythonVariable, | ||||
| 									deploymentType, | ||||
| 									denoOptions, | ||||
| 									baseImage, | ||||
| 									baseBuildImage, | ||||
| 									buildPack, | ||||
| 									port, | ||||
| 									exposePort, | ||||
| 									installCommand, | ||||
| 									buildCommand, | ||||
| 									startCommand, | ||||
| 									secrets, | ||||
| 									branch, | ||||
| 									repository, | ||||
| 									fqdn | ||||
| 								}) | ||||
| 							) | ||||
| 							.digest('hex'); | ||||
| 						try { | ||||
| 							const { debug } = settings; | ||||
| 							if (concurrency === 1) { | ||||
| 								await prisma.build.updateMany({ | ||||
| 									where: { | ||||
| 										status: { in: ['queued', 'running'] }, | ||||
| 										id: { not: buildId }, | ||||
| 										applicationId, | ||||
| 										createdAt: { lt: new Date(new Date().getTime() - 10 * 1000) } | ||||
| 									}, | ||||
| 									data: { status: 'failed' } | ||||
| 								}); | ||||
| 							} | ||||
| 							let imageId = applicationId; | ||||
| 							let domain = getDomain(fqdn); | ||||
| 							const volumes = | ||||
| 								persistentStorage?.map((storage) => { | ||||
| 									return `${applicationId}${storage.path.replace(/\//gi, '-')}:${buildPack !== 'docker' ? '/app' : '' | ||||
| 										}${storage.path}`;
 | ||||
| 								}) || []; | ||||
| 							// Previews, we need to get the source branch and set subdomain
 | ||||
| 							if (pullmergeRequestId) { | ||||
| 								branch = sourceBranch; | ||||
| 								domain = `${pullmergeRequestId}.${domain}`; | ||||
| 								imageId = `${applicationId}-${pullmergeRequestId}`; | ||||
| 							} | ||||
| 
 | ||||
| 							let deployNeeded = true; | ||||
| 							let destinationType; | ||||
| 
 | ||||
| 							if (destinationDockerId) { | ||||
| 								destinationType = 'docker'; | ||||
| 							} | ||||
| 							if (destinationType === 'docker') { | ||||
| 								await prisma.build.update({ where: { id: buildId }, data: { status: 'running' } }); | ||||
| 								const { workdir, repodir } = await createDirectories({ repository, buildId }); | ||||
| 								const configuration = await setDefaultConfiguration(application); | ||||
| 
 | ||||
| 								buildPack = configuration.buildPack; | ||||
| 								port = configuration.port; | ||||
| 								installCommand = configuration.installCommand; | ||||
| 								startCommand = configuration.startCommand; | ||||
| 								buildCommand = configuration.buildCommand; | ||||
| 								publishDirectory = configuration.publishDirectory; | ||||
| 								baseDirectory = configuration.baseDirectory; | ||||
| 								dockerFileLocation = configuration.dockerFileLocation; | ||||
| 								denoMainFile = configuration.denoMainFile; | ||||
| 								const commit = await importers[gitSource.type]({ | ||||
| 									applicationId, | ||||
| 									debug, | ||||
| 									workdir, | ||||
| 									repodir, | ||||
| 									githubAppId: gitSource.githubApp?.id, | ||||
| 									gitlabAppId: gitSource.gitlabApp?.id, | ||||
| 									customPort: gitSource.customPort, | ||||
| 									repository, | ||||
| 									branch, | ||||
| 									buildId, | ||||
| 									apiUrl: gitSource.apiUrl, | ||||
| 									htmlUrl: gitSource.htmlUrl, | ||||
| 									projectId, | ||||
| 									deployKeyId: gitSource.gitlabApp?.deployKeyId || null, | ||||
| 									privateSshKey: decrypt(gitSource.gitlabApp?.privateSshKey) || null, | ||||
| 									forPublic: gitSource.forPublic | ||||
| 								}); | ||||
| 								if (!commit) { | ||||
| 									throw new Error('No commit found?'); | ||||
| 								} | ||||
| 								let tag = commit.slice(0, 7); | ||||
| 								if (pullmergeRequestId) { | ||||
| 									tag = `${commit.slice(0, 7)}-${pullmergeRequestId}`; | ||||
| 								} | ||||
| 
 | ||||
| 								try { | ||||
| 									await prisma.build.update({ where: { id: buildId }, data: { commit } }); | ||||
| 								} catch (err) { | ||||
| 									console.log(err); | ||||
| 								} | ||||
| 
 | ||||
| 								if (!pullmergeRequestId) { | ||||
| 									if (configHash !== currentHash) { | ||||
| 										deployNeeded = true; | ||||
| 										if (configHash) { | ||||
| 											await saveBuildLog({ line: 'Configuration changed.', buildId, applicationId }); | ||||
| 										} | ||||
| 									} else { | ||||
| 										deployNeeded = false; | ||||
| 									} | ||||
| 								} else { | ||||
| 									deployNeeded = true; | ||||
| 								} | ||||
| 
 | ||||
| 								let imageFound = false; | ||||
| 								try { | ||||
| 									await executeDockerCmd({ | ||||
| 										dockerId: destinationDocker.id, | ||||
| 										command: `docker image inspect ${applicationId}:${tag}` | ||||
| 									}) | ||||
| 									imageFound = true; | ||||
| 								} catch (error) { | ||||
| 									//
 | ||||
| 								} | ||||
| 								await copyBaseConfigurationFiles(buildPack, workdir, buildId, applicationId, baseImage); | ||||
| 
 | ||||
| 								if (forceRebuild) deployNeeded = true | ||||
| 								if (!imageFound || deployNeeded) { | ||||
| 									// if (true) {
 | ||||
| 									if (buildpacks[buildPack]) | ||||
| 										await buildpacks[buildPack]({ | ||||
| 											dockerId: destinationDocker.id, | ||||
| 											buildId, | ||||
| 											applicationId, | ||||
| 											domain, | ||||
| 											name, | ||||
| 											type, | ||||
| 											pullmergeRequestId, | ||||
| 											buildPack, | ||||
| 											repository, | ||||
| 											branch, | ||||
| 											projectId, | ||||
| 											publishDirectory, | ||||
| 											debug, | ||||
| 											commit, | ||||
| 											tag, | ||||
| 											workdir, | ||||
| 											port: exposePort ? `${exposePort}:${port}` : port, | ||||
| 											installCommand, | ||||
| 											buildCommand, | ||||
| 											startCommand, | ||||
| 											baseDirectory, | ||||
| 											secrets, | ||||
| 											phpModules, | ||||
| 											pythonWSGI, | ||||
| 											pythonModule, | ||||
| 											pythonVariable, | ||||
| 											dockerFileLocation, | ||||
| 											denoMainFile, | ||||
| 											denoOptions, | ||||
| 											baseImage, | ||||
| 											baseBuildImage, | ||||
| 											deploymentType | ||||
| 										}); | ||||
| 									else { | ||||
| 										await saveBuildLog({ line: `Build pack ${buildPack} not found`, buildId, applicationId }); | ||||
| 										throw new Error(`Build pack ${buildPack} not found.`); | ||||
| 									} | ||||
| 								} else { | ||||
| 									await saveBuildLog({ line: 'Build image already available - no rebuild required.', buildId, applicationId }); | ||||
| 								} | ||||
| 								try { | ||||
| 									await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker stop -t 0 ${imageId}` }) | ||||
| 									await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker rm ${imageId}` }) | ||||
| 								} catch (error) { | ||||
| 									//
 | ||||
| 								} | ||||
| 								const envs = [ | ||||
| 									`PORT=${port}` | ||||
| 								]; | ||||
| 								if (secrets.length > 0) { | ||||
| 									secrets.forEach((secret) => { | ||||
| 										if (pullmergeRequestId) { | ||||
| 											if (secret.isPRMRSecret) { | ||||
| 												envs.push(`${secret.name}=${secret.value}`); | ||||
| 											} | ||||
| 										} else { | ||||
| 											if (!secret.isPRMRSecret) { | ||||
| 												envs.push(`${secret.name}=${secret.value}`); | ||||
| 											} | ||||
| 										} | ||||
| 									}); | ||||
| 								} | ||||
| 								await fs.writeFile(`${workdir}/.env`, envs.join('\n')); | ||||
| 								const labels = makeLabelForStandaloneApplication({ | ||||
| 									applicationId, | ||||
| 									fqdn, | ||||
| 									name, | ||||
| 									type, | ||||
| 									pullmergeRequestId, | ||||
| 									buildPack, | ||||
| 									repository, | ||||
| 									branch, | ||||
| 									projectId, | ||||
| 									port: exposePort ? `${exposePort}:${port}` : port, | ||||
| 									commit, | ||||
| 									installCommand, | ||||
| 									buildCommand, | ||||
| 									startCommand, | ||||
| 									baseDirectory, | ||||
| 									publishDirectory | ||||
| 								}); | ||||
| 								let envFound = false; | ||||
| 								try { | ||||
| 									envFound = !!(await fs.stat(`${workdir}/.env`)); | ||||
| 								} catch (error) { | ||||
| 									//
 | ||||
| 								} | ||||
| 								try { | ||||
| 									await saveBuildLog({ line: 'Deployment started.', buildId, applicationId }); | ||||
| 									const composeVolumes = volumes.map((volume) => { | ||||
| 										return { | ||||
| 											[`${volume.split(':')[0]}`]: { | ||||
| 												name: volume.split(':')[0] | ||||
| 											} | ||||
| 										}; | ||||
| 									}); | ||||
| 									const composeFile = { | ||||
| 										version: '3.8', | ||||
| 										services: { | ||||
| 											[imageId]: { | ||||
| 												image: `${applicationId}:${tag}`, | ||||
| 												container_name: imageId, | ||||
| 												volumes, | ||||
| 												env_file: envFound ? [`${workdir}/.env`] : [], | ||||
| 												labels, | ||||
| 												depends_on: [], | ||||
| 												expose: [port], | ||||
| 												...(exposePort ? { ports: [`${exposePort}:${port}`] } : {}), | ||||
| 												// logging: {
 | ||||
| 												// 	driver: 'fluentd',
 | ||||
| 												// },
 | ||||
| 												...defaultComposeConfiguration(destinationDocker.network), | ||||
| 											} | ||||
| 										}, | ||||
| 										networks: { | ||||
| 											[destinationDocker.network]: { | ||||
| 												external: true | ||||
| 											} | ||||
| 										}, | ||||
| 										volumes: Object.assign({}, ...composeVolumes) | ||||
| 									}; | ||||
| 									await fs.writeFile(`${workdir}/docker-compose.yml`, yaml.dump(composeFile)); | ||||
| 									await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose --project-directory ${workdir} up -d` }) | ||||
| 									await saveBuildLog({ line: 'Deployment successful!', buildId, applicationId }); | ||||
| 								} catch (error) { | ||||
| 									await saveBuildLog({ line: error, buildId, applicationId }); | ||||
| 									await prisma.build.updateMany({ | ||||
| 										where: { id: buildId, status: { in: ['queued', 'running'] } }, | ||||
| 										data: { status: 'failed' } | ||||
| 									}); | ||||
| 									throw new Error(error); | ||||
| 								} | ||||
| 								await saveBuildLog({ line: 'Proxy will be updated shortly.', buildId, applicationId }); | ||||
| 								await prisma.build.update({ where: { id: buildId }, data: { status: 'success' } }); | ||||
| 								if (!pullmergeRequestId) await prisma.application.update({ | ||||
| 									where: { id: applicationId }, | ||||
| 									data: { configHash: currentHash } | ||||
| 								}); | ||||
| 							} | ||||
| 						} | ||||
| 						catch (error) { | ||||
| 							await prisma.build.updateMany({ | ||||
| 								where: { id: buildId, status: { in: ['queued', 'running'] } }, | ||||
| 								data: { status: 'failed' } | ||||
| 							}); | ||||
| 							await saveBuildLog({ line: error, buildId, applicationId }); | ||||
| 						} | ||||
| 					}); | ||||
| 				} | ||||
| 
 | ||||
| 				await pAll.default(actions, { concurrency }) | ||||
| 			} | ||||
| 
 | ||||
| 		} catch (error) { | ||||
| 			process.exit(0); | ||||
| 
 | ||||
| 		} finally { | ||||
| 			await prisma.$disconnect(); | ||||
| 			process.exit(0); | ||||
| 		} | ||||
| 	} else process.exit(0); | ||||
| })(); | ||||
|  | ||||
| @ -553,7 +553,7 @@ export async function buildImage({ | ||||
| 	await executeDockerCmd({ debug, buildId, applicationId, dockerId, command: `docker build --progress plain -f ${workdir}/${dockerFile} -t ${cache} ${workdir}` }) | ||||
| 	const { status } = await prisma.build.findUnique({ where: { id: buildId } }) | ||||
| 	if (status === 'canceled') { | ||||
| 		throw new Error('Build canceled.') | ||||
| 		throw new Error('Deployment canceled.') | ||||
| 	} | ||||
| 	if (isCache) { | ||||
| 		await saveBuildLog({ line: `Building cache image successful.`, buildId, applicationId }); | ||||
|  | ||||
| @ -93,7 +93,6 @@ export const asyncExecShellStream = async ({ debug, buildId, applicationId, comm | ||||
| 		const { execaCommand } = await import('execa') | ||||
| 		const subprocess = execaCommand(command, { env: { DOCKER_BUILDKIT: "1", DOCKER_HOST: engine } }) | ||||
| 		if (debug) { | ||||
| 			await saveBuildLog({ line: `=========================`, buildId, applicationId }); | ||||
| 			subprocess.stdout.on('data', async (data) => { | ||||
| 				const stdout = data.toString(); | ||||
| 				const array = stdout.split('\n') | ||||
| @ -123,7 +122,6 @@ export const asyncExecShellStream = async ({ debug, buildId, applicationId, comm | ||||
| 		} | ||||
| 		subprocess.on('exit', async (code) => { | ||||
| 			await asyncSleep(1000); | ||||
| 			await saveBuildLog({ line: `=========================`, buildId, applicationId }); | ||||
| 			if (code === 0) { | ||||
| 				resolve(code) | ||||
| 			} else { | ||||
| @ -1871,7 +1869,7 @@ export async function stopBuild(buildId, applicationId) { | ||||
| 	let count = 0; | ||||
| 	await new Promise<void>(async (resolve, reject) => { | ||||
| 		const { destinationDockerId, status } = await prisma.build.findFirst({ where: { id: buildId } }); | ||||
| 		const { engine, id: dockerId } = await prisma.destinationDocker.findFirst({ where: { id: destinationDockerId } }); | ||||
| 		const { id: dockerId } = await prisma.destinationDocker.findFirst({ where: { id: destinationDockerId } }); | ||||
| 		const interval = setInterval(async () => { | ||||
| 			try { | ||||
| 				if (status === 'failed' || status === 'canceled') { | ||||
| @ -1881,10 +1879,10 @@ export async function stopBuild(buildId, applicationId) { | ||||
| 				if (count > 15) { | ||||
| 					clearInterval(interval); | ||||
| 					if (scheduler.workers.has('deployApplication')) { | ||||
| 						scheduler.workers.get('deployApplication').postMessage("action:flushQueue") | ||||
| 						scheduler.workers.get('deployApplication').postMessage('cancel') | ||||
| 					} | ||||
| 					await cleanupDB(buildId); | ||||
| 					return reject(new Error('Build canceled')); | ||||
| 					await cleanupDB(buildId, applicationId); | ||||
| 					return reject(new Error('Deployment canceled.')); | ||||
| 				} | ||||
| 				const { stdout: buildContainers } = await executeDockerCmd({ dockerId, command: `docker container ls --filter "label=coolify.buildId=${buildId}" --format '{{json .}}'` }) | ||||
| 				if (buildContainers) { | ||||
| @ -1896,9 +1894,9 @@ export async function stopBuild(buildId, applicationId) { | ||||
| 							await removeContainer({ id, dockerId }); | ||||
| 							clearInterval(interval); | ||||
| 							if (scheduler.workers.has('deployApplication')) { | ||||
| 								scheduler.workers.get('deployApplication').postMessage("action:flushQueue") | ||||
| 								scheduler.workers.get('deployApplication').postMessage('cancel') | ||||
| 							} | ||||
| 							await cleanupDB(buildId); | ||||
| 							await cleanupDB(buildId, applicationId); | ||||
| 							return resolve(); | ||||
| 						} | ||||
| 					} | ||||
| @ -1909,11 +1907,12 @@ export async function stopBuild(buildId, applicationId) { | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| async function cleanupDB(buildId: string) { | ||||
| async function cleanupDB(buildId: string, applicationId: string) { | ||||
| 	const data = await prisma.build.findUnique({ where: { id: buildId } }); | ||||
| 	if (data?.status === 'queued' || data?.status === 'running') { | ||||
| 		await prisma.build.update({ where: { id: buildId }, data: { status: 'canceled' } }); | ||||
| 	} | ||||
| 	await saveBuildLog({ line: 'Deployment canceled.', buildId, applicationId }); | ||||
| } | ||||
| 
 | ||||
| export function convertTolOldVolumeNames(type) { | ||||
|  | ||||
| @ -9,27 +9,17 @@ Bree.extend(TSBree); | ||||
| 
 | ||||
| const options: any = { | ||||
| 	defaultExtension: 'js', | ||||
| 	logger: false, | ||||
| 	logger: new Cabin(), | ||||
| 	workerMessageHandler: async ({ name, message }) => { | ||||
| 		if (name === 'deployApplication') { | ||||
| 			if (message.pending === 0 && message.size === 0) { | ||||
| 				if (message.caller === 'autoUpdater') { | ||||
| 					if (!scheduler.workers.has('autoUpdater')) { | ||||
| 						await scheduler.run('autoUpdater') | ||||
| 					} | ||||
| 				} | ||||
| 				if (message.caller === 'cleanupStorage') { | ||||
| 					if (!scheduler.workers.has('cleanupStorage')) { | ||||
| 						await scheduler.run('cleanupStorage') | ||||
| 					} | ||||
| 				} | ||||
| 
 | ||||
| 		if (name === 'deployApplication' && message?.deploying) { | ||||
| 			if (scheduler.workers.has('autoUpdater') || scheduler.workers.has('cleanupStorage')) { | ||||
| 				scheduler.workers.get('deployApplication').postMessage('cancel') | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	jobs: [ | ||||
| 		{ | ||||
| 			name: 'deployApplication' | ||||
| 			name: 'deployApplication', | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: 'cleanupStorage', | ||||
|  | ||||
| @ -75,7 +75,6 @@ export async function getApplicationStatus(request: FastifyRequest<OnlyId>) { | ||||
|             isExited = await isContainerExited(application.destinationDocker.id, id); | ||||
|         } | ||||
|         return { | ||||
|             isQueueActive: scheduler.workers.has('deployApplication'), | ||||
|             isRunning, | ||||
|             isExited, | ||||
|         }; | ||||
| @ -453,6 +452,8 @@ export async function deployApplication(request: FastifyRequest<DeployApplicatio | ||||
|                     id: buildId, | ||||
|                     applicationId: id, | ||||
|                     branch: application.branch, | ||||
|                     pullmergeRequestId, | ||||
|                     forceRebuild, | ||||
|                     destinationDockerId: application.destinationDocker?.id, | ||||
|                     gitSourceId: application.gitSource?.id, | ||||
|                     githubAppId: application.gitSource?.githubApp?.id, | ||||
| @ -461,24 +462,6 @@ export async function deployApplication(request: FastifyRequest<DeployApplicatio | ||||
|                     type: 'manual' | ||||
|                 } | ||||
|             }); | ||||
|             if (pullmergeRequestId) { | ||||
|                 scheduler.workers.get('deployApplication').postMessage({ | ||||
|                     build_id: buildId, | ||||
|                     type: 'manual', | ||||
|                     ...application, | ||||
|                     sourceBranch: branch, | ||||
|                     pullmergeRequestId, | ||||
|                     forceRebuild | ||||
|                 }); | ||||
|             } else { | ||||
|                 scheduler.workers.get('deployApplication').postMessage({ | ||||
|                     build_id: buildId, | ||||
|                     type: 'manual', | ||||
|                     ...application, | ||||
|                     forceRebuild | ||||
|                 }); | ||||
| 
 | ||||
|             } | ||||
|             return { | ||||
|                 buildId | ||||
|             }; | ||||
|  | ||||
| @ -142,12 +142,6 @@ export async function gitHubEvents(request: FastifyRequest<GitHubEvents>): Promi | ||||
|                         type: 'webhook_commit' | ||||
|                     } | ||||
|                 }); | ||||
|                 scheduler.workers.get('deployApplication').postMessage({ | ||||
|                     build_id: buildId, | ||||
|                     type: 'webhook_commit', | ||||
|                     ...applicationFound | ||||
|                 }); | ||||
| 
 | ||||
|                 return { | ||||
|                     message: 'Queued. Thank you!' | ||||
|                 }; | ||||
| @ -183,6 +177,8 @@ export async function gitHubEvents(request: FastifyRequest<GitHubEvents>): Promi | ||||
|                         await prisma.build.create({ | ||||
|                             data: { | ||||
|                                 id: buildId, | ||||
|                                 pullmergeRequestId, | ||||
|                                 sourceBranch, | ||||
|                                 applicationId: applicationFound.id, | ||||
|                                 destinationDockerId: applicationFound.destinationDocker.id, | ||||
|                                 gitSourceId: applicationFound.gitSource.id, | ||||
| @ -192,14 +188,7 @@ export async function gitHubEvents(request: FastifyRequest<GitHubEvents>): Promi | ||||
|                                 type: 'webhook_pr' | ||||
|                             } | ||||
|                         }); | ||||
|                         scheduler.workers.get('deployApplication').postMessage({ | ||||
|                             build_id: buildId, | ||||
|                             type: 'webhook_pr', | ||||
|                             ...applicationFound, | ||||
|                             sourceBranch, | ||||
|                             pullmergeRequestId | ||||
|                         }); | ||||
| 
 | ||||
|                      | ||||
|                         return { | ||||
|                             message: 'Queued. Thank you!' | ||||
|                         }; | ||||
|  | ||||
| @ -89,12 +89,6 @@ export async function gitLabEvents(request: FastifyRequest<GitLabEvents>) { | ||||
|                     } | ||||
|                 }); | ||||
| 
 | ||||
|                 scheduler.workers.get('deployApplication').postMessage({ | ||||
|                     build_id: buildId, | ||||
|                     type: 'webhook_commit', | ||||
|                     ...applicationFound | ||||
|                 }); | ||||
| 
 | ||||
|                 return { | ||||
|                     message: 'Queued. Thank you!' | ||||
|                 }; | ||||
| @ -141,6 +135,8 @@ export async function gitLabEvents(request: FastifyRequest<GitLabEvents>) { | ||||
|                         await prisma.build.create({ | ||||
|                             data: { | ||||
|                                 id: buildId, | ||||
|                                 pullmergeRequestId, | ||||
|                                 sourceBranch, | ||||
|                                 applicationId: applicationFound.id, | ||||
|                                 destinationDockerId: applicationFound.destinationDocker.id, | ||||
|                                 gitSourceId: applicationFound.gitSource.id, | ||||
| @ -150,14 +146,6 @@ export async function gitLabEvents(request: FastifyRequest<GitLabEvents>) { | ||||
|                                 type: 'webhook_mr' | ||||
|                             } | ||||
|                         }); | ||||
|                         scheduler.workers.get('deployApplication').postMessage({ | ||||
|                             build_id: buildId, | ||||
|                             type: 'webhook_mr', | ||||
|                             ...applicationFound, | ||||
|                             sourceBranch, | ||||
|                             pullmergeRequestId | ||||
|                         }); | ||||
| 
 | ||||
|                         return { | ||||
|                             message: 'Queued. Thank you!' | ||||
|                         }; | ||||
|  | ||||
| @ -14,20 +14,20 @@ | ||||
| 		"format": "prettier --write --plugin-search-dir=. ." | ||||
| 	}, | ||||
| 	"devDependencies": { | ||||
| 		"@playwright/test": "1.24.2", | ||||
| 		"@playwright/test": "1.25.1", | ||||
| 		"@sveltejs/kit": "1.0.0-next.405", | ||||
| 		"@types/js-cookie": "3.0.2", | ||||
| 		"@typescript-eslint/eslint-plugin": "5.33.0", | ||||
| 		"@typescript-eslint/parser": "5.33.0", | ||||
| 		"@typescript-eslint/eslint-plugin": "5.35.1", | ||||
| 		"@typescript-eslint/parser": "5.35.1", | ||||
| 		"autoprefixer": "10.4.8", | ||||
| 		"eslint": "8.21.0", | ||||
| 		"eslint": "8.22.0", | ||||
| 		"eslint-config-prettier": "8.5.0", | ||||
| 		"eslint-plugin-svelte3": "4.0.0", | ||||
| 		"postcss": "8.4.16", | ||||
| 		"prettier": "2.7.1", | ||||
| 		"prettier-plugin-svelte": "2.7.0", | ||||
| 		"svelte": "3.49.0", | ||||
| 		"svelte-check": "2.8.0", | ||||
| 		"svelte-check": "2.8.1", | ||||
| 		"svelte-preprocess": "4.10.7", | ||||
| 		"tailwindcss": "3.1.8", | ||||
| 		"tailwindcss-scrollbar": "0.1.0", | ||||
| @ -39,7 +39,7 @@ | ||||
| 	"dependencies": { | ||||
| 		"@sveltejs/adapter-static": "1.0.0-next.39", | ||||
| 		"cuid": "2.1.8", | ||||
| 		"daisyui": "2.22.0", | ||||
| 		"daisyui": "2.24.0", | ||||
| 		"js-cookie": "3.0.1", | ||||
| 		"p-limit": "4.0.0", | ||||
| 		"svelte-select": "4.4.7", | ||||
|  | ||||
| @ -66,7 +66,6 @@ | ||||
| 
 | ||||
| 	let loading = false; | ||||
| 	let statusInterval: any; | ||||
| 	let isQueueActive = false; | ||||
| 	$disabledButton = | ||||
| 		!$appSession.isAdmin || | ||||
| 		(!application.fqdn && !application.settings.isBot) || | ||||
| @ -121,7 +120,6 @@ | ||||
| 		if ($status.application.loading) return; | ||||
| 		$status.application.loading = true; | ||||
| 		const data = await get(`/applications/${id}/status`); | ||||
| 		isQueueActive = data.isQueueActive; | ||||
| 		$status.application.isRunning = data.isRunning; | ||||
| 		$status.application.isExited = data.isExited; | ||||
| 		$status.application.loading = false; | ||||
| @ -259,13 +257,10 @@ | ||||
| 			<form on:submit|preventDefault={() => handleDeploySubmit(true)}> | ||||
| 				<button | ||||
| 					type="submit" | ||||
| 					disabled={$disabledButton || !isQueueActive} | ||||
| 					class:hover:text-green-500={isQueueActive} | ||||
| 					disabled={$disabledButton} | ||||
| 					class="icons bg-transparent tooltip tooltip-primary tooltip-bottom text-sm flex items-center space-x-2" | ||||
| 					data-tip={$appSession.isAdmin | ||||
| 						? isQueueActive | ||||
| 							? 'Force Rebuild Application' | ||||
| 							: 'Autoupdate inprogress. Cannot rebuild application.' | ||||
| 						? 'Force Rebuild Application' | ||||
| 						: 'You do not have permission to rebuild application.'} | ||||
| 				> | ||||
| 					<svg | ||||
| @ -287,7 +282,7 @@ | ||||
| 				</button> | ||||
| 			</form> | ||||
| 		{:else} | ||||
| 			<form on:submit|preventDefault={handleDeploySubmit}> | ||||
| 			<form on:submit|preventDefault={() => handleDeploySubmit(false)}> | ||||
| 				<button | ||||
| 					type="submit" | ||||
| 					disabled={$disabledButton} | ||||
| @ -359,7 +354,7 @@ | ||||
| 			<button | ||||
| 				disabled={$disabledButton} | ||||
| 				class="icons bg-transparent tooltip tooltip-primary tooltip-bottom text-sm" | ||||
| 				data-tip="Secret" | ||||
| 				data-tip="Secrets" | ||||
| 			> | ||||
| 				<svg | ||||
| 					xmlns="http://www.w3.org/2000/svg" | ||||
|  | ||||
| @ -178,7 +178,7 @@ | ||||
| 		{#if !noMoreBuilds} | ||||
| 			{#if buildCount > 5} | ||||
| 				<div class="flex space-x-2"> | ||||
| 					<button disabled={noMoreBuilds} class="w-full" on:click={loadMoreBuilds} | ||||
| 					<button disabled={noMoreBuilds} class=" btn btn-sm w-full" on:click={loadMoreBuilds} | ||||
| 						>{$t('application.build.load_more')}</button | ||||
| 					> | ||||
| 				</div> | ||||
|  | ||||
							
								
								
									
										386
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										386
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							| @ -23,15 +23,15 @@ importers: | ||||
|       '@fastify/static': 6.5.0 | ||||
|       '@iarna/toml': 2.2.5 | ||||
|       '@prisma/client': 3.15.2 | ||||
|       '@types/node': 18.7.11 | ||||
|       '@types/node': 18.7.13 | ||||
|       '@types/node-os-utils': 1.3.0 | ||||
|       '@typescript-eslint/eslint-plugin': 5.34.0 | ||||
|       '@typescript-eslint/parser': 5.34.0 | ||||
|       '@typescript-eslint/eslint-plugin': 5.35.1 | ||||
|       '@typescript-eslint/parser': 5.35.1 | ||||
|       axios: 0.27.2 | ||||
|       bcryptjs: 2.4.3 | ||||
|       bree: 9.1.2 | ||||
|       cabin: 9.1.2 | ||||
|       compare-versions: 4.1.3 | ||||
|       compare-versions: 4.1.4 | ||||
|       cuid: 2.1.8 | ||||
|       dayjs: 1.11.5 | ||||
|       dockerode: 3.3.4 | ||||
| @ -52,7 +52,7 @@ importers: | ||||
|       node-forge: 1.3.1 | ||||
|       node-os-utils: 1.3.7 | ||||
|       nodemon: 2.0.19 | ||||
|       p-queue: 7.3.0 | ||||
|       p-all: 4.0.0 | ||||
|       prettier: 2.7.1 | ||||
|       prisma: 3.15.2 | ||||
|       public-ip: 6.0.1 | ||||
| @ -63,7 +63,7 @@ importers: | ||||
|       typescript: 4.7.4 | ||||
|       unique-names-generator: 4.7.1 | ||||
|     dependencies: | ||||
|       '@breejs/ts-worker': 2.0.0_vko2uubnomvm6mw63pxqdtopyq | ||||
|       '@breejs/ts-worker': 2.0.0_rzqxabipis2a5sxrpk4obdh4zu | ||||
|       '@fastify/autoload': 5.2.0 | ||||
|       '@fastify/cookie': 8.0.0 | ||||
|       '@fastify/cors': 8.1.0 | ||||
| @ -76,7 +76,7 @@ importers: | ||||
|       bcryptjs: 2.4.3 | ||||
|       bree: 9.1.2 | ||||
|       cabin: 9.1.2 | ||||
|       compare-versions: 4.1.3 | ||||
|       compare-versions: 4.1.4 | ||||
|       cuid: 2.1.8 | ||||
|       dayjs: 1.11.5 | ||||
|       dockerode: 3.3.4 | ||||
| @ -92,16 +92,16 @@ importers: | ||||
|       jsonwebtoken: 8.5.1 | ||||
|       node-forge: 1.3.1 | ||||
|       node-os-utils: 1.3.7 | ||||
|       p-queue: 7.3.0 | ||||
|       p-all: 4.0.0 | ||||
|       public-ip: 6.0.1 | ||||
|       ssh-config: 4.1.6 | ||||
|       strip-ansi: 7.0.1 | ||||
|       unique-names-generator: 4.7.1 | ||||
|     devDependencies: | ||||
|       '@types/node': 18.7.11 | ||||
|       '@types/node': 18.7.13 | ||||
|       '@types/node-os-utils': 1.3.0 | ||||
|       '@typescript-eslint/eslint-plugin': 5.34.0_euudt5oqhhodkyae5tf6wjmsda | ||||
|       '@typescript-eslint/parser': 5.34.0_4rv7y5c6xz3vfxwhbrcxxi73bq | ||||
|       '@typescript-eslint/eslint-plugin': 5.35.1_ktjxjibzrfqejavile4bhmzhjq | ||||
|       '@typescript-eslint/parser': 5.35.1_4rv7y5c6xz3vfxwhbrcxxi73bq | ||||
|       esbuild: 0.15.5 | ||||
|       eslint: 8.22.0 | ||||
|       eslint-config-prettier: 8.5.0_eslint@8.22.0 | ||||
| @ -115,16 +115,16 @@ importers: | ||||
| 
 | ||||
|   apps/ui: | ||||
|     specifiers: | ||||
|       '@playwright/test': 1.24.2 | ||||
|       '@playwright/test': 1.25.1 | ||||
|       '@sveltejs/adapter-static': 1.0.0-next.39 | ||||
|       '@sveltejs/kit': 1.0.0-next.405 | ||||
|       '@types/js-cookie': 3.0.2 | ||||
|       '@typescript-eslint/eslint-plugin': 5.33.0 | ||||
|       '@typescript-eslint/parser': 5.33.0 | ||||
|       '@typescript-eslint/eslint-plugin': 5.35.1 | ||||
|       '@typescript-eslint/parser': 5.35.1 | ||||
|       autoprefixer: 10.4.8 | ||||
|       cuid: 2.1.8 | ||||
|       daisyui: 2.22.0 | ||||
|       eslint: 8.21.0 | ||||
|       daisyui: 2.24.0 | ||||
|       eslint: 8.22.0 | ||||
|       eslint-config-prettier: 8.5.0 | ||||
|       eslint-plugin-svelte3: 4.0.0 | ||||
|       js-cookie: 3.0.1 | ||||
| @ -133,7 +133,7 @@ importers: | ||||
|       prettier: 2.7.1 | ||||
|       prettier-plugin-svelte: 2.7.0 | ||||
|       svelte: 3.49.0 | ||||
|       svelte-check: 2.8.0 | ||||
|       svelte-check: 2.8.1 | ||||
|       svelte-preprocess: 4.10.7 | ||||
|       svelte-select: 4.4.7 | ||||
|       sveltekit-i18n: 2.2.2 | ||||
| @ -145,26 +145,26 @@ importers: | ||||
|     dependencies: | ||||
|       '@sveltejs/adapter-static': 1.0.0-next.39 | ||||
|       cuid: 2.1.8 | ||||
|       daisyui: 2.22.0_25hquoklqeoqwmt7fwvvcyxm5e | ||||
|       daisyui: 2.24.0_25hquoklqeoqwmt7fwvvcyxm5e | ||||
|       js-cookie: 3.0.1 | ||||
|       p-limit: 4.0.0 | ||||
|       svelte-select: 4.4.7 | ||||
|       sveltekit-i18n: 2.2.2_svelte@3.49.0 | ||||
|     devDependencies: | ||||
|       '@playwright/test': 1.24.2 | ||||
|       '@playwright/test': 1.25.1 | ||||
|       '@sveltejs/kit': 1.0.0-next.405_svelte@3.49.0+vite@3.0.5 | ||||
|       '@types/js-cookie': 3.0.2 | ||||
|       '@typescript-eslint/eslint-plugin': 5.33.0_njno5y7ry2l2lcmiu4tywxkwnq | ||||
|       '@typescript-eslint/parser': 5.33.0_qugx7qdu5zevzvxaiqyxfiwquq | ||||
|       '@typescript-eslint/eslint-plugin': 5.35.1_ktjxjibzrfqejavile4bhmzhjq | ||||
|       '@typescript-eslint/parser': 5.35.1_4rv7y5c6xz3vfxwhbrcxxi73bq | ||||
|       autoprefixer: 10.4.8_postcss@8.4.16 | ||||
|       eslint: 8.21.0 | ||||
|       eslint-config-prettier: 8.5.0_eslint@8.21.0 | ||||
|       eslint-plugin-svelte3: 4.0.0_a7wk4ghvg4hia4trwaglu7p6cq | ||||
|       eslint: 8.22.0 | ||||
|       eslint-config-prettier: 8.5.0_eslint@8.22.0 | ||||
|       eslint-plugin-svelte3: 4.0.0_laaqauvsmoyypsiqkozwyi2fn4 | ||||
|       postcss: 8.4.16 | ||||
|       prettier: 2.7.1 | ||||
|       prettier-plugin-svelte: 2.7.0_o3ioganyptcsrh6x4hnxvjkpqi | ||||
|       svelte: 3.49.0 | ||||
|       svelte-check: 2.8.0_vylzxgme5yisu3bsyvcau4hjtq | ||||
|       svelte-check: 2.8.1_vylzxgme5yisu3bsyvcau4hjtq | ||||
|       svelte-preprocess: 4.10.7_fje22ktja5v2dh6nbkissncqme | ||||
|       tailwindcss: 3.1.8 | ||||
|       tailwindcss-scrollbar: 0.1.0_tailwindcss@3.1.8 | ||||
| @ -211,14 +211,14 @@ packages: | ||||
|     engines: {node: '>= 10'} | ||||
|     dev: false | ||||
| 
 | ||||
|   /@breejs/ts-worker/2.0.0_vko2uubnomvm6mw63pxqdtopyq: | ||||
|   /@breejs/ts-worker/2.0.0_rzqxabipis2a5sxrpk4obdh4zu: | ||||
|     resolution: {integrity: sha512-6anHRcmgYlF7mrm/YVRn6rx2cegLuiY3VBxkkimOTWC/dVQeH336imVSuIKEGKTwiuNTPr2hswVdDSneNuXg3A==} | ||||
|     engines: {node: '>= 12.11'} | ||||
|     peerDependencies: | ||||
|       bree: '>=9.0.0' | ||||
|     dependencies: | ||||
|       bree: 9.1.2 | ||||
|       ts-node: 10.8.2_yuzmdm4dwbtqx7oi4ad7vmtwja | ||||
|       ts-node: 10.8.2_57uwcby55h6tzvkj3v5sfcgxoe | ||||
|       tsconfig-paths: 4.1.0 | ||||
|     transitivePeerDependencies: | ||||
|       - '@swc/core' | ||||
| @ -401,13 +401,13 @@ packages: | ||||
|       '@nodelib/fs.scandir': 2.1.5 | ||||
|       fastq: 1.13.0 | ||||
| 
 | ||||
|   /@playwright/test/1.24.2: | ||||
|     resolution: {integrity: sha512-Q4X224pRHw4Dtkk5PoNJplZCokLNvVbXD9wDQEMrHcEuvWpJWEQDeJ9gEwkZ3iCWSFSWBshIX177B231XW4wOQ==} | ||||
|   /@playwright/test/1.25.1: | ||||
|     resolution: {integrity: sha512-IJ4X0yOakXtwkhbnNzKkaIgXe6df7u3H3FnuhI9Jqh+CdO0e/lYQlDLYiyI9cnXK8E7UAppAWP+VqAv6VX7HQg==} | ||||
|     engines: {node: '>=14'} | ||||
|     hasBin: true | ||||
|     dependencies: | ||||
|       '@types/node': 18.6.5 | ||||
|       playwright-core: 1.24.2 | ||||
|       '@types/node': 18.7.13 | ||||
|       playwright-core: 1.25.1 | ||||
|     dev: true | ||||
| 
 | ||||
|   /@prisma/client/3.15.2_prisma@3.15.2: | ||||
| @ -534,7 +534,7 @@ packages: | ||||
|     dependencies: | ||||
|       '@types/http-cache-semantics': 4.0.1 | ||||
|       '@types/keyv': 3.1.4 | ||||
|       '@types/node': 18.7.11 | ||||
|       '@types/node': 18.7.13 | ||||
|       '@types/responselike': 1.0.0 | ||||
|     dev: false | ||||
| 
 | ||||
| @ -557,7 +557,7 @@ packages: | ||||
|   /@types/keyv/3.1.4: | ||||
|     resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} | ||||
|     dependencies: | ||||
|       '@types/node': 18.7.11 | ||||
|       '@types/node': 18.7.13 | ||||
|     dev: false | ||||
| 
 | ||||
|   /@types/lodash/4.14.182: | ||||
| @ -568,16 +568,8 @@ 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.6.5: | ||||
|     resolution: {integrity: sha512-Xjt5ZGUa5WusGZJ4WJPbOT8QOqp6nDynVFRKcUt32bOgvXEoc6o085WNkYTMO7ifAj2isEfQQ2cseE+wT6jsRw==} | ||||
|     dev: true | ||||
| 
 | ||||
|   /@types/node/18.7.11: | ||||
|     resolution: {integrity: sha512-KZhFpSLlmK/sdocfSAjqPETTMd0ug6HIMIAwkwUpU79olnZdQtMxpQP+G1wDzCH7na+FltSIhbaZuKdwZ8RDrw==} | ||||
|   /@types/node/18.7.13: | ||||
|     resolution: {integrity: sha512-46yIhxSe5xEaJZXWdIBP7GU4HDTG8/eo0qd9atdiL+lFpA03y8KS+lkTN834TWJj5767GbWv4n/P6efyTFt1Dw==} | ||||
| 
 | ||||
|   /@types/normalize-package-data/2.4.1: | ||||
|     resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} | ||||
| @ -590,17 +582,17 @@ packages: | ||||
|   /@types/responselike/1.0.0: | ||||
|     resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==} | ||||
|     dependencies: | ||||
|       '@types/node': 18.7.11 | ||||
|       '@types/node': 18.7.13 | ||||
|     dev: false | ||||
| 
 | ||||
|   /@types/sass/1.43.1: | ||||
|     resolution: {integrity: sha512-BPdoIt1lfJ6B7rw35ncdwBZrAssjcwzI5LByIrYs+tpXlj/CAkuVdRsgZDdP4lq5EjyWzwxZCqAoFyHKFwp32g==} | ||||
|     dependencies: | ||||
|       '@types/node': 18.0.3 | ||||
|       '@types/node': 18.7.13 | ||||
|     dev: true | ||||
| 
 | ||||
|   /@typescript-eslint/eslint-plugin/5.33.0_njno5y7ry2l2lcmiu4tywxkwnq: | ||||
|     resolution: {integrity: sha512-jHvZNSW2WZ31OPJ3enhLrEKvAZNyAFWZ6rx9tUwaessTc4sx9KmgMNhVcqVAl1ETnT5rU5fpXTLmY9YvC1DCNg==} | ||||
|   /@typescript-eslint/eslint-plugin/5.35.1_ktjxjibzrfqejavile4bhmzhjq: | ||||
|     resolution: {integrity: sha512-RBZZXZlI4XCY4Wzgy64vB+0slT9+yAPQRjj/HSaRwUot33xbDjF1oN9BLwOLTewoOI0jothIltZRe9uJCHf8gg==} | ||||
|     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} | ||||
|     peerDependencies: | ||||
|       '@typescript-eslint/parser': ^5.0.0 | ||||
| @ -610,37 +602,10 @@ packages: | ||||
|       typescript: | ||||
|         optional: true | ||||
|     dependencies: | ||||
|       '@typescript-eslint/parser': 5.33.0_qugx7qdu5zevzvxaiqyxfiwquq | ||||
|       '@typescript-eslint/scope-manager': 5.33.0 | ||||
|       '@typescript-eslint/type-utils': 5.33.0_qugx7qdu5zevzvxaiqyxfiwquq | ||||
|       '@typescript-eslint/utils': 5.33.0_qugx7qdu5zevzvxaiqyxfiwquq | ||||
|       debug: 4.3.4 | ||||
|       eslint: 8.21.0 | ||||
|       functional-red-black-tree: 1.0.1 | ||||
|       ignore: 5.2.0 | ||||
|       regexpp: 3.2.0 | ||||
|       semver: 7.3.7 | ||||
|       tsutils: 3.21.0_typescript@4.7.4 | ||||
|       typescript: 4.7.4 | ||||
|     transitivePeerDependencies: | ||||
|       - supports-color | ||||
|     dev: true | ||||
| 
 | ||||
|   /@typescript-eslint/eslint-plugin/5.34.0_euudt5oqhhodkyae5tf6wjmsda: | ||||
|     resolution: {integrity: sha512-eRfPPcasO39iwjlUAMtjeueRGuIrW3TQ9WseIDl7i5UWuFbf83yYaU7YPs4j8+4CxUMIsj1k+4kV+E+G+6ypDQ==} | ||||
|     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} | ||||
|     peerDependencies: | ||||
|       '@typescript-eslint/parser': ^5.0.0 | ||||
|       eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 | ||||
|       typescript: '*' | ||||
|     peerDependenciesMeta: | ||||
|       typescript: | ||||
|         optional: true | ||||
|     dependencies: | ||||
|       '@typescript-eslint/parser': 5.34.0_4rv7y5c6xz3vfxwhbrcxxi73bq | ||||
|       '@typescript-eslint/scope-manager': 5.34.0 | ||||
|       '@typescript-eslint/type-utils': 5.34.0_4rv7y5c6xz3vfxwhbrcxxi73bq | ||||
|       '@typescript-eslint/utils': 5.34.0_4rv7y5c6xz3vfxwhbrcxxi73bq | ||||
|       '@typescript-eslint/parser': 5.35.1_4rv7y5c6xz3vfxwhbrcxxi73bq | ||||
|       '@typescript-eslint/scope-manager': 5.35.1 | ||||
|       '@typescript-eslint/type-utils': 5.35.1_4rv7y5c6xz3vfxwhbrcxxi73bq | ||||
|       '@typescript-eslint/utils': 5.35.1_4rv7y5c6xz3vfxwhbrcxxi73bq | ||||
|       debug: 4.3.4 | ||||
|       eslint: 8.22.0 | ||||
|       functional-red-black-tree: 1.0.1 | ||||
| @ -653,8 +618,8 @@ packages: | ||||
|       - supports-color | ||||
|     dev: true | ||||
| 
 | ||||
|   /@typescript-eslint/parser/5.33.0_qugx7qdu5zevzvxaiqyxfiwquq: | ||||
|     resolution: {integrity: sha512-cgM5cJrWmrDV2KpvlcSkelTBASAs1mgqq+IUGKJvFxWrapHpaRy5EXPQz9YaKF3nZ8KY18ILTiVpUtbIac86/w==} | ||||
|   /@typescript-eslint/parser/5.35.1_4rv7y5c6xz3vfxwhbrcxxi73bq: | ||||
|     resolution: {integrity: sha512-XL2TBTSrh3yWAsMYpKseBYTVpvudNf69rPOWXWVBI08My2JVT5jR66eTt4IgQFHA/giiKJW5dUD4x/ZviCKyGg==} | ||||
|     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} | ||||
|     peerDependencies: | ||||
|       eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 | ||||
| @ -663,29 +628,9 @@ packages: | ||||
|       typescript: | ||||
|         optional: true | ||||
|     dependencies: | ||||
|       '@typescript-eslint/scope-manager': 5.33.0 | ||||
|       '@typescript-eslint/types': 5.33.0 | ||||
|       '@typescript-eslint/typescript-estree': 5.33.0_typescript@4.7.4 | ||||
|       debug: 4.3.4 | ||||
|       eslint: 8.21.0 | ||||
|       typescript: 4.7.4 | ||||
|     transitivePeerDependencies: | ||||
|       - supports-color | ||||
|     dev: true | ||||
| 
 | ||||
|   /@typescript-eslint/parser/5.34.0_4rv7y5c6xz3vfxwhbrcxxi73bq: | ||||
|     resolution: {integrity: sha512-SZ3NEnK4usd2CXkoV3jPa/vo1mWX1fqRyIVUQZR4As1vyp4fneknBNJj+OFtV8WAVgGf+rOHMSqQbs2Qn3nFZQ==} | ||||
|     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} | ||||
|     peerDependencies: | ||||
|       eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 | ||||
|       typescript: '*' | ||||
|     peerDependenciesMeta: | ||||
|       typescript: | ||||
|         optional: true | ||||
|     dependencies: | ||||
|       '@typescript-eslint/scope-manager': 5.34.0 | ||||
|       '@typescript-eslint/types': 5.34.0 | ||||
|       '@typescript-eslint/typescript-estree': 5.34.0_typescript@4.7.4 | ||||
|       '@typescript-eslint/scope-manager': 5.35.1 | ||||
|       '@typescript-eslint/types': 5.35.1 | ||||
|       '@typescript-eslint/typescript-estree': 5.35.1_typescript@4.7.4 | ||||
|       debug: 4.3.4 | ||||
|       eslint: 8.22.0 | ||||
|       typescript: 4.7.4 | ||||
| @ -693,24 +638,16 @@ packages: | ||||
|       - supports-color | ||||
|     dev: true | ||||
| 
 | ||||
|   /@typescript-eslint/scope-manager/5.33.0: | ||||
|     resolution: {integrity: sha512-/Jta8yMNpXYpRDl8EwF/M8It2A9sFJTubDo0ATZefGXmOqlaBffEw0ZbkbQ7TNDK6q55NPHFshGBPAZvZkE8Pw==} | ||||
|   /@typescript-eslint/scope-manager/5.35.1: | ||||
|     resolution: {integrity: sha512-kCYRSAzIW9ByEIzmzGHE50NGAvAP3wFTaZevgWva7GpquDyFPFcmvVkFJGWJJktg/hLwmys/FZwqM9EKr2u24Q==} | ||||
|     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} | ||||
|     dependencies: | ||||
|       '@typescript-eslint/types': 5.33.0 | ||||
|       '@typescript-eslint/visitor-keys': 5.33.0 | ||||
|       '@typescript-eslint/types': 5.35.1 | ||||
|       '@typescript-eslint/visitor-keys': 5.35.1 | ||||
|     dev: true | ||||
| 
 | ||||
|   /@typescript-eslint/scope-manager/5.34.0: | ||||
|     resolution: {integrity: sha512-HNvASMQlah5RsBW6L6c7IJ0vsm+8Sope/wu5sEAf7joJYWNb1LDbJipzmdhdUOnfrDFE6LR1j57x1EYVxrY4ow==} | ||||
|     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} | ||||
|     dependencies: | ||||
|       '@typescript-eslint/types': 5.34.0 | ||||
|       '@typescript-eslint/visitor-keys': 5.34.0 | ||||
|     dev: true | ||||
| 
 | ||||
|   /@typescript-eslint/type-utils/5.33.0_qugx7qdu5zevzvxaiqyxfiwquq: | ||||
|     resolution: {integrity: sha512-2zB8uEn7hEH2pBeyk3NpzX1p3lF9dKrEbnXq1F7YkpZ6hlyqb2yZujqgRGqXgRBTHWIUG3NGx/WeZk224UKlIA==} | ||||
|   /@typescript-eslint/type-utils/5.35.1_4rv7y5c6xz3vfxwhbrcxxi73bq: | ||||
|     resolution: {integrity: sha512-8xT8ljvo43Mp7BiTn1vxLXkjpw8wS4oAc00hMSB4L1/jIiYbjjnc3Qp2GAUOG/v8zsNCd1qwcqfCQ0BuishHkw==} | ||||
|     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} | ||||
|     peerDependencies: | ||||
|       eslint: '*' | ||||
| @ -719,26 +656,7 @@ packages: | ||||
|       typescript: | ||||
|         optional: true | ||||
|     dependencies: | ||||
|       '@typescript-eslint/utils': 5.33.0_qugx7qdu5zevzvxaiqyxfiwquq | ||||
|       debug: 4.3.4 | ||||
|       eslint: 8.21.0 | ||||
|       tsutils: 3.21.0_typescript@4.7.4 | ||||
|       typescript: 4.7.4 | ||||
|     transitivePeerDependencies: | ||||
|       - supports-color | ||||
|     dev: true | ||||
| 
 | ||||
|   /@typescript-eslint/type-utils/5.34.0_4rv7y5c6xz3vfxwhbrcxxi73bq: | ||||
|     resolution: {integrity: sha512-Pxlno9bjsQ7hs1pdWRUv9aJijGYPYsHpwMeCQ/Inavhym3/XaKt1ZKAA8FIw4odTBfowBdZJDMxf2aavyMDkLg==} | ||||
|     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} | ||||
|     peerDependencies: | ||||
|       eslint: '*' | ||||
|       typescript: '*' | ||||
|     peerDependenciesMeta: | ||||
|       typescript: | ||||
|         optional: true | ||||
|     dependencies: | ||||
|       '@typescript-eslint/utils': 5.34.0_4rv7y5c6xz3vfxwhbrcxxi73bq | ||||
|       '@typescript-eslint/utils': 5.35.1_4rv7y5c6xz3vfxwhbrcxxi73bq | ||||
|       debug: 4.3.4 | ||||
|       eslint: 8.22.0 | ||||
|       tsutils: 3.21.0_typescript@4.7.4 | ||||
| @ -747,18 +665,13 @@ packages: | ||||
|       - supports-color | ||||
|     dev: true | ||||
| 
 | ||||
|   /@typescript-eslint/types/5.33.0: | ||||
|     resolution: {integrity: sha512-nIMt96JngB4MYFYXpZ/3ZNU4GWPNdBbcB5w2rDOCpXOVUkhtNlG2mmm8uXhubhidRZdwMaMBap7Uk8SZMU/ppw==} | ||||
|   /@typescript-eslint/types/5.35.1: | ||||
|     resolution: {integrity: sha512-FDaujtsH07VHzG0gQ6NDkVVhi1+rhq0qEvzHdJAQjysN+LHDCKDKCBRlZFFE0ec0jKxiv0hN63SNfExy0KrbQQ==} | ||||
|     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} | ||||
|     dev: true | ||||
| 
 | ||||
|   /@typescript-eslint/types/5.34.0: | ||||
|     resolution: {integrity: sha512-49fm3xbbUPuzBIOcy2CDpYWqy/X7VBkxVN+DC21e0zIm3+61Z0NZi6J9mqPmSW1BDVk9FIOvuCFyUPjXz93sjA==} | ||||
|     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} | ||||
|     dev: true | ||||
| 
 | ||||
|   /@typescript-eslint/typescript-estree/5.33.0_typescript@4.7.4: | ||||
|     resolution: {integrity: sha512-tqq3MRLlggkJKJUrzM6wltk8NckKyyorCSGMq4eVkyL5sDYzJJcMgZATqmF8fLdsWrW7OjjIZ1m9v81vKcaqwQ==} | ||||
|   /@typescript-eslint/typescript-estree/5.35.1_typescript@4.7.4: | ||||
|     resolution: {integrity: sha512-JUqE1+VRTGyoXlDWWjm6MdfpBYVq+hixytrv1oyjYIBEOZhBCwtpp5ZSvBt4wIA1MKWlnaC2UXl2XmYGC3BoQA==} | ||||
|     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} | ||||
|     peerDependencies: | ||||
|       typescript: '*' | ||||
| @ -766,8 +679,8 @@ packages: | ||||
|       typescript: | ||||
|         optional: true | ||||
|     dependencies: | ||||
|       '@typescript-eslint/types': 5.33.0 | ||||
|       '@typescript-eslint/visitor-keys': 5.33.0 | ||||
|       '@typescript-eslint/types': 5.35.1 | ||||
|       '@typescript-eslint/visitor-keys': 5.35.1 | ||||
|       debug: 4.3.4 | ||||
|       globby: 11.1.0 | ||||
|       is-glob: 4.0.3 | ||||
| @ -778,55 +691,16 @@ packages: | ||||
|       - supports-color | ||||
|     dev: true | ||||
| 
 | ||||
|   /@typescript-eslint/typescript-estree/5.34.0_typescript@4.7.4: | ||||
|     resolution: {integrity: sha512-mXHAqapJJDVzxauEkfJI96j3D10sd567LlqroyCeJaHnu42sDbjxotGb3XFtGPYKPD9IyLjhsoULML1oI3M86A==} | ||||
|     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} | ||||
|     peerDependencies: | ||||
|       typescript: '*' | ||||
|     peerDependenciesMeta: | ||||
|       typescript: | ||||
|         optional: true | ||||
|     dependencies: | ||||
|       '@typescript-eslint/types': 5.34.0 | ||||
|       '@typescript-eslint/visitor-keys': 5.34.0 | ||||
|       debug: 4.3.4 | ||||
|       globby: 11.1.0 | ||||
|       is-glob: 4.0.3 | ||||
|       semver: 7.3.7 | ||||
|       tsutils: 3.21.0_typescript@4.7.4 | ||||
|       typescript: 4.7.4 | ||||
|     transitivePeerDependencies: | ||||
|       - supports-color | ||||
|     dev: true | ||||
| 
 | ||||
|   /@typescript-eslint/utils/5.33.0_qugx7qdu5zevzvxaiqyxfiwquq: | ||||
|     resolution: {integrity: sha512-JxOAnXt9oZjXLIiXb5ZIcZXiwVHCkqZgof0O8KPgz7C7y0HS42gi75PdPlqh1Tf109M0fyUw45Ao6JLo7S5AHw==} | ||||
|   /@typescript-eslint/utils/5.35.1_4rv7y5c6xz3vfxwhbrcxxi73bq: | ||||
|     resolution: {integrity: sha512-v6F8JNXgeBWI4pzZn36hT2HXXzoBBBJuOYvoQiaQaEEjdi5STzux3Yj8v7ODIpx36i/5s8TdzuQ54TPc5AITQQ==} | ||||
|     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} | ||||
|     peerDependencies: | ||||
|       eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 | ||||
|     dependencies: | ||||
|       '@types/json-schema': 7.0.11 | ||||
|       '@typescript-eslint/scope-manager': 5.33.0 | ||||
|       '@typescript-eslint/types': 5.33.0 | ||||
|       '@typescript-eslint/typescript-estree': 5.33.0_typescript@4.7.4 | ||||
|       eslint: 8.21.0 | ||||
|       eslint-scope: 5.1.1 | ||||
|       eslint-utils: 3.0.0_eslint@8.21.0 | ||||
|     transitivePeerDependencies: | ||||
|       - supports-color | ||||
|       - typescript | ||||
|     dev: true | ||||
| 
 | ||||
|   /@typescript-eslint/utils/5.34.0_4rv7y5c6xz3vfxwhbrcxxi73bq: | ||||
|     resolution: {integrity: sha512-kWRYybU4Rn++7lm9yu8pbuydRyQsHRoBDIo11k7eqBWTldN4xUdVUMCsHBiE7aoEkFzrUEaZy3iH477vr4xHAQ==} | ||||
|     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} | ||||
|     peerDependencies: | ||||
|       eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 | ||||
|     dependencies: | ||||
|       '@types/json-schema': 7.0.11 | ||||
|       '@typescript-eslint/scope-manager': 5.34.0 | ||||
|       '@typescript-eslint/types': 5.34.0 | ||||
|       '@typescript-eslint/typescript-estree': 5.34.0_typescript@4.7.4 | ||||
|       '@typescript-eslint/scope-manager': 5.35.1 | ||||
|       '@typescript-eslint/types': 5.35.1 | ||||
|       '@typescript-eslint/typescript-estree': 5.35.1_typescript@4.7.4 | ||||
|       eslint: 8.22.0 | ||||
|       eslint-scope: 5.1.1 | ||||
|       eslint-utils: 3.0.0_eslint@8.22.0 | ||||
| @ -835,19 +709,11 @@ packages: | ||||
|       - typescript | ||||
|     dev: true | ||||
| 
 | ||||
|   /@typescript-eslint/visitor-keys/5.33.0: | ||||
|     resolution: {integrity: sha512-/XsqCzD4t+Y9p5wd9HZiptuGKBlaZO5showwqODii5C0nZawxWLF+Q6k5wYHBrQv96h6GYKyqqMHCSTqta8Kiw==} | ||||
|   /@typescript-eslint/visitor-keys/5.35.1: | ||||
|     resolution: {integrity: sha512-cEB1DvBVo1bxbW/S5axbGPE6b7FIMAbo3w+AGq6zNDA7+NYJOIkKj/sInfTv4edxd4PxJSgdN4t6/pbvgA+n5g==} | ||||
|     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} | ||||
|     dependencies: | ||||
|       '@typescript-eslint/types': 5.33.0 | ||||
|       eslint-visitor-keys: 3.3.0 | ||||
|     dev: true | ||||
| 
 | ||||
|   /@typescript-eslint/visitor-keys/5.34.0: | ||||
|     resolution: {integrity: sha512-O1moYjOSrab0a2fUvFpsJe0QHtvTC+cR+ovYpgKrAVXzqQyc74mv76TgY6z+aEtjQE2vgZux3CQVtGryqdcOAw==} | ||||
|     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} | ||||
|     dependencies: | ||||
|       '@typescript-eslint/types': 5.34.0 | ||||
|       '@typescript-eslint/types': 5.35.1 | ||||
|       eslint-visitor-keys: 3.3.0 | ||||
|     dev: true | ||||
| 
 | ||||
| @ -2073,8 +1939,8 @@ packages: | ||||
|       delayed-stream: 1.0.0 | ||||
|     dev: false | ||||
| 
 | ||||
|   /compare-versions/4.1.3: | ||||
|     resolution: {integrity: sha512-WQfnbDcrYnGr55UwbxKiQKASnTtNnaAWVi8jZyy8NTpVAXWACSne8lMD1iaIo9AiU6mnuLvSVshCzewVuWxHUg==} | ||||
|   /compare-versions/4.1.4: | ||||
|     resolution: {integrity: sha512-FemMreK9xNyL8gQevsdRMrvO4lFCkQP7qbuktn1q8ndcNk1+0mz7lgE7b/sNvbhVgY4w6tMN1FDp6aADjqw2rw==} | ||||
|     dev: false | ||||
| 
 | ||||
|   /component-emitter/1.3.0: | ||||
| @ -2224,8 +2090,8 @@ packages: | ||||
|     resolution: {integrity: sha512-p6JFxJc3M4OTD2li2qaHkDCw9SfMw82Ldr6OC9Je1aXiGfhx2W8p3GaoeaGrPJTUN9NirTM/KTxHWMUdR1rsUg==} | ||||
|     dev: false | ||||
| 
 | ||||
|   /daisyui/2.22.0_25hquoklqeoqwmt7fwvvcyxm5e: | ||||
|     resolution: {integrity: sha512-H08aQP+Mfl2fQOmyaxd1NP54gQbr2xRUj2MmFFvfJ5EDGbthVBICDMNFKyia/zBfR58G8eTJo3CmydglM81/7Q==} | ||||
|   /daisyui/2.24.0_25hquoklqeoqwmt7fwvvcyxm5e: | ||||
|     resolution: {integrity: sha512-Fdu/4LCdTfWLWAbCuPxvnaRotEfJ+hVPgZ2kv/aUk9RZ00Yk8fGdJtIf0kXJ3IgUKOr8rCXUpfQY6DQU9usPCQ==} | ||||
|     peerDependencies: | ||||
|       autoprefixer: ^10.0.2 | ||||
|       postcss: ^8.1.6 | ||||
| @ -2984,15 +2850,6 @@ packages: | ||||
|     engines: {node: '>=12'} | ||||
|     dev: false | ||||
| 
 | ||||
|   /eslint-config-prettier/8.5.0_eslint@8.21.0: | ||||
|     resolution: {integrity: sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==} | ||||
|     hasBin: true | ||||
|     peerDependencies: | ||||
|       eslint: '>=7.0.0' | ||||
|     dependencies: | ||||
|       eslint: 8.21.0 | ||||
|     dev: true | ||||
| 
 | ||||
|   /eslint-config-prettier/8.5.0_eslint@8.22.0: | ||||
|     resolution: {integrity: sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==} | ||||
|     hasBin: true | ||||
| @ -3019,13 +2876,13 @@ packages: | ||||
|       prettier-linter-helpers: 1.0.0 | ||||
|     dev: true | ||||
| 
 | ||||
|   /eslint-plugin-svelte3/4.0.0_a7wk4ghvg4hia4trwaglu7p6cq: | ||||
|   /eslint-plugin-svelte3/4.0.0_laaqauvsmoyypsiqkozwyi2fn4: | ||||
|     resolution: {integrity: sha512-OIx9lgaNzD02+MDFNLw0GEUbuovNcglg+wnd/UY0fbZmlQSz7GlQiQ1f+yX0XvC07XPcDOnFcichqI3xCwp71g==} | ||||
|     peerDependencies: | ||||
|       eslint: '>=8.0.0' | ||||
|       svelte: ^3.2.0 | ||||
|     dependencies: | ||||
|       eslint: 8.21.0 | ||||
|       eslint: 8.22.0 | ||||
|       svelte: 3.49.0 | ||||
|     dev: true | ||||
| 
 | ||||
| @ -3045,16 +2902,6 @@ packages: | ||||
|       estraverse: 5.3.0 | ||||
|     dev: true | ||||
| 
 | ||||
|   /eslint-utils/3.0.0_eslint@8.21.0: | ||||
|     resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} | ||||
|     engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} | ||||
|     peerDependencies: | ||||
|       eslint: '>=5' | ||||
|     dependencies: | ||||
|       eslint: 8.21.0 | ||||
|       eslint-visitor-keys: 2.1.0 | ||||
|     dev: true | ||||
| 
 | ||||
|   /eslint-utils/3.0.0_eslint@8.22.0: | ||||
|     resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} | ||||
|     engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} | ||||
| @ -3075,54 +2922,6 @@ packages: | ||||
|     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} | ||||
|     dev: true | ||||
| 
 | ||||
|   /eslint/8.21.0: | ||||
|     resolution: {integrity: sha512-/XJ1+Qurf1T9G2M5IHrsjp+xrGT73RZf23xA1z5wB1ZzzEAWSZKvRwhWxTFp1rvkvCfwcvAUNAP31bhKTTGfDA==} | ||||
|     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} | ||||
|     hasBin: true | ||||
|     dependencies: | ||||
|       '@eslint/eslintrc': 1.3.0 | ||||
|       '@humanwhocodes/config-array': 0.10.4 | ||||
|       '@humanwhocodes/gitignore-to-minimatch': 1.0.2 | ||||
|       ajv: 6.12.6 | ||||
|       chalk: 4.1.2 | ||||
|       cross-spawn: 7.0.3 | ||||
|       debug: 4.3.4 | ||||
|       doctrine: 3.0.0 | ||||
|       escape-string-regexp: 4.0.0 | ||||
|       eslint-scope: 7.1.1 | ||||
|       eslint-utils: 3.0.0_eslint@8.21.0 | ||||
|       eslint-visitor-keys: 3.3.0 | ||||
|       espree: 9.3.3 | ||||
|       esquery: 1.4.0 | ||||
|       esutils: 2.0.3 | ||||
|       fast-deep-equal: 3.1.3 | ||||
|       file-entry-cache: 6.0.1 | ||||
|       find-up: 5.0.0 | ||||
|       functional-red-black-tree: 1.0.1 | ||||
|       glob-parent: 6.0.2 | ||||
|       globals: 13.15.0 | ||||
|       globby: 11.1.0 | ||||
|       grapheme-splitter: 1.0.4 | ||||
|       ignore: 5.2.0 | ||||
|       import-fresh: 3.3.0 | ||||
|       imurmurhash: 0.1.4 | ||||
|       is-glob: 4.0.3 | ||||
|       js-yaml: 4.1.0 | ||||
|       json-stable-stringify-without-jsonify: 1.0.1 | ||||
|       levn: 0.4.1 | ||||
|       lodash.merge: 4.6.2 | ||||
|       minimatch: 3.1.2 | ||||
|       natural-compare: 1.4.0 | ||||
|       optionator: 0.9.1 | ||||
|       regexpp: 3.2.0 | ||||
|       strip-ansi: 6.0.1 | ||||
|       strip-json-comments: 3.1.1 | ||||
|       text-table: 0.2.0 | ||||
|       v8-compile-cache: 2.3.0 | ||||
|     transitivePeerDependencies: | ||||
|       - supports-color | ||||
|     dev: true | ||||
| 
 | ||||
|   /eslint/8.22.0: | ||||
|     resolution: {integrity: sha512-ci4t0sz6vSRKdmkOGmprBo6fmI4PrphDFMy5JEq/fNS0gQkJM3rLmrqcp8ipMcdobH3KtUP40KniAE9W19S4wA==} | ||||
|     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} | ||||
| @ -3223,10 +3022,6 @@ packages: | ||||
|     engines: {node: '>=6'} | ||||
|     dev: false | ||||
| 
 | ||||
|   /eventemitter3/4.0.7: | ||||
|     resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} | ||||
|     dev: false | ||||
| 
 | ||||
|   /execa/6.1.0: | ||||
|     resolution: {integrity: sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==} | ||||
|     engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} | ||||
| @ -4703,6 +4498,13 @@ packages: | ||||
|     engines: {node: '>=0.10.0'} | ||||
|     dev: true | ||||
| 
 | ||||
|   /p-all/4.0.0: | ||||
|     resolution: {integrity: sha512-QXqMc8PpYu0gmNM6VcKP0uYqeI+dtvSNeaDb8ktnNjposr+nftHHCSYbj/S/oUceF6R868jw1XOxkJKUSiHgEQ==} | ||||
|     engines: {node: '>=12.20'} | ||||
|     dependencies: | ||||
|       p-map: 5.5.0 | ||||
|     dev: false | ||||
| 
 | ||||
|   /p-cancelable/3.0.0: | ||||
|     resolution: {integrity: sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==} | ||||
|     engines: {node: '>=12.20'} | ||||
| @ -4754,12 +4556,11 @@ packages: | ||||
|       p-limit: 3.1.0 | ||||
|     dev: true | ||||
| 
 | ||||
|   /p-queue/7.3.0: | ||||
|     resolution: {integrity: sha512-5fP+yVQ0qp0rEfZoDTlP2c3RYBgxvRsw30qO+VtPPc95lyvSG+x6USSh1TuLB4n96IO6I8/oXQGsTgtna4q2nQ==} | ||||
|   /p-map/5.5.0: | ||||
|     resolution: {integrity: sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==} | ||||
|     engines: {node: '>=12'} | ||||
|     dependencies: | ||||
|       eventemitter3: 4.0.7 | ||||
|       p-timeout: 5.0.2 | ||||
|       aggregate-error: 4.0.1 | ||||
|     dev: false | ||||
| 
 | ||||
|   /p-timeout/3.2.0: | ||||
| @ -4769,11 +4570,6 @@ packages: | ||||
|       p-finally: 1.0.0 | ||||
|     dev: false | ||||
| 
 | ||||
|   /p-timeout/5.0.2: | ||||
|     resolution: {integrity: sha512-sEmji9Yaq+Tw+STwsGAE56hf7gMy9p0tQfJojIAamB7WHJYJKf1qlsg9jqBWG8q9VCxKPhZaP/AcXwEoBcYQhQ==} | ||||
|     engines: {node: '>=12'} | ||||
|     dev: false | ||||
| 
 | ||||
|   /p-try/2.2.0: | ||||
|     resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} | ||||
|     engines: {node: '>=6'} | ||||
| @ -4954,8 +4750,8 @@ packages: | ||||
|       find-up: 3.0.0 | ||||
|     dev: false | ||||
| 
 | ||||
|   /playwright-core/1.24.2: | ||||
|     resolution: {integrity: sha512-zfAoDoPY/0sDLsgSgLZwWmSCevIg1ym7CppBwllguVBNiHeixZkc1AdMuYUPZC6AdEYc4CxWEyLMBTw2YcmRrA==} | ||||
|   /playwright-core/1.25.1: | ||||
|     resolution: {integrity: sha512-lSvPCmA2n7LawD2Hw7gSCLScZ+vYRkhU8xH0AapMyzwN+ojoDqhkH/KIEUxwNu2PjPoE/fcE0wLAksdOhJ2O5g==} | ||||
|     engines: {node: '>=14'} | ||||
|     hasBin: true | ||||
|     dev: true | ||||
| @ -5751,8 +5547,8 @@ packages: | ||||
|     resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} | ||||
|     engines: {node: '>= 0.4'} | ||||
| 
 | ||||
|   /svelte-check/2.8.0_vylzxgme5yisu3bsyvcau4hjtq: | ||||
|     resolution: {integrity: sha512-HRL66BxffMAZusqe5I5k26mRWQ+BobGd9Rxm3onh7ZVu0nTk8YTKJ9vu3LVPjUGLU9IX7zS+jmwPVhJYdXJ8vg==} | ||||
|   /svelte-check/2.8.1_vylzxgme5yisu3bsyvcau4hjtq: | ||||
|     resolution: {integrity: sha512-cibyY1sgt3ONIDnQbSgV2X9AJFhwEslRHNo95lijrYfPzVEvTvbmL2ohsUyqB5L7j1GhLXtQbjCJ4lZZ/fwbeQ==} | ||||
|     hasBin: true | ||||
|     peerDependencies: | ||||
|       svelte: ^3.24.0 | ||||
| @ -5988,7 +5784,7 @@ packages: | ||||
|     engines: {node: '>=0.10.0'} | ||||
|     dev: true | ||||
| 
 | ||||
|   /ts-node/10.8.2_yuzmdm4dwbtqx7oi4ad7vmtwja: | ||||
|   /ts-node/10.8.2_57uwcby55h6tzvkj3v5sfcgxoe: | ||||
|     resolution: {integrity: sha512-LYdGnoGddf1D6v8REPtIH+5iq/gTDuZqv2/UJUU7tKjuEU8xVZorBM+buCGNjj+pGEud+sOoM4CX3/YzINpENA==} | ||||
|     hasBin: true | ||||
|     peerDependencies: | ||||
| @ -6007,7 +5803,7 @@ packages: | ||||
|       '@tsconfig/node12': 1.0.9 | ||||
|       '@tsconfig/node14': 1.0.1 | ||||
|       '@tsconfig/node16': 1.0.2 | ||||
|       '@types/node': 18.7.11 | ||||
|       '@types/node': 18.7.13 | ||||
|       acorn: 8.8.0 | ||||
|       acorn-walk: 8.2.0 | ||||
|       arg: 4.1.3 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user