Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .storybook/manager.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { addons } from 'storybook/manager-api'

import npmxDark from './theme'

addons.setConfig({
Expand Down
3 changes: 1 addition & 2 deletions .storybook/preview.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import type { Preview } from '@storybook-vue/nuxt'
import { withThemeByDataAttribute } from '@storybook/addon-themes'
import { addons } from 'storybook/preview-api'
import { currentLocales } from '../config/i18n'
import { fn } from 'storybook/test'
import { currentLocales } from '../config/i18n'
import { ACCENT_COLORS } from '../shared/utils/constants'

import npmxDark from './theme'

// related: https://github.com/npmx-dev/npmx.dev/blob/1431d24be555bca5e1ae6264434d49ca15173c43/test/nuxt/setup.ts#L12-L26
Expand Down
4 changes: 2 additions & 2 deletions app/components/AppHeader.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<script setup lang="ts">
import { LinkBase } from '#components'
import type { NavigationConfig, NavigationConfigWithGroups } from '~/types'
import { isEditableElement } from '~/utils/input'
import { LinkBase } from '#components'
import { NPMX_DOCS_SITE } from '#shared/utils/constants'
import { isEditableElement } from '~/utils/input'

const keyboardShortcuts = useKeyboardShortcuts()
const discord = useDiscordLink()
Expand Down
2 changes: 1 addition & 1 deletion app/components/BlueskyComment.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script setup lang="ts">
import type { AppBskyRichtextFacet } from '@atproto/api'
import { segmentize } from '@atcute/bluesky-richtext-segmenter'
import type { Comment } from '#shared/types/blog-post'
import { segmentize } from '@atcute/bluesky-richtext-segmenter'

type RichtextFeature =
| AppBskyRichtextFacet.Link
Expand Down
7 changes: 3 additions & 4 deletions app/components/Compare/FacetBarChart.vue
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
<script setup lang="ts">
import type { VueUiHorizontalBarConfig, VueUiHorizontalBarDatasetItem } from 'vue-data-ui'
import { ref, computed } from 'vue'
import { VueUiHorizontalBar } from 'vue-data-ui/vue-ui-horizontal-bar'
import type { VueUiHorizontalBarConfig, VueUiHorizontalBarDatasetItem } from 'vue-data-ui'
import { getFrameworkColor, isListedFramework } from '~/utils/frameworks'
import { createChartPatternSlotMarkup } from '~/utils/charts'
import { drawSmallNpmxLogoAndTaglineWatermark } from '~/composables/useChartWatermark'

import { createChartPatternSlotMarkup } from '~/utils/charts'
import {
loadFile,
insertLineBreaks,
sanitise,
applyEllipsis,
copyAltTextForCompareFacetBarChart,
} from '~/utils/charts'
import { getFrameworkColor, isListedFramework } from '~/utils/frameworks'

import('vue-data-ui/style.css')

Expand Down
2 changes: 1 addition & 1 deletion app/components/Header/AuthModal.client.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script setup lang="ts">
import { isAtIdentifierString } from '@atproto/lex'
import { useAtproto } from '~/composables/atproto/useAtproto'
import { authRedirect } from '~/utils/atproto/helpers'
import { isAtIdentifierString } from '@atproto/lex'

const authModal = useModal('auth-modal')

Expand Down
2 changes: 1 addition & 1 deletion app/components/Header/MobileMenu.client.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script setup lang="ts">
import type { NavigationConfigWithGroups } from '~/types'
import { useFocusTrap } from '@vueuse/integrations/useFocusTrap'
import { useAtproto } from '~/composables/atproto/useAtproto'
import type { NavigationConfigWithGroups } from '~/types'

const isOpen = defineModel<boolean>('open', { default: false })
const { links } = defineProps<{
Expand Down
2 changes: 1 addition & 1 deletion app/components/Package/InstallScripts.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script setup lang="ts">
import { getOutdatedTooltip, getVersionClass } from '~/utils/npm/outdated-dependencies'
import type { RouteLocationRaw } from 'vue-router'
import { getOutdatedTooltip, getVersionClass } from '~/utils/npm/outdated-dependencies'
const props = defineProps<{
packageName: string
Expand Down
18 changes: 9 additions & 9 deletions app/components/Package/TrendsChart.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
<script setup lang="ts">
import type { Theme as VueDataUiTheme, VueUiXyConfig, VueUiXyDatasetItem } from 'vue-data-ui'
import { VueUiXy } from 'vue-data-ui/vue-ui-xy'
import { useDebounceFn, useElementSize, useTimeoutFn } from '@vueuse/core'
import { useCssVariables } from '~/composables/useColors'
import { OKLCH_NEUTRAL_FALLBACK, transparentizeOklch, lightenOklch } from '~/utils/colors'
import { getFrameworkColor, isListedFramework } from '~/utils/frameworks'
import { drawNpmxLogoAndTaglineWatermark } from '~/composables/useChartWatermark'
import type { RepoRef } from '#shared/utils/git-providers'
import type {
ChartTimeGranularity,
Expand All @@ -17,14 +10,21 @@ import type {
WeeklyDataPoint,
YearlyDataPoint,
} from '~/types/chart'
import { DATE_INPUT_MAX } from '~/utils/input'
import type { Theme as VueDataUiTheme, VueUiXyConfig, VueUiXyDatasetItem } from 'vue-data-ui'
import { useDebounceFn, useElementSize, useTimeoutFn } from '@vueuse/core'
import { VueUiXy } from 'vue-data-ui/vue-ui-xy'
import { drawNpmxLogoAndTaglineWatermark } from '~/composables/useChartWatermark'
import { useCssVariables } from '~/composables/useColors'
import {
applyDataPipeline,
endDateOnlyToUtcMs,
DEFAULT_PREDICTION_POINTS,
} from '~/utils/chart-data-prediction'
import { applyBlocklistCorrection, getAnomaliesForPackages } from '~/utils/download-anomalies'
import { copyAltTextForTrendLineChart, sanitise, loadFile, applyEllipsis } from '~/utils/charts'
import { OKLCH_NEUTRAL_FALLBACK, transparentizeOklch, lightenOklch } from '~/utils/colors'
import { applyBlocklistCorrection, getAnomaliesForPackages } from '~/utils/download-anomalies'
import { getFrameworkColor, isListedFramework } from '~/utils/frameworks'
import { DATE_INPUT_MAX } from '~/utils/input'

import('vue-data-ui/style.css')

Expand Down
2 changes: 1 addition & 1 deletion app/components/Package/Versions.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script setup lang="ts">
import { compare, validRange } from 'semver'
import type { RouteLocationRaw } from 'vue-router'
import { compare, validRange } from 'semver'
import { fetchAllPackageVersions } from '~/utils/npm/api'

const props = defineProps<{
Expand Down
8 changes: 4 additions & 4 deletions app/components/Package/WeeklyDownloadStats.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<script setup lang="ts">
import type { RepoRef } from '#shared/utils/git-providers'
import type { WeeklyDataPoint } from '~/types/chart'
import type { VueUiSparklineConfig, VueUiSparklineDatasetItem } from 'vue-data-ui'
import { onKeyDown } from '@vueuse/core'
import { VueUiSparkline } from 'vue-data-ui/vue-ui-sparkline'
import { useCssVariables } from '~/composables/useColors'
import type { WeeklyDataPoint } from '~/types/chart'
import { applyDataCorrection } from '~/utils/chart-data-correction'
import { OKLCH_NEUTRAL_FALLBACK, lightenOklch } from '~/utils/colors'
import { applyBlocklistCorrection } from '~/utils/download-anomalies'
import type { RepoRef } from '#shared/utils/git-providers'
import type { VueUiSparklineConfig, VueUiSparklineDatasetItem } from 'vue-data-ui'
import { onKeyDown } from '@vueuse/core'

import('vue-data-ui/style.css')

Expand Down
2 changes: 1 addition & 1 deletion app/composables/useGlobalSearch.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { normalizeSearchParam } from '#shared/utils/url'
import { debounce } from 'perfect-debounce'
import { normalizeSearchParam } from '#shared/utils/url'

// Pages that have their own local filter using ?q
const pagesWithLocalFilter = new Set(['~username', 'org'])
Expand Down
2 changes: 1 addition & 1 deletion app/composables/useSettings.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { LocaleObject } from '@nuxtjs/i18n'
import type { RemovableRef } from '@vueuse/core'
import { useLocalStorage } from '@vueuse/core'
import { ACCENT_COLORS, type AccentColorId } from '#shared/utils/constants'
import type { LocaleObject } from '@nuxtjs/i18n'
import { BACKGROUND_THEMES } from '#shared/utils/constants'

type BackgroundThemeId = keyof typeof BACKGROUND_THEMES
Expand Down
4 changes: 2 additions & 2 deletions app/composables/useVersionDistribution.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { MaybeRefOrGetter } from 'vue'
import { toValue } from 'vue'
import type {
VersionDistributionResponse,
VersionGroupDownloads,
VersionGroupingMode,
} from '#shared/types/version-downloads'
import type { MaybeRefOrGetter } from 'vue'
import { toValue } from 'vue'

interface ChartDataItem {
name: string
Expand Down
4 changes: 2 additions & 2 deletions app/pages/about.stories.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import About from './about.vue'
import type { Meta, StoryObj } from '@storybook-vue/nuxt'
import AppHeader from '~/components/AppHeader.vue'
import AppFooter from '~/components/AppFooter.vue'
import AppHeader from '~/components/AppHeader.vue'
import About from './about.vue'

const meta = {
component: About,
Expand Down
2 changes: 1 addition & 1 deletion app/pages/compare.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script setup lang="ts">
import { NO_DEPENDENCY_ID } from '~/composables/usePackageComparison'
import { useRouteQuery } from '@vueuse/router'
import FacetBarChart from '~/components/Compare/FacetBarChart.vue'
import { NO_DEPENDENCY_ID } from '~/composables/usePackageComparison'

definePageMeta({
name: 'compare',
Expand Down
2 changes: 1 addition & 1 deletion app/pages/org/[org].vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script setup lang="ts">
import type { FilterChip, SortOption } from '#shared/types/preferences'
import { normalizeSearchParam } from '#shared/utils/url'
import { debounce } from 'perfect-debounce'
import { normalizeSearchParam } from '#shared/utils/url'

definePageMeta({
name: 'org',
Expand Down
4 changes: 2 additions & 2 deletions app/pages/search.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<script setup lang="ts">
import type { FilterChip, SortKey } from '#shared/types/preferences'
import { parseSortOption, PROVIDER_SORT_KEYS } from '#shared/types/preferences'
import { onKeyDown } from '@vueuse/core'
import { debounce } from 'perfect-debounce'
import { parseSortOption, PROVIDER_SORT_KEYS } from '#shared/types/preferences'
import { normalizeSearchParam } from '#shared/utils/url'
import { isValidNewPackageName } from '~/utils/package-name'
import { isPlatformSpecificPackage } from '~/utils/platform-packages'
import { normalizeSearchParam } from '#shared/utils/url'

definePageMeta({
preserveScrollOnQuery: true,
Expand Down
2 changes: 1 addition & 1 deletion app/utils/atproto/likes.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { PackageLikes } from '#shared/types/social'
import { FetchError } from 'ofetch'
import { handleAuthError } from '~/utils/atproto/helpers'
import type { PackageLikes } from '#shared/types/social'

type LikeResult = { success: true; data: PackageLikes } | { success: false; error: Error }

Expand Down
2 changes: 1 addition & 1 deletion app/utils/run-command.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { PackageManagerId } from './install-command'
import type { JsrPackageInfo } from '#shared/types/jsr'
import { getPackageSpecifier, packageManagers } from './install-command'
import type { PackageManagerId } from './install-command'

/**
* Information about executable commands provided by a package.
Expand Down
8 changes: 4 additions & 4 deletions cli/src/mock-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@
* but backed by in-memory state. Used by the mock CLI and E2E tests.
*/

import { H3, HTTPError, handleCors, type H3Event } from 'h3-next'
import type { CorsOptions } from 'h3-next'
import { serve, type Server } from 'srvx'
import type { MockConnectorStateManager } from './mock-state.ts'
import type {
OperationType,
ApiResponse,
ConnectorEndpoints,
AssertEndpointsImplemented,
} from './types.ts'
import type { MockConnectorStateManager } from './mock-state.ts'
import type { CorsOptions } from 'h3-next'
import { H3, HTTPError, handleCors, type H3Event } from 'h3-next'
import { serve, type Server } from 'srvx'

// Endpoint completeness check β€” errors if this list diverges from ConnectorEndpoints.
// oxlint-disable-next-line no-unused-vars
Expand Down
38 changes: 4 additions & 34 deletions cli/src/server.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,9 @@
import crypto from 'node:crypto'
import { H3, HTTPError, handleCors, type H3Event } from 'h3-next'
import type { ConnectorState, PendingOperation, ApiResponse, ConnectorEndpoints } from './types.ts'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Reinstate compile-time endpoint parity check.

Line 1 now omits the AssertEndpointsImplemented safeguard, so endpoint drift between ConnectorEndpoints and this server can go unnoticed at compile time.

Suggested fix
-import type { ConnectorState, PendingOperation, ApiResponse, ConnectorEndpoints } from './types.ts'
+import type {
+  ConnectorState,
+  PendingOperation,
+  ApiResponse,
+  ConnectorEndpoints,
+  AssertEndpointsImplemented,
+} from './types.ts'
 export const CONNECTOR_VERSION = pkg.version
+
+type ImplementedEndpoint =
+  | 'POST /connect'
+  | 'GET /state'
+  | 'POST /operations'
+  | 'POST /operations/batch'
+  | 'DELETE /operations'
+  | 'DELETE /operations/all'
+  | 'POST /approve'
+  | 'POST /approve-all'
+  | 'POST /retry'
+  | 'POST /execute'
+  | 'GET /org/:org/users'
+  | 'GET /org/:org/teams'
+  | 'GET /team/:scopeTeam/users'
+  | 'GET /package/:pkg/collaborators'
+  | 'GET /user/packages'
+  | 'GET /user/orgs'
+
+const _endpointCheck: AssertEndpointsImplemented<ImplementedEndpoint> = true

import type { CorsOptions } from 'h3-next'
import { H3, HTTPError, handleCors, type H3Event } from 'h3-next'
import crypto from 'node:crypto'
import * as v from 'valibot'

import type {
ConnectorState,
PendingOperation,
ApiResponse,
ConnectorEndpoints,
AssertEndpointsImplemented,
} from './types.ts'

// Endpoint completeness check β€” errors if this list diverges from ConnectorEndpoints.
const _endpointCheck: AssertEndpointsImplemented<
| 'POST /connect'
| 'GET /state'
| 'POST /operations'
| 'POST /operations/batch'
| 'DELETE /operations'
| 'DELETE /operations/all'
| 'POST /approve'
| 'POST /approve-all'
| 'POST /retry'
| 'POST /execute'
| 'GET /org/:org/users'
| 'GET /org/:org/teams'
| 'GET /team/:scopeTeam/users'
| 'GET /package/:pkg/collaborators'
| 'GET /user/packages'
| 'GET /user/orgs'
> = true
void _endpointCheck
import pkg from '../package.json' with { type: 'json' }
import { logDebug, logError } from './logger.ts'
import {
getNpmUser,
Expand Down Expand Up @@ -68,9 +41,6 @@ import {
validateOperationParams,
} from './schemas.ts'

// Read version from package.json
import pkg from '../package.json' with { type: 'json' }

export const CONNECTOR_VERSION = pkg.version

function generateToken(): string {
Expand Down
3 changes: 1 addition & 2 deletions config/env.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
// TODO(serhalp): Extract most of this module to https://github.com/unjs/std-env.

import Git from 'simple-git'
import * as process from 'node:process'

import Git from 'simple-git'
import { version as packageVersion } from '../package.json'
import { getNextVersion } from '../scripts/next-version'

Expand Down
2 changes: 1 addition & 1 deletion lunaria.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { defineConfig } from '@lunariajs/core/config'
import type { Locale, Merge } from '@lunariajs/core'
import { defineConfig } from '@lunariajs/core/config'
import { currentLocales, countryLocaleVariants } from './config/i18n.ts'

// The source locale is `en` (en.json contains all reference translation keys).
Expand Down
2 changes: 1 addition & 1 deletion lunaria/components.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { I18nStatus } from '../shared/types/i18n-status.ts'
import {
type createLunaria,
type Locale,
Expand All @@ -6,7 +7,6 @@ import {
type StatusEntry,
} from '@lunariajs/core'
import { BaseStyles, CustomStyles } from './styles.ts'
import type { I18nStatus } from '../shared/types/i18n-status.ts'

export function html(
strings: TemplateStringsArray,
Expand Down
4 changes: 2 additions & 2 deletions lunaria/lunaria.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { I18nStatus } from '../shared/types/i18n-status.ts'
import { createLunaria } from '@lunariajs/core'
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
import { Page } from './components.ts'
import { countryLocaleVariants, currentLocales } from '../config/i18n.ts'
import type { I18nStatus } from '../shared/types/i18n-status.ts'
import { Page } from './components.ts'

// skip lunaria during git merges as git history may be in an inconsistent state.
if (existsSync('.git/MERGE_HEAD')) {
Expand Down
18 changes: 9 additions & 9 deletions modules/blog.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
import { join } from 'node:path'
import Markdown from 'unplugin-vue-markdown/vite'
import { addTemplate, addVitePlugin, defineNuxtModule, useNuxt, createResolver } from 'nuxt/kit'
import shiki from '@shikijs/markdown-exit'
import MarkdownItAnchor from 'markdown-it-anchor'
import { defu } from 'defu'
import { read } from 'gray-matter'
import MarkdownItAnchor from 'markdown-it-anchor'
import crypto from 'node:crypto'
import { existsSync } from 'node:fs'
import { mkdir, writeFile } from 'node:fs/promises'
import { join } from 'node:path'
import { addTemplate, addVitePlugin, defineNuxtModule, useNuxt, createResolver } from 'nuxt/kit'
import { globSync } from 'tinyglobby'
import Markdown from 'unplugin-vue-markdown/vite'
import { array, safeParse } from 'valibot'
import { isProduction } from '../config/env'
import {
AuthorSchema,
RawBlogPostSchema,
type Author,
type BlogPostFrontmatter,
type ResolvedAuthor,
} from '../shared/schemas/blog'
import { globSync } from 'tinyglobby'
import { isProduction } from '../config/env'
import { BLUESKY_API } from '../shared/utils/constants'
import { mkdir, writeFile } from 'node:fs/promises'
import { existsSync } from 'node:fs'
import crypto from 'node:crypto'

/**
* Fetches Bluesky avatars for a set of authors at build time.
Expand Down
2 changes: 1 addition & 1 deletion modules/runtime/server/cache.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import process from 'node:process'
import type { CachedFetchResult } from '#shared/utils/fetch-cache-config'
import process from 'node:process'
import { createFetch } from 'ofetch'

/**
Expand Down
Loading
Loading