mirror of
https://github.com/sourcebot-dev/sourcebot.git
synced 2025-12-11 20:05:25 +00:00
Add additional telemetry (#63)
This commit is contained in:
parent
379976d458
commit
adba96a8c4
15 changed files with 229 additions and 14 deletions
|
|
@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Added additional telemetry events. ([#63](https://github.com/sourcebot-dev/sourcebot/pull/63))
|
||||||
|
|
||||||
## [2.4.0] - 2024-11-06
|
## [2.4.0] - 2024-11-06
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
|
||||||
|
|
@ -55,13 +55,14 @@ RUN echo "Sourcebot Version: $SOURCEBOT_VERSION"
|
||||||
ENV SOURCEBOT_LOG_LEVEL=info
|
ENV SOURCEBOT_LOG_LEVEL=info
|
||||||
|
|
||||||
# @note: This is also set in .env
|
# @note: This is also set in .env
|
||||||
ENV NEXT_PUBLIC_POSTHOG_KEY=phc_VFn4CkEGHRdlVyOOw8mfkoj1DKVoG6y1007EClvzAnS
|
ENV POSTHOG_KEY=phc_VFn4CkEGHRdlVyOOw8mfkoj1DKVoG6y1007EClvzAnS
|
||||||
|
ENV NEXT_PUBLIC_POSTHOG_KEY=$POSTHOG_KEY
|
||||||
|
|
||||||
# Sourcebot collects anonymous usage data using [PostHog](https://posthog.com/). Uncomment this line to disable.
|
# Sourcebot collects anonymous usage data using [PostHog](https://posthog.com/). Uncomment this line to disable.
|
||||||
# ENV SOURCEBOT_TELEMETRY_DISABLED=1
|
# ENV SOURCEBOT_TELEMETRY_DISABLED=1
|
||||||
|
|
||||||
# Configure dependencies
|
# Configure dependencies
|
||||||
RUN apk add --no-cache git ca-certificates bind-tools tini jansson wget supervisor uuidgen curl perl
|
RUN apk add --no-cache git ca-certificates bind-tools tini jansson wget supervisor uuidgen curl perl jq
|
||||||
|
|
||||||
# Configure zoekt
|
# Configure zoekt
|
||||||
COPY vendor/zoekt/install-ctags-alpine.sh .
|
COPY vendor/zoekt/install-ctags-alpine.sh .
|
||||||
|
|
|
||||||
|
|
@ -15,24 +15,48 @@ fi
|
||||||
|
|
||||||
# In order to detect if this is the first run, we create a `.installed` file in
|
# In order to detect if this is the first run, we create a `.installed` file in
|
||||||
# the cache directory.
|
# the cache directory.
|
||||||
FIRST_RUN_FILE="$DATA_CACHE_DIR/.installed"
|
FIRST_RUN_FILE="$DATA_CACHE_DIR/.installedv2"
|
||||||
|
|
||||||
if [ ! -f "$FIRST_RUN_FILE" ]; then
|
if [ ! -f "$FIRST_RUN_FILE" ]; then
|
||||||
touch "$FIRST_RUN_FILE"
|
touch "$FIRST_RUN_FILE"
|
||||||
|
export SOURCEBOT_INSTALL_ID=$(uuidgen)
|
||||||
|
|
||||||
# If this is our first run, send a `install` event to PostHog
|
# If this is our first run, send a `install` event to PostHog
|
||||||
# (if telemetry is enabled)
|
# (if telemetry is enabled)
|
||||||
if [ -z "$SOURCEBOT_TELEMETRY_DISABLED" ]; then
|
if [ -z "$SOURCEBOT_TELEMETRY_DISABLED" ]; then
|
||||||
curl -L -s --header "Content-Type: application/json" -d '{
|
curl -L -s --header "Content-Type: application/json" -d '{
|
||||||
"api_key": "'"$NEXT_PUBLIC_POSTHOG_KEY"'",
|
"api_key": "'"$POSTHOG_KEY"'",
|
||||||
"event": "install",
|
"event": "install",
|
||||||
"distinct_id": "'"$(uuidgen)"'",
|
"distinct_id": "'"$SOURCEBOT_INSTALL_ID"'",
|
||||||
"properties": {
|
"properties": {
|
||||||
"sourcebot_version": "'"$SOURCEBOT_VERSION"'"
|
"sourcebot_version": "'"$SOURCEBOT_VERSION"'"
|
||||||
}
|
}
|
||||||
}' https://us.i.posthog.com/capture/ > /dev/null
|
}' https://us.i.posthog.com/capture/ > /dev/null
|
||||||
fi
|
fi
|
||||||
|
else
|
||||||
|
export SOURCEBOT_INSTALL_ID=$(cat "$FIRST_RUN_FILE" | jq -r '.install_id')
|
||||||
|
PREVIOUS_VERSION=$(cat "$FIRST_RUN_FILE" | jq -r '.version')
|
||||||
|
|
||||||
|
# If the version has changed, we assume an upgrade has occurred.
|
||||||
|
if [ "$PREVIOUS_VERSION" != "$SOURCEBOT_VERSION" ]; then
|
||||||
|
echo -e "\e[34m[Info] Upgraded from version $PREVIOUS_VERSION to $SOURCEBOT_VERSION\e[0m"
|
||||||
|
|
||||||
|
if [ -z "$SOURCEBOT_TELEMETRY_DISABLED" ]; then
|
||||||
|
curl -L -s --header "Content-Type: application/json" -d '{
|
||||||
|
"api_key": "'"$POSTHOG_KEY"'",
|
||||||
|
"event": "upgrade",
|
||||||
|
"distinct_id": "'"$SOURCEBOT_INSTALL_ID"'",
|
||||||
|
"properties": {
|
||||||
|
"from_version": "'"$PREVIOUS_VERSION"'",
|
||||||
|
"to_version": "'"$SOURCEBOT_VERSION"'"
|
||||||
|
}
|
||||||
|
}' https://us.i.posthog.com/capture/ > /dev/null
|
||||||
|
fi
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echo "{\"version\": \"$SOURCEBOT_VERSION\", \"install_id\": \"$SOURCEBOT_INSTALL_ID\"}" > "$FIRST_RUN_FILE"
|
||||||
|
|
||||||
# Fallback to sample config if a config does not exist
|
# Fallback to sample config if a config does not exist
|
||||||
if echo "$CONFIG_PATH" | grep -qE '^https?://'; then
|
if echo "$CONFIG_PATH" | grep -qE '^https?://'; then
|
||||||
if ! curl --output /dev/null --silent --head --fail "$CONFIG_PATH"; then
|
if ! curl --output /dev/null --silent --head --fail "$CONFIG_PATH"; then
|
||||||
|
|
|
||||||
4
packages/backend/.env
Normal file
4
packages/backend/.env
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
POSTHOG_HOST=https://us.i.posthog.com
|
||||||
|
|
||||||
|
# @note: This is also set in the Dockerfile
|
||||||
|
POSTHOG_KEY=phc_VFn4CkEGHRdlVyOOw8mfkoj1DKVoG6y1007EClvzAnS
|
||||||
3
packages/backend/.gitignore
vendored
3
packages/backend/.gitignore
vendored
|
|
@ -1 +1,2 @@
|
||||||
dist/
|
dist/
|
||||||
|
!.env
|
||||||
|
|
@ -24,9 +24,11 @@
|
||||||
"@octokit/rest": "^21.0.2",
|
"@octokit/rest": "^21.0.2",
|
||||||
"argparse": "^2.0.1",
|
"argparse": "^2.0.1",
|
||||||
"cross-fetch": "^4.0.0",
|
"cross-fetch": "^4.0.0",
|
||||||
|
"dotenv": "^16.4.5",
|
||||||
"gitea-js": "^1.22.0",
|
"gitea-js": "^1.22.0",
|
||||||
"lowdb": "^7.0.1",
|
"lowdb": "^7.0.1",
|
||||||
"micromatch": "^4.0.8",
|
"micromatch": "^4.0.8",
|
||||||
|
"posthog-node": "^4.2.1",
|
||||||
"simple-git": "^3.27.0",
|
"simple-git": "^3.27.0",
|
||||||
"strip-json-comments": "^5.0.1",
|
"strip-json-comments": "^5.0.1",
|
||||||
"winston": "^3.15.0"
|
"winston": "^3.15.0"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,23 @@
|
||||||
|
import dotenv from 'dotenv';
|
||||||
|
|
||||||
export const getEnv = (env: string | undefined, defaultValue = '') => {
|
export const getEnv = (env: string | undefined, defaultValue = '') => {
|
||||||
return env ?? defaultValue;
|
return env ?? defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getEnvBoolean = (env: string | undefined, defaultValue: boolean) => {
|
||||||
|
if (!env) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
return env === 'true' || env === '1';
|
||||||
|
}
|
||||||
|
|
||||||
|
dotenv.config({
|
||||||
|
path: './.env',
|
||||||
|
});
|
||||||
|
|
||||||
export const SOURCEBOT_LOG_LEVEL = getEnv(process.env.SOURCEBOT_LOG_LEVEL, 'info');
|
export const SOURCEBOT_LOG_LEVEL = getEnv(process.env.SOURCEBOT_LOG_LEVEL, 'info');
|
||||||
|
export const SOURCEBOT_TELEMETRY_DISABLED = getEnvBoolean(process.env.SOURCEBOT_TELEMETRY_DISABLED, false);
|
||||||
|
export const SOURCEBOT_INSTALL_ID = getEnv(process.env.SOURCEBOT_INSTALL_ID, 'unknown');
|
||||||
|
export const SOURCEBOT_VERSION = getEnv(process.env.SOURCEBOT_VERSION, 'unknown');
|
||||||
|
export const POSTHOG_KEY = getEnv(process.env.POSTHOG_KEY);
|
||||||
|
export const POSTHOG_HOST = getEnv(process.env.POSTHOG_HOST);
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ export const getGiteaReposFromConfig = async (config: GiteaConfig, ctx: AppConte
|
||||||
|
|
||||||
return {
|
return {
|
||||||
vcs: 'git',
|
vcs: 'git',
|
||||||
|
codeHost: 'gitea',
|
||||||
name: repo.full_name!,
|
name: repo.full_name!,
|
||||||
id: repoId,
|
id: repoId,
|
||||||
cloneUrl: cloneUrl.toString(),
|
cloneUrl: cloneUrl.toString(),
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,7 @@ export const getGitHubReposFromConfig = async (config: GitHubConfig, signal: Abo
|
||||||
|
|
||||||
return {
|
return {
|
||||||
vcs: 'git',
|
vcs: 'git',
|
||||||
|
codeHost: 'github',
|
||||||
name: repo.full_name,
|
name: repo.full_name,
|
||||||
id: repoId,
|
id: repoId,
|
||||||
cloneUrl: cloneUrl.toString(),
|
cloneUrl: cloneUrl.toString(),
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,7 @@ export const getGitLabReposFromConfig = async (config: GitLabConfig, ctx: AppCon
|
||||||
|
|
||||||
return {
|
return {
|
||||||
vcs: 'git',
|
vcs: 'git',
|
||||||
|
codeHost: 'gitlab',
|
||||||
name: project.path_with_namespace,
|
name: project.path_with_namespace,
|
||||||
id: repoId,
|
id: repoId,
|
||||||
cloneUrl: cloneUrl.toString(),
|
cloneUrl: cloneUrl.toString(),
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { ArgumentParser } from "argparse";
|
import { ArgumentParser } from "argparse";
|
||||||
import { mkdir, readFile } from 'fs/promises';
|
import { mkdir, readFile } from 'fs/promises';
|
||||||
import { existsSync, watch, FSWatcher } from 'fs';
|
import { existsSync, watch } from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { SourcebotConfigurationSchema } from "./schemas/v2.js";
|
import { SourcebotConfigurationSchema } from "./schemas/v2.js";
|
||||||
import { getGitHubReposFromConfig } from "./github.js";
|
import { getGitHubReposFromConfig } from "./github.js";
|
||||||
|
|
@ -15,6 +15,7 @@ import { REINDEX_INTERVAL_MS, RESYNC_CONFIG_INTERVAL_MS } from "./constants.js";
|
||||||
import stripJsonComments from 'strip-json-comments';
|
import stripJsonComments from 'strip-json-comments';
|
||||||
import { indexGitRepository, indexLocalRepository } from "./zoekt.js";
|
import { indexGitRepository, indexLocalRepository } from "./zoekt.js";
|
||||||
import { getLocalRepoFromConfig, initLocalRepoFileWatchers } from "./local.js";
|
import { getLocalRepoFromConfig, initLocalRepoFileWatchers } from "./local.js";
|
||||||
|
import { captureEvent } from "./posthog.js";
|
||||||
|
|
||||||
const logger = createLogger('main');
|
const logger = createLogger('main');
|
||||||
|
|
||||||
|
|
@ -28,15 +29,19 @@ type Arguments = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const syncGitRepository = async (repo: GitRepository, ctx: AppContext) => {
|
const syncGitRepository = async (repo: GitRepository, ctx: AppContext) => {
|
||||||
|
let fetchDuration_s: number | undefined = undefined;
|
||||||
|
let cloneDuration_s: number | undefined = undefined;
|
||||||
|
|
||||||
if (existsSync(repo.path)) {
|
if (existsSync(repo.path)) {
|
||||||
logger.info(`Fetching ${repo.id}...`);
|
logger.info(`Fetching ${repo.id}...`);
|
||||||
|
|
||||||
const { durationMs } = await measure(() => fetchRepository(repo, ({ method, stage , progress}) => {
|
const { durationMs } = await measure(() => fetchRepository(repo, ({ method, stage , progress}) => {
|
||||||
logger.info(`git.${method} ${stage} stage ${progress}% complete for ${repo.id}`)
|
logger.info(`git.${method} ${stage} stage ${progress}% complete for ${repo.id}`)
|
||||||
}));
|
}));
|
||||||
|
fetchDuration_s = durationMs / 1000;
|
||||||
|
|
||||||
process.stdout.write('\n');
|
process.stdout.write('\n');
|
||||||
logger.info(`Fetched ${repo.id} in ${durationMs / 1000}s`);
|
logger.info(`Fetched ${repo.id} in ${fetchDuration_s}s`);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
logger.info(`Cloning ${repo.id}...`);
|
logger.info(`Cloning ${repo.id}...`);
|
||||||
|
|
@ -44,20 +49,32 @@ const syncGitRepository = async (repo: GitRepository, ctx: AppContext) => {
|
||||||
const { durationMs } = await measure(() => cloneRepository(repo, ({ method, stage, progress }) => {
|
const { durationMs } = await measure(() => cloneRepository(repo, ({ method, stage, progress }) => {
|
||||||
logger.info(`git.${method} ${stage} stage ${progress}% complete for ${repo.id}`)
|
logger.info(`git.${method} ${stage} stage ${progress}% complete for ${repo.id}`)
|
||||||
}));
|
}));
|
||||||
|
cloneDuration_s = durationMs / 1000;
|
||||||
|
|
||||||
process.stdout.write('\n');
|
process.stdout.write('\n');
|
||||||
logger.info(`Cloned ${repo.id} in ${durationMs / 1000}s`);
|
logger.info(`Cloned ${repo.id} in ${cloneDuration_s}s`);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info(`Indexing ${repo.id}...`);
|
logger.info(`Indexing ${repo.id}...`);
|
||||||
const { durationMs } = await measure(() => indexGitRepository(repo, ctx));
|
const { durationMs } = await measure(() => indexGitRepository(repo, ctx));
|
||||||
logger.info(`Indexed ${repo.id} in ${durationMs / 1000}s`);
|
const indexDuration_s = durationMs / 1000;
|
||||||
|
logger.info(`Indexed ${repo.id} in ${indexDuration_s}s`);
|
||||||
|
|
||||||
|
return {
|
||||||
|
fetchDuration_s,
|
||||||
|
cloneDuration_s,
|
||||||
|
indexDuration_s,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const syncLocalRepository = async (repo: LocalRepository, ctx: AppContext, signal?: AbortSignal) => {
|
const syncLocalRepository = async (repo: LocalRepository, ctx: AppContext, signal?: AbortSignal) => {
|
||||||
logger.info(`Indexing ${repo.id}...`);
|
logger.info(`Indexing ${repo.id}...`);
|
||||||
const { durationMs } = await measure(() => indexLocalRepository(repo, ctx, signal));
|
const { durationMs } = await measure(() => indexLocalRepository(repo, ctx, signal));
|
||||||
logger.info(`Indexed ${repo.id} in ${durationMs / 1000}s`);
|
const indexDuration_s = durationMs / 1000;
|
||||||
|
logger.info(`Indexed ${repo.id} in ${indexDuration_s}s`);
|
||||||
|
return {
|
||||||
|
indexDuration_s,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const isRepoReindxingRequired = (previous: Repository, current: Repository) => {
|
export const isRepoReindxingRequired = (previous: Repository, current: Repository) => {
|
||||||
|
|
@ -172,6 +189,11 @@ const syncConfig = async (configPath: string, db: Database, signal: AbortSignal,
|
||||||
}, db);
|
}, db);
|
||||||
} else {
|
} else {
|
||||||
await createRepository(newRepo, db);
|
await createRepository(newRepo, db);
|
||||||
|
|
||||||
|
captureEvent("repo_created", {
|
||||||
|
vcs: newRepo.vcs,
|
||||||
|
codeHost: newRepo.codeHost,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -297,11 +319,27 @@ const syncConfig = async (configPath: string, db: Database, signal: AbortSignal,
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
let indexDuration_s: number | undefined;
|
||||||
|
let fetchDuration_s: number | undefined;
|
||||||
|
let cloneDuration_s: number | undefined;
|
||||||
|
|
||||||
if (repo.vcs === 'git') {
|
if (repo.vcs === 'git') {
|
||||||
await syncGitRepository(repo, context);
|
const stats = await syncGitRepository(repo, context);
|
||||||
|
indexDuration_s = stats.indexDuration_s;
|
||||||
|
fetchDuration_s = stats.fetchDuration_s;
|
||||||
|
cloneDuration_s = stats.cloneDuration_s;
|
||||||
} else if (repo.vcs === 'local') {
|
} else if (repo.vcs === 'local') {
|
||||||
await syncLocalRepository(repo, context);
|
const stats = await syncLocalRepository(repo, context);
|
||||||
|
indexDuration_s = stats.indexDuration_s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
captureEvent('repo_synced', {
|
||||||
|
vcs: repo.vcs,
|
||||||
|
codeHost: repo.codeHost,
|
||||||
|
indexDuration_s,
|
||||||
|
fetchDuration_s,
|
||||||
|
cloneDuration_s,
|
||||||
|
});
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
// @todo : better error handling here..
|
// @todo : better error handling here..
|
||||||
logger.error(err);
|
logger.error(err);
|
||||||
|
|
@ -312,5 +350,6 @@ const syncConfig = async (configPath: string, db: Database, signal: AbortSignal,
|
||||||
}
|
}
|
||||||
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||||
|
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
|
||||||
27
packages/backend/src/posthog.ts
Normal file
27
packages/backend/src/posthog.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
import { PostHog } from 'posthog-node';
|
||||||
|
import { PosthogEvent, PosthogEventMap } from './posthogEvents.js';
|
||||||
|
import { POSTHOG_HOST, POSTHOG_KEY, SOURCEBOT_INSTALL_ID, SOURCEBOT_TELEMETRY_DISABLED, SOURCEBOT_VERSION } from './environment.js';
|
||||||
|
|
||||||
|
const posthog = new PostHog(
|
||||||
|
POSTHOG_KEY,
|
||||||
|
{
|
||||||
|
host: POSTHOG_HOST,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export function captureEvent<E extends PosthogEvent>(event: E, properties: PosthogEventMap[E]) {
|
||||||
|
if (SOURCEBOT_TELEMETRY_DISABLED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
posthog.capture({
|
||||||
|
distinctId: SOURCEBOT_INSTALL_ID,
|
||||||
|
event: event,
|
||||||
|
properties: {
|
||||||
|
...properties,
|
||||||
|
sourcebot_version: SOURCEBOT_VERSION,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await posthog.shutdown();
|
||||||
17
packages/backend/src/posthogEvents.ts
Normal file
17
packages/backend/src/posthogEvents.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
/* eslint-disable @typescript-eslint/no-empty-object-type */
|
||||||
|
|
||||||
|
export type PosthogEventMap = {
|
||||||
|
repo_created: {
|
||||||
|
vcs: string;
|
||||||
|
codeHost?: string;
|
||||||
|
},
|
||||||
|
repo_synced: {
|
||||||
|
vcs: string;
|
||||||
|
codeHost?: string;
|
||||||
|
fetchDuration_s?: number;
|
||||||
|
cloneDuration_s?: number;
|
||||||
|
indexDuration_s?: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type PosthogEvent = keyof PosthogEventMap;
|
||||||
|
|
@ -8,6 +8,7 @@ interface BaseRepository {
|
||||||
lastIndexedDate?: string;
|
lastIndexedDate?: string;
|
||||||
isFork?: boolean;
|
isFork?: boolean;
|
||||||
isArchived?: boolean;
|
isArchived?: boolean;
|
||||||
|
codeHost?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GitRepository extends BaseRepository {
|
export interface GitRepository extends BaseRepository {
|
||||||
|
|
|
||||||
75
yarn.lock
75
yarn.lock
|
|
@ -1747,6 +1747,11 @@ async@^3.2.3:
|
||||||
resolved "https://registry.yarnpkg.com/async/-/async-3.2.6.tgz#1b0728e14929d51b85b449b7f06e27c1145e38ce"
|
resolved "https://registry.yarnpkg.com/async/-/async-3.2.6.tgz#1b0728e14929d51b85b449b7f06e27c1145e38ce"
|
||||||
integrity sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==
|
integrity sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==
|
||||||
|
|
||||||
|
asynckit@^0.4.0:
|
||||||
|
version "0.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
||||||
|
integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
|
||||||
|
|
||||||
available-typed-arrays@^1.0.7:
|
available-typed-arrays@^1.0.7:
|
||||||
version "1.0.7"
|
version "1.0.7"
|
||||||
resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846"
|
resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846"
|
||||||
|
|
@ -1759,6 +1764,15 @@ axe-core@^4.10.0:
|
||||||
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.10.0.tgz#d9e56ab0147278272739a000880196cdfe113b59"
|
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.10.0.tgz#d9e56ab0147278272739a000880196cdfe113b59"
|
||||||
integrity sha512-Mr2ZakwQ7XUAjp7pAwQWRhhK8mQQ6JAaNWSjmjxil0R8BPioMtQsTLOolGYkji1rcL++3dCqZA3zWqpT+9Ew6g==
|
integrity sha512-Mr2ZakwQ7XUAjp7pAwQWRhhK8mQQ6JAaNWSjmjxil0R8BPioMtQsTLOolGYkji1rcL++3dCqZA3zWqpT+9Ew6g==
|
||||||
|
|
||||||
|
axios@^1.7.4:
|
||||||
|
version "1.7.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f"
|
||||||
|
integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==
|
||||||
|
dependencies:
|
||||||
|
follow-redirects "^1.15.6"
|
||||||
|
form-data "^4.0.0"
|
||||||
|
proxy-from-env "^1.1.0"
|
||||||
|
|
||||||
axobject-query@^4.1.0:
|
axobject-query@^4.1.0:
|
||||||
version "4.1.0"
|
version "4.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-4.1.0.tgz#28768c76d0e3cff21bc62a9e2d0b6ac30042a1ee"
|
resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-4.1.0.tgz#28768c76d0e3cff21bc62a9e2d0b6ac30042a1ee"
|
||||||
|
|
@ -1970,6 +1984,13 @@ colorspace@1.1.x:
|
||||||
color "^3.1.3"
|
color "^3.1.3"
|
||||||
text-hex "1.0.x"
|
text-hex "1.0.x"
|
||||||
|
|
||||||
|
combined-stream@^1.0.8:
|
||||||
|
version "1.0.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
|
||||||
|
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
|
||||||
|
dependencies:
|
||||||
|
delayed-stream "~1.0.0"
|
||||||
|
|
||||||
commander@^4.0.0:
|
commander@^4.0.0:
|
||||||
version "4.1.1"
|
version "4.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068"
|
resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068"
|
||||||
|
|
@ -2115,6 +2136,11 @@ define-properties@^1.1.3, define-properties@^1.2.0, define-properties@^1.2.1:
|
||||||
has-property-descriptors "^1.0.0"
|
has-property-descriptors "^1.0.0"
|
||||||
object-keys "^1.1.1"
|
object-keys "^1.1.1"
|
||||||
|
|
||||||
|
delayed-stream@~1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
||||||
|
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
|
||||||
|
|
||||||
detect-libc@^2.0.3:
|
detect-libc@^2.0.3:
|
||||||
version "2.0.3"
|
version "2.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.3.tgz#f0cd503b40f9939b894697d19ad50895e30cf700"
|
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.3.tgz#f0cd503b40f9939b894697d19ad50895e30cf700"
|
||||||
|
|
@ -2156,6 +2182,11 @@ doctrine@^3.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
esutils "^2.0.2"
|
esutils "^2.0.2"
|
||||||
|
|
||||||
|
dotenv@^16.4.5:
|
||||||
|
version "16.4.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f"
|
||||||
|
integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==
|
||||||
|
|
||||||
duplexer@~0.1.1:
|
duplexer@~0.1.1:
|
||||||
version "0.1.2"
|
version "0.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6"
|
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6"
|
||||||
|
|
@ -2713,6 +2744,11 @@ fn.name@1.x.x:
|
||||||
resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc"
|
resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc"
|
||||||
integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==
|
integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==
|
||||||
|
|
||||||
|
follow-redirects@^1.15.6:
|
||||||
|
version "1.15.9"
|
||||||
|
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1"
|
||||||
|
integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==
|
||||||
|
|
||||||
for-each@^0.3.3:
|
for-each@^0.3.3:
|
||||||
version "0.3.3"
|
version "0.3.3"
|
||||||
resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e"
|
resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e"
|
||||||
|
|
@ -2728,6 +2764,15 @@ foreground-child@^3.1.0:
|
||||||
cross-spawn "^7.0.0"
|
cross-spawn "^7.0.0"
|
||||||
signal-exit "^4.0.1"
|
signal-exit "^4.0.1"
|
||||||
|
|
||||||
|
form-data@^4.0.0:
|
||||||
|
version "4.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.1.tgz#ba1076daaaa5bfd7e99c1a6cb02aa0a5cff90d48"
|
||||||
|
integrity sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==
|
||||||
|
dependencies:
|
||||||
|
asynckit "^0.4.0"
|
||||||
|
combined-stream "^1.0.8"
|
||||||
|
mime-types "^2.1.12"
|
||||||
|
|
||||||
from@~0:
|
from@~0:
|
||||||
version "0.1.7"
|
version "0.1.7"
|
||||||
resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe"
|
resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe"
|
||||||
|
|
@ -3464,6 +3509,18 @@ micromatch@^4.0.4, micromatch@^4.0.5, micromatch@^4.0.8:
|
||||||
braces "^3.0.3"
|
braces "^3.0.3"
|
||||||
picomatch "^2.3.1"
|
picomatch "^2.3.1"
|
||||||
|
|
||||||
|
mime-db@1.52.0:
|
||||||
|
version "1.52.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
|
||||||
|
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
|
||||||
|
|
||||||
|
mime-types@^2.1.12:
|
||||||
|
version "2.1.35"
|
||||||
|
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
|
||||||
|
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
|
||||||
|
dependencies:
|
||||||
|
mime-db "1.52.0"
|
||||||
|
|
||||||
minimatch@9.0.3:
|
minimatch@9.0.3:
|
||||||
version "9.0.3"
|
version "9.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825"
|
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825"
|
||||||
|
|
@ -3892,6 +3949,14 @@ posthog-js@^1.161.5:
|
||||||
preact "^10.19.3"
|
preact "^10.19.3"
|
||||||
web-vitals "^4.0.1"
|
web-vitals "^4.0.1"
|
||||||
|
|
||||||
|
posthog-node@^4.2.1:
|
||||||
|
version "4.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/posthog-node/-/posthog-node-4.2.1.tgz#c9f077116bebd06dc65a3f9ae282d10db242c660"
|
||||||
|
integrity sha512-l+fsjYEkTik3m/G0pE7gMr4qBJP84LhK779oQm6MBzhBGpd4By4qieTW+4FUAlNCyzQTynn3Nhsa50c0IELSxQ==
|
||||||
|
dependencies:
|
||||||
|
axios "^1.7.4"
|
||||||
|
rusha "^0.8.14"
|
||||||
|
|
||||||
preact@^10.19.3:
|
preact@^10.19.3:
|
||||||
version "10.24.2"
|
version "10.24.2"
|
||||||
resolved "https://registry.yarnpkg.com/preact/-/preact-10.24.2.tgz#42179771d3b06e7adb884e3f8127ddd3d99b78f6"
|
resolved "https://registry.yarnpkg.com/preact/-/preact-10.24.2.tgz#42179771d3b06e7adb884e3f8127ddd3d99b78f6"
|
||||||
|
|
@ -3926,6 +3991,11 @@ prop-types@^15.8.1:
|
||||||
object-assign "^4.1.1"
|
object-assign "^4.1.1"
|
||||||
react-is "^16.13.1"
|
react-is "^16.13.1"
|
||||||
|
|
||||||
|
proxy-from-env@^1.1.0:
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
|
||||||
|
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
|
||||||
|
|
||||||
ps-tree@^1.2.0:
|
ps-tree@^1.2.0:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.2.0.tgz#5e7425b89508736cdd4f2224d028f7bb3f722ebd"
|
resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.2.0.tgz#5e7425b89508736cdd4f2224d028f7bb3f722ebd"
|
||||||
|
|
@ -4136,6 +4206,11 @@ run-parallel@^1.1.9:
|
||||||
dependencies:
|
dependencies:
|
||||||
queue-microtask "^1.2.2"
|
queue-microtask "^1.2.2"
|
||||||
|
|
||||||
|
rusha@^0.8.14:
|
||||||
|
version "0.8.14"
|
||||||
|
resolved "https://registry.yarnpkg.com/rusha/-/rusha-0.8.14.tgz#a977d0de9428406138b7bb90d3de5dcd024e2f68"
|
||||||
|
integrity sha512-cLgakCUf6PedEu15t8kbsjnwIFFR2D4RfL+W3iWFJ4iac7z4B0ZI8fxy4R3J956kAI68HclCFGL8MPoUVC3qVA==
|
||||||
|
|
||||||
safe-array-concat@^1.1.2:
|
safe-array-concat@^1.1.2:
|
||||||
version "1.1.2"
|
version "1.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.2.tgz#81d77ee0c4e8b863635227c721278dd524c20edb"
|
resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.2.tgz#81d77ee0c4e8b863635227c721278dd524c20edb"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue