From d64bb1f2b7615ff3a2d574930861e8fd25ed593c Mon Sep 17 00:00:00 2001 From: Nicolas Meienberger Date: Thu, 28 Jul 2022 19:46:12 +0200 Subject: [PATCH] Initial commit --- .github/workflows/ci.yml | 41 + .gitignore | 1 + .husky/pre-commit | 4 + apps/__tests__/apps.test.ts | 176 ++ apps/adguard/config.json | 16 + apps/adguard/data/conf/AdGuardHome.yaml | 131 + apps/adguard/docker-compose.yml | 16 + apps/adguard/metadata/description.md | 6 + apps/anonaddy/config.json | 47 + apps/anonaddy/docker-compose.yml | 80 + apps/anonaddy/metadata/description.md | 0 apps/calibre-web/config.json | 13 + apps/calibre-web/data/books/metadata.db | Bin 0 -> 356352 bytes apps/calibre-web/docker-compose.yml | 17 + apps/calibre-web/metadata/description.md | 7 + apps/code-server/config.json | 22 + apps/code-server/docker-compose.yml | 19 + apps/code-server/metadata/description.md | 7 + apps/docker-compose.common.yml | 6 + apps/filebrowser/config.json | 14 + apps/filebrowser/data/config/settings.json | 8 + apps/filebrowser/docker-compose.yml | 17 + apps/filebrowser/metadata/description.md | 12 + apps/filerun/config.json | 12 + apps/filerun/docker-compose.yml | 38 + apps/filerun/metadata/description.md | 0 apps/firefly-iii/config.json | 35 + apps/firefly-iii/docker-compose.yml | 59 + apps/firefly-iii/metadata/description.md | 26 + apps/freshrss/config.json | 13 + apps/freshrss/docker-compose.yml | 25 + apps/freshrss/metadata/description.md | 27 + apps/gitea/config.json | 13 + apps/gitea/data/gitea/gitea/conf/app.ini | 88 + apps/gitea/docker-compose.yml | 37 + apps/gitea/metadata/description.md | 5 + apps/homarr/config.json | 14 + apps/homarr/docker-compose.yml | 12 + apps/homarr/metadata/description.md | 10 + apps/homeassistant/config.json | 13 + apps/homeassistant/docker-compose.yml | 13 + apps/homeassistant/metadata/description.md | 7 + apps/invidious/config.json | 13 + apps/invidious/data/init/init-invidious-db.sh | 12 + apps/invidious/data/init/sql/annotations.sql | 12 + .../data/init/sql/channel_videos.sql | 30 + apps/invidious/data/init/sql/channels.sql | 25 + apps/invidious/data/init/sql/nonces.sql | 22 + .../data/init/sql/playlist_videos.sql | 19 + apps/invidious/data/init/sql/playlists.sql | 29 + apps/invidious/data/init/sql/session_ids.sql | 23 + apps/invidious/data/init/sql/users.sql | 29 + apps/invidious/data/init/sql/videos.sql | 23 + apps/invidious/data/postgres/.gitkeep | 0 apps/invidious/data/sql/.gitkeep | 0 apps/invidious/docker-compose.arm.yml | 47 + apps/invidious/docker-compose.yml | 48 + apps/invidious/metadata/description.md | 27 + apps/jackett/config.json | 13 + apps/jackett/docker-compose.yml | 20 + apps/jackett/metadata/description.md | 5 + apps/jellyfin/config.json | 13 + apps/jellyfin/data/config/.gitkeep | 0 apps/jellyfin/docker-compose.yml | 18 + apps/jellyfin/metadata/description.md | 5 + apps/joplin/README.md | 13 + apps/joplin/config.json | 14 + apps/joplin/docker-compose.yml | 38 + apps/joplin/metadata/description.md | 17 + apps/libreddit/config.json | 13 + apps/libreddit/docker-compose.arm.yml | 12 + apps/libreddit/docker-compose.yml | 12 + apps/libreddit/metadata/description.md | 12 + apps/mealie/config.json | 13 + apps/mealie/docker-compose.yml | 15 + apps/mealie/metadata/description.md | 9 + apps/n8n/config.json | 14 + apps/n8n/docker-compose.yml | 36 + apps/n8n/metadata/description.md | 6 + apps/nextcloud/config.json | 30 + apps/nextcloud/data/nextcloud/.gitkeep | 0 apps/nextcloud/data/redis/.gitkeep | 0 apps/nextcloud/docker-compose.yml | 67 + apps/nextcloud/metadata/description.md | 29 + apps/nitter/config.json | 13 + apps/nitter/data/nitter.conf | 45 + apps/nitter/docker-compose.yml | 24 + apps/nitter/metadata/description.md | 16 + apps/nodered/config.json | 13 + apps/nodered/data/settings.js | 499 ++++ apps/nodered/docker-compose.yml | 13 + apps/nodered/metadata/description.md | 6 + apps/overseerr/config.json | 13 + apps/overseerr/docker-compose.yml | 16 + apps/overseerr/metadata/description.md | 14 + apps/photoprism/config.json | 22 + apps/photoprism/docker-compose.yml | 59 + apps/photoprism/metadata/description.md | 9 + apps/pihole/config.json | 25 + apps/pihole/data/unbound/a-records.conf | 6 + apps/pihole/data/unbound/root.hints | 92 + apps/pihole/data/unbound/root.key | 9 + apps/pihole/data/unbound/unbound.conf | 136 + apps/pihole/docker-compose.yml | 39 + apps/pihole/metadata/description.md | 14 + apps/plex/config.json | 14 + apps/plex/docker-compose.yml | 15 + apps/plex/metadata/description.md | 5 + apps/portainer/config.json | 13 + apps/portainer/docker-compose.yml | 14 + apps/portainer/metadata/description.md | 6 + apps/prowlarr/config.json | 13 + apps/prowlarr/docker-compose.yml | 16 + apps/prowlarr/metadata/description.md | 18 + apps/radarr/config.json | 13 + apps/radarr/docker-compose.yml | 20 + apps/radarr/metadata/description.md | 23 + apps/readarr/config.json | 13 + apps/readarr/docker-compose.yml | 20 + apps/readarr/metadata/description.md | 22 + apps/resilio-sync/config.json | 13 + apps/resilio-sync/docker-compose.yml | 18 + apps/resilio-sync/metadata/description.md | 3 + apps/simple-torrent/config.json | 11 + apps/simple-torrent/docker-compose.yml | 25 + apps/simple-torrent/metadata/description.md | 0 apps/sonarr/config.json | 13 + apps/sonarr/docker-compose.yml | 20 + apps/sonarr/metadata/description.md | 17 + apps/syncthing/config.json | 14 + apps/syncthing/data/.gitkeep | 0 apps/syncthing/docker-compose.yml | 21 + apps/syncthing/metadata/description.md | 38 + apps/tailscale/config.json | 14 + apps/tailscale/docker-compose.yml | 14 + apps/tailscale/metadata/description.md | 7 + apps/tautulli/config.json | 13 + apps/tautulli/docker-compose.yml | 16 + apps/tautulli/metadata/description.md | 19 + apps/transmission/config.json | 33 + apps/transmission/data/config/.gitkeep | 0 apps/transmission/docker-compose.yml | 27 + apps/transmission/metadata/description.md | 9 + apps/ttyd/config.json | 28 + apps/ttyd/docker-compose.yml | 0 apps/ttyd/metadata/description.md | 0 apps/vaultwarden/config.json | 22 + apps/vaultwarden/docker-compose.yml | 16 + apps/vaultwarden/metadata/description.md | 13 + apps/wg-easy/config.json | 37 + apps/wg-easy/data/.gitkeep | 0 apps/wg-easy/docker-compose.yml | 35 + apps/wg-easy/metadata/description.md | 14 + apps/your-spotify/config.json | 28 + apps/your-spotify/docker-compose.yml | 46 + apps/your-spotify/metadata/description.md | 19 + jest.config.js | 6 + package.json | 29 + pnpm-lock.yaml | 2338 +++++++++++++++++ tsconfig.json | 19 + 160 files changed, 6193 insertions(+) create mode 100644 .github/workflows/ci.yml create mode 100644 .gitignore create mode 100755 .husky/pre-commit create mode 100644 apps/__tests__/apps.test.ts create mode 100644 apps/adguard/config.json create mode 100644 apps/adguard/data/conf/AdGuardHome.yaml create mode 100644 apps/adguard/docker-compose.yml create mode 100644 apps/adguard/metadata/description.md create mode 100644 apps/anonaddy/config.json create mode 100644 apps/anonaddy/docker-compose.yml create mode 100644 apps/anonaddy/metadata/description.md create mode 100644 apps/calibre-web/config.json create mode 100644 apps/calibre-web/data/books/metadata.db create mode 100644 apps/calibre-web/docker-compose.yml create mode 100644 apps/calibre-web/metadata/description.md create mode 100644 apps/code-server/config.json create mode 100644 apps/code-server/docker-compose.yml create mode 100644 apps/code-server/metadata/description.md create mode 100644 apps/docker-compose.common.yml create mode 100644 apps/filebrowser/config.json create mode 100644 apps/filebrowser/data/config/settings.json create mode 100644 apps/filebrowser/docker-compose.yml create mode 100644 apps/filebrowser/metadata/description.md create mode 100644 apps/filerun/config.json create mode 100644 apps/filerun/docker-compose.yml create mode 100644 apps/filerun/metadata/description.md create mode 100644 apps/firefly-iii/config.json create mode 100644 apps/firefly-iii/docker-compose.yml create mode 100644 apps/firefly-iii/metadata/description.md create mode 100644 apps/freshrss/config.json create mode 100644 apps/freshrss/docker-compose.yml create mode 100644 apps/freshrss/metadata/description.md create mode 100644 apps/gitea/config.json create mode 100644 apps/gitea/data/gitea/gitea/conf/app.ini create mode 100644 apps/gitea/docker-compose.yml create mode 100644 apps/gitea/metadata/description.md create mode 100644 apps/homarr/config.json create mode 100644 apps/homarr/docker-compose.yml create mode 100644 apps/homarr/metadata/description.md create mode 100644 apps/homeassistant/config.json create mode 100644 apps/homeassistant/docker-compose.yml create mode 100644 apps/homeassistant/metadata/description.md create mode 100644 apps/invidious/config.json create mode 100644 apps/invidious/data/init/init-invidious-db.sh create mode 100644 apps/invidious/data/init/sql/annotations.sql create mode 100644 apps/invidious/data/init/sql/channel_videos.sql create mode 100644 apps/invidious/data/init/sql/channels.sql create mode 100644 apps/invidious/data/init/sql/nonces.sql create mode 100644 apps/invidious/data/init/sql/playlist_videos.sql create mode 100644 apps/invidious/data/init/sql/playlists.sql create mode 100644 apps/invidious/data/init/sql/session_ids.sql create mode 100644 apps/invidious/data/init/sql/users.sql create mode 100644 apps/invidious/data/init/sql/videos.sql create mode 100644 apps/invidious/data/postgres/.gitkeep create mode 100644 apps/invidious/data/sql/.gitkeep create mode 100644 apps/invidious/docker-compose.arm.yml create mode 100644 apps/invidious/docker-compose.yml create mode 100644 apps/invidious/metadata/description.md create mode 100644 apps/jackett/config.json create mode 100644 apps/jackett/docker-compose.yml create mode 100644 apps/jackett/metadata/description.md create mode 100644 apps/jellyfin/config.json create mode 100644 apps/jellyfin/data/config/.gitkeep create mode 100644 apps/jellyfin/docker-compose.yml create mode 100644 apps/jellyfin/metadata/description.md create mode 100644 apps/joplin/README.md create mode 100644 apps/joplin/config.json create mode 100644 apps/joplin/docker-compose.yml create mode 100644 apps/joplin/metadata/description.md create mode 100644 apps/libreddit/config.json create mode 100644 apps/libreddit/docker-compose.arm.yml create mode 100644 apps/libreddit/docker-compose.yml create mode 100644 apps/libreddit/metadata/description.md create mode 100644 apps/mealie/config.json create mode 100644 apps/mealie/docker-compose.yml create mode 100644 apps/mealie/metadata/description.md create mode 100644 apps/n8n/config.json create mode 100644 apps/n8n/docker-compose.yml create mode 100644 apps/n8n/metadata/description.md create mode 100644 apps/nextcloud/config.json create mode 100644 apps/nextcloud/data/nextcloud/.gitkeep create mode 100644 apps/nextcloud/data/redis/.gitkeep create mode 100644 apps/nextcloud/docker-compose.yml create mode 100644 apps/nextcloud/metadata/description.md create mode 100644 apps/nitter/config.json create mode 100644 apps/nitter/data/nitter.conf create mode 100644 apps/nitter/docker-compose.yml create mode 100644 apps/nitter/metadata/description.md create mode 100644 apps/nodered/config.json create mode 100644 apps/nodered/data/settings.js create mode 100644 apps/nodered/docker-compose.yml create mode 100644 apps/nodered/metadata/description.md create mode 100644 apps/overseerr/config.json create mode 100644 apps/overseerr/docker-compose.yml create mode 100644 apps/overseerr/metadata/description.md create mode 100644 apps/photoprism/config.json create mode 100644 apps/photoprism/docker-compose.yml create mode 100644 apps/photoprism/metadata/description.md create mode 100644 apps/pihole/config.json create mode 100644 apps/pihole/data/unbound/a-records.conf create mode 100644 apps/pihole/data/unbound/root.hints create mode 100644 apps/pihole/data/unbound/root.key create mode 100644 apps/pihole/data/unbound/unbound.conf create mode 100644 apps/pihole/docker-compose.yml create mode 100644 apps/pihole/metadata/description.md create mode 100644 apps/plex/config.json create mode 100644 apps/plex/docker-compose.yml create mode 100644 apps/plex/metadata/description.md create mode 100644 apps/portainer/config.json create mode 100644 apps/portainer/docker-compose.yml create mode 100644 apps/portainer/metadata/description.md create mode 100644 apps/prowlarr/config.json create mode 100644 apps/prowlarr/docker-compose.yml create mode 100644 apps/prowlarr/metadata/description.md create mode 100644 apps/radarr/config.json create mode 100644 apps/radarr/docker-compose.yml create mode 100644 apps/radarr/metadata/description.md create mode 100644 apps/readarr/config.json create mode 100644 apps/readarr/docker-compose.yml create mode 100644 apps/readarr/metadata/description.md create mode 100644 apps/resilio-sync/config.json create mode 100644 apps/resilio-sync/docker-compose.yml create mode 100644 apps/resilio-sync/metadata/description.md create mode 100644 apps/simple-torrent/config.json create mode 100644 apps/simple-torrent/docker-compose.yml create mode 100644 apps/simple-torrent/metadata/description.md create mode 100644 apps/sonarr/config.json create mode 100644 apps/sonarr/docker-compose.yml create mode 100644 apps/sonarr/metadata/description.md create mode 100644 apps/syncthing/config.json create mode 100644 apps/syncthing/data/.gitkeep create mode 100644 apps/syncthing/docker-compose.yml create mode 100644 apps/syncthing/metadata/description.md create mode 100644 apps/tailscale/config.json create mode 100644 apps/tailscale/docker-compose.yml create mode 100644 apps/tailscale/metadata/description.md create mode 100644 apps/tautulli/config.json create mode 100644 apps/tautulli/docker-compose.yml create mode 100644 apps/tautulli/metadata/description.md create mode 100644 apps/transmission/config.json create mode 100644 apps/transmission/data/config/.gitkeep create mode 100644 apps/transmission/docker-compose.yml create mode 100644 apps/transmission/metadata/description.md create mode 100644 apps/ttyd/config.json create mode 100644 apps/ttyd/docker-compose.yml create mode 100644 apps/ttyd/metadata/description.md create mode 100644 apps/vaultwarden/config.json create mode 100644 apps/vaultwarden/docker-compose.yml create mode 100644 apps/vaultwarden/metadata/description.md create mode 100644 apps/wg-easy/config.json create mode 100644 apps/wg-easy/data/.gitkeep create mode 100644 apps/wg-easy/docker-compose.yml create mode 100644 apps/wg-easy/metadata/description.md create mode 100644 apps/your-spotify/config.json create mode 100644 apps/your-spotify/docker-compose.yml create mode 100644 apps/your-spotify/metadata/description.md create mode 100644 jest.config.js create mode 100644 package.json create mode 100644 pnpm-lock.yaml create mode 100644 tsconfig.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..123f6ecd --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,41 @@ +name: Tipi CI +on: + push: + +jobs: + ci: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Install Node.js + uses: actions/setup-node@v3 + with: + node-version: 16 + + - uses: pnpm/action-setup@v2.0.1 + name: Install pnpm + id: pnpm-install + with: + version: 7 + run_install: false + + - name: Get pnpm store directory + id: pnpm-cache + run: | + echo "::set-output name=pnpm_cache_dir::$(pnpm store path)" + + - uses: actions/cache@v3 + name: Setup pnpm cache + with: + path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + + - name: Install dependencies + run: pnpm install + + - name: Run global tests + run: pnpm test \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..c2658d7d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules/ diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 00000000..879e9351 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +npm run test diff --git a/apps/__tests__/apps.test.ts b/apps/__tests__/apps.test.ts new file mode 100644 index 00000000..9e96e89d --- /dev/null +++ b/apps/__tests__/apps.test.ts @@ -0,0 +1,176 @@ +import fs from "fs"; +import jsyaml from "js-yaml"; + +interface AppConfig { + id: string; + port: number; + categories: string[]; + requirements?: { + ports?: number[]; + }; + name: string; + description: string; + version: string; + image: string; + short_desc: string; + author: string; + source: string; + available: boolean; +} + +const networkExceptions = ["pihole", "tailscale", "homeassistant", "plex"]; +const getAppConfigs = (): AppConfig[] => { + const apps: AppConfig[] = []; + + const appsDir = fs.readdirSync("./apps"); + + appsDir.forEach((app) => { + const path = `./apps/${app}/config.json`; + + if (fs.existsSync(path)) { + const configFile = fs.readFileSync(path).toString(); + + try { + const config: AppConfig = JSON.parse(configFile); + if (config.available) { + apps.push(config); + } + } catch (e) { + console.error("Error parsing config file", app); + } + } + }); + + return apps; +}; + +describe("App configs", () => { + it("Get app config should return at least one app", () => { + const apps = getAppConfigs(); + + expect(apps.length).toBeGreaterThan(0); + }); + + it("Each app should have an id", () => { + const apps = getAppConfigs(); + + apps.forEach((app) => { + expect(app.id).toBeDefined(); + }); + }); + + it("Each app should have a md description", () => { + const apps = getAppConfigs(); + + apps.forEach((app) => { + const path = `./apps/${app.id}/metadata/description.md`; + + if (fs.existsSync(path)) { + const description = fs.readFileSync(path).toString(); + expect(description).toBeDefined(); + } else { + console.error(`Missing description for app ${app.id}`); + expect(true).toBe(false); + } + }); + }); + + it("Each app should have categories defined as an array", () => { + const apps = getAppConfigs(); + + apps.forEach((app) => { + expect(app.categories).toBeDefined(); + expect(app.categories).toBeInstanceOf(Array); + }); + }); + + it("Each app should have a name", () => { + const apps = getAppConfigs(); + + apps.forEach((app) => { + expect(app.name).toBeDefined(); + }); + }); + + it("Each app should have a description", () => { + const apps = getAppConfigs(); + + apps.forEach((app) => { + expect(app.description).toBeDefined(); + }); + }); + + it("Each app should have a port", () => { + const apps = getAppConfigs(); + + apps.forEach((app) => { + expect(app.port).toBeDefined(); + expect(app.port).toBeGreaterThan(999); + expect(app.port).toBeLessThan(65535); + }); + }); + + it("Each app should have a different port", () => { + const appConfigs = getAppConfigs(); + const ports = appConfigs.map((app) => app.port); + expect(new Set(ports).size).toBe(appConfigs.length); + }); + + it("Each app should have a unique id", () => { + const appConfigs = getAppConfigs(); + const ids = appConfigs.map((app) => app.id); + expect(new Set(ids).size).toBe(appConfigs.length); + }); + + it("Each app should have a docker-compose file beside it", () => { + const apps = getAppConfigs(); + + apps.forEach((app) => { + expect(fs.existsSync(`./apps/${app.id}/docker-compose.yml`)).toBe(true); + }); + }); + + it("Each app should have a container name equals to its id", () => { + const apps = getAppConfigs(); + + apps.forEach((app) => { + const dockerComposeFile = fs + .readFileSync(`./apps/${app.id}/docker-compose.yml`) + .toString(); + + const dockerCompose: any = jsyaml.load(dockerComposeFile); + + if (!dockerCompose.services[app.id]) { + console.error(app.id); + } + + expect(dockerCompose.services[app.id]).toBeDefined(); + expect(dockerCompose.services[app.id].container_name).toBe(app.id); + }); + }); + + it("Each app should have network tipi_main_network", () => { + const apps = getAppConfigs(); + + apps.forEach((app) => { + if (!networkExceptions.includes(app.id)) { + const dockerComposeFile = fs + .readFileSync(`./apps/${app.id}/docker-compose.yml`) + .toString(); + + const dockerCompose: any = jsyaml.load(dockerComposeFile); + + expect(dockerCompose.services[app.id]).toBeDefined(); + + if (!dockerCompose.services[app.id].networks) { + console.error(app.id); + } + + expect(dockerCompose.services[app.id].networks).toBeDefined(); + expect(dockerCompose.services[app.id].networks).toStrictEqual([ + "tipi_main_network", + ]); + } + }); + }); +}); diff --git a/apps/adguard/config.json b/apps/adguard/config.json new file mode 100644 index 00000000..91ef7290 --- /dev/null +++ b/apps/adguard/config.json @@ -0,0 +1,16 @@ +{ + "name": "Adguard", + "available": true, + "port": 8104, + "id": "adguard", + "categories": ["network", "security"], + "description": "Adguard is the best way to get rid of annoying ads and online tracking and protect your computer from malware. Make your web surfing fast, safe and ad-free.", + "short_desc": "World's most advanced adblocker!", + "author": "AdguardTeam", + "source": "https://github.com/AdguardTeam", + "image": "/logos/apps/adguard.jpg", + "requirements": { + "ports": [53] + }, + "form_fields": [] +} diff --git a/apps/adguard/data/conf/AdGuardHome.yaml b/apps/adguard/data/conf/AdGuardHome.yaml new file mode 100644 index 00000000..4fcefdb2 --- /dev/null +++ b/apps/adguard/data/conf/AdGuardHome.yaml @@ -0,0 +1,131 @@ +bind_host: 0.0.0.0 +bind_port: 80 +beta_bind_port: 0 +users: [] +auth_attempts: 5 +block_auth_min: 15 +http_proxy: "" +language: "" +debug_pprof: false +web_session_ttl: 720 +dns: + bind_hosts: + - 0.0.0.0 + port: 53 + statistics_interval: 1 + querylog_enabled: true + querylog_file_enabled: true + querylog_interval: 2160h + querylog_size_memory: 1000 + anonymize_client_ip: false + protection_enabled: true + blocking_mode: default + blocking_ipv4: "" + blocking_ipv6: "" + blocked_response_ttl: 10 + parental_block_host: family-block.dns.adguard.com + safebrowsing_block_host: standard-block.dns.adguard.com + ratelimit: 20 + ratelimit_whitelist: [] + refuse_any: true + upstream_dns: + - https://dns10.quad9.net/dns-query + upstream_dns_file: "" + bootstrap_dns: + - 9.9.9.10 + - 149.112.112.10 + - 2620:fe::10 + - 2620:fe::fe:10 + all_servers: false + fastest_addr: false + fastest_timeout: 1s + allowed_clients: [] + disallowed_clients: [] + blocked_hosts: + - version.bind + - id.server + - hostname.bind + trusted_proxies: + - 127.0.0.0/8 + - ::1/128 + cache_size: 4194304 + cache_ttl_min: 0 + cache_ttl_max: 0 + cache_optimistic: false + bogus_nxdomain: [] + aaaa_disabled: false + enable_dnssec: false + edns_client_subnet: false + max_goroutines: 300 + ipset: [] + filtering_enabled: true + filters_update_interval: 24 + parental_enabled: false + safesearch_enabled: false + safebrowsing_enabled: false + safebrowsing_cache_size: 1048576 + safesearch_cache_size: 1048576 + parental_cache_size: 1048576 + cache_time: 30 + rewrites: [] + blocked_services: [] + upstream_timeout: 10s + local_domain_name: lan + resolve_clients: true + use_private_ptr_resolvers: true + local_ptr_upstreams: [] +tls: + enabled: false + server_name: "" + force_https: false + port_https: 443 + port_dns_over_tls: 853 + port_dns_over_quic: 784 + port_dnscrypt: 0 + dnscrypt_config_file: "" + allow_unencrypted_doh: false + strict_sni_check: false + certificate_chain: "" + private_key: "" + certificate_path: "" + private_key_path: "" +filters: +- enabled: true + url: https://adguardteam.github.io/AdGuardSDNSFilter/Filters/filter.txt + name: AdGuard DNS filter + id: 1 +- enabled: false + url: https://adaway.org/hosts.txt + name: AdAway Default Blocklist + id: 2 +whitelist_filters: [] +user_rules: [] +dhcp: + enabled: false + interface_name: "" + dhcpv4: + gateway_ip: "" + subnet_mask: "" + range_start: "" + range_end: "" + lease_duration: 86400 + icmp_timeout_msec: 1000 + options: [] + dhcpv6: + range_start: "" + lease_duration: 86400 + ra_slaac_only: false + ra_allow_slaac: false +clients: [] +log_compress: false +log_localtime: false +log_max_backups: 0 +log_max_size: 100 +log_max_age: 3 +log_file: "" +verbose: false +os: + group: "" + user: "" + rlimit_nofile: 0 +schema_version: 12 diff --git a/apps/adguard/docker-compose.yml b/apps/adguard/docker-compose.yml new file mode 100644 index 00000000..f5aeb613 --- /dev/null +++ b/apps/adguard/docker-compose.yml @@ -0,0 +1,16 @@ + +version: "3.7" +services: + adguard: + image: adguard/adguardhome:v0.107.7 + container_name: adguard + volumes: + - "${APP_DATA_DIR}/data/work:/opt/adguardhome/work" + - "${APP_DATA_DIR}/data/conf:/opt/adguardhome/conf" + restart: unless-stopped + networks: + - tipi_main_network + ports: + - 53:53/tcp + - 53:53/udp + - ${APP_PORT}:80 diff --git a/apps/adguard/metadata/description.md b/apps/adguard/metadata/description.md new file mode 100644 index 00000000..3efa30f5 --- /dev/null +++ b/apps/adguard/metadata/description.md @@ -0,0 +1,6 @@ +## AdGuard Home is a network-wide software for blocking ads & tracking. + +After you set it up, it'll cover ALL your home devices, and you don't need any client-side software for that. +It operates as a DNS server that re-routes tracking domains to a "black hole", thus preventing your devices from connecting to those servers. It's based on software we use for our public AdGuard DNS servers -- both share a lot of common code. + +![Screenshot](https://cdn.adguard.com/public/Adguard/Common/adguard_home.gif) diff --git a/apps/anonaddy/config.json b/apps/anonaddy/config.json new file mode 100644 index 00000000..d71bca69 --- /dev/null +++ b/apps/anonaddy/config.json @@ -0,0 +1,47 @@ +{ + "name": "Anonaddy", + "port": 8084, + "available": false, + "categories": ["utilities"], + "id": "anonaddy", + "description": "", + "short_desc": "Anonymous email forwarding", + "author": "", + "source": "https://github.com/anonaddy/anonaddy", + "image": "https://avatars.githubusercontent.com/u/51450862?s=200&v=4", + "requirements": { + "ports": [25] + }, + "form_fields": [ + { + "type": "text", + "label": "Username", + "required": true, + "env_variable": "ANONADDY_USERNAME" + }, + { + "type": "text", + "label": "App key", + "hint": "Application key for encrypter service. Generate one with : echo \"base64:$(openssl rand -base64 32)\"", + "required": true, + "env_variable": "ANONADDY_KEY" + }, + { + "type": "fqdn", + "label": "Your email domain (eg. example.com)", + "max": 50, + "min": 3, + "required": true, + "env_variable": "ANONADDY_DOMAIN" + }, + { + "type": "text", + "label": "App secret", + "hint": "Long random string used when hashing data for the anonymous replies", + "max": 50, + "min": 3, + "required": true, + "env_variable": "ANONADDY_SECRET" + } + ] +} diff --git a/apps/anonaddy/docker-compose.yml b/apps/anonaddy/docker-compose.yml new file mode 100644 index 00000000..d66b56d3 --- /dev/null +++ b/apps/anonaddy/docker-compose.yml @@ -0,0 +1,80 @@ +version: "3.7" +services: + db: + image: mariadb:10.5 + container_name: db-anonaddy + command: + - "mysqld" + - "--character-set-server=utf8mb4" + - "--collation-server=utf8mb4_unicode_ci" + volumes: + - "${APP_DATA_DIR}/db:/var/lib/mysql" + environment: + MARIADB_DATABASE: anonaddy + MARIADB_USER: anonaddy + MARIADB_ROOT_PASSWORD: anonaddy + MARIADB_PASSWORD: anonaddy + restart: unless-stopped + networks: + - tipi_main_network + + redis: + image: redis:4.0-alpine + container_name: redis-anonaddy + restart: unless-stopped + networks: + - tipi_main_network + + anonaddy: + image: anonaddy/anonaddy:0.11.1 + container_name: anonaddy + ports: + - 25:25 + - ${APP_PORT}:8000 + depends_on: + - db + - redis + volumes: + - "${APP_DATA_DIR}/data:/data" + environment: + TZ: ${TZ} + DB_HOST: db-anonaddy + DB_PASSWORD: anonaddy + REDIS_HOST: redis-anonaddy + APP_KEY: ${ANONADDY_KEY} + ANONADDY_DOMAIN: ${ANONADDY_DOMAIN} + ANONADDY_SECRET: ${ANONADDY_SECRET} + ANONADDY_ADMIN_USERNAME: ${ANONADDY_USERNAME} + restart: unless-stopped + networks: + - tipi_main_network + # labels: + # traefik.enable: true + # traefik.http.routers.anonaddy.rule: Host(`anonaddy.tipi.home`) + # traefik.http.routers.anonaddy.tls: true + # traefik.http.routers.anonaddy.entrypoints: websecure + # traefik.http.routers.anonaddy.service: anonaddy + # traefik.http.services.anonaddy.loadbalancer.server.port: 8000 + # labels: + # traefik.enable: true + # traefik.http.routers.anonaddy.rule: PathPrefix(`/anonaddy`) + + # # Redirect to ending / + # traefik.http.middlewares.anonaddy-redirect.redirectregex.regex: ^(http:\/\/(\[[\w:.]+\]|[\w\._-]+)(:\d+)?)\/anonaddy$$ + # traefik.http.middlewares.anonaddy-redirect.redirectregex.replacement: $${1}/anonaddy/ + + # # Strip /anonaddy/ from URL + # traefik.http.middlewares.anonaddy-stripprefix.stripprefixregex.regex: (/anonaddy/|/anonaddy) + + # traefik.http.middlewares.anonaddy-headers.headers.customrequestheaders.Host: $$host + # traefik.http.middlewares.anonaddy-headers.headers.customrequestheaders.X-Forwarded-Proto: $$scheme + # traefik.http.middlewares.anonaddy-headers.headers.customrequestheaders.X-Forwarded-For: $$proxy_add_x_forwarded_for + # traefik.http.middlewares.anonaddy-headers.headers.customrequestheaders.X-Real-IP: $$remote_addr + # traefik.http.middlewares.anonaddy-headers.headers.customrequestheaders.X-Frame-Options: "SAMEORIGIN" + + # # Apply middleware + # traefik.http.routers.anonaddy.middlewares: anonaddy-redirect, anonaddy-stripprefix, anonaddy-headers + + # traefik.http.routers.anonaddy.entrypoints: http + # traefik.http.routers.anonaddy.service: anonaddy + # traefik.http.services.anonaddy.loadbalancer.server.port: 8000 diff --git a/apps/anonaddy/metadata/description.md b/apps/anonaddy/metadata/description.md new file mode 100644 index 00000000..e69de29b diff --git a/apps/calibre-web/config.json b/apps/calibre-web/config.json new file mode 100644 index 00000000..2680eca4 --- /dev/null +++ b/apps/calibre-web/config.json @@ -0,0 +1,13 @@ +{ + "name": "Calibre-Web - EBook Reader", + "available": true, + "port": 8100, + "id": "calibre-web", + "categories": ["books"], + "description": "On the initial setup screen, enter /books as your calibre library location. \n Default admin login: Username: admin Password: admin123", + "short_desc": "Calibre-web is a web app providing a clean interface for browsing, reading and downloading eBooks using an existing Calibre database.", + "author": "https://github.com/janeczku/", + "source": "https://github.com/janeczku/calibre-web", + "image": "/logos/apps/calibre-web.jpg", + "form_fields": [] +} diff --git a/apps/calibre-web/data/books/metadata.db b/apps/calibre-web/data/books/metadata.db new file mode 100644 index 0000000000000000000000000000000000000000..c32a5867d017c11ffa0dae52f6d60634439c7c2d GIT binary patch literal 356352 zcmeI5du$v>p5JFgYGz1@9(!%xte2~GiCV8XD^lW!qGZdaWr`ZnwD^$tu4#2vLEoeFzm#$v_OUN={@PEE)0{-|CoF#<`HSSw zlYf=`i{$@I{`cgc^2D%;NCN>7009sH0T2KI5C8!X009sH0T5`5zF@wqgUvkuV18pdQa0oUr6@QztQA>i_m{~fdB}A00@8p2!H?xfB*=900@8p2pmWP zBzin@Hr?}PWwlHe@~cKEXH@0;AYsYfRIh0A|3v6Nyg&d1KmY_l00ck)1V8`;KmY_l z00a&Pfu}ppcKLP#`1Aj-M3P@Q9121U5C8!X009sH0T2KI5C8!X009u#K7kD_nv7hy zFmtUd-P5zswbV6pr)K8Y$bzj`Z8BLi3r1bS#o>#?L&KMbE?y?XBUdjDUmbn<{L2?# z8qHifH#~fGcz8H7oEdWd5$BpF@eKcidEYAiLR~9lAd}85k6tbmM)E_Mi;J!rB>!eV_ZNKw0T2KI5C8!X009sH0T2KI5C8!X z*cpM&XlJCWi+}(B7m?&Ib|wY2KmY_l00ck)1V8`;KmY_l00ck)1okz7&d#o`F8=)g z(@65uece}d4g^2|1V8`;KmY_l00ck)1V8`;Kwu{Xj?@2ZfUd3tp8xLz9_oMq2!H?x zfB*=900@8p2!H?xfWUzv;6DG4JbhsLjE;f;2!H?xfB*=900@8p2!H?xfB*>WfB<{` zkM;i!z@Z8VfB*=900@8p2!H?xfB*=900(gQ2@1 z00JNY0w4eaAOHd&00JNY0wAyh0(kzv18ArM0w4eaAOHd&00JNY0w4eaAOHdfj6hHF zlSnf1!^l$~B>#Q)54-imA9Q~?_Q#0_$AA6!n;n1A@ehwp9y=EKVf5cbGW37!m3R>Q zr%zVL&FN%3b>TvEYtq(pMI%?KtXZ06R87Ouie`DOF5&5k`Rw>&mMo56pU#rHY%)O1 z0-2g!%uZ(K$?f^6neq8|$gS)gr?22=(aavW~Hp?pD#OK#rniKjA|=+--m zP1IWTb)E{bidtiTn1%Ofugo$?xV&wcXX<1u_1=}{=2@@hil(({RQ(nTB=>B-dm^5? zawWR8q!=ksh}$WUcrwIPfg=0ET5hNI%3#|t)OdF+wRE9{p^CK?v#b?#TbILV-Ag*L z`DPcN*(Ov2c?E=VyoByB!+6;PyPDTnYdhsw)=LIi%)U+M!R^h3_w?e9>M3*IAZt9G ze)#2hJT*ERee|vZv#6I>YWj-rPT@~Wgdp{o*b`SL&V6X7c*Sjr^-IfF3dSzw&? zRjLJ}S|^Cy$le@ZnqDNs+qsz$qS}MF{q%-YdNL79y*t``xcIrt5#vwo+Pr(b{?1Y}f;F0mA#kr|jT5TpfyVwG(ZQ4b{k>s1#+yQcSsk~OM+%KOc6LZtkEZ&@*n;2in zwh(Josy4TTBX(PLZL?%pwq9B%i&Hb%g~joi+irIzmgeWFQkt97q963uNpDL`LAS<^ zWr<+ii69A$y{Fx~fGaX{zSV@ny-0KTY#)tj<;wgs9vklTR)@LqTH%((HqD;I`Lnho11pUx3W!9w`{FcDVWQq zLECYiPu}cZLH!qphlhuTGxQ%B9=_`QJLmlEPjB9e##4QL(XEm*j>W7Y-j4akvPhJp zIb1c<8r@F?KrJIabg-2?TgK!3 z|C8O!KP~Q~$L`>lrxt`pKRX zlPA8=J=^_RceFd&s?X7%Mb5Pk*kLU&cT1CEQ*_9GK98|28%9j7?OFrZH z^T0PH0oP_(rn>!Ly{*H_CB3?)QLtLUC>qXD zIsc(4_mo?Bw~PWmu;@Q(m1$9{U|Q=%{ee*2JW2!o?6^iKg-PV zi_~8Wyk7I+BD~JAPyN}_^ebPCrRLI&+|TbiTE>6f_b}D#9PNF?Pmks+WqMN0GAm`R zvToBit3Kt6e%Gw4u_s4+cRe-mp&ACAIJi%W}UJ1i-T?Sbn z>dhz12H(>Yztrq#aJ^ZmY3oe!{N{;gyMcI(<62dB+K!ie|2=S089* z!Ta=8-_Y^WWn3E)7`1aVa8G)-J*P336;947d;XoykXS1FLZg|)``%5){di`>cp;v8 z;f3hK=egqY`&DjpLN3d-Yxq;Upv&Ec;7AZM~2%x-OW4U#xmk-RSKHXuf$SQ zXBwd~3-rdt4#U&09A%V?)0+=Y#Zza_L?6BE;8C)akHm*a&F~QIn2$4`dVIGxBRY|B zAm;YY_OtI;Z1YPMoHJqH@}n#bt4^p|6)u~Z|IEgMFG8q0ZmVdH+E z^Od59Gme>@MCZ>}e5P@dq)m2U5&jh-pVqC0xRtM(>wyrYRUP5RPHP?yf!_a?X6OH- z$)82&KfFKy1V8`;KmY_l00ck)1V8`;KmY^|DuGkc&Pdm_Jbj>-s~Y4^&CIWn1zV>- zIxbaZv$_x}!|VWAQT zfB*=900@8p2!H?xfB*=900;yK;P?LmKyV2HAOHd&00JNY0w4eaAOHd&00M`Q0G|IJ zLZd<@5C8!X009sH0T2KI5C8!X009sP5Ww^Q01#Y)00@8p2!H?xfB*=900@8p2!OyL zB*1_F|BoWcKRSfUK_w6X0T2KI5C8!X009sH0T2KI5ICd+&PQXBuHKHh?CquNk)Qrf z-S7RAA@XKrwM-WBt41kjRQd1!|8*q!*M}4c)B*tz009sH0T2KI5C8!X009sHfulztS>&Eiv<>d^2{{NFm@+SvVQS=%FKmY_l00ck)1V8`;KmY_l00fRQfwLV; zUG1#@Pjz{G0|0h2?%z8pM5C8!X z009sH0T2KI5C8!X009s<(gZq>Q}v_#;s0Hn0XWjW0Odgd1V8`;KmY_l00ck)1V8`; z4lRMV;_Uf)hrZ@vX-ZLE0wBgSjWHEF&bT|R%+`;L9-0K znqSpyqgt{$S${13o||k~9nW^0i`JMJul}*#j!YMAwrFX3)zIv!>2$3p@vkG#M1~{X zpLUOS{aNCZ#P7$ynb?Yr$1fZ|9(%4c+4(2OKIr&&C(cKPX+iqhdgEfecVr~-(JM?3 zwa0qRUaeHAP)`YwG%=qYU(AxXrm}ZQNH!T?APd>)?8IU>33-`?!O--wUNXXS2Dmgb zF}F0kIA9ji$ zo#*fA(0(>-oT_aX2SvApB;GBWlcPBzEnF(^x?Mb9*LyNPdxO?L&-5Lm1=u@F3zs8R zFbiai)#BHV44Ea8UVV)Wr-^=VMdJzKc!*W0+RUWvy{<{e5CZh(n-}7#k&)=uE4H31 z8b#f*wW^^PwDpQ*+GeF}g(Qs#XIdP;KAj~Y1;_xQs!Yu;W+$`rnx3ZV%av+Lx5;AmZJH#KsrO7zGq;_cn;2in(o$?d`ODD6f^pBx z8+FO~WwS2LSg+()2^|a5ZX;9xRaRTB>Un<#xskm&zBIi^hG~(d*{M5A*#Xx6AmI&i zw;3e7=jrZrb~u)LXCxXi%LU_o>sxgGF_^1YoNFzFla>idytMJ=P(0P!8{MQso7#kq zRyLrmjE_1?;h2d_(+4_a6uU`m*!t1bk#@_5eBdm|029+-yvbVWv*%-}S9%*UVOnSz z_V?oE$#e14^Up^gQe~;ulrx=h`QHmZ&3W36bthz(+7mvy97hfMr&K%qeLLLF4aQQ} zo^QmBGte^peRyLn9Z&W3MIR11?8KZQ-iCbiMB*;+i7CP*ARRb$zx8s)q}$NIW=k=`(0jHk|=i9URuTgJ;$N)7mJXgwQ_fP%Pczo?wK0Aso*Ej8 zZjL(eg5`tPU-MxM=I)GTgIl@7xX~ZMgjG$aNBWyNoeb7Zio^T-;;+qR;=R4SiNAZC zMZZiF_McGCiEr68jegv~M}(p@h$XgZ7waQd8LYCgmamj)z&?=Ei!=xwbjEPw*p&r| z)G^+io0=67tVQN#2Y7HrV>uCJIpHi179D0Z$fNpOPO>Oc=Yq0N&LrZ5Y~H{VF|(II zCDE}!WF0qyELSTf5#73pmKt}nj*PjzNfWnJ!w&Izl}FTKjuripGp@fgqP)@*QLb4x zc#*n3*k;L~@j+?5E=Q_9Gye8Kt(>ov=oCW32f9o%zikKuvSp&^s$Xrw3N;idJi>`~ zxY|zeC4zq%y9DUdT$Q^M<0vZ~f75BU8nYU>K9UFgZa-gc)W|@lP@9FS%L;Fc_*~LN80U^dw zje*S39FZ0-($SI%IA5nw@jN3kMzh#EQ!-qF>^TK7M%xn_I8bC3e9;rx9B zdD9f4es4wNLc&QBW__lwRjJx_-E^=qV?D}Wj`vPXBtE{=(0{2jn?|??^Q@LW%!_?4 zUd)>c^MG^m9>ehmPKCG>1*tqP0+8SMyppJ1;sWYCI`#_jP!W+`WNj z2g={M4$XaBuzU2~OYz=Yw-O&eXz1kYwH&>htQytu>DFQq59eVrrf)lT~Ph)?~3zz3b$3%@MHOc!ryhoFK1I-SUkF#i|`4lh6^>qJoFBk{jF z{#zY)qF+t^qvXI-|Kh1{_WZc#t&{)pWcI{=IB}=@kGqY?zlz*yu^Oh5e%hkQ!OY(J z`YZ9?p`pY_CxVjzTkojx9lLHc*je6V9^lQF+3Io{OJ;8$z*#cy+46U5_G-L0lSzD3 zw=m!f2i0A8N+XBixu37g@HTniaF^}P5T4?#Tpyd~s7>$DOdjkz-$Z&m6L}jBw6m4w z*7VEq-jR{SM|B~Hh|*P$5=o6*N@VZQr+Dq~%_0ACGB6Q|W>vT1Ny-}WvH6v+@jY^^ zy52uw&*J@Qe!~|Www7Ot_rCmc;-j_T&CH8>Rgdyg8#$F%Vuya!?!qnLRbIQQW4WpR zb;@INFSk95_hOGc%oXcb;|crOc9u>w);l5MJ!>+adig?hJ+3Xt0uo5(y*HERP$O^vxL46Zt#YmRrFPhX`aGr^0ihC`&Cw}67fJKz0oldPmN!R zZuBW_yB^F3hN5>M=e3X?1d0T-59A5}8;R?@7cVyHg$E%ZWUP%|_)!D|kO4O#{oV0+ z>e^^@Bc=4DsFzo2`ifD9!=LeLNI(1~0xr5PBRzL5mUG3^;4piMi=%_BeBPZen~Po4)^A{peEn02D7% zlV1*LOwA7Rwtx5*?Rr=jm;I!?b7%|#AOHd&00JNY0w4eaAOHd&aP$aZ{eSdq z4vj$o1V8`;KmY_l00ck)1V8`;jvfK5|Bs%{p)m-600@8p2!H?xfB*=900@A<(IbHM z|IxEKGzI|>009sH0T2KI5C8!X009sOLPRb&aGCw}GkR2GmJ~zKONY37@R1I^bOxBDC zb6-aU*%mcS8QUIc{69zK55z68?U$t^kQu)o*F$D-RLmO1>=3z3rn;06-z6c zkey#VWZ{Z71Zo48uv4K*$ihZkCZYFE5?qy@xGx{;^B<&NDMYuzV%1XM>I?N;`7tq`ye4O4S~-O}l7l?Bf8N z$em07oXgsCU%pwN-VnxTZ;-j^8@wKQ^)=!O@#bk(naE$u={0+`Qss9*p#)-}6-Dp;o4!>KAvDB&F zsO7|Aj+JRB#ollG0xp@u#uNKY2FiNLAQN-b(=0-sons+ydSM}!I{kd~14o$fIVz5S zn)3kG5Qk4NkC3{!1KIvY%CL%*GCA<~mPCRw?h3LjJPAi_j z((3NTjIRwhSvKJ&kOB5l%U23@gl^o9rOxz5>HVI@*vpk_NvE+CZG*Y^v`@T}DFaP1 zz!TGN&&5)GBhhd1zE;lt&| zv@sJ)Wzx~_I<@mP%dV6tg<`E#c9is|O!*}G^CVJ#D&v|nis=W_@zhvG+NyrIvD#X$ zKK%`Ui*>`4*JC=>*A;v=x^MBeN4SpRGW7cTlkK#vH)@;PJviK^-;AYRJQX!WS43n^ zm6tPDHqfY7f;Yskg=#qe|9H12ARPoi00ck)1V8`;KmY_l00ck)1oi^~tpE3e70?F| z009sH0T2KI5C8!X009sH0T6h+1hD>pynG=Y1V8`;KmY_l00ck)1V8`;KmY{x0|EU0 z-+r(H`TznT00JNY0w4eaAOHd&00JNY0*{XX`~5#W|9^aZAsGZf00ck)1V8`;KmY_l z00ck)1ojI7{`~)wNb-~Y(j)W(1V8`;KmY_l00ck)1V8`;KmY_lV6OQ$J!i!GX09Z@f5EPrD=S8Ic`dJ*Wy`4ATCP%Av$XYEu4r1TM%B`aW_c|%abi9@ zzL+J8^HY)D%g^I0-AyO5nkp zH@`SY&fct44RfVT){F<_o>?jCwpl4(bp(@g#U^H%H*z)|kQLe=kF38_Zu;(f=8BTt za}z9IAG5PJUU9ojFCKoU5bvAJB))&5kz43Bd$r>82{omaL#Solb{lv@gR+Op6@-p{ zKj4YGcLFX)dVpxEsrff&^6|b*Z(>VR%wI5yhHYq-vS#Zm7W*&6%Kkz@)83#1md+D& zptI^quHTr=Ms{FqPs}aNE)JN5G`TrHHzVc`Cfu2<1W$TBHaC6aJS+AZ8Ft&1(@^^( zok=F9MJ(Ga7D?4uHmXKBZxnnq2?-9T&2Qx5eWTAOwrZg~>1=Bn7XRCnDKFyoUkn(J zYF+-`a^>PxvOHyv;BsL*!Fyki_l=!SJn9R@>&2;_VvSLUmf2g}UK1*EH+7Gw zyYhD8*jtHTiT7nk6W>1_O1`L9nyO={$wLNnfG$vjQ3sXOKg1@id@|3#amO{qKrb)3Cum%^#%48wUDoZ=1F@* zS;*fBsB%(ixBz`mYTb)1Zcs=@~r#?LSKTdq(#I=yczmnAb8_|c#B|d)s z1Rfsy)p*~nOybeA%4pz|jM$1%CrK^G_e#{XkkQekzA^%w;o{9iT&A}lqqd>c+V!{* za{ZAEPiz#%Y-c(WYKV;)(O9b~>3!2N!q#`&GJ?KKBj^gwfDxR@)ZG#jy?5@9N}XMs z!0Er=04!-Q@H+}L*%b>0kPi#1@xJkMiSMl_=zUv}?z-OTwX+T3015H?@Olclz#SqW zQ7Pz0e85)^&i;jO2b88XGIsknekw%X_gM?RF;-{hdnrqjz(rywi&otl!R8M zR*EV%3^jIm(L-f!uA+Z<^R(UDT*wv!oL@CJ{CAdH>?v32etKDK-EqsSDXmPemThJG z24xSG@r90l>+{6jTc693gI+Y%)ciD{`h(9usM^aGA9j}FeRr-T9;pvSd;ylXm*(7; zG!Y&Il0zK1xs;$cdyyI&C0?8sXh*5$ckFHKi|oTycqKzsn@mI~i? zl##MOwUrV4rL~*_GZ3h;lFo*ZX9#~~rRuKj;7axnYqt-LM)r2%W>=UT-fpA50bakJ ze;8TgmWj7%88JRw`HiBvX4Y*xg!Z?xmqu~!Repo8q`k0(Gr+eIME9KdMx-n9Vx;T$ z663MoJD%Nt?r&FDctT)|)Rl4>j^A9Q zkNv$3d0x`ZzMl2_y_mmvDf$$Dkyw?gJ!YGB(a_k(0rqUZte5C+wl7#U3%;k+n=3XA zCC??c%trpkqES8-i{-ML5YUYsS@3z8Td>*Cr-i&h@78Fj_YUS=Ce+V>rtF1dv91fh zVr{e-*_%a+leSuu7K55eZEHNc1+}(^vRh>@QSYNsy!oAKyl?74lSo61MRp=b-rtm@ zR?e*yZRXx$fV!IyO0~TNFPiaRG$2RS6Irz6eXyok*2^r)mN!!8S zw$Cf__Y(d-^7@Cz)>~|Vigku>Mpx5Xfmh2mb9`RTo7&ZSdkJ62^-u6TaW7n7s3BZm zG}daSf4|aV160W2Mi7&|nzk(?wC(!hi`87<606^b1boAt^LcDYDu@P{y`$z6e<1A<$EHz-_~O*jh=kb?FZ|uX1`gsWh?y!(^@a;4_Iw3 ziuS~`v^+g1vr?(D^kuzh8Bz?(vev^=YnELpg=827Q+C;|)>J{ITG2Mw9c8?>*UU0g zrGMEpiUqfqMLlN}Su)jAc7^RW&?Lq|CRGjgRfvM|K20B%iI$;P^Q)R|R7)03e^=6_ zqS_;Clx>rCr^;%#i`X{a-wxvd8ICxZxI4m9?Yy2}H8i_Iqe0828ubrKqSW#%jpfx$ zCx>Rb&R8@3l^l7l%d|9`2T|HZ*sp)8P@kt7@?sm7tdqdJ*p;hjVOqIzTV{9n9u=dD zG2v`@F+Qw}vyUtr@P=MUo;m{e!aeH7bLNsv4RWq? zWdCGLH+0x7ZW~Z{aMwI|w@iseQgsa=zToYxg?v^RmF0t0klrrkw&m>d%jAl2b~%an zZ}V3AM5gfu>rZ#<(H#JRK()R=&}vn;s$(^_9V3>kEyEm7c)02M-2!T4$~WSh*iRIY zZsXmC0~yMVxIdWHavNbkSuxQ0fC&S+(th*KSx3L|gyC9_I3cou)p)LIGQRiJ#AE}? z(F@kWblUBhXFjLr(yFTQgm^dWKp8L4`GD~PxzczG&KI^_M(TX|lElzxx)dTC7|+Y) zQD{F;aQC6wjmwsc6@5EfM*Au-^XV*k3ifKuu5!<`+}H6*4ae_~BSZyuAW0cJt+qqA zc{|#V;2n(v-1`?CpLb4bg*yJlhT)pSn(l+BJlo=LetSDX+`)EvrfVH?HBoi;)~H#{ zwiq8F=Vqz~5ihbchmD;&({jVlyK}b1o1I)!CX+)L`^wS&M4k*dc%_X4_i~z7Z+>PD zSzaAsmt|t3+ql{io!gl3@bSj7)L@M5&eC7cDY3_1?cU9Ius%JIySg45iC;!sH`sz+ zCaQ*Nxx2{NH873;cJGYjZ5ZVs-{`rnlBb01OopM9+nWa4!d$Cu>*?}ArtGL1fZQ;C zZ8_sO(!%E$>B!w5vfuxUcl~K3`De-hl>FV~Zzk`ZB=iz55C8!X009sH0T2LzgGgZO z_4x6~#78syI}7(r<36FsElr!O>t(u$L62k_Y(*)~jd?#v<}GT(&&bdO_aU}Coy4{! zyzLJE`5KzzZm+rzx0OSY^g)rc%(_b4hfeOZBP!P26BiFIt`g-D2m9$$TIPz3lP$jM z=WcO1%jc`a4UfGw;#J}<{^Z&%L)8}>=lsEi#>6Q*E*^kP#;xr~pd_oufEXP&%Tw5& z$bTu@A?cQNl~#)Ktx$hCp}0~?sII0cn+LvRx{Jl7c>q?;0zI=xPZYBAy9~j*?{$Cp zy@lBE$mHLu6wO>!uRhQmCsO?>=tO#v{@`_qo`|FZ#CC6h8&xot~u6$bQwx+s-jO z_wg{zRs@9?VUIhsReDyLpHP3-=>h-CcJ^FlL@x+G!|s%NkM*Pb!!yS_Ba_ci4qC2S zxlfr=s{45(s6u((1^HyDn0L0VhzG62iZ2z~f^1#UT-uy9c!th5DIs<@faVqq%q# z*bZ3s|2D%lmTcrxt8wT5iKfXje0T8>#4Mdf<;lZ3*+w(|%BoVH(w8Rb_nn||Ez|FG zS<2ppZQSsdl6zd=p_FjiA4&b>YmL9+_ci`-aC-*#p3MiI<#UUyqcJF!8bTzs^?W&B zxkq;-+|3Gi@HLti5AfHQxvCPfN1p+ZsVe$R8|+!#aEBLnL$Pp|-!E?;^fvE5`*e;Q jY&^vcZf}Z{1f`{<{cifdx!>=zpu2?=GJ0r`xA^}7LVg8j literal 0 HcmV?d00001 diff --git a/apps/calibre-web/docker-compose.yml b/apps/calibre-web/docker-compose.yml new file mode 100644 index 00000000..da5bd292 --- /dev/null +++ b/apps/calibre-web/docker-compose.yml @@ -0,0 +1,17 @@ +version: "3.7" +services: + calibre-web: + image: lscr.io/linuxserver/calibre-web:0.6.18 + container_name: calibre-web + environment: + - PUID=1000 + - PGID=1000 + - TZ=${TZ} + volumes: + - ${APP_DATA_DIR}/data/config:/config + - ${ROOT_FOLDER_HOST}/media/data/books:/books + ports: + - ${APP_PORT}:8083 + restart: unless-stopped + networks: + - tipi_main_network diff --git a/apps/calibre-web/metadata/description.md b/apps/calibre-web/metadata/description.md new file mode 100644 index 00000000..795e2a5b --- /dev/null +++ b/apps/calibre-web/metadata/description.md @@ -0,0 +1,7 @@ +Calibre-Web is a web app providing a clean interface for browsing, reading and downloading eBooks using a valid Calibre database. + +On the initial setup screen, enter /books as your calibre library location. + +- **username**: admin +- **password**: admin123 +
\ No newline at end of file diff --git a/apps/code-server/config.json b/apps/code-server/config.json new file mode 100644 index 00000000..38b0b83e --- /dev/null +++ b/apps/code-server/config.json @@ -0,0 +1,22 @@ +{ + "name": "Code-Server - Web VS Code", + "available": true, + "port": 8101, + "id": "code-server", + "categories": ["development"], + "description": "", + "short_desc": "Code-server is VS Code running on a remote server, accessible through the browser.", + "author": "https://github.com/coder", + "source": "https://github.com/linuxserver/docker-code-server", + "image": "https://avatars.githubusercontent.com/u/95932066", + "form_fields": [ + { + "type": "password", + "label": "Password", + "max": 50, + "min": 3, + "required": true, + "env_variable": "CODESERVER_PASSWORD" + } + ] +} diff --git a/apps/code-server/docker-compose.yml b/apps/code-server/docker-compose.yml new file mode 100644 index 00000000..6d5d3336 --- /dev/null +++ b/apps/code-server/docker-compose.yml @@ -0,0 +1,19 @@ +version: "3.7" +services: + code-server: + image: lscr.io/linuxserver/code-server:4.5.1 + container_name: code-server + environment: + - PUID=1000 + - PGID=1000 + - TZ=${TZ} + - PASSWORD=${CODESERVER_PASSWORD} + - DEFAULT_WORKSPACE=/config/workspace #optional + volumes: + - ${APP_DATA_DIR}/data/config:/config #config dir + - ${APP_DATA_DIR}/data/projects:/projects + ports: + - ${APP_PORT}:8443 + restart: unless-stopped + networks: + - tipi_main_network diff --git a/apps/code-server/metadata/description.md b/apps/code-server/metadata/description.md new file mode 100644 index 00000000..abe472d8 --- /dev/null +++ b/apps/code-server/metadata/description.md @@ -0,0 +1,7 @@ +## Run VS Code on any machine anywhere and access it in the browser. + +- Code on any device with a consistent development environment +- Use cloud servers to speed up tests, compilations, downloads, and more +- Preserve battery life when you're on the go; all intensive tasks run on your server + +![screenshot](https://raw.githubusercontent.com/coder/code-server/main/docs/assets/screenshot.png) \ No newline at end of file diff --git a/apps/docker-compose.common.yml b/apps/docker-compose.common.yml new file mode 100644 index 00000000..23cc7651 --- /dev/null +++ b/apps/docker-compose.common.yml @@ -0,0 +1,6 @@ +version: "3.7" + +networks: + tipi_main_network: + external: + name: runtipi_tipi_main_network \ No newline at end of file diff --git a/apps/filebrowser/config.json b/apps/filebrowser/config.json new file mode 100644 index 00000000..3f08306d --- /dev/null +++ b/apps/filebrowser/config.json @@ -0,0 +1,14 @@ +{ + "name": "File Browser", + "available": true, + "port": 8096, + "id": "filebrowser", + "categories": ["utilities"], + "description": "Reliable and Performant File Management Desktop Sync and File Sharing\n Default credentials: admin / admin", + "short_desc": "Access your homeserver files from your browser", + "author": "filebrowser.org", + "website": "https://filebrowser.org/", + "source": "https://github.com/filebrowser/filebrowser", + "image": "/logos/apps/filebrowser.jpg", + "form_fields": [] +} diff --git a/apps/filebrowser/data/config/settings.json b/apps/filebrowser/data/config/settings.json new file mode 100644 index 00000000..cf7fb4ee --- /dev/null +++ b/apps/filebrowser/data/config/settings.json @@ -0,0 +1,8 @@ +{ + "port": 80, + "baseURL": "", + "address": "", + "log": "stdout", + "database": "/database/filebrowser.db", + "root": "/srv" +} diff --git a/apps/filebrowser/docker-compose.yml b/apps/filebrowser/docker-compose.yml new file mode 100644 index 00000000..5e1d0cf1 --- /dev/null +++ b/apps/filebrowser/docker-compose.yml @@ -0,0 +1,17 @@ +version: "3.7" +services: + filebrowser: + container_name: filebrowser + image: filebrowser/filebrowser:s6 + ports: + - ${APP_PORT}:80 + environment: + - PUID=1000 + - PGID=1000 + volumes: + - ${ROOT_FOLDER_HOST}/app-data:/srv/app-data + - ${ROOT_FOLDER_HOST}/media:/srv/media + - ${APP_DATA_DIR}/data/db:/database + - ${APP_DATA_DIR}/data/config:/config + networks: + - tipi_main_network diff --git a/apps/filebrowser/metadata/description.md b/apps/filebrowser/metadata/description.md new file mode 100644 index 00000000..3c7355e1 --- /dev/null +++ b/apps/filebrowser/metadata/description.md @@ -0,0 +1,12 @@ +## Access your homeserver files from your browser + +filebrowser provides a file managing interface within a specified directory and it can be used to upload, delete, preview, rename and edit your files. It allows the creation of multiple users and each user can have its own directory. It can be used as a standalone app. + +- **username**: admin +- **password**: admin +
+## Features + +Please refer to our docs at [https://filebrowser.org/features](https://filebrowser.org/features) + +![Preview](https://user-images.githubusercontent.com/5447088/50716739-ebd26700-107a-11e9-9817-14230c53efd2.gif) \ No newline at end of file diff --git a/apps/filerun/config.json b/apps/filerun/config.json new file mode 100644 index 00000000..12be5101 --- /dev/null +++ b/apps/filerun/config.json @@ -0,0 +1,12 @@ +{ + "name": "FileRun", + "port": 8087, + "available": false, + "id": "filerun", + "description": "Reliable and Performant File Management Desktop Sync and File Sharing", + "short_desc": "Access your homeserver files from your browser", + "author": "FileRun, LDA - Portugal", + "source": "https://www.filerun.com/", + "image": "https://avatars.githubusercontent.com/u/6422152?v=4", + "form_fields": [] +} diff --git a/apps/filerun/docker-compose.yml b/apps/filerun/docker-compose.yml new file mode 100644 index 00000000..71dea393 --- /dev/null +++ b/apps/filerun/docker-compose.yml @@ -0,0 +1,38 @@ +services: + filerun-db: + container_name: filerun-db + user: 1000:1000 + image: mariadb:10.1 + environment: + MYSQL_ROOT_PASSWORD: tipi + MYSQL_USER: tipi + MYSQL_PASSWORD: tipi + MYSQL_DATABASE: tipi + volumes: + - ${APP_DATA_DIR}/data/db:/var/lib/mysql + networks: + - tipi_main_network + + filerun: + container_name: filerun + image: filerun/filerun:arm64v8 + environment: + FR_DB_HOST: filerun-db + FR_DB_PORT: 3306 + FR_DB_NAME: tipi + FR_DB_USER: tipi + FR_DB_PASS: tipi + APACHE_RUN_USER: 1000 + APACHE_RUN_GROUP: 1000 + APACHE_RUN_USER_ID: 33 + APACHE_RUN_GROUP_ID: 33 + depends_on: + - db + links: + - db:db + ports: + - ${APP_PORT}:80 + volumes: + - ${ROOT_FOLDER_HOST}/app-data/medias:/user-files + networks: + - tipi_main_network diff --git a/apps/filerun/metadata/description.md b/apps/filerun/metadata/description.md new file mode 100644 index 00000000..e69de29b diff --git a/apps/firefly-iii/config.json b/apps/firefly-iii/config.json new file mode 100644 index 00000000..8f0d8539 --- /dev/null +++ b/apps/firefly-iii/config.json @@ -0,0 +1,35 @@ +{ + "name": "Firefly III", + "available": true, + "port": 8115, + "id": "firefly-iii", + "categories": ["finance"], + "description": "", + "short_desc": "Firefly III: a personal finances manager ", + "author": "JC5", + "website": "https://www.firefly-iii.org/", + "source": "https://github.com/firefly-iii/firefly-iii", + "image": "/logos/apps/firefly-iii.jpg", + "form_fields": [ + { + "type": "email", + "label": "Your email", + "required": true, + "env_variable": "EMAIL" + }, + { + "type": "random", + "min": 32, + "max": 32, + "label": "Random key", + "env_variable": "APP_KEY" + }, + { + "type": "random", + "min": 32, + "max": 32, + "label": "Database password", + "env_variable": "MYSQL_PASSWORD" + } + ] +} diff --git a/apps/firefly-iii/docker-compose.yml b/apps/firefly-iii/docker-compose.yml new file mode 100644 index 00000000..58159244 --- /dev/null +++ b/apps/firefly-iii/docker-compose.yml @@ -0,0 +1,59 @@ +version: '3.9' + +services: + firefly-iii: + image: fireflyiii/core:latest + container_name: firefly-iii + restart: unless-stopped + volumes: + - ${APP_DATA_DIR}/data/uplodad:/var/www/html/storage/upload + ports: + - ${APP_PORT}:8080 + depends_on: + - firefly-iii-db + environment: + - APP_ENV=local + - APP_DEBUG=false + - SITE_OWNER=${EMAIL} + - APP_KEY=${APP_KEY} + - TZ=${TZ} + - TRUSTED_PROXIES=** + + # Database + - DB_CONNECTION=mysql + - DB_HOST=firefly-iii-db + - DB_PORT=3306 + - DB_DATABASE=firefly + - DB_USERNAME=firefly + - DB_PASSWORD=${MYSQL_PASSWORD} + + # Cookie settings + - COOKIE_PATH="/" + - COOKIE_DOMAIN= + - COOKIE_SECURE=false + - COOKIE_SAMESITE=lax + + - APP_NAME=FireflyIII + - BROADCAST_DRIVER=log + - QUEUE_DRIVER=sync + - CACHE_PREFIX=firefly + - IS_HEROKU=false + - FIREFLY_III_LAYOUT=v1 + - APP_URL=http://localhost:${APP_PORT} + networks: + - tipi_main_network + + firefly-iii-db: + container_name: firefly-iii-db + image: mariadb + hostname: fireflyiii-db + restart: unless-stopped + environment: + - MYSQL_RANDOM_ROOT_PASSWORD=yes + - MYSQL_USER=firefly + - MYSQL_PASSWORD=${MYSQL_PASSWORD} + - MYSQL_DATABASE=firefly + volumes: + - ${APP_DATA_DIR}/data/db:/var/lib/mysql + networks: + - tipi_main_network diff --git a/apps/firefly-iii/metadata/description.md b/apps/firefly-iii/metadata/description.md new file mode 100644 index 00000000..4f81d34f --- /dev/null +++ b/apps/firefly-iii/metadata/description.md @@ -0,0 +1,26 @@ +"Firefly III" is a (self-hosted) manager for your personal finances. It can help you keep track of your expenses and income, so you can spend less and save more. Firefly III supports the use of budgets, categories and tags. Using a bunch of external tools, you can import data. It also has many neat financial reports available. + +Firefly III should give you **insight** into and **control** over your finances. Money should be useful, not scary. You should be able to *see* where it is going, to *feel* your expenses and to... wow, I'm going overboard with this aren't I? + +But you get the idea: this is your money. These are your expenses. Stop them from controlling you. I built this tool because I started to dislike money. Having money, not having money, paying bills with money, you get the idea. But no more. I want to feel "safe", whatever my balance is. And I hope this tool can help you. I know it helps me. + +![Firefly III on iMac](https://raw.githubusercontent.com/firefly-iii/firefly-iii/develop/.github/assets/img/imac-complete.png) + +### Purpose + +Personal financial management is pretty difficult, and everybody has their own approach to it. Some people make budgets, other people limit their cashflow by throwing away their credit cards, others try to increase their current cashflow. There are tons of ways to save and earn money. Firefly III works on the principle that if you know where your money is going, you can stop it from going there. + +By keeping track of your expenses and your income you can budget accordingly and save money. Stop living from paycheck to paycheck but give yourself the financial wiggle room you need. + +You can read more about the purpose of Firefly III in the [documentation](https://docs.firefly-iii.org/). + +![Firefly III on iPad](https://raw.githubusercontent.com/firefly-iii/firefly-iii/develop/.github/assets/img/ipad-complete.png) + +## Need help? + +If you need support using Firefly III or the associated tools, come find us! + +- [GitHub Discussions for questions and support](https://github.com/firefly-iii/firefly-iii/discussions/) +- [Gitter.im for a good chat and a quick answer](https://gitter.im/firefly-iii/firefly-iii) +- [GitHub Issues for bugs and issues](https://github.com/firefly-iii/firefly-iii/issues) +- [Follow me around for news and updates on Twitter](https://twitter.com/Firefly_iii) \ No newline at end of file diff --git a/apps/freshrss/config.json b/apps/freshrss/config.json new file mode 100644 index 00000000..adfe1643 --- /dev/null +++ b/apps/freshrss/config.json @@ -0,0 +1,13 @@ +{ + "name": "FreshRSS", + "available": true, + "port": 8086, + "id": "freshrss", + "categories": ["utilities"], + "description": "FreshRSS is a self-hosted RSS feed aggregator like Leed or Kriss Feed.\nIt is lightweight, easy to work with, powerful, and customizable.\n\nIt is a multi-user application with an anonymous reading mode. It supports custom tags. There is an API for (mobile) clients, and a Command-Line Interface.\n\nThanks to the WebSub standard (formerly PubSubHubbub), FreshRSS is able to receive instant push notifications from compatible sources, such as Mastodon, Friendica, WordPress, Blogger, FeedBurner, etc.\n\nFreshRSS natively supports basic Web scraping, based on XPath, for Web sites not providing any RSS / Atom feed.\n\nFinally, it supports extensions for further tuning.", + "short_desc": "A free, self-hostable aggregator… ", + "author": "https://freshrss.org/", + "source": "https://github.com/FreshRSS/FreshRSS", + "image": "/logos/apps/freshrss.jpg", + "form_fields": [] +} diff --git a/apps/freshrss/docker-compose.yml b/apps/freshrss/docker-compose.yml new file mode 100644 index 00000000..782e09cb --- /dev/null +++ b/apps/freshrss/docker-compose.yml @@ -0,0 +1,25 @@ +version: "3.7" + +services: + freshrss: + image: lscr.io/linuxserver/freshrss:1.19.2 + container_name: freshrss + environment: + - PUID=1000 + - PGID=1000 + - TZ=${TZ} + volumes: + - ${APP_DATA_DIR}/data/freshrss:/config + ports: + - ${APP_PORT}:80 + restart: unless-stopped + networks: + - tipi_main_network + + # labels: + # traefik.enable: true + # traefik.http.routers.freshrss.rule: Host(`freshrss.tipi.home`) + # traefik.http.routers.freshrss.service: freshrss + # traefik.http.routers.freshrss.tls: true + # traefik.http.routers.freshrss.entrypoints: websecure + # traefik.http.services.freshrss.loadbalancer.server.port: 80 diff --git a/apps/freshrss/metadata/description.md b/apps/freshrss/metadata/description.md new file mode 100644 index 00000000..bc58cde2 --- /dev/null +++ b/apps/freshrss/metadata/description.md @@ -0,0 +1,27 @@ + + +## A free, self-hostable aggregator… + +FreshRSS is a self-hosted RSS feed aggregator like [Leed](https://github.com/LeedRSS/Leed) or [Kriss Feed](https://tontof.net/kriss/feed/). + +It is lightweight, easy to work with, powerful, and customizable. + +It is a multi-user application with an anonymous reading mode. It supports custom tags. +There is an API for (mobile) clients, and a [Command-Line Interface](cli/README.md). + +Thanks to the [WebSub](https://www.w3.org/TR/websub/) standard (formerly [PubSubHubbub](https://github.com/pubsubhubbub/PubSubHubbub)), +FreshRSS is able to receive instant push notifications from compatible sources, such as [Mastodon](https://joinmastodon.org), [Friendica](https://friendi.ca), [WordPress](https://wordpress.org/plugins/pubsubhubbub/), Blogger, FeedBurner, etc. + +FreshRSS natively supports basic Web scraping, based on [XPath](https://www.w3.org/TR/xpath-10/), for Web sites not providing any RSS / Atom feed. + +Finally, it supports [extensions](#extensions) for further tuning. + +Feature requests, bug reports, and other contributions are welcome. The best way to contribute is to [open an issue on GitHub](https://github.com/FreshRSS/FreshRSS/issues). +We are a friendly community. + +* Official website: [website](https://freshrss.org) +* Demo: [Demo](https://demo.freshrss.org/) +* License: [GNU AGPL 3](https://www.gnu.org/licenses/agpl-3.0.html) + +![Screenshot](https://raw.githubusercontent.com/FreshRSS/FreshRSS/edge/docs/img/FreshRSS-screenshot.png) + diff --git a/apps/gitea/config.json b/apps/gitea/config.json new file mode 100644 index 00000000..5a71cb07 --- /dev/null +++ b/apps/gitea/config.json @@ -0,0 +1,13 @@ +{ + "name": "Gitea", + "port": 8108, + "available": true, + "id": "gitea", + "categories": ["development"], + "description": "Gitea is a painless self-hosted Git service. It is similar to GitHub, Bitbucket, and GitLab. Gitea is a fork of Gogs. See the Gitea Announcement blog post to read about the justification for a fork.", + "short_desc": "Gitea - Git with a cup of tea · A painless self-hosted Git service. · Cross-platform · Easy to install · Lightweight · Open Source.", + "author": "go-gitea", + "source": "https://github.com/go-gitea/gitea", + "image": "/logos/apps/gitea.jpg", + "form_fields": [] +} diff --git a/apps/gitea/data/gitea/gitea/conf/app.ini b/apps/gitea/data/gitea/gitea/conf/app.ini new file mode 100644 index 00000000..8056f275 --- /dev/null +++ b/apps/gitea/data/gitea/gitea/conf/app.ini @@ -0,0 +1,88 @@ +APP_NAME = Gitea: Git with a cup of tea +RUN_MODE = prod +RUN_USER = git + +[repository] +ROOT = /data/git/repositories + +[repository.local] +LOCAL_COPY_PATH = /data/gitea/tmp/local-repo + +[repository.upload] +TEMP_PATH = /data/gitea/uploads + +[server] +APP_DATA_PATH = /data/gitea +DOMAIN = localhost +SSH_DOMAIN = localhost +HTTP_PORT = 3000 +ROOT_URL = http://localhost:8108/ +DISABLE_SSH = false +SSH_PORT = 22 +SSH_LISTEN_PORT = 22 +LFS_START_SERVER = true +LFS_CONTENT_PATH = /data/git/lfs +LFS_JWT_SECRET = wo2G20l0nGsspUp8xsLNSNF7H8U-GQUVth5gj_q5cDk +OFFLINE_MODE = false + +[database] +PATH = /data/gitea/gitea.db +DB_TYPE = postgres +HOST = gitea-db:5432 +NAME = gitea +USER = gitea +PASSWD = gitea +LOG_SQL = false +SCHEMA = +SSL_MODE = disable +CHARSET = utf8 + +[indexer] +ISSUE_INDEXER_PATH = /data/gitea/indexers/issues.bleve + +[session] +PROVIDER_CONFIG = /data/gitea/sessions +PROVIDER = file + +[picture] +AVATAR_UPLOAD_PATH = /data/gitea/avatars +REPOSITORY_AVATAR_UPLOAD_PATH = /data/gitea/repo-avatars +DISABLE_GRAVATAR = false +ENABLE_FEDERATED_AVATAR = true + +[attachment] +PATH = /data/gitea/attachments + +[log] +MODE = console +LEVEL = info +ROUTER = console +ROOT_PATH = /data/gitea/log + +[security] +INSTALL_LOCK = true +SECRET_KEY = +REVERSE_PROXY_LIMIT = 1 +REVERSE_PROXY_TRUSTED_PROXIES = * +INTERNAL_TOKEN = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE2NTMyODU5ODh9.l7fPuVA8LSHZvdBum8YDrH47RZjEx_cZLbswO5pMDk8 +PASSWORD_HASH_ALGO = pbkdf2 + +[service] +DISABLE_REGISTRATION = false +REQUIRE_SIGNIN_VIEW = false +REGISTER_EMAIL_CONFIRM = false +ENABLE_NOTIFY_MAIL = false +ALLOW_ONLY_EXTERNAL_REGISTRATION = false +ENABLE_CAPTCHA = false +DEFAULT_KEEP_EMAIL_PRIVATE = false +DEFAULT_ALLOW_CREATE_ORGANIZATION = true +DEFAULT_ENABLE_TIMETRACKING = true +NO_REPLY_ADDRESS = noreply.localhost + +[mailer] +ENABLED = false + +[openid] +ENABLE_OPENID_SIGNIN = true +ENABLE_OPENID_SIGNUP = true + diff --git a/apps/gitea/docker-compose.yml b/apps/gitea/docker-compose.yml new file mode 100644 index 00000000..50dc6a48 --- /dev/null +++ b/apps/gitea/docker-compose.yml @@ -0,0 +1,37 @@ +version: "3.7" + +services: + gitea: + image: gitea/gitea:1.16.8 + container_name: gitea + environment: + - USER_UID=1000 + - USER_GID=1000 + - GITEA__database__DB_TYPE=postgres + - GITEA__database__HOST=gitea-db:5432 + - GITEA__database__NAME=gitea + - GITEA__database__USER=gitea + - GITEA__database__PASSWD=gitea + restart: unless-stopped + networks: + - tipi_main_network + volumes: + - ${APP_DATA_DIR}/data/gitea:/data + ports: + - ${APP_PORT}:3000 + - "222:22" + depends_on: + - gitea-db + + gitea-db: + container_name: gitea-db + image: postgres:14 + restart: unless-stopped + environment: + - POSTGRES_USER=gitea + - POSTGRES_PASSWORD=gitea + - POSTGRES_DB=gitea + volumes: + - ${APP_DATA_DIR}/data/postgres:/var/lib/postgresql/data + networks: + - tipi_main_network diff --git a/apps/gitea/metadata/description.md b/apps/gitea/metadata/description.md new file mode 100644 index 00000000..9a52a06f --- /dev/null +++ b/apps/gitea/metadata/description.md @@ -0,0 +1,5 @@ +# A painless self-hosted Git service + +The goal of this project is to make the easiest, fastest, and most painless way of setting up a self-hosted Git service. Using Go, this can be done with an independent binary distribution across all platforms which Go supports, including Linux, macOS, and Windows on x86, amd64, ARM and PowerPC architectures. Want to try it before doing anything else? Do it with the online demo! This project has been forked from Gogs since 2016.11 but changed a lot. + +![Screenshot](https://camo.githubusercontent.com/134f49a62801ab393c211125515d108439c67b59befb2ec3e42e7235af4f5d6c/68747470733a2f2f646c2e67697465612e696f2f73637265656e73686f74732f686f6d655f74696d656c696e652e706e67) \ No newline at end of file diff --git a/apps/homarr/config.json b/apps/homarr/config.json new file mode 100644 index 00000000..63e496d2 --- /dev/null +++ b/apps/homarr/config.json @@ -0,0 +1,14 @@ +{ + "name": "Homarr", + "available": true, + "port": 8102, + "id": "homarr", + "categories": ["utilities"], + "description": "A homepage for your server.", + "short_desc": "Homarr is a simple and lightweight homepage for your server, that helps you easily access all of your services in one place.", + "author": "ajnart", + "source": "https://github.com/ajnart/homarr", + "website": "https://discord.gg/C2WTXkzkwK", + "image": "/logos/apps/homarr.jpg", + "form_fields": [] +} diff --git a/apps/homarr/docker-compose.yml b/apps/homarr/docker-compose.yml new file mode 100644 index 00000000..850c4de5 --- /dev/null +++ b/apps/homarr/docker-compose.yml @@ -0,0 +1,12 @@ +version: "3.7" +services: + homarr: + container_name: homarr + image: ghcr.io/ajnart/homarr:0.8.0 + restart: unless-stopped + volumes: + - ${APP_DATA_DIR}/data/config:/app/data/configs + ports: + - ${APP_PORT}:7575 + networks: + - tipi_main_network diff --git a/apps/homarr/metadata/description.md b/apps/homarr/metadata/description.md new file mode 100644 index 00000000..88ddc31a --- /dev/null +++ b/apps/homarr/metadata/description.md @@ -0,0 +1,10 @@ +# Lightweight homepage for your server +Homarr is a simple and lightweight homepage for your server, that helps you easily access all of your services in one place. +It integrates with the services you use to display information on the homepage (E.g. Show upcoming Sonarr/Radarr releases). + +If you have any questions about Homarr or want to share information with us, please go to one of the following places: + +- [Github Discussions](https://github.com/ajnart/homarr/discussions) +- [Discord Server](https://discord.gg/aCsmEV5RgA) + +![Screenshot](https://user-images.githubusercontent.com/71191962/169860380-856634fb-4f41-47cb-ba54-6a9e7b3b9c81.gif) \ No newline at end of file diff --git a/apps/homeassistant/config.json b/apps/homeassistant/config.json new file mode 100644 index 00000000..cfec8457 --- /dev/null +++ b/apps/homeassistant/config.json @@ -0,0 +1,13 @@ +{ + "name": "Home Assistant", + "available": true, + "port": 8123, + "id": "homeassistant", + "categories": ["automation"], + "description": "Open source home automation that puts local control and privacy first. Powered by a worldwide community of tinkerers and DIY enthusiasts. Perfect to run on a Raspberry Pi or a local server.", + "short_desc": "Open source home automation that puts local control and privacy first", + "author": "ArneNaessens", + "source": "https://github.com/home-assistant/core", + "image": "/logos/apps/homeassistant.jpg", + "form_fields": [] +} diff --git a/apps/homeassistant/docker-compose.yml b/apps/homeassistant/docker-compose.yml new file mode 100644 index 00000000..c17aec22 --- /dev/null +++ b/apps/homeassistant/docker-compose.yml @@ -0,0 +1,13 @@ + +version: '3' +services: + homeassistant: + container_name: homeassistant + image: "ghcr.io/home-assistant/home-assistant:stable" + volumes: + - ${APP_DATA_DIR}/config:/config + restart: unless-stopped + privileged: true + ports: + - ${APP_PORT}:8123 + network_mode: host \ No newline at end of file diff --git a/apps/homeassistant/metadata/description.md b/apps/homeassistant/metadata/description.md new file mode 100644 index 00000000..b7b2a420 --- /dev/null +++ b/apps/homeassistant/metadata/description.md @@ -0,0 +1,7 @@ + +## Open source home automation that puts local control and privacy first + +Open source home automation that puts local control and privacy first. Powered by a worldwide community of tinkerers and DIY enthusiasts. Perfect to run on a Raspberry Pi or a local server. +Check out [home-assistant.io](https://home-assistant.io) for a [demo](https://home-assistant.io/demo/), installation [instructions](https://home-assistant.io/getting-started/), [tutorials](https://home-assistant.io/getting-started/automation/) and [documentation](https://home-assistant.io/docs/) + +![Screenshot](https://raw.githubusercontent.com/home-assistant/core/master/docs/screenshots.png) \ No newline at end of file diff --git a/apps/invidious/config.json b/apps/invidious/config.json new file mode 100644 index 00000000..d4d1415f --- /dev/null +++ b/apps/invidious/config.json @@ -0,0 +1,13 @@ +{ + "name": "Invidious", + "available": true, + "port": 8095, + "id": "invidious", + "categories": ["media", "social"], + "description": "Invidious is an open source alternative front-end to YouTube.", + "short_desc": "An alternative front-end to YouTube", + "author": "iv-org", + "source": "https://github.com/iv-org/invidious", + "image": "https://raw.githubusercontent.com/iv-org/invidious/master/assets/invidious-colored-vector.svg", + "form_fields": [] +} diff --git a/apps/invidious/data/init/init-invidious-db.sh b/apps/invidious/data/init/init-invidious-db.sh new file mode 100644 index 00000000..c86823dc --- /dev/null +++ b/apps/invidious/data/init/init-invidious-db.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -eou pipefail + +psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" +**Data import/export** +- Import subscriptions from YouTube, NewPipe and Freetube +- Import watch history from NewPipe +- Export subscriptions to NewPipe and Freetube +- Import/Export Invidious user data +
+**Technical features** +- Embedded video support +- [Developer API](https://docs.invidious.io/api/) +- Does not use official YouTube APIs +- No Contributor License Agreement (CLA) \ No newline at end of file diff --git a/apps/jackett/config.json b/apps/jackett/config.json new file mode 100644 index 00000000..ed27f38c --- /dev/null +++ b/apps/jackett/config.json @@ -0,0 +1,13 @@ +{ + "name": "Jackett", + "available": true, + "port": 8097, + "id": "jackett", + "description": "Jackett works as a proxy server: it translates queries from apps (Sonarr, Radarr, SickRage, CouchPotato, Mylar3, Lidarr, DuckieTV, qBittorrent, Nefarious etc.) into tracker-site-specific http queries, parses the html or json response, and then sends results back to the requesting software. This allows for getting recent uploads (like RSS) and performing searches.", + "short_desc": "API Support for your favorite torrent trackers ", + "categories": ["media", "utilities"], + "author": "", + "source": "https://github.com/Jackett/Jackett", + "image": "/logos/apps/jackett.jpg", + "form_fields": [] +} diff --git a/apps/jackett/docker-compose.yml b/apps/jackett/docker-compose.yml new file mode 100644 index 00000000..90462991 --- /dev/null +++ b/apps/jackett/docker-compose.yml @@ -0,0 +1,20 @@ +version: "3.7" +services: + jackett: + image: lscr.io/linuxserver/jackett:0.20.1342 + container_name: jackett + environment: + - PUID=1000 + - PGID=1000 + - TZ=${TZ} + - AUTO_UPDATE=true + dns: + - ${DNS_IP} + volumes: + - ${APP_DATA_DIR}/data:/config + - ${ROOT_FOLDER_HOST}/media/torrents:/media/torrents + ports: + - ${APP_PORT}:9117 + restart: unless-stopped + networks: + - tipi_main_network diff --git a/apps/jackett/metadata/description.md b/apps/jackett/metadata/description.md new file mode 100644 index 00000000..7d2fce91 --- /dev/null +++ b/apps/jackett/metadata/description.md @@ -0,0 +1,5 @@ +## API Support for your favorite torrent trackers + +Jackett works as a proxy server: it translates queries from apps ([Sonarr](https://github.com/Sonarr/Sonarr), [Radarr](https://github.com/Radarr/Radarr), [SickRage](https://sickrage.github.io/), [CouchPotato](https://couchpota.to/), [Mylar3](https://github.com/mylar3/mylar3), [Lidarr](https://github.com/lidarr/lidarr), [DuckieTV](https://github.com/SchizoDuckie/DuckieTV), [qBittorrent](https://www.qbittorrent.org/), [Nefarious](https://github.com/lardbit/nefarious) etc.) into tracker-site-specific http queries, parses the html or json response, and then sends results back to the requesting software. This allows for getting recent uploads (like RSS) and performing searches. Jackett is a single repository of maintained indexer scraping & translation logic - removing the burden from other apps. + +![Screenshot](https://raw.githubusercontent.com/Jackett/Jackett/master/.github/jackett-screenshot1.png) \ No newline at end of file diff --git a/apps/jellyfin/config.json b/apps/jellyfin/config.json new file mode 100644 index 00000000..95d08844 --- /dev/null +++ b/apps/jellyfin/config.json @@ -0,0 +1,13 @@ +{ + "name": "Jellyfin", + "available": true, + "port": 8091, + "id": "jellyfin", + "categories": ["media"], + "description": "Jellyfin is a Free Software Media System that puts you in control of managing and streaming your media. It is an alternative to the proprietary Emby and Plex, to provide media from a dedicated server to end-user devices via multiple apps. Jellyfin is descended from Emby's 3.5.2 release and ported to the .NET Core framework to enable full cross-platform support. There are no strings attached, no premium licenses or features, and no hidden agendas: just a team who want to build something better and work together to achieve it. We welcome anyone who is interested in joining us in our quest!", + "short_desc": "A media server for your home collection", + "author": "jellyfin.org", + "source": "https://github.com/jellyfin/jellyfin", + "image": "https://avatars.githubusercontent.com/u/45698031?s=200&v=4", + "form_fields": [] +} diff --git a/apps/jellyfin/data/config/.gitkeep b/apps/jellyfin/data/config/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/apps/jellyfin/docker-compose.yml b/apps/jellyfin/docker-compose.yml new file mode 100644 index 00000000..535736e3 --- /dev/null +++ b/apps/jellyfin/docker-compose.yml @@ -0,0 +1,18 @@ +version: "3.7" + +services: + jellyfin: + image: lscr.io/linuxserver/jellyfin:10.8.1 + container_name: jellyfin + volumes: + - ${APP_DATA_DIR}/data/config:/config + - ${ROOT_FOLDER_HOST}/media/data:/media/data + environment: + - PUID=1000 + - PGID=1000 + - TZ=${TZ} + restart: "unless-stopped" + ports: + - ${APP_PORT}:8096 + networks: + - tipi_main_network diff --git a/apps/jellyfin/metadata/description.md b/apps/jellyfin/metadata/description.md new file mode 100644 index 00000000..b280e86b --- /dev/null +++ b/apps/jellyfin/metadata/description.md @@ -0,0 +1,5 @@ +## A media server for your home collection + +Jellyfin is a Free Software Media System that puts you in control of managing and streaming your media. It is an alternative to the proprietary Emby and Plex, to provide media from a dedicated server to end-user devices via multiple apps. Jellyfin is descended from Emby's 3.5.2 release and ported to the .NET Core framework to enable full cross-platform support. There are no strings attached, no premium licenses or features, and no hidden agendas: just a team who want to build something better and work together to achieve it. We welcome anyone who is interested in joining us in our quest! + +For further details, please see [our documentation page](https://docs.jellyfin.org/). To receive the latest updates, get help with Jellyfin, and join the community, please visit [one of our communication channels](https://docs.jellyfin.org/general/getting-help.html). For more information about the project, please see our [about page](https://docs.jellyfin.org/general/about.html). \ No newline at end of file diff --git a/apps/joplin/README.md b/apps/joplin/README.md new file mode 100644 index 00000000..63665775 --- /dev/null +++ b/apps/joplin/README.md @@ -0,0 +1,13 @@ +Joplin is a free, open source note taking and to-do application, which can handle a large number of notes organised into notebooks. The notes are searchable, can be copied, tagged and modified either from the applications directly or from your own text editor. The notes are in Markdown format. +Notes exported from Evernote can be imported into Joplin, including the formatted content (which is converted to Markdown), resources (images, attachments, etc.) and complete metadata (geolocation, updated time, created time, etc.). Plain Markdown files can also be imported. + +The notes can be securely synchronised using end-to-end encryption with various cloud services including Nextcloud, Dropbox, OneDrive and Joplin Cloud. + +Full text search is available on all platforms to quickly find the information you need. The app can be customised using plugins and themes, and you can also easily create your own. + +The application is available for Windows, Linux, macOS, Android and iOS. A Web Clipper, to save web pages and screenshots from your browser, is also available for Firefox and Chrome. + +## Credentials + +Username: admin@localhost +Password: admin diff --git a/apps/joplin/config.json b/apps/joplin/config.json new file mode 100644 index 00000000..016012aa --- /dev/null +++ b/apps/joplin/config.json @@ -0,0 +1,14 @@ +{ + "name": "Joplin Server", + "available": true, + "port": 8099, + "id": "joplin", + "categories": ["utilities"], + "description": "Default credentials: admin@localhost / admin", + "short_desc": "Note taking and to-do application with synchronisation", + "author": "https://github.com/laurent22", + "source": "https://github.com/laurent22/joplin", + "website": "https://joplinapp.org", + "image": "/logos/apps/joplin.jpg", + "form_fields": [] +} diff --git a/apps/joplin/docker-compose.yml b/apps/joplin/docker-compose.yml new file mode 100644 index 00000000..9f1a4997 --- /dev/null +++ b/apps/joplin/docker-compose.yml @@ -0,0 +1,38 @@ +version: "3.7" + +services: + db-joplin: + container_name: db-joplin + image: postgres:14.2 + volumes: + - ${APP_DATA_DIR}/data/postgres:/var/lib/postgresql/data + restart: unless-stopped + environment: + - POSTGRES_PASSWORD=tipi + - POSTGRES_USER=tipi + - POSTGRES_DB=joplin + networks: + - tipi_main_network + + joplin: + container_name: joplin + image: florider89/joplin-server:2.7.4 + restart: unless-stopped + depends_on: + - db-joplin + ports: + - ${APP_PORT}:22300 + dns: + - ${DNS_IP} + environment: + - APP_PORT=22300 + - APP_BASE_URL=http://${INTERNAL_IP}:${APP_PORT} + - DB_CLIENT=pg + - POSTGRES_PASSWORD=tipi + - POSTGRES_USER=tipi + - POSTGRES_DATABASE=joplin + - POSTGRES_PORT=5432 + - POSTGRES_HOST=db-joplin + - MAX_TIME_DRIFT=0 + networks: + - tipi_main_network diff --git a/apps/joplin/metadata/description.md b/apps/joplin/metadata/description.md new file mode 100644 index 00000000..c21b2807 --- /dev/null +++ b/apps/joplin/metadata/description.md @@ -0,0 +1,17 @@ +## Note taking and to-do application with synchronisation + +- **username**: admin@localhost +- **password**: admin +
+ +Joplin is a free, open source note taking and to-do application, which can handle a large number of notes organised into notebooks. The notes are searchable, can be copied, tagged and modified either from the applications directly or from your own text editor. The notes are in Markdown format. + +Notes exported from Evernote can be imported into Joplin, including the formatted content (which is converted to Markdown), resources (images, attachments, etc.) and complete metadata (geolocation, updated time, created time, etc.). Plain Markdown files can also be imported. + +The notes can be securely synchronised using end-to-end encryption with various cloud services including Nextcloud, Dropbox, OneDrive and Joplin Cloud. + +Full text search is available on all platforms to quickly find the information you need. The app can be customised using plugins and themes, and you can also easily create your own. + +The application is available for Windows, Linux, macOS, Android and iOS. A Web Clipper, to save web pages and screenshots from your browser, is also available for Firefox and Chrome. + +![Screenshot](https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/home-top-img.png) \ No newline at end of file diff --git a/apps/libreddit/config.json b/apps/libreddit/config.json new file mode 100644 index 00000000..4bcaefec --- /dev/null +++ b/apps/libreddit/config.json @@ -0,0 +1,13 @@ +{ + "name": "LibReddit", + "available": true, + "port": 8105, + "id": "libreddit", + "categories": ["social"], + "description": "LibReddit is a bloat free reddit frontend written in Rust, no ads, no tracking and strong Content Security Policy prevents any request from going to reddit, everything is proxied.", + "short_desc": "Browse reddit without problems!", + "author": "spikecodes", + "source": "https://github.com/spikecodes/libreddit", + "image": "/logos/apps/libreddit.jpg", + "form_fields": [] +} diff --git a/apps/libreddit/docker-compose.arm.yml b/apps/libreddit/docker-compose.arm.yml new file mode 100644 index 00000000..1ab9b6c3 --- /dev/null +++ b/apps/libreddit/docker-compose.arm.yml @@ -0,0 +1,12 @@ +version: "3.7" +services: + libreddit: + container_name: libreddit + image: spikecodes/libreddit:arm + dns: + - ${DNS_IP} + ports: + - ${APP_PORT}:8080 + restart: unless-stopped + networks: + - tipi_main_network diff --git a/apps/libreddit/docker-compose.yml b/apps/libreddit/docker-compose.yml new file mode 100644 index 00000000..b5eaa195 --- /dev/null +++ b/apps/libreddit/docker-compose.yml @@ -0,0 +1,12 @@ +version: "3.7" +services: + libreddit: + container_name: libreddit + image: spikecodes/libreddit + dns: + - ${DNS_IP} + ports: + - ${APP_PORT}:8080 + restart: unless-stopped + networks: + - tipi_main_network diff --git a/apps/libreddit/metadata/description.md b/apps/libreddit/metadata/description.md new file mode 100644 index 00000000..5925ab9a --- /dev/null +++ b/apps/libreddit/metadata/description.md @@ -0,0 +1,12 @@ +## An alternative private front-end to Reddit + + +**10 second pitch:** Libreddit is a portmanteau of "libre" (meaning freedom) and "Reddit". It is a private front-end like [Invidious](https://github.com/iv-org/invidious) but for Reddit. Browse the coldest takes of [r/unpopularopinion](https://libreddit.spike.codes/r/unpopularopinion) without being [tracked](#reddit). + +- 🚀 Fast: written in Rust for blazing-fast speeds and memory safety +- ☁️ Light: no JavaScript, no ads, no tracking, no bloat +- 🕵 Private: all requests are proxied through the server, including media +- 🔒 Secure: strong [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) prevents browser requests to Reddit +
+ +![Screenshot](https://camo.githubusercontent.com/0753860e104fd86d32e13d47b31c8db88ec86bbdc66911480d92d20a96332c51/68747470733a2f2f692e6962622e636f2f515962715451742f6c69627265646469742d727573742e706e67) \ No newline at end of file diff --git a/apps/mealie/config.json b/apps/mealie/config.json new file mode 100644 index 00000000..b436d865 --- /dev/null +++ b/apps/mealie/config.json @@ -0,0 +1,13 @@ +{ + "name": "Mealie", + "port": 8114, + "available": true, + "id": "mealie", + "description": "Mealie is a self-hosted recipe manager and meal planner with a RestAPI backend and a reactive frontend application built in Vue for a pleasant user experience for the whole family. Easily add recipes into your database by providing the url and Mealie will automatically import the relevant data or add a family recipe with the UI editor. Mealie also provides an API for interactions from 3rd party applications. Default username / password is changeme@email.com / MyPassword", + "short_desc": "Mealie is a self-hosted recipe manager and meal planner.", + "author": "hay-kot", + "categories": [], + "source": "https://github.com/hay-kot/mealie", + "image": "https://raw.githubusercontent.com/hay-kot/mealie/mealie-next/frontend/static/icons/android-chrome-512x512.png", + "form_fields": [] +} diff --git a/apps/mealie/docker-compose.yml b/apps/mealie/docker-compose.yml new file mode 100644 index 00000000..af1f452a --- /dev/null +++ b/apps/mealie/docker-compose.yml @@ -0,0 +1,15 @@ +version: "3.7" +services: + mealie: + container_name: mealie + image: hkotel/mealie:v0.5.6 + restart: unless-stopped + ports: + - ${APP_PORT}:80 + environment: + PUID: 1000 + PGID: 1000 + volumes: + - ${APP_DATA_DIR}/data:/app/data + networks: + - tipi_main_network \ No newline at end of file diff --git a/apps/mealie/metadata/description.md b/apps/mealie/metadata/description.md new file mode 100644 index 00000000..d914d9da --- /dev/null +++ b/apps/mealie/metadata/description.md @@ -0,0 +1,9 @@ +## Mealie is a self-hosted recipe manager and meal planner. + +- **username**: changeme@email.com +- **password**: MyPassword +
+ +Mealie is a self hosted recipe manager and meal planner with a RestAPI backend and a reactive frontend application built in Vue for a pleasant user experience for the whole family. Easily add recipes into your database by providing the url and Mealie will automatically import the relevant data or add a family recipe with the UI editor. Mealie also provides an API for interactions from 3rd party applications. + +[![Product Name Screen Shot](https://raw.githubusercontent.com/hay-kot/mealie/mealie-next/docs/docs/assets/img/home_screenshot.png)](https://docs.mealie.io/) \ No newline at end of file diff --git a/apps/n8n/config.json b/apps/n8n/config.json new file mode 100644 index 00000000..f87884a9 --- /dev/null +++ b/apps/n8n/config.json @@ -0,0 +1,14 @@ +{ + "name": "n8n", + "available": true, + "port": 8094, + "id": "n8n", + "categories": ["automation"], + "description": "n8n is an extendable workflow automation tool. With a fair-code distribution model, n8n will always have visible source code, be available to self-host, and allow you to add your own custom functions, logic and apps. n8n's node-based approach makes it highly versatile, enabling you to connect anything to everything.", + "short_desc": "Workflow Automation Tool. Alternative to Zapier", + "author": "n8n.io", + "source": "https://github.com/n8n-io/n8n", + "website": "https://n8n.io/", + "image": "/logos/apps/n8n.jpg", + "form_fields": [] +} diff --git a/apps/n8n/docker-compose.yml b/apps/n8n/docker-compose.yml new file mode 100644 index 00000000..86743c25 --- /dev/null +++ b/apps/n8n/docker-compose.yml @@ -0,0 +1,36 @@ +version: "3.7" + +services: + db-n8n: + container_name: db-n8n + image: postgres:14.2 + restart: on-failure + volumes: + - ${APP_DATA_DIR}/data/db:/var/lib/postgresql/data + environment: + - POSTGRES_PASSWORD=tipi + - POSTGRES_USER=tipi + - POSTGRES_DB=n8n + networks: + - tipi_main_network + + n8n: + container_name: n8n + image: n8nio/n8n:0.186.1 + restart: unless-stopped + ports: + - ${APP_PORT}:5678 + volumes: + - ${APP_DATA_DIR}/data/n8n:/home/node/.n8n + command: /bin/sh -c "sleep 5; n8n start" + environment: + - DB-TYPE=postgresdb + - DB_POSTGRESDB_DATABASE=n8n + - DB_POSTGRESDB_HOST=db-n8n + - DB_POSTGRESDB_PORT=5432 + - DB_POSTGRESDB_USER=tipi + - DB_POSTGRESDB_PASSWORD=tipi + depends_on: + - db-n8n + networks: + - tipi_main_network diff --git a/apps/n8n/metadata/description.md b/apps/n8n/metadata/description.md new file mode 100644 index 00000000..810892f6 --- /dev/null +++ b/apps/n8n/metadata/description.md @@ -0,0 +1,6 @@ +## Easily automate tasks across different services. + +n8n is an extendable workflow automation tool. With a fair-code distribution model, n8n will always have visible source code, be available to self-host, and allow you to add your own custom functions, logic and apps. n8n's node-based approach makes it highly +versatile, enabling you to connect anything to everything. + +![Screenshot](https://raw.githubusercontent.com/n8n-io/n8n/master/assets/n8n-screenshot.png) \ No newline at end of file diff --git a/apps/nextcloud/config.json b/apps/nextcloud/config.json new file mode 100644 index 00000000..a9179c8d --- /dev/null +++ b/apps/nextcloud/config.json @@ -0,0 +1,30 @@ +{ + "name": "Nextcloud", + "available": true, + "port": 8083, + "id": "nextcloud", + "categories": ["data"], + "description": "Nextcloud is a self-hosted, open source, and fully-featured cloud storage solution for your personal files, office documents, and photos.", + "short_desc": "Productivity platform that keeps you in control", + "author": "Nextcloud GmbH", + "source": "https://github.com/nextcloud/server", + "image": "https://avatars.githubusercontent.com/u/19211038?s=200&v=4", + "form_fields": [ + { + "type": "text", + "label": "Username", + "max": 50, + "min": 3, + "required": true, + "env_variable": "NEXTCLOUD_ADMIN_USER" + }, + { + "type": "password", + "label": "Password", + "max": 50, + "min": 3, + "required": true, + "env_variable": "NEXTCLOUD_ADMIN_PASSWORD" + } + ] +} diff --git a/apps/nextcloud/data/nextcloud/.gitkeep b/apps/nextcloud/data/nextcloud/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/apps/nextcloud/data/redis/.gitkeep b/apps/nextcloud/data/redis/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/apps/nextcloud/docker-compose.yml b/apps/nextcloud/docker-compose.yml new file mode 100644 index 00000000..e35298aa --- /dev/null +++ b/apps/nextcloud/docker-compose.yml @@ -0,0 +1,67 @@ +version: "3.7" + +services: + db-nextcloud: + container_name: db-nextcloud + image: postgres:14.2 + restart: on-failure + volumes: + - ${APP_DATA_DIR}/data/db:/var/lib/postgresql/data + environment: + - POSTGRES_PASSWORD=tipi + - POSTGRES_USER=tipi + - POSTGRES_DB=nextcloud + networks: + - tipi_main_network + + redis-nextcloud: + container_name: redis-nextcloud + user: "1000:1000" + image: redis:6.2.6 + restart: on-failure + volumes: + - "${APP_DATA_DIR}/data/redis:/data" + networks: + - tipi_main_network + + cron: + image: nextcloud:24.0.3-apache + restart: on-failure + volumes: + - ${APP_DATA_DIR}/data/nextcloud:/var/www/html + entrypoint: /cron.sh + depends_on: + - db-nextcloud + - redis-nextcloud + networks: + - tipi_main_network + + nextcloud: + container_name: nextcloud + image: nextcloud:24.0.3-apache + restart: unless-stopped + ports: + - ${APP_PORT}:80 + volumes: + - ${APP_DATA_DIR}/data/nextcloud:/var/www/html + environment: + - POSTGRES_HOST=db-nextcloud + - REDIS_HOST=redis-nextcloud + - POSTGRES_PASSWORD=tipi + - POSTGRES_USER=tipi + - POSTGRES_DB=nextcloud + - NEXTCLOUD_ADMIN_USER=${NEXTCLOUD_ADMIN_USER} + - NEXTCLOUD_ADMIN_PASSWORD=${NEXTCLOUD_ADMIN_PASSWORD} + - NEXTCLOUD_TRUSTED_DOMAINS=${INTERNAL_IP}:${APP_PORT} + depends_on: + - db-nextcloud + - redis-nextcloud + networks: + - tipi_main_network + # labels: + # traefik.enable: true + # traefik.http.routers.nextcloud.rule: Host(`nextcloud.tipi.home`) + # traefik.http.routers.nextcloud.service: nextcloud + # traefik.http.routers.nextcloud.tls: true + # traefik.http.routers.nextcloud.entrypoints: websecure + # traefik.http.services.nextcloud.loadbalancer.server.port: 80 diff --git a/apps/nextcloud/metadata/description.md b/apps/nextcloud/metadata/description.md new file mode 100644 index 00000000..c8da741a --- /dev/null +++ b/apps/nextcloud/metadata/description.md @@ -0,0 +1,29 @@ +## A safe home for all your data. + +* 📁 **Access your Data** You can store your files, contacts, calendars and more on a server of your choosing. +* 🔄 **Sync your Data** You keep your files, contacts, calendars and more synchronized amongst your devices. +* 🙌 **Share your Data** …by giving others access to the stuff you want them to see or to collaborate with. +* 🚀 **Expandable with hundreds of Apps** ...like [Calendar](https://github.com/nextcloud/calendar), [Contacts](https://github.com/nextcloud/contacts), [Mail](https://github.com/nextcloud/mail), [Video Chat](https://github.com/nextcloud/spreed) and all those you can discover in our [App Store](https://apps.nextcloud.com) +* 🔒 **Security** with our encryption mechanisms, [HackerOne bounty program](https://hackerone.com/nextcloud) and two-factor authentication. + +You want to learn more about how you can use Nextcloud to access, share and protect your files, calendars, contacts, communication & more at home and at your organization? [**Learn about all our Features**](https://nextcloud.com/athome/). + +## Get your Nextcloud 🚚 + +- ☑️ [**Simply sign up**](https://nextcloud.com/signup/) at one of our providers either through our website or through the apps directly. +- 🖥 [**Install** a server by yourself](https://nextcloud.com/install/#instructions-server) on your own hardware or by using one of our ready to use **appliances** +- 📦 Buy one of the [awesome **devices** coming with a preinstalled Nextcloud](https://nextcloud.com/devices/) +- 🏢 Find a [service **provider**](https://nextcloud.com/providers/) who hosts Nextcloud for you or your company + +Enterprise? Public Sector or Education user? You may want to have a look into [**Nextcloud Enterprise**](https://nextcloud.com/enterprise/) provided by Nextcloud GmbH. + +## Get in touch 💬 + +* [📋 Forum](https://help.nextcloud.com) +* [👥 Facebook](https://www.facebook.com/nextclouders) +* [🐣 Twitter](https://twitter.com/Nextclouders) +* [🐘 Mastodon](https://mastodon.xyz/@nextcloud) + +You can also [get support for Nextcloud](https://nextcloud.com/support)! + +![](https://raw.githubusercontent.com/nextcloud/screenshots/master/files/Files%20Sharing.png) \ No newline at end of file diff --git a/apps/nitter/config.json b/apps/nitter/config.json new file mode 100644 index 00000000..e3af65d1 --- /dev/null +++ b/apps/nitter/config.json @@ -0,0 +1,13 @@ +{ + "name": "Nitter", + "available": true, + "port": 8106, + "id": "nitter", + "categories": ["social"], + "description": "A free and open source alternative Twitter front-end focused on privacy and performance.", + "short_desc": "Twitter without annoyances!", + "author": "zedeus", + "source": "https://github.com/zedeus/nitter", + "image": "/logos/apps/nitter.jpg", + "form_fields": [] +} diff --git a/apps/nitter/data/nitter.conf b/apps/nitter/data/nitter.conf new file mode 100644 index 00000000..5acc5be4 --- /dev/null +++ b/apps/nitter/data/nitter.conf @@ -0,0 +1,45 @@ +[Server] +address = "0.0.0.0" +port = 8080 +https = false # disable to enable cookies when not using https +httpMaxConnections = 100 +staticDir = "./public" +title = "nitter" +hostname = "" + +[Cache] +listMinutes = 240 # how long to cache list info (not the tweets, so keep it high) +rssMinutes = 10 # how long to cache rss queries +redisHost = "nitter-redis" # Change to "nitter-redis" if using docker-compose +redisPort = 6379 +redisPassword = "" +redisConnections = 20 # connection pool size +redisMaxConnections = 30 +# max, new connections are opened when none are available, but if the pool size +# goes above this, they're closed when released. don't worry about this unless +# you receive tons of requests per second + +[Config] +hmacKey = "secretkey" # random key for cryptographic signing of video urls +base64Media = false # use base64 encoding for proxied media urls +enableRSS = true # set this to false to disable RSS feeds +enableDebug = false # enable request logs and debug endpoints +proxy = "" # http/https url, SOCKS proxies are not supported +proxyAuth = "" +tokenCount = 10 +# minimum amount of usable tokens. tokens are used to authorize API requests, +# but they expire after ~1 hour, and have a limit of 187 requests. +# the limit gets reset every 15 minutes, and the pool is filled up so there's +# always at least $tokenCount usable tokens. again, only increase this if +# you receive major bursts all the time + +# Change default preferences here, see src/prefs_impl.nim for a complete list +[Preferences] +theme = "Nitter" +replaceTwitter = "" +replaceYouTube = "" +replaceReddit = "" +replaceInstagram = "" +proxyVideos = true +hlsPlayback = true +infiniteScroll = true \ No newline at end of file diff --git a/apps/nitter/docker-compose.yml b/apps/nitter/docker-compose.yml new file mode 100644 index 00000000..479cc285 --- /dev/null +++ b/apps/nitter/docker-compose.yml @@ -0,0 +1,24 @@ +version: "3.7" + +services: + nitter: + image: zedeus/nitter:latest + container_name: nitter + networks: + - tipi_main_network + ports: + - ${APP_PORT}:8080 + volumes: + - "${APP_DATA_DIR}/data/nitter.conf:/src/nitter.conf:ro" + depends_on: + - nitter-redis + restart: unless-stopped + nitter-redis: + image: redis:6-alpine + container_name: nitter-redis + networks: + - tipi_main_network + command: redis-server --save 60 1 --loglevel warning + volumes: + - "${APP_DATA_DIR}/data/redis:/data" + restart: unless-stopped \ No newline at end of file diff --git a/apps/nitter/metadata/description.md b/apps/nitter/metadata/description.md new file mode 100644 index 00000000..091ddf59 --- /dev/null +++ b/apps/nitter/metadata/description.md @@ -0,0 +1,16 @@ +## Alternative Twitter front-end + +A free and open source alternative Twitter front-end focused on privacy and performance. Inspired by the [Invidious](https://github.com/iv-org/invidious) project. + +- No JavaScript or ads +- All requests go through the backend, client never talks to Twitter +- Prevents Twitter from tracking your IP or JavaScript fingerprint +- Uses Twitter's unofficial API (no rate limits or developer account required) +- Lightweight (for [@nim_lang](https://nitter.net/nim_lang), 60KB vs 784KB from twitter.com) +- RSS feeds +- Themes +- Mobile support (responsive design) +- AGPLv3 licensed, no proprietary instances permitted +
+ +![Screenshot](https://raw.githubusercontent.com/zedeus/nitter/master/screenshot.png) \ No newline at end of file diff --git a/apps/nodered/config.json b/apps/nodered/config.json new file mode 100644 index 00000000..02cd2577 --- /dev/null +++ b/apps/nodered/config.json @@ -0,0 +1,13 @@ +{ + "name": "Node-RED", + "port": 8111, + "available": true, + "id": "nodered", + "categories": ["automation"], + "description": "Node-RED is a programming tool for wiring together hardware devices, APIs and online services in new and interesting ways. It provides a browser-based editor that makes it easy to wire together flows using the wide range of nodes in the palette that can be deployed to its runtime in a single-click.", + "short_desc": "Low-code programming for event-driven applications", + "author": "node-red", + "source": "https://github.com/node-red/node-red", + "image": "https://avatars.githubusercontent.com/u/5375661?s=200&v=4", + "form_fields": [] +} diff --git a/apps/nodered/data/settings.js b/apps/nodered/data/settings.js new file mode 100644 index 00000000..9138d419 --- /dev/null +++ b/apps/nodered/data/settings.js @@ -0,0 +1,499 @@ + +/** + * This is the default settings file provided by Node-RED. + * + * It can contain any valid JavaScript code that will get run when Node-RED + * is started. + * + * Lines that start with // are commented out. + * Each entry should be separated from the entries above and below by a comma ',' + * + * For more information about individual settings, refer to the documentation: + * https://nodered.org/docs/user-guide/runtime/configuration + * + * The settings are split into the following sections: + * - Flow File and User Directory Settings + * - Security + * - Server Settings + * - Runtime Settings + * - Editor Settings + * - Node Settings + * + **/ + + module.exports = { + + /******************************************************************************* + * Flow File and User Directory Settings + * - flowFile + * - credentialSecret + * - flowFilePretty + * - userDir + * - nodesDir + ******************************************************************************/ + + /** The file containing the flows. If not set, defaults to flows_.json **/ + flowFile: 'flows.json', + + /** By default, credentials are encrypted in storage using a generated key. To + * specify your own secret, set the following property. + * If you want to disable encryption of credentials, set this property to false. + * Note: once you set this property, do not change it - doing so will prevent + * node-red from being able to decrypt your existing credentials and they will be + * lost. + */ + //credentialSecret: "a-secret-key", + + /** By default, the flow JSON will be formatted over multiple lines making + * it easier to compare changes when using version control. + * To disable pretty-printing of the JSON set the following property to false. + */ + flowFilePretty: true, + + /** By default, all user data is stored in a directory called `.node-red` under + * the user's home directory. To use a different location, the following + * property can be used + */ + //userDir: '/home/nol/.node-red/', + + /** Node-RED scans the `nodes` directory in the userDir to find local node files. + * The following property can be used to specify an additional directory to scan. + */ + //nodesDir: '/home/nol/.node-red/nodes', + + /******************************************************************************* + * Security + * - adminAuth + * - https + * - httpsRefreshInterval + * - requireHttps + * - httpNodeAuth + * - httpStaticAuth + ******************************************************************************/ + + /** To password protect the Node-RED editor and admin API, the following + * property can be used. See http://nodered.org/docs/security.html for details. + */ + //adminAuth: { + // type: "credentials", + // users: [{ + // username: "admin", + // password: "$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN.", + // permissions: "*" + // }] + //}, + + /** The following property can be used to enable HTTPS + * This property can be either an object, containing both a (private) key + * and a (public) certificate, or a function that returns such an object. + * See http://nodejs.org/api/https.html#https_https_createserver_options_requestlistener + * for details of its contents. + */ + + /** Option 1: static object */ + //https: { + // key: require("fs").readFileSync('privkey.pem'), + // cert: require("fs").readFileSync('cert.pem') + //}, + + /** Option 2: function that returns the HTTP configuration object */ + // https: function() { + // // This function should return the options object, or a Promise + // // that resolves to the options object + // return { + // key: require("fs").readFileSync('privkey.pem'), + // cert: require("fs").readFileSync('cert.pem') + // } + // }, + + /** If the `https` setting is a function, the following setting can be used + * to set how often, in hours, the function will be called. That can be used + * to refresh any certificates. + */ + //httpsRefreshInterval : 12, + + /** The following property can be used to cause insecure HTTP connections to + * be redirected to HTTPS. + */ + //requireHttps: true, + + /** To password protect the node-defined HTTP endpoints (httpNodeRoot), + * including node-red-dashboard, or the static content (httpStatic), the + * following properties can be used. + * The `pass` field is a bcrypt hash of the password. + * See http://nodered.org/docs/security.html#generating-the-password-hash + */ + //httpNodeAuth: {user:"user",pass:"$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN."}, + //httpStaticAuth: {user:"user",pass:"$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN."}, + + /******************************************************************************* + * Server Settings + * - uiPort + * - uiHost + * - apiMaxLength + * - httpServerOptions + * - httpAdminRoot + * - httpAdminMiddleware + * - httpNodeRoot + * - httpNodeCors + * - httpNodeMiddleware + * - httpStatic + ******************************************************************************/ + + /** the tcp port that the Node-RED web server is listening on */ + uiPort: process.env.PORT || 1880, + + /** By default, the Node-RED UI accepts connections on all IPv4 interfaces. + * To listen on all IPv6 addresses, set uiHost to "::", + * The following property can be used to listen on a specific interface. For + * example, the following would only allow connections from the local machine. + */ + //uiHost: "127.0.0.1", + + /** The maximum size of HTTP request that will be accepted by the runtime api. + * Default: 5mb + */ + //apiMaxLength: '5mb', + + /** The following property can be used to pass custom options to the Express.js + * server used by Node-RED. For a full list of available options, refer + * to http://expressjs.com/en/api.html#app.settings.table + */ + //httpServerOptions: { }, + + /** By default, the Node-RED UI is available at http://localhost:1880/ + * The following property can be used to specify a different root path. + * If set to false, this is disabled. + */ + //httpAdminRoot: '/admin', + + /** The following property can be used to add a custom middleware function + * in front of all admin http routes. For example, to set custom http + * headers. It can be a single function or an array of middleware functions. + */ + // httpAdminMiddleware: function(req,res,next) { + // // Set the X-Frame-Options header to limit where the editor + // // can be embedded + // //res.set('X-Frame-Options', 'sameorigin'); + // next(); + // }, + + + /** Some nodes, such as HTTP In, can be used to listen for incoming http requests. + * By default, these are served relative to '/'. The following property + * can be used to specifiy a different root path. If set to false, this is + * disabled. + */ + //httpNodeRoot: '/red-nodes', + + /** The following property can be used to configure cross-origin resource sharing + * in the HTTP nodes. + * See https://github.com/troygoode/node-cors#configuration-options for + * details on its contents. The following is a basic permissive set of options: + */ + //httpNodeCors: { + // origin: "*", + // methods: "GET,PUT,POST,DELETE" + //}, + + /** If you need to set an http proxy please set an environment variable + * called http_proxy (or HTTP_PROXY) outside of Node-RED in the operating system. + * For example - http_proxy=http://myproxy.com:8080 + * (Setting it here will have no effect) + * You may also specify no_proxy (or NO_PROXY) to supply a comma separated + * list of domains to not proxy, eg - no_proxy=.acme.co,.acme.co.uk + */ + + /** The following property can be used to add a custom middleware function + * in front of all http in nodes. This allows custom authentication to be + * applied to all http in nodes, or any other sort of common request processing. + * It can be a single function or an array of middleware functions. + */ + //httpNodeMiddleware: function(req,res,next) { + // // Handle/reject the request, or pass it on to the http in node by calling next(); + // // Optionally skip our rawBodyParser by setting this to true; + // //req.skipRawBodyParser = true; + // next(); + //}, + + /** When httpAdminRoot is used to move the UI to a different root path, the + * following property can be used to identify a directory of static content + * that should be served at http://localhost:1880/. + */ + //httpStatic: '/home/nol/node-red-static/', + + /******************************************************************************* + * Runtime Settings + * - lang + * - logging + * - contextStorage + * - exportGlobalContextKeys + * - externalModules + ******************************************************************************/ + + /** Uncomment the following to run node-red in your preferred language. + * Available languages include: en-US (default), ja, de, zh-CN, zh-TW, ru, ko + * Some languages are more complete than others. + */ + // lang: "de", + + /** Configure the logging output */ + logging: { + /** Only console logging is currently supported */ + console: { + /** Level of logging to be recorded. Options are: + * fatal - only those errors which make the application unusable should be recorded + * error - record errors which are deemed fatal for a particular request + fatal errors + * warn - record problems which are non fatal + errors + fatal errors + * info - record information about the general running of the application + warn + error + fatal errors + * debug - record information which is more verbose than info + info + warn + error + fatal errors + * trace - record very detailed logging + debug + info + warn + error + fatal errors + * off - turn off all logging (doesn't affect metrics or audit) + */ + level: "info", + /** Whether or not to include metric events in the log output */ + metrics: false, + /** Whether or not to include audit events in the log output */ + audit: false + } + }, + + /** Context Storage + * The following property can be used to enable context storage. The configuration + * provided here will enable file-based context that flushes to disk every 30 seconds. + * Refer to the documentation for further options: https://nodered.org/docs/api/context/ + */ + //contextStorage: { + // default: { + // module:"localfilesystem" + // }, + //}, + + /** `global.keys()` returns a list of all properties set in global context. + * This allows them to be displayed in the Context Sidebar within the editor. + * In some circumstances it is not desirable to expose them to the editor. The + * following property can be used to hide any property set in `functionGlobalContext` + * from being list by `global.keys()`. + * By default, the property is set to false to avoid accidental exposure of + * their values. Setting this to true will cause the keys to be listed. + */ + exportGlobalContextKeys: false, + + /** Configure how the runtime will handle external npm modules. + * This covers: + * - whether the editor will allow new node modules to be installed + * - whether nodes, such as the Function node are allowed to have their + * own dynamically configured dependencies. + * The allow/denyList options can be used to limit what modules the runtime + * will install/load. It can use '*' as a wildcard that matches anything. + */ + externalModules: { + // autoInstall: false, /** Whether the runtime will attempt to automatically install missing modules */ + // autoInstallRetry: 30, /** Interval, in seconds, between reinstall attempts */ + // palette: { /** Configuration for the Palette Manager */ + // allowInstall: true, /** Enable the Palette Manager in the editor */ + // allowUpdate: true, /** Allow modules to be updated in the Palette Manager */ + // allowUpload: true, /** Allow module tgz files to be uploaded and installed */ + // allowList: ['*'], + // denyList: [], + // allowUpdateList: ['*'], + // denyUpdateList: [] + // }, + // modules: { /** Configuration for node-specified modules */ + // allowInstall: true, + // allowList: [], + // denyList: [] + // } + }, + + + /******************************************************************************* + * Editor Settings + * - disableEditor + * - editorTheme + ******************************************************************************/ + + /** The following property can be used to disable the editor. The admin API + * is not affected by this option. To disable both the editor and the admin + * API, use either the httpRoot or httpAdminRoot properties + */ + //disableEditor: false, + + /** Customising the editor + * See https://nodered.org/docs/user-guide/runtime/configuration#editor-themes + * for all available options. + */ + editorTheme: { + /** The following property can be used to set a custom theme for the editor. + * See https://github.com/node-red-contrib-themes/theme-collection for + * a collection of themes to chose from. + */ + //theme: "", + + /** To disable the 'Welcome to Node-RED' tour that is displayed the first + * time you access the editor for each release of Node-RED, set this to false + */ + //tours: false, + + palette: { + /** The following property can be used to order the categories in the editor + * palette. If a node's category is not in the list, the category will get + * added to the end of the palette. + * If not set, the following default order is used: + */ + //categories: ['subflows', 'common', 'function', 'network', 'sequence', 'parser', 'storage'], + }, + + projects: { + /** To enable the Projects feature, set this value to true */ + enabled: false, + workflow: { + /** Set the default projects workflow mode. + * - manual - you must manually commit changes + * - auto - changes are automatically committed + * This can be overridden per-user from the 'Git config' + * section of 'User Settings' within the editor + */ + mode: "manual" + } + }, + + codeEditor: { + /** Select the text editor component used by the editor. + * Defaults to "ace", but can be set to "ace" or "monaco" + */ + lib: "ace", + options: { + /** The follow options only apply if the editor is set to "monaco" + * + * theme - must match the file name of a theme in + * packages/node_modules/@node-red/editor-client/src/vendor/monaco/dist/theme + * e.g. "tomorrow-night", "upstream-sunburst", "github", "my-theme" + */ + theme: "vs", + /** other overrides can be set e.g. fontSize, fontFamily, fontLigatures etc. + * for the full list, see https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.istandaloneeditorconstructionoptions.html + */ + //fontSize: 14, + //fontFamily: "Cascadia Code, Fira Code, Consolas, 'Courier New', monospace", + //fontLigatures: true, + } + } + }, + + /******************************************************************************* + * Node Settings + * - fileWorkingDirectory + * - functionGlobalContext + * - functionExternalModules + * - nodeMessageBufferMaxLength + * - ui (for use with Node-RED Dashboard) + * - debugUseColors + * - debugMaxLength + * - execMaxBufferSize + * - httpRequestTimeout + * - mqttReconnectTime + * - serialReconnectTime + * - socketReconnectTime + * - socketTimeout + * - tcpMsgQueueSize + * - inboundWebSocketTimeout + * - tlsConfigDisableLocalFiles + * - webSocketNodeVerifyClient + ******************************************************************************/ + + /** The working directory to handle relative file paths from within the File nodes + * defaults to the working directory of the Node-RED process. + */ + //fileWorkingDirectory: "", + + /** Allow the Function node to load additional npm modules directly */ + functionExternalModules: true, + + /** The following property can be used to set predefined values in Global Context. + * This allows extra node modules to be made available with in Function node. + * For example, the following: + * functionGlobalContext: { os:require('os') } + * will allow the `os` module to be accessed in a Function node using: + * global.get("os") + */ + functionGlobalContext: { + // os:require('os'), + }, + + /** The maximum number of messages nodes will buffer internally as part of their + * operation. This applies across a range of nodes that operate on message sequences. + * defaults to no limit. A value of 0 also means no limit is applied. + */ + //nodeMessageBufferMaxLength: 0, + + /** If you installed the optional node-red-dashboard you can set it's path + * relative to httpNodeRoot + * Other optional properties include + * readOnly:{boolean}, + * middleware:{function or array}, (req,res,next) - http middleware + * ioMiddleware:{function or array}, (socket,next) - socket.io middleware + */ + //ui: { path: "ui" }, + + /** Colourise the console output of the debug node */ + //debugUseColors: true, + + /** The maximum length, in characters, of any message sent to the debug sidebar tab */ + debugMaxLength: 1000, + + /** Maximum buffer size for the exec node. Defaults to 10Mb */ + //execMaxBufferSize: 10000000, + + /** Timeout in milliseconds for HTTP request connections. Defaults to 120s */ + //httpRequestTimeout: 120000, + + /** Retry time in milliseconds for MQTT connections */ + mqttReconnectTime: 15000, + + /** Retry time in milliseconds for Serial port connections */ + serialReconnectTime: 15000, + + /** Retry time in milliseconds for TCP socket connections */ + //socketReconnectTime: 10000, + + /** Timeout in milliseconds for TCP server socket connections. Defaults to no timeout */ + //socketTimeout: 120000, + + /** Maximum number of messages to wait in queue while attempting to connect to TCP socket + * defaults to 1000 + */ + //tcpMsgQueueSize: 2000, + + /** Timeout in milliseconds for inbound WebSocket connections that do not + * match any configured node. Defaults to 5000 + */ + //inboundWebSocketTimeout: 5000, + + /** To disable the option for using local files for storing keys and + * certificates in the TLS configuration node, set this to true. + */ + //tlsConfigDisableLocalFiles: true, + + /** The following property can be used to verify websocket connection attempts. + * This allows, for example, the HTTP request headers to be checked to ensure + * they include valid authentication information. + */ + //webSocketNodeVerifyClient: function(info) { + // /** 'info' has three properties: + // * - origin : the value in the Origin header + // * - req : the HTTP request + // * - secure : true if req.connection.authorized or req.connection.encrypted is set + // * + // * The function should return true if the connection should be accepted, false otherwise. + // * + // * Alternatively, if this function is defined to accept a second argument, callback, + // * it can be used to verify the client asynchronously. + // * The callback takes three arguments: + // * - result : boolean, whether to accept the connection or not + // * - code : if result is false, the HTTP error status to return + // * - reason: if result is false, the HTTP reason string to return + // */ + //}, + } + \ No newline at end of file diff --git a/apps/nodered/docker-compose.yml b/apps/nodered/docker-compose.yml new file mode 100644 index 00000000..6784593a --- /dev/null +++ b/apps/nodered/docker-compose.yml @@ -0,0 +1,13 @@ +version: "3.7" + +services: + nodered: + container_name: nodered + image: nodered/node-red:3.0.0 + restart: unless-stopped + ports: + - ${APP_PORT}:1880 + volumes: + - ${APP_DATA_DIR}/data:/data + networks: + - tipi_main_network \ No newline at end of file diff --git a/apps/nodered/metadata/description.md b/apps/nodered/metadata/description.md new file mode 100644 index 00000000..af9ca0d7 --- /dev/null +++ b/apps/nodered/metadata/description.md @@ -0,0 +1,6 @@ +## Low-code programming for event-driven applications. + +Node-RED is a programming tool for wiring together hardware devices, APIs and online services in new and interesting ways. +It provides a browser-based editor that makes it easy to wire together flows using the wide range of nodes in the palette that can be deployed to its runtime in a single-click. + +![Screenshot](https://camo.githubusercontent.com/c7b6e0b937295c4d2c852130814050eb0caffac5b700ead6de21df6dbf83aa82/687474703a2f2f6e6f64657265642e6f72672f696d616765732f6e6f64652d7265642d73637265656e73686f742e706e67) \ No newline at end of file diff --git a/apps/overseerr/config.json b/apps/overseerr/config.json new file mode 100644 index 00000000..464dafad --- /dev/null +++ b/apps/overseerr/config.json @@ -0,0 +1,13 @@ +{ + "name": "Overseerr", + "available": true, + "port": 8116, + "id": "overseerr", + "categories": ["media", "utilities"], + "description": "Overseerr is a free and open source software application for managing requests for your media library. It integrates with your existing services, such as Sonarr, Radarr, and Plex!", + "short_desc": "Request management and media discovery tool for the Plex ecosystem", + "author": "sct", + "source": "https://github.com/sct/overseerr", + "image": "/logos/apps/overseerr.jpg", + "form_fields": [] +} diff --git a/apps/overseerr/docker-compose.yml b/apps/overseerr/docker-compose.yml new file mode 100644 index 00000000..77f33a6f --- /dev/null +++ b/apps/overseerr/docker-compose.yml @@ -0,0 +1,16 @@ +version: "3" +services: + overseerr: + container_name: overseerr + image: sctx/overseerr:latest + environment: + - TZ=${TZ} + volumes: + - ${APP_DATA_DIR}/data/config:/app/config + ports: + - ${APP_PORT}:5055 + restart: unless-stopped + dns: + - ${DNS_IP} + networks: + - tipi_main_network diff --git a/apps/overseerr/metadata/description.md b/apps/overseerr/metadata/description.md new file mode 100644 index 00000000..ef83a357 --- /dev/null +++ b/apps/overseerr/metadata/description.md @@ -0,0 +1,14 @@ +**Overseerr** is a free and open source software application for managing requests for your media library. It integrates with your existing services, such as **[Sonarr](https://sonarr.tv/)**, **[Radarr](https://radarr.video/)**, and **[Plex](https://www.plex.tv/)**! + +## Current Features + +- Full Plex integration. Authenticate and manage user access with Plex! +- Easy integration with your existing services. Currently, Overseerr supports Sonarr and Radarr. More to come! +- Plex library scan, to keep track of the titles which are already available. +- Customizable request system, which allows users to request individual seasons or movies in a friendly, easy-to-use interface. +- Incredibly simple request management UI. Don't dig through the app to simply approve recent requests! +- Granular permission system. +- Support for various notification agents. +- Mobile-friendly design, for when you need to approve requests on the go! + +With more features on the way! Check out our [issue tracker](https://github.com/sct/overseerr/issues) to see the features which have already been requested. \ No newline at end of file diff --git a/apps/photoprism/config.json b/apps/photoprism/config.json new file mode 100644 index 00000000..8b8ad100 --- /dev/null +++ b/apps/photoprism/config.json @@ -0,0 +1,22 @@ +{ + "name": "PhotoPrism", + "port": 8110, + "available": true, + "id": "photoprism", + "categories": ["photography"], + "description": "PhotoPrism® is an AI-Powered Photos App for the Decentralized Web. It makes use of the latest technologies to tag and find pictures automatically without getting in your way. You can run it at home, on a private server, or in the cloud. Default username: admin", + "short_desc": "AI-Powered Photos App for the Decentralized Web. We are on a mission to protect your freedom and privacy.", + "author": "PhotoPrism", + "source": "https://github.com/photoprism/photoprism", + "image": "/logos/apps/photoprism.jpg", + "form_fields": [ + { + "type": "password", + "label": "Photoprism admin password", + "max": 50, + "min": 8, + "required": true, + "env_variable": "PHOTOPRISM_ADMIN_PASSWORD" + } + ] +} diff --git a/apps/photoprism/docker-compose.yml b/apps/photoprism/docker-compose.yml new file mode 100644 index 00000000..1ffa33bc --- /dev/null +++ b/apps/photoprism/docker-compose.yml @@ -0,0 +1,59 @@ +version: "3.7" + +services: + photoprism: + # TODO: Special image for arm/v7 is available + image: photoprism/photoprism:latest + container_name: photoprism + depends_on: + - photoprism-db + restart: unless-stopped + ports: + - "${APP_PORT}:2342" + environment: + PHOTOPRISM_ADMIN_PASSWORD: ${PHOTOPRISM_ADMIN_PASSWORD} + PHOTOPRISM_SITE_URL: "http://localhost:2342/" + PHOTOPRISM_ORIGINALS_LIMIT: 5000 + PHOTOPRISM_HTTP_COMPRESSION: "gzip" + PHOTOPRISM_LOG_LEVEL: "info" + PHOTOPRISM_PUBLIC: "false" + PHOTOPRISM_READONLY: "false" + PHOTOPRISM_EXPERIMENTAL: "false" + PHOTOPRISM_DISABLE_CHOWN: "false" + PHOTOPRISM_DISABLE_WEBDAV: "false" + PHOTOPRISM_DISABLE_SETTINGS: "false" + PHOTOPRISM_DISABLE_TENSORFLOW: "false" + PHOTOPRISM_DISABLE_FACES: "false" + PHOTOPRISM_DISABLE_CLASSIFICATION: "false" + PHOTOPRISM_DISABLE_RAW: "false" + PHOTOPRISM_RAW_PRESETS: "false" + PHOTOPRISM_JPEG_QUALITY: 85 + PHOTOPRISM_DETECT_NSFW: "false" + PHOTOPRISM_UPLOAD_NSFW: "true" + PHOTOPRISM_DATABASE_DRIVER: "mysql" + PHOTOPRISM_DATABASE_SERVER: "photoprism-db:3306" + PHOTOPRISM_DATABASE_NAME: "photoprism" + PHOTOPRISM_DATABASE_USER: "photoprism" + PHOTOPRISM_DATABASE_PASSWORD: "photoprism" + PHOTOPRISM_SITE_CAPTION: "AI-Powered Photos App" + working_dir: "/photoprism" + volumes: + - "${APP_DATA_DIR}/data/photoprism/originals:/photoprism/originals" + - "${APP_DATA_DIR}/data/photoprism/storage:/photoprism/storage" + networks: + - tipi_main_network + + photoprism-db: + restart: unless-stopped + image: mariadb:10.8.3 + container_name: photoprism-db + command: mysqld --innodb-buffer-pool-size=128M --transaction-isolation=READ-COMMITTED --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --max-connections=512 --innodb-rollback-on-timeout=OFF --innodb-lock-wait-timeout=120 + volumes: + - "${APP_DATA_DIR}/data/mariadb:/var/lib/mysql" + environment: + MARIADB_DATABASE: "photoprism" + MARIADB_USER: "photoprism" + MARIADB_PASSWORD: "photoprism" + MARIADB_ROOT_PASSWORD: "photoprism" + networks: + - tipi_main_network diff --git a/apps/photoprism/metadata/description.md b/apps/photoprism/metadata/description.md new file mode 100644 index 00000000..f2fb525b --- /dev/null +++ b/apps/photoprism/metadata/description.md @@ -0,0 +1,9 @@ +## AI-Powered Photos App for the Decentralized Web 🌈💎✨ + +- **username**: admin +
+ +PhotoPrism® is an AI-Powered Photos App for the Decentralized Web. It makes use of the latest technologies to tag and find pictures automatically without getting in your way. You can run it at home, on a private server, or in the cloud. +To get a first impression, you are welcome to play with our [public demo](https://try.photoprism.app/). Be careful not to upload any private pictures. + +![Screenshot](https://camo.githubusercontent.com/5e03a87e47aad26ad7248b8b43eac6471fe96f7b655ac2e532697692753c3ff8/68747470733a2f2f646c2e70686f746f707269736d2e6170702f696d672f75692f6465736b746f702d3130303070782e6a7067) \ No newline at end of file diff --git a/apps/pihole/config.json b/apps/pihole/config.json new file mode 100644 index 00000000..ef73c36d --- /dev/null +++ b/apps/pihole/config.json @@ -0,0 +1,25 @@ +{ + "name": "Pi-hole", + "available": true, + "port": 8081, + "requirements": { + "ports": [53] + }, + "id": "pihole", + "categories": ["network", "security"], + "description": "The Pi-hole® is a DNS sinkhole that protects your devices from unwanted content without installing any client-side software.", + "short_desc": "A black hole for Internet advertisements", + "author": "pi-hole.net", + "source": "https://github.com/pi-hole/pi-hole", + "image": "/logos/apps/pihole.jpg", + "form_fields": [ + { + "type": "password", + "label": "Password", + "max": 50, + "min": 3, + "required": true, + "env_variable": "APP_PASSWORD" + } + ] +} diff --git a/apps/pihole/data/unbound/a-records.conf b/apps/pihole/data/unbound/a-records.conf new file mode 100644 index 00000000..7b1908f9 --- /dev/null +++ b/apps/pihole/data/unbound/a-records.conf @@ -0,0 +1,6 @@ + +# A Record + #local-data: "somecomputer.local. A 192.168.1.1" + +# PTR Record + #local-data-ptr: "192.168.1.1 somecomputer.local." \ No newline at end of file diff --git a/apps/pihole/data/unbound/root.hints b/apps/pihole/data/unbound/root.hints new file mode 100644 index 00000000..69d60632 --- /dev/null +++ b/apps/pihole/data/unbound/root.hints @@ -0,0 +1,92 @@ +; This file holds the information on root name servers needed to +; initialize cache of Internet domain name servers +; (e.g. reference this file in the "cache . " +; configuration file of BIND domain name servers). +; +; This file is made available by InterNIC +; under anonymous FTP as +; file /domain/named.cache +; on server FTP.INTERNIC.NET +; -OR- RS.INTERNIC.NET +; +; last update: December 07, 2021 +; related version of root zone: 2021120701 +; +; FORMERLY NS.INTERNIC.NET +; +. 3600000 NS A.ROOT-SERVERS.NET. +A.ROOT-SERVERS.NET. 3600000 A 198.41.0.4 +A.ROOT-SERVERS.NET. 3600000 AAAA 2001:503:ba3e::2:30 +; +; FORMERLY NS1.ISI.EDU +; +. 3600000 NS B.ROOT-SERVERS.NET. +B.ROOT-SERVERS.NET. 3600000 A 199.9.14.201 +B.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:200::b +; +; FORMERLY C.PSI.NET +; +. 3600000 NS C.ROOT-SERVERS.NET. +C.ROOT-SERVERS.NET. 3600000 A 192.33.4.12 +C.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:2::c +; +; FORMERLY TERP.UMD.EDU +; +. 3600000 NS D.ROOT-SERVERS.NET. +D.ROOT-SERVERS.NET. 3600000 A 199.7.91.13 +D.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:2d::d +; +; FORMERLY NS.NASA.GOV +; +. 3600000 NS E.ROOT-SERVERS.NET. +E.ROOT-SERVERS.NET. 3600000 A 192.203.230.10 +E.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:a8::e +; +; FORMERLY NS.ISC.ORG +; +. 3600000 NS F.ROOT-SERVERS.NET. +F.ROOT-SERVERS.NET. 3600000 A 192.5.5.241 +F.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:2f::f +; +; FORMERLY NS.NIC.DDN.MIL +; +. 3600000 NS G.ROOT-SERVERS.NET. +G.ROOT-SERVERS.NET. 3600000 A 192.112.36.4 +G.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:12::d0d +; +; FORMERLY AOS.ARL.ARMY.MIL +; +. 3600000 NS H.ROOT-SERVERS.NET. +H.ROOT-SERVERS.NET. 3600000 A 198.97.190.53 +H.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:1::53 +; +; FORMERLY NIC.NORDU.NET +; +. 3600000 NS I.ROOT-SERVERS.NET. +I.ROOT-SERVERS.NET. 3600000 A 192.36.148.17 +I.ROOT-SERVERS.NET. 3600000 AAAA 2001:7fe::53 +; +; OPERATED BY VERISIGN, INC. +; +. 3600000 NS J.ROOT-SERVERS.NET. +J.ROOT-SERVERS.NET. 3600000 A 192.58.128.30 +J.ROOT-SERVERS.NET. 3600000 AAAA 2001:503:c27::2:30 +; +; OPERATED BY RIPE NCC +; +. 3600000 NS K.ROOT-SERVERS.NET. +K.ROOT-SERVERS.NET. 3600000 A 193.0.14.129 +K.ROOT-SERVERS.NET. 3600000 AAAA 2001:7fd::1 +; +; OPERATED BY ICANN +; +. 3600000 NS L.ROOT-SERVERS.NET. +L.ROOT-SERVERS.NET. 3600000 A 199.7.83.42 +L.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:9f::42 +; +; OPERATED BY WIDE +; +. 3600000 NS M.ROOT-SERVERS.NET. +M.ROOT-SERVERS.NET. 3600000 A 202.12.27.33 +M.ROOT-SERVERS.NET. 3600000 AAAA 2001:dc3::35 +; End of file \ No newline at end of file diff --git a/apps/pihole/data/unbound/root.key b/apps/pihole/data/unbound/root.key new file mode 100644 index 00000000..c1c7a0c0 --- /dev/null +++ b/apps/pihole/data/unbound/root.key @@ -0,0 +1,9 @@ +; autotrust trust anchor file +;;id: . 1 +;;last_queried: 1650921300 ;;Mon Apr 25 21:15:00 2022 +;;last_success: 1650921300 ;;Mon Apr 25 21:15:00 2022 +;;next_probe_time: 1650962281 ;;Tue Apr 26 08:38:01 2022 +;;query_failed: 0 +;;query_interval: 43200 +;;retry_time: 8640 +. 86400 IN DNSKEY 257 3 8 AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3+/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQlNVz8Og8kvArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF0jLHwVN8efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7pr+eoZG+SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLYA4/ilBmSVIzuDWfdRUfhHdY6+cn8HFRm+2hM8AnXGXws9555KrUB5qihylGa8subX2Nn6UwNR1AkUTV74bU= ;{id = 20326 (ksk), size = 2048b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1650921210 ;;Mon Apr 25 21:13:30 2022 diff --git a/apps/pihole/data/unbound/unbound.conf b/apps/pihole/data/unbound/unbound.conf new file mode 100644 index 00000000..30f7f3e2 --- /dev/null +++ b/apps/pihole/data/unbound/unbound.conf @@ -0,0 +1,136 @@ +# https://linux.die.net/man/5/unbound.conf +# https://docs.pi-hole.net/guides/unbound/ + +server: + # Enable or disable whether the unbound server forks into the background + # as a daemon. Default is yes. + do-daemonize: no + + # If given, after binding the port the user privileges are dropped. + # Default is "unbound". If you give username: "" no user change is performed. + username: "" + + # No need to chroot as this container has been stripped of all other binaries. + chroot: "" + + # If "" is given, logging goes to stderr, or nowhere once daemonized. + logfile: "" + + # The process id is written to the file. Not required since we are running + # in a container with one process. + pidfile: "" + + # The verbosity number, level 0 means no verbosity, only errors. + # Level 1 gives operational information. + # Level 2 gives detailed operational information. + # Level 3 gives query level information, output per query. + # Level 4 gives algorithm level information. + # Level 5 logs client identification for cache misses. + # Default is level 1. The verbosity can also be increased from the commandline. + verbosity: 1 + + # Listen on all ipv4 interfaces, answer queries from the local subnet. + interface: 0.0.0.0 + + # The port number, default 53, on which the server responds to queries. + port: 53 + + do-ip4: yes + do-udp: yes + do-tcp: yes + do-ip6: no + + # You want to leave this to no unless you have *native* IPv6. With 6to4 and + # Terredo tunnels your web browser should favor IPv4 for the same reasons + prefer-ip6: no + + # Trust glue only if it is within the server's authority + harden-glue: yes + + # Require DNSSEC data for trust-anchored zones, if such data is absent, the zone becomes BOGUS + harden-dnssec-stripped: yes + + # Don't use Capitalization randomization as it known to cause DNSSEC issues sometimes + # see https://discourse.pi-hole.net/t/unbound-stubby-or-dnscrypt-proxy/9378 for further details + use-caps-for-id: no + + # Reduce EDNS reassembly buffer size (see also https://docs.pi-hole.net/guides/dns/unbound/ ) + # IP fragmentation is unreliable on the Internet today, and can cause + # transmission failures when large DNS messages are sent via UDP. Even + # when fragmentation does work, it may not be secure; it is theoretically + # possible to spoof parts of a fragmented DNS message, without easy + # detection at the receiving end. Recently, there was an excellent study + # >>> Defragmenting DNS - Determining the optimal maximum UDP response size for DNS <<< + # by Axel Koolhaas, and Tjeerd Slokker (https://indico.dns-oarc.net/event/36/contributions/776/) + # in collaboration with NLnet Labs explored DNS using real world data from the + # the RIPE Atlas probes and the researchers suggested different values for + # IPv4 and IPv6 and in different scenarios. They advise that servers should + # be configured to limit DNS messages sent over UDP to a size that will not + # trigger fragmentation on typical network links. DNS servers can switch + # from UDP to TCP when a DNS response is too big to fit in this limited + # buffer size. This value has also been suggested in DNS Flag Day 2020. + edns-buffer-size: 1232 + + # Perform prefetching of close to expired message cache entries + # This only applies to domains that have been frequently queried + prefetch: yes + + # One thread should be sufficient, can be increased on beefy machines. + # In reality for most users running on small networks or on a single machine, + # it should be unnecessary to seek performance enhancement by increasing num-threads above 1. + num-threads: 1 + + # Ensure kernel buffer is large enough to not lose messages in traffic spikes + # (requires CAP_NET_ADMIN or privileged) + # so-rcvbuf: 1m + + # The netblock is given as an IP4 or IP6 address with /size appended for a + # classless network block. The action can be deny, refuse, allow or allow_snoop. + access-control: 127.0.0.1/32 allow + access-control: 192.168.0.0/16 allow + access-control: 172.16.0.0/12 allow + access-control: 10.0.0.0/8 allow + access-control: 100.64.0.0/10 allow + access-control: 10.21.21.0/24 allow + + # Ensure privacy of local IP ranges + private-address: 192.168.0.0/16 + private-address: 169.254.0.0/16 + private-address: 172.16.0.0/12 + private-address: 10.0.0.0/8 + private-address: fd00::/8 + private-address: fe80::/10 + + # Read the root hints from this file. Default is nothing, using built in + # hints for the IN class. The file has the format of zone files, with root + # nameserver names and addresses only. The default may become outdated, + # when servers change, therefore it is good practice to use a root-hints + # file. get one from https://www.internic.net/domain/named.root + root-hints: /etc/unbound/root.hints + + # File with trust anchor for one zone, which is tracked with RFC5011 probes. + # The probes are several times per month, thus the machine must be online frequently. + # The initial file can be one with contents as described in trust-anchor-file. + # The file is written to when the anchor is updated, so the unbound user must + # have write permission. + auto-trust-anchor-file: /etc/unbound/root.key + + # Number of ports to open. This number of file descriptors can be opened per thread. + # Must be at least 1. Default depends on compile options. Larger numbers need extra + # resources from the operating system. For performance a very large value is best, + # use libevent to make this possible. + outgoing-range: 8192 + + # The number of queries that every thread will service simultaneously. If more queries + # arrive that need servicing, and no queries can be jostled out (see jostle-timeout), + # then the queries are dropped. This forces the client to resend after a timeout; + # allowing the server time to work on the existing queries. Default depends on + # compile options, 512 or 1024. + num-queries-per-thread: 4096 + + include: /etc/unbound/a-records.conf + + # forward-zone: + # name: "." + # forward-addr: 194.242.2.3@853 # Mullvad primary + # forward-addr: 193.19.108.3@853 # Mullvad secondary diff --git a/apps/pihole/docker-compose.yml b/apps/pihole/docker-compose.yml new file mode 100644 index 00000000..e3d47d26 --- /dev/null +++ b/apps/pihole/docker-compose.yml @@ -0,0 +1,39 @@ +version: "3.7" + +services: + # unbound: + # image: "klutchell/unbound" + # container_name: unbound + # restart: unless-stopped + # volumes: + # - "${APP_DATA_DIR}/data/unbound:/etc/unbound" + # networks: + # tipi_main_network: + # ipv4_address: 10.21.21.200 + + pihole: + # depends_on: [unbound] + container_name: pihole + image: pihole/pihole:2022.07.1 + restart: unless-stopped + hostname: pihole + dns: + - 127.0.0.1 + # - 10.21.21.200 # Points to unbound + ports: + - 53:53/tcp + - 53:53/udp + - ${APP_PORT}:80 + volumes: + - ${APP_DATA_DIR}/data/pihole:/etc/pihole + - ${APP_DATA_DIR}/data/dnsmasq:/etc/dnsmasq.d + environment: + TZ: ${TZ} + WEBPASSWORD: ${APP_PASSWORD} + # PIHOLE_DNS_: 10.21.21.200 # Points to unbound + FTLCONF_REPLY_ADDR4: 10.21.21.201 + cap_add: + - NET_ADMIN + networks: + tipi_main_network: + ipv4_address: 10.21.21.201 diff --git a/apps/pihole/metadata/description.md b/apps/pihole/metadata/description.md new file mode 100644 index 00000000..5062451e --- /dev/null +++ b/apps/pihole/metadata/description.md @@ -0,0 +1,14 @@ +## A black hole for Internet advertisements + +The Pi-hole® is a [DNS sinkhole](https://en.wikipedia.org/wiki/DNS_Sinkhole) that protects your devices from unwanted content without installing any client-side software. + +- **Easy-to-install**: our versatile installer walks you through the process and takes less than ten minutes +- **Resolute**: content is blocked in _non-browser locations_, such as ad-laden mobile apps and smart TVs +- **Responsive**: seamlessly speeds up the feel of everyday browsing by caching DNS queries +- **Lightweight**: runs smoothly with [minimal hardware and software requirements](https://docs.pi-hole.net/main/prerequisites/) +- **Robust**: a command line interface that is quality assured for interoperability +- **Insightful**: a beautiful responsive Web Interface dashboard to view and control your Pi-hole +- **Versatile**: can optionally function as a [DHCP server](https://discourse.pi-hole.net/t/how-do-i-use-pi-holes-built-in-dhcp-server-and-why-would-i-want-to/3026), ensuring *all* your devices are protected automatically +- **Scalable**: [capable of handling hundreds of millions of queries](https://pi-hole.net/2017/05/24/how-much-traffic-can-pi-hole-handle/) when installed on server-grade hardware +- **Modern**: blocks ads over both IPv4 and IPv6 +- **Free**: open source software that helps ensure _you_ are the sole person in control of your privacy \ No newline at end of file diff --git a/apps/plex/config.json b/apps/plex/config.json new file mode 100644 index 00000000..ea51bcea --- /dev/null +++ b/apps/plex/config.json @@ -0,0 +1,14 @@ +{ + "name": "Plex", + "available": true, + "port": 32400, + "id": "plex", + "url_suffix": "/web", + "categories": ["media"], + "description": "", + "short_desc": "Stream Movies & TV Shows", + "author": "plexinc", + "source": "https://github.com/plexinc/pms-docker", + "image": "/logos/apps/plex.png", + "form_fields": [] +} diff --git a/apps/plex/docker-compose.yml b/apps/plex/docker-compose.yml new file mode 100644 index 00000000..00555764 --- /dev/null +++ b/apps/plex/docker-compose.yml @@ -0,0 +1,15 @@ +version: "3.7" + +services: + plex: + image: lscr.io/linuxserver/plex:1.27.2 + container_name: plex + network_mode: host + environment: + - PUID=1000 + - PGID=1000 + - VERSION=docker + volumes: + - ${APP_DATA_DIR}/data/config:/config + - ${ROOT_FOLDER_HOST}/media/data:/media + restart: unless-stopped diff --git a/apps/plex/metadata/description.md b/apps/plex/metadata/description.md new file mode 100644 index 00000000..81b0fe40 --- /dev/null +++ b/apps/plex/metadata/description.md @@ -0,0 +1,5 @@ +## Stream Movies & TV Shows + +Plex Media Server is a digital media player and organizational tool that allows you to access the music, pictures, and videos stored on one computer with any other computer or compatible mobile device. You can install the Plex Media Server software on a Windows, Mac, or Linux computer, or a compatible network-attached storage (NAS) device, then play it back on any other internet-connected device capable of running the Plex app. + +Use any compatible device to watch movies, listen to music, and view pictures stored on a computer that runs Plex Media Server. Access media files stored on your Plex Media Server computer remotely over the internet. Allow friends and family to access your movies, music, and pictures over the internet. \ No newline at end of file diff --git a/apps/portainer/config.json b/apps/portainer/config.json new file mode 100644 index 00000000..f5c6ad22 --- /dev/null +++ b/apps/portainer/config.json @@ -0,0 +1,13 @@ +{ + "name": "Portainer", + "port": 9443, + "available": true, + "id": "portainer", + "categories": ["utilities"], + "description": "", + "short_desc": "Making Docker and Kubernetes management easy.", + "author": "portainer.io", + "source": "https://github.com/portainer/portainer", + "image": "/logos/apps/portainer.jpg", + "form_fields": [] +} diff --git a/apps/portainer/docker-compose.yml b/apps/portainer/docker-compose.yml new file mode 100644 index 00000000..2d95f435 --- /dev/null +++ b/apps/portainer/docker-compose.yml @@ -0,0 +1,14 @@ +version: "3.9" + +services: + portainer: + image: portainer/portainer-ce:latest + container_name: portainer + restart: unless-stopped + ports: + - "${APP_PORT}:9443" + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - "${APP_DATA_DIR}/data:/data" + networks: + - tipi_main_network \ No newline at end of file diff --git a/apps/portainer/metadata/description.md b/apps/portainer/metadata/description.md new file mode 100644 index 00000000..6567921c --- /dev/null +++ b/apps/portainer/metadata/description.md @@ -0,0 +1,6 @@ + +![Screenshot](https://github.com/portainer/portainer/blob/develop/app/assets/images/portainer-github-banner.png?raw=true) + +**Portainer Community Edition** is a lightweight service delivery platform for containerized applications that can be used to manage Docker, Swarm, Kubernetes and ACI environments. It is designed to be as simple to deploy as it is to use. The application allows you to manage all your orchestrator resources (containers, images, volumes, networks and more) through a ‘smart’ GUI and/or an extensive API. + +Portainer consists of a single container that can run on any cluster. It can be deployed as a Linux container or a Windows native container. \ No newline at end of file diff --git a/apps/prowlarr/config.json b/apps/prowlarr/config.json new file mode 100644 index 00000000..7b67fde5 --- /dev/null +++ b/apps/prowlarr/config.json @@ -0,0 +1,13 @@ +{ + "name": "Prowlarr", + "available": true, + "port": 8109, + "id": "prowlarr", + "categories": ["media", "utilities"], + "description": "Prowlarr is an indexer manager/proxy built on the popular *arr .net/reactjs base stack to integrate with your various PVR apps. Prowlarr supports management of both Torrent Trackers and Usenet Indexers. It integrates seamlessly with Lidarr, Mylar3, Radarr, Readarr, and Sonarr offering complete management of your indexers with no per app Indexer setup required (we do it all).", + "short_desc": "A torrent/usenet indexer manager/proxy", + "author": "Prowlarr", + "source": "https://github.com/Prowlarr/Prowlarr/", + "image": "/logos/apps/prowlarr.jpg", + "form_fields": [] +} diff --git a/apps/prowlarr/docker-compose.yml b/apps/prowlarr/docker-compose.yml new file mode 100644 index 00000000..629babec --- /dev/null +++ b/apps/prowlarr/docker-compose.yml @@ -0,0 +1,16 @@ +version: "3.7" +services: + prowlarr: # Should be exact same name as "id" field in config.json + container_name: prowlarr # Should be exact same name as "id" field in config.json + image: ghcr.io/linuxserver/prowlarr:develop + environment: + - TZ=${TZ} # Can use any env variable. List in runtipi/templates/env-sample + dns: + - ${DNS_IP} + volumes: + - ${APP_DATA_DIR}/data/config:/config #Always start the path with ${APP_DATA_DIR}. This will put all data inside app-data/my-app/data + ports: + - ${APP_PORT}:9696 + restart: unless-stopped + networks: + - tipi_main_network diff --git a/apps/prowlarr/metadata/description.md b/apps/prowlarr/metadata/description.md new file mode 100644 index 00000000..7a1fe674 --- /dev/null +++ b/apps/prowlarr/metadata/description.md @@ -0,0 +1,18 @@ +## A torrent/usenet indexer manager/proxy + +Prowlarr is an indexer manager/proxy built on the popular *arr .net/reactjs base stack to integrate with your various PVR apps. Prowlarr supports management of both Torrent Trackers and Usenet Indexers. It integrates seamlessly with Lidarr, Mylar3, Radarr, Readarr, and Sonarr offering complete management of your indexers with no per app Indexer setup required (we do it all). + +### Major Features Include + +- Usenet support for 24 indexers natively, including Headphones VIP +- Usenet support for any Newznab compatible indexer via "Generic Newznab" +- Torrent support for over 500 trackers with more added all the time +- Torrent support for any Torznab compatible tracker via "Generic Torznab" +- Support for custom YML definitions via Cardigann that includes JSON and XML parsing +- Indexer Sync to Lidarr/Mylar3/Radarr/Readarr/Sonarr, so no manual configuration of the other applications are required +- Indexer history and statistics +- Manual searching of Trackers & Indexers at a category level +- Parameter based manual searching +- Support for pushing multiple releases at once directly to your download clients from Prowlarr +- Indexer health and status notifications +- Per Indexer proxy support (SOCKS4, SOCKS5, HTTP, Flaresolverr) \ No newline at end of file diff --git a/apps/radarr/config.json b/apps/radarr/config.json new file mode 100644 index 00000000..dad907e5 --- /dev/null +++ b/apps/radarr/config.json @@ -0,0 +1,13 @@ +{ + "name": "Radarr", + "available": true, + "port": 8088, + "id": "radarr", + "categories": ["media", "utilities"], + "description": "Radarr is a movie collection manager for Usenet and BitTorrent users. It can monitor multiple RSS feeds for new movies and will interface with clients and indexers to grab, sort, and rename them. It can also be configured to automatically upgrade the quality of existing files in the library when a better quality format becomes available. Note that only one type of a given movie is supported. If you want both an 4k version and 1080p version of a given movie you will need multiple instances.", + "short_desc": "Movie collection manager for Usenet and BitTorrent users.", + "author": "radarr.video", + "source": "https://github.com/Radarr/Radarr", + "image": "/logos/apps/radarr.jpg", + "form_fields": [] +} diff --git a/apps/radarr/docker-compose.yml b/apps/radarr/docker-compose.yml new file mode 100644 index 00000000..8a880300 --- /dev/null +++ b/apps/radarr/docker-compose.yml @@ -0,0 +1,20 @@ +version: "3.7" +services: + radarr: + image: lscr.io/linuxserver/radarr:4.1.0 + container_name: radarr + environment: + - PUID=1000 + - PGID=1000 + - TZ=${TZ} + dns: + - ${DNS_IP} + volumes: + - /etc/localtime:/etc/localtime:ro + - ${APP_DATA_DIR}/data:/config + - ${ROOT_FOLDER_HOST}/media:/media + ports: + - ${APP_PORT}:7878 + restart: unless-stopped + networks: + - tipi_main_network diff --git a/apps/radarr/metadata/description.md b/apps/radarr/metadata/description.md new file mode 100644 index 00000000..d68512b0 --- /dev/null +++ b/apps/radarr/metadata/description.md @@ -0,0 +1,23 @@ +## A fork of Sonarr to work with movies à la Couchpotato. + +Radarr is a movie collection manager for Usenet and BitTorrent users. It can monitor multiple RSS feeds for new movies and will interface with clients and indexers to grab, sort, and rename them. It can also be configured to automatically upgrade the quality of existing files in the library when a better quality format becomes available. Note that only one type of a given movie is supported. If you want both an 4k version and 1080p version of a given movie you will need multiple instances. + +### Major Features Include + +* Adding new movies with lots of information, such as trailers, ratings, etc. +* Support for major platforms: Windows, Linux, macOS, Raspberry Pi, etc. +* Can watch for better quality of the movies you have and do an automatic upgrade. *e.g. from DVD to Blu-Ray* +* Automatic failed download handling will try another release if one fails +* Manual search so you can pick any release or to see why a release was not downloaded automatically +* Full integration with SABnzbd and NZBGet +* Automatically searching for releases as well as RSS Sync +* Automatically importing downloaded movies +* Recognizing Special Editions, Director's Cut, etc. +* Identifying releases with hardcoded subs +* Identifying releases with AKA movie names +* SABnzbd, NZBGet, QBittorrent, Deluge, rTorrent, Transmission, uTorrent, and other download clients are supported and integrated +* Full integration with Kodi and Plex (notifications, library updates) +* Importing Metadata such as trailers or subtitles +* Adding metadata such as posters and information for Kodi and others to use +* Advanced customization for profiles, such that Radarr will always download the copy you want +* A beautiful UI \ No newline at end of file diff --git a/apps/readarr/config.json b/apps/readarr/config.json new file mode 100644 index 00000000..3ed11512 --- /dev/null +++ b/apps/readarr/config.json @@ -0,0 +1,13 @@ +{ + "name": "Readarr", + "available": true, + "port": 8112, + "id": "readarr", + "categories": ["books", "media"], + "description": "", + "short_desc": "Book Manager and Automation (Sonarr for Ebooks)", + "author": "readarr.com", + "source": "https://github.com/Readarr/Readarr", + "image": "/logos/apps/readarr.jpg", + "form_fields": [] +} diff --git a/apps/readarr/docker-compose.yml b/apps/readarr/docker-compose.yml new file mode 100644 index 00000000..f687e65f --- /dev/null +++ b/apps/readarr/docker-compose.yml @@ -0,0 +1,20 @@ +version: "3.9" +services: + readarr: + image: lscr.io/linuxserver/readarr:develop + container_name: readarr + environment: + - PUID=1000 + - PGID=1000 + - TZ=${TZ} + dns: + - ${DNS_IP} + volumes: + - /etc/localtime:/etc/localtime:ro + - ${APP_DATA_DIR}/data:/config + - ${ROOT_FOLDER_HOST}/media:/media + ports: + - ${APP_PORT}:8787 + restart: unless-stopped + networks: + - tipi_main_network diff --git a/apps/readarr/metadata/description.md b/apps/readarr/metadata/description.md new file mode 100644 index 00000000..b1652ea7 --- /dev/null +++ b/apps/readarr/metadata/description.md @@ -0,0 +1,22 @@ +Readarr is an ebook and audiobook collection manager for Usenet and BitTorrent users. It can monitor multiple RSS feeds for new books from your favorite authors and will grab, sort, and rename them. +Note that only one type of a given book is supported. If you want both an audiobook and ebook of a given book you will need multiple instances. + +## Major Features Include + +* Can watch for better quality of the ebooks and audiobooks you have and do an automatic upgrade. *e.g. from PDF to AZW3* +* Support for major platforms: Windows, Linux, macOS, Raspberry Pi, etc. +* Automatically detects new books +* Can scan your existing library and download any missing books +* Automatic failed download handling will try another release if one fails +* Manual search so you can pick any release or to see why a release was not downloaded automatically +* Advanced customization for profiles, such that Readarr will always download the copy you want +* Fully configurable book renaming +* SABnzbd, NZBGet, QBittorrent, Deluge, rTorrent, Transmission, uTorrent, and other download clients are supported and integrated +* Full integration with Calibre (add to library, conversion) (Requires Calibre Content Server) +* And a beautiful UI + +## Support + +[![Wiki](https://img.shields.io/badge/servarr-wiki-181717.svg?maxAge=60)](https://wiki.servarr.com/readarr) +[![Discord](https://img.shields.io/badge/discord-chat-7289DA.svg?maxAge=60)](https://readarr.com/discord) +[![Reddit](https://img.shields.io/badge/reddit-discussion-FF4500.svg?maxAge=60)](https://www.reddit.com/r/readarr) \ No newline at end of file diff --git a/apps/resilio-sync/config.json b/apps/resilio-sync/config.json new file mode 100644 index 00000000..77b96040 --- /dev/null +++ b/apps/resilio-sync/config.json @@ -0,0 +1,13 @@ +{ + "name": "Resilio", + "port": 8113, + "available": true, + "id": "resilio-sync", + "categories": ["data", "utilities"], + "description": "", + "short_desc": "Resilio Sync is a fast, reliable, and simple file sync and share solution, powered by P2P technology", + "author": "Resilio, Inc.", + "source": "https://github.com/bt-sync", + "image": "/logos/apps/resilio-sync.png", + "form_fields": [] +} diff --git a/apps/resilio-sync/docker-compose.yml b/apps/resilio-sync/docker-compose.yml new file mode 100644 index 00000000..a2dab643 --- /dev/null +++ b/apps/resilio-sync/docker-compose.yml @@ -0,0 +1,18 @@ +version: "3.7" +services: + resilio-sync: + image: lscr.io/linuxserver/resilio-sync:2.7.3 + container_name: resilio-sync + environment: + - PUID=1000 + - PGID=1000 + volumes: + - ${APP_DATA_DIR}/data/config:/config + - ${APP_DATA_DIR}/data/downloads:/downloads + - ${APP_DATA_DIR}/data/sync:/sync + ports: + - ${APP_PORT}:8888 + - 55555:55555 + restart: unless-stopped + networks: + - tipi_main_network \ No newline at end of file diff --git a/apps/resilio-sync/metadata/description.md b/apps/resilio-sync/metadata/description.md new file mode 100644 index 00000000..8173c323 --- /dev/null +++ b/apps/resilio-sync/metadata/description.md @@ -0,0 +1,3 @@ +[Resilio-sync](https://www.resilio.com/individuals/) (formerly BitTorrent Sync) uses the BitTorrent protocol to sync files and folders between all of your devices. There are both free and paid versions, this container supports both. There is an official sync image but we created this one as it supports user mapping to simplify permissions for volumes. + +[![resilio-sync](https://www.resilio.com/img/individual/freeproduct.jpg)](https://www.resilio.com/individuals/) diff --git a/apps/simple-torrent/config.json b/apps/simple-torrent/config.json new file mode 100644 index 00000000..d1ff9c88 --- /dev/null +++ b/apps/simple-torrent/config.json @@ -0,0 +1,11 @@ +{ + "name": "Simple Torrent", + "port": 8085, + "id": "simple-torrent", + "description": "SimpleTorrent is a a self-hosted remote torrent client, written in Go (golang). Started torrents remotely, download sets of files on the local disk of the server, which are then retrievable or streamable via HTTP.", + "short_desc": "A self-hosted remote torrent client", + "author": "", + "source": "https://github.com/boypt/simple-torrent", + "image": "https://getumbrel.github.io/umbrel-apps-gallery/simple-torrent/icon.svg", + "form_fields": [] +} diff --git a/apps/simple-torrent/docker-compose.yml b/apps/simple-torrent/docker-compose.yml new file mode 100644 index 00000000..6f2e30e4 --- /dev/null +++ b/apps/simple-torrent/docker-compose.yml @@ -0,0 +1,25 @@ +version: "3.7" + +services: + server: + container_name: simple-torrent + image: boypt/cloud-torrent:1.3.9 + restart: on-failure + ports: + - ${APP_PORT}:${APP_PORT} + command: > + --port=${APP_PORT} + --config-path /config/simple-torrent.json + volumes: + - ${APP_DATA_DIR}/data/torrents:/torrents + - ${APP_DATA_DIR}/data/downloads:/downloads + - ${APP_DATA_DIR}/data/config:/config + networks: + - tipi_main_network + # labels: + # traefik.enable: true + # traefik.http.routers.simple-torrent.rule: Host(`simple-torrent.tipi.home`) + # traefik.http.routers.simple-torrent.service: simple-torrent + # traefik.http.routers.simple-torrent.tls: true + # traefik.http.routers.simple-torrent.entrypoints: websecure + # traefik.http.services.simple-torrent.loadbalancer.server.port: ${APP_SIMPLETORRENT_PORT} \ No newline at end of file diff --git a/apps/simple-torrent/metadata/description.md b/apps/simple-torrent/metadata/description.md new file mode 100644 index 00000000..e69de29b diff --git a/apps/sonarr/config.json b/apps/sonarr/config.json new file mode 100644 index 00000000..b7f963d2 --- /dev/null +++ b/apps/sonarr/config.json @@ -0,0 +1,13 @@ +{ + "name": "Sonarr", + "available": true, + "port": 8098, + "id": "sonarr", + "categories": ["media", "utilities"], + "description": "Sonarr is a PVR for Usenet and BitTorrent users. It can monitor multiple RSS feeds for new episodes of your favorite shows and will grab, sort and rename them. It can also be configured to automatically upgrade the quality of files already downloaded when a better quality format becomes available.", + "short_desc": "TV show manager for Usenet and BitTorrent", + "author": "sonarr.tv", + "source": "https://github.com/Sonarr/Sonarr", + "image": "/logos/apps/sonarr.jpg", + "form_fields": [] +} diff --git a/apps/sonarr/docker-compose.yml b/apps/sonarr/docker-compose.yml new file mode 100644 index 00000000..f797679e --- /dev/null +++ b/apps/sonarr/docker-compose.yml @@ -0,0 +1,20 @@ +version: "3.7" +services: + sonarr: + image: lscr.io/linuxserver/sonarr:3.0.8 + container_name: sonarr + environment: + - PUID=1000 + - PGID=1000 + - TZ=${TZ} + dns: + - ${DNS_IP} + volumes: + - /etc/localtime:/etc/localtime:ro + - ${APP_DATA_DIR}/data:/config + - ${ROOT_FOLDER_HOST}/media:/media + ports: + - ${APP_PORT}:8989 + restart: unless-stopped + networks: + - tipi_main_network diff --git a/apps/sonarr/metadata/description.md b/apps/sonarr/metadata/description.md new file mode 100644 index 00000000..bc10934e --- /dev/null +++ b/apps/sonarr/metadata/description.md @@ -0,0 +1,17 @@ +## Smart PVR for newsgroup and bittorrent users. + +Sonarr is a PVR for Usenet and BitTorrent users. It can monitor multiple RSS feeds for new episodes of your favorite shows and will grab, sort and rename them. It can also be configured to automatically upgrade the quality of files already downloaded when a better quality format becomes available. + +### Current Features + +- Support for major platforms: Windows, Linux, macOS, Raspberry Pi, etc. +- Automatically detects new episodes +- Can scan your existing library and download any missing episodes +- Can watch for better quality of the episodes you already have and do an automatic upgrade. *eg. from DVD to Blu-Ray* +- Automatic failed download handling will try another release if one fails +- Manual search so you can pick any release or to see why a release was not downloaded automatically +- Fully configurable episode renaming +- Full integration with SABnzbd and NZBGet +- Full integration with Kodi, Plex (notification, library update, metadata) +- Full support for specials and multi-episode releases +- And a beautiful UI \ No newline at end of file diff --git a/apps/syncthing/config.json b/apps/syncthing/config.json new file mode 100644 index 00000000..c886ba2d --- /dev/null +++ b/apps/syncthing/config.json @@ -0,0 +1,14 @@ +{ + "name": "Syncthing", + "available": true, + "port": 8090, + "id": "syncthing", + "categories": ["data", "utilities"], + "description": "Syncthing is a peer-to-peer continuous file synchronization program. It synchronizes files between two or more computers in real time, safely protected from prying eyes. Your data is your data alone and you deserve to choose where it is stored, whether it is shared with some third party, and how it's transmitted over the internet.\n\nInstall the Syncthing app on your Umbrel and pair it with the Syncthing app on your phone or computer for a self hosted peer-to-peer backup solution.", + "short_desc": "Peer-to-peer file synchronization between your devices", + "author": "The Syncthing Foundation", + "source": "https://github.com/syncthing", + "website": "https://syncthing.net", + "image": "/logos/apps/syncthing.jpg", + "form_fields": [] +} diff --git a/apps/syncthing/data/.gitkeep b/apps/syncthing/data/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/apps/syncthing/docker-compose.yml b/apps/syncthing/docker-compose.yml new file mode 100644 index 00000000..78ddbced --- /dev/null +++ b/apps/syncthing/docker-compose.yml @@ -0,0 +1,21 @@ +version: "3.7" + +services: + syncthing: + container_name: syncthing + image: syncthing/syncthing:1.20 + stop_grace_period: 1m + hostname: tipi + environment: + - PUID=1000 + - PGID=1000 + volumes: + - ${APP_DATA_DIR}/data:/var/syncthing + ports: + - ${APP_PORT}:8384 + - 22000:22000/tcp # TCP file transfers + - 22000:22000/udp # QUIC file transfers + - 21027:21027/udp # Receive local discovery broadcasts + restart: unless-stopped + networks: + - tipi_main_network diff --git a/apps/syncthing/metadata/description.md b/apps/syncthing/metadata/description.md new file mode 100644 index 00000000..39d27440 --- /dev/null +++ b/apps/syncthing/metadata/description.md @@ -0,0 +1,38 @@ +## Peer-to-peer file synchronization between your devices + +Syncthing is a continuous file synchronization program. It synchronizes files between two or more computers. We strive to fulfill the goals below. The goals are listed in order of importance, the most important one being the first. This is the summary version of the goal list - for more commentary, see the full Goals document. + +1. **Safe From Data Loss** + + Protecting the user's data is paramount. We take every reasonable + precaution to avoid corrupting the user's files. + +2. **Secure Against Attackers** + + Again, protecting the user's data is paramount. Regardless of our other + goals we must never allow the user's data to be susceptible to + eavesdropping or modification by unauthorized parties. + +3. **Easy to Use** + + Syncthing should be approachable, understandable and inclusive. + +4. **Automatic** + + User interaction should be required only when absolutely necessary. + +5. **Universally Available** + + Syncthing should run on every common computer. We are mindful that the + latest technology is not always available to any given individual. + +6. **For Individuals** + + Syncthing is primarily about empowering the individual user with safe, + secure and easy to use file synchronization. + +7. **Everything Else** + + There are many things we care about that don't make it on to the list. It + is fine to optimize for these values, as long as they are not in conflict + with the stated goals above. \ No newline at end of file diff --git a/apps/tailscale/config.json b/apps/tailscale/config.json new file mode 100644 index 00000000..27d95799 --- /dev/null +++ b/apps/tailscale/config.json @@ -0,0 +1,14 @@ +{ + "name": "Tailscale", + "available": true, + "port": 8093, + "id": "tailscale", + "categories": ["network", "security"], + "description": "Zero config VPN. Installs on any device in minutes, manages firewall rules for you, and works from anywhere.", + "short_desc": "The easiest, most secure way to use WireGuard and 2FA.", + "author": "© Tailscale Inc.", + "source": "https://github.com/tailscale/tailscale", + "website": "https://tailscale.com/", + "image": "https://avatars.githubusercontent.com/u/48932923?s=200&v=4", + "form_fields": [] +} diff --git a/apps/tailscale/docker-compose.yml b/apps/tailscale/docker-compose.yml new file mode 100644 index 00000000..e96f48c8 --- /dev/null +++ b/apps/tailscale/docker-compose.yml @@ -0,0 +1,14 @@ +version: "2" + +services: + tailscale: + container_name: tailscale + network_mode: "host" # TODO: Find a way to remove this + image: tailscale/tailscale:v1.29.10 + privileged: true + restart: on-failure + stop_grace_period: 1m + command: "sh -c 'tailscale web --listen 0.0.0.0:${APP_PORT} & exec tailscaled --tun=userspace-networking'" + volumes: + - /var/lib:/var/lib + - /dev/net/tun:/dev/net/tun diff --git a/apps/tailscale/metadata/description.md b/apps/tailscale/metadata/description.md new file mode 100644 index 00000000..1b4f17a3 --- /dev/null +++ b/apps/tailscale/metadata/description.md @@ -0,0 +1,7 @@ +## The easiest, most secure way to use WireGuard and 2FA. + +Zero config VPN. Installs on any device in minutes, manages firewall rules for you, and works from anywhere. +Create a secure network between your servers, computers, and cloud instances. Even when separated by firewalls or subnets, Tailscale just works. +Devices only connect after signing in through your existing identity provider. Easily enforce multi-factor authentication, deauthorize employees who’ve moved on, and more. + +![Screenshot](https://tailscale.com/static/images/marketing/home-illustration-2080w.webp) \ No newline at end of file diff --git a/apps/tautulli/config.json b/apps/tautulli/config.json new file mode 100644 index 00000000..adc7a025 --- /dev/null +++ b/apps/tautulli/config.json @@ -0,0 +1,13 @@ +{ + "name": "Tautulli", + "available": true, + "port": 8181, + "id": "tautulli", + "categories": ["media", "utilities"], + "description": "Tautulli is a 3rd party application that you can run alongside your Plex Media Server to monitor activity and track various statistics. Most importantly, these statistics include what has been watched, who watched it, when and where they watched it, and how it was watched. The only thing missing is \"why they watched it\", but who am I to question your 42 plays of Frozen. All statistics are presented in a nice and clean interface with many tables and graphs, which makes it easy to brag about your server to everyone else.", + "short_desc": "Monitoring and tracking tool for Plex Media Server.", + "author": "JonnyWong16", + "source": "https://github.com/Tautulli/Tautulli", + "image": "/logos/apps/tautulli.jpg", + "form_fields": [] +} diff --git a/apps/tautulli/docker-compose.yml b/apps/tautulli/docker-compose.yml new file mode 100644 index 00000000..214585a8 --- /dev/null +++ b/apps/tautulli/docker-compose.yml @@ -0,0 +1,16 @@ +version: "2.1" +services: + tautulli: + container_name: tautulli + image: lscr.io/linuxserver/tautulli:2.10.2 + environment: + - PUID=1000 + - PGID=1000 + - TZ=${TZ} # Can use any env variable. List in runtipi/templates/env-sample + volumes: + - ${APP_DATA_DIR}/data/config:/config + ports: + - ${APP_PORT}:8181 + restart: unless-stopped + networks: + - tipi_main_network \ No newline at end of file diff --git a/apps/tautulli/metadata/description.md b/apps/tautulli/metadata/description.md new file mode 100644 index 00000000..281a0661 --- /dev/null +++ b/apps/tautulli/metadata/description.md @@ -0,0 +1,19 @@ +## A Python based monitoring and tracking tool for Plex Media Server. + +- Responsive web design viewable on desktop, tablet and mobile web browsers. +- Themed to complement Plex/Web. +- Easy configuration setup (no separate web server required). +- Monitor current Plex Media Server activity. +- Fully customizable notifications for stream activity and recently added media. +- Top statistics on home page with configurable duration and measurement metric. +- Global watching history with search/filtering & dynamic column sorting. +- Full user list with general information and comparison stats. +- Individual user information including devices IP addresses. +- Complete library statistics and media file information. +- Rich analytics presented using Highcharts graphing. +- Beautiful content information pages. +- Full sync list data on all users syncing items from your library. +- And many more!! +
+ +![Screenshot](https://camo.githubusercontent.com/8e79a14ca41c16c2b1390fd3b3d686e90d5f1aaf2b466327f20d03fd123156cc/68747470733a2f2f74617574756c6c692e636f6d2f696d616765732f73637265656e73686f74732f61637469766974792d636f6d707265737365642e6a70673f763d32) \ No newline at end of file diff --git a/apps/transmission/config.json b/apps/transmission/config.json new file mode 100644 index 00000000..7a1325e6 --- /dev/null +++ b/apps/transmission/config.json @@ -0,0 +1,33 @@ +{ + "name": "Transmission", + "available": true, + "port": 8089, + "requirements": { + "ports": [51413] + }, + "id": "transmission", + "categories": ["utilities"], + "description": "Transmission is a fast, easy, and free BitTorrent client.", + "short_desc": "Fast, easy, and free BitTorrent client", + "author": "Transmission Project", + "source": "https://github.com/transmission/transmission", + "image": "https://avatars.githubusercontent.com/u/223312?s=200&v=4", + "form_fields": [ + { + "type": "text", + "label": "Username", + "max": 50, + "min": 3, + "required": true, + "env_variable": "TRANSMISSION_USERNAME" + }, + { + "type": "password", + "label": "Password", + "max": 50, + "min": 3, + "required": true, + "env_variable": "TRANSMISSION_PASSWORD" + } + ] +} diff --git a/apps/transmission/data/config/.gitkeep b/apps/transmission/data/config/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/apps/transmission/docker-compose.yml b/apps/transmission/docker-compose.yml new file mode 100644 index 00000000..2a2e9299 --- /dev/null +++ b/apps/transmission/docker-compose.yml @@ -0,0 +1,27 @@ +version: "3.7" +services: + transmission: + image: lscr.io/linuxserver/transmission:latest + container_name: transmission + dns: + - ${DNS_IP} + environment: + - PUID=1000 + - PGID=1000 + - TZ=${TZ} + - USER=${TRANSMISSION_USERNAME} + - PASS=${TRANSMISSION_PASSWORD} + - TRANSMISSION_WEB_HOME=/transmission-web-control/ + # - WHITELIST=iplist #optional + # - PEERPORT=peerport #optional + # - HOST_WHITELIST=dnsnane list #optional + volumes: + - ${APP_DATA_DIR}/data/config:/config + - ${ROOT_FOLDER_HOST}/media/torrents:/downloads + ports: + - ${APP_PORT}:9091 + - 51413:51413 + - 51413:51413/udp + restart: unless-stopped + networks: + - tipi_main_network diff --git a/apps/transmission/metadata/description.md b/apps/transmission/metadata/description.md new file mode 100644 index 00000000..85bf1f8d --- /dev/null +++ b/apps/transmission/metadata/description.md @@ -0,0 +1,9 @@ +## Fast, easy, and free BitTorrent client + +Transmission is a fast, easy, and free BitTorrent client. It comes in several flavors: + * A native macOS GUI application + * GTK+ and Qt GUI applications for Linux, BSD, etc. + * A headless daemon for servers and routers + * A web UI for remote controlling any of the above + +Visit [https://transmissionbt.com/](https://transmissionbt.com/) for more information. \ No newline at end of file diff --git a/apps/ttyd/config.json b/apps/ttyd/config.json new file mode 100644 index 00000000..9337921b --- /dev/null +++ b/apps/ttyd/config.json @@ -0,0 +1,28 @@ +{ + "name": "TTYD - Web terminal", + "port": 8092, + "id": "ttyd", + "description": "", + "short_desc": "A utility that allows you to access a command line from your web browser", + "author": "", + "source": "", + "image": "", + "form_fields": [ + { + "type": "text", + "label": "Username", + "max": 50, + "min": 3, + "required": true, + "env_variable": "TRANSMISSION_USERNAME" + }, + { + "type": "password", + "label": "Password", + "max": 50, + "min": 3, + "required": true, + "env_variable": "TRANSMISSION_PASSWORD" + } + ] +} diff --git a/apps/ttyd/docker-compose.yml b/apps/ttyd/docker-compose.yml new file mode 100644 index 00000000..e69de29b diff --git a/apps/ttyd/metadata/description.md b/apps/ttyd/metadata/description.md new file mode 100644 index 00000000..e69de29b diff --git a/apps/vaultwarden/config.json b/apps/vaultwarden/config.json new file mode 100644 index 00000000..ce563a24 --- /dev/null +++ b/apps/vaultwarden/config.json @@ -0,0 +1,22 @@ +{ + "name": "VaultWarden", + "available": true, + "port": 8107, + "id": "vaultwarden", + "categories": ["utilities"], + "description": "Alternative implementation of the Bitwarden server API written in Rust and compatible with upstream Bitwarden clients, perfect for self-hosted deployment where running the official resource-heavy service might not be ideal.", + "short_desc": "All your passwords in your control!", + "author": "Daniel García", + "source": "https://github.com/dani-garcia/vaultwarden", + "image": "/logos/apps/vaultwarden.jpg", + "form_fields": [ + { + "type": "password", + "label": "Admin Panel Password", + "max": 50, + "min": 10, + "required": true, + "env_variable": "VAULTWARDEN_ADMIN_PASSWORD" + } + ] +} diff --git a/apps/vaultwarden/docker-compose.yml b/apps/vaultwarden/docker-compose.yml new file mode 100644 index 00000000..9ec92962 --- /dev/null +++ b/apps/vaultwarden/docker-compose.yml @@ -0,0 +1,16 @@ +version: '3.7' + +services: + vaultwarden: + image: vaultwarden/server:1.25.1 + container_name: vaultwarden + restart: unless-stopped + ports: + - ${APP_PORT}:80 + environment: + - WEBSOCKET_ENABLED=true + - ADMIN_TOKEN=${VAULTWARDEN_ADMIN_PASSWORD} + volumes: + - ${APP_DATA_DIR}/data:/data + networks: + - tipi_main_network diff --git a/apps/vaultwarden/metadata/description.md b/apps/vaultwarden/metadata/description.md new file mode 100644 index 00000000..30d146af --- /dev/null +++ b/apps/vaultwarden/metadata/description.md @@ -0,0 +1,13 @@ +## All your passwords in your control! + +Alternative implementation of the Bitwarden server API written in Rust and compatible with [upstream Bitwarden clients](https://bitwarden.com/download/), perfect for self-hosted deployment where running the official resource-heavy service might not be ideal. + +Basically full implementation of Bitwarden API is provided including: + + * Organizations support + * Attachments + * Vault API support + * Serving the static files for Vault interface + * Website icons API + * Authenticator and U2F support + * YubiKey and Duo support \ No newline at end of file diff --git a/apps/wg-easy/config.json b/apps/wg-easy/config.json new file mode 100644 index 00000000..bb2df8df --- /dev/null +++ b/apps/wg-easy/config.json @@ -0,0 +1,37 @@ +{ + "name": "Wireguard", + "available": true, + "port": 8082, + "requirements": { + "ports": [51820] + }, + "id": "wg-easy", + "categories": ["network"], + "description": "Access your homeserver from anywhere even on your mobile device. Wireguard-easy is a simple tool to configure and manage Wireguard VPN servers. It is written in Go and uses the official Wireguard client. You have to open and redirect port 51820 to your homeserver in order to connect.", + "short_desc": "VPN server for your homeserver", + "author": "WeeJeWel", + "source": "https://github.com/WeeJeWel/wg-easy/", + "image": "/logos/apps/wireguard.jpg", + "form_fields": [ + { + "type": "fqdnip", + "label": "Your public IP address or domain name", + "required": true, + "env_variable": "WIREGUARD_HOST" + }, + { + "type": "password", + "label": "Password", + "max": 50, + "min": 3, + "required": true, + "env_variable": "WIREGUARD_PASSWORD" + }, + { + "type": "ip", + "label": "Default DNS server", + "required": false, + "env_variable": "WIREGUARD_DNS" + } + ] +} diff --git a/apps/wg-easy/data/.gitkeep b/apps/wg-easy/data/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/apps/wg-easy/docker-compose.yml b/apps/wg-easy/docker-compose.yml new file mode 100644 index 00000000..907cb315 --- /dev/null +++ b/apps/wg-easy/docker-compose.yml @@ -0,0 +1,35 @@ +version: "3.7" +services: + wg-easy: + container_name: wg-easy + image: weejewel/wg-easy:7 + restart: unless-stopped + volumes: + - ${APP_DATA_DIR}/data:/etc/wireguard + - /lib/modules:/lib/modules + ports: + - 51822:51820/udp + - ${APP_PORT}:51821/tcp + environment: + WG_HOST: "${WIREGUARD_HOST}" + PASSWORD: "${WIREGUARD_PASSWORD}" + WG_ALLOWED_IPS: 0.0.0.0/0,::/0 + WG_PORT: 51822 + WG_DEFAULT_DNS: "${WIREGUARD_DNS:-8.8.8.8}" + cap_add: + - NET_ADMIN + - SYS_MODULE + dns: + - "${WIREGUARD_DNS:-8.8.8.8}" + sysctls: + - net.ipv4.conf.all.src_valid_mark=1 + - net.ipv4.ip_forward=1 + networks: + - tipi_main_network + # labels: + # traefik.enable: true + # traefik.http.routers.wireguard.rule: Host(`wireguard.tipi.home`) + # traefik.http.routers.wireguard.service: wireguard + # traefik.http.routers.wireguard.tls: true + # traefik.http.routers.wireguard.entrypoints: websecure + # traefik.http.services.wireguard.loadbalancer.server.port: 51821 diff --git a/apps/wg-easy/metadata/description.md b/apps/wg-easy/metadata/description.md new file mode 100644 index 00000000..b5378eaa --- /dev/null +++ b/apps/wg-easy/metadata/description.md @@ -0,0 +1,14 @@ +## The easiest way to run WireGuard VPN + Web-based Admin UI. + +You have found the easiest way to install & manage WireGuard on any Linux host! + +* All-in-one: WireGuard + Web UI. +* Easy installation, simple to use. +* List, create, edit, delete, enable & disable clients. +* Show a client's QR code. +* Download a client's configuration file. +* Statistics for which clients are connected. +* Tx/Rx charts for each connected client. +* Gravatar support. + +![Screenshot](https://raw.githubusercontent.com/WeeJeWel/wg-easy/master/assets/screenshot.png) \ No newline at end of file diff --git a/apps/your-spotify/config.json b/apps/your-spotify/config.json new file mode 100644 index 00000000..1a35f8ee --- /dev/null +++ b/apps/your-spotify/config.json @@ -0,0 +1,28 @@ +{ + "name": "Your Spotify", + "available": true, + "port": 8103, + "id": "your-spotify", + "categories": ["music", "utilities"], + "description": "Self hosted Spotify tracking dashboard.", + "short_desc": "Self hosted Spotify tracking dashboard.", + "author": "Yooooomi", + "source": "https://github.com/Yooooomi/your_spotify", + "image": "/logos/apps/your-spotify.jpg", + "form_fields": [ + { + "type": "text", + "label": "Spotify public key", + "hint": "The public key of your Spotify application", + "required": true, + "env_variable": "SPOTIFY_PUBLIC" + }, + { + "type": "password", + "label": "Spotify secret key", + "hint": "The secret key of your Spotify application", + "required": true, + "env_variable": "SPOTIFY_SECRET" + } + ] +} diff --git a/apps/your-spotify/docker-compose.yml b/apps/your-spotify/docker-compose.yml new file mode 100644 index 00000000..32e542e1 --- /dev/null +++ b/apps/your-spotify/docker-compose.yml @@ -0,0 +1,46 @@ +version: "3" + +services: + your-spotify-server: + container_name: your-spotify-server + image: yooooomi/your_spotify_server + restart: unless-stopped + dns: + - ${DNS_IP} + ports: + - 32500:8080 + links: + - your-spotify-db + depends_on: + - your-spotify-db + environment: + - API_ENDPOINT=http://${INTERNAL_IP}:32500 # This MUST be included as a valid URL in the spotify dashboard (see below) + - CLIENT_ENDPOINT=http://${INTERNAL_IP}:${APP_PORT} + - SPOTIFY_PUBLIC=${SPOTIFY_PUBLIC} + - SPOTIFY_SECRET=${SPOTIFY_SECRET} + - MONGO_ENDPOINT=mongodb://your-spotify-db:27017/your_spotify + - CORS=all + networks: + - tipi_main_network + + your-spotify-db: + container_name: your-spotify-db + image: mongo:4.4.8 + restart: unless-stopped + volumes: + - ${APP_DATA_DIR}/data/db:/data/db + networks: + - tipi_main_network + + your-spotify: + container_name: your-spotify + image: yooooomi/your_spotify_client + depends_on: + - your-spotify-server + restart: unless-stopped + ports: + - ${APP_PORT}:3000 + environment: + - API_ENDPOINT=http://${INTERNAL_IP}:32500 + networks: + - tipi_main_network diff --git a/apps/your-spotify/metadata/description.md b/apps/your-spotify/metadata/description.md new file mode 100644 index 00000000..47ff0ca8 --- /dev/null +++ b/apps/your-spotify/metadata/description.md @@ -0,0 +1,19 @@ +## Your Spotify + +YourSpotify is a self-hosted application that tracks what you listen and offers you a dashboard to explore statistics about it! It's composed of a web server which polls the Spotify API every now and then and a web application on which you can explore your statistics. + +![Screenshots](https://user-images.githubusercontent.com/17204739/154752226-c2215a51-e20e-4ade-ac63-42c5abb25240.png) + +### Creating the Spotify Application + +For **YourSpotify** to work you need to provide a Spotify application **public** AND **secret** to the server environment. +To do so, you need to create a **Spotify application** [here](https://developer.spotify.com/dashboard/applications). + +1. Click on **Create a client ID**. +2. Fill out all the informations. +3. Copy the **public** and the **secret** key respectively. +4. Add an authorized redirect URI corresponding to your **server** location on the internet adding the suffix **/oauth/spotify/callback**. + 1. use the `EDIT SETTINGS` button on the top right corner of the page. + 2. add your URI under the `Redirect URIs` section. + - i.e: `http://localhost:8080/oauth/spotify/callback` or `http://home.mydomain.com/your_spotify_backend/oauth/spotify/callback` + 3. Do not forget to hit the save button at the bottom of the popup. diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 00000000..1de058a4 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,6 @@ +/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ +module.exports = { + preset: "ts-jest", + testEnvironment: "node", + testMatch: ["**/__tests__/**/*.test.ts"], +}; diff --git a/package.json b/package.json new file mode 100644 index 00000000..864eb8d5 --- /dev/null +++ b/package.json @@ -0,0 +1,29 @@ +{ + "name": "runtipi-appstore", + "version": "1.0.0", + "description": "", + "main": "", + "scripts": { + "test": "jest", + "prepare": "husky install" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/meienberger/runtipi-appstore.git" + }, + "author": "", + "license": "GNU General Public License v3.0", + "bugs": { + "url": "https://github.com/meienberger/runtipi-appstore/issues" + }, + "homepage": "https://github.com/meienberger/runtipi-appstore#readme", + "devDependencies": { + "@types/jest": "^28.1.6", + "@types/js-yaml": "^4.0.5", + "husky": "^8.0.1", + "jest": "^28.1.3", + "js-yaml": "^4.1.0", + "ts-jest": "^28.0.7", + "typescript": "^4.7.4" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 00000000..96812a36 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,2338 @@ +lockfileVersion: 5.4 + +specifiers: + '@types/jest': ^28.1.6 + '@types/js-yaml': ^4.0.5 + husky: ^8.0.1 + jest: ^28.1.3 + js-yaml: ^4.1.0 + ts-jest: ^28.0.7 + typescript: ^4.7.4 + +devDependencies: + '@types/jest': 28.1.6 + '@types/js-yaml': 4.0.5 + husky: 8.0.1 + jest: 28.1.3 + js-yaml: 4.1.0 + ts-jest: 28.0.7_bi2kohzqnxavgozw3csgny5hju + typescript: 4.7.4 + +packages: + + /@ampproject/remapping/2.2.0: + resolution: {integrity: sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/gen-mapping': 0.1.1 + '@jridgewell/trace-mapping': 0.3.14 + dev: true + + /@babel/code-frame/7.18.6: + resolution: {integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/highlight': 7.18.6 + dev: true + + /@babel/compat-data/7.18.8: + resolution: {integrity: sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/core/7.18.9: + resolution: {integrity: sha512-1LIb1eL8APMy91/IMW+31ckrfBM4yCoLaVzoDhZUKSM4cu1L1nIidyxkCgzPAgrC5WEz36IPEr/eSeSF9pIn+g==} + engines: {node: '>=6.9.0'} + dependencies: + '@ampproject/remapping': 2.2.0 + '@babel/code-frame': 7.18.6 + '@babel/generator': 7.18.9 + '@babel/helper-compilation-targets': 7.18.9_@babel+core@7.18.9 + '@babel/helper-module-transforms': 7.18.9 + '@babel/helpers': 7.18.9 + '@babel/parser': 7.18.9 + '@babel/template': 7.18.6 + '@babel/traverse': 7.18.9 + '@babel/types': 7.18.9 + convert-source-map: 1.8.0 + debug: 4.3.4 + gensync: 1.0.0-beta.2 + json5: 2.2.1 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/generator/7.18.9: + resolution: {integrity: sha512-wt5Naw6lJrL1/SGkipMiFxJjtyczUWTP38deiP1PO60HsBjDeKk08CGC3S8iVuvf0FmTdgKwU1KIXzSKL1G0Ug==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.18.9 + '@jridgewell/gen-mapping': 0.3.2 + jsesc: 2.5.2 + dev: true + + /@babel/helper-compilation-targets/7.18.9_@babel+core@7.18.9: + resolution: {integrity: sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/compat-data': 7.18.8 + '@babel/core': 7.18.9 + '@babel/helper-validator-option': 7.18.6 + browserslist: 4.21.3 + semver: 6.3.0 + dev: true + + /@babel/helper-environment-visitor/7.18.9: + resolution: {integrity: sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-function-name/7.18.9: + resolution: {integrity: sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.18.6 + '@babel/types': 7.18.9 + dev: true + + /@babel/helper-hoist-variables/7.18.6: + resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.18.9 + dev: true + + /@babel/helper-module-imports/7.18.6: + resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.18.9 + dev: true + + /@babel/helper-module-transforms/7.18.9: + resolution: {integrity: sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-environment-visitor': 7.18.9 + '@babel/helper-module-imports': 7.18.6 + '@babel/helper-simple-access': 7.18.6 + '@babel/helper-split-export-declaration': 7.18.6 + '@babel/helper-validator-identifier': 7.18.6 + '@babel/template': 7.18.6 + '@babel/traverse': 7.18.9 + '@babel/types': 7.18.9 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-plugin-utils/7.18.9: + resolution: {integrity: sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-simple-access/7.18.6: + resolution: {integrity: sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.18.9 + dev: true + + /@babel/helper-split-export-declaration/7.18.6: + resolution: {integrity: sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.18.9 + dev: true + + /@babel/helper-validator-identifier/7.18.6: + resolution: {integrity: sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-validator-option/7.18.6: + resolution: {integrity: sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helpers/7.18.9: + resolution: {integrity: sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.18.6 + '@babel/traverse': 7.18.9 + '@babel/types': 7.18.9 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/highlight/7.18.6: + resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.18.6 + chalk: 2.4.2 + js-tokens: 4.0.0 + dev: true + + /@babel/parser/7.18.9: + resolution: {integrity: sha512-9uJveS9eY9DJ0t64YbIBZICtJy8a5QrDEVdiLCG97fVLpDTpGX7t8mMSb6OWw6Lrnjqj4O8zwjELX3dhoMgiBg==} + engines: {node: '>=6.0.0'} + hasBin: true + dev: true + + /@babel/plugin-syntax-async-generators/7.8.4_@babel+core@7.18.9: + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.18.9 + '@babel/helper-plugin-utils': 7.18.9 + dev: true + + /@babel/plugin-syntax-bigint/7.8.3_@babel+core@7.18.9: + resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.18.9 + '@babel/helper-plugin-utils': 7.18.9 + dev: true + + /@babel/plugin-syntax-class-properties/7.12.13_@babel+core@7.18.9: + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.18.9 + '@babel/helper-plugin-utils': 7.18.9 + dev: true + + /@babel/plugin-syntax-import-meta/7.10.4_@babel+core@7.18.9: + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.18.9 + '@babel/helper-plugin-utils': 7.18.9 + dev: true + + /@babel/plugin-syntax-json-strings/7.8.3_@babel+core@7.18.9: + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.18.9 + '@babel/helper-plugin-utils': 7.18.9 + dev: true + + /@babel/plugin-syntax-logical-assignment-operators/7.10.4_@babel+core@7.18.9: + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.18.9 + '@babel/helper-plugin-utils': 7.18.9 + dev: true + + /@babel/plugin-syntax-nullish-coalescing-operator/7.8.3_@babel+core@7.18.9: + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.18.9 + '@babel/helper-plugin-utils': 7.18.9 + dev: true + + /@babel/plugin-syntax-numeric-separator/7.10.4_@babel+core@7.18.9: + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.18.9 + '@babel/helper-plugin-utils': 7.18.9 + dev: true + + /@babel/plugin-syntax-object-rest-spread/7.8.3_@babel+core@7.18.9: + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.18.9 + '@babel/helper-plugin-utils': 7.18.9 + dev: true + + /@babel/plugin-syntax-optional-catch-binding/7.8.3_@babel+core@7.18.9: + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.18.9 + '@babel/helper-plugin-utils': 7.18.9 + dev: true + + /@babel/plugin-syntax-optional-chaining/7.8.3_@babel+core@7.18.9: + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.18.9 + '@babel/helper-plugin-utils': 7.18.9 + dev: true + + /@babel/plugin-syntax-top-level-await/7.14.5_@babel+core@7.18.9: + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.18.9 + '@babel/helper-plugin-utils': 7.18.9 + dev: true + + /@babel/plugin-syntax-typescript/7.18.6_@babel+core@7.18.9: + resolution: {integrity: sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.18.9 + '@babel/helper-plugin-utils': 7.18.9 + dev: true + + /@babel/template/7.18.6: + resolution: {integrity: sha512-JoDWzPe+wgBsTTgdnIma3iHNFC7YVJoPssVBDjiHfNlyt4YcunDtcDOUmfVDfCK5MfdsaIoX9PkijPhjH3nYUw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.18.6 + '@babel/parser': 7.18.9 + '@babel/types': 7.18.9 + dev: true + + /@babel/traverse/7.18.9: + resolution: {integrity: sha512-LcPAnujXGwBgv3/WHv01pHtb2tihcyW1XuL9wd7jqh1Z8AQkTd+QVjMrMijrln0T7ED3UXLIy36P9Ao7W75rYg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.18.6 + '@babel/generator': 7.18.9 + '@babel/helper-environment-visitor': 7.18.9 + '@babel/helper-function-name': 7.18.9 + '@babel/helper-hoist-variables': 7.18.6 + '@babel/helper-split-export-declaration': 7.18.6 + '@babel/parser': 7.18.9 + '@babel/types': 7.18.9 + debug: 4.3.4 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/types/7.18.9: + resolution: {integrity: sha512-WwMLAg2MvJmt/rKEVQBBhIVffMmnilX4oe0sRe7iPOHIGsqpruFHHdrfj4O1CMMtgMtCU4oPafZjDPCRgO57Wg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.18.6 + to-fast-properties: 2.0.0 + dev: true + + /@bcoe/v8-coverage/0.2.3: + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + dev: true + + /@istanbuljs/load-nyc-config/1.1.0: + resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} + engines: {node: '>=8'} + dependencies: + camelcase: 5.3.1 + find-up: 4.1.0 + get-package-type: 0.1.0 + js-yaml: 3.14.1 + resolve-from: 5.0.0 + dev: true + + /@istanbuljs/schema/0.1.3: + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + dev: true + + /@jest/console/28.1.3: + resolution: {integrity: sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@jest/types': 28.1.3 + '@types/node': 18.6.2 + chalk: 4.1.2 + jest-message-util: 28.1.3 + jest-util: 28.1.3 + slash: 3.0.0 + dev: true + + /@jest/core/28.1.3: + resolution: {integrity: sha512-CIKBrlaKOzA7YG19BEqCw3SLIsEwjZkeJzf5bdooVnW4bH5cktqe3JX+G2YV1aK5vP8N9na1IGWFzYaTp6k6NA==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@jest/console': 28.1.3 + '@jest/reporters': 28.1.3 + '@jest/test-result': 28.1.3 + '@jest/transform': 28.1.3 + '@jest/types': 28.1.3 + '@types/node': 18.6.2 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + ci-info: 3.3.2 + exit: 0.1.2 + graceful-fs: 4.2.10 + jest-changed-files: 28.1.3 + jest-config: 28.1.3_@types+node@18.6.2 + jest-haste-map: 28.1.3 + jest-message-util: 28.1.3 + jest-regex-util: 28.0.2 + jest-resolve: 28.1.3 + jest-resolve-dependencies: 28.1.3 + jest-runner: 28.1.3 + jest-runtime: 28.1.3 + jest-snapshot: 28.1.3 + jest-util: 28.1.3 + jest-validate: 28.1.3 + jest-watcher: 28.1.3 + micromatch: 4.0.5 + pretty-format: 28.1.3 + rimraf: 3.0.2 + slash: 3.0.0 + strip-ansi: 6.0.1 + transitivePeerDependencies: + - supports-color + - ts-node + dev: true + + /@jest/environment/28.1.3: + resolution: {integrity: sha512-1bf40cMFTEkKyEf585R9Iz1WayDjHoHqvts0XFYEqyKM3cFWDpeMoqKKTAF9LSYQModPUlh8FKptoM2YcMWAXA==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@jest/fake-timers': 28.1.3 + '@jest/types': 28.1.3 + '@types/node': 18.6.2 + jest-mock: 28.1.3 + dev: true + + /@jest/expect-utils/28.1.3: + resolution: {integrity: sha512-wvbi9LUrHJLn3NlDW6wF2hvIMtd4JUl2QNVrjq+IBSHirgfrR3o9RnVtxzdEGO2n9JyIWwHnLfby5KzqBGg2YA==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + jest-get-type: 28.0.2 + dev: true + + /@jest/expect/28.1.3: + resolution: {integrity: sha512-lzc8CpUbSoE4dqT0U+g1qODQjBRHPpCPXissXD4mS9+sWQdmmpeJ9zSH1rS1HEkrsMN0fb7nKrJ9giAR1d3wBw==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + expect: 28.1.3 + jest-snapshot: 28.1.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@jest/fake-timers/28.1.3: + resolution: {integrity: sha512-D/wOkL2POHv52h+ok5Oj/1gOG9HSywdoPtFsRCUmlCILXNn5eIWmcnd3DIiWlJnpGvQtmajqBP95Ei0EimxfLw==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@jest/types': 28.1.3 + '@sinonjs/fake-timers': 9.1.2 + '@types/node': 18.6.2 + jest-message-util: 28.1.3 + jest-mock: 28.1.3 + jest-util: 28.1.3 + dev: true + + /@jest/globals/28.1.3: + resolution: {integrity: sha512-XFU4P4phyryCXu1pbcqMO0GSQcYe1IsalYCDzRNyhetyeyxMcIxa11qPNDpVNLeretItNqEmYYQn1UYz/5x1NA==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@jest/environment': 28.1.3 + '@jest/expect': 28.1.3 + '@jest/types': 28.1.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@jest/reporters/28.1.3: + resolution: {integrity: sha512-JuAy7wkxQZVNU/V6g9xKzCGC5LVXx9FDcABKsSXp5MiKPEE2144a/vXTEDoyzjUpZKfVwp08Wqg5A4WfTMAzjg==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@bcoe/v8-coverage': 0.2.3 + '@jest/console': 28.1.3 + '@jest/test-result': 28.1.3 + '@jest/transform': 28.1.3 + '@jest/types': 28.1.3 + '@jridgewell/trace-mapping': 0.3.14 + '@types/node': 18.6.2 + chalk: 4.1.2 + collect-v8-coverage: 1.0.1 + exit: 0.1.2 + glob: 7.2.3 + graceful-fs: 4.2.10 + istanbul-lib-coverage: 3.2.0 + istanbul-lib-instrument: 5.2.0 + istanbul-lib-report: 3.0.0 + istanbul-lib-source-maps: 4.0.1 + istanbul-reports: 3.1.5 + jest-message-util: 28.1.3 + jest-util: 28.1.3 + jest-worker: 28.1.3 + slash: 3.0.0 + string-length: 4.0.2 + strip-ansi: 6.0.1 + terminal-link: 2.1.1 + v8-to-istanbul: 9.0.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@jest/schemas/28.1.3: + resolution: {integrity: sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@sinclair/typebox': 0.24.21 + dev: true + + /@jest/source-map/28.1.2: + resolution: {integrity: sha512-cV8Lx3BeStJb8ipPHnqVw/IM2VCMWO3crWZzYodSIkxXnRcXJipCdx1JCK0K5MsJJouZQTH73mzf4vgxRaH9ww==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@jridgewell/trace-mapping': 0.3.14 + callsites: 3.1.0 + graceful-fs: 4.2.10 + dev: true + + /@jest/test-result/28.1.3: + resolution: {integrity: sha512-kZAkxnSE+FqE8YjW8gNuoVkkC9I7S1qmenl8sGcDOLropASP+BkcGKwhXoyqQuGOGeYY0y/ixjrd/iERpEXHNg==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@jest/console': 28.1.3 + '@jest/types': 28.1.3 + '@types/istanbul-lib-coverage': 2.0.4 + collect-v8-coverage: 1.0.1 + dev: true + + /@jest/test-sequencer/28.1.3: + resolution: {integrity: sha512-NIMPEqqa59MWnDi1kvXXpYbqsfQmSJsIbnd85mdVGkiDfQ9WQQTXOLsvISUfonmnBT+w85WEgneCigEEdHDFxw==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@jest/test-result': 28.1.3 + graceful-fs: 4.2.10 + jest-haste-map: 28.1.3 + slash: 3.0.0 + dev: true + + /@jest/transform/28.1.3: + resolution: {integrity: sha512-u5dT5di+oFI6hfcLOHGTAfmUxFRrjK+vnaP0kkVow9Md/M7V/MxqQMOz/VV25UZO8pzeA9PjfTpOu6BDuwSPQA==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@babel/core': 7.18.9 + '@jest/types': 28.1.3 + '@jridgewell/trace-mapping': 0.3.14 + babel-plugin-istanbul: 6.1.1 + chalk: 4.1.2 + convert-source-map: 1.8.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.10 + jest-haste-map: 28.1.3 + jest-regex-util: 28.0.2 + jest-util: 28.1.3 + micromatch: 4.0.5 + pirates: 4.0.5 + slash: 3.0.0 + write-file-atomic: 4.0.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@jest/types/28.1.3: + resolution: {integrity: sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@jest/schemas': 28.1.3 + '@types/istanbul-lib-coverage': 2.0.4 + '@types/istanbul-reports': 3.0.1 + '@types/node': 18.6.2 + '@types/yargs': 17.0.10 + chalk: 4.1.2 + dev: true + + /@jridgewell/gen-mapping/0.1.1: + resolution: {integrity: sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/set-array': 1.1.2 + '@jridgewell/sourcemap-codec': 1.4.14 + dev: true + + /@jridgewell/gen-mapping/0.3.2: + resolution: {integrity: sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/set-array': 1.1.2 + '@jridgewell/sourcemap-codec': 1.4.14 + '@jridgewell/trace-mapping': 0.3.14 + dev: true + + /@jridgewell/resolve-uri/3.1.0: + resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/set-array/1.1.2: + resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/sourcemap-codec/1.4.14: + resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} + dev: true + + /@jridgewell/trace-mapping/0.3.14: + resolution: {integrity: sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==} + dependencies: + '@jridgewell/resolve-uri': 3.1.0 + '@jridgewell/sourcemap-codec': 1.4.14 + dev: true + + /@sinclair/typebox/0.24.21: + resolution: {integrity: sha512-II2SIjvxBVJmrGkkZYza/BqNjwx3PWROIA8CZ0/Hn7LV0Mv0CVpZxoyHGBVsQqfFLMv9DmArIeRHTwo76bE6oA==} + dev: true + + /@sinonjs/commons/1.8.3: + resolution: {integrity: sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==} + dependencies: + type-detect: 4.0.8 + dev: true + + /@sinonjs/fake-timers/9.1.2: + resolution: {integrity: sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw==} + dependencies: + '@sinonjs/commons': 1.8.3 + dev: true + + /@types/babel__core/7.1.19: + resolution: {integrity: sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==} + dependencies: + '@babel/parser': 7.18.9 + '@babel/types': 7.18.9 + '@types/babel__generator': 7.6.4 + '@types/babel__template': 7.4.1 + '@types/babel__traverse': 7.17.1 + dev: true + + /@types/babel__generator/7.6.4: + resolution: {integrity: sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==} + dependencies: + '@babel/types': 7.18.9 + dev: true + + /@types/babel__template/7.4.1: + resolution: {integrity: sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==} + dependencies: + '@babel/parser': 7.18.9 + '@babel/types': 7.18.9 + dev: true + + /@types/babel__traverse/7.17.1: + resolution: {integrity: sha512-kVzjari1s2YVi77D3w1yuvohV2idweYXMCDzqBiVNN63TcDWrIlTVOYpqVrvbbyOE/IyzBoTKF0fdnLPEORFxA==} + dependencies: + '@babel/types': 7.18.9 + dev: true + + /@types/graceful-fs/4.1.5: + resolution: {integrity: sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==} + dependencies: + '@types/node': 18.6.2 + dev: true + + /@types/istanbul-lib-coverage/2.0.4: + resolution: {integrity: sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==} + dev: true + + /@types/istanbul-lib-report/3.0.0: + resolution: {integrity: sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==} + dependencies: + '@types/istanbul-lib-coverage': 2.0.4 + dev: true + + /@types/istanbul-reports/3.0.1: + resolution: {integrity: sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==} + dependencies: + '@types/istanbul-lib-report': 3.0.0 + dev: true + + /@types/jest/28.1.6: + resolution: {integrity: sha512-0RbGAFMfcBJKOmqRazM8L98uokwuwD5F8rHrv/ZMbrZBwVOWZUyPG6VFNscjYr/vjM3Vu4fRrCPbOs42AfemaQ==} + dependencies: + jest-matcher-utils: 28.1.3 + pretty-format: 28.1.3 + dev: true + + /@types/js-yaml/4.0.5: + resolution: {integrity: sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==} + dev: true + + /@types/node/18.6.2: + resolution: {integrity: sha512-KcfkBq9H4PI6Vpu5B/KoPeuVDAbmi+2mDBqGPGUgoL7yXQtcWGu2vJWmmRkneWK3Rh0nIAX192Aa87AqKHYChQ==} + dev: true + + /@types/prettier/2.6.4: + resolution: {integrity: sha512-fOwvpvQYStpb/zHMx0Cauwywu9yLDmzWiiQBC7gJyq5tYLUXFZvDG7VK1B7WBxxjBJNKFOZ0zLoOQn8vmATbhw==} + dev: true + + /@types/stack-utils/2.0.1: + resolution: {integrity: sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==} + dev: true + + /@types/yargs-parser/21.0.0: + resolution: {integrity: sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==} + dev: true + + /@types/yargs/17.0.10: + resolution: {integrity: sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==} + dependencies: + '@types/yargs-parser': 21.0.0 + dev: true + + /ansi-escapes/4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.21.3 + dev: true + + /ansi-regex/5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: true + + /ansi-styles/3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + dependencies: + color-convert: 1.9.3 + dev: true + + /ansi-styles/4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + dev: true + + /ansi-styles/5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + dev: true + + /anymatch/3.1.2: + resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + dev: true + + /argparse/1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + dependencies: + sprintf-js: 1.0.3 + dev: true + + /argparse/2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + dev: true + + /babel-jest/28.1.3_@babel+core@7.18.9: + resolution: {integrity: sha512-epUaPOEWMk3cWX0M/sPvCHHCe9fMFAa/9hXEgKP8nFfNl/jlGkE9ucq9NqkZGXLDduCJYS0UvSlPUwC0S+rH6Q==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + peerDependencies: + '@babel/core': ^7.8.0 + dependencies: + '@babel/core': 7.18.9 + '@jest/transform': 28.1.3 + '@types/babel__core': 7.1.19 + babel-plugin-istanbul: 6.1.1 + babel-preset-jest: 28.1.3_@babel+core@7.18.9 + chalk: 4.1.2 + graceful-fs: 4.2.10 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-istanbul/6.1.1: + resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} + engines: {node: '>=8'} + dependencies: + '@babel/helper-plugin-utils': 7.18.9 + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-instrument: 5.2.0 + test-exclude: 6.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-jest-hoist/28.1.3: + resolution: {integrity: sha512-Ys3tUKAmfnkRUpPdpa98eYrAR0nV+sSFUZZEGuQ2EbFd1y4SOLtD5QDNHAq+bb9a+bbXvYQC4b+ID/THIMcU6Q==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@babel/template': 7.18.6 + '@babel/types': 7.18.9 + '@types/babel__core': 7.1.19 + '@types/babel__traverse': 7.17.1 + dev: true + + /babel-preset-current-node-syntax/1.0.1_@babel+core@7.18.9: + resolution: {integrity: sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.18.9 + '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.18.9 + '@babel/plugin-syntax-bigint': 7.8.3_@babel+core@7.18.9 + '@babel/plugin-syntax-class-properties': 7.12.13_@babel+core@7.18.9 + '@babel/plugin-syntax-import-meta': 7.10.4_@babel+core@7.18.9 + '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.18.9 + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.18.9 + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.18.9 + '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.18.9 + '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.18.9 + '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.18.9 + '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.18.9 + '@babel/plugin-syntax-top-level-await': 7.14.5_@babel+core@7.18.9 + dev: true + + /babel-preset-jest/28.1.3_@babel+core@7.18.9: + resolution: {integrity: sha512-L+fupJvlWAHbQfn74coNX3zf60LXMJsezNvvx8eIh7iOR1luJ1poxYgQk1F8PYtNq/6QODDHCqsSnTFSWC491A==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.18.9 + babel-plugin-jest-hoist: 28.1.3 + babel-preset-current-node-syntax: 1.0.1_@babel+core@7.18.9 + dev: true + + /balanced-match/1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true + + /brace-expansion/1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /braces/3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + dev: true + + /browserslist/4.21.3: + resolution: {integrity: sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001372 + electron-to-chromium: 1.4.204 + node-releases: 2.0.6 + update-browserslist-db: 1.0.5_browserslist@4.21.3 + dev: true + + /bs-logger/0.2.6: + resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} + engines: {node: '>= 6'} + dependencies: + fast-json-stable-stringify: 2.1.0 + dev: true + + /bser/2.1.1: + resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + dependencies: + node-int64: 0.4.0 + dev: true + + /buffer-from/1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + dev: true + + /callsites/3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + dev: true + + /camelcase/5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + dev: true + + /camelcase/6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + dev: true + + /caniuse-lite/1.0.30001372: + resolution: {integrity: sha512-tBgBhIXBIqORB9ieUEYBKRfSlaF6YPq7WNNqcreF6Cl24UKNGIvE5/rP59dOGN6TRIS/5zOMHAMSRrVNmifWWw==} + dev: true + + /chalk/2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + dev: true + + /chalk/4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: true + + /char-regex/1.0.2: + resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} + engines: {node: '>=10'} + dev: true + + /ci-info/3.3.2: + resolution: {integrity: sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==} + dev: true + + /cjs-module-lexer/1.2.2: + resolution: {integrity: sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==} + dev: true + + /cliui/7.0.4: + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: true + + /co/4.6.0: + resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} + engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + dev: true + + /collect-v8-coverage/1.0.1: + resolution: {integrity: sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==} + dev: true + + /color-convert/1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + dev: true + + /color-convert/2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + dev: true + + /color-name/1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + dev: true + + /color-name/1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + dev: true + + /concat-map/0.0.1: + resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} + dev: true + + /convert-source-map/1.8.0: + resolution: {integrity: sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==} + dependencies: + safe-buffer: 5.1.2 + dev: true + + /cross-spawn/7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: true + + /debug/4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: true + + /dedent/0.7.0: + resolution: {integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==} + dev: true + + /deepmerge/4.2.2: + resolution: {integrity: sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==} + engines: {node: '>=0.10.0'} + dev: true + + /detect-newline/3.1.0: + resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} + engines: {node: '>=8'} + dev: true + + /diff-sequences/28.1.1: + resolution: {integrity: sha512-FU0iFaH/E23a+a718l8Qa/19bF9p06kgE0KipMOMadwa3SjnaElKzPaUC0vnibs6/B/9ni97s61mcejk8W1fQw==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dev: true + + /electron-to-chromium/1.4.204: + resolution: {integrity: sha512-5Ojjtw9/c9HCXtMVE6SXVSHSNjmbFOXpKprl6mY/5moLSxLeWatuYA7KTD+RzJMxLRH6yNNQrqGz9p6IoNBMgw==} + dev: true + + /emittery/0.10.2: + resolution: {integrity: sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==} + engines: {node: '>=12'} + dev: true + + /emoji-regex/8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + dev: true + + /error-ex/1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + dependencies: + is-arrayish: 0.2.1 + dev: true + + /escalade/3.1.1: + resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} + engines: {node: '>=6'} + dev: true + + /escape-string-regexp/1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + dev: true + + /escape-string-regexp/2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + dev: true + + /esprima/4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /execa/5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + dev: true + + /exit/0.1.2: + resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} + engines: {node: '>= 0.8.0'} + dev: true + + /expect/28.1.3: + resolution: {integrity: sha512-eEh0xn8HlsuOBxFgIss+2mX85VAS4Qy3OSkjV7rlBWljtA4oWH37glVGyOZSZvErDT/yBywZdPGwCXuTvSG85g==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@jest/expect-utils': 28.1.3 + jest-get-type: 28.0.2 + jest-matcher-utils: 28.1.3 + jest-message-util: 28.1.3 + jest-util: 28.1.3 + dev: true + + /fast-json-stable-stringify/2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: true + + /fb-watchman/2.0.1: + resolution: {integrity: sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==} + dependencies: + bser: 2.1.1 + dev: true + + /fill-range/7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: true + + /find-up/4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + dev: true + + /fs.realpath/1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: true + + /fsevents/2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /function-bind/1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + dev: true + + /gensync/1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + dev: true + + /get-caller-file/2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + dev: true + + /get-package-type/0.1.0: + resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} + engines: {node: '>=8.0.0'} + dev: true + + /get-stream/6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + dev: true + + /glob/7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /globals/11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + dev: true + + /graceful-fs/4.2.10: + resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} + dev: true + + /has-flag/3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + dev: true + + /has-flag/4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + dev: true + + /has/1.0.3: + resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} + engines: {node: '>= 0.4.0'} + dependencies: + function-bind: 1.1.1 + dev: true + + /html-escaper/2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + dev: true + + /human-signals/2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + dev: true + + /husky/8.0.1: + resolution: {integrity: sha512-xs7/chUH/CKdOCs7Zy0Aev9e/dKOMZf3K1Az1nar3tzlv0jfqnYtu235bstsWTmXOR0EfINrPa97yy4Lz6RiKw==} + engines: {node: '>=14'} + hasBin: true + dev: true + + /import-local/3.1.0: + resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==} + engines: {node: '>=8'} + hasBin: true + dependencies: + pkg-dir: 4.2.0 + resolve-cwd: 3.0.0 + dev: true + + /imurmurhash/0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + dev: true + + /inflight/1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + + /inherits/2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: true + + /is-arrayish/0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + dev: true + + /is-core-module/2.9.0: + resolution: {integrity: sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==} + dependencies: + has: 1.0.3 + dev: true + + /is-fullwidth-code-point/3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + dev: true + + /is-generator-fn/2.1.0: + resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} + engines: {node: '>=6'} + dev: true + + /is-number/7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: true + + /is-stream/2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + dev: true + + /isexe/2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true + + /istanbul-lib-coverage/3.2.0: + resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==} + engines: {node: '>=8'} + dev: true + + /istanbul-lib-instrument/5.2.0: + resolution: {integrity: sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==} + engines: {node: '>=8'} + dependencies: + '@babel/core': 7.18.9 + '@babel/parser': 7.18.9 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.0 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + /istanbul-lib-report/3.0.0: + resolution: {integrity: sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==} + engines: {node: '>=8'} + dependencies: + istanbul-lib-coverage: 3.2.0 + make-dir: 3.1.0 + supports-color: 7.2.0 + dev: true + + /istanbul-lib-source-maps/4.0.1: + resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} + engines: {node: '>=10'} + dependencies: + debug: 4.3.4 + istanbul-lib-coverage: 3.2.0 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color + dev: true + + /istanbul-reports/3.1.5: + resolution: {integrity: sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==} + engines: {node: '>=8'} + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.0 + dev: true + + /jest-changed-files/28.1.3: + resolution: {integrity: sha512-esaOfUWJXk2nfZt9SPyC8gA1kNfdKLkQWyzsMlqq8msYSlNKfmZxfRgZn4Cd4MGVUF+7v6dBs0d5TOAKa7iIiA==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + execa: 5.1.1 + p-limit: 3.1.0 + dev: true + + /jest-circus/28.1.3: + resolution: {integrity: sha512-cZ+eS5zc79MBwt+IhQhiEp0OeBddpc1n8MBo1nMB8A7oPMKEO+Sre+wHaLJexQUj9Ya/8NOBY0RESUgYjB6fow==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@jest/environment': 28.1.3 + '@jest/expect': 28.1.3 + '@jest/test-result': 28.1.3 + '@jest/types': 28.1.3 + '@types/node': 18.6.2 + chalk: 4.1.2 + co: 4.6.0 + dedent: 0.7.0 + is-generator-fn: 2.1.0 + jest-each: 28.1.3 + jest-matcher-utils: 28.1.3 + jest-message-util: 28.1.3 + jest-runtime: 28.1.3 + jest-snapshot: 28.1.3 + jest-util: 28.1.3 + p-limit: 3.1.0 + pretty-format: 28.1.3 + slash: 3.0.0 + stack-utils: 2.0.5 + transitivePeerDependencies: + - supports-color + dev: true + + /jest-cli/28.1.3: + resolution: {integrity: sha512-roY3kvrv57Azn1yPgdTebPAXvdR2xfezaKKYzVxZ6It/5NCxzJym6tUI5P1zkdWhfUYkxEI9uZWcQdaFLo8mJQ==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@jest/core': 28.1.3 + '@jest/test-result': 28.1.3 + '@jest/types': 28.1.3 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.10 + import-local: 3.1.0 + jest-config: 28.1.3 + jest-util: 28.1.3 + jest-validate: 28.1.3 + prompts: 2.4.2 + yargs: 17.5.1 + transitivePeerDependencies: + - '@types/node' + - supports-color + - ts-node + dev: true + + /jest-config/28.1.3: + resolution: {integrity: sha512-MG3INjByJ0J4AsNBm7T3hsuxKQqFIiRo/AUqb1q9LRKI5UU6Aar9JHbr9Ivn1TVwfUD9KirRoM/T6u8XlcQPHQ==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + peerDependencies: + '@types/node': '*' + ts-node: '>=9.0.0' + peerDependenciesMeta: + '@types/node': + optional: true + ts-node: + optional: true + dependencies: + '@babel/core': 7.18.9 + '@jest/test-sequencer': 28.1.3 + '@jest/types': 28.1.3 + babel-jest: 28.1.3_@babel+core@7.18.9 + chalk: 4.1.2 + ci-info: 3.3.2 + deepmerge: 4.2.2 + glob: 7.2.3 + graceful-fs: 4.2.10 + jest-circus: 28.1.3 + jest-environment-node: 28.1.3 + jest-get-type: 28.0.2 + jest-regex-util: 28.0.2 + jest-resolve: 28.1.3 + jest-runner: 28.1.3 + jest-util: 28.1.3 + jest-validate: 28.1.3 + micromatch: 4.0.5 + parse-json: 5.2.0 + pretty-format: 28.1.3 + slash: 3.0.0 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /jest-config/28.1.3_@types+node@18.6.2: + resolution: {integrity: sha512-MG3INjByJ0J4AsNBm7T3hsuxKQqFIiRo/AUqb1q9LRKI5UU6Aar9JHbr9Ivn1TVwfUD9KirRoM/T6u8XlcQPHQ==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + peerDependencies: + '@types/node': '*' + ts-node: '>=9.0.0' + peerDependenciesMeta: + '@types/node': + optional: true + ts-node: + optional: true + dependencies: + '@babel/core': 7.18.9 + '@jest/test-sequencer': 28.1.3 + '@jest/types': 28.1.3 + '@types/node': 18.6.2 + babel-jest: 28.1.3_@babel+core@7.18.9 + chalk: 4.1.2 + ci-info: 3.3.2 + deepmerge: 4.2.2 + glob: 7.2.3 + graceful-fs: 4.2.10 + jest-circus: 28.1.3 + jest-environment-node: 28.1.3 + jest-get-type: 28.0.2 + jest-regex-util: 28.0.2 + jest-resolve: 28.1.3 + jest-runner: 28.1.3 + jest-util: 28.1.3 + jest-validate: 28.1.3 + micromatch: 4.0.5 + parse-json: 5.2.0 + pretty-format: 28.1.3 + slash: 3.0.0 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /jest-diff/28.1.3: + resolution: {integrity: sha512-8RqP1B/OXzjjTWkqMX67iqgwBVJRgCyKD3L9nq+6ZqJMdvjE8RgHktqZ6jNrkdMT+dJuYNI3rhQpxaz7drJHfw==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + chalk: 4.1.2 + diff-sequences: 28.1.1 + jest-get-type: 28.0.2 + pretty-format: 28.1.3 + dev: true + + /jest-docblock/28.1.1: + resolution: {integrity: sha512-3wayBVNiOYx0cwAbl9rwm5kKFP8yHH3d/fkEaL02NPTkDojPtheGB7HZSFY4wzX+DxyrvhXz0KSCVksmCknCuA==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + detect-newline: 3.1.0 + dev: true + + /jest-each/28.1.3: + resolution: {integrity: sha512-arT1z4sg2yABU5uogObVPvSlSMQlDA48owx07BDPAiasW0yYpYHYOo4HHLz9q0BVzDVU4hILFjzJw0So9aCL/g==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@jest/types': 28.1.3 + chalk: 4.1.2 + jest-get-type: 28.0.2 + jest-util: 28.1.3 + pretty-format: 28.1.3 + dev: true + + /jest-environment-node/28.1.3: + resolution: {integrity: sha512-ugP6XOhEpjAEhGYvp5Xj989ns5cB1K6ZdjBYuS30umT4CQEETaxSiPcZ/E1kFktX4GkrcM4qu07IIlDYX1gp+A==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@jest/environment': 28.1.3 + '@jest/fake-timers': 28.1.3 + '@jest/types': 28.1.3 + '@types/node': 18.6.2 + jest-mock: 28.1.3 + jest-util: 28.1.3 + dev: true + + /jest-get-type/28.0.2: + resolution: {integrity: sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dev: true + + /jest-haste-map/28.1.3: + resolution: {integrity: sha512-3S+RQWDXccXDKSWnkHa/dPwt+2qwA8CJzR61w3FoYCvoo3Pn8tvGcysmMF0Bj0EX5RYvAI2EIvC57OmotfdtKA==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@jest/types': 28.1.3 + '@types/graceful-fs': 4.1.5 + '@types/node': 18.6.2 + anymatch: 3.1.2 + fb-watchman: 2.0.1 + graceful-fs: 4.2.10 + jest-regex-util: 28.0.2 + jest-util: 28.1.3 + jest-worker: 28.1.3 + micromatch: 4.0.5 + walker: 1.0.8 + optionalDependencies: + fsevents: 2.3.2 + dev: true + + /jest-leak-detector/28.1.3: + resolution: {integrity: sha512-WFVJhnQsiKtDEo5lG2mM0v40QWnBM+zMdHHyJs8AWZ7J0QZJS59MsyKeJHWhpBZBH32S48FOVvGyOFT1h0DlqA==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + jest-get-type: 28.0.2 + pretty-format: 28.1.3 + dev: true + + /jest-matcher-utils/28.1.3: + resolution: {integrity: sha512-kQeJ7qHemKfbzKoGjHHrRKH6atgxMk8Enkk2iPQ3XwO6oE/KYD8lMYOziCkeSB9G4adPM4nR1DE8Tf5JeWH6Bw==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + chalk: 4.1.2 + jest-diff: 28.1.3 + jest-get-type: 28.0.2 + pretty-format: 28.1.3 + dev: true + + /jest-message-util/28.1.3: + resolution: {integrity: sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@babel/code-frame': 7.18.6 + '@jest/types': 28.1.3 + '@types/stack-utils': 2.0.1 + chalk: 4.1.2 + graceful-fs: 4.2.10 + micromatch: 4.0.5 + pretty-format: 28.1.3 + slash: 3.0.0 + stack-utils: 2.0.5 + dev: true + + /jest-mock/28.1.3: + resolution: {integrity: sha512-o3J2jr6dMMWYVH4Lh/NKmDXdosrsJgi4AviS8oXLujcjpCMBb1FMsblDnOXKZKfSiHLxYub1eS0IHuRXsio9eA==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@jest/types': 28.1.3 + '@types/node': 18.6.2 + dev: true + + /jest-pnp-resolver/1.2.2_jest-resolve@28.1.3: + resolution: {integrity: sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==} + engines: {node: '>=6'} + peerDependencies: + jest-resolve: '*' + peerDependenciesMeta: + jest-resolve: + optional: true + dependencies: + jest-resolve: 28.1.3 + dev: true + + /jest-regex-util/28.0.2: + resolution: {integrity: sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dev: true + + /jest-resolve-dependencies/28.1.3: + resolution: {integrity: sha512-qa0QO2Q0XzQoNPouMbCc7Bvtsem8eQgVPNkwn9LnS+R2n8DaVDPL/U1gngC0LTl1RYXJU0uJa2BMC2DbTfFrHA==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + jest-regex-util: 28.0.2 + jest-snapshot: 28.1.3 + transitivePeerDependencies: + - supports-color + dev: true + + /jest-resolve/28.1.3: + resolution: {integrity: sha512-Z1W3tTjE6QaNI90qo/BJpfnvpxtaFTFw5CDgwpyE/Kz8U/06N1Hjf4ia9quUhCh39qIGWF1ZuxFiBiJQwSEYKQ==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + chalk: 4.1.2 + graceful-fs: 4.2.10 + jest-haste-map: 28.1.3 + jest-pnp-resolver: 1.2.2_jest-resolve@28.1.3 + jest-util: 28.1.3 + jest-validate: 28.1.3 + resolve: 1.22.1 + resolve.exports: 1.1.0 + slash: 3.0.0 + dev: true + + /jest-runner/28.1.3: + resolution: {integrity: sha512-GkMw4D/0USd62OVO0oEgjn23TM+YJa2U2Wu5zz9xsQB1MxWKDOlrnykPxnMsN0tnJllfLPinHTka61u0QhaxBA==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@jest/console': 28.1.3 + '@jest/environment': 28.1.3 + '@jest/test-result': 28.1.3 + '@jest/transform': 28.1.3 + '@jest/types': 28.1.3 + '@types/node': 18.6.2 + chalk: 4.1.2 + emittery: 0.10.2 + graceful-fs: 4.2.10 + jest-docblock: 28.1.1 + jest-environment-node: 28.1.3 + jest-haste-map: 28.1.3 + jest-leak-detector: 28.1.3 + jest-message-util: 28.1.3 + jest-resolve: 28.1.3 + jest-runtime: 28.1.3 + jest-util: 28.1.3 + jest-watcher: 28.1.3 + jest-worker: 28.1.3 + p-limit: 3.1.0 + source-map-support: 0.5.13 + transitivePeerDependencies: + - supports-color + dev: true + + /jest-runtime/28.1.3: + resolution: {integrity: sha512-NU+881ScBQQLc1JHG5eJGU7Ui3kLKrmwCPPtYsJtBykixrM2OhVQlpMmFWJjMyDfdkGgBMNjXCGB/ebzsgNGQw==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@jest/environment': 28.1.3 + '@jest/fake-timers': 28.1.3 + '@jest/globals': 28.1.3 + '@jest/source-map': 28.1.2 + '@jest/test-result': 28.1.3 + '@jest/transform': 28.1.3 + '@jest/types': 28.1.3 + chalk: 4.1.2 + cjs-module-lexer: 1.2.2 + collect-v8-coverage: 1.0.1 + execa: 5.1.1 + glob: 7.2.3 + graceful-fs: 4.2.10 + jest-haste-map: 28.1.3 + jest-message-util: 28.1.3 + jest-mock: 28.1.3 + jest-regex-util: 28.0.2 + jest-resolve: 28.1.3 + jest-snapshot: 28.1.3 + jest-util: 28.1.3 + slash: 3.0.0 + strip-bom: 4.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /jest-snapshot/28.1.3: + resolution: {integrity: sha512-4lzMgtiNlc3DU/8lZfmqxN3AYD6GGLbl+72rdBpXvcV+whX7mDrREzkPdp2RnmfIiWBg1YbuFSkXduF2JcafJg==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@babel/core': 7.18.9 + '@babel/generator': 7.18.9 + '@babel/plugin-syntax-typescript': 7.18.6_@babel+core@7.18.9 + '@babel/traverse': 7.18.9 + '@babel/types': 7.18.9 + '@jest/expect-utils': 28.1.3 + '@jest/transform': 28.1.3 + '@jest/types': 28.1.3 + '@types/babel__traverse': 7.17.1 + '@types/prettier': 2.6.4 + babel-preset-current-node-syntax: 1.0.1_@babel+core@7.18.9 + chalk: 4.1.2 + expect: 28.1.3 + graceful-fs: 4.2.10 + jest-diff: 28.1.3 + jest-get-type: 28.0.2 + jest-haste-map: 28.1.3 + jest-matcher-utils: 28.1.3 + jest-message-util: 28.1.3 + jest-util: 28.1.3 + natural-compare: 1.4.0 + pretty-format: 28.1.3 + semver: 7.3.7 + transitivePeerDependencies: + - supports-color + dev: true + + /jest-util/28.1.3: + resolution: {integrity: sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@jest/types': 28.1.3 + '@types/node': 18.6.2 + chalk: 4.1.2 + ci-info: 3.3.2 + graceful-fs: 4.2.10 + picomatch: 2.3.1 + dev: true + + /jest-validate/28.1.3: + resolution: {integrity: sha512-SZbOGBWEsaTxBGCOpsRWlXlvNkvTkY0XxRfh7zYmvd8uL5Qzyg0CHAXiXKROflh801quA6+/DsT4ODDthOC/OA==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@jest/types': 28.1.3 + camelcase: 6.3.0 + chalk: 4.1.2 + jest-get-type: 28.0.2 + leven: 3.1.0 + pretty-format: 28.1.3 + dev: true + + /jest-watcher/28.1.3: + resolution: {integrity: sha512-t4qcqj9hze+jviFPUN3YAtAEeFnr/azITXQEMARf5cMwKY2SMBRnCQTXLixTl20OR6mLh9KLMrgVJgJISym+1g==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@jest/test-result': 28.1.3 + '@jest/types': 28.1.3 + '@types/node': 18.6.2 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + emittery: 0.10.2 + jest-util: 28.1.3 + string-length: 4.0.2 + dev: true + + /jest-worker/28.1.3: + resolution: {integrity: sha512-CqRA220YV/6jCo8VWvAt1KKx6eek1VIHMPeLEbpcfSfkEeWyBNppynM/o6q+Wmw+sOhos2ml34wZbSX3G13//g==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@types/node': 18.6.2 + merge-stream: 2.0.0 + supports-color: 8.1.1 + dev: true + + /jest/28.1.3: + resolution: {integrity: sha512-N4GT5on8UkZgH0O5LUavMRV1EDEhNTL0KEfRmDIeZHSV7p2XgLoY9t9VDUgL6o+yfdgYHVxuz81G8oB9VG5uyA==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@jest/core': 28.1.3 + '@jest/types': 28.1.3 + import-local: 3.1.0 + jest-cli: 28.1.3 + transitivePeerDependencies: + - '@types/node' + - supports-color + - ts-node + dev: true + + /js-tokens/4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + dev: true + + /js-yaml/3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + dev: true + + /js-yaml/4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + dev: true + + /jsesc/2.5.2: + resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /json-parse-even-better-errors/2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + dev: true + + /json5/2.2.1: + resolution: {integrity: sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==} + engines: {node: '>=6'} + hasBin: true + dev: true + + /kleur/3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + dev: true + + /leven/3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + dev: true + + /lines-and-columns/1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + dev: true + + /locate-path/5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + dependencies: + p-locate: 4.1.0 + dev: true + + /lodash.memoize/4.1.2: + resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} + dev: true + + /lru-cache/6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + dev: true + + /make-dir/3.1.0: + resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} + engines: {node: '>=8'} + dependencies: + semver: 6.3.0 + dev: true + + /make-error/1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + dev: true + + /makeerror/1.0.12: + resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} + dependencies: + tmpl: 1.0.5 + dev: true + + /merge-stream/2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + dev: true + + /micromatch/4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + dev: true + + /mimic-fn/2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + dev: true + + /minimatch/3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /ms/2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + dev: true + + /natural-compare/1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + dev: true + + /node-int64/0.4.0: + resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} + dev: true + + /node-releases/2.0.6: + resolution: {integrity: sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==} + dev: true + + /normalize-path/3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: true + + /npm-run-path/4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + dependencies: + path-key: 3.1.1 + dev: true + + /once/1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: true + + /onetime/5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + dependencies: + mimic-fn: 2.1.0 + dev: true + + /p-limit/2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + dependencies: + p-try: 2.2.0 + dev: true + + /p-limit/3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + dev: true + + /p-locate/4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + dependencies: + p-limit: 2.3.0 + dev: true + + /p-try/2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + dev: true + + /parse-json/5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + dependencies: + '@babel/code-frame': 7.18.6 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + dev: true + + /path-exists/4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: true + + /path-is-absolute/1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: true + + /path-key/3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + dev: true + + /path-parse/1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: true + + /picocolors/1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + dev: true + + /picomatch/2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + dev: true + + /pirates/4.0.5: + resolution: {integrity: sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==} + engines: {node: '>= 6'} + dev: true + + /pkg-dir/4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + dependencies: + find-up: 4.1.0 + dev: true + + /pretty-format/28.1.3: + resolution: {integrity: sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@jest/schemas': 28.1.3 + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 18.2.0 + dev: true + + /prompts/2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + dev: true + + /react-is/18.2.0: + resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} + dev: true + + /require-directory/2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + dev: true + + /resolve-cwd/3.0.0: + resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} + engines: {node: '>=8'} + dependencies: + resolve-from: 5.0.0 + dev: true + + /resolve-from/5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + dev: true + + /resolve.exports/1.1.0: + resolution: {integrity: sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==} + engines: {node: '>=10'} + dev: true + + /resolve/1.22.1: + resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} + hasBin: true + dependencies: + is-core-module: 2.9.0 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: true + + /rimraf/3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: true + + /safe-buffer/5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + dev: true + + /semver/6.3.0: + resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} + hasBin: true + dev: true + + /semver/7.3.7: + resolution: {integrity: sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: true + + /shebang-command/2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + dev: true + + /shebang-regex/3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: true + + /signal-exit/3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + dev: true + + /sisteransi/1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + dev: true + + /slash/3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + dev: true + + /source-map-support/0.5.13: + resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + dev: true + + /source-map/0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: true + + /sprintf-js/1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + dev: true + + /stack-utils/2.0.5: + resolution: {integrity: sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==} + engines: {node: '>=10'} + dependencies: + escape-string-regexp: 2.0.0 + dev: true + + /string-length/4.0.2: + resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} + engines: {node: '>=10'} + dependencies: + char-regex: 1.0.2 + strip-ansi: 6.0.1 + dev: true + + /string-width/4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + dev: true + + /strip-ansi/6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: true + + /strip-bom/4.0.0: + resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + engines: {node: '>=8'} + dev: true + + /strip-final-newline/2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + dev: true + + /strip-json-comments/3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + dev: true + + /supports-color/5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + dependencies: + has-flag: 3.0.0 + dev: true + + /supports-color/7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + dev: true + + /supports-color/8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + dependencies: + has-flag: 4.0.0 + dev: true + + /supports-hyperlinks/2.2.0: + resolution: {integrity: sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + supports-color: 7.2.0 + dev: true + + /supports-preserve-symlinks-flag/1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: true + + /terminal-link/2.1.1: + resolution: {integrity: sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==} + engines: {node: '>=8'} + dependencies: + ansi-escapes: 4.3.2 + supports-hyperlinks: 2.2.0 + dev: true + + /test-exclude/6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 7.2.3 + minimatch: 3.1.2 + dev: true + + /tmpl/1.0.5: + resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} + dev: true + + /to-fast-properties/2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + dev: true + + /to-regex-range/5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: true + + /ts-jest/28.0.7_bi2kohzqnxavgozw3csgny5hju: + resolution: {integrity: sha512-wWXCSmTwBVmdvWrOpYhal79bDpioDy4rTT+0vyUnE3ZzM7LOAAGG9NXwzkEL/a516rQEgnMmS/WKP9jBPCVJyA==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + hasBin: true + peerDependencies: + '@babel/core': '>=7.0.0-beta.0 <8' + '@jest/types': ^28.0.0 + babel-jest: ^28.0.0 + esbuild: '*' + jest: ^28.0.0 + typescript: '>=4.3' + peerDependenciesMeta: + '@babel/core': + optional: true + '@jest/types': + optional: true + babel-jest: + optional: true + esbuild: + optional: true + dependencies: + bs-logger: 0.2.6 + fast-json-stable-stringify: 2.1.0 + jest: 28.1.3 + jest-util: 28.1.3 + json5: 2.2.1 + lodash.memoize: 4.1.2 + make-error: 1.3.6 + semver: 7.3.7 + typescript: 4.7.4 + yargs-parser: 21.0.1 + dev: true + + /type-detect/4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + dev: true + + /type-fest/0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + dev: true + + /typescript/4.7.4: + resolution: {integrity: sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==} + engines: {node: '>=4.2.0'} + hasBin: true + dev: true + + /update-browserslist-db/1.0.5_browserslist@4.21.3: + resolution: {integrity: sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + dependencies: + browserslist: 4.21.3 + escalade: 3.1.1 + picocolors: 1.0.0 + dev: true + + /v8-to-istanbul/9.0.1: + resolution: {integrity: sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==} + engines: {node: '>=10.12.0'} + dependencies: + '@jridgewell/trace-mapping': 0.3.14 + '@types/istanbul-lib-coverage': 2.0.4 + convert-source-map: 1.8.0 + dev: true + + /walker/1.0.8: + resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + dependencies: + makeerror: 1.0.12 + dev: true + + /which/2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /wrap-ansi/7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: true + + /wrappy/1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: true + + /write-file-atomic/4.0.1: + resolution: {integrity: sha512-nSKUxgAbyioruk6hU87QzVbY279oYT6uiwgDoujth2ju4mJ+TZau7SQBhtbTmUyuNYTuXnSyRn66FV0+eCgcrQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16} + dependencies: + imurmurhash: 0.1.4 + signal-exit: 3.0.7 + dev: true + + /y18n/5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + dev: true + + /yallist/4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: true + + /yargs-parser/21.0.1: + resolution: {integrity: sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==} + engines: {node: '>=12'} + dev: true + + /yargs/17.5.1: + resolution: {integrity: sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==} + engines: {node: '>=12'} + dependencies: + cliui: 7.0.4 + escalade: 3.1.1 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.0.1 + dev: true + + /yocto-queue/0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + dev: true diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..650222c3 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "es6", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "esModuleInterop": true, + "module": "commonjs", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": false, + "jsx": "preserve", + "incremental": true + }, + "include": ["apps/**/*.ts"] +}