Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create the toolkit for plugin authors #88

Merged
merged 19 commits into from
Oct 15, 2024
Merged
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 packages/pretty-reporter/src/format-single-diagnostic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { relative } from 'node:path'
import figures from 'figures'
import terminalLink from 'terminal-link'
import chalk from 'chalk'

import type { Diagnostic } from '@steiger/types'

export function formatSingleDiagnostic(d: Diagnostic, cwd: string): string {
Expand Down
4 changes: 1 addition & 3 deletions packages/pretty-reporter/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import chalk from 'chalk'
import figures from 'figures'

import type { Diagnostic } from '@steiger/types'

import { formatSingleDiagnostic } from './format-single-diagnostic.js'
import { s } from './pluralization.js'

Expand Down Expand Up @@ -46,5 +46,3 @@ export function formatPretty(diagnostics: Array<Diagnostic>, cwd: string) {
export function reportPretty(diagnostics: Array<Diagnostic>, cwd: string) {
console.error(formatPretty(diagnostics, cwd))
}

export type { Diagnostic }
2 changes: 1 addition & 1 deletion packages/steiger-plugin-fsd/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@
},
"devDependencies": {
"@steiger/eslint-config": "workspace:*",
"@steiger/toolkit": "workspace:*",
"@steiger/tsconfig": "workspace:*",
"@steiger/types": "workspace:*",
"@total-typescript/ts-reset": "^0.5.1",
"@types/lodash-es": "^4.17.12",
"@types/pluralize": "^0.0.33",
Expand Down
4 changes: 1 addition & 3 deletions packages/steiger-plugin-fsd/src/_lib/index-source-files.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { getIndex, getLayers, getSegments, getSlices, isSliced, type LayerName } from '@feature-sliced/filesystem'
import type { File, Folder } from '@steiger/types'

import { joinFromRoot, parseIntoFsdRoot } from './prepare-test.js'
import { joinFromRoot, parseIntoFolder as parseIntoFsdRoot, type File, type Folder } from '@steiger/toolkit'

type SourceFile = {
file: File
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { join } from 'node:path'
import { expect, it } from 'vitest'

import ambiguousSliceNames from './index.js'
import { joinFromRoot, parseIntoFsdRoot } from '../_lib/prepare-test.js'
import { joinFromRoot, parseIntoFolder as parseIntoFsdRoot } from '@steiger/toolkit'

it('reports no errors on a project without slice names that match some segment name in Shared', () => {
const root = parseIntoFsdRoot(`
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { basename, sep } from 'node:path'
import { getAllSlices, getLayers, getSegments, type LayerName } from '@feature-sliced/filesystem'
import type { PartialDiagnostic, Folder, Rule } from '@steiger/types'
import type { PartialDiagnostic, Folder, Rule } from '@steiger/toolkit'
import { NAMESPACE } from '../constants.js'

/** Forbid slice names that match some segment’s name in shared (e.g., theme, i18n) */
const ambiguousSliceNames = {
name: `${NAMESPACE}/ambiguous-slice-names`,
name: `${NAMESPACE}/ambiguous-slice-names` as const,
check(root) {
const diagnostics: Array<PartialDiagnostic> = []

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect, it } from 'vitest'

import { joinFromRoot, parseIntoFsdRoot } from '../_lib/prepare-test.js'
import { joinFromRoot, parseIntoFolder as parseIntoFsdRoot } from '@steiger/toolkit'
import excessiveSlicing from './index.js'

it('reports no errors on projects with moderate slicing', () => {
Expand Down
4 changes: 2 additions & 2 deletions packages/steiger-plugin-fsd/src/excessive-slicing/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { join } from 'node:path'
import { getLayers, getSlices, isSliced } from '@feature-sliced/filesystem'
import type { PartialDiagnostic, Rule } from '@steiger/types'
import type { PartialDiagnostic, Rule } from '@steiger/toolkit'

import { groupSlices } from '../_lib/group-slices.js'
import { NAMESPACE } from '../constants.js'
Expand All @@ -14,7 +14,7 @@ const THRESHOLDS = {

/** Warn about excessive amounts of ungrouped entities/features/widgets/pages. */
const excessiveSlicing = {
name: `${NAMESPACE}/excessive-slicing`,
name: `${NAMESPACE}/excessive-slicing` as const,
check(root) {
const diagnostics: Array<PartialDiagnostic> = []

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect, it, vi } from 'vitest'

import { joinFromRoot, parseIntoFsdRoot } from '../_lib/prepare-test.js'
import { joinFromRoot, parseIntoFolder as parseIntoFsdRoot } from '@steiger/toolkit'
import forbiddenImports from './index.js'

vi.mock('tsconfck', async (importOriginal) => {
Expand All @@ -23,7 +23,7 @@ vi.mock('tsconfck', async (importOriginal) => {

vi.mock('node:fs', async (importOriginal) => {
const originalFs = await importOriginal<typeof import('fs')>()
const { createFsMocks } = await import('../_lib/prepare-test.js')
const { createFsMocks } = await import('@steiger/toolkit')

return createFsMocks(
{
Expand Down
4 changes: 2 additions & 2 deletions packages/steiger-plugin-fsd/src/forbidden-imports/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import { layerSequence, resolveImport, isCrossImportPublicApi } from '@feature-s
import precinct from 'precinct'
const { paperwork } = precinct
import { parse as parseNearestTsConfig } from 'tsconfck'
import type { PartialDiagnostic, Rule } from '@steiger/types'
import type { PartialDiagnostic, Rule } from '@steiger/toolkit'

import { indexSourceFiles } from '../_lib/index-source-files.js'
import { NAMESPACE } from '../constants.js'

const forbiddenImports = {
name: `${NAMESPACE}/forbidden-imports`,
name: `${NAMESPACE}/forbidden-imports` as const,
async check(root) {
const diagnostics: Array<PartialDiagnostic> = []
const { tsconfig } = await parseNearestTsConfig(root.path)
Expand Down
37 changes: 0 additions & 37 deletions packages/steiger-plugin-fsd/src/forbidden-imports/precinct.d.ts

This file was deleted.

4 changes: 2 additions & 2 deletions packages/steiger-plugin-fsd/src/import-locality/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect, it, vi } from 'vitest'

import { joinFromRoot, parseIntoFsdRoot } from '../_lib/prepare-test.js'
import { joinFromRoot, parseIntoFolder as parseIntoFsdRoot } from '@steiger/toolkit'
import importLocality from './index.js'

vi.mock('tsconfck', async (importOriginal) => {
Expand All @@ -12,7 +12,7 @@ vi.mock('tsconfck', async (importOriginal) => {

vi.mock('node:fs', async (importOriginal) => {
const originalFs = await importOriginal<typeof import('fs')>()
const { createFsMocks } = await import('../_lib/prepare-test.js')
const { createFsMocks } = await import('@steiger/toolkit')

return createFsMocks(
{
Expand Down
2 changes: 1 addition & 1 deletion packages/steiger-plugin-fsd/src/import-locality/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { resolveImport } from '@feature-sliced/filesystem'
import precinct from 'precinct'
const { paperwork } = precinct
import { parse as parseNearestTsConfig } from 'tsconfck'
import type { PartialDiagnostic, Rule } from '@steiger/types'
import type { PartialDiagnostic, Rule } from '@steiger/toolkit'

import { indexSourceFiles } from '../_lib/index-source-files.js'
import { NAMESPACE } from '../constants.js'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect, it } from 'vitest'

import { compareMessages, parseIntoFsdRoot, joinFromRoot } from '../_lib/prepare-test.js'
import { compareMessages, joinFromRoot, parseIntoFolder as parseIntoFsdRoot } from '@steiger/toolkit'
import inconsistentNaming from './index.js'

it('reports no errors on slice names that are pluralized consistently', () => {
Expand Down
4 changes: 2 additions & 2 deletions packages/steiger-plugin-fsd/src/inconsistent-naming/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import { partition } from 'lodash-es'
import pluralize from 'pluralize'
const { isPlural, plural, singular } = pluralize
import { getLayers, getSlices } from '@feature-sliced/filesystem'
import type { PartialDiagnostic, Rule } from '@steiger/types'
import type { PartialDiagnostic, Rule } from '@steiger/toolkit'

import { groupSlices } from '../_lib/group-slices.js'
import { NAMESPACE } from '../constants.js'

/** Detect inconsistent naming of slices on layers (singular vs plural) */
const inconsistentNaming = {
name: `${NAMESPACE}/inconsistent-naming`,
name: `${NAMESPACE}/inconsistent-naming` as const,
check(root) {
const diagnostics: Array<PartialDiagnostic> = []

Expand Down
22 changes: 10 additions & 12 deletions packages/steiger-plugin-fsd/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Config, Rule, Plugin, ConfigObject } from '@steiger/types'
import { enableAllRules, type ConfigObjectOf, createPlugin, createConfigs } from '@steiger/toolkit'

import ambiguousSliceNames from './ambiguous-slice-names/index.js'
import excessiveSlicing from './excessive-slicing/index.js'
Expand All @@ -19,7 +19,7 @@ import typoInLayerName from './typo-in-layer-name/index.js'
import noProcesses from './no-processes/index.js'
import packageJson from '../package.json'

const allRules: Array<Rule> = [
const rules = [
ambiguousSliceNames,
excessiveSlicing,
forbiddenImports,
Expand All @@ -39,23 +39,21 @@ const allRules: Array<Rule> = [
noProcesses,
]

const allRulesEnabledConfig: ConfigObject = {
rules: allRules.reduce((acc, rule) => ({ ...acc, [rule.name]: 'error' }), {}),
}

const plugin: Plugin = {
const plugin = createPlugin({
meta: {
name: 'steiger-plugin-fsd',
version: packageJson.version,
},
ruleDefinitions: allRules,
}
ruleDefinitions: rules,
})

const configs: Record<string, Config> = {
recommended: [plugin, allRulesEnabledConfig],
}
const configs = createConfigs({
recommended: enableAllRules(plugin),
})

export default {
plugin,
configs,
}

export type FSDConfigObject = ConfigObjectOf<typeof plugin>
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { expect, it, vi } from 'vitest'
import { join } from 'node:path'

import { compareMessages, joinFromRoot, parseIntoFsdRoot } from '../_lib/prepare-test.js'
import { compareMessages, joinFromRoot, parseIntoFolder as parseIntoFsdRoot } from '@steiger/toolkit'
import insignificantSlice from './index.js'

vi.mock('tsconfck', async (importOriginal) => {
Expand All @@ -13,7 +13,7 @@ vi.mock('tsconfck', async (importOriginal) => {

vi.mock('node:fs', async (importOriginal) => {
const originalFs = await importOriginal<typeof import('fs')>()
const { createFsMocks } = await import('../_lib/prepare-test.js')
const { createFsMocks } = await import('@steiger/toolkit')

return createFsMocks(
{
Expand Down
4 changes: 2 additions & 2 deletions packages/steiger-plugin-fsd/src/insignificant-slice/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ import * as fs from 'node:fs'
import { sep, join } from 'node:path'
import { parse as parseNearestTsConfig } from 'tsconfck'
import { isSliced, resolveImport, unslicedLayers, type LayerName } from '@feature-sliced/filesystem'
import type { Folder, PartialDiagnostic, Rule } from '@steiger/types'
import type { Folder, PartialDiagnostic, Rule } from '@steiger/toolkit'
import precinct from 'precinct'
const { paperwork } = precinct

import { indexSourceFiles } from '../_lib/index-source-files.js'
import { NAMESPACE } from '../constants.js'

const insignificantSlice = {
name: `${NAMESPACE}/insignificant-slice`,
name: `${NAMESPACE}/insignificant-slice` as const,
async check(root) {
const diagnostics: Array<PartialDiagnostic> = []

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect, it } from 'vitest'

import { compareMessages, joinFromRoot, parseIntoFsdRoot } from '../_lib/prepare-test.js'
import { compareMessages, joinFromRoot, parseIntoFolder as parseIntoFsdRoot } from '@steiger/toolkit'
import noFileSegments from './index.js'

it('reports no errors on a project with only folder segments', async () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/steiger-plugin-fsd/src/no-file-segments/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { basename } from 'node:path'
import { getLayers, getSlices, isSliced } from '@feature-sliced/filesystem'
import type { PartialDiagnostic, Rule } from '@steiger/types'
import type { PartialDiagnostic, Rule } from '@steiger/toolkit'
import { NAMESPACE } from '../constants.js'

const noFileSegments = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { expect, it } from 'vitest'

import noLayerPublicApi from './index.js'
import { joinFromRoot, parseIntoFsdRoot } from '../_lib/prepare-test.js'
import { joinFromRoot, parseIntoFolder as parseIntoFsdRoot } from '@steiger/toolkit'

it('reports no errors on a project without index files on layer level', () => {
const root = parseIntoFsdRoot(`
Expand Down
4 changes: 2 additions & 2 deletions packages/steiger-plugin-fsd/src/no-layer-public-api/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { getIndex, getLayers } from '@feature-sliced/filesystem'
import type { PartialDiagnostic, Rule } from '@steiger/types'
import type { PartialDiagnostic, Rule } from '@steiger/toolkit'
import { NAMESPACE } from '../constants.js'

/** Layers that are allowed to have an index file. */
const exceptionLayers = ['app']

/** Forbid index files on layer level. */
const noLayerPublicApi = {
name: `${NAMESPACE}/no-layer-public-api`,
name: `${NAMESPACE}/no-layer-public-api` as const,
check(root) {
const diagnostics: Array<PartialDiagnostic> = []

Expand Down
2 changes: 1 addition & 1 deletion packages/steiger-plugin-fsd/src/no-processes/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { expect, it } from 'vitest'

import noProcesses from './index.js'
import { joinFromRoot, parseIntoFsdRoot } from '../_lib/prepare-test.js'
import { joinFromRoot, parseIntoFolder as parseIntoFsdRoot } from '@steiger/toolkit'

it('reports no errors on a project without the Processes layer', () => {
const root = parseIntoFsdRoot(`
Expand Down
4 changes: 2 additions & 2 deletions packages/steiger-plugin-fsd/src/no-processes/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { basename } from 'node:path'
import type { PartialDiagnostic, Rule } from '@steiger/types'
import type { PartialDiagnostic, Rule } from '@steiger/toolkit'
import { NAMESPACE } from '../constants.js'

const noProcesses = {
name: `${NAMESPACE}/no-processes`,
name: `${NAMESPACE}/no-processes` as const,
check(root) {
const diagnostics: Array<PartialDiagnostic> = []

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect, it, vi } from 'vitest'

import { joinFromRoot, parseIntoFsdRoot } from '../_lib/prepare-test.js'
import { joinFromRoot, parseIntoFolder as parseIntoFsdRoot } from '@steiger/toolkit'
import noPublicApiSidestep from './index.js'

vi.mock('tsconfck', async (importOriginal) => {
Expand All @@ -12,7 +12,7 @@ vi.mock('tsconfck', async (importOriginal) => {

vi.mock('node:fs', async (importOriginal) => {
const originalFs = await importOriginal<typeof import('fs')>()
const { createFsMocks } = await import('../_lib/prepare-test.js')
const { createFsMocks } = await import('@steiger/toolkit')

return createFsMocks(
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ import {
resolveImport,
crossReferenceToken,
} from '@feature-sliced/filesystem'
import type { Folder, File, PartialDiagnostic, Rule } from '@steiger/types'
import type { Folder, File, PartialDiagnostic, Rule } from '@steiger/toolkit'

import { indexSourceFiles } from '../_lib/index-source-files.js'
import { NAMESPACE } from '../constants.js'

/** Restrict imports that go inside the slice, sidestepping the public API. */
const noPublicApiSidestep = {
name: `${NAMESPACE}/no-public-api-sidestep`,
name: `${NAMESPACE}/no-public-api-sidestep` as const,
async check(root) {
const diagnostics: Array<PartialDiagnostic> = []
const { tsconfig } = await parseNearestTsConfig(root.path)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { expect, it } from 'vitest'

import noReservedFolderNames from './index.js'
import { joinFromRoot, parseIntoFsdRoot } from '../_lib/prepare-test.js'
import { joinFromRoot, parseIntoFolder as parseIntoFsdRoot } from '@steiger/toolkit'

it('reports no errors on a project without subfolders in segments that use reserved names', () => {
const root = parseIntoFsdRoot(`
Expand Down
Loading