@webority/repo-checks

中文文档
0.119.0发布于 2026/11/03SEE LICENSE IN LICENSEES Module零依赖

Repository checks for Webority React web portals, React Native apps and Razor sites: banned and required dependencies, pnpm only, exact pins, the shared Biome preset, and token use in style, markup and component code. Run before a push; existing findings

原始使用文档
文档目录6 节
  1. Use
  2. Token rules: counted per file
  3. New rules start as warnings
  4. Existing findings: a baseline that only shrinks
  5. The shared pre-commit hook
  6. Versioning

@webority/repo-checks

Repository checks for Webority React web portals and React Native apps. One command reads every app package.json in the git repository and reports what the house rules say it must not have, must have, and how it must be pinned and installed.

It also counts raw measures, raw colours, root font sizes and palette reads in every tracked style, markup and script file of the repository (bootstrap-ui.md → Tokens).

Use

pnpm add -D --save-exact @webority/repo-checks
pnpm exec webority-repo-checks              # every app in the repository
pnpm exec webority-repo-checks apps/portal  # one app folder

An app is a package.json whose dependencies hold react-native (mobile) or react-dom (web). A react-dom folder that also has react-native-web is a react-native-web demo: it gets the pnpm and Biome checks, not the portal rules. Biome and @webority/biome-config are read from the package.json beside the biome.json in effect (a nested config with "root": false defers to the one above), so a sub-folder linted by the root config does not repeat them. A workspace:, file: or link: reference is local and never counts as a lockstep version. A package with agentation in its dependencies is a build tool, not an app. It and anything else (tooling roots, libraries) get only the lockfile check.

Every app also gets the Node checks: engines.node (from the app's package.json, else the one beside its pnpm-lock.yaml) must be >=24.15 <25, and the nearest .nvmrc must hold 24. A mobile app with an android/ folder gets the Android checks, and a web app's src/ the import checks. The missing-export:<file> check runs the Biome installed beside the app or in a folder above it, so it needs @biomejs/biome installed; without one it reports nothing, and the required:@biomejs/biome finding fails the app.

FindingWhat it means
banned:<name>A dependency the rules retire or forbid (ESLint, Prettier, lint-staged, react-toastify, moment and the rest; the mobile list is the retired-libraries table)
required:<name>A dependency every app carries (Biome and the shared preset, the core and UI packages, Bootstrap and react-bootstrap on web, Crashlytics on mobile)
not-exact:<name>A ^ or ~ range. Web pins @webority/* and bootstrap exactly; a React Native app pins every dependency exactly
bootstrap-versionBootstrap other than 5.3.3
lockstep:<set>Packages that publish together at one version are pinned at different versions
pnpm:*A committed package-lock.json or yarn.lock, no pnpm-lock.yaml, no devEngines.packageManager of { "name": "pnpm", "version": "<x.y.z>", "onFail": "error" } (a plain npm install fails, and pnpm refuses any other version), a leftover packageManager field (pnpm ignores it beside devEngines), or a pnpm-workspace.yaml without engineStrict: true and strictPeerDependencies: true
biome:*No Biome config, a config that does not extend @webority/biome-config/biome.jsonc, a formatter.lineEnding or root linter.rules, or (mobile) no __DEV__ global, either top-level or in an override whose includes cover the app folder
catalogue-copy:<file>A web file under src/components/ named like a @webority/ui-react export
engines-node-floor:package.jsonengines.node is missing or is not >=24.15 <25
engines-node-floor:.nvmrcNo .nvmrc at or above the app, or it does not hold 24
android-release-signingandroid/app/build.gradle has no guard that throws a GradleException when a requested task name contains release and a signing setting or the upload key is missing
android-edge-to-edgeandroid/gradle.properties sets edgeToEdgeEnabled=false
rn-mainactivity-oncreate-bundle:<file>A MainActivity.kt or .java passes a bundle to super.onCreate; pass null
metro-bridge:<file>A React Native app's entry file (package.json main, default index.js), root App.js or src/App.js nor any other source file of the app (outside node_modules, ios, android and build output) imports createMetroBridge from @webority/mobile-core/metro and assigns globalThis.__METRO_BRIDGE__ from a createMetroBridge(...) call inside if (__DEV__) in the same file; react-native-procedures.md → Debugging: the development bridge
mobile-production-stamps:<file>A mobile app's Android manifest or iOS Expo.plist points over-the-air updates at the Staging or Development feed, or android/gradle.properties carries a .staging or .development app id, left by mobile-tools prebuild. Run mobile-tools prebuild --env Production before committing
spa-host-immutable-assets:<file>A web app's web.config, staticwebapp.config.json, _headers or spa-host*.json sets Cache-Control with immutable
stale-theme-name:<file>A web style or source file reads a pre-0.89.0 theme name as a whole token (var(--radius), --color-primary-ink). No alias ships for these. Run webority upgrade 0.89.0 --path <folder> once, then webority brand. --color-primary-text is not flagged. Never recorded in the baseline
lint:<file>Biome's check, with warnings as errors, over the app folder: any error or warning. Never recorded in the baseline; fix the finding
web-import-axios:<file>A web source file under src/ imports axios; HTTP goes through @webority/web-core
web-import-router:<file>A web source file imports BrowserRouter or Routes from react-router or react-router-dom; routes are objects for createBrowserRouter
web-import-env-branch:<file>A web source file reads import.meta.env.DEV or import.meta.env.PROD; branch on AppSettings.ENVIRONMENT
missing-export:<file>A file imports a name its module does not export; Biome's React false alarms and unresolved aliases are not reported
raw-measure:<file>A px, rem or em literal, or a bare number for a weight or a leading, in padding, margin, gap, inset, a corner, font size, font weight or line height. Counted per file.
raw-colour:<file>A hex, an rgb() or hsl() with numbers, or a CSS named colour in a colour property or style key, where a colour meaning belongs. Counted per file.
root-font-size:<file>A font-size or font declared on html or :root. The type scale assumes the browser's root size. Counted per file.
palette-read:<file>A read of a raw palette step (var(--wui-<step>), or a phone palette. read) or of a Bootstrap theme colour (var(--bs-primary), var(--bs-primary-rgb) or Sass $primary, for the eight theme colours), where a colour meaning belongs. The message names the meaning to read. Counted per file.
missing-canvas-key:<file>A list item (the first JSX tag in a .map( callback) with no data-canvas key on web or testID on a phone, and no spread. Counted per file.
repeated-canvas-key:<file>A quoted data-canvas or testID value that a second tag in the same module repeats. Counted per file.
raw-bootstrap:<file>A .jsx, .tsx or .cshtml file writes a raw Bootstrap component class (btn, card, modal, table, badge, alert, form-control, form-select, form-check-input, pagination, nav-tabs, dropdown-menu, offcanvas, breadcrumb, progress, spinner-border, accordion); the message names the library component. A modifier such as btn-primary alone is not counted. Counted per file.
library-class-restyle:<file>A product .scss or .css selector names a class the library theme defines (a wui-* component class or an app-* shell, navigation or tab class), including as an ancestor (.my-page .wui-card-body, .app-shell.collapsed .app-sidebar .brand-logo); use a library prop or token, or a product class. A token file that only sets custom properties names no class and is not counted. Counted per file.
shadowed-library-name:<file>A .jsx or .tsx file imports a catalogue component from @webority/ui-react under another name and declares a component under the catalogue name (import { AppButton as LibraryAppButton } with function AppButton), so its call sites read as the library component. Use the library component and its props, or give the product component its own name. Counted per file.
rename-wrapper:<file>A re-export of @webority/ui-react, a component whose body only returns one catalogue component, or a _Name.cshtml partial that is one <app-*> element: import the library name. Counted per file.
single-use-component:<file>A file under src/components/<feature>/ (not layout/), or a shared partial under Pages/Shared/ or a *.Web.Common project, that fewer than two files use; move it next to the page that uses it. A layout is skipped: a _…Layout.cshtml file, or one that a _ViewStart.cshtml of the same project names with Layout = "<name>", because areas find it by that name. A Razor file whose first line is @* layering-allow single-use-component: <reason> *@ is skipped too; a mark with no reason is a finding. Counted per file.
error-summary-title:<file>A .cshtml <app-error-summary> sets a title with the old generic wording ("Please fix the following", "There were errors"); drop it, the library writes the standard heading. A computed title or one naming the failed action is not counted. Counted per file.
route-internal-id:<file>A route binds a record's internal number: a .cshtml @page or a C# [Route], [Http*] or Map* template whose id or ...Id parameter is constrained int or long, or an asp-route-* link that passes a record's .Id. Route by the public id ({publicId:guid}) instead. An untyped {id} is not counted. Counted per file.
oversize:<file>A .jsx, .tsx or .cshtml file over 600 lines (over 800 says to split it along its concerns). A warning only: it never fails, even outside the baseline. Counted per file.
hook:driftThe root .husky/pre-commit is missing or differs from the shared hook this package ships (CRLF is ignored)
tracked-case:<path>A tracked file or folder whose name on disk differs only by letter case, a rename done by hand on a Mac that git never saw; a Linux checkout cannot find the import. Run the git mv the message gives. A folder is reported once. Always fails.

Comment lines (//, /*, *) and .test. or .spec. files are not read by the import checks.

Token rules: counted per file

The four rules read every tracked .scss, .css, .cshtml, .jsx and .tsx file, and each .js or .ts file that imports react-native. They skip a path with a node_modules, dist, generated, vendor, __tests__ or __mocks__ segment, an email template project folder (<Product>.Email or <Product>.Emails: email clients read no CSS variables, so inline pixels and colours are required there; a plain Email folder of admin screens stays checked), a path containing wwwroot/lib/, a .generated. name, a .min.css name, a .test. or .spec. script, and any path the repo lists under generated[].paths in .webority/map.json (a trailing / names a folder; * matches within one segment). List a compiled stylesheet there: it bundles the shared theme, so its library rules are not the product's code, and the rules still read the SCSS it is built from.

raw-measure counts a non-zero px, rem or em literal, or a bare number for a weight or a leading, in padding, margin, gap, inset, a corner, font size, font weight or line height: one finding per declaration or style key. A zero, a keyword (auto, bold, normal), a token (var(--wui-space-md)), a percentage or another unit, and a custom property or Sass variable declaration are not counted.

raw-colour counts a hex, an rgb(), rgba(), hsl() or hsla() with numeric arguments, or a CSS named colour, in a colour property or style key (including a fallback inside var(--color-x, #fff)). transparent, currentColor, a meaning read, a custom property or Sass variable declaration, and text inside a url() or a quoted string are not counted.

root-font-size counts every font-size or font declaration in a rule whose selector is html or :root (with or without an attribute, class or pseudo-class), whatever its value.

palette-read counts each var(--wui-<step>) and each phone palette. read, plus each var(--bs-<colour>), var(--bs-<colour>-rgb) and Sass $<colour> for Bootstrap's eight theme colours: one finding per read, and a declaration is not a read.

missing-canvas-key and repeated-canvas-key read every script module that imports react-native, @webority/mobile-ui or @webority/ui-react. The attribute is testID in a module that imports react-native or @webority/mobile-ui, and data-canvas in any other. A spread on the item counts as keyed, and a repeat adds one finding per tag after the first.

src/assets/styles/_home.scss:12: color: var(--wui-primary);
  (read the meaning: var(--color-primary))

New rules start as warnings

lint, rn-mainactivity-oncreate-bundle, spa-host-immutable-assets and oversize print as warnings and do not fail until REPO_CHECKS_ENFORCE names them: REPO_CHECKS_ENFORCE=lint,rn-mainactivity-oncreate-bundle, or all. A release removes a rule from the warning list when no repository has a hit. --json carries the warnings under warnings.

Existing findings: a baseline that only shrinks

A repository adopting the checks records what it has today, once:

pnpm exec webority-repo-checks --baseline-init

That writes .webority/baselines/repo-checks-baseline.json, creating the folder: the dependency findings as "<app folder> | <id>", and the code rules counted per file:

{
    "version": 2,
    "findings": ["apps/portal | banned:@webority/ui-elements", "samples/react-sandbox | required:@webority/web-core"],
    "counts": { "palette-read:packages/theme/scss/wui/_buttons.scss": 3, "raw-measure:src/assets/styles/_home.scss": 14 }
}

From then on a finding in the baseline is reported as known and does not fail; any other finding fails (exit 1). A count may only fall: a file above its recorded count fails and prints its lines, and a file missing from the baseline is at 0, so a new or renamed file starts at 0. After fixing old findings or lowering counts, --baseline-shrink drops the fixed findings and lowers each count to its current value, deleting one that reaches 0; it never adds or raises one.

--baseline-accept <folder> --reason <text> records debt the owner has accepted: every current finding and count under that folder is added, and a count is raised to its current value, never lowered. Use it only for debt the owner has accepted, and give a reason that names the decision; the reason is kept in accepted in the baseline file, and --baseline-shrink keeps that entry.

--baseline-adopt <rule,...> records today's findings and counts for rules the baseline has never recorded, such as a rule a new release adds. It refuses a rule the baseline already records, so it never raises an existing entry, and names how many findings and counts it adopted per rule.

--baseline-init runs once: it refuses an existing file and folder arguments. When the file is the earlier shape (no version), delete it and run --baseline-init once from the git root, then review the diff before committing.

--json prints { root, new, known, stale } for tools; a count above its record appears in new with its lines.

The shared pre-commit hook

Every repository runs the pre-commit hook this package ships. Adopt it once, from the git root:

pnpm exec webority-repo-checks --sync-hook

That writes .husky/pre-commit, creating .husky when it is missing, with LF line endings. A multi-app repository installs it once, at the root. husky stays the installer, through the prepare script. Remove lint-staged (pnpm remove lint-staged, and delete its config key): the shared hook runs Biome itself. Put repo-only steps in .husky/pre-commit.local; the shared hook runs that file after Biome, and --sync-hook never touches it.

hook:drift keeps the root copy equal to the shipped one.

Versioning

Published from the webority-ui monorepo in lockstep with the other @webority/* packages. Pin an exact version; a new rule arrives when you bump it.

版本与发布记录

@webority/repo-checks 共发布 140 个版本,首次发布于 2026/10/10;过去 12 个月发布了 140 个版本。

版本发布日期距今
0.119.0latest2026/11/03今天
0.118.02026/11/03今天
0.117.02026/11/03今天
0.116.02026/11/02今天
0.115.02026/11/021 天前
0.114.02026/11/021 天前

关于 @webority/repo-checks 的常见问题

@webority/repo-checks 是什么?

对webbority React门户网站、React Native应用程序和Razor站点的存储库检查:禁止的和必需的依赖项,仅限pnpm,确切的pin,共享的Biome预设,以及样式、标记和组件代码中的令牌使用。在推之前跑;现有的结果

如何安装 @webority/repo-checks?

在项目目录运行 npm install @webority/repo-checks,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 webority-repo-checks,可以用 npx webority-repo-checks 直接运行。

@webority/repo-checks 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/webority__repo-checks 是否存在。

@webority/repo-checks 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@webority/repo-checks 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=24.15 <25。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@webority/repo-checks 可以商用吗?

@webority/repo-checks 使用 SEE LICENSE IN LICENSE 许可。许可条款写在包内的独立文件中,请阅读该文件确认可否商用。以上为概括,不构成法律意见,请以许可原文为准。

@webority/repo-checks 还在维护吗?

最新版本 0.119.0 发布于 2026/11/03(今天);至今共发布 140 个版本,其中过去 12 个月发布了 140 个;首次发布于 2026/10/10。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。