@openpkg-ts/spec 0.12.0 → 0.23.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
@@ -1,6 +1,6 @@
1
1
  # @openpkg-ts/spec
2
2
 
3
- OpenPkg schema, types, validation, and diffing utilities.
3
+ OpenPkg specification types, validation, normalization, and diffing utilities.
4
4
 
5
5
  ## Install
6
6
 
@@ -8,35 +8,126 @@ OpenPkg schema, types, validation, and diffing utilities.
8
8
  npm install @openpkg-ts/spec
9
9
  ```
10
10
 
11
- ## Usage
11
+ ## Quick Start
12
12
 
13
13
  ```typescript
14
14
  import { validateSpec, normalize, diffSpec } from '@openpkg-ts/spec';
15
15
 
16
- // Validate
17
- const result = validateSpec(normalize(spec));
16
+ // Validate a spec
17
+ const result = validateSpec(spec);
18
18
  if (!result.ok) {
19
19
  console.error(result.errors);
20
20
  }
21
21
 
22
+ // Normalize for consistent structure
23
+ const normalized = normalize(spec);
24
+
22
25
  // Diff two specs
23
26
  const diff = diffSpec(oldSpec, newSpec);
24
- console.log(`Coverage delta: ${diff.coverageDelta}%`);
27
+ console.log(`Breaking changes: ${diff.breaking.length}`);
28
+ ```
29
+
30
+ ## Validation
31
+
32
+ ```typescript
33
+ import { validateSpec, assertSpec, getValidationErrors } from '@openpkg-ts/spec';
34
+
35
+ // Returns { ok: boolean, errors?: ValidationError[] }
36
+ const result = validateSpec(spec);
37
+
38
+ // Throws on invalid
39
+ assertSpec(spec);
40
+
41
+ // Get errors only
42
+ const errors = getValidationErrors(spec);
43
+ ```
44
+
45
+ ## Normalization
46
+
47
+ Ensures consistent structure and defaults.
48
+
49
+ ```typescript
50
+ import { normalize } from '@openpkg-ts/spec';
51
+
52
+ const normalized = normalize(spec);
53
+ // - Sorts exports alphabetically
54
+ // - Ensures meta fields exist
55
+ // - Normalizes type references
56
+ ```
57
+
58
+ ## Diffing
59
+
60
+ Compare specs and detect breaking changes.
61
+
62
+ ```typescript
63
+ import { diffSpec, recommendSemverBump, calculateNextVersion } from '@openpkg-ts/spec';
64
+
65
+ const diff = diffSpec(baseSpec, headSpec);
66
+
67
+ console.log(`Added: ${diff.added.length}`);
68
+ console.log(`Removed: ${diff.removed.length}`);
69
+ console.log(`Modified: ${diff.modified.length}`);
70
+ console.log(`Breaking: ${diff.breaking.length}`);
71
+
72
+ // Get semver recommendation
73
+ const recommendation = recommendSemverBump(diff);
74
+ console.log(`Suggested bump: ${recommendation.bump}`); // 'major' | 'minor' | 'patch'
75
+ console.log(`Reason: ${recommendation.reason}`);
76
+
77
+ // Calculate next version
78
+ const next = calculateNextVersion('1.2.3', recommendation.bump);
79
+ console.log(`Next version: ${next}`); // '2.0.0'
80
+ ```
81
+
82
+ ## Dereferencing
83
+
84
+ Resolve `$ref` pointers in the spec.
85
+
86
+ ```typescript
87
+ import { dereference } from '@openpkg-ts/spec';
88
+
89
+ const dereferenced = dereference(spec);
90
+ // All $ref pointers are resolved inline
91
+ ```
92
+
93
+ ## Types
94
+
95
+ ```typescript
96
+ import type {
97
+ OpenPkg,
98
+ SpecExport,
99
+ SpecType,
100
+ SpecFunction,
101
+ SpecClass,
102
+ SpecInterface,
103
+ SpecMeta,
104
+ } from '@openpkg-ts/spec';
25
105
  ```
26
106
 
27
107
  ## Exports
28
108
 
29
- - `validateSpec` / `assertSpec` - Schema validation
30
- - `normalize` - Ensure consistent structure
31
- - `dereference` - Resolve `$ref` pointers
32
- - `diffSpec` - Compare specs
109
+ ### Validation
110
+ - `validateSpec(spec)` - Validate against schema
111
+ - `assertSpec(spec)` - Throw on invalid
112
+ - `getValidationErrors(spec)` - Get errors array
113
+ - `getAvailableVersions()` - List schema versions
114
+
115
+ ### Transformation
116
+ - `normalize(spec)` - Normalize structure
117
+ - `dereference(spec)` - Resolve $ref pointers
33
118
 
34
- ## Documentation
119
+ ### Diffing
120
+ - `diffSpec(base, head)` - Compare specs
121
+ - `recommendSemverBump(diff)` - Suggest version bump
122
+ - `calculateNextVersion(version, bump)` - Calculate next version
123
+ - `categorizeBreakingChanges(diff)` - Group by severity
35
124
 
36
- - [Spec Overview](../../docs/spec/overview.md)
37
- - [Types Reference](../../docs/spec/types.md)
38
- - [Drift Types](../../docs/spec/drift-types.md)
39
- - [Diffing](../../docs/spec/diffing.md)
125
+ ### Types
126
+ - `OpenPkg` - Root spec type
127
+ - `SpecExport` - Export definition
128
+ - `SpecType` - Type definition
129
+ - `SpecFunction`, `SpecClass`, `SpecInterface` - Export kinds
130
+ - `SpecDiff` - Diff result type
40
131
 
41
132
  ## License
42
133
 
package/dist/index.d.ts CHANGED
@@ -1,6 +1,23 @@
1
+ /**
2
+ * Structured data for @param tags.
3
+ */
4
+ type SpecTagParam = {
5
+ /** Parameter name (e.g., "options", "opts.nested") */
6
+ name: string;
7
+ /** Type annotation from JSDoc {type} syntax */
8
+ type?: string;
9
+ /** Parameter description */
10
+ description?: string;
11
+ /** Whether param is marked optional with [brackets] */
12
+ optional?: boolean;
13
+ };
1
14
  type SpecTag = {
15
+ /** Tag name (e.g., "param", "returns", "example") */
2
16
  name: string;
17
+ /** Raw tag text (for backwards compatibility) */
3
18
  text: string;
19
+ /** Structured data for @param tags */
20
+ param?: SpecTagParam;
4
21
  };
5
22
  type SpecTypeAliasKind = "alias" | "conditional" | "mapped" | "template-literal" | "infer";
6
23
  type SpecConditionalType = {
@@ -95,7 +112,7 @@ type SpecSchemaRef = {
95
112
  type SpecSchemaFallback = {
96
113
  type: string;
97
114
  };
98
- type SpecSchemaGeneric = Record<string, unknown>;
115
+ type SpecSchemaGeneric = Record<string, unknown> & Partial<JSONSchemaExtensions>;
99
116
  type SpecSchema = string | SpecSchemaPrimitive | SpecSchemaComposite | SpecSchemaCombinator | SpecSchemaRef | SpecSchemaFallback | SpecSchemaGeneric;
100
117
  type SpecExampleLanguage = "ts" | "js" | "tsx" | "jsx" | "shell" | "json";
101
118
  type SpecExample = {
@@ -146,6 +163,50 @@ type SpecSignature = {
146
163
  isImplementation?: boolean;
147
164
  throws?: SpecThrows[];
148
165
  };
166
+ /**
167
+ * JSON Schema extension fields for TypeScript-specific type information.
168
+ *
169
+ * These extensions use the `x-` prefix which is valid JSON Schema for vendor extensions.
170
+ * They allow consumers to preserve TypeScript-specific information while still having
171
+ * valid JSON Schema. The extensions are optional - a consumer can ignore them for pure
172
+ * JSON Schema usage.
173
+ *
174
+ * Extension semantics:
175
+ * | Extension | Purpose |
176
+ * |----------------------|----------------------------------------------------------------------|
177
+ * | `x-ts-type` | Preserves original TS type for types that map to JSON Schema but |
178
+ * | | lose fidelity (bigint → integer, symbol → string) |
179
+ * | `x-ts-function` | Marks a schema as representing a function type |
180
+ * | `x-ts-signatures` | Contains function/method signatures for callable types |
181
+ * | `x-ts-type-arguments`| Preserves generic type arguments for parameterized types |
182
+ */
183
+ type JSONSchemaExtensions = {
184
+ /**
185
+ * Preserves the original TypeScript type when mapping to JSON Schema loses fidelity.
186
+ * Examples:
187
+ * - bigint → { type: "integer", "x-ts-type": "bigint" }
188
+ * - symbol → { type: "string", "x-ts-type": "symbol" }
189
+ * - void → { type: "null", "x-ts-type": "void" } (optionally)
190
+ * - never, any, unknown, undefined also supported
191
+ */
192
+ "x-ts-type"?: "bigint" | "symbol" | "void" | "never" | "any" | "unknown" | "undefined" | string;
193
+ /**
194
+ * Marks a schema as representing a function type.
195
+ * When true, the schema represents a callable TypeScript function.
196
+ */
197
+ "x-ts-function"?: boolean;
198
+ /**
199
+ * Contains function/method signatures for callable types.
200
+ * Used in conjunction with `x-ts-function` to preserve full signature information.
201
+ */
202
+ "x-ts-signatures"?: SpecSignature[];
203
+ /**
204
+ * Preserves generic type arguments for parameterized types.
205
+ * Used with $ref to maintain generic instantiation information.
206
+ * Example: Map<string, number> → { "$ref": "#/$defs/Map", "x-ts-type-arguments": [...] }
207
+ */
208
+ "x-ts-type-arguments"?: SpecSchema[];
209
+ };
149
210
  type SpecMember = {
150
211
  id?: string;
151
212
  name?: string;
@@ -411,6 +472,10 @@ declare function validateSpec(spec: unknown, version?: SchemaVersion): {
411
472
  errors: SpecError[];
412
473
  };
413
474
  /**
475
+ * Get available schema versions.
476
+ */
477
+ declare function getAvailableVersions(): string[];
478
+ /**
414
479
  * Assert that a value is a valid OpenPkg spec.
415
480
  * Throws an error with details if validation fails.
416
481
  *
@@ -426,4 +491,4 @@ declare function assertSpec(spec: unknown, version?: SchemaVersion): asserts spe
426
491
  * @returns Array of validation errors (empty if valid)
427
492
  */
428
493
  declare function getValidationErrors(spec: unknown, version?: SchemaVersion): SpecError[];
429
- export { validateSpec, recommendSemverBump, normalize, getValidationErrors, diffSpec, dereference, categorizeBreakingChanges, calculateNextVersion, assertSpec, SpecVisibility, SpecTypeParameter, SpecTypeKind, SpecTypeAliasKind, SpecType, SpecThrows, SpecTag, SpecSource, SpecSignatureReturn, SpecSignatureParameter, SpecSignature, SpecSchemaRef, SpecSchemaPrimitive, SpecSchemaGeneric, SpecSchemaFallback, SpecSchemaComposite, SpecSchemaCombinator, SpecSchema, SpecPresentationMeta, SpecMember, SpecMappedType, SpecGenerationMeta, SpecGenerationInfo, SpecExtensions, SpecExtension, SpecExportKind, SpecExport, SpecExampleLanguage, SpecExample, SpecDiff, SpecDecorator, SpecConditionalType, SemverRecommendation, SemverBump, SCHEMA_VERSION, SCHEMA_URL, OpenPkgVersion, OpenPkgMeta, OpenPkg, MemberChangeInfo, JSON_SCHEMA_DRAFT, GenerationIssueSeverity, GenerationIssue, EntryPointDetectionMethod, CategorizedBreaking, BreakingSeverity };
494
+ export { validateSpec, recommendSemverBump, normalize, getValidationErrors, getAvailableVersions, diffSpec, dereference, categorizeBreakingChanges, calculateNextVersion, assertSpec, SpecVisibility, SpecTypeParameter, SpecTypeKind, SpecTypeAliasKind, SpecType, SpecThrows, SpecTagParam, SpecTag, SpecSource, SpecSignatureReturn, SpecSignatureParameter, SpecSignature, SpecSchemaRef, SpecSchemaPrimitive, SpecSchemaGeneric, SpecSchemaFallback, SpecSchemaComposite, SpecSchemaCombinator, SpecSchema, SpecPresentationMeta, SpecMember, SpecMappedType, SpecGenerationMeta, SpecGenerationInfo, SpecExtensions, SpecExtension, SpecExportKind, SpecExport, SpecExampleLanguage, SpecExample, SpecDiff, SpecDecorator, SpecConditionalType, SemverRecommendation, SemverBump, SCHEMA_VERSION, SCHEMA_URL, OpenPkgVersion, OpenPkgMeta, OpenPkg, MemberChangeInfo, JSON_SCHEMA_DRAFT, JSONSchemaExtensions, GenerationIssueSeverity, GenerationIssue, EntryPointDetectionMethod, CategorizedBreaking, BreakingSeverity };
package/dist/index.js CHANGED
@@ -373,10 +373,14 @@ function normalizeType(item) {
373
373
  return clone;
374
374
  }
375
375
  function normalizeTag(tag) {
376
- return {
376
+ const result = {
377
377
  name: tag.name,
378
378
  text: tag.text
379
379
  };
380
+ if (tag.param) {
381
+ result.param = tag.param;
382
+ }
383
+ return result;
380
384
  }
381
385
  function normalizeMember(member) {
382
386
  const clone = structuredClone(member);
@@ -2287,7 +2291,19 @@ var openpkg_schema_default4 = {
2287
2291
  required: ["name", "text"],
2288
2292
  properties: {
2289
2293
  name: { type: "string" },
2290
- text: { type: "string" }
2294
+ text: { type: "string" },
2295
+ param: { $ref: "#/$defs/tagParam" }
2296
+ },
2297
+ additionalProperties: false
2298
+ },
2299
+ tagParam: {
2300
+ type: "object",
2301
+ required: ["name"],
2302
+ properties: {
2303
+ name: { type: "string" },
2304
+ type: { type: "string" },
2305
+ description: { type: "string" },
2306
+ optional: { type: "boolean" }
2291
2307
  },
2292
2308
  additionalProperties: false
2293
2309
  },
@@ -2539,6 +2555,9 @@ function validateSpec(spec, version = "latest") {
2539
2555
  errors
2540
2556
  };
2541
2557
  }
2558
+ function getAvailableVersions() {
2559
+ return Object.keys(schemas);
2560
+ }
2542
2561
  function assertSpec(spec, version = "latest") {
2543
2562
  const result = validateSpec(spec, version);
2544
2563
  if (!result.ok) {
@@ -2557,6 +2576,7 @@ export {
2557
2576
  recommendSemverBump,
2558
2577
  normalize,
2559
2578
  getValidationErrors,
2579
+ getAvailableVersions,
2560
2580
  diffSpec,
2561
2581
  dereference,
2562
2582
  categorizeBreakingChanges,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openpkg-ts/spec",
3
- "version": "0.12.0",
3
+ "version": "0.23.0",
4
4
  "description": "Shared schema, validation, and diff utilities for OpenPkg specs",
5
5
  "keywords": [
6
6
  "openpkg",
@@ -171,7 +171,19 @@
171
171
  "required": ["name", "text"],
172
172
  "properties": {
173
173
  "name": { "type": "string" },
174
- "text": { "type": "string" }
174
+ "text": { "type": "string" },
175
+ "param": { "$ref": "#/$defs/tagParam" }
176
+ },
177
+ "additionalProperties": false
178
+ },
179
+ "tagParam": {
180
+ "type": "object",
181
+ "required": ["name"],
182
+ "properties": {
183
+ "name": { "type": "string" },
184
+ "type": { "type": "string" },
185
+ "description": { "type": "string" },
186
+ "optional": { "type": "boolean" }
175
187
  },
176
188
  "additionalProperties": false
177
189
  },