feat: dashboard v2, esm, upgrades (#211)

* esm

* wip

* wip

* wip

* wip

* wip

* wip

* subscription notice

* wip

* wip

* wip

* fix envs

* fix: update docker build

* fix

* esm/types

* delete dashboard :D

* add patches to dockerfiles

* update packages + catalogs + ts

* wip

* remove native libs

* ts

* improvements

* fix redirects and fetching session

* try fix favicon

* fixes

* fix

* order and resize reportds within a dashboard

* improvements

* wip

* added userjot to dashboard

* fix

* add op

* wip

* different cache key

* improve date picker

* fix table

* event details loading

* redo onboarding completely

* fix login

* fix

* fix

* extend session, billing and improve bars

* fix

* reduce price on 10M
This commit is contained in:
Carl-Gerhard Lindesvärd
2025-10-16 12:27:44 +02:00
committed by GitHub
parent 436e81ecc9
commit 81a7e5d62e
741 changed files with 32695 additions and 16996 deletions

View File

@@ -13,8 +13,8 @@
},
"devDependencies": {
"@openpanel/tsconfig": "workspace:*",
"@types/node": "20.14.8",
"@types/node": "catalog:",
"@types/semver": "^7.5.4",
"typescript": "^5.2.2"
"typescript": "catalog:"
}
}

View File

@@ -1,6 +1,11 @@
import { execSync } from 'node:child_process';
import fs from 'node:fs';
import { join, resolve } from 'node:path';
import { dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
import arg from 'arg';
import type { ReleaseType } from 'semver';
import semver, { RELEASE_TYPES } from 'semver';

View File

@@ -10,14 +10,16 @@
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"noUncheckedIndexedAccess": true,
"allowUnreachableCode": true
"allowUnreachableCode": true,
"module": "ESNext",
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"verbatimModuleSyntax": true
},
"exclude": ["node_modules", "build", "dist"]
}

View File

@@ -1,6 +1,7 @@
{
"name": "@openpanel/tsconfig",
"version": "0.1.0",
"type": "module",
"private": true,
"files": ["base.json", "sdk.json", "tsup.config.json"],
"devDependencies": {

201
tooling/unused-deps.mjs Normal file
View File

@@ -0,0 +1,201 @@
#!/usr/bin/env node
import { spawn } from 'node:child_process';
import { promises as fs } from 'node:fs';
import path from 'node:path';
import url from 'node:url';
// Lazy import depcheck to avoid hard crash if not installed
async function loadDepcheck() {
try {
const mod = await import('depcheck');
return mod.default ?? mod;
} catch (err) {
console.error(
'depcheck is not installed. Install it with: pnpm -w add -D depcheck',
);
process.exitCode = 1;
process.exit(1);
}
}
const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
const repoRoot = path.resolve(__dirname, '..');
const DEFAULT_IGNORE_DIRS = [
'node_modules',
'dist',
'build',
'.next',
'.nuxt',
'.svelte-kit',
'.output',
'.turbo',
'coverage',
'.vercel',
'.cache',
'.astro',
'.pnpm',
];
function parseArgs() {
const args = new Set(process.argv.slice(2));
return {
json: args.has('--json') || args.has('-j'),
};
}
async function fileExists(p) {
try {
await fs.access(p);
return true;
} catch {
return false;
}
}
async function readWorkspacePatterns() {
const workspaceFile = path.join(repoRoot, 'pnpm-workspace.yaml');
if (!(await fileExists(workspaceFile))) return [];
const content = await fs.readFile(workspaceFile, 'utf8');
const patterns = [];
for (const line of content.split(/\r?\n/)) {
const m = line.match(/^\s*-\s*"?([^"#]+)"?\s*(?:#.*)?$/);
if (m) {
patterns.push(m[1].trim());
}
}
return patterns.filter(Boolean);
}
async function isPackageDir(dir) {
const pkgPath = path.join(dir, 'package.json');
return fileExists(pkgPath);
}
async function listSubdirs(dir) {
const entries = await fs.readdir(dir, { withFileTypes: true });
return entries
.filter((e) => e.isDirectory())
.map((e) => path.join(dir, e.name));
}
async function findPackagesFromPattern(pattern) {
// Normalize pattern relative to repo root
const absolutePattern = path.resolve(repoRoot, pattern);
if (pattern.endsWith('/**')) {
const baseDir = absolutePattern.slice(0, -3); // remove /**
return await findPackagesRecursively(baseDir);
}
if (pattern.endsWith('/*')) {
const baseDir = absolutePattern.slice(0, -2); // remove /*
return (await listSubdirs(baseDir)).filterAsync(isPackageDir);
}
// Direct path
return (await isPackageDir(absolutePattern)) ? [absolutePattern] : [];
}
async function findPackagesRecursively(startDir) {
const results = [];
async function walk(dir) {
if (!(await fileExists(dir))) return;
if (await isPackageDir(dir)) results.push(dir);
const subdirs = await listSubdirs(dir);
for (const sub of subdirs) {
await walk(sub);
}
}
await walk(startDir);
return results;
}
// Add filterAsync utility on arrays
Object.defineProperty(Array.prototype, 'filterAsync', {
value: async function (predicate) {
const results = await Promise.all(this.map(predicate));
return this.filter((_, i) => results[i]);
},
enumerable: false,
});
async function discoverWorkspacePackageDirs() {
const patterns = await readWorkspacePatterns();
const discovered = new Set();
for (const pattern of patterns) {
const pkgs = await findPackagesFromPattern(pattern);
for (const p of pkgs) discovered.add(path.resolve(p));
}
// Always include repo root as well
discovered.add(repoRoot);
return Array.from(discovered);
}
async function runDepcheckOnDir(depcheck, dir) {
const result = await depcheck(dir, {
ignoreBinPackage: false,
ignoreDirs: DEFAULT_IGNORE_DIRS,
ignoreMatches: [],
specials: [
depcheck.special.eslint,
depcheck.special.typescript,
depcheck.special.webpack,
depcheck.special.rollup,
depcheck.special.babel,
depcheck.special.postcss,
],
});
return {
dir,
unused: {
dependencies: result.dependencies ?? [],
devDependencies: result.devDependencies ?? [],
},
};
}
function relative(p) {
return path.relative(repoRoot, p) || '.';
}
function printHuman(results) {
let any = false;
for (const { dir, unused } of results) {
if (unused.dependencies.length + unused.devDependencies.length === 0)
continue;
any = true;
console.log(`\n${relative(dir)}:`);
if (unused.dependencies.length) {
console.log(` unused dependencies (${unused.dependencies.length}):`);
for (const d of unused.dependencies) console.log(` - ${d}`);
}
if (unused.devDependencies.length) {
console.log(
` unused devDependencies (${unused.devDependencies.length}):`,
);
for (const d of unused.devDependencies) console.log(` - ${d}`);
}
}
if (!any) console.log('No unused dependencies found.');
}
async function main() {
const args = parseArgs();
const depcheck = await loadDepcheck();
const packageDirs = await discoverWorkspacePackageDirs();
const checks = await Promise.all(
packageDirs.map((dir) => runDepcheckOnDir(depcheck, dir)),
);
if (args.json) {
const compact = checks
.map(({ dir, unused }) => ({ dir: relative(dir), ...unused }))
.filter((r) => r.dependencies.length || r.devDependencies.length);
console.log(JSON.stringify(compact, null, 2));
} else {
printHuman(checks);
}
}
main().catch((err) => {
console.error(err);
process.exitCode = 1;
});