schemantic 0.3.0 → 0.4.1

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.
Files changed (124) hide show
  1. package/CHANGELOG.md +204 -174
  2. package/LICENSE +21 -21
  3. package/README.md +88 -830
  4. package/dist/cli/index.d.ts +4 -1
  5. package/dist/cli/index.d.ts.map +1 -1
  6. package/dist/cli/index.js +185 -61
  7. package/dist/cli/index.js.map +1 -1
  8. package/dist/core/configuration.d.ts +6 -0
  9. package/dist/core/configuration.d.ts.map +1 -0
  10. package/dist/core/configuration.js +64 -0
  11. package/dist/core/configuration.js.map +1 -0
  12. package/dist/core/index.d.ts +1 -0
  13. package/dist/core/index.d.ts.map +1 -1
  14. package/dist/core/index.js +1 -0
  15. package/dist/core/index.js.map +1 -1
  16. package/dist/core/output-writer.d.ts +7 -0
  17. package/dist/core/output-writer.d.ts.map +1 -0
  18. package/dist/core/output-writer.js +255 -0
  19. package/dist/core/output-writer.js.map +1 -0
  20. package/dist/core/schemantic.d.ts +8 -2
  21. package/dist/core/schemantic.d.ts.map +1 -1
  22. package/dist/core/schemantic.js +196 -71
  23. package/dist/core/schemantic.js.map +1 -1
  24. package/dist/generators/api-client-generator.d.ts +10 -20
  25. package/dist/generators/api-client-generator.d.ts.map +1 -1
  26. package/dist/generators/api-client-generator.js +374 -424
  27. package/dist/generators/api-client-generator.js.map +1 -1
  28. package/dist/generators/base.d.ts.map +1 -1
  29. package/dist/generators/base.js +7 -25
  30. package/dist/generators/base.js.map +1 -1
  31. package/dist/generators/enum-generator.d.ts.map +1 -1
  32. package/dist/generators/enum-generator.js +30 -3
  33. package/dist/generators/enum-generator.js.map +1 -1
  34. package/dist/generators/hook-generator.d.ts +3 -17
  35. package/dist/generators/hook-generator.d.ts.map +1 -1
  36. package/dist/generators/hook-generator.js +51 -445
  37. package/dist/generators/hook-generator.js.map +1 -1
  38. package/dist/generators/naming.d.ts +10 -0
  39. package/dist/generators/naming.d.ts.map +1 -0
  40. package/dist/generators/naming.js +331 -0
  41. package/dist/generators/naming.js.map +1 -0
  42. package/dist/generators/object-generator.d.ts +0 -4
  43. package/dist/generators/object-generator.d.ts.map +1 -1
  44. package/dist/generators/object-generator.js +13 -101
  45. package/dist/generators/object-generator.js.map +1 -1
  46. package/dist/generators/primitive-generator.d.ts +1 -13
  47. package/dist/generators/primitive-generator.d.ts.map +1 -1
  48. package/dist/generators/primitive-generator.js +11 -76
  49. package/dist/generators/primitive-generator.js.map +1 -1
  50. package/dist/generators/projections.d.ts +10 -0
  51. package/dist/generators/projections.d.ts.map +1 -0
  52. package/dist/generators/projections.js +65 -0
  53. package/dist/generators/projections.js.map +1 -0
  54. package/dist/generators/schema-type.d.ts +23 -0
  55. package/dist/generators/schema-type.d.ts.map +1 -0
  56. package/dist/generators/schema-type.js +233 -0
  57. package/dist/generators/schema-type.js.map +1 -0
  58. package/dist/parsers/base.d.ts +2 -0
  59. package/dist/parsers/base.d.ts.map +1 -1
  60. package/dist/parsers/base.js +12 -2
  61. package/dist/parsers/base.js.map +1 -1
  62. package/dist/parsers/factory.d.ts.map +1 -1
  63. package/dist/parsers/factory.js +2 -1
  64. package/dist/parsers/factory.js.map +1 -1
  65. package/dist/parsers/openapi.d.ts +4 -0
  66. package/dist/parsers/openapi.d.ts.map +1 -1
  67. package/dist/parsers/openapi.js +107 -20
  68. package/dist/parsers/openapi.js.map +1 -1
  69. package/dist/plugins/branded-types.d.ts.map +1 -1
  70. package/dist/plugins/branded-types.js +231 -365
  71. package/dist/plugins/branded-types.js.map +1 -1
  72. package/dist/plugins/builtin.d.ts.map +1 -1
  73. package/dist/plugins/builtin.js +6 -141
  74. package/dist/plugins/builtin.js.map +1 -1
  75. package/dist/plugins/index.d.ts +4 -0
  76. package/dist/plugins/index.d.ts.map +1 -1
  77. package/dist/plugins/index.js +17 -0
  78. package/dist/plugins/index.js.map +1 -1
  79. package/dist/plugins/loader.d.ts +5 -1
  80. package/dist/plugins/loader.d.ts.map +1 -1
  81. package/dist/plugins/loader.js +42 -5
  82. package/dist/plugins/loader.js.map +1 -1
  83. package/dist/plugins/manager.d.ts.map +1 -1
  84. package/dist/plugins/manager.js +7 -7
  85. package/dist/plugins/manager.js.map +1 -1
  86. package/dist/plugins/performance-monitoring.d.ts +31 -1
  87. package/dist/plugins/performance-monitoring.d.ts.map +1 -1
  88. package/dist/plugins/performance-monitoring.js +146 -207
  89. package/dist/plugins/performance-monitoring.js.map +1 -1
  90. package/dist/plugins/request-deduplication.d.ts.map +1 -1
  91. package/dist/plugins/request-deduplication.js +151 -586
  92. package/dist/plugins/request-deduplication.js.map +1 -1
  93. package/dist/plugins/zod-validation.d.ts +23 -15
  94. package/dist/plugins/zod-validation.d.ts.map +1 -1
  95. package/dist/plugins/zod-validation.js +392 -268
  96. package/dist/plugins/zod-validation.js.map +1 -1
  97. package/dist/types/core.d.ts +20 -3
  98. package/dist/types/core.d.ts.map +1 -1
  99. package/dist/types/core.js +2 -0
  100. package/dist/types/core.js.map +1 -1
  101. package/dist/types/openapi.d.ts +14 -1
  102. package/dist/types/openapi.d.ts.map +1 -1
  103. package/docs/ADVANCED_PLUGINS_IMPLEMENTATION.md +24 -355
  104. package/docs/ADVANCED_PLUGIN_DEVELOPMENT.md +33 -309
  105. package/docs/API.md +80 -601
  106. package/docs/AUDIT.md +49 -0
  107. package/docs/CONFIGURATION.md +81 -715
  108. package/docs/FASTAPI_TUTORIAL.md +109 -1497
  109. package/docs/NAMING_MIGRATION.md +59 -0
  110. package/docs/PLUGINS.md +49 -687
  111. package/docs/PLUGIN_DEVELOPMENT.md +53 -720
  112. package/docs/REAUDIT.md +399 -0
  113. package/docs/RELEASING.md +88 -0
  114. package/docs/REMEDIATION.md +58 -0
  115. package/docs/superpowers/plans/2026-10-10-audit-remediation.md +113 -0
  116. package/package.json +114 -95
  117. package/dist/__tests__/setup.d.ts +0 -6
  118. package/dist/__tests__/setup.d.ts.map +0 -1
  119. package/dist/__tests__/setup.js +0 -30
  120. package/dist/__tests__/setup.js.map +0 -1
  121. package/dist/__tests__/test-config.d.ts +0 -36
  122. package/dist/__tests__/test-config.d.ts.map +0 -1
  123. package/dist/__tests__/test-config.js +0 -562
  124. package/dist/__tests__/test-config.js.map +0 -1
package/docs/PLUGINS.md CHANGED
@@ -1,687 +1,49 @@
1
- # Plugin Development Guide
2
-
3
- This guide explains how to create custom plugins for Schemantic to extend its functionality.
4
-
5
- ## Plugin Overview
6
-
7
- Plugins in Schemantic allow you to:
8
-
9
- - Transform schemas before type generation
10
- - Modify generated types and API clients
11
- - Add custom type generators
12
- - Add custom client generators
13
- - Execute code at various stages of the generation process
14
-
15
- ## Plugin Interface
16
-
17
- All plugins must implement the `SchemanticPlugin` interface:
18
-
19
- ```typescript
20
- interface SchemanticPlugin {
21
- name: string;
22
- version: string;
23
- description: string;
24
-
25
- // Lifecycle hooks
26
- beforeGeneration?(context: GenerationContext): Promise<void> | void;
27
- afterGeneration?(
28
- context: GenerationContext,
29
- result: GenerationResult
30
- ): Promise<void> | void;
31
-
32
- // Type generation hooks
33
- beforeTypeGeneration?(
34
- typeName: string,
35
- schema: ResolvedSchema,
36
- context: GenerationContext
37
- ): Promise<void> | void;
38
- afterTypeGeneration?(
39
- typeName: string,
40
- generatedType: GeneratedType,
41
- context: GenerationContext
42
- ): Promise<void> | void;
43
-
44
- // Client generation hooks
45
- beforeClientGeneration?(context: GenerationContext): Promise<void> | void;
46
- afterClientGeneration?(
47
- generatedClient: GeneratedApiClient,
48
- context: GenerationContext
49
- ): Promise<void> | void;
50
-
51
- // Schema transformation hooks
52
- transformSchema?(
53
- schema: ResolvedSchema,
54
- context: GenerationContext
55
- ): ResolvedSchema;
56
-
57
- // Custom generators
58
- customTypeGenerators?: Record<
59
- string,
60
- (schema: ResolvedSchema, context: GenerationContext) => GeneratedType
61
- >;
62
- customClientGenerators?: Record<
63
- string,
64
- (context: GenerationContext) => GeneratedApiClient
65
- >;
66
- }
67
- ```
68
-
69
- ## Basic Plugin Structure
70
-
71
- Here's a minimal plugin:
72
-
73
- ```typescript
74
- import { SchemanticPlugin, GenerationContext, GeneratedType } from "schemantic";
75
-
76
- const myPlugin: SchemanticPlugin = {
77
- name: "my-plugin",
78
- version: "1.0.0",
79
- description: "My custom plugin",
80
-
81
- beforeGeneration: async (context: GenerationContext) => {
82
- console.log("Starting generation...");
83
- },
84
-
85
- afterGeneration: async (context: GenerationContext, result: any) => {
86
- console.log("Generation completed!");
87
- },
88
- };
89
- ```
90
-
91
- ## Plugin Hooks
92
-
93
- ### Lifecycle Hooks
94
-
95
- #### `beforeGeneration`
96
-
97
- Called before the generation process starts. Use this to:
98
-
99
- - Validate configuration
100
- - Set up plugin-specific state
101
- - Modify the generation context
102
-
103
- ```typescript
104
- beforeGeneration: async (context: GenerationContext) => {
105
- // Validate configuration
106
- if (!context.config.customOption) {
107
- throw new Error('Custom option is required');
108
- }
109
-
110
- // Set up plugin state
111
- context.pluginState = { myData: 'value' };
112
- },
113
- ```
114
-
115
- #### `afterGeneration`
116
-
117
- Called after the generation process completes. Use this to:
118
-
119
- - Clean up resources
120
- - Generate additional files
121
- - Post-process results
122
-
123
- ```typescript
124
- afterGeneration: async (context: GenerationContext, result: any) => {
125
- // Generate additional files
126
- if (result.success) {
127
- await generateAdditionalFiles(context);
128
- }
129
-
130
- // Clean up
131
- delete context.pluginState;
132
- },
133
- ```
134
-
135
- ---
136
-
137
- Note: The `react-hooks` built-in plugin is temporarily disabled in the default plugin lists due to known generation issues that can corrupt output for some schemas. To re-enable it for a specific project, add `{ name: 'react-hooks', enabled: true }` to your `plugins` array in `schemantic.config.*`, and run the generator on a small sample schema first to validate output.
138
-
139
- ### Type Generation Hooks
140
-
141
- #### `beforeTypeGeneration`
142
-
143
- Called before generating a specific type. Use this to:
144
-
145
- - Transform the schema
146
- - Add metadata
147
- - Skip generation for certain types
148
-
149
- ```typescript
150
- beforeTypeGeneration: async (typeName: string, schema: ResolvedSchema, context: GenerationContext) => {
151
- // Add custom metadata
152
- schema._customMetadata = { processed: true };
153
-
154
- // Skip certain types
155
- if (typeName.includes('Internal')) {
156
- return;
157
- }
158
- },
159
- ```
160
-
161
- #### `afterTypeGeneration`
162
-
163
- Called after generating a specific type. Use this to:
164
-
165
- - Modify the generated type content
166
- - Add imports
167
- - Post-process the type
168
-
169
- ```typescript
170
- afterTypeGeneration: async (typeName: string, generatedType: GeneratedType, context: GenerationContext) => {
171
- // Add custom imports
172
- generatedType.content = `import { CustomType } from './custom';\n\n${generatedType.content}`;
173
-
174
- // Add custom decorators
175
- if (generatedType.isInterface) {
176
- generatedType.content = generatedType.content.replace(
177
- /export interface (\w+)/g,
178
- '@CustomDecorator\nexport interface $1'
179
- );
180
- }
181
- },
182
- ```
183
-
184
- ### Client Generation Hooks
185
-
186
- #### `beforeClientGeneration`
187
-
188
- Called before generating API clients. Use this to:
189
-
190
- - Set up client-specific configuration
191
- - Modify the generation context
192
-
193
- ```typescript
194
- beforeClientGeneration: async (context: GenerationContext) => {
195
- // Add custom configuration
196
- context.clientConfig = {
197
- baseUrl: 'https://api.example.com',
198
- timeout: 30000,
199
- };
200
- },
201
- ```
202
-
203
- #### `afterClientGeneration`
204
-
205
- Called after generating API clients. Use this to:
206
-
207
- - Modify the generated client
208
- - Add custom methods
209
- - Post-process the client
210
-
211
- ```typescript
212
- afterClientGeneration: async (generatedClient: GeneratedApiClient, context: GenerationContext) => {
213
- // Add custom methods
214
- const customMethods = `
215
- async customMethod(): Promise<string> {
216
- return 'custom result';
217
- }
218
- `;
219
-
220
- generatedClient.content = generatedClient.content.replace(
221
- /}\s*$/,
222
- `${customMethods}\n}`
223
- );
224
- },
225
- ```
226
-
227
- ### Schema Transformation
228
-
229
- #### `transformSchema`
230
-
231
- Transform schemas before type generation. Use this to:
232
-
233
- - Add custom properties
234
- - Modify type information
235
- - Standardize schema format
236
-
237
- ```typescript
238
- transformSchema: (schema: ResolvedSchema, context: GenerationContext): ResolvedSchema => {
239
- // Add custom properties
240
- if (schema.properties) {
241
- for (const [propName, propSchema] of Object.entries(schema.properties)) {
242
- if (typeof propSchema === 'object' && propSchema !== null) {
243
- // Add custom metadata
244
- propSchema._customProperty = true;
245
-
246
- // Transform specific types
247
- if (propSchema.format === 'uuid') {
248
- propSchema._customType = 'CustomUuid';
249
- }
250
- }
251
- }
252
- }
253
-
254
- return schema;
255
- },
256
- ```
257
-
258
- ## Custom Generators
259
-
260
- ### Custom Type Generators
261
-
262
- Add custom type generators for specific schema types:
263
-
264
- ```typescript
265
- customTypeGenerators: {
266
- 'custom-type': (schema: ResolvedSchema, context: GenerationContext): GeneratedType => {
267
- return {
268
- name: 'CustomType',
269
- content: `export type CustomType = string;`,
270
- dependencies: [],
271
- exports: ['CustomType'],
272
- isInterface: false,
273
- isEnum: false,
274
- isUnion: false,
275
- sourceSchema: schema,
276
- };
277
- },
278
-
279
- 'date-time': (schema: ResolvedSchema, context: GenerationContext): GeneratedType => {
280
- return {
281
- name: 'DateTime',
282
- content: `export type DateTime = string; // ISO 8601 format`,
283
- dependencies: [],
284
- exports: ['DateTime'],
285
- isInterface: false,
286
- isEnum: false,
287
- isUnion: false,
288
- sourceSchema: schema,
289
- };
290
- },
291
- },
292
- ```
293
-
294
- ### Custom Client Generators
295
-
296
- Add custom client generators:
297
-
298
- ```typescript
299
- customClientGenerators: {
300
- 'react-query': (context: GenerationContext): GeneratedApiClient => {
301
- const hooks = generateReactQueryHooks(context);
302
-
303
- return {
304
- name: 'ReactQueryHooks',
305
- content: hooks,
306
- dependencies: ['react-query'],
307
- exports: ['useApiHooks'],
308
- endpoints: [],
309
- };
310
- },
311
-
312
- 'axios': (context: GenerationContext): GeneratedApiClient => {
313
- const client = generateAxiosClient(context);
314
-
315
- return {
316
- name: 'AxiosClient',
317
- content: client,
318
- dependencies: ['axios'],
319
- exports: ['AxiosApiClient'],
320
- endpoints: [],
321
- };
322
- },
323
- },
324
- ```
325
-
326
- ## Plugin Examples
327
-
328
- ### JSDoc Plugin
329
-
330
- Adds JSDoc comments to generated types:
331
-
332
- ```typescript
333
- const jsdocPlugin: SchemanticPlugin = {
334
- name: "jsdoc",
335
- version: "1.0.0",
336
- description: "Adds JSDoc comments to generated types",
337
-
338
- afterTypeGeneration: async (
339
- typeName: string,
340
- generatedType: GeneratedType,
341
- context: GenerationContext
342
- ) => {
343
- if (!generatedType.content.includes("/**")) {
344
- const comment = `/**\n * ${
345
- generatedType.sourceSchema.description || `Generated type: ${typeName}`
346
- }\n */\n`;
347
- generatedType.content = comment + generatedType.content;
348
- }
349
- },
350
- };
351
- ```
352
-
353
- ### Validation Plugin
354
-
355
- Adds validation decorators for class-validator:
356
-
357
- ```typescript
358
- const validationPlugin: SchemanticPlugin = {
359
- name: "validation",
360
- version: "1.0.0",
361
- description: "Adds validation decorators to generated types",
362
-
363
- afterTypeGeneration: async (
364
- typeName: string,
365
- generatedType: GeneratedType,
366
- context: GenerationContext
367
- ) => {
368
- if (generatedType.isInterface) {
369
- // Add validation imports
370
- const imports = `import { IsString, IsNumber, IsOptional, IsNotEmpty } from 'class-validator';\n\n`;
371
-
372
- // Add validation decorators to properties
373
- let content = generatedType.content;
374
- content = content.replace(
375
- /(\w+)(\?)?: (\w+);/g,
376
- (match, propName, optional, type) => {
377
- const decorators = [];
378
-
379
- if (type === "string") decorators.push("@IsString()");
380
- if (type === "number") decorators.push("@IsNumber()");
381
- if (optional) decorators.push("@IsOptional()");
382
- else decorators.push("@IsNotEmpty()");
383
-
384
- return `${decorators.join("\n ")}\n ${match}`;
385
- }
386
- );
387
-
388
- generatedType.content = imports + content;
389
- }
390
- },
391
- };
392
- ```
393
-
394
- ### React Hooks Plugin
395
-
396
- Generates React hooks for API endpoints:
397
-
398
- ```typescript
399
- const reactHooksPlugin: SchemanticPlugin = {
400
- name: "react-hooks",
401
- version: "1.0.0",
402
- description: "Generates React hooks for API endpoints",
403
-
404
- customClientGenerators: {
405
- "react-hooks": (context: GenerationContext): GeneratedApiClient => {
406
- const hooks = generateReactHooks(context);
407
-
408
- return {
409
- name: "ApiHooks",
410
- content: hooks,
411
- dependencies: ["react-query"],
412
- exports: ["useApiHooks"],
413
- endpoints: [],
414
- };
415
- },
416
- },
417
- };
418
-
419
- function generateReactHooks(context: GenerationContext): string {
420
- let hooks = `import { useQuery, useMutation, useQueryClient } from 'react-query';\n`;
421
- hooks += `import { ApiClient } from './api-client';\n\n`;
422
-
423
- hooks += `export const useApiHooks = (client: ApiClient) => {\n`;
424
- hooks += ` const queryClient = useQueryClient();\n\n`;
425
-
426
- // Generate hooks for each endpoint
427
- for (const [path, pathItem] of Object.entries(context.schema.paths)) {
428
- if (typeof pathItem === "object" && pathItem !== null) {
429
- const operations = ["get", "post", "put", "delete", "patch"] as const;
430
-
431
- for (const method of operations) {
432
- const operation = pathItem[method];
433
- if (operation) {
434
- const hookName = generateHookName(
435
- operation.operationId || `${method}${path}`
436
- );
437
- const hook = generateHook(operation, method, path);
438
- hooks += ` ${hookName} = ${hook};\n`;
439
- }
440
- }
441
- }
442
- }
443
-
444
- hooks += `};\n`;
445
- return hooks;
446
- }
447
- ```
448
-
449
- ## Plugin Loading
450
-
451
- ### From File
452
-
453
- ```typescript
454
- import { PluginLoader } from "schemantic";
455
-
456
- const loader = new PluginLoader();
457
- const plugin = await loader.loadPluginFromFile("./my-plugin.js");
458
- ```
459
-
460
- ### From Package
461
-
462
- ```typescript
463
- const plugin = await loader.loadPluginFromPackage("my-Schemantic-plugin");
464
- ```
465
-
466
- ### From Directory
467
-
468
- ```typescript
469
- const plugins = await loader.loadPluginsFromDirectory("./plugins");
470
- ```
471
-
472
- ## Plugin Registration
473
-
474
- ### In Code
475
-
476
- ```typescript
477
- import { Schemantic } from "schemantic";
478
-
479
- const Schemantic = new Schemantic(config);
480
- const pluginManager = Schemantic.getPluginManager();
481
-
482
- pluginManager.registerPlugin(myPlugin);
483
- pluginManager.enablePlugin("my-plugin");
484
- ```
485
-
486
- ### Via Configuration
487
-
488
- ```typescript
489
- const config: SchemanticConfig = {
490
- // ... other config
491
- plugins: [
492
- { name: "my-plugin", enabled: true },
493
- { name: "jsdoc", enabled: true },
494
- ],
495
- };
496
- ```
497
-
498
- ### Via CLI
499
-
500
- ```bash
501
- npx schemantic generate --plugins my-plugin,jsdoc
502
- ```
503
-
504
- ## Best Practices
505
-
506
- ### 1. Error Handling
507
-
508
- Always handle errors gracefully:
509
-
510
- ```typescript
511
- beforeTypeGeneration: async (typeName: string, schema: ResolvedSchema, context: GenerationContext) => {
512
- try {
513
- // Plugin logic
514
- } catch (error) {
515
- console.warn(`Plugin ${this.name} failed for type ${typeName}:`, error);
516
- // Don't throw - let generation continue
517
- }
518
- },
519
- ```
520
-
521
- ### 2. Performance
522
-
523
- Consider performance implications:
524
-
525
- ```typescript
526
- // Cache expensive operations
527
- const cache = new Map();
528
-
529
- transformSchema: (schema: ResolvedSchema, context: GenerationContext): ResolvedSchema => {
530
- const cacheKey = JSON.stringify(schema);
531
-
532
- if (cache.has(cacheKey)) {
533
- return cache.get(cacheKey);
534
- }
535
-
536
- const result = expensiveTransformation(schema);
537
- cache.set(cacheKey, result);
538
- return result;
539
- },
540
- ```
541
-
542
- ### 3. Documentation
543
-
544
- Document your plugin thoroughly:
545
-
546
- ```typescript
547
- const myPlugin: SchemanticPlugin = {
548
- name: "my-plugin",
549
- version: "1.0.0",
550
- description: `
551
- My custom plugin that adds special functionality.
552
-
553
- Features:
554
- - Adds custom decorators
555
- - Transforms specific types
556
- - Generates additional files
557
-
558
- Usage:
559
- Enable via configuration or CLI: --plugins my-plugin
560
- `,
561
-
562
- // ... implementation
563
- };
564
- ```
565
-
566
- ### 4. Testing
567
-
568
- Test your plugins:
569
-
570
- ```typescript
571
- import { Schemantic, SchemanticConfig } from "schemantic";
572
-
573
- describe("My Plugin", () => {
574
- it("should transform schemas correctly", async () => {
575
- const config: SchemanticConfig = {
576
- schemaData: testSchema,
577
- outputDir: "./test-output",
578
- plugins: [{ name: "my-plugin", enabled: true }],
579
- };
580
-
581
- const Schemantic = new Schemantic(config);
582
- const result = await Schemantic.generate();
583
-
584
- expect(result.success).toBe(true);
585
- expect(result.generatedFiles).toHaveLength(1);
586
- });
587
- });
588
- ```
589
-
590
- ### 5. Versioning
591
-
592
- Use semantic versioning for your plugins:
593
-
594
- ```typescript
595
- const myPlugin: SchemanticPlugin = {
596
- name: "my-plugin",
597
- version: "1.2.3", // Major.Minor.Patch
598
- description: "My plugin description",
599
-
600
- // ... implementation
601
- };
602
- ```
603
-
604
- ## Publishing Plugins
605
-
606
- ### As NPM Package
607
-
608
- 1. Create a package.json:
609
-
610
- ```json
611
- {
612
- "name": "Schemantic-my-plugin",
613
- "version": "1.0.0",
614
- "description": "My custom Schemantic plugin",
615
- "main": "dist/index.js",
616
- "types": "dist/index.d.ts",
617
- "keywords": ["Schemantic", "plugin", "typescript", "openapi"],
618
- "peerDependencies": {
619
- "schemantic": "^1.0.0"
620
- }
621
- }
622
- ```
623
-
624
- 2. Export your plugin:
625
-
626
- ```typescript
627
- // src/index.ts
628
- export { myPlugin } from "./plugin";
629
- export * from "./types";
630
- ```
631
-
632
- 3. Build and publish:
633
-
634
- ```bash
635
- npm run build
636
- npm publish
637
- ```
638
-
639
- ### Usage
640
-
641
- Users can install and use your plugin:
642
-
643
- ```bash
644
- npm install Schemantic-my-plugin
645
- ```
646
-
647
- ```typescript
648
- import { myPlugin } from "Schemantic-my-plugin";
649
- import { Schemantic } from "schemantic";
650
-
651
- const Schemantic = new Schemantic(config);
652
- Schemantic.getPluginManager().registerPlugin(myPlugin);
653
- ```
654
-
655
- ## Troubleshooting
656
-
657
- ### Common Issues
658
-
659
- 1. **Plugin not loading**: Check that the plugin exports the correct interface
660
- 2. **Type errors**: Ensure your plugin implements all required interface properties
661
- 3. **Performance issues**: Use caching and avoid expensive operations in hooks
662
- 4. **Conflicts**: Check for naming conflicts with other plugins
663
-
664
- ### Debug Mode
665
-
666
- Enable debug mode to see plugin execution:
667
-
668
- ```typescript
669
- const config: SchemanticConfig = {
670
- // ... other config
671
- plugins: [{ name: "my-plugin", enabled: true, options: { debug: true } }],
672
- };
673
- ```
674
-
675
- ### Logging
676
-
677
- Add logging to your plugin:
678
-
679
- ```typescript
680
- beforeTypeGeneration: async (typeName: string, schema: ResolvedSchema, context: GenerationContext) => {
681
- console.log(`[My Plugin] Processing type: ${typeName}`);
682
-
683
- // Plugin logic
684
-
685
- console.log(`[My Plugin] Completed processing: ${typeName}`);
686
- },
687
- ```
1
+ # Plugins
2
+
3
+ Plugins are generation extensions or explicit runtime helper emitters. Enabling validation, caching, branding, or timing does not automatically wrap client endpoints. Import helpers from generated output and integrate them deliberately.
4
+
5
+ ```sh
6
+ npx schemantic plugin list
7
+ npx schemantic generate ./openapi.json --plugins jsdoc,zod-validation --output ./generated
8
+ ```
9
+
10
+ Install `zod@^4` in the consuming project for generated validation and schema-backed branded helpers. React hooks use `--hooks`/`generateHooks`, not a `react-hooks` plugin.
11
+
12
+ | Name | Observable behavior and boundary |
13
+ | --- | --- |
14
+ | `jsdoc` | Adds documentation to generated declarations |
15
+ | `validation` | Compatibility alias for the Zod validation plugin |
16
+ | `zod-validation` | Generates Zod schemas/helpers; consumer must call them |
17
+ | `strict-mode` | Retired; active use fails explicitly. Use core strict output defaults |
18
+ | `branded-types` | Nominal metadata and schema-backed guards/assertions/create helpers; Zod dependency |
19
+ | `request-deduplication` | Emits manual caching/coalescing helpers; endpoints are not automatically cached |
20
+ | `performance-monitoring` | Emits optional timing helpers; source-size analysis is an estimate, not a bundled artifact measurement |
21
+
22
+ Local and installed package plugins are resolved during the generation invocation:
23
+
24
+ ```json
25
+ {
26
+ "schemaFile": "./openapi.json",
27
+ "outputDir": "./generated",
28
+ "plugins": [
29
+ { "name": "./plugins/example.cjs", "enabled": true },
30
+ { "name": "installed-plugin-package", "enabled": true }
31
+ ]
32
+ }
33
+ ```
34
+
35
+ File paths resolve relative to the config. Package names resolve from the consumer/config directory. `--plugins ./plugin.cjs` is also supported. Plugins must export nonempty `name`, `version`, `description`, and compatible hook functions. Compile TypeScript plugins to JavaScript before loading. The inspection command `plugin load ./plugin.cjs` does not register that plugin in a future process.
36
+
37
+ Options belong in the plugin's config `options` object; enabled/disabled status is explicit. Programmatic factories are useful for function-valued settings that JSON cannot represent. See [development](PLUGIN_DEVELOPMENT.md).
38
+
39
+ ## Runtime caching scope
40
+
41
+ The deduplication helper includes request method/URL/body/parameters/headers in identity. Use an execution `cacheScope` (or an instance per authenticated session) when ambient cookies or credential context changes the response. A shared instance cannot infer browser cookie changes. Mutation methods bypass caching. Custom key generators run on the runtime `RequestDeduplicator` constructor; do not place functions in JSON configuration. Avoid logging credentials.
42
+
43
+ Regex and string invalidation operate on tracked request URLs. Cache statistics report actual counters. Endpoint stale/TTL policies govern helper calls; they do not create automatic endpoint instrumentation.
44
+
45
+ ## Capability limits
46
+
47
+ Auth-state branding records client metadata; server authorization still requires server checks. Zod's public constraints and unsupported schema diagnostics determine validation coverage. `optimizeBundle`, custom validation error wording, and automatic middleware claims should not be treated as implemented runtime features. Timing helpers observe explicit calls. `generateReports` writes `performance-report.json`, `.html`, or `.md`; report utilities can also return strings. These observe generator activity or explicitly instrumented calls; they are not historical regression monitoring or continuous browser memory monitoring. No request/error reduction percentages are promised.
48
+
49
+ See [advanced capabilities](ADVANCED_PLUGINS_IMPLEMENTATION.md) for experimental options and [API](API.md) for the actual hook/client contract.