@mochi-css/config 3.0.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -38,7 +38,7 @@ All Mochi-CSS integrations automatically load this file - you don't need to pass
38
38
  Identity helper that provides full type inference for your config file.
39
39
 
40
40
  ```typescript
41
- function defineConfig(config: MochiConfig): MochiConfig
41
+ function defineConfig(config: Partial<Config>): Partial<Config>
42
42
  ```
43
43
 
44
44
  ---
@@ -48,7 +48,7 @@ function defineConfig(config: MochiConfig): MochiConfig
48
48
  Finds and loads the nearest `mochi.config.*` file. Returns `{}` if no file is found.
49
49
 
50
50
  ```typescript
51
- async function loadConfig(cwd?: string): Promise<MochiConfig>
51
+ async function loadConfig(cwd?: string): Promise<Partial<Config>>
52
52
  ```
53
53
 
54
54
  Searched file names (in order): `mochi.config.mts`, `mochi.config.cts`, `mochi.config.ts`, `mochi.config.mjs`, `mochi.config.cjs`, `mochi.config.js`.
@@ -62,14 +62,15 @@ Runs all `MochiPlugin.onConfigResolved` hooks in order.
62
62
 
63
63
  ```typescript
64
64
  async function resolveConfig(
65
- fileConfig: MochiConfig,
66
- inlineOpts?: MochiConfig,
67
- defaults?: Partial<ResolvedConfig>,
68
- ): Promise<ResolvedConfig>
65
+ fileConfig: Partial<Config>,
66
+ inlineOpts?: Partial<Config>,
67
+ defaults?: Partial<Config>,
68
+ ): Promise<Config>
69
69
  ```
70
70
 
71
71
  **Merge behaviour:**
72
- - Arrays (`roots`, `extractors`, `esbuildPlugins`): file config + inline options concatenated, falling back to defaults
72
+
73
+ - Arrays (`roots`, `plugins`): file config + inline options concatenated, falling back to defaults
73
74
  - Scalar values (`splitCss`, `tmpDir`): inline options take precedence over file config, then defaults
74
75
  - Callbacks (`onDiagnostic`): both callbacks are called when both are provided
75
76
 
@@ -77,50 +78,60 @@ async function resolveConfig(
77
78
 
78
79
  ## Types
79
80
 
80
- ### `MochiConfig`
81
-
82
- The user-facing config. All fields are optional.
83
-
84
- | Field | Type | Description |
85
- |------------------|--------------------|-----------------------------------------------------------|
86
- | `roots` | `RootEntry[]` | Directories scanned for source files (default: `["src"]`) |
87
- | `extractors` | `StyleExtractor[]` | Style extractors - merged with defaults from integrations |
88
- | `splitCss` | `boolean` | Emit per-source-file CSS instead of one global file |
89
- | `onDiagnostic` | `OnDiagnostic` | Callback for warnings and non-fatal errors |
90
- | `esbuildPlugins` | `EsbuildPlugin[]` | esbuild plugins forwarded to the bundler |
91
- | `plugins` | `MochiPlugin[]` | Mochi plugins - run after config is resolved |
92
- | `tmpDir` | `string` | Manifest/styles output directory |
81
+ ### `Config`
93
82
 
94
- ### `ResolvedConfig`
83
+ The config shape. All fields are optional in `defineConfig`; `resolveConfig` fills required fields from defaults.
95
84
 
96
- Same as `MochiConfig` but with required fields and no `plugins` key. Produced by `resolveConfig`.
85
+ | Field | Type | Description |
86
+ | -------------- | --------------- | ------------------------------------------------------------- |
87
+ | `roots` | `RootEntry[]` | Directories scanned for source files (default: `["src"]`) |
88
+ | `splitCss` | `boolean` | Emit per-source-file CSS instead of one global file |
89
+ | `onDiagnostic` | `OnDiagnostic` | Callback for warnings and non-fatal errors |
90
+ | `plugins` | `MochiPlugin[]` | Mochi plugins — register stages, transforms, and emit hooks |
91
+ | `tmpDir` | `string` | Manifest/styles output directory |
92
+ | `debug` | `boolean` | Enable debug output |
97
93
 
98
94
  ### `MochiPlugin`
99
95
 
100
- Hook interface for extending the resolved config.
96
+ Hook interface for extending the build pipeline.
101
97
 
102
98
  ```typescript
103
99
  interface MochiPlugin {
104
100
  name: string
105
- onConfigResolved?: (config: ResolvedConfig) => Promise<ResolvedConfig> | ResolvedConfig
101
+ // Called during config resolution mutate or replace the config object.
102
+ onConfigResolved?(config: Config): Promise<Config> | Config
103
+ // Called after config is resolved — register stages, transforms, and emit hooks.
104
+ onLoad?(context: PluginContext): void
106
105
  }
107
106
  ```
108
107
 
108
+ ### `PluginContext`
109
+
110
+ Passed to `onLoad`. Each field is a collector that plugins call `register()` on.
111
+
112
+ | Field | Purpose |
113
+ |--------------------|-------------------------------------------------------------------|
114
+ | `stages` | Register analysis pipeline stages |
115
+ | `sourceTransforms` | Register `AstPostProcessor` hooks (run after analysis) |
116
+ | `emitHooks` | Register `EmitHook` hooks (run after evaluation) |
117
+ | `cleanup` | Register cleanup functions called at the end of each build |
118
+ | `filePreProcess` | Register source-level text transformations (used by Vite/Next) |
119
+ | `onDiagnostic` | Diagnostics callback from the resolved config |
120
+
109
121
  ---
110
122
 
111
123
  ## Writing a Plugin
112
124
 
113
125
  ```typescript
114
126
  import type { MochiPlugin } from "@mochi-css/config"
115
- import { myExtractor } from "./myExtractor"
116
127
 
117
128
  export const myPlugin: MochiPlugin = {
118
129
  name: "my-plugin",
119
- onConfigResolved(config) {
120
- return {
121
- ...config,
122
- extractors: [...config.extractors, myExtractor],
123
- }
130
+ onLoad(context) {
131
+ // Register an emit hook that writes a file after every build
132
+ context.emitHooks.register(async (_index, ctx) => {
133
+ ctx.emitChunk("my-output.txt", "hello from my-plugin")
134
+ })
124
135
  },
125
136
  }
126
137
  ```
@@ -134,3 +145,24 @@ export default defineConfig({
134
145
  plugins: [myPlugin],
135
146
  })
136
147
  ```
148
+
149
+ ---
150
+
151
+ ## `styledIdPlugin`
152
+
153
+ A built-in plugin that injects stable `s-` class IDs into every `styled()` call matched by the given extractors. This keeps class names stable across incremental builds.
154
+
155
+ ```typescript
156
+ import { styledIdPlugin } from "@mochi-css/config"
157
+ import { myExtractor } from "./myExtractor"
158
+
159
+ export default defineConfig({
160
+ plugins: [styledIdPlugin([myExtractor])],
161
+ })
162
+ ```
163
+
164
+ The plugin registers two hooks:
165
+ - A `filePreProcess` transformation that inserts stable IDs into the raw source (used by Vite/Next `transform` hooks).
166
+ - A `sourceTransforms` hook that injects the same IDs directly into the AST (used during CSS extraction).
167
+
168
+ It is idempotent — calls that already carry an `s-` ID are skipped.
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { AstPostProcessor, OnDiagnostic, OnDiagnostic as OnDiagnostic$1, RootEntry, RootEntry as RootEntry$1, StyleExtractor, StyleExtractor as StyleExtractor$1 } from "@mochi-css/builder";
1
+ import { AstPostProcessor, EmitHook, OnDiagnostic, OnDiagnostic as OnDiagnostic$1, RootEntry, RootEntry as RootEntry$1, StageDefinition, StyleExtractor } from "@mochi-css/builder";
2
2
 
3
3
  //#region src/merge.d.ts
4
4
  declare function mergeArrays<T>(a: T[] | undefined, b: T[] | undefined): T[] | undefined;
@@ -41,22 +41,54 @@ type FileTransformData = {
41
41
  filter?: string;
42
42
  };
43
43
  type FileTransformationHookProvider = TransformationHookProvider<string, [FileTransformOptions], FileTransformData>;
44
- interface AnalysisTransformHookProvider {
44
+ interface SourceTransformHookProvider {
45
45
  register(hook: AstPostProcessor): void;
46
46
  }
47
- declare class AnalysisHookCollector implements AnalysisTransformHookProvider {
47
+ interface StageHookProvider {
48
+ register(stage: StageDefinition<any[], any>): void;
49
+ }
50
+ interface EmitHookProvider {
51
+ register(hook: EmitHook): void;
52
+ }
53
+ interface CleanupHookProvider {
54
+ register(fn: () => void): void;
55
+ }
56
+ declare class SourceTransformCollector implements SourceTransformHookProvider {
48
57
  private readonly hooks;
49
58
  register(hook: AstPostProcessor): void;
50
- getHooks(): AstPostProcessor[];
59
+ getAll(): AstPostProcessor[];
60
+ }
61
+ declare class StageCollector implements StageHookProvider {
62
+ private readonly stageList;
63
+ register(stage: StageDefinition<any[], any>): void;
64
+ getAll(): readonly StageDefinition<any[], any>[];
65
+ }
66
+ declare class EmitHookCollector implements EmitHookProvider {
67
+ private readonly hooks;
68
+ register(hook: EmitHook): void;
69
+ getAll(): EmitHook[];
70
+ }
71
+ declare class CleanupCollector implements CleanupHookProvider {
72
+ private readonly fns;
73
+ register(fn: () => void): void;
74
+ runAll(): void;
51
75
  }
52
76
  interface PluginContext {
53
- readonly sourceTransform: FileTransformationHookProvider;
54
- readonly analysisTransform: AnalysisTransformHookProvider;
77
+ readonly filePreProcess: FileTransformationHookProvider;
78
+ readonly sourceTransforms: SourceTransformHookProvider;
79
+ readonly stages: StageHookProvider;
80
+ readonly emitHooks: EmitHookProvider;
81
+ readonly cleanup: CleanupHookProvider;
82
+ readonly onDiagnostic: OnDiagnostic$1;
55
83
  }
56
84
  declare class FullContext implements PluginContext {
57
- readonly sourceTransform: FilteredTransformationPipeline<string, FileTransformData, [FileTransformOptions]>;
58
- readonly analysisTransform: AnalysisHookCollector;
59
- getAnalysisHooks(): AstPostProcessor[];
85
+ readonly filePreProcess: FilteredTransformationPipeline<string, FileTransformData, [FileTransformOptions]>;
86
+ readonly sourceTransforms: SourceTransformCollector;
87
+ readonly stages: StageCollector;
88
+ readonly emitHooks: EmitHookCollector;
89
+ readonly cleanup: CleanupCollector;
90
+ readonly onDiagnostic: OnDiagnostic$1;
91
+ constructor(onDiagnostic: OnDiagnostic$1);
60
92
  }
61
93
  //#endregion
62
94
  //#region src/plugin/Plugin.d.ts
@@ -69,7 +101,6 @@ interface Plugin<Config$1 extends object> {
69
101
  //#region src/config/index.d.ts
70
102
  interface Config {
71
103
  roots: RootEntry$1[];
72
- extractors: StyleExtractor$1[];
73
104
  splitCss: boolean;
74
105
  onDiagnostic?: OnDiagnostic$1;
75
106
  plugins: Plugin<Config>[];
@@ -83,11 +114,13 @@ declare function loadConfig(cwd?: string): Promise<Partial<Config>>;
83
114
  //#endregion
84
115
  //#region src/styledIdPlugin.d.ts
85
116
  /**
86
- * Returns a MochiPlugin that injects stable `s-` class IDs into every `styled()` call.
87
- * - Registers a `sourceTransform` for runtime source injection (Vite/Next `transform` hook).
88
- * - Registers an `analysisTransform` for CSS extraction via direct AST mutation.
117
+ * Returns a MochiPlugin that injects stable `s-` class IDs into every call expression
118
+ * matched by the given extractors.
119
+ * - Registers a `filePreProcess` transformation for runtime source injection (Vite/Next `transform` hook).
120
+ * - Registers a `sourceTransforms` hook for CSS extraction via direct AST mutation,
121
+ * using data from the extractor pipeline stages (`extractedCallExpressions`).
89
122
  */
90
- declare function styledIdPlugin(): MochiPlugin;
123
+ declare function styledIdPlugin(extractors: StyleExtractor[]): MochiPlugin;
91
124
  //#endregion
92
- export { type AnalysisTransformHookProvider, Config, FullContext, MochiPlugin, type OnDiagnostic, type PluginContext, type RootEntry, type StyleExtractor, type TransformationHookProvider, TransformationPipeline, type TransformationUser, defineConfig, loadConfig, mergeArrays, mergeCallbacks, resolveConfig, styledIdPlugin };
125
+ export { type CleanupHookProvider, Config, type EmitHookProvider, FullContext, MochiPlugin, type OnDiagnostic, type PluginContext, type RootEntry, type SourceTransformHookProvider, type StageHookProvider, type TransformationHookProvider, TransformationPipeline, type TransformationUser, defineConfig, loadConfig, mergeArrays, mergeCallbacks, resolveConfig, styledIdPlugin };
93
126
  //# sourceMappingURL=index.d.mts.map
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { AstPostProcessor, OnDiagnostic, OnDiagnostic as OnDiagnostic$1, RootEntry, RootEntry as RootEntry$1, StyleExtractor, StyleExtractor as StyleExtractor$1 } from "@mochi-css/builder";
1
+ import { AstPostProcessor, EmitHook, OnDiagnostic, OnDiagnostic as OnDiagnostic$1, RootEntry, RootEntry as RootEntry$1, StageDefinition, StyleExtractor } from "@mochi-css/builder";
2
2
 
3
3
  //#region src/merge.d.ts
4
4
  declare function mergeArrays<T>(a: T[] | undefined, b: T[] | undefined): T[] | undefined;
@@ -41,22 +41,54 @@ type FileTransformData = {
41
41
  filter?: string;
42
42
  };
43
43
  type FileTransformationHookProvider = TransformationHookProvider<string, [FileTransformOptions], FileTransformData>;
44
- interface AnalysisTransformHookProvider {
44
+ interface SourceTransformHookProvider {
45
45
  register(hook: AstPostProcessor): void;
46
46
  }
47
- declare class AnalysisHookCollector implements AnalysisTransformHookProvider {
47
+ interface StageHookProvider {
48
+ register(stage: StageDefinition<any[], any>): void;
49
+ }
50
+ interface EmitHookProvider {
51
+ register(hook: EmitHook): void;
52
+ }
53
+ interface CleanupHookProvider {
54
+ register(fn: () => void): void;
55
+ }
56
+ declare class SourceTransformCollector implements SourceTransformHookProvider {
48
57
  private readonly hooks;
49
58
  register(hook: AstPostProcessor): void;
50
- getHooks(): AstPostProcessor[];
59
+ getAll(): AstPostProcessor[];
60
+ }
61
+ declare class StageCollector implements StageHookProvider {
62
+ private readonly stageList;
63
+ register(stage: StageDefinition<any[], any>): void;
64
+ getAll(): readonly StageDefinition<any[], any>[];
65
+ }
66
+ declare class EmitHookCollector implements EmitHookProvider {
67
+ private readonly hooks;
68
+ register(hook: EmitHook): void;
69
+ getAll(): EmitHook[];
70
+ }
71
+ declare class CleanupCollector implements CleanupHookProvider {
72
+ private readonly fns;
73
+ register(fn: () => void): void;
74
+ runAll(): void;
51
75
  }
52
76
  interface PluginContext {
53
- readonly sourceTransform: FileTransformationHookProvider;
54
- readonly analysisTransform: AnalysisTransformHookProvider;
77
+ readonly filePreProcess: FileTransformationHookProvider;
78
+ readonly sourceTransforms: SourceTransformHookProvider;
79
+ readonly stages: StageHookProvider;
80
+ readonly emitHooks: EmitHookProvider;
81
+ readonly cleanup: CleanupHookProvider;
82
+ readonly onDiagnostic: OnDiagnostic$1;
55
83
  }
56
84
  declare class FullContext implements PluginContext {
57
- readonly sourceTransform: FilteredTransformationPipeline<string, FileTransformData, [FileTransformOptions]>;
58
- readonly analysisTransform: AnalysisHookCollector;
59
- getAnalysisHooks(): AstPostProcessor[];
85
+ readonly filePreProcess: FilteredTransformationPipeline<string, FileTransformData, [FileTransformOptions]>;
86
+ readonly sourceTransforms: SourceTransformCollector;
87
+ readonly stages: StageCollector;
88
+ readonly emitHooks: EmitHookCollector;
89
+ readonly cleanup: CleanupCollector;
90
+ readonly onDiagnostic: OnDiagnostic$1;
91
+ constructor(onDiagnostic: OnDiagnostic$1);
60
92
  }
61
93
  //#endregion
62
94
  //#region src/plugin/Plugin.d.ts
@@ -69,7 +101,6 @@ interface Plugin<Config$1 extends object> {
69
101
  //#region src/config/index.d.ts
70
102
  interface Config {
71
103
  roots: RootEntry$1[];
72
- extractors: StyleExtractor$1[];
73
104
  splitCss: boolean;
74
105
  onDiagnostic?: OnDiagnostic$1;
75
106
  plugins: Plugin<Config>[];
@@ -83,11 +114,13 @@ declare function loadConfig(cwd?: string): Promise<Partial<Config>>;
83
114
  //#endregion
84
115
  //#region src/styledIdPlugin.d.ts
85
116
  /**
86
- * Returns a MochiPlugin that injects stable `s-` class IDs into every `styled()` call.
87
- * - Registers a `sourceTransform` for runtime source injection (Vite/Next `transform` hook).
88
- * - Registers an `analysisTransform` for CSS extraction via direct AST mutation.
117
+ * Returns a MochiPlugin that injects stable `s-` class IDs into every call expression
118
+ * matched by the given extractors.
119
+ * - Registers a `filePreProcess` transformation for runtime source injection (Vite/Next `transform` hook).
120
+ * - Registers a `sourceTransforms` hook for CSS extraction via direct AST mutation,
121
+ * using data from the extractor pipeline stages (`extractedCallExpressions`).
89
122
  */
90
- declare function styledIdPlugin(): MochiPlugin;
123
+ declare function styledIdPlugin(extractors: StyleExtractor[]): MochiPlugin;
91
124
  //#endregion
92
- export { type AnalysisTransformHookProvider, Config, FullContext, MochiPlugin, type OnDiagnostic, type PluginContext, type RootEntry, type StyleExtractor, type TransformationHookProvider, TransformationPipeline, type TransformationUser, defineConfig, loadConfig, mergeArrays, mergeCallbacks, resolveConfig, styledIdPlugin };
125
+ export { type CleanupHookProvider, Config, type EmitHookProvider, FullContext, MochiPlugin, type OnDiagnostic, type PluginContext, type RootEntry, type SourceTransformHookProvider, type StageHookProvider, type TransformationHookProvider, TransformationPipeline, type TransformationUser, defineConfig, loadConfig, mergeArrays, mergeCallbacks, resolveConfig, styledIdPlugin };
93
126
  //# sourceMappingURL=index.d.ts.map