taist 0.1.7 → 0.1.9

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
@@ -1,7 +1,7 @@
1
1
  # Taist - AI Test Runner
2
2
  ## Token-Optimized Testing Framework for AI-Assisted Development
3
3
 
4
- Version: 0.1.0 | January 2025 | [Technical Specification](./SPEC.md)
4
+ Version: 0.1.8 | January 2025 | [Technical Specification](./SPEC.md)
5
5
 
6
6
  ---
7
7
 
@@ -294,6 +294,33 @@ const service = new DynamicService();
294
294
  const traced = instrumentService(service, 'DynamicService');
295
295
  ```
296
296
 
297
+ #### Module-Level Instrumentation
298
+
299
+ When you have a module with multiple exported functions or classes, use `instrumentModule` to wrap all exports at once:
300
+
301
+ ```javascript
302
+ import { instrumentModule } from 'taist/instrument';
303
+ import * as orderServices from './services/order.js';
304
+
305
+ // Wrap all exports from the module
306
+ export const Order = instrumentModule(orderServices, 'Order');
307
+
308
+ // Now all functions in Order are traced:
309
+ // Order.createOrder() → traced as "Order.createOrder"
310
+ // Order.getOrder() → traced as "Order.getOrder"
311
+ // Order.updateOrder() → traced as "Order.updateOrder"
312
+ ```
313
+
314
+ This is particularly useful for:
315
+ - **GraphQL resolvers** - Instrument all resolver functions in a module
316
+ - **Service layers** - Wrap entire service modules without individual instrumentation
317
+ - **Utility modules** - Trace helper functions across a module
318
+
319
+ **How it works:**
320
+ - Functions are wrapped with context-aware tracing
321
+ - Classes are wrapped so new instances are automatically instrumented
322
+ - Non-function exports are passed through unchanged
323
+
297
324
  ---
298
325
 
299
326
  ## Test Integration
package/instrument.js CHANGED
@@ -46,7 +46,8 @@ import {
46
46
  instrumentDirectory,
47
47
  instrumentModules,
48
48
  wrapWithContext,
49
- instrumentClassWithContext
49
+ instrumentClassWithContext,
50
+ instrumentModule
50
51
  } from './lib/instrument-all.js';
51
52
 
52
53
  // Initialize global reporter for cross-process trace collection
@@ -277,6 +278,7 @@ export {
277
278
  instrumentAll,
278
279
  instrumentDirectory,
279
280
  instrumentModules,
281
+ instrumentModule,
280
282
  wrapWithContext,
281
283
  startTrace,
282
284
  getContext,
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Taist Rollup Plugin - Build-time instrumentation for bundled code
3
+ *
4
+ * Transforms source files during build to add tracing, BEFORE bundling
5
+ * collapses them into a single file. This enables deep tracing of internal
6
+ * functions within bundled applications.
7
+ *
8
+ * Usage:
9
+ * import taistPlugin from 'taist/rollup-plugin';
10
+ *
11
+ * export default {
12
+ * plugins: [
13
+ * taistPlugin({
14
+ * include: ['src/**\/*.js'],
15
+ * exclude: ['**\/*.test.js']
16
+ * })
17
+ * ]
18
+ * };
19
+ */
20
+
21
+ import { transformSource } from './transform.js';
22
+ import { shouldInstrument, matchGlob, loadConfig } from './config-loader.js';
23
+ import path from 'node:path';
24
+
25
+ /**
26
+ * Create a Taist Rollup plugin
27
+ * @param {Object} options - Plugin options
28
+ * @param {string[]} [options.include] - Glob patterns for files to instrument
29
+ * @param {string[]} [options.exclude] - Glob patterns for files to skip
30
+ * @param {boolean} [options.enabled] - Enable/disable plugin (default: true, or TAIST_ENABLED env)
31
+ * @returns {import('rollup').Plugin}
32
+ */
33
+ export function taistPlugin(options = {}) {
34
+ // Determine if enabled
35
+ const enabled = options.enabled ?? (process.env.TAIST_ENABLED !== 'false');
36
+
37
+ if (!enabled) {
38
+ return {
39
+ name: 'taist',
40
+ // No-op plugin when disabled
41
+ };
42
+ }
43
+
44
+ // Build config from options or load from file
45
+ let config;
46
+
47
+ return {
48
+ name: 'taist',
49
+
50
+ async buildStart() {
51
+ if (options.include || options.exclude) {
52
+ // Use provided options
53
+ config = {
54
+ include: options.include || ['**/*.js', '**/*.ts'],
55
+ exclude: options.exclude || ['**/node_modules/**', '**/*.test.*', '**/*.spec.*'],
56
+ };
57
+ } else {
58
+ // Load from .taistrc.json
59
+ config = await loadConfig();
60
+ if (config.include.length === 0) {
61
+ // Default to instrumenting src/ if no config
62
+ config.include = ['src/**/*.js', 'src/**/*.ts'];
63
+ }
64
+ }
65
+ },
66
+
67
+ transform(code, id) {
68
+ // Skip if no config yet
69
+ if (!config) {
70
+ return null;
71
+ }
72
+
73
+ // Skip node_modules
74
+ if (id.includes('node_modules')) {
75
+ return null;
76
+ }
77
+
78
+ // Skip non-JS/TS files
79
+ if (!id.match(/\.[jt]sx?$/)) {
80
+ return null;
81
+ }
82
+
83
+ // Get relative path for matching
84
+ const relativePath = path.relative(process.cwd(), id);
85
+
86
+ // Check include patterns
87
+ const included = config.include.some(pattern => matchGlob(relativePath, pattern));
88
+ if (!included) {
89
+ return null;
90
+ }
91
+
92
+ // Check exclude patterns
93
+ const excluded = config.exclude.some(pattern => matchGlob(relativePath, pattern));
94
+ if (excluded) {
95
+ return null;
96
+ }
97
+
98
+ try {
99
+ // Transform the source
100
+ const transformed = transformSource(code, {
101
+ filename: id,
102
+ useReporter: true,
103
+ // Use package paths - these should be externalized or bundled with the app
104
+ traceReporterPath: null, // Uses default 'taist/lib/trace-reporter.js'
105
+ traceContextPath: null, // Uses default 'taist/lib/trace-context.js'
106
+ });
107
+
108
+ return {
109
+ code: transformed,
110
+ map: null, // TODO: Add sourcemap support
111
+ };
112
+ } catch (err) {
113
+ this.warn(`Failed to transform ${relativePath}: ${err.message}`);
114
+ return null;
115
+ }
116
+ },
117
+ };
118
+ }
119
+
120
+ export default taistPlugin;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Taist Vite Plugin - Build-time instrumentation for bundled code
3
+ *
4
+ * Vite uses Rollup under the hood, so this re-exports the Rollup plugin.
5
+ *
6
+ * Usage:
7
+ * import taistPlugin from 'taist/vite-plugin';
8
+ *
9
+ * export default defineConfig({
10
+ * plugins: [
11
+ * taistPlugin({
12
+ * include: ['src/**\/*.js'],
13
+ * exclude: ['**\/*.test.js']
14
+ * })
15
+ * ]
16
+ * });
17
+ */
18
+
19
+ import { taistPlugin } from './rollup-plugin.js';
20
+
21
+ export { taistPlugin };
22
+ export default taistPlugin;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "taist",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "Token-Optimized Testing Framework for AI-Assisted Development",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -46,6 +46,14 @@
46
46
  "./trace-context": "./lib/trace-context.js",
47
47
  "./instrument-all": "./lib/instrument-all.js",
48
48
  "./config-loader": "./lib/config-loader.js",
49
+ "./rollup-plugin": {
50
+ "types": "./types/rollup-plugin.d.ts",
51
+ "default": "./lib/rollup-plugin.js"
52
+ },
53
+ "./vite-plugin": {
54
+ "types": "./types/vite-plugin.d.ts",
55
+ "default": "./lib/vite-plugin.js"
56
+ },
49
57
  "./lib/*": "./lib/*"
50
58
  },
51
59
  "scripts": {
@@ -199,6 +199,28 @@ export declare function instrumentModules(
199
199
  options?: InstrumentAllOptions
200
200
  ): Promise<Record<string, unknown>>;
201
201
 
202
+ /**
203
+ * Instrument all exports from a module object
204
+ *
205
+ * Wraps all function exports with context-aware tracing.
206
+ * Classes are wrapped so new instances are automatically instrumented.
207
+ *
208
+ * @param moduleExports Module exports object (e.g., from `import * as mod from './mod.js'`)
209
+ * @param moduleName Module name prefix for trace names
210
+ * @returns Object with same keys but instrumented values
211
+ *
212
+ * @example
213
+ * import { instrumentModule } from 'taist/instrument';
214
+ * import * as orderServices from './services/order.js';
215
+ *
216
+ * export const Order = instrumentModule(orderServices, 'Order');
217
+ * // All functions in Order will now be traced
218
+ */
219
+ export declare function instrumentModule<T extends Record<string, unknown>>(
220
+ moduleExports: T,
221
+ moduleName: string
222
+ ): T;
223
+
202
224
  /**
203
225
  * Wrap a function with trace context
204
226
  * @param fn Function to wrap
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Taist Rollup Plugin Type Definitions
3
+ */
4
+
5
+ import type { Plugin } from 'rollup';
6
+
7
+ /**
8
+ * Options for the Taist Rollup/Vite plugin
9
+ */
10
+ export interface TaistPluginOptions {
11
+ /**
12
+ * Glob patterns for files to instrument.
13
+ * If not provided, loads from .taistrc.json or defaults to ['src/**\/*.js', 'src/**\/*.ts']
14
+ */
15
+ include?: string[];
16
+
17
+ /**
18
+ * Glob patterns for files to skip.
19
+ * Defaults to ['**\/node_modules/**', '**\/*.test.*', '**\/*.spec.*']
20
+ */
21
+ exclude?: string[];
22
+
23
+ /**
24
+ * Enable/disable the plugin.
25
+ * Defaults to true, or respects TAIST_ENABLED environment variable.
26
+ */
27
+ enabled?: boolean;
28
+ }
29
+
30
+ /**
31
+ * Create a Taist Rollup plugin for build-time instrumentation.
32
+ *
33
+ * Transforms source files during build to add tracing, BEFORE bundling
34
+ * collapses them into a single file. This enables deep tracing of internal
35
+ * functions within bundled applications like Directus extensions.
36
+ *
37
+ * @param options - Plugin options
38
+ * @returns Rollup plugin
39
+ *
40
+ * @example
41
+ * // rollup.config.js
42
+ * import taistPlugin from 'taist/rollup-plugin';
43
+ *
44
+ * export default {
45
+ * input: 'src/index.js',
46
+ * output: { file: 'dist/bundle.js', format: 'es' },
47
+ * plugins: [
48
+ * taistPlugin({
49
+ * include: ['src/**\/*.js'],
50
+ * exclude: ['**\/*.test.js']
51
+ * })
52
+ * ]
53
+ * };
54
+ */
55
+ export function taistPlugin(options?: TaistPluginOptions): Plugin;
56
+
57
+ export default taistPlugin;
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Taist Vite Plugin Type Definitions
3
+ *
4
+ * Re-exports the Rollup plugin types since Vite uses Rollup internally.
5
+ */
6
+
7
+ import type { Plugin } from 'vite';
8
+ import type { TaistPluginOptions } from './rollup-plugin';
9
+
10
+ export type { TaistPluginOptions };
11
+
12
+ /**
13
+ * Create a Taist Vite plugin for build-time instrumentation.
14
+ *
15
+ * Transforms source files during build to add tracing, BEFORE bundling
16
+ * collapses them into a single file. This enables deep tracing of internal
17
+ * functions within bundled applications like Directus extensions.
18
+ *
19
+ * @param options - Plugin options
20
+ * @returns Vite plugin
21
+ *
22
+ * @example
23
+ * // vite.config.js
24
+ * import { defineConfig } from 'vite';
25
+ * import taistPlugin from 'taist/vite-plugin';
26
+ *
27
+ * export default defineConfig({
28
+ * plugins: [
29
+ * taistPlugin({
30
+ * include: ['src/**\/*.js'],
31
+ * exclude: ['**\/*.test.js']
32
+ * })
33
+ * ]
34
+ * });
35
+ */
36
+ export function taistPlugin(options?: TaistPluginOptions): Plugin;
37
+
38
+ export default taistPlugin;