Replies: 1 comment
-
ServicesThe "what"A service is a special kind of helper that maintains state (cache, mostly). Each service is in tight integration with Steiger core because of how completely different the rules of cache invalidation are. Services are written and maintained by Steiger, which means that plugin writers cannot provide their own services unless they make PRs to Steiger. A service is preconfigured for each FSD root separately to support monorepos. If we have flowchart TD
services ~~~ resolveImport
plugin ~~~ root[FSD root]
services -->|for example| resolveImport
steiger --->|needs to keep up-to-date| services
plugin -->|needs to use| services
plugin -->|has access to| root([FSD root])
root --->|wants preconfigured| resolveImport{{resolveImport}}
resolveImport <-->|know when to invalidate cache| steiger
The "where"Code-wise, services will be in the
The "how (to use)"Plugin authors use the services like so: // plugin/src/rule1.js
import { getServices } from "steiger";
import { createRule } from "@steiger/toolkit";
const rule1 = createRule({
check(root) {
const { resolveImport } = getServices(root);
// …
const resolvedPath = resolveImport(file1.path, "@/pages/home"); // "/home/project/src/pages/home/index.ts"
}
}); The "how (to write)"Steiger registers services as subscribers to the VFS and each service defines for itself what events it wants to act on. Steiger provides a unified way to access all services for each root — // steiger/src/services/manager.ts, rough concept
import resolveImport from "./resolveImport";
export function getServices(root: Folder) {
return {
get resolveImport() {
// initialize cache if necessary
return resolveImport.bind(caches[root.path]["resolveImport"])
}
}
} Each service is defined with something like this: // steiger/src/services/resolveImport.ts
export default function resolveImport(this: ResolveImportCache, pathA: string, pathB: string) {}
export function subscribe(fsUpdate, vfs) {
// initialize or update the cache or the tracked tsconfig
} |
Beta Was this translation helpful? Give feedback.
-
Issue #69 proposed to remove the Steiger-provided "context" object.
With this proposal, the meaning of context was redefined:
Following this change, we no longer have a way for plugin writers to tap into the knowledge of the linter core. A simple example of why this might be useful is caching information. Currently, the operations of resolving dependencies and extracting imports from a file are done independently by every rule, possibly, several times, if the linter is running in watch mode. This is inefficient, but most importantly, it puts the burden of optimization onto the plugin writers, which causes them to sacrifice developer experience. We strive for the best possible DX, so this should be avoided.
Provide solutions that would enable plugin writers to have convenient access to what the linter knows about the project. Here are the use cases that are on the radar right now:
Accurate import resolution requires finding the right
tsconfig.json
and resolving aliasesCurrently done with
paperwork
, it's a way to get a list of all dependencies of a particular fileFor example, if a rule wants to suggest a fix of creating an index file, it needs to know if it should use
.js
or.ts
(or something else entirely)A future feature, and something to keep in mind, is to let Steiger work with several roots simultaneously, yet independently:
Beta Was this translation helpful? Give feedback.
All reactions