diff --git a/.github/workflows/pkg-pr-new.yaml b/.github/workflows/pkg-pr-new.yaml new file mode 100644 index 00000000..03fc9f9e --- /dev/null +++ b/.github/workflows/pkg-pr-new.yaml @@ -0,0 +1,44 @@ +name: Publish Any Commit +on: + push: + branches: + - "**" + pull_request: + branches: + - "**" + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [18] + + steps: + - uses: actions/checkout@v4 + + - name: Install pnpm + uses: pnpm/action-setup@v4 + with: + version: 9.1.0 + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: "pnpm" + + - name: Install dependencies + run: pnpm install --frozen-lockfile --strict-peer-dependencies=false + + - name: Build + run: | + cd packages/scan + NODE_ENV=production pnpm build + env: + NODE_ENV: production + + - name: Publish NPM Package to pkg-pr-new + run: pnpx pkg-pr-new publish ./packages/scan + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/packages/scan/LICENSE b/LICENSE similarity index 100% rename from packages/scan/LICENSE rename to LICENSE diff --git a/package.json b/package.json index ffc5d54b..32e94c36 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,8 @@ "name": "root", "private": true, "scripts": { - "build": "pnpm --parallel --filter=!extension build", + "build": "WORKSPACE_BUILD=true pnpm --parallel --filter=!extension build && node scripts/version-warning.mjs", + "version-warning": "node scripts/version-warning.mjs", "dev": "pnpm --parallel --filter=!extension dev", "pack": "pnpm --parallel --filter=!extension pack", "pack:bump": "pnpm --filter scan pack:bump", @@ -15,6 +16,8 @@ "@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/parser": "^6.0.0", "@vercel/style-guide": "^6.0.0", + "boxen": "^8.0.1", + "chalk": "^5.3.0", "eslint": "^8.57.1", "eslint-import-resolver-typescript": "^3.7.0", "eslint-plugin-jsonc": "^2.18.2", diff --git a/packages/extension/package.json b/packages/extension/package.json index 7386566d..296c3bc0 100644 --- a/packages/extension/package.json +++ b/packages/extension/package.json @@ -6,6 +6,7 @@ "scripts": { "clean": "rm -rf dist", "build": "vite build", + "postbuild": "node ../../scripts/version-warning.mjs", "dev": "pnpm dev:chrome", "dev:chrome": "cross-env BROWSER=chrome vite", "dev:firefox": "cross-env BROWSER=firefox vite", diff --git a/packages/scan/package.json b/packages/scan/package.json index 8f022a82..6c0619c1 100644 --- a/packages/scan/package.json +++ b/packages/scan/package.json @@ -215,7 +215,7 @@ ], "scripts": { "build": "npm run build:css && NODE_ENV=production tsup", - "postbuild": "pnpm copy-astro", + "postbuild": "pnpm copy-astro && node ../../scripts/version-warning.mjs", "build:copy": "NODE_ENV=production tsup && cat dist/auto.global.js | pbcopy", "copy-astro": "cp -R src/core/monitor/params/astro dist/core/monitor/params", "dev:css": "npx tailwindcss -i ./src/core/web/assets/css/styles.tailwind.css -o ./src/core/web/assets/css/styles.css --watch", @@ -239,6 +239,7 @@ "@rollup/pluginutils": "^5.1.3", "@types/node": "^20.17.9", "bippy": "^0.0.14", + "esbuild": "^0.24.0", "estree-walker": "^3.0.3", "kleur": "^4.1.5", "mri": "^1.2.0", diff --git a/packages/scan/src/core/index.ts b/packages/scan/src/core/index.ts index e3d75cc7..cf97a045 100644 --- a/packages/scan/src/core/index.ts +++ b/packages/scan/src/core/index.ts @@ -133,12 +133,13 @@ export type MonitoringOptions = Pick< interface Monitor { pendingRequests: number; - url: string | null; - apiKey: string | null; interactions: Array; - route: string | null; session: ReturnType; - path: string | null; + url: string | null; + route: string | null; + apiKey: string | null; + commit: string | null; + branch: string | null; } interface StoreType { diff --git a/packages/scan/src/core/monitor/index.ts b/packages/scan/src/core/monitor/index.ts index f592d6b9..6afba476 100644 --- a/packages/scan/src/core/monitor/index.ts +++ b/packages/scan/src/core/monitor/index.ts @@ -14,35 +14,63 @@ import { addFiberToSet, isValidFiber, updateFiberRenderData } from '../utils'; import { initPerformanceMonitoring } from './performance'; import { getSession } from './utils'; import { flush } from './network'; +import { computeRoute } from './params/utils'; // max retries before the set of components do not get reported (avoid memory leaks of the set of fibers stored on the component aggregation) const MAX_RETRIES_BEFORE_COMPONENT_GC = 7; +export interface MonitoringProps { + url?: string; + apiKey: string; + + // For Session and Interaction + path?: string | null; // pathname (i.e /foo/2/bar/3) + route?: string | null; // computed from path and params (i.e /foo/:fooId/bar/:barId) + + // Only used / should be provided to compute the route when using Monitoring without supported framework + params?: Record; + + // Tracking regressions across commits and branches + commit?: string | null; + branch?: string | null; +} + +export type MonitoringWithoutRouteProps = Omit< + MonitoringProps, + 'route' | 'path' +>; + export const Monitoring = ({ url, apiKey, - path, - route, -}: { url?: string; apiKey: string } & { - // todo: ask for path + params so we can compute route for them - path: string; - route: string | null; -}) => { + params, + path = null, // path passed down would be reactive + route = null, + commit = null, + branch = null, +}: MonitoringProps) => { if (!apiKey) throw new Error('Please provide a valid API key for React Scan monitoring'); url ??= 'https://monitoring.react-scan.com/api/v1/ingest'; Store.monitor.value ??= { pendingRequests: 0, + interactions: [], + session: getSession({ commit, branch }).catch(() => null), url, apiKey, - interactions: [], - session: getSession().catch(() => null), route, - path, + commit, + branch, }; - Store.monitor.value.route = route; - Store.monitor.value.path = path; + + // When using Monitoring without framework, we need to compute the route from the path and params + if (!route && path && params) { + Store.monitor.value.route = computeRoute(path, params); + } else { + Store.monitor.value.route = + route ?? path ?? new URL(window.location.toString()).pathname; // this is inaccurate on vanilla react if the path is not provided but used for session route + } useEffect(() => { scanMonitoring({ diff --git a/packages/scan/src/core/monitor/network.ts b/packages/scan/src/core/monitor/network.ts index 693eb6f9..8c7ce5a2 100644 --- a/packages/scan/src/core/monitor/network.ts +++ b/packages/scan/src/core/monitor/network.ts @@ -6,19 +6,29 @@ import { MAX_PENDING_REQUESTS, } from './constants'; import { getSession } from './utils'; -import type { Interaction, IngestRequest, InternalInteraction } from './types'; - -const getInteractionId = (interaction: InternalInteraction) => - `${interaction.performanceEntry.type}::${interaction.componentPath}::${interaction.url}`; +import type { Interaction, IngestRequest, InternalInteraction, Component } from './types'; const INTERACTION_TIME_TILL_COMPLETED = 4000; -const splitInteractions = (interactions: Array) => { +export const flush = async (): Promise => { + const monitor = Store.monitor.value; + if ( + !monitor || + !navigator.onLine || + !monitor.url || + !monitor.interactions.length + ) { + return; + } const now = performance.now(); - const pendingInteractions: typeof interactions = []; - const completedInteractions: typeof interactions = []; - - interactions.forEach((interaction) => { + // We might trigger flush before the interaction is completed, + // so we need to split them into pending and completed by an arbitrary time. + const pendingInteractions = new Array(); + const completedInteractions = new Array(); + + const interactions = monitor.interactions; + for (let i = 0; i < interactions.length; i++) { + const interaction = interactions[i]; if ( now - interaction.performanceEntry.startTime <= INTERACTION_TIME_TILL_COMPLETED @@ -27,102 +37,63 @@ const splitInteractions = (interactions: Array) => { } else { completedInteractions.push(interaction); } - }); + } - return { pendingInteractions, completedInteractions }; -}; + // nothing to flush + if (!completedInteractions.length) return; -const aggregateComponents = (interactions: Array) => { - const aggregatedComponents: Array<{ - interactionId: string; - name: string; - renders: number; - instances: number; - totalTime?: number; - selfTime?: number; - }> = []; - - for (const interaction of interactions) { - for (const [name, component] of Array.from( - interaction.components.entries(), - )) { + // idempotent + const session = await getSession({ + commit: monitor.commit, + branch: monitor.branch, + }).catch(() => null); + + if (!session) return; + + const aggregatedComponents = new Array(); + const aggregatedInteractions = new Array(); + for (let i = 0; i < completedInteractions.length; i++) { + const interaction = completedInteractions[i]; + + aggregatedInteractions.push({ + id: i, + path: interaction.componentPath, + name: interaction.componentName, + time: interaction.performanceEntry.duration, + timestamp: interaction.performanceEntry.timestamp, + type: interaction.performanceEntry.type, + url: interaction.url, + route: interaction.route, + commit: interaction.commit, + branch: interaction.branch, + uniqueInteractionId: interaction.uniqueInteractionId, + }); + + const components = Array.from(interaction.components.entries()); + for (let j = 0; j < components.length; j++) { + const [name, component] = components[j]; aggregatedComponents.push({ name, instances: component.fibers.size, - interactionId: getInteractionId(interaction), + interactionId: i, renders: component.renders, totalTime: component.totalTime, }); - - if (component.retiresAllowed === 0) { - // otherwise there will be a memory leak if the user loses internet or our server goes down - // we decide to skip the collection if this is the case - interaction.components.delete(name); - } - - component.retiresAllowed -= 1; } } - return aggregatedComponents; -}; - -const toPayloadInteraction = (interactions: Array) => - interactions.map( - (interaction) => - ({ - id: getInteractionId(interaction), - name: interaction.componentName, - time: interaction.performanceEntry.duration, - timestamp: interaction.performanceEntry.timestamp, - type: interaction.performanceEntry.type, - route: interaction.route, - url: interaction.url, - uniqueInteractionId: interaction.uniqueInteractionId, - }) satisfies Interaction, - ); - -export const flush = async (): Promise => { - const monitor = Store.monitor.value; - if ( - !monitor || - !navigator.onLine || - !monitor.url || - !monitor.interactions.length - ) { - return; - } - const { completedInteractions, pendingInteractions } = splitInteractions( - monitor.interactions, - ); - - // nothing to flush - if (!completedInteractions.length) { - return; - } - // idempotent - const session = await getSession().catch(() => null); - - if (!session) return; - - const aggregatedComponents = aggregateComponents(monitor.interactions); const payload: IngestRequest = { - interactions: toPayloadInteraction(completedInteractions), + interactions: aggregatedInteractions, components: aggregatedComponents, session: { ...session, + url: window.location.toString(), + route: monitor.route, // this might be inaccurate but used to caculate which paths all the unique sessions are coming from without having to join on the interactions table (expensive) }, }; monitor.pendingRequests++; - // remove all completed interactions from batch - monitor.interactions = monitor.interactions.filter((interaction) => - completedInteractions.some( - (completedInteraction) => - completedInteraction.performanceEntry.id !== - interaction.performanceEntry.id, - ), - ); + monitor.interactions = pendingInteractions; try { transport(monitor.url, payload) .then(() => { diff --git a/packages/scan/src/core/monitor/params/astro/Monitoring.astro b/packages/scan/src/core/monitor/params/astro/Monitoring.astro index cbde58e9..8e77c352 100644 --- a/packages/scan/src/core/monitor/params/astro/Monitoring.astro +++ b/packages/scan/src/core/monitor/params/astro/Monitoring.astro @@ -9,8 +9,8 @@ interface Props { const { apiKey, url } = Astro.props; -const pathname = Astro.url.pathname; +const path = Astro.url.pathname; const params = Astro.params; --- - + diff --git a/packages/scan/src/core/monitor/params/astro/component.ts b/packages/scan/src/core/monitor/params/astro/component.ts index 8d0a0ed4..d37b578f 100644 --- a/packages/scan/src/core/monitor/params/astro/component.ts +++ b/packages/scan/src/core/monitor/params/astro/component.ts @@ -1,14 +1,14 @@ import { createElement } from 'react'; -import { Monitoring as BaseMonitoring } from '../..'; +import { Monitoring as BaseMonitoring, type MonitoringWithoutRouteProps } from '../..'; import { computeRoute } from '../utils'; export function AstroMonitor(props: { url?: string; apiKey: string; - pathname: string; + path: string; params: Record; -}) { - const path = props.pathname; +} & MonitoringWithoutRouteProps) { + const path = props.path; const route = computeRoute(path, props.params); return createElement(BaseMonitoring, { diff --git a/packages/scan/src/core/monitor/params/next.ts b/packages/scan/src/core/monitor/params/next.ts index 6288fc81..510b039d 100644 --- a/packages/scan/src/core/monitor/params/next.ts +++ b/packages/scan/src/core/monitor/params/next.ts @@ -2,7 +2,7 @@ import { useParams, usePathname, useSearchParams } from 'next/navigation.js'; import { createElement, Suspense } from 'react'; -import { Monitoring as BaseMonitoring } from '..'; +import { Monitoring as BaseMonitoring, type MonitoringWithoutRouteProps } from '..'; import { computeRoute } from './utils'; /** @@ -29,7 +29,7 @@ const useRoute = (): { : Object.fromEntries(searchParams.entries()); return { route: computeRoute(path, finalParams), path }; }; -export function MonitoringInner(props: { url?: string; apiKey: string }) { +export function MonitoringInner(props: MonitoringWithoutRouteProps) { const { route, path } = useRoute(); // we need to fix build so this doesn't get compiled to preact jsx diff --git a/packages/scan/src/core/monitor/params/react-router-v5.ts b/packages/scan/src/core/monitor/params/react-router-v5.ts index 70e2f167..71b81206 100644 --- a/packages/scan/src/core/monitor/params/react-router-v5.ts +++ b/packages/scan/src/core/monitor/params/react-router-v5.ts @@ -1,6 +1,6 @@ import { createElement } from 'react'; import { useRouteMatch, useLocation } from 'react-router'; -import { Monitoring as BaseMonitoring} from '..'; +import { Monitoring as BaseMonitoring, type MonitoringWithoutRouteProps} from '..'; import { computeRoute } from './utils'; import type { RouteInfo } from './types'; @@ -19,7 +19,7 @@ const useRoute = (): RouteInfo => { }; }; -function ReactRouterV5Monitor(props: { url?: string; apiKey: string }) { +function ReactRouterV5Monitor(props: MonitoringWithoutRouteProps) { const { route, path } = useRoute(); return createElement(BaseMonitoring, { ...props, diff --git a/packages/scan/src/core/monitor/params/react-router-v6.ts b/packages/scan/src/core/monitor/params/react-router-v6.ts index 2be9c05a..d62f12f1 100644 --- a/packages/scan/src/core/monitor/params/react-router-v6.ts +++ b/packages/scan/src/core/monitor/params/react-router-v6.ts @@ -1,6 +1,6 @@ import { createElement } from 'react'; import { useParams, useLocation } from 'react-router'; -import { Monitoring as BaseMonitoring } from '..'; +import { Monitoring as BaseMonitoring, type MonitoringWithoutRouteProps } from '..'; import { computeReactRouterRoute } from './utils'; import type { RouteInfo } from './types'; @@ -22,7 +22,7 @@ const useRoute = (): RouteInfo => { }; }; -function ReactRouterMonitor(props: { url?: string; apiKey: string }) { +function ReactRouterMonitor(props: MonitoringWithoutRouteProps) { const { route, path } = useRoute(); return createElement(BaseMonitoring, { ...props, diff --git a/packages/scan/src/core/monitor/params/remix.ts b/packages/scan/src/core/monitor/params/remix.ts index 6b0e55f7..e9ff727a 100644 --- a/packages/scan/src/core/monitor/params/remix.ts +++ b/packages/scan/src/core/monitor/params/remix.ts @@ -1,6 +1,6 @@ import { createElement } from 'react'; import { useParams, useLocation } from '@remix-run/react'; -import { Monitoring as BaseMonitoring} from '..'; +import { Monitoring as BaseMonitoring, type MonitoringWithoutRouteProps} from '..'; import { computeReactRouterRoute } from './utils'; import type { RouteInfo } from './types'; @@ -20,7 +20,7 @@ const useRoute = (): RouteInfo => { }; }; -function RemixMonitor(props: { url?: string; apiKey: string }) { +function RemixMonitor(props: MonitoringWithoutRouteProps) { const { route, path } = useRoute(); return createElement(BaseMonitoring, { ...props, diff --git a/packages/scan/src/core/monitor/performance.ts b/packages/scan/src/core/monitor/performance.ts index 6d901b54..548e106e 100644 --- a/packages/scan/src/core/monitor/performance.ts +++ b/packages/scan/src/core/monitor/performance.ts @@ -97,8 +97,8 @@ const isMinified = (name: string): boolean => { export function getInteractionPath( fiber: Fiber | null, filters: PathFilters = DEFAULT_FILTERS, -): string { - if (!fiber) return ''; +): Array { + if (!fiber) return []; const fullPath: Array = []; @@ -118,8 +118,7 @@ export function getInteractionPath( current = current.return; } - const normalized = normalizePath(fullPath); - return normalized; + return fullPath; } let currentMouseOver: Element; @@ -131,7 +130,7 @@ function getCleanComponentName(component: any): string { return name.replace(/^(?:Memo|Forward(?:Ref)?|With.*?)\((?.*?)\)$/, '$'); } -function normalizePath(path: Array): string { +export function normalizePath(path: Array): string { const cleaned = path.filter(Boolean); const deduped = cleaned.filter((name, i) => name !== cleaned[i - 1]); @@ -194,8 +193,11 @@ export function initPerformanceMonitoring(options?: Partial) { componentPath: path, performanceEntry: entry, components: new Map(), - route: Store.monitor.value?.route ?? null, url: window.location.toString(), + route: + Store.monitor.value?.route ?? new URL(window.location.href).pathname, + commit: Store.monitor.value?.commit ?? null, + branch: Store.monitor.value?.branch ?? null, uniqueInteractionId: entry.id, }); }); diff --git a/packages/scan/src/core/monitor/types.ts b/packages/scan/src/core/monitor/types.ts index 52d82f16..a95622d4 100644 --- a/packages/scan/src/core/monitor/types.ts +++ b/packages/scan/src/core/monitor/types.ts @@ -15,16 +15,26 @@ export interface Session { cpu: number; gpu: string | null; mem: number; + url: string; + route: string | null; + commit: string | null; + branch: string | null; } export interface Interaction { - id: string; // a hashed unique id for interaction (groupable across sessions) - name: string; // name of interaction (i.e nav#top-menu.sc-601d0142-19.gHiJkL) or something useful + id: string | number; // index of the interaction in the batch at ingest | server converts to a hashed string from route, type, name, path + path: Array; // the path of the interaction + name: string; // name of interaction type: string; // type of interaction i.e pointer time: number; // time of interaction in ms timestamp: number; - route: string | null; // the computed route that handles dynamic params url: string; + route: string | null; // the computed route that handles dynamic params + + // Regression tracking + commit: string | null; + branch: string | null; + // clickhouse + ingest specific types projectId?: string; sessionId?: string; @@ -32,7 +42,7 @@ export interface Interaction { } export interface Component { - interactionId: string; // grouping components by interaction + interactionId: string | number; // grouping components by interaction name: string; renders: number; // how many times it re-rendered / instances (normalized) instances: number; // instances which will be used to get number of total renders by * by renders @@ -51,8 +61,10 @@ export interface InternalInteraction { componentName: string; url: string; route: string | null; + commit: string | null; + branch: string | null; uniqueInteractionId: string; - componentPath: string; + componentPath: Array; performanceEntry: PerformanceInteraction; components: Map; } diff --git a/packages/scan/src/core/monitor/utils.ts b/packages/scan/src/core/monitor/utils.ts index edb31efc..8b9d8a7c 100644 --- a/packages/scan/src/core/monitor/utils.ts +++ b/packages/scan/src/core/monitor/utils.ts @@ -61,7 +61,13 @@ const getGpuRenderer = () => { * DO NOT CALL THIS EVERYTIME */ let cachedSession: Session; -export const getSession = async () => { +export const getSession = async ({ + commit = null, + branch = null, +}: { + commit?: string | null; + branch?: string | null; +}) => { if (isSSR) return null; if (cachedSession) { return cachedSession; @@ -102,12 +108,16 @@ export const getSession = async () => { const session = { id, url, + route: null, device: getDeviceType(), wifi, cpu, mem, gpu: await gpuRendererPromise, agent: navigator.userAgent, + commit, + branch, + version: process.env.NPM_PACKAGE_VERSION, }; cachedSession = session; return session; diff --git a/packages/scan/src/core/web/inspect-element/view-state.ts b/packages/scan/src/core/web/inspect-element/view-state.ts index 4a40397c..eaba2f5b 100644 --- a/packages/scan/src/core/web/inspect-element/view-state.ts +++ b/packages/scan/src/core/web/inspect-element/view-state.ts @@ -588,6 +588,9 @@ export const getValuePreview = (value: any) => { case 'boolean': return value.toString(); case 'object': { + if (value instanceof Promise) { + return 'Promise'; + } const keys = Object.keys(value); if (keys.length <= 3) { return `{${keys.join(', ')}}`; diff --git a/packages/scan/tsup.config.ts b/packages/scan/tsup.config.ts index 2abfcd12..c571005f 100644 --- a/packages/scan/tsup.config.ts +++ b/packages/scan/tsup.config.ts @@ -1,4 +1,5 @@ -import fs from 'node:fs/promises'; +import fsPromise from 'node:fs/promises'; +import * as fs from 'node:fs'; import path from 'node:path'; import { defineConfig } from 'tsup'; import { TsconfigPathsPlugin } from '@esbuild-plugins/tsconfig-paths'; @@ -7,16 +8,16 @@ const DIST_PATH = './dist'; const addDirectivesToChunkFiles = async (readPath: string): Promise => { try { - const files = await fs.readdir(readPath); + const files = await fsPromise.readdir(readPath); for (const file of files) { if (file.endsWith('.mjs') || file.endsWith('.js')) { const filePath = path.join(readPath, file); - const data = await fs.readFile(filePath, 'utf8'); + const data = await fsPromise.readFile(filePath, 'utf8'); const updatedContent = `'use client';\n${data}`; - await fs.writeFile(filePath, updatedContent, 'utf8'); + await fsPromise.writeFile(filePath, updatedContent, 'utf8'); // eslint-disable-next-line no-console console.log(`Directive has been added to ${file}`); @@ -28,10 +29,32 @@ const addDirectivesToChunkFiles = async (readPath: string): Promise => { } }; +const banner = `/** + * Copyright 2024 Aiden Bai, Million Software, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the “Software”), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */`; + export default defineConfig([ { entry: ['./src/auto.ts'], outDir: DIST_PATH, + banner: { + js: banner, + }, splitting: false, clean: false, sourcemap: false, @@ -69,6 +92,9 @@ export default defineConfig([ './src/core/monitor/params/remix.ts', './src/core/monitor/params/astro/component.ts', ], + banner: { + js: banner, + }, outDir: DIST_PATH, splitting: false, clean: true, @@ -89,6 +115,11 @@ export default defineConfig([ minify: process.env.NODE_ENV === 'production', env: { NODE_ENV: process.env.NODE_ENV ?? 'development', + NPM_PACKAGE_VERSION: JSON.parse(fs.readFileSync( + path.join(__dirname, '../scan', 'package.json'), + 'utf8', + ), + ).version, }, external: [ 'react', @@ -112,6 +143,9 @@ export default defineConfig([ { entry: ['./src/cli.mts'], outDir: DIST_PATH, + banner: { + js: banner, + }, splitting: false, clean: true, sourcemap: false, diff --git a/packages/website/package.json b/packages/website/package.json index 382ad719..6f0bf372 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -5,6 +5,7 @@ "scripts": { "dev": "next dev --turbopack", "build": "next build", + "postbuild": "node ../../scripts/version-warning.mjs", "start": "next start", "lint": "next lint" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 65d9d06a..61532358 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -24,6 +24,12 @@ importers: '@vercel/style-guide': specifier: ^6.0.0 version: 6.0.0(eslint@8.57.1)(prettier@3.3.3)(typescript@5.4.5)(vitest@1.0.0(@types/node@22.10.2)(terser@5.36.0)) + boxen: + specifier: ^8.0.1 + version: 8.0.1 + chalk: + specifier: ^5.3.0 + version: 5.3.0 eslint: specifier: ^8.57.1 version: 8.57.1 @@ -140,9 +146,15 @@ importers: '@rollup/pluginutils': specifier: ^5.1.3 version: 5.1.3(rollup@4.28.0) + '@types/node': + specifier: ^20.17.9 + version: 20.17.10 bippy: - specifier: ^0.0.10 - version: 0.0.10 + specifier: ^0.0.14 + version: 0.0.14 + esbuild: + specifier: ^0.24.0 + version: 0.24.0 estree-walker: specifier: ^3.0.3 version: 3.0.3 @@ -168,7 +180,7 @@ importers: devDependencies: '@esbuild-plugins/tsconfig-paths': specifier: ^0.1.2 - version: 0.1.2(esbuild@0.23.1)(typescript@5.6.3) + version: 0.1.2(esbuild@0.24.0)(typescript@5.6.3) '@remix-run/react': specifier: '*' version: 2.15.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.6.3) @@ -234,7 +246,7 @@ importers: version: 8.2.4(jiti@1.21.6)(postcss@8.4.49)(tsx@4.0.0)(typescript@5.6.3)(yaml@2.6.1) vitest: specifier: ^1.0.0 - version: 1.0.0(@types/node@22.10.2)(terser@5.36.0) + version: 1.0.0(@types/node@20.17.10)(terser@5.36.0) packages/website: dependencies: @@ -254,8 +266,8 @@ importers: specifier: 19.0.0-rc-66855b96-20241106 version: 19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106) react-scan: - specifier: ^0.0.35 - version: 0.0.35 + specifier: ^0.0.42 + version: 0.0.42(@remix-run/react@2.15.0(react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106))(react@19.0.0-rc-66855b96-20241106)(typescript@5.6.3))(next@15.0.3(@babel/core@7.26.0)(react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106))(react@19.0.0-rc-66855b96-20241106))(react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106))(react-router-dom@6.28.0(react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106))(react@19.0.0-rc-66855b96-20241106))(react-router@6.28.0(react@19.0.0-rc-66855b96-20241106))(react@19.0.0-rc-66855b96-20241106)(rollup@4.28.0) zod: specifier: ^3.23.8 version: 3.23.8 @@ -422,6 +434,12 @@ packages: cpu: [ppc64] os: [aix] + '@esbuild/aix-ppc64@0.24.0': + resolution: {integrity: sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + '@esbuild/android-arm64@0.18.20': resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} engines: {node: '>=12'} @@ -440,6 +458,12 @@ packages: cpu: [arm64] os: [android] + '@esbuild/android-arm64@0.24.0': + resolution: {integrity: sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm@0.18.20': resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} engines: {node: '>=12'} @@ -458,6 +482,12 @@ packages: cpu: [arm] os: [android] + '@esbuild/android-arm@0.24.0': + resolution: {integrity: sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + '@esbuild/android-x64@0.18.20': resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} engines: {node: '>=12'} @@ -476,6 +506,12 @@ packages: cpu: [x64] os: [android] + '@esbuild/android-x64@0.24.0': + resolution: {integrity: sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + '@esbuild/darwin-arm64@0.18.20': resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} engines: {node: '>=12'} @@ -494,6 +530,12 @@ packages: cpu: [arm64] os: [darwin] + '@esbuild/darwin-arm64@0.24.0': + resolution: {integrity: sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-x64@0.18.20': resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} engines: {node: '>=12'} @@ -512,6 +554,12 @@ packages: cpu: [x64] os: [darwin] + '@esbuild/darwin-x64@0.24.0': + resolution: {integrity: sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + '@esbuild/freebsd-arm64@0.18.20': resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} engines: {node: '>=12'} @@ -530,6 +578,12 @@ packages: cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-arm64@0.24.0': + resolution: {integrity: sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-x64@0.18.20': resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} engines: {node: '>=12'} @@ -548,6 +602,12 @@ packages: cpu: [x64] os: [freebsd] + '@esbuild/freebsd-x64@0.24.0': + resolution: {integrity: sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + '@esbuild/linux-arm64@0.18.20': resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} engines: {node: '>=12'} @@ -566,6 +626,12 @@ packages: cpu: [arm64] os: [linux] + '@esbuild/linux-arm64@0.24.0': + resolution: {integrity: sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm@0.18.20': resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} engines: {node: '>=12'} @@ -584,6 +650,12 @@ packages: cpu: [arm] os: [linux] + '@esbuild/linux-arm@0.24.0': + resolution: {integrity: sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + '@esbuild/linux-ia32@0.18.20': resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} engines: {node: '>=12'} @@ -602,6 +674,12 @@ packages: cpu: [ia32] os: [linux] + '@esbuild/linux-ia32@0.24.0': + resolution: {integrity: sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-loong64@0.18.20': resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} engines: {node: '>=12'} @@ -620,6 +698,12 @@ packages: cpu: [loong64] os: [linux] + '@esbuild/linux-loong64@0.24.0': + resolution: {integrity: sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-mips64el@0.18.20': resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} engines: {node: '>=12'} @@ -638,6 +722,12 @@ packages: cpu: [mips64el] os: [linux] + '@esbuild/linux-mips64el@0.24.0': + resolution: {integrity: sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-ppc64@0.18.20': resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} engines: {node: '>=12'} @@ -656,6 +746,12 @@ packages: cpu: [ppc64] os: [linux] + '@esbuild/linux-ppc64@0.24.0': + resolution: {integrity: sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-riscv64@0.18.20': resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} engines: {node: '>=12'} @@ -674,6 +770,12 @@ packages: cpu: [riscv64] os: [linux] + '@esbuild/linux-riscv64@0.24.0': + resolution: {integrity: sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-s390x@0.18.20': resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} engines: {node: '>=12'} @@ -692,6 +794,12 @@ packages: cpu: [s390x] os: [linux] + '@esbuild/linux-s390x@0.24.0': + resolution: {integrity: sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-x64@0.18.20': resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} engines: {node: '>=12'} @@ -710,6 +818,12 @@ packages: cpu: [x64] os: [linux] + '@esbuild/linux-x64@0.24.0': + resolution: {integrity: sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + '@esbuild/netbsd-x64@0.18.20': resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} engines: {node: '>=12'} @@ -728,12 +842,24 @@ packages: cpu: [x64] os: [netbsd] + '@esbuild/netbsd-x64@0.24.0': + resolution: {integrity: sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + '@esbuild/openbsd-arm64@0.23.1': resolution: {integrity: sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] + '@esbuild/openbsd-arm64@0.24.0': + resolution: {integrity: sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + '@esbuild/openbsd-x64@0.18.20': resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} engines: {node: '>=12'} @@ -752,6 +878,12 @@ packages: cpu: [x64] os: [openbsd] + '@esbuild/openbsd-x64@0.24.0': + resolution: {integrity: sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + '@esbuild/sunos-x64@0.18.20': resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==} engines: {node: '>=12'} @@ -770,6 +902,12 @@ packages: cpu: [x64] os: [sunos] + '@esbuild/sunos-x64@0.24.0': + resolution: {integrity: sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + '@esbuild/win32-arm64@0.18.20': resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} engines: {node: '>=12'} @@ -788,6 +926,12 @@ packages: cpu: [arm64] os: [win32] + '@esbuild/win32-arm64@0.24.0': + resolution: {integrity: sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-ia32@0.18.20': resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} engines: {node: '>=12'} @@ -806,6 +950,12 @@ packages: cpu: [ia32] os: [win32] + '@esbuild/win32-ia32@0.24.0': + resolution: {integrity: sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-x64@0.18.20': resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} engines: {node: '>=12'} @@ -824,6 +974,12 @@ packages: cpu: [x64] os: [win32] + '@esbuild/win32-x64@0.24.0': + resolution: {integrity: sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@eslint-community/eslint-utils@4.4.1': resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1290,6 +1446,9 @@ packages: '@types/minimatch@3.0.5': resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==} + '@types/node@20.17.10': + resolution: {integrity: sha512-/jrvh5h6NXhEauFFexRin69nA0uHJ5gwk4iDivp/DeoEua3uwCUto6PC86IpRITBOs4+6i2I56K5x5b6WYGXHA==} + '@types/node@22.10.2': resolution: {integrity: sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==} @@ -1734,6 +1893,9 @@ packages: bippy@0.0.10: resolution: {integrity: sha512-2E8U2h/3ZltRwxfVkT1c2DqWUjgIGFRg8cD1qQDJ0m7YOJCpxqI87s+vaaEzvIxRw4MJOUVJ3OZ6K904UNX+iw==} + bippy@0.0.14: + resolution: {integrity: sha512-flYbctf6HUYYkaXci8669fU25b9gIrBFbXWt//2M5PSJeGVziwKGKZYs+3FaJnXIx0TQ1qKYLB1nBQf2PWbkLA==} + bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} @@ -1747,6 +1909,10 @@ packages: resolution: {integrity: sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==} engines: {node: '>=14.16'} + boxen@8.0.1: + resolution: {integrity: sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==} + engines: {node: '>=18'} + brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} @@ -1822,6 +1988,10 @@ packages: resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==} engines: {node: '>=14.16'} + camelcase@8.0.0: + resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==} + engines: {node: '>=16'} + caniuse-lite@1.0.30001684: resolution: {integrity: sha512-G1LRwLIQjBQoyq0ZJGqGIJUXzJ8irpbjHLpVRXDvBEScFJ9b17sgK6vlx0GAJFE21okD7zXl08rRRUfq6HdoEQ==} @@ -2145,6 +2315,9 @@ packages: electron-to-chromium@1.5.67: resolution: {integrity: sha512-nz88NNBsD7kQSAGGJyp8hS6xSPtWwqNogA0mjtc2nUYeEf3nURK9qpV18TuBdDmEDgVWotS8Wkzf+V52dSQ/LQ==} + emoji-regex@10.4.0: + resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} + emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -2217,6 +2390,11 @@ packages: engines: {node: '>=18'} hasBin: true + esbuild@0.24.0: + resolution: {integrity: sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==} + engines: {node: '>=18'} + hasBin: true + escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} @@ -2606,6 +2784,10 @@ packages: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} + get-east-asian-width@1.3.0: + resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==} + engines: {node: '>=18'} + get-func-name@2.0.2: resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} @@ -3816,9 +3998,25 @@ packages: resolution: {integrity: sha512-sB1h7z0Y3sufhcTg6XNmIu4Wq2pQRK2Jk7/1NDPzxVKzFFcRwpjDqtiZP1C/8V8xPPQIiAaGsP6QNNVsQ3VLbg==} hasBin: true - react-scan@0.0.35: - resolution: {integrity: sha512-1ZrSO4prPDDiJg6/ZauxlYMaCFsxo6KrV9fBOVJ5aGkwXw3EyBCzfQpYzIzkwE19iE9Nw3mWd8uEiWupAwDP1w==} + react-scan@0.0.42: + resolution: {integrity: sha512-uERtHi9n11kwy5gD6bXZtVw2JBaf/TVdVKJcIo33IUI3d+bXecwFwDBTMkvcYrMkJBADwbV30ug9gqf1VBid8Q==} hasBin: true + peerDependencies: + '@remix-run/react': '>=1.0.0' + next: '>=13.0.0' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-router: ^5.0.0 || ^6.0.0 + react-router-dom: ^5.0.0 || ^6.0.0 + peerDependenciesMeta: + '@remix-run/react': + optional: true + next: + optional: true + react-router: + optional: true + react-router-dom: + optional: true react@18.2.0: resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} @@ -4138,6 +4336,10 @@ packages: resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} engines: {node: '>=12'} + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} + string.prototype.includes@2.0.1: resolution: {integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==} engines: {node: '>= 0.4'} @@ -4408,6 +4610,10 @@ packages: resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==} engines: {node: '>=14.16'} + type-fest@4.30.0: + resolution: {integrity: sha512-G6zXWS1dLj6eagy6sVhOMQiLtJdxQBHIA9Z6HFUNLOlr6MFOgzV8wvmidtPONfPtEUv0uZsy77XJNzTAfwPDaA==} + engines: {node: '>=16'} + typed-array-buffer@1.0.2: resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==} engines: {node: '>= 0.4'} @@ -4449,6 +4655,9 @@ packages: unbox-primitive@1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + undici-types@6.19.8: + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + undici-types@6.20.0: resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} @@ -4464,6 +4673,10 @@ packages: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} + unplugin@2.0.0-beta.2: + resolution: {integrity: sha512-gWIFAjTFKFsHI9xSWQGhhoLkAqMoG/JzVZ0T4W0VeC02kitb8zIdiTjUBJXX5tCt0bdfr/0cJaOf2S7ujuVqtw==} + engines: {node: '>=18.12.0'} + unplugin@2.1.0: resolution: {integrity: sha512-us4j03/499KhbGP8BU7Hrzrgseo+KdfJYWcbcajCOqsAyb8Gk0Yn2kiUIcZISYCb1JFaZfIuG3b42HmguVOKCQ==} engines: {node: '>=18.12.0'} @@ -4629,6 +4842,10 @@ packages: resolution: {integrity: sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==} engines: {node: '>=12'} + widest-line@5.0.0: + resolution: {integrity: sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==} + engines: {node: '>=18'} + winreg@0.0.12: resolution: {integrity: sha512-typ/+JRmi7RqP1NanzFULK36vczznSNN8kWVA9vIqXyv8GhghUlwhGp1Xj3Nms1FsPcNnsQrJOR10N58/nQ9hQ==} @@ -4644,6 +4861,10 @@ packages: resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} engines: {node: '>=12'} + wrap-ansi@9.0.0: + resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} + engines: {node: '>=18'} + wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} @@ -4877,10 +5098,10 @@ snapshots: tslib: 2.8.1 optional: true - '@esbuild-plugins/tsconfig-paths@0.1.2(esbuild@0.23.1)(typescript@5.6.3)': + '@esbuild-plugins/tsconfig-paths@0.1.2(esbuild@0.24.0)(typescript@5.6.3)': dependencies: debug: 4.3.7 - esbuild: 0.23.1 + esbuild: 0.24.0 find-up: 5.0.0 strip-json-comments: 3.1.1 typescript: 5.6.3 @@ -4893,6 +5114,9 @@ snapshots: '@esbuild/aix-ppc64@0.23.1': optional: true + '@esbuild/aix-ppc64@0.24.0': + optional: true + '@esbuild/android-arm64@0.18.20': optional: true @@ -4902,6 +5126,9 @@ snapshots: '@esbuild/android-arm64@0.23.1': optional: true + '@esbuild/android-arm64@0.24.0': + optional: true + '@esbuild/android-arm@0.18.20': optional: true @@ -4911,6 +5138,9 @@ snapshots: '@esbuild/android-arm@0.23.1': optional: true + '@esbuild/android-arm@0.24.0': + optional: true + '@esbuild/android-x64@0.18.20': optional: true @@ -4920,6 +5150,9 @@ snapshots: '@esbuild/android-x64@0.23.1': optional: true + '@esbuild/android-x64@0.24.0': + optional: true + '@esbuild/darwin-arm64@0.18.20': optional: true @@ -4929,6 +5162,9 @@ snapshots: '@esbuild/darwin-arm64@0.23.1': optional: true + '@esbuild/darwin-arm64@0.24.0': + optional: true + '@esbuild/darwin-x64@0.18.20': optional: true @@ -4938,6 +5174,9 @@ snapshots: '@esbuild/darwin-x64@0.23.1': optional: true + '@esbuild/darwin-x64@0.24.0': + optional: true + '@esbuild/freebsd-arm64@0.18.20': optional: true @@ -4947,6 +5186,9 @@ snapshots: '@esbuild/freebsd-arm64@0.23.1': optional: true + '@esbuild/freebsd-arm64@0.24.0': + optional: true + '@esbuild/freebsd-x64@0.18.20': optional: true @@ -4956,6 +5198,9 @@ snapshots: '@esbuild/freebsd-x64@0.23.1': optional: true + '@esbuild/freebsd-x64@0.24.0': + optional: true + '@esbuild/linux-arm64@0.18.20': optional: true @@ -4965,6 +5210,9 @@ snapshots: '@esbuild/linux-arm64@0.23.1': optional: true + '@esbuild/linux-arm64@0.24.0': + optional: true + '@esbuild/linux-arm@0.18.20': optional: true @@ -4974,6 +5222,9 @@ snapshots: '@esbuild/linux-arm@0.23.1': optional: true + '@esbuild/linux-arm@0.24.0': + optional: true + '@esbuild/linux-ia32@0.18.20': optional: true @@ -4983,6 +5234,9 @@ snapshots: '@esbuild/linux-ia32@0.23.1': optional: true + '@esbuild/linux-ia32@0.24.0': + optional: true + '@esbuild/linux-loong64@0.18.20': optional: true @@ -4992,6 +5246,9 @@ snapshots: '@esbuild/linux-loong64@0.23.1': optional: true + '@esbuild/linux-loong64@0.24.0': + optional: true + '@esbuild/linux-mips64el@0.18.20': optional: true @@ -5001,6 +5258,9 @@ snapshots: '@esbuild/linux-mips64el@0.23.1': optional: true + '@esbuild/linux-mips64el@0.24.0': + optional: true + '@esbuild/linux-ppc64@0.18.20': optional: true @@ -5010,6 +5270,9 @@ snapshots: '@esbuild/linux-ppc64@0.23.1': optional: true + '@esbuild/linux-ppc64@0.24.0': + optional: true + '@esbuild/linux-riscv64@0.18.20': optional: true @@ -5019,6 +5282,9 @@ snapshots: '@esbuild/linux-riscv64@0.23.1': optional: true + '@esbuild/linux-riscv64@0.24.0': + optional: true + '@esbuild/linux-s390x@0.18.20': optional: true @@ -5028,6 +5294,9 @@ snapshots: '@esbuild/linux-s390x@0.23.1': optional: true + '@esbuild/linux-s390x@0.24.0': + optional: true + '@esbuild/linux-x64@0.18.20': optional: true @@ -5037,6 +5306,9 @@ snapshots: '@esbuild/linux-x64@0.23.1': optional: true + '@esbuild/linux-x64@0.24.0': + optional: true + '@esbuild/netbsd-x64@0.18.20': optional: true @@ -5046,9 +5318,15 @@ snapshots: '@esbuild/netbsd-x64@0.23.1': optional: true + '@esbuild/netbsd-x64@0.24.0': + optional: true + '@esbuild/openbsd-arm64@0.23.1': optional: true + '@esbuild/openbsd-arm64@0.24.0': + optional: true + '@esbuild/openbsd-x64@0.18.20': optional: true @@ -5058,6 +5336,9 @@ snapshots: '@esbuild/openbsd-x64@0.23.1': optional: true + '@esbuild/openbsd-x64@0.24.0': + optional: true + '@esbuild/sunos-x64@0.18.20': optional: true @@ -5067,6 +5348,9 @@ snapshots: '@esbuild/sunos-x64@0.23.1': optional: true + '@esbuild/sunos-x64@0.24.0': + optional: true + '@esbuild/win32-arm64@0.18.20': optional: true @@ -5076,6 +5360,9 @@ snapshots: '@esbuild/win32-arm64@0.23.1': optional: true + '@esbuild/win32-arm64@0.24.0': + optional: true + '@esbuild/win32-ia32@0.18.20': optional: true @@ -5085,6 +5372,9 @@ snapshots: '@esbuild/win32-ia32@0.23.1': optional: true + '@esbuild/win32-ia32@0.24.0': + optional: true + '@esbuild/win32-x64@0.18.20': optional: true @@ -5094,6 +5384,9 @@ snapshots: '@esbuild/win32-x64@0.23.1': optional: true + '@esbuild/win32-x64@0.24.0': + optional: true + '@eslint-community/eslint-utils@4.4.1(eslint@8.57.1)': dependencies: eslint: 8.57.1 @@ -5502,6 +5795,10 @@ snapshots: '@types/minimatch@3.0.5': {} + '@types/node@20.17.10': + dependencies: + undici-types: 6.19.8 + '@types/node@22.10.2': dependencies: undici-types: 6.20.0 @@ -6125,6 +6422,8 @@ snapshots: bippy@0.0.10: {} + bippy@0.0.14: {} + bl@4.1.0: dependencies: buffer: 5.7.1 @@ -6146,6 +6445,17 @@ snapshots: widest-line: 4.0.1 wrap-ansi: 8.1.0 + boxen@8.0.1: + dependencies: + ansi-align: 3.0.1 + camelcase: 8.0.0 + chalk: 5.3.0 + cli-boxes: 3.0.0 + string-width: 7.2.0 + type-fest: 4.30.0 + widest-line: 5.0.0 + wrap-ansi: 9.0.0 + brace-expansion@1.1.11: dependencies: balanced-match: 1.0.2 @@ -6225,6 +6535,8 @@ snapshots: camelcase@7.0.1: {} + camelcase@8.0.0: {} + caniuse-lite@1.0.30001684: {} chai@4.5.0: @@ -6546,6 +6858,8 @@ snapshots: electron-to-chromium@1.5.67: {} + emoji-regex@10.4.0: {} + emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} @@ -6740,6 +7054,33 @@ snapshots: '@esbuild/win32-ia32': 0.23.1 '@esbuild/win32-x64': 0.23.1 + esbuild@0.24.0: + optionalDependencies: + '@esbuild/aix-ppc64': 0.24.0 + '@esbuild/android-arm': 0.24.0 + '@esbuild/android-arm64': 0.24.0 + '@esbuild/android-x64': 0.24.0 + '@esbuild/darwin-arm64': 0.24.0 + '@esbuild/darwin-x64': 0.24.0 + '@esbuild/freebsd-arm64': 0.24.0 + '@esbuild/freebsd-x64': 0.24.0 + '@esbuild/linux-arm': 0.24.0 + '@esbuild/linux-arm64': 0.24.0 + '@esbuild/linux-ia32': 0.24.0 + '@esbuild/linux-loong64': 0.24.0 + '@esbuild/linux-mips64el': 0.24.0 + '@esbuild/linux-ppc64': 0.24.0 + '@esbuild/linux-riscv64': 0.24.0 + '@esbuild/linux-s390x': 0.24.0 + '@esbuild/linux-x64': 0.24.0 + '@esbuild/netbsd-x64': 0.24.0 + '@esbuild/openbsd-arm64': 0.24.0 + '@esbuild/openbsd-x64': 0.24.0 + '@esbuild/sunos-x64': 0.24.0 + '@esbuild/win32-arm64': 0.24.0 + '@esbuild/win32-ia32': 0.24.0 + '@esbuild/win32-x64': 0.24.0 + escalade@3.2.0: {} escape-goat@4.0.0: {} @@ -7287,6 +7628,8 @@ snapshots: get-caller-file@2.0.5: {} + get-east-asian-width@1.3.0: {} + get-func-name@2.0.2: {} get-intrinsic@1.2.4: @@ -8515,13 +8858,34 @@ snapshots: mri: 1.2.0 playwright: 1.49.0 - react-scan@0.0.35: + react-scan@0.0.42(@remix-run/react@2.15.0(react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106))(react@19.0.0-rc-66855b96-20241106)(typescript@5.6.3))(next@15.0.3(@babel/core@7.26.0)(react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106))(react@19.0.0-rc-66855b96-20241106))(react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106))(react-router-dom@6.28.0(react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106))(react@19.0.0-rc-66855b96-20241106))(react-router@6.28.0(react@19.0.0-rc-66855b96-20241106))(react@19.0.0-rc-66855b96-20241106)(rollup@4.28.0): dependencies: + '@babel/core': 7.26.0 + '@babel/generator': 7.26.2 + '@babel/types': 7.26.0 '@clack/core': 0.3.5 '@clack/prompts': 0.8.2 + '@preact/signals': 1.3.1(preact@10.25.1) + '@rollup/pluginutils': 5.1.3(rollup@4.28.0) + '@types/node': 20.17.10 + bippy: 0.0.10 + estree-walker: 3.0.3 kleur: 4.1.5 mri: 1.2.0 playwright: 1.49.0 + preact: 10.25.1 + react: 19.0.0-rc-66855b96-20241106 + react-dom: 19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106) + tsx: 4.0.0 + unplugin: 2.0.0-beta.2 + optionalDependencies: + '@remix-run/react': 2.15.0(react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106))(react@19.0.0-rc-66855b96-20241106)(typescript@5.6.3) + next: 15.0.3(@babel/core@7.26.0)(react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106))(react@19.0.0-rc-66855b96-20241106) + react-router: 6.28.0(react@19.0.0-rc-66855b96-20241106) + react-router-dom: 6.28.0(react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106))(react@19.0.0-rc-66855b96-20241106) + transitivePeerDependencies: + - rollup + - supports-color react@18.2.0: dependencies: @@ -8896,6 +9260,12 @@ snapshots: emoji-regex: 9.2.2 strip-ansi: 7.1.0 + string-width@7.2.0: + dependencies: + emoji-regex: 10.4.0 + get-east-asian-width: 1.3.0 + strip-ansi: 7.1.0 + string.prototype.includes@2.0.1: dependencies: call-bind: 1.0.7 @@ -9203,6 +9573,8 @@ snapshots: type-fest@3.13.1: {} + type-fest@4.30.0: {} + typed-array-buffer@1.0.2: dependencies: call-bind: 1.0.7 @@ -9257,6 +9629,8 @@ snapshots: has-symbols: 1.0.3 which-boxed-primitive: 1.0.2 + undici-types@6.19.8: {} + undici-types@6.20.0: {} unique-string@3.0.0: @@ -9267,6 +9641,11 @@ snapshots: universalify@2.0.1: {} + unplugin@2.0.0-beta.2: + dependencies: + acorn: 8.14.0 + webpack-virtual-modules: 0.6.2 + unplugin@2.1.0: dependencies: acorn: 8.14.0 @@ -9311,6 +9690,24 @@ snapshots: value-equal@1.0.1: {} + vite-node@1.0.0(@types/node@20.17.10)(terser@5.36.0): + dependencies: + cac: 6.7.14 + debug: 4.3.7 + pathe: 1.1.2 + picocolors: 1.1.1 + vite: 5.4.3(@types/node@20.17.10)(terser@5.36.0) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + vite-node@1.0.0(@types/node@22.10.2)(terser@5.36.0): dependencies: cac: 6.7.14 @@ -9328,6 +9725,7 @@ snapshots: - sugarss - supports-color - terser + optional: true vite-plugin-inspect@0.8.7(rollup@4.28.0)(vite@5.4.3(@types/node@22.10.2)(terser@5.36.0)): dependencies: @@ -9372,6 +9770,16 @@ snapshots: - terser - utf-8-validate + vite@5.4.3(@types/node@20.17.10)(terser@5.36.0): + dependencies: + esbuild: 0.21.5 + postcss: 8.4.49 + rollup: 4.28.0 + optionalDependencies: + '@types/node': 20.17.10 + fsevents: 2.3.3 + terser: 5.36.0 + vite@5.4.3(@types/node@22.10.2)(terser@5.36.0): dependencies: esbuild: 0.21.5 @@ -9382,6 +9790,41 @@ snapshots: fsevents: 2.3.3 terser: 5.36.0 + vitest@1.0.0(@types/node@20.17.10)(terser@5.36.0): + dependencies: + '@vitest/expect': 1.0.0 + '@vitest/runner': 1.0.0 + '@vitest/snapshot': 1.0.0 + '@vitest/spy': 1.0.0 + '@vitest/utils': 1.0.0 + acorn-walk: 8.3.4 + cac: 6.7.14 + chai: 4.5.0 + debug: 4.3.7 + execa: 8.0.1 + local-pkg: 0.5.1 + magic-string: 0.30.14 + pathe: 1.1.2 + picocolors: 1.1.1 + std-env: 3.8.0 + strip-literal: 1.3.0 + tinybench: 2.9.0 + tinypool: 0.8.4 + vite: 5.4.3(@types/node@20.17.10)(terser@5.36.0) + vite-node: 1.0.0(@types/node@20.17.10)(terser@5.36.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 20.17.10 + transitivePeerDependencies: + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + vitest@1.0.0(@types/node@22.10.2)(terser@5.36.0): dependencies: '@vitest/expect': 1.0.0 @@ -9416,6 +9859,7 @@ snapshots: - sugarss - supports-color - terser + optional: true watchpack@2.4.1: dependencies: @@ -9457,8 +9901,7 @@ snapshots: webidl-conversions@4.0.2: {} - webpack-virtual-modules@0.6.2: - optional: true + webpack-virtual-modules@0.6.2: {} whatwg-url@7.1.0: dependencies: @@ -9529,6 +9972,10 @@ snapshots: dependencies: string-width: 5.1.2 + widest-line@5.0.0: + dependencies: + string-width: 7.2.0 + winreg@0.0.12: {} word-wrap@1.2.5: {} @@ -9545,6 +9992,12 @@ snapshots: string-width: 5.1.2 strip-ansi: 7.1.0 + wrap-ansi@9.0.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 7.2.0 + strip-ansi: 7.1.0 + wrappy@1.0.2: {} write-file-atomic@3.0.3: diff --git a/scripts/version-warning.mjs b/scripts/version-warning.mjs new file mode 100755 index 00000000..d02c45fa --- /dev/null +++ b/scripts/version-warning.mjs @@ -0,0 +1,97 @@ +#!/usr/bin/env node +import boxen from 'boxen'; +import chalk from 'chalk'; +import { readFileSync, readdirSync } from 'fs'; +import { resolve, dirname } from 'path'; +import { fileURLToPath } from 'url'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + +// Styling constants +const styles = { + title: '#7B65D0', + header: chalk.hex('#C4B5FD').bold, + text: chalk.hex('#E4E4E7'), + arrow: chalk.hex('#C4B5FD'), + version: chalk.hex('#C4B5FD'), + border: '#503C9B', + dim: chalk.hex('#A1A1AA') +}; + +const MESSAGES = { + workspace: { + header: '📦 Workspace Packages', + text: 'Make sure to bump versions if publishing' + }, + package: { + text: 'Make sure to bump version if publishing' + } +}; + +function getWorkspacePackages() { + const packagesDir = resolve(__dirname, '../packages'); + const packages = {}; + + try { + const dirs = readdirSync(packagesDir, { withFileTypes: true }) + .filter(dirent => dirent.isDirectory() && dirent.name !== 'extension'); + + for (const dir of dirs) { + const pkgPath = resolve(packagesDir, dir.name, 'package.json'); + try { + const pkg = JSON.parse(readFileSync(pkgPath, 'utf8')); + packages[pkg.name] = pkg.version; + } catch (err) { + console.error(`Error reading ${dir.name}/package.json:`, err); + } + } + + return packages; + } catch (err) { + console.error('Error reading packages directory:', err); + process.exit(1); + } +} + +function getPackageInfo() { + const cwd = process.cwd(); + const isWorkspacePackage = cwd.includes('packages/'); + const isRootDir = cwd === resolve(__dirname, '..'); + const isDirectPackageBuild = isWorkspacePackage && !process.env.WORKSPACE_BUILD; + + if (isDirectPackageBuild) { + const pkgPath = resolve(cwd, 'package.json'); + const pkg = JSON.parse(readFileSync(pkgPath, 'utf8')); + return { name: pkg.name, version: pkg.version }; + } + + if (isRootDir) { + return { + name: 'Workspace Packages', + versions: getWorkspacePackages() + }; + } + + process.exit(0); +} + +const pkgInfo = getPackageInfo(); + +const message = pkgInfo.versions + ? `${styles.text(MESSAGES.workspace.text)}\n\n` + + `${styles.header(MESSAGES.workspace.header)}\n` + + Object.entries(pkgInfo.versions) + .map(([pkg, version]) => `${styles.dim(pkg.padEnd(12))}${styles.version(`v${version}`)}`) + .join('\n') + : `${styles.text(MESSAGES.package.text)}\n\n` + + `${styles.dim(pkgInfo.name.padEnd(12))}${styles.version(`v${pkgInfo.version}`)}`; + +console.log(boxen(message, { + padding: 1, + margin: 1, + borderStyle: 'round', + borderColor: styles.border, + title: chalk.hex(styles.title)(`⚡ Version Check`), + titleAlignment: 'left', + float: 'left' +}));