@mikofia/xia-config-types
v0.1.0
Published
TypeScript types for Mikofia Xia configuration files and custom rules
Maintainers
Readme
@mikofia/xia-config-types
TypeScript type definitions for Mikofia, a declarative, expressive file system linter.
Installation
npm install --save-dev @mikofia/xia-config-typesor
pnpm add -D @mikofia/xia-config-typesor
yarn add -D @mikofia/xia-config-typesUsage
TypeScript Configuration Files
// mikofia.config.ts
import type { Config } from '@mikofia/xia-config-types';
export default {
ignore: ['node_modules', 'dist'],
nodes: [
{
path: 'src',
kind: 'directory',
existence: 'required',
children: [
{ path: 'index.ts', kind: 'file', existence: 'required' }
]
}
]
} satisfies Config;JavaScript Configuration Files (with JSDoc)
// mikofia.config.js
// @ts-check
/// <reference types="@mikofia/xia-config-types" />
/** @type {import('@mikofia/xia-config-types').Config} */
const config = {
ignore: ['node_modules', 'dist'],
nodes: [
{
path: 'src',
kind: 'directory',
existence: 'required',
children: [
{ path: 'index.js', kind: 'file', existence: 'required' }
]
}
]
};
export default config;Custom Rules
// mikofia.config.ts
import type { Config, RuleFunction } from '@mikofia/xia-config-types';
const checkNamingConvention: RuleFunction = async (ctx) => {
if (!ctx.name.match(/^[a-z0-9-]+$/)) {
return {
type: 'fail',
violation: {
key: 'invalid-naming',
message: `Invalid name: ${ctx.name}. Use lowercase, numbers, and hyphens only.`
}
};
}
return { type: 'pass' };
};
const validatePackageJson: RuleFunction = async (ctx) => {
if (ctx.name !== 'package.json') {
return { type: 'skip', reason: 'Not a package.json file' };
}
const content = await ctx.fs.readJson(ctx.path);
const pkg = content as Record<string, unknown>;
if (!pkg.name || !pkg.version) {
return {
type: 'fail',
violation: {
key: 'missing-required-fields',
message: "package.json must have 'name' and 'version' fields"
}
};
}
return { type: 'pass' };
};
export default {
nodes: [
{
path: 'package.json',
kind: 'file',
existence: 'required',
rules: [validatePackageJson]
},
{
path: 'src',
kind: 'directory',
existence: 'required',
rules: [checkNamingConvention]
}
]
} satisfies Config;Type Definitions
Config
The main configuration object for Mikofia.
interface Config {
ignore?: string[];
nodes: Node[];
}Node
A node in the file structure tree, representing a file or directory.
interface Node {
path: string;
existence?: Existence;
kind?: NodeKind;
children?: Node[];
strict?: boolean | null;
ignore?: string[];
rules?: RuleFunction[];
}Existence
Specifies whether a file or directory must exist, may exist, or must not exist.
type Existence = "required" | "optional" | "absent";"required": The item must exist"optional": The item may or may not exist (default)"absent": The item must not exist
NodeKind
Specifies the expected type of a filesystem item.
type NodeKind = "file" | "directory" | "any";"file": Must be a file"directory": Must be a directory"any": Can be either (default)
strict Field Behavior
The strict field controls whether a directory allows only explicitly listed children.
strict?: boolean | null;true: Strict mode enabled - only listed children are allowedfalse: Strict mode disabled - unlisted files/directories are allowednullorundefined: Automatically defaults totrueifchildrenare defined,falseotherwise
Important: If you define children for a directory, strict mode will be automatically enabled unless you explicitly set strict: false.
Example:
{
path: 'src',
kind: 'directory',
children: [
{ path: 'index.ts', kind: 'file' }
]
// strict is implicitly true - only index.ts is allowed in src/
}
{
path: 'src',
kind: 'directory',
strict: false, // explicitly disable strict mode
children: [
{ path: 'index.ts', kind: 'file' }
]
// a file named index.ts is allowed, but other files are also allowed
}RuleFunction
Custom validation rule function.
type RuleFunction = (ctx: EvaluationContext) => RuleResult | Promise<RuleResult>;EvaluationContext
Context provided to custom validation rules.
interface EvaluationContext {
path: string;
name: string;
extension?: string;
parent?: ParentInfo;
siblings: SiblingInfo[];
fs: {
readFile(path: string): Promise<string>;
readJson(path: string): Promise<unknown>;
exists(path: string): boolean;
};
}RuleResult
Result of a validation rule check.
type RuleResult =
| { type: "pass" }
| { type: "fail"; violation: { key: string; message: string; path?: string } }
| { type: "skip"; reason: string };Violation Fields:
key: Unique identifier for the violation typemessage: Human-readable error messagepath(optional): Custom path to report the violation at. If not specified, the path from the evaluation context will be used.
Example with custom path:
const validateImports: RuleFunction = async (ctx) => {
const content = await ctx.fs.readFile(ctx.path);
const match = content.match(/import .+ from ['"](.+)['"]/);
if (match && match[1].startsWith('../../../')) {
return {
type: 'fail',
violation: {
key: 'deep-import',
message: 'Avoid imports with more than 2 parent directory references',
path: ctx.path // Explicitly specify which file has the violation
}
};
}
return { type: 'pass' };
};License
MIT
Related
- Mikofia - Declarative, Expressive file system linter
