@contractspec/lib.contracts-transformers 1.46.2 → 1.48.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.
Files changed (32) hide show
  1. package/dist/common/utils.js.map +1 -1
  2. package/dist/openapi/differ.js.map +1 -1
  3. package/dist/openapi/exporter/data-views.js.map +1 -1
  4. package/dist/openapi/exporter/events.js.map +1 -1
  5. package/dist/openapi/exporter/features.js.map +1 -1
  6. package/dist/openapi/exporter/forms.js.map +1 -1
  7. package/dist/openapi/exporter/operations.js.map +1 -1
  8. package/dist/openapi/exporter/presentations.js.map +1 -1
  9. package/dist/openapi/exporter/registries.js.map +1 -1
  10. package/dist/openapi/exporter/workflows.js.map +1 -1
  11. package/dist/openapi/exporter.d.ts +1 -1
  12. package/dist/openapi/exporter.d.ts.map +1 -1
  13. package/dist/openapi/exporter.js.map +1 -1
  14. package/dist/openapi/importer/events.js.map +1 -1
  15. package/dist/openapi/importer/generator.js.map +1 -1
  16. package/dist/openapi/importer/grouping.js.map +1 -1
  17. package/dist/openapi/importer/index.d.ts +3 -3
  18. package/dist/openapi/importer/index.d.ts.map +1 -1
  19. package/dist/openapi/importer/index.js.map +1 -1
  20. package/dist/openapi/importer/models.js.map +1 -1
  21. package/dist/openapi/importer/schemas.js.map +1 -1
  22. package/dist/openapi/parser/document.js.map +1 -1
  23. package/dist/openapi/parser/operation.js.map +1 -1
  24. package/dist/openapi/parser/parameters.js.map +1 -1
  25. package/dist/openapi/parser/resolvers.js.map +1 -1
  26. package/dist/openapi/parser/utils.js.map +1 -1
  27. package/dist/openapi/schema-converter.d.ts +3 -3
  28. package/dist/openapi/schema-converter.d.ts.map +1 -1
  29. package/dist/openapi/schema-converter.js.map +1 -1
  30. package/dist/openapi/schema-generators/index.js.map +1 -1
  31. package/dist/openapi/types.d.ts.map +1 -1
  32. package/package.json +7 -9
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","names":["current: unknown"],"sources":["../../src/common/utils.ts"],"sourcesContent":["/**\n * Common utilities for contract transformations.\n */\n\n/**\n * Convert a string to PascalCase.\n */\nexport function toPascalCase(str: string): string {\n return str\n .replace(/[-_./\\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : ''))\n .replace(/^./, (c) => c.toUpperCase());\n}\n\n/**\n * Convert a string to camelCase.\n */\nexport function toCamelCase(str: string): string {\n const pascal = toPascalCase(str);\n return pascal.charAt(0).toLowerCase() + pascal.slice(1);\n}\n\n/**\n * Convert a string to kebab-case.\n */\nexport function toKebabCase(str: string): string {\n return str\n .replace(/([a-z])([A-Z])/g, '$1-$2')\n .replace(/[\\s_./]+/g, '-')\n .toLowerCase();\n}\n\n/**\n * Convert a string to snake_case.\n */\nexport function toSnakeCase(str: string): string {\n return str\n .replace(/([a-z])([A-Z])/g, '$1_$2')\n .replace(/[\\s\\-./]+/g, '_')\n .toLowerCase();\n}\n\n/**\n * Sanitize a string to be a valid TypeScript identifier.\n */\nexport function toValidIdentifier(str: string): string {\n // Remove invalid characters\n let result = str.replace(/[^a-zA-Z0-9_$]/g, '_');\n // Ensure it doesn't start with a number\n if (/^[0-9]/.test(result)) {\n result = '_' + result;\n }\n return result;\n}\n\n/**\n * Generate a ContractSpec key from an operation identifier.\n */\nexport function toSpecKey(operationId: string, prefix?: string): string {\n const key = toCamelCase(operationId);\n return prefix ? `${prefix}.${key}` : key;\n}\n\n/**\n * Generate a file name from a spec name.\n */\nexport function toFileName(specName: string): string {\n return toKebabCase(specName.replace(/\\./g, '-')) + '.ts';\n}\n\n/**\n * Deep equality check for objects.\n */\nexport function deepEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n if (a === null || b === null) return false;\n if (typeof a !== typeof b) return false;\n\n if (typeof a === 'object') {\n const aObj = a as Record<string, unknown>;\n const bObj = b as Record<string, unknown>;\n\n const aKeys = Object.keys(aObj);\n const bKeys = Object.keys(bObj);\n\n if (aKeys.length !== bKeys.length) return false;\n\n for (const key of aKeys) {\n if (!bKeys.includes(key)) return false;\n if (!deepEqual(aObj[key], bObj[key])) return false;\n }\n\n return true;\n }\n\n return false;\n}\n\n/**\n * Get a value from an object by JSON path.\n */\nexport function getByPath(obj: unknown, path: string): unknown {\n const parts = path.split('.').filter(Boolean);\n let current: unknown = obj;\n\n for (const part of parts) {\n if (current === null || current === undefined) return undefined;\n if (typeof current !== 'object') return undefined;\n current = (current as Record<string, unknown>)[part];\n }\n\n return current;\n}\n\n/**\n * Extract path parameters from a URL path template.\n * e.g., \"/users/{userId}/orders/{orderId}\" -> [\"userId\", \"orderId\"]\n */\nexport function extractPathParams(path: string): string[] {\n const matches = path.match(/\\{([^}]+)\\}/g) || [];\n return matches.map((m) => m.slice(1, -1));\n}\n\n/**\n * Normalize a URL path for comparison.\n */\nexport function normalizePath(path: string): string {\n // Remove leading/trailing slashes\n let normalized = path.replace(/^\\/+|\\/+$/g, '');\n // Replace multiple slashes with single\n normalized = normalized.replace(/\\/+/g, '/');\n // Add leading slash\n return '/' + normalized;\n}\n"],"mappings":";;;;;;;AAOA,SAAgB,aAAa,KAAqB;AAChD,QAAO,IACJ,QAAQ,mBAAmB,GAAG,MAAO,IAAI,EAAE,aAAa,GAAG,GAAI,CAC/D,QAAQ,OAAO,MAAM,EAAE,aAAa,CAAC;;;;;AAM1C,SAAgB,YAAY,KAAqB;CAC/C,MAAM,SAAS,aAAa,IAAI;AAChC,QAAO,OAAO,OAAO,EAAE,CAAC,aAAa,GAAG,OAAO,MAAM,EAAE;;;;;AAMzD,SAAgB,YAAY,KAAqB;AAC/C,QAAO,IACJ,QAAQ,mBAAmB,QAAQ,CACnC,QAAQ,aAAa,IAAI,CACzB,aAAa;;;;;AAMlB,SAAgB,YAAY,KAAqB;AAC/C,QAAO,IACJ,QAAQ,mBAAmB,QAAQ,CACnC,QAAQ,cAAc,IAAI,CAC1B,aAAa;;;;;AAMlB,SAAgB,kBAAkB,KAAqB;CAErD,IAAI,SAAS,IAAI,QAAQ,mBAAmB,IAAI;AAEhD,KAAI,SAAS,KAAK,OAAO,CACvB,UAAS,MAAM;AAEjB,QAAO;;;;;AAMT,SAAgB,UAAU,aAAqB,QAAyB;CACtE,MAAM,MAAM,YAAY,YAAY;AACpC,QAAO,SAAS,GAAG,OAAO,GAAG,QAAQ;;;;;AAMvC,SAAgB,WAAW,UAA0B;AACnD,QAAO,YAAY,SAAS,QAAQ,OAAO,IAAI,CAAC,GAAG;;;;;AAMrD,SAAgB,UAAU,GAAY,GAAqB;AACzD,KAAI,MAAM,EAAG,QAAO;AACpB,KAAI,MAAM,QAAQ,MAAM,KAAM,QAAO;AACrC,KAAI,OAAO,MAAM,OAAO,EAAG,QAAO;AAElC,KAAI,OAAO,MAAM,UAAU;EACzB,MAAM,OAAO;EACb,MAAM,OAAO;EAEb,MAAM,QAAQ,OAAO,KAAK,KAAK;EAC/B,MAAM,QAAQ,OAAO,KAAK,KAAK;AAE/B,MAAI,MAAM,WAAW,MAAM,OAAQ,QAAO;AAE1C,OAAK,MAAM,OAAO,OAAO;AACvB,OAAI,CAAC,MAAM,SAAS,IAAI,CAAE,QAAO;AACjC,OAAI,CAAC,UAAU,KAAK,MAAM,KAAK,KAAK,CAAE,QAAO;;AAG/C,SAAO;;AAGT,QAAO;;;;;AAMT,SAAgB,UAAU,KAAc,MAAuB;CAC7D,MAAM,QAAQ,KAAK,MAAM,IAAI,CAAC,OAAO,QAAQ;CAC7C,IAAIA,UAAmB;AAEvB,MAAK,MAAM,QAAQ,OAAO;AACxB,MAAI,YAAY,QAAQ,YAAY,OAAW,QAAO;AACtD,MAAI,OAAO,YAAY,SAAU,QAAO;AACxC,YAAW,QAAoC;;AAGjD,QAAO;;;;;;AAOT,SAAgB,kBAAkB,MAAwB;AAExD,SADgB,KAAK,MAAM,eAAe,IAAI,EAAE,EACjC,KAAK,MAAM,EAAE,MAAM,GAAG,GAAG,CAAC;;;;;AAM3C,SAAgB,cAAc,MAAsB;CAElD,IAAI,aAAa,KAAK,QAAQ,cAAc,GAAG;AAE/C,cAAa,WAAW,QAAQ,QAAQ,IAAI;AAE5C,QAAO,MAAM"}
1
+ {"version":3,"file":"utils.js","names":[],"sources":["../../src/common/utils.ts"],"sourcesContent":["/**\n * Common utilities for contract transformations.\n */\n\n/**\n * Convert a string to PascalCase.\n */\nexport function toPascalCase(str: string): string {\n return str\n .replace(/[-_./\\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : ''))\n .replace(/^./, (c) => c.toUpperCase());\n}\n\n/**\n * Convert a string to camelCase.\n */\nexport function toCamelCase(str: string): string {\n const pascal = toPascalCase(str);\n return pascal.charAt(0).toLowerCase() + pascal.slice(1);\n}\n\n/**\n * Convert a string to kebab-case.\n */\nexport function toKebabCase(str: string): string {\n return str\n .replace(/([a-z])([A-Z])/g, '$1-$2')\n .replace(/[\\s_./]+/g, '-')\n .toLowerCase();\n}\n\n/**\n * Convert a string to snake_case.\n */\nexport function toSnakeCase(str: string): string {\n return str\n .replace(/([a-z])([A-Z])/g, '$1_$2')\n .replace(/[\\s\\-./]+/g, '_')\n .toLowerCase();\n}\n\n/**\n * Sanitize a string to be a valid TypeScript identifier.\n */\nexport function toValidIdentifier(str: string): string {\n // Remove invalid characters\n let result = str.replace(/[^a-zA-Z0-9_$]/g, '_');\n // Ensure it doesn't start with a number\n if (/^[0-9]/.test(result)) {\n result = '_' + result;\n }\n return result;\n}\n\n/**\n * Generate a ContractSpec key from an operation identifier.\n */\nexport function toSpecKey(operationId: string, prefix?: string): string {\n const key = toCamelCase(operationId);\n return prefix ? `${prefix}.${key}` : key;\n}\n\n/**\n * Generate a file name from a spec name.\n */\nexport function toFileName(specName: string): string {\n return toKebabCase(specName.replace(/\\./g, '-')) + '.ts';\n}\n\n/**\n * Deep equality check for objects.\n */\nexport function deepEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n if (a === null || b === null) return false;\n if (typeof a !== typeof b) return false;\n\n if (typeof a === 'object') {\n const aObj = a as Record<string, unknown>;\n const bObj = b as Record<string, unknown>;\n\n const aKeys = Object.keys(aObj);\n const bKeys = Object.keys(bObj);\n\n if (aKeys.length !== bKeys.length) return false;\n\n for (const key of aKeys) {\n if (!bKeys.includes(key)) return false;\n if (!deepEqual(aObj[key], bObj[key])) return false;\n }\n\n return true;\n }\n\n return false;\n}\n\n/**\n * Get a value from an object by JSON path.\n */\nexport function getByPath(obj: unknown, path: string): unknown {\n const parts = path.split('.').filter(Boolean);\n let current: unknown = obj;\n\n for (const part of parts) {\n if (current === null || current === undefined) return undefined;\n if (typeof current !== 'object') return undefined;\n current = (current as Record<string, unknown>)[part];\n }\n\n return current;\n}\n\n/**\n * Extract path parameters from a URL path template.\n * e.g., \"/users/{userId}/orders/{orderId}\" -> [\"userId\", \"orderId\"]\n */\nexport function extractPathParams(path: string): string[] {\n const matches = path.match(/\\{([^}]+)\\}/g) || [];\n return matches.map((m) => m.slice(1, -1));\n}\n\n/**\n * Normalize a URL path for comparison.\n */\nexport function normalizePath(path: string): string {\n // Remove leading/trailing slashes\n let normalized = path.replace(/^\\/+|\\/+$/g, '');\n // Replace multiple slashes with single\n normalized = normalized.replace(/\\/+/g, '/');\n // Add leading slash\n return '/' + normalized;\n}\n"],"mappings":";;;;;;;AAOA,SAAgB,aAAa,KAAqB;AAChD,QAAO,IACJ,QAAQ,mBAAmB,GAAG,MAAO,IAAI,EAAE,aAAa,GAAG,GAAI,CAC/D,QAAQ,OAAO,MAAM,EAAE,aAAa,CAAC;;;;;AAM1C,SAAgB,YAAY,KAAqB;CAC/C,MAAM,SAAS,aAAa,IAAI;AAChC,QAAO,OAAO,OAAO,EAAE,CAAC,aAAa,GAAG,OAAO,MAAM,EAAE;;;;;AAMzD,SAAgB,YAAY,KAAqB;AAC/C,QAAO,IACJ,QAAQ,mBAAmB,QAAQ,CACnC,QAAQ,aAAa,IAAI,CACzB,aAAa;;;;;AAMlB,SAAgB,YAAY,KAAqB;AAC/C,QAAO,IACJ,QAAQ,mBAAmB,QAAQ,CACnC,QAAQ,cAAc,IAAI,CAC1B,aAAa;;;;;AAMlB,SAAgB,kBAAkB,KAAqB;CAErD,IAAI,SAAS,IAAI,QAAQ,mBAAmB,IAAI;AAEhD,KAAI,SAAS,KAAK,OAAO,CACvB,UAAS,MAAM;AAEjB,QAAO;;;;;AAMT,SAAgB,UAAU,aAAqB,QAAyB;CACtE,MAAM,MAAM,YAAY,YAAY;AACpC,QAAO,SAAS,GAAG,OAAO,GAAG,QAAQ;;;;;AAMvC,SAAgB,WAAW,UAA0B;AACnD,QAAO,YAAY,SAAS,QAAQ,OAAO,IAAI,CAAC,GAAG;;;;;AAMrD,SAAgB,UAAU,GAAY,GAAqB;AACzD,KAAI,MAAM,EAAG,QAAO;AACpB,KAAI,MAAM,QAAQ,MAAM,KAAM,QAAO;AACrC,KAAI,OAAO,MAAM,OAAO,EAAG,QAAO;AAElC,KAAI,OAAO,MAAM,UAAU;EACzB,MAAM,OAAO;EACb,MAAM,OAAO;EAEb,MAAM,QAAQ,OAAO,KAAK,KAAK;EAC/B,MAAM,QAAQ,OAAO,KAAK,KAAK;AAE/B,MAAI,MAAM,WAAW,MAAM,OAAQ,QAAO;AAE1C,OAAK,MAAM,OAAO,OAAO;AACvB,OAAI,CAAC,MAAM,SAAS,IAAI,CAAE,QAAO;AACjC,OAAI,CAAC,UAAU,KAAK,MAAM,KAAK,KAAK,CAAE,QAAO;;AAG/C,SAAO;;AAGT,QAAO;;;;;AAMT,SAAgB,UAAU,KAAc,MAAuB;CAC7D,MAAM,QAAQ,KAAK,MAAM,IAAI,CAAC,OAAO,QAAQ;CAC7C,IAAI,UAAmB;AAEvB,MAAK,MAAM,QAAQ,OAAO;AACxB,MAAI,YAAY,QAAQ,YAAY,OAAW,QAAO;AACtD,MAAI,OAAO,YAAY,SAAU,QAAO;AACxC,YAAW,QAAoC;;AAGjD,QAAO;;;;;;AAOT,SAAgB,kBAAkB,MAAwB;AAExD,SADgB,KAAK,MAAM,eAAe,IAAI,EAAE,EACjC,KAAK,MAAM,EAAE,MAAM,GAAG,GAAG,CAAC;;;;;AAM3C,SAAgB,cAAc,MAAsB;CAElD,IAAI,aAAa,KAAK,QAAQ,cAAc,GAAG;AAE/C,cAAa,WAAW,QAAQ,QAAQ,IAAI;AAE5C,QAAO,MAAM"}
@@ -1 +1 @@
1
- {"version":3,"file":"differ.js","names":["changeType: DiffChangeType","changes: DiffChange[]","diffs: SpecDiff[]","existing: AnyOperationSpec | undefined","lines: string[]"],"sources":["../../src/openapi/differ.ts"],"sourcesContent":["/**\n * Diff ContractSpec specs against OpenAPI operations.\n * Used for sync operations to detect changes.\n */\n\nimport type { AnyOperationSpec } from '@contractspec/lib.contracts';\nimport type { ParsedOperation } from './types';\nimport type {\n DiffChange,\n DiffChangeType,\n ImportedOperationSpec,\n SpecDiff,\n} from '../common/types';\nimport { deepEqual } from '../common/utils';\n\n/**\n * Options for diffing specs.\n */\nexport interface DiffOptions {\n /** Ignore description changes */\n ignoreDescriptions?: boolean;\n /** Ignore tag changes */\n ignoreTags?: boolean;\n /** Ignore transport changes (path, method) */\n ignoreTransport?: boolean;\n /** Custom paths to ignore */\n ignorePaths?: string[];\n}\n\n/**\n * Compare two values and generate a diff change if different.\n */\nfunction compareValues(\n path: string,\n oldValue: unknown,\n newValue: unknown,\n description: string\n): DiffChange | null {\n if (deepEqual(oldValue, newValue)) {\n return null;\n }\n\n let changeType: DiffChangeType = 'modified';\n if (oldValue === undefined || oldValue === null) {\n changeType = 'added';\n } else if (newValue === undefined || newValue === null) {\n changeType = 'removed';\n } else if (typeof oldValue !== typeof newValue) {\n changeType = 'type_changed';\n }\n\n return {\n path,\n type: changeType,\n oldValue,\n newValue,\n description,\n };\n}\n\n/**\n * Diff two objects recursively.\n */\nfunction diffObjects(\n path: string,\n oldObj: Record<string, unknown> | undefined,\n newObj: Record<string, unknown> | undefined,\n options: DiffOptions\n): DiffChange[] {\n const changes: DiffChange[] = [];\n\n if (!oldObj && !newObj) return changes;\n if (!oldObj) {\n changes.push({\n path,\n type: 'added',\n newValue: newObj,\n description: `Added ${path}`,\n });\n return changes;\n }\n if (!newObj) {\n changes.push({\n path,\n type: 'removed',\n oldValue: oldObj,\n description: `Removed ${path}`,\n });\n return changes;\n }\n\n const allKeys = new Set([...Object.keys(oldObj), ...Object.keys(newObj)]);\n\n for (const key of allKeys) {\n const keyPath = path ? `${path}.${key}` : key;\n\n // Skip ignored paths\n if (options.ignorePaths?.some((p) => keyPath.startsWith(p))) {\n continue;\n }\n\n const oldVal = oldObj[key];\n const newVal = newObj[key];\n\n if (typeof oldVal === 'object' && typeof newVal === 'object') {\n changes.push(\n ...diffObjects(\n keyPath,\n oldVal as Record<string, unknown>,\n newVal as Record<string, unknown>,\n options\n )\n );\n } else {\n const change = compareValues(\n keyPath,\n oldVal,\n newVal,\n `Changed ${keyPath}`\n );\n if (change) {\n changes.push(change);\n }\n }\n }\n\n return changes;\n}\n\n/**\n * Diff a ContractSpec against an OpenAPI operation.\n */\nexport function diffSpecVsOperation(\n spec: AnyOperationSpec,\n operation: ParsedOperation,\n options: DiffOptions = {}\n): DiffChange[] {\n const changes: DiffChange[] = [];\n\n // Compare basic metadata\n if (!options.ignoreDescriptions) {\n const descChange = compareValues(\n 'meta.description',\n spec.meta.description,\n operation.summary ?? operation.description,\n 'Description changed'\n );\n if (descChange) changes.push(descChange);\n }\n\n if (!options.ignoreTags) {\n const oldTags = [...(spec.meta.tags ?? [])].sort();\n const newTags = [...operation.tags].sort();\n if (!deepEqual(oldTags, newTags)) {\n changes.push({\n path: 'meta.tags',\n type: 'modified',\n oldValue: oldTags,\n newValue: newTags,\n description: 'Tags changed',\n });\n }\n }\n\n // Compare transport\n if (!options.ignoreTransport) {\n const specMethod =\n spec.transport?.rest?.method ??\n (spec.meta.kind === 'query' ? 'GET' : 'POST');\n const opMethod = operation.method.toUpperCase();\n\n if (specMethod !== opMethod) {\n changes.push({\n path: 'transport.rest.method',\n type: 'modified',\n oldValue: specMethod,\n newValue: opMethod,\n description: 'HTTP method changed',\n });\n }\n\n const specPath = spec.transport?.rest?.path;\n if (specPath && specPath !== operation.path) {\n changes.push({\n path: 'transport.rest.path',\n type: 'modified',\n oldValue: specPath,\n newValue: operation.path,\n description: 'Path changed',\n });\n }\n }\n\n // Compare deprecation status\n const specDeprecated = spec.meta.stability === 'deprecated';\n if (specDeprecated !== operation.deprecated) {\n changes.push({\n path: 'meta.stability',\n type: 'modified',\n oldValue: spec.meta.stability,\n newValue: operation.deprecated ? 'deprecated' : 'stable',\n description: 'Deprecation status changed',\n });\n }\n\n return changes;\n}\n\n/**\n * Diff two ContractSpecs.\n */\nexport function diffSpecs(\n oldSpec: AnyOperationSpec,\n newSpec: AnyOperationSpec,\n options: DiffOptions = {}\n): DiffChange[] {\n const changes: DiffChange[] = [];\n\n // Compare meta\n const metaChanges = diffObjects(\n 'meta',\n oldSpec.meta as unknown as Record<string, unknown>,\n newSpec.meta as unknown as Record<string, unknown>,\n {\n ...options,\n ignorePaths: [\n ...(options.ignorePaths ?? []),\n ...(options.ignoreDescriptions\n ? ['meta.description', 'meta.goal', 'meta.context']\n : []),\n ...(options.ignoreTags ? ['meta.tags'] : []),\n ],\n }\n );\n changes.push(...metaChanges);\n\n // Compare transport\n if (!options.ignoreTransport) {\n const transportChanges = diffObjects(\n 'transport',\n oldSpec.transport as unknown as Record<string, unknown>,\n newSpec.transport as unknown as Record<string, unknown>,\n options\n );\n changes.push(...transportChanges);\n }\n\n // Compare policy\n const policyChanges = diffObjects(\n 'policy',\n oldSpec.policy as unknown as Record<string, unknown>,\n newSpec.policy as unknown as Record<string, unknown>,\n options\n );\n changes.push(...policyChanges);\n\n return changes;\n}\n\n/**\n * Create a SpecDiff from an existing spec and an imported spec.\n */\nexport function createSpecDiff(\n operationId: string,\n existing: AnyOperationSpec | undefined,\n incoming: ImportedOperationSpec,\n options: DiffOptions = {}\n): SpecDiff {\n let changes: DiffChange[] = [];\n let isEquivalent = false;\n\n if (existing && incoming.operationSpec) {\n // Compare existing vs incoming\n changes = diffSpecs(existing, incoming.operationSpec, options);\n isEquivalent = changes.length === 0;\n } else if (existing && !incoming.operationSpec) {\n // Incoming has code but no runtime spec - can't compare directly\n changes = [\n {\n path: '',\n type: 'modified',\n oldValue: existing,\n newValue: incoming.code,\n description:\n 'Spec code imported from OpenAPI (runtime comparison not available)',\n },\n ];\n } else {\n // New spec - mark as added\n changes = [\n {\n path: '',\n type: 'added',\n newValue: incoming.operationSpec ?? incoming.code,\n description: 'New spec imported from OpenAPI',\n },\n ];\n }\n\n return {\n operationId,\n existing,\n incoming,\n changes,\n isEquivalent,\n };\n}\n\n/**\n * Batch diff multiple specs against OpenAPI operations.\n */\nexport function diffAll(\n existingSpecs: Map<string, AnyOperationSpec>,\n importedSpecs: ImportedOperationSpec[],\n options: DiffOptions = {}\n): SpecDiff[] {\n const diffs: SpecDiff[] = [];\n\n // Track which existing specs have been matched\n const matchedExisting = new Set<string>();\n\n for (const imported of importedSpecs) {\n const operationId = imported.source.sourceId;\n\n // Try to find matching existing spec\n // Match by operationId in x-contractspec extension or by name\n let existing: AnyOperationSpec | undefined;\n\n for (const [key, spec] of existingSpecs) {\n // Check x-contractspec match or name match\n const specName = spec.meta.key;\n if (key === operationId || specName.includes(operationId)) {\n existing = spec;\n matchedExisting.add(key);\n break;\n }\n }\n\n diffs.push(createSpecDiff(operationId, existing, imported, options));\n }\n\n // Add diffs for existing specs that weren't matched (removed from OpenAPI)\n for (const [key, spec] of existingSpecs) {\n if (!matchedExisting.has(key)) {\n diffs.push({\n operationId: key,\n existing: spec,\n incoming: undefined as unknown as ImportedOperationSpec,\n changes: [\n {\n path: '',\n type: 'removed',\n oldValue: spec,\n description: 'Spec no longer exists in OpenAPI source',\n },\n ],\n isEquivalent: false,\n });\n }\n }\n\n return diffs;\n}\n\n/**\n * Format diff changes for display.\n */\nexport function formatDiffChanges(changes: DiffChange[]): string {\n if (changes.length === 0) {\n return 'No changes detected';\n }\n\n const lines: string[] = [];\n\n for (const change of changes) {\n const prefix = {\n added: '+',\n removed: '-',\n modified: '~',\n type_changed: '!',\n required_changed: '?',\n }[change.type];\n\n lines.push(`${prefix} ${change.path}: ${change.description}`);\n\n if (change.type === 'modified' || change.type === 'type_changed') {\n lines.push(` old: ${JSON.stringify(change.oldValue)}`);\n lines.push(` new: ${JSON.stringify(change.newValue)}`);\n } else if (change.type === 'added') {\n lines.push(` value: ${JSON.stringify(change.newValue)}`);\n } else if (change.type === 'removed') {\n lines.push(` was: ${JSON.stringify(change.oldValue)}`);\n }\n }\n\n return lines.join('\\n');\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"differ.js","names":[],"sources":["../../src/openapi/differ.ts"],"sourcesContent":["/**\n * Diff ContractSpec specs against OpenAPI operations.\n * Used for sync operations to detect changes.\n */\n\nimport type { AnyOperationSpec } from '@contractspec/lib.contracts';\nimport type { ParsedOperation } from './types';\nimport type {\n DiffChange,\n DiffChangeType,\n ImportedOperationSpec,\n SpecDiff,\n} from '../common/types';\nimport { deepEqual } from '../common/utils';\n\n/**\n * Options for diffing specs.\n */\nexport interface DiffOptions {\n /** Ignore description changes */\n ignoreDescriptions?: boolean;\n /** Ignore tag changes */\n ignoreTags?: boolean;\n /** Ignore transport changes (path, method) */\n ignoreTransport?: boolean;\n /** Custom paths to ignore */\n ignorePaths?: string[];\n}\n\n/**\n * Compare two values and generate a diff change if different.\n */\nfunction compareValues(\n path: string,\n oldValue: unknown,\n newValue: unknown,\n description: string\n): DiffChange | null {\n if (deepEqual(oldValue, newValue)) {\n return null;\n }\n\n let changeType: DiffChangeType = 'modified';\n if (oldValue === undefined || oldValue === null) {\n changeType = 'added';\n } else if (newValue === undefined || newValue === null) {\n changeType = 'removed';\n } else if (typeof oldValue !== typeof newValue) {\n changeType = 'type_changed';\n }\n\n return {\n path,\n type: changeType,\n oldValue,\n newValue,\n description,\n };\n}\n\n/**\n * Diff two objects recursively.\n */\nfunction diffObjects(\n path: string,\n oldObj: Record<string, unknown> | undefined,\n newObj: Record<string, unknown> | undefined,\n options: DiffOptions\n): DiffChange[] {\n const changes: DiffChange[] = [];\n\n if (!oldObj && !newObj) return changes;\n if (!oldObj) {\n changes.push({\n path,\n type: 'added',\n newValue: newObj,\n description: `Added ${path}`,\n });\n return changes;\n }\n if (!newObj) {\n changes.push({\n path,\n type: 'removed',\n oldValue: oldObj,\n description: `Removed ${path}`,\n });\n return changes;\n }\n\n const allKeys = new Set([...Object.keys(oldObj), ...Object.keys(newObj)]);\n\n for (const key of allKeys) {\n const keyPath = path ? `${path}.${key}` : key;\n\n // Skip ignored paths\n if (options.ignorePaths?.some((p) => keyPath.startsWith(p))) {\n continue;\n }\n\n const oldVal = oldObj[key];\n const newVal = newObj[key];\n\n if (typeof oldVal === 'object' && typeof newVal === 'object') {\n changes.push(\n ...diffObjects(\n keyPath,\n oldVal as Record<string, unknown>,\n newVal as Record<string, unknown>,\n options\n )\n );\n } else {\n const change = compareValues(\n keyPath,\n oldVal,\n newVal,\n `Changed ${keyPath}`\n );\n if (change) {\n changes.push(change);\n }\n }\n }\n\n return changes;\n}\n\n/**\n * Diff a ContractSpec against an OpenAPI operation.\n */\nexport function diffSpecVsOperation(\n spec: AnyOperationSpec,\n operation: ParsedOperation,\n options: DiffOptions = {}\n): DiffChange[] {\n const changes: DiffChange[] = [];\n\n // Compare basic metadata\n if (!options.ignoreDescriptions) {\n const descChange = compareValues(\n 'meta.description',\n spec.meta.description,\n operation.summary ?? operation.description,\n 'Description changed'\n );\n if (descChange) changes.push(descChange);\n }\n\n if (!options.ignoreTags) {\n const oldTags = [...(spec.meta.tags ?? [])].sort();\n const newTags = [...operation.tags].sort();\n if (!deepEqual(oldTags, newTags)) {\n changes.push({\n path: 'meta.tags',\n type: 'modified',\n oldValue: oldTags,\n newValue: newTags,\n description: 'Tags changed',\n });\n }\n }\n\n // Compare transport\n if (!options.ignoreTransport) {\n const specMethod =\n spec.transport?.rest?.method ??\n (spec.meta.kind === 'query' ? 'GET' : 'POST');\n const opMethod = operation.method.toUpperCase();\n\n if (specMethod !== opMethod) {\n changes.push({\n path: 'transport.rest.method',\n type: 'modified',\n oldValue: specMethod,\n newValue: opMethod,\n description: 'HTTP method changed',\n });\n }\n\n const specPath = spec.transport?.rest?.path;\n if (specPath && specPath !== operation.path) {\n changes.push({\n path: 'transport.rest.path',\n type: 'modified',\n oldValue: specPath,\n newValue: operation.path,\n description: 'Path changed',\n });\n }\n }\n\n // Compare deprecation status\n const specDeprecated = spec.meta.stability === 'deprecated';\n if (specDeprecated !== operation.deprecated) {\n changes.push({\n path: 'meta.stability',\n type: 'modified',\n oldValue: spec.meta.stability,\n newValue: operation.deprecated ? 'deprecated' : 'stable',\n description: 'Deprecation status changed',\n });\n }\n\n return changes;\n}\n\n/**\n * Diff two ContractSpecs.\n */\nexport function diffSpecs(\n oldSpec: AnyOperationSpec,\n newSpec: AnyOperationSpec,\n options: DiffOptions = {}\n): DiffChange[] {\n const changes: DiffChange[] = [];\n\n // Compare meta\n const metaChanges = diffObjects(\n 'meta',\n oldSpec.meta as unknown as Record<string, unknown>,\n newSpec.meta as unknown as Record<string, unknown>,\n {\n ...options,\n ignorePaths: [\n ...(options.ignorePaths ?? []),\n ...(options.ignoreDescriptions\n ? ['meta.description', 'meta.goal', 'meta.context']\n : []),\n ...(options.ignoreTags ? ['meta.tags'] : []),\n ],\n }\n );\n changes.push(...metaChanges);\n\n // Compare transport\n if (!options.ignoreTransport) {\n const transportChanges = diffObjects(\n 'transport',\n oldSpec.transport as unknown as Record<string, unknown>,\n newSpec.transport as unknown as Record<string, unknown>,\n options\n );\n changes.push(...transportChanges);\n }\n\n // Compare policy\n const policyChanges = diffObjects(\n 'policy',\n oldSpec.policy as unknown as Record<string, unknown>,\n newSpec.policy as unknown as Record<string, unknown>,\n options\n );\n changes.push(...policyChanges);\n\n return changes;\n}\n\n/**\n * Create a SpecDiff from an existing spec and an imported spec.\n */\nexport function createSpecDiff(\n operationId: string,\n existing: AnyOperationSpec | undefined,\n incoming: ImportedOperationSpec,\n options: DiffOptions = {}\n): SpecDiff {\n let changes: DiffChange[] = [];\n let isEquivalent = false;\n\n if (existing && incoming.operationSpec) {\n // Compare existing vs incoming\n changes = diffSpecs(existing, incoming.operationSpec, options);\n isEquivalent = changes.length === 0;\n } else if (existing && !incoming.operationSpec) {\n // Incoming has code but no runtime spec - can't compare directly\n changes = [\n {\n path: '',\n type: 'modified',\n oldValue: existing,\n newValue: incoming.code,\n description:\n 'Spec code imported from OpenAPI (runtime comparison not available)',\n },\n ];\n } else {\n // New spec - mark as added\n changes = [\n {\n path: '',\n type: 'added',\n newValue: incoming.operationSpec ?? incoming.code,\n description: 'New spec imported from OpenAPI',\n },\n ];\n }\n\n return {\n operationId,\n existing,\n incoming,\n changes,\n isEquivalent,\n };\n}\n\n/**\n * Batch diff multiple specs against OpenAPI operations.\n */\nexport function diffAll(\n existingSpecs: Map<string, AnyOperationSpec>,\n importedSpecs: ImportedOperationSpec[],\n options: DiffOptions = {}\n): SpecDiff[] {\n const diffs: SpecDiff[] = [];\n\n // Track which existing specs have been matched\n const matchedExisting = new Set<string>();\n\n for (const imported of importedSpecs) {\n const operationId = imported.source.sourceId;\n\n // Try to find matching existing spec\n // Match by operationId in x-contractspec extension or by name\n let existing: AnyOperationSpec | undefined;\n\n for (const [key, spec] of existingSpecs) {\n // Check x-contractspec match or name match\n const specName = spec.meta.key;\n if (key === operationId || specName.includes(operationId)) {\n existing = spec;\n matchedExisting.add(key);\n break;\n }\n }\n\n diffs.push(createSpecDiff(operationId, existing, imported, options));\n }\n\n // Add diffs for existing specs that weren't matched (removed from OpenAPI)\n for (const [key, spec] of existingSpecs) {\n if (!matchedExisting.has(key)) {\n diffs.push({\n operationId: key,\n existing: spec,\n incoming: undefined as unknown as ImportedOperationSpec,\n changes: [\n {\n path: '',\n type: 'removed',\n oldValue: spec,\n description: 'Spec no longer exists in OpenAPI source',\n },\n ],\n isEquivalent: false,\n });\n }\n }\n\n return diffs;\n}\n\n/**\n * Format diff changes for display.\n */\nexport function formatDiffChanges(changes: DiffChange[]): string {\n if (changes.length === 0) {\n return 'No changes detected';\n }\n\n const lines: string[] = [];\n\n for (const change of changes) {\n const prefix = {\n added: '+',\n removed: '-',\n modified: '~',\n type_changed: '!',\n required_changed: '?',\n }[change.type];\n\n lines.push(`${prefix} ${change.path}: ${change.description}`);\n\n if (change.type === 'modified' || change.type === 'type_changed') {\n lines.push(` old: ${JSON.stringify(change.oldValue)}`);\n lines.push(` new: ${JSON.stringify(change.newValue)}`);\n } else if (change.type === 'added') {\n lines.push(` value: ${JSON.stringify(change.newValue)}`);\n } else if (change.type === 'removed') {\n lines.push(` was: ${JSON.stringify(change.oldValue)}`);\n }\n }\n\n return lines.join('\\n');\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"data-views.js","names":["registrations: string[]"],"sources":["../../../src/openapi/exporter/data-views.ts"],"sourcesContent":["/**\n * Data views exporter - exports DataViewSpec to OpenAPI extensions.\n */\nimport type { DataViewRegistry } from '@contractspec/lib.contracts';\nimport type { GeneratedRegistryCode } from '../types';\n\n/**\n * Exported data view structure for OpenAPI extensions.\n */\nexport interface ExportedDataView {\n name: string;\n version: string;\n description?: string;\n stability?: string;\n entity: string;\n kind: 'list' | 'detail' | 'table' | 'grid';\n source: {\n primary: { key: string; version: string };\n item?: { key: string; version: string };\n };\n fields: unknown[];\n}\n\n/**\n * Export data views to OpenAPI extension format.\n */\nexport function exportDataViews(\n registry: DataViewRegistry\n): ExportedDataView[] {\n return registry.list().map((dv) => ({\n name: dv.meta.key,\n version: dv.meta.version,\n description: dv.meta.description,\n stability: dv.meta.stability,\n entity: dv.meta.entity,\n kind: dv.view.kind,\n source: dv.source,\n fields: dv.view.fields,\n }));\n}\n\n/**\n * Generate TypeScript code for data views registry.\n */\nexport function generateDataViewsRegistry(\n registry: DataViewRegistry\n): GeneratedRegistryCode {\n const dataViews = registry.list();\n const imports = new Set<string>();\n const registrations: string[] = [];\n\n for (const dv of dataViews) {\n const dvVarName = dv.meta.key.replace(/\\./g, '_') + `_v${dv.meta.version}`;\n imports.add(\n `import { ${dvVarName} } from './${dv.meta.key.split('.')[0]}';`\n );\n registrations.push(` .register(${dvVarName})`);\n }\n\n const code = `/**\n * Auto-generated data views registry.\n * DO NOT EDIT - This file is generated by ContractSpec exporter.\n */\nimport { DataViewRegistry } from '@contractspec/lib.contracts';\n\n${Array.from(imports).join('\\n')}\n\nexport const dataViewsRegistry = new DataViewRegistry()\n${registrations.join('\\n')};\n`;\n\n return {\n code,\n fileName: 'dataviews-registry.ts',\n };\n}\n"],"mappings":";;;;AA0BA,SAAgB,gBACd,UACoB;AACpB,QAAO,SAAS,MAAM,CAAC,KAAK,QAAQ;EAClC,MAAM,GAAG,KAAK;EACd,SAAS,GAAG,KAAK;EACjB,aAAa,GAAG,KAAK;EACrB,WAAW,GAAG,KAAK;EACnB,QAAQ,GAAG,KAAK;EAChB,MAAM,GAAG,KAAK;EACd,QAAQ,GAAG;EACX,QAAQ,GAAG,KAAK;EACjB,EAAE;;;;;AAML,SAAgB,0BACd,UACuB;CACvB,MAAM,YAAY,SAAS,MAAM;CACjC,MAAM,0BAAU,IAAI,KAAa;CACjC,MAAMA,gBAA0B,EAAE;AAElC,MAAK,MAAM,MAAM,WAAW;EAC1B,MAAM,YAAY,GAAG,KAAK,IAAI,QAAQ,OAAO,IAAI,GAAG,KAAK,GAAG,KAAK;AACjE,UAAQ,IACN,YAAY,UAAU,aAAa,GAAG,KAAK,IAAI,MAAM,IAAI,CAAC,GAAG,IAC9D;AACD,gBAAc,KAAK,eAAe,UAAU,GAAG;;AAejD,QAAO;EACL,MAbW;;;;;;EAMb,MAAM,KAAK,QAAQ,CAAC,KAAK,KAAK,CAAC;;;EAG/B,cAAc,KAAK,KAAK,CAAC;;EAKvB,UAAU;EACX"}
1
+ {"version":3,"file":"data-views.js","names":[],"sources":["../../../src/openapi/exporter/data-views.ts"],"sourcesContent":["/**\n * Data views exporter - exports DataViewSpec to OpenAPI extensions.\n */\nimport type { DataViewRegistry } from '@contractspec/lib.contracts';\nimport type { GeneratedRegistryCode } from '../types';\n\n/**\n * Exported data view structure for OpenAPI extensions.\n */\nexport interface ExportedDataView {\n name: string;\n version: string;\n description?: string;\n stability?: string;\n entity: string;\n kind: 'list' | 'detail' | 'table' | 'grid';\n source: {\n primary: { key: string; version: string };\n item?: { key: string; version: string };\n };\n fields: unknown[];\n}\n\n/**\n * Export data views to OpenAPI extension format.\n */\nexport function exportDataViews(\n registry: DataViewRegistry\n): ExportedDataView[] {\n return registry.list().map((dv) => ({\n name: dv.meta.key,\n version: dv.meta.version,\n description: dv.meta.description,\n stability: dv.meta.stability,\n entity: dv.meta.entity,\n kind: dv.view.kind,\n source: dv.source,\n fields: dv.view.fields,\n }));\n}\n\n/**\n * Generate TypeScript code for data views registry.\n */\nexport function generateDataViewsRegistry(\n registry: DataViewRegistry\n): GeneratedRegistryCode {\n const dataViews = registry.list();\n const imports = new Set<string>();\n const registrations: string[] = [];\n\n for (const dv of dataViews) {\n const dvVarName = dv.meta.key.replace(/\\./g, '_') + `_v${dv.meta.version}`;\n imports.add(\n `import { ${dvVarName} } from './${dv.meta.key.split('.')[0]}';`\n );\n registrations.push(` .register(${dvVarName})`);\n }\n\n const code = `/**\n * Auto-generated data views registry.\n * DO NOT EDIT - This file is generated by ContractSpec exporter.\n */\nimport { DataViewRegistry } from '@contractspec/lib.contracts';\n\n${Array.from(imports).join('\\n')}\n\nexport const dataViewsRegistry = new DataViewRegistry()\n${registrations.join('\\n')};\n`;\n\n return {\n code,\n fileName: 'dataviews-registry.ts',\n };\n}\n"],"mappings":";;;;AA0BA,SAAgB,gBACd,UACoB;AACpB,QAAO,SAAS,MAAM,CAAC,KAAK,QAAQ;EAClC,MAAM,GAAG,KAAK;EACd,SAAS,GAAG,KAAK;EACjB,aAAa,GAAG,KAAK;EACrB,WAAW,GAAG,KAAK;EACnB,QAAQ,GAAG,KAAK;EAChB,MAAM,GAAG,KAAK;EACd,QAAQ,GAAG;EACX,QAAQ,GAAG,KAAK;EACjB,EAAE;;;;;AAML,SAAgB,0BACd,UACuB;CACvB,MAAM,YAAY,SAAS,MAAM;CACjC,MAAM,0BAAU,IAAI,KAAa;CACjC,MAAM,gBAA0B,EAAE;AAElC,MAAK,MAAM,MAAM,WAAW;EAC1B,MAAM,YAAY,GAAG,KAAK,IAAI,QAAQ,OAAO,IAAI,GAAG,KAAK,GAAG,KAAK;AACjE,UAAQ,IACN,YAAY,UAAU,aAAa,GAAG,KAAK,IAAI,MAAM,IAAI,CAAC,GAAG,IAC9D;AACD,gBAAc,KAAK,eAAe,UAAU,GAAG;;AAejD,QAAO;EACL,MAbW;;;;;;EAMb,MAAM,KAAK,QAAQ,CAAC,KAAK,KAAK,CAAC;;;EAG/B,cAAc,KAAK,KAAK,CAAC;;EAKvB,UAAU;EACX"}
@@ -1 +1 @@
1
- {"version":3,"file":"events.js","names":["eventExports: string[]"],"sources":["../../../src/openapi/exporter/events.ts"],"sourcesContent":["/**\n * Events exporter - exports EventSpec to OpenAPI extensions.\n */\nimport type { EventSpec } from '@contractspec/lib.contracts';\nimport type { AnySchemaModel } from '@contractspec/lib.schema';\nimport { z } from 'zod';\nimport type { GeneratedRegistryCode } from '../types';\n\ntype OpenApiSchemaObject = Record<string, unknown>;\n\n/**\n * Exported event structure for OpenAPI extensions.\n */\nexport interface ExportedEvent {\n name: string;\n version: string;\n description: string;\n payload: OpenApiSchemaObject | null;\n pii?: string[];\n}\n\n/**\n * Export events to OpenAPI extension format.\n */\nexport function exportEvents(\n events: EventSpec<AnySchemaModel>[]\n): ExportedEvent[] {\n return events.map((event) => ({\n name: event.meta.key,\n version: event.meta.version,\n description: event.meta.description,\n payload: event.payload\n ? (z.toJSONSchema(event.payload.getZod()) as OpenApiSchemaObject)\n : null,\n pii: event.pii,\n }));\n}\n\n/**\n * Generate TypeScript code for events exports.\n */\nexport function generateEventsExports(\n events: EventSpec<AnySchemaModel>[]\n): GeneratedRegistryCode {\n const eventExports: string[] = [];\n\n for (const event of events) {\n const eventVarName =\n event.meta.key.replace(/\\./g, '_') + `_v${event.meta.version}`;\n eventExports.push(\n `export { ${eventVarName} } from './${event.meta.key.split('.')[0]}';`\n );\n }\n\n const code = `/**\n * Auto-generated events exports.\n * DO NOT EDIT - This file is generated by ContractSpec exporter.\n */\n\n${eventExports.join('\\n')}\n`;\n\n return {\n code,\n fileName: 'events-exports.ts',\n };\n}\n"],"mappings":";;;;;;AAwBA,SAAgB,aACd,QACiB;AACjB,QAAO,OAAO,KAAK,WAAW;EAC5B,MAAM,MAAM,KAAK;EACjB,SAAS,MAAM,KAAK;EACpB,aAAa,MAAM,KAAK;EACxB,SAAS,MAAM,UACV,EAAE,aAAa,MAAM,QAAQ,QAAQ,CAAC,GACvC;EACJ,KAAK,MAAM;EACZ,EAAE;;;;;AAML,SAAgB,sBACd,QACuB;CACvB,MAAMA,eAAyB,EAAE;AAEjC,MAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,eACJ,MAAM,KAAK,IAAI,QAAQ,OAAO,IAAI,GAAG,KAAK,MAAM,KAAK;AACvD,eAAa,KACX,YAAY,aAAa,aAAa,MAAM,KAAK,IAAI,MAAM,IAAI,CAAC,GAAG,IACpE;;AAWH,QAAO;EACL,MATW;;;;;EAKb,aAAa,KAAK,KAAK,CAAC;;EAKtB,UAAU;EACX"}
1
+ {"version":3,"file":"events.js","names":[],"sources":["../../../src/openapi/exporter/events.ts"],"sourcesContent":["/**\n * Events exporter - exports EventSpec to OpenAPI extensions.\n */\nimport type { EventSpec } from '@contractspec/lib.contracts';\nimport type { AnySchemaModel } from '@contractspec/lib.schema';\nimport { z } from 'zod';\nimport type { GeneratedRegistryCode } from '../types';\n\ntype OpenApiSchemaObject = Record<string, unknown>;\n\n/**\n * Exported event structure for OpenAPI extensions.\n */\nexport interface ExportedEvent {\n name: string;\n version: string;\n description: string;\n payload: OpenApiSchemaObject | null;\n pii?: string[];\n}\n\n/**\n * Export events to OpenAPI extension format.\n */\nexport function exportEvents(\n events: EventSpec<AnySchemaModel>[]\n): ExportedEvent[] {\n return events.map((event) => ({\n name: event.meta.key,\n version: event.meta.version,\n description: event.meta.description,\n payload: event.payload\n ? (z.toJSONSchema(event.payload.getZod()) as OpenApiSchemaObject)\n : null,\n pii: event.pii,\n }));\n}\n\n/**\n * Generate TypeScript code for events exports.\n */\nexport function generateEventsExports(\n events: EventSpec<AnySchemaModel>[]\n): GeneratedRegistryCode {\n const eventExports: string[] = [];\n\n for (const event of events) {\n const eventVarName =\n event.meta.key.replace(/\\./g, '_') + `_v${event.meta.version}`;\n eventExports.push(\n `export { ${eventVarName} } from './${event.meta.key.split('.')[0]}';`\n );\n }\n\n const code = `/**\n * Auto-generated events exports.\n * DO NOT EDIT - This file is generated by ContractSpec exporter.\n */\n\n${eventExports.join('\\n')}\n`;\n\n return {\n code,\n fileName: 'events-exports.ts',\n };\n}\n"],"mappings":";;;;;;AAwBA,SAAgB,aACd,QACiB;AACjB,QAAO,OAAO,KAAK,WAAW;EAC5B,MAAM,MAAM,KAAK;EACjB,SAAS,MAAM,KAAK;EACpB,aAAa,MAAM,KAAK;EACxB,SAAS,MAAM,UACV,EAAE,aAAa,MAAM,QAAQ,QAAQ,CAAC,GACvC;EACJ,KAAK,MAAM;EACZ,EAAE;;;;;AAML,SAAgB,sBACd,QACuB;CACvB,MAAM,eAAyB,EAAE;AAEjC,MAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,eACJ,MAAM,KAAK,IAAI,QAAQ,OAAO,IAAI,GAAG,KAAK,MAAM,KAAK;AACvD,eAAa,KACX,YAAY,aAAa,aAAa,MAAM,KAAK,IAAI,MAAM,IAAI,CAAC,GAAG,IACpE;;AAWH,QAAO;EACL,MATW;;;;;EAKb,aAAa,KAAK,KAAK,CAAC;;EAKtB,UAAU;EACX"}
@@ -1 +1 @@
1
- {"version":3,"file":"features.js","names":["registrations: string[]"],"sources":["../../../src/openapi/exporter/features.ts"],"sourcesContent":["/**\n * Features exporter - exports FeatureModuleSpec to OpenAPI extensions.\n */\nimport type { FeatureRegistry } from '@contractspec/lib.contracts';\nimport type { GeneratedRegistryCode } from '../types';\n\n/**\n * Exported feature structure for OpenAPI extensions.\n */\nexport interface ExportedFeature {\n key: string;\n description?: string;\n owners?: string[];\n stability?: string;\n operations?: { key: string; version: string }[];\n events?: { key: string; version: string }[];\n presentations?: { key: string; version: string }[];\n}\n\n/**\n * Export features to OpenAPI extension format.\n */\nexport function exportFeatures(registry: FeatureRegistry): ExportedFeature[] {\n return registry.list().map((feature) => ({\n key: feature.meta.key,\n description: feature.meta.description,\n owners: feature.meta.owners,\n stability: feature.meta.stability,\n operations: feature.operations,\n events: feature.events,\n presentations: feature.presentations,\n }));\n}\n\n/**\n * Generate TypeScript code for features registry.\n */\nexport function generateFeaturesRegistry(\n registry: FeatureRegistry\n): GeneratedRegistryCode {\n const features = registry.list();\n const imports = new Set<string>();\n const registrations: string[] = [];\n\n for (const feature of features) {\n const featureVarName = feature.meta.key.replace(/-/g, '_');\n imports.add(`import { ${featureVarName} } from './${feature.meta.key}';`);\n registrations.push(` .register(${featureVarName})`);\n }\n\n const code = `/**\n * Auto-generated features registry.\n * DO NOT EDIT - This file is generated by ContractSpec exporter.\n */\nimport { FeatureRegistry } from '@contractspec/lib.contracts';\n\n${Array.from(imports).join('\\n')}\n\nexport const featuresRegistry = new FeatureRegistry()\n${registrations.join('\\n')};\n`;\n\n return {\n code,\n fileName: 'features-registry.ts',\n };\n}\n"],"mappings":";;;;AAsBA,SAAgB,eAAe,UAA8C;AAC3E,QAAO,SAAS,MAAM,CAAC,KAAK,aAAa;EACvC,KAAK,QAAQ,KAAK;EAClB,aAAa,QAAQ,KAAK;EAC1B,QAAQ,QAAQ,KAAK;EACrB,WAAW,QAAQ,KAAK;EACxB,YAAY,QAAQ;EACpB,QAAQ,QAAQ;EAChB,eAAe,QAAQ;EACxB,EAAE;;;;;AAML,SAAgB,yBACd,UACuB;CACvB,MAAM,WAAW,SAAS,MAAM;CAChC,MAAM,0BAAU,IAAI,KAAa;CACjC,MAAMA,gBAA0B,EAAE;AAElC,MAAK,MAAM,WAAW,UAAU;EAC9B,MAAM,iBAAiB,QAAQ,KAAK,IAAI,QAAQ,MAAM,IAAI;AAC1D,UAAQ,IAAI,YAAY,eAAe,aAAa,QAAQ,KAAK,IAAI,IAAI;AACzE,gBAAc,KAAK,eAAe,eAAe,GAAG;;AAetD,QAAO;EACL,MAbW;;;;;;EAMb,MAAM,KAAK,QAAQ,CAAC,KAAK,KAAK,CAAC;;;EAG/B,cAAc,KAAK,KAAK,CAAC;;EAKvB,UAAU;EACX"}
1
+ {"version":3,"file":"features.js","names":[],"sources":["../../../src/openapi/exporter/features.ts"],"sourcesContent":["/**\n * Features exporter - exports FeatureModuleSpec to OpenAPI extensions.\n */\nimport type { FeatureRegistry } from '@contractspec/lib.contracts';\nimport type { GeneratedRegistryCode } from '../types';\n\n/**\n * Exported feature structure for OpenAPI extensions.\n */\nexport interface ExportedFeature {\n key: string;\n description?: string;\n owners?: string[];\n stability?: string;\n operations?: { key: string; version: string }[];\n events?: { key: string; version: string }[];\n presentations?: { key: string; version: string }[];\n}\n\n/**\n * Export features to OpenAPI extension format.\n */\nexport function exportFeatures(registry: FeatureRegistry): ExportedFeature[] {\n return registry.list().map((feature) => ({\n key: feature.meta.key,\n description: feature.meta.description,\n owners: feature.meta.owners,\n stability: feature.meta.stability,\n operations: feature.operations,\n events: feature.events,\n presentations: feature.presentations,\n }));\n}\n\n/**\n * Generate TypeScript code for features registry.\n */\nexport function generateFeaturesRegistry(\n registry: FeatureRegistry\n): GeneratedRegistryCode {\n const features = registry.list();\n const imports = new Set<string>();\n const registrations: string[] = [];\n\n for (const feature of features) {\n const featureVarName = feature.meta.key.replace(/-/g, '_');\n imports.add(`import { ${featureVarName} } from './${feature.meta.key}';`);\n registrations.push(` .register(${featureVarName})`);\n }\n\n const code = `/**\n * Auto-generated features registry.\n * DO NOT EDIT - This file is generated by ContractSpec exporter.\n */\nimport { FeatureRegistry } from '@contractspec/lib.contracts';\n\n${Array.from(imports).join('\\n')}\n\nexport const featuresRegistry = new FeatureRegistry()\n${registrations.join('\\n')};\n`;\n\n return {\n code,\n fileName: 'features-registry.ts',\n };\n}\n"],"mappings":";;;;AAsBA,SAAgB,eAAe,UAA8C;AAC3E,QAAO,SAAS,MAAM,CAAC,KAAK,aAAa;EACvC,KAAK,QAAQ,KAAK;EAClB,aAAa,QAAQ,KAAK;EAC1B,QAAQ,QAAQ,KAAK;EACrB,WAAW,QAAQ,KAAK;EACxB,YAAY,QAAQ;EACpB,QAAQ,QAAQ;EAChB,eAAe,QAAQ;EACxB,EAAE;;;;;AAML,SAAgB,yBACd,UACuB;CACvB,MAAM,WAAW,SAAS,MAAM;CAChC,MAAM,0BAAU,IAAI,KAAa;CACjC,MAAM,gBAA0B,EAAE;AAElC,MAAK,MAAM,WAAW,UAAU;EAC9B,MAAM,iBAAiB,QAAQ,KAAK,IAAI,QAAQ,MAAM,IAAI;AAC1D,UAAQ,IAAI,YAAY,eAAe,aAAa,QAAQ,KAAK,IAAI,IAAI;AACzE,gBAAc,KAAK,eAAe,eAAe,GAAG;;AAetD,QAAO;EACL,MAbW;;;;;;EAMb,MAAM,KAAK,QAAQ,CAAC,KAAK,KAAK,CAAC;;;EAG/B,cAAc,KAAK,KAAK,CAAC;;EAKvB,UAAU;EACX"}
@@ -1 +1 @@
1
- {"version":3,"file":"forms.js","names":["registrations: string[]"],"sources":["../../../src/openapi/exporter/forms.ts"],"sourcesContent":["/**\n * Forms exporter - exports FormSpec to OpenAPI extensions.\n */\nimport type { FormRegistry, Stability } from '@contractspec/lib.contracts';\nimport type { AnySchemaModel } from '@contractspec/lib.schema';\nimport { z } from 'zod';\nimport type { GeneratedRegistryCode } from '../types';\n\ntype OpenApiSchemaObject = Record<string, unknown>;\n\n/**\n * Exported form structure for OpenAPI extensions.\n */\nexport interface ExportedForm {\n key: string;\n version: string;\n description: string;\n stability: Stability;\n owners?: string[];\n fields: unknown[];\n model: OpenApiSchemaObject | null;\n actions?: unknown[];\n}\n\n/**\n * Export forms to OpenAPI extension format.\n */\nexport function exportForms(registry: FormRegistry): ExportedForm[] {\n return registry.list().map((form) => ({\n key: form.meta.key,\n version: form.meta.version,\n description: form.meta.description,\n stability: form.meta.stability,\n owners: form.meta.owners,\n fields: form.fields,\n model: form.model\n ? (z.toJSONSchema(\n (form.model as AnySchemaModel).getZod()\n ) as OpenApiSchemaObject)\n : null,\n actions: form.actions,\n }));\n}\n\n/**\n * Generate TypeScript code for forms registry.\n */\nexport function generateFormsRegistry(\n registry: FormRegistry\n): GeneratedRegistryCode {\n const forms = registry.list();\n const imports = new Set<string>();\n const registrations: string[] = [];\n\n for (const form of forms) {\n const formVarName =\n form.meta.key.replace(/-/g, '_') + `_v${form.meta.version}`;\n imports.add(`import { ${formVarName} } from './${form.meta.key}';`);\n registrations.push(` .register(${formVarName})`);\n }\n\n const code = `/**\n * Auto-generated forms registry.\n * DO NOT EDIT - This file is generated by ContractSpec exporter.\n */\nimport { FormRegistry } from '@contractspec/lib.contracts';\n\n${Array.from(imports).join('\\n')}\n\nexport const formsRegistry = new FormRegistry()\n${registrations.join('\\n')};\n`;\n\n return {\n code,\n fileName: 'forms-registry.ts',\n };\n}\n"],"mappings":";;;;;;AA2BA,SAAgB,YAAY,UAAwC;AAClE,QAAO,SAAS,MAAM,CAAC,KAAK,UAAU;EACpC,KAAK,KAAK,KAAK;EACf,SAAS,KAAK,KAAK;EACnB,aAAa,KAAK,KAAK;EACvB,WAAW,KAAK,KAAK;EACrB,QAAQ,KAAK,KAAK;EAClB,QAAQ,KAAK;EACb,OAAO,KAAK,QACP,EAAE,aACA,KAAK,MAAyB,QAAQ,CACxC,GACD;EACJ,SAAS,KAAK;EACf,EAAE;;;;;AAML,SAAgB,sBACd,UACuB;CACvB,MAAM,QAAQ,SAAS,MAAM;CAC7B,MAAM,0BAAU,IAAI,KAAa;CACjC,MAAMA,gBAA0B,EAAE;AAElC,MAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,cACJ,KAAK,KAAK,IAAI,QAAQ,MAAM,IAAI,GAAG,KAAK,KAAK,KAAK;AACpD,UAAQ,IAAI,YAAY,YAAY,aAAa,KAAK,KAAK,IAAI,IAAI;AACnE,gBAAc,KAAK,eAAe,YAAY,GAAG;;AAenD,QAAO;EACL,MAbW;;;;;;EAMb,MAAM,KAAK,QAAQ,CAAC,KAAK,KAAK,CAAC;;;EAG/B,cAAc,KAAK,KAAK,CAAC;;EAKvB,UAAU;EACX"}
1
+ {"version":3,"file":"forms.js","names":[],"sources":["../../../src/openapi/exporter/forms.ts"],"sourcesContent":["/**\n * Forms exporter - exports FormSpec to OpenAPI extensions.\n */\nimport type { FormRegistry, Stability } from '@contractspec/lib.contracts';\nimport type { AnySchemaModel } from '@contractspec/lib.schema';\nimport { z } from 'zod';\nimport type { GeneratedRegistryCode } from '../types';\n\ntype OpenApiSchemaObject = Record<string, unknown>;\n\n/**\n * Exported form structure for OpenAPI extensions.\n */\nexport interface ExportedForm {\n key: string;\n version: string;\n description: string;\n stability: Stability;\n owners?: string[];\n fields: unknown[];\n model: OpenApiSchemaObject | null;\n actions?: unknown[];\n}\n\n/**\n * Export forms to OpenAPI extension format.\n */\nexport function exportForms(registry: FormRegistry): ExportedForm[] {\n return registry.list().map((form) => ({\n key: form.meta.key,\n version: form.meta.version,\n description: form.meta.description,\n stability: form.meta.stability,\n owners: form.meta.owners,\n fields: form.fields,\n model: form.model\n ? (z.toJSONSchema(\n (form.model as AnySchemaModel).getZod()\n ) as OpenApiSchemaObject)\n : null,\n actions: form.actions,\n }));\n}\n\n/**\n * Generate TypeScript code for forms registry.\n */\nexport function generateFormsRegistry(\n registry: FormRegistry\n): GeneratedRegistryCode {\n const forms = registry.list();\n const imports = new Set<string>();\n const registrations: string[] = [];\n\n for (const form of forms) {\n const formVarName =\n form.meta.key.replace(/-/g, '_') + `_v${form.meta.version}`;\n imports.add(`import { ${formVarName} } from './${form.meta.key}';`);\n registrations.push(` .register(${formVarName})`);\n }\n\n const code = `/**\n * Auto-generated forms registry.\n * DO NOT EDIT - This file is generated by ContractSpec exporter.\n */\nimport { FormRegistry } from '@contractspec/lib.contracts';\n\n${Array.from(imports).join('\\n')}\n\nexport const formsRegistry = new FormRegistry()\n${registrations.join('\\n')};\n`;\n\n return {\n code,\n fileName: 'forms-registry.ts',\n };\n}\n"],"mappings":";;;;;;AA2BA,SAAgB,YAAY,UAAwC;AAClE,QAAO,SAAS,MAAM,CAAC,KAAK,UAAU;EACpC,KAAK,KAAK,KAAK;EACf,SAAS,KAAK,KAAK;EACnB,aAAa,KAAK,KAAK;EACvB,WAAW,KAAK,KAAK;EACrB,QAAQ,KAAK,KAAK;EAClB,QAAQ,KAAK;EACb,OAAO,KAAK,QACP,EAAE,aACA,KAAK,MAAyB,QAAQ,CACxC,GACD;EACJ,SAAS,KAAK;EACf,EAAE;;;;;AAML,SAAgB,sBACd,UACuB;CACvB,MAAM,QAAQ,SAAS,MAAM;CAC7B,MAAM,0BAAU,IAAI,KAAa;CACjC,MAAM,gBAA0B,EAAE;AAElC,MAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,cACJ,KAAK,KAAK,IAAI,QAAQ,MAAM,IAAI,GAAG,KAAK,KAAK,KAAK;AACpD,UAAQ,IAAI,YAAY,YAAY,aAAa,KAAK,KAAK,IAAI,IAAI;AACnE,gBAAc,KAAK,eAAe,YAAY,GAAG;;AAenD,QAAO;EACL,MAbW;;;;;;EAMb,MAAM,KAAK,QAAQ,CAAC,KAAK,KAAK,CAAC;;;EAG/B,cAAc,KAAK,KAAK,CAAC;;EAKvB,UAAU;EACX"}
@@ -1 +1 @@
1
- {"version":3,"file":"operations.js","names":["paths: Record<string, Record<string, unknown>>","schemas: Record<string, OpenApiSchemaObject>","op: Record<string, unknown>","responses: Record<string, unknown>","registrations: string[]"],"sources":["../../../src/openapi/exporter/operations.ts"],"sourcesContent":["/**\n * Operations exporter - exports OperationSpec to OpenAPI paths.\n */\nimport type {\n AnyOperationSpec,\n OperationSpec,\n OperationSpecRegistry,\n} from '@contractspec/lib.contracts';\nimport type { AnySchemaModel } from '@contractspec/lib.schema';\nimport { z } from 'zod';\nimport { compareVersions } from 'compare-versions';\nimport type { GeneratedRegistryCode } from '../types';\n\ntype OpenApiSchemaObject = Record<string, unknown>;\n\n/**\n * Convert a spec name and version to an operationId.\n */\nexport function toOperationId(name: string, version: string): string {\n return `${name.replace(/\\./g, '_')}_v${version.replace(/\\./g, '_')}`;\n}\n\n/**\n * Convert a spec name and version to a schema name.\n */\nexport function toSchemaName(\n prefix: 'Input' | 'Output',\n name: string,\n version: string\n): string {\n return `${prefix}_${toOperationId(name, version)}`;\n}\n\n/**\n * Determine HTTP method from spec kind and override.\n */\nexport function toHttpMethod(\n kind: 'command' | 'query',\n override?: 'GET' | 'POST'\n): string {\n const method = override ?? (kind === 'query' ? 'GET' : 'POST');\n return method.toLowerCase();\n}\n\n/**\n * Generate default REST path from spec name and version.\n */\nexport function defaultRestPath(name: string, version: string): string {\n return `/${name.replace(/\\./g, '/')}/v${version}`;\n}\n\n/**\n * Get REST path from spec, using transport override or default.\n */\nexport function toRestPath(spec: AnyOperationSpec): string {\n const path =\n spec.transport?.rest?.path ??\n defaultRestPath(spec.meta.key, spec.meta.version);\n return path.startsWith('/') ? path : `/${path}`;\n}\n\n/**\n * Convert a SchemaModel to JSON Schema using Zod.\n */\nexport function schemaModelToJsonSchema(\n schema: AnySchemaModel | null\n): OpenApiSchemaObject | null {\n if (!schema) return null;\n return z.toJSONSchema(schema.getZod()) as OpenApiSchemaObject;\n}\n\ninterface SpecJsonSchema {\n input: OpenApiSchemaObject | null;\n output: OpenApiSchemaObject | null;\n meta: {\n key: string;\n version: string;\n kind: 'command' | 'query';\n description: string;\n tags: string[];\n stability: string;\n };\n}\n\n/**\n * Extract JSON Schema for a spec's input and output.\n */\nexport function jsonSchemaForSpec(\n spec: OperationSpec<AnySchemaModel, AnySchemaModel>\n): SpecJsonSchema {\n return {\n input: schemaModelToJsonSchema(spec.io.input),\n output: schemaModelToJsonSchema(spec.io.output as AnySchemaModel | null),\n meta: {\n key: spec.meta.key,\n version: spec.meta.version,\n kind: spec.meta.kind,\n description: spec.meta.description,\n tags: spec.meta.tags ?? [],\n stability: spec.meta.stability ?? 'stable',\n },\n };\n}\n\n/**\n * Result of exporting operations to OpenAPI format.\n */\nexport interface OperationsExportResult {\n paths: Record<string, Record<string, unknown>>;\n schemas: Record<string, OpenApiSchemaObject>;\n}\n\n/**\n * Export operations from a registry to OpenAPI paths and schemas.\n */\nexport function exportOperations(\n registry: OperationSpecRegistry\n): OperationsExportResult {\n const specs = Array.from(registry.list().values())\n .filter(\n (s): s is AnyOperationSpec =>\n s.meta.kind === 'command' || s.meta.kind === 'query'\n )\n .sort((a, b) => {\n const byName = a.meta.key.localeCompare(b.meta.key);\n return byName !== 0\n ? byName\n : compareVersions(a.meta.version, b.meta.version);\n });\n\n const paths: Record<string, Record<string, unknown>> = {};\n const schemas: Record<string, OpenApiSchemaObject> = {};\n\n for (const spec of specs) {\n const schema = jsonSchemaForSpec(\n spec as unknown as OperationSpec<AnySchemaModel, AnySchemaModel>\n );\n const method = toHttpMethod(spec.meta.kind, spec.transport?.rest?.method);\n const path = toRestPath(spec);\n\n const operationId = toOperationId(spec.meta.key, spec.meta.version);\n\n const pathItem = (paths[path] ??= {});\n const op: Record<string, unknown> = {\n operationId,\n summary: spec.meta.description ?? spec.meta.key,\n description: spec.meta.description,\n tags: spec.meta.tags ?? [],\n 'x-contractspec': {\n name: spec.meta.key,\n version: spec.meta.version,\n kind: spec.meta.kind,\n },\n responses: {},\n };\n\n if (schema.input) {\n const inputName = toSchemaName('Input', spec.meta.key, spec.meta.version);\n schemas[inputName] = schema.input;\n op['requestBody'] = {\n required: true,\n content: {\n 'application/json': {\n schema: { $ref: `#/components/schemas/${inputName}` },\n },\n },\n };\n }\n\n const responses: Record<string, unknown> = {};\n if (schema.output) {\n const outputName = toSchemaName(\n 'Output',\n spec.meta.key,\n spec.meta.version\n );\n schemas[outputName] = schema.output;\n responses['200'] = {\n description: 'OK',\n content: {\n 'application/json': {\n schema: { $ref: `#/components/schemas/${outputName}` },\n },\n },\n };\n } else {\n responses['200'] = { description: 'OK' };\n }\n op['responses'] = responses;\n\n pathItem[method] = op;\n }\n\n return { paths, schemas };\n}\n\n/**\n * Generate TypeScript code for operations registry.\n */\nexport function generateOperationsRegistry(\n registry: OperationSpecRegistry\n): GeneratedRegistryCode {\n const specs = Array.from(registry.list().values());\n\n const imports = new Set<string>();\n const registrations: string[] = [];\n\n for (const spec of specs) {\n const specVarName =\n spec.meta.key.replace(/\\./g, '_') +\n `_v${spec.meta.version.replace(/\\./g, '_')}`;\n imports.add(\n `import { ${specVarName} } from './${spec.meta.key.split('.')[0]}';`\n );\n registrations.push(` .register(${specVarName})`);\n }\n\n const code = `/**\n * Auto-generated operations registry.\n * DO NOT EDIT - This file is generated by ContractSpec exporter.\n */\nimport { OperationSpecRegistry } from '@contractspec/lib.contracts';\n\n${Array.from(imports).join('\\n')}\n\nexport const operationsRegistry = new OperationSpecRegistry()\n${registrations.join('\\n')};\n`;\n\n return {\n code,\n fileName: 'operations-registry.ts',\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"operations.js","names":[],"sources":["../../../src/openapi/exporter/operations.ts"],"sourcesContent":["/**\n * Operations exporter - exports OperationSpec to OpenAPI paths.\n */\nimport type {\n AnyOperationSpec,\n OperationSpec,\n OperationSpecRegistry,\n} from '@contractspec/lib.contracts';\nimport type { AnySchemaModel } from '@contractspec/lib.schema';\nimport { z } from 'zod';\nimport { compareVersions } from 'compare-versions';\nimport type { GeneratedRegistryCode } from '../types';\n\ntype OpenApiSchemaObject = Record<string, unknown>;\n\n/**\n * Convert a spec name and version to an operationId.\n */\nexport function toOperationId(name: string, version: string): string {\n return `${name.replace(/\\./g, '_')}_v${version.replace(/\\./g, '_')}`;\n}\n\n/**\n * Convert a spec name and version to a schema name.\n */\nexport function toSchemaName(\n prefix: 'Input' | 'Output',\n name: string,\n version: string\n): string {\n return `${prefix}_${toOperationId(name, version)}`;\n}\n\n/**\n * Determine HTTP method from spec kind and override.\n */\nexport function toHttpMethod(\n kind: 'command' | 'query',\n override?: 'GET' | 'POST'\n): string {\n const method = override ?? (kind === 'query' ? 'GET' : 'POST');\n return method.toLowerCase();\n}\n\n/**\n * Generate default REST path from spec name and version.\n */\nexport function defaultRestPath(name: string, version: string): string {\n return `/${name.replace(/\\./g, '/')}/v${version}`;\n}\n\n/**\n * Get REST path from spec, using transport override or default.\n */\nexport function toRestPath(spec: AnyOperationSpec): string {\n const path =\n spec.transport?.rest?.path ??\n defaultRestPath(spec.meta.key, spec.meta.version);\n return path.startsWith('/') ? path : `/${path}`;\n}\n\n/**\n * Convert a SchemaModel to JSON Schema using Zod.\n */\nexport function schemaModelToJsonSchema(\n schema: AnySchemaModel | null\n): OpenApiSchemaObject | null {\n if (!schema) return null;\n return z.toJSONSchema(schema.getZod()) as OpenApiSchemaObject;\n}\n\ninterface SpecJsonSchema {\n input: OpenApiSchemaObject | null;\n output: OpenApiSchemaObject | null;\n meta: {\n key: string;\n version: string;\n kind: 'command' | 'query';\n description: string;\n tags: string[];\n stability: string;\n };\n}\n\n/**\n * Extract JSON Schema for a spec's input and output.\n */\nexport function jsonSchemaForSpec(\n spec: OperationSpec<AnySchemaModel, AnySchemaModel>\n): SpecJsonSchema {\n return {\n input: schemaModelToJsonSchema(spec.io.input),\n output: schemaModelToJsonSchema(spec.io.output as AnySchemaModel | null),\n meta: {\n key: spec.meta.key,\n version: spec.meta.version,\n kind: spec.meta.kind,\n description: spec.meta.description,\n tags: spec.meta.tags ?? [],\n stability: spec.meta.stability ?? 'stable',\n },\n };\n}\n\n/**\n * Result of exporting operations to OpenAPI format.\n */\nexport interface OperationsExportResult {\n paths: Record<string, Record<string, unknown>>;\n schemas: Record<string, OpenApiSchemaObject>;\n}\n\n/**\n * Export operations from a registry to OpenAPI paths and schemas.\n */\nexport function exportOperations(\n registry: OperationSpecRegistry\n): OperationsExportResult {\n const specs = Array.from(registry.list().values())\n .filter(\n (s): s is AnyOperationSpec =>\n s.meta.kind === 'command' || s.meta.kind === 'query'\n )\n .sort((a, b) => {\n const byName = a.meta.key.localeCompare(b.meta.key);\n return byName !== 0\n ? byName\n : compareVersions(a.meta.version, b.meta.version);\n });\n\n const paths: Record<string, Record<string, unknown>> = {};\n const schemas: Record<string, OpenApiSchemaObject> = {};\n\n for (const spec of specs) {\n const schema = jsonSchemaForSpec(\n spec as unknown as OperationSpec<AnySchemaModel, AnySchemaModel>\n );\n const method = toHttpMethod(spec.meta.kind, spec.transport?.rest?.method);\n const path = toRestPath(spec);\n\n const operationId = toOperationId(spec.meta.key, spec.meta.version);\n\n const pathItem = (paths[path] ??= {});\n const op: Record<string, unknown> = {\n operationId,\n summary: spec.meta.description ?? spec.meta.key,\n description: spec.meta.description,\n tags: spec.meta.tags ?? [],\n 'x-contractspec': {\n name: spec.meta.key,\n version: spec.meta.version,\n kind: spec.meta.kind,\n },\n responses: {},\n };\n\n if (schema.input) {\n const inputName = toSchemaName('Input', spec.meta.key, spec.meta.version);\n schemas[inputName] = schema.input;\n op['requestBody'] = {\n required: true,\n content: {\n 'application/json': {\n schema: { $ref: `#/components/schemas/${inputName}` },\n },\n },\n };\n }\n\n const responses: Record<string, unknown> = {};\n if (schema.output) {\n const outputName = toSchemaName(\n 'Output',\n spec.meta.key,\n spec.meta.version\n );\n schemas[outputName] = schema.output;\n responses['200'] = {\n description: 'OK',\n content: {\n 'application/json': {\n schema: { $ref: `#/components/schemas/${outputName}` },\n },\n },\n };\n } else {\n responses['200'] = { description: 'OK' };\n }\n op['responses'] = responses;\n\n pathItem[method] = op;\n }\n\n return { paths, schemas };\n}\n\n/**\n * Generate TypeScript code for operations registry.\n */\nexport function generateOperationsRegistry(\n registry: OperationSpecRegistry\n): GeneratedRegistryCode {\n const specs = Array.from(registry.list().values());\n\n const imports = new Set<string>();\n const registrations: string[] = [];\n\n for (const spec of specs) {\n const specVarName =\n spec.meta.key.replace(/\\./g, '_') +\n `_v${spec.meta.version.replace(/\\./g, '_')}`;\n imports.add(\n `import { ${specVarName} } from './${spec.meta.key.split('.')[0]}';`\n );\n registrations.push(` .register(${specVarName})`);\n }\n\n const code = `/**\n * Auto-generated operations registry.\n * DO NOT EDIT - This file is generated by ContractSpec exporter.\n */\nimport { OperationSpecRegistry } from '@contractspec/lib.contracts';\n\n${Array.from(imports).join('\\n')}\n\nexport const operationsRegistry = new OperationSpecRegistry()\n${registrations.join('\\n')};\n`;\n\n return {\n code,\n fileName: 'operations-registry.ts',\n };\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"presentations.js","names":["registrations: string[]"],"sources":["../../../src/openapi/exporter/presentations.ts"],"sourcesContent":["/**\n * Presentations exporter - exports PresentationSpec to OpenAPI extensions.\n */\nimport type {\n PresentationSpec,\n PresentationRegistry,\n Stability,\n} from '@contractspec/lib.contracts';\nimport type { GeneratedRegistryCode } from '../types';\n\n/**\n * Exported presentation structure for OpenAPI extensions.\n */\nexport interface ExportedPresentation {\n name: string;\n version: string;\n description: string; // Changed from description?: string;\n stability: Stability; // Changed from stability?: string;\n sourceType: 'component' | 'blocknotejs';\n targets: string[];\n tags?: string[];\n}\n\n/**\n * Export presentations to OpenAPI extension format.\n */\nexport function exportPresentations(\n registry: PresentationRegistry\n): ExportedPresentation[] {\n return registry.list().map((pres) => ({\n name: pres.meta.key,\n version: pres.meta.version,\n description: pres.meta.description,\n stability: pres.meta.stability,\n sourceType: pres.source.type,\n targets: pres.targets,\n tags: pres.meta.tags,\n }));\n}\n\n/**\n * Export presentations from an array.\n */\nexport function exportPresentationsFromArray(\n descriptors: PresentationSpec[]\n): ExportedPresentation[] {\n return descriptors.map((desc) => ({\n name: desc.meta.key,\n version: desc.meta.version,\n description: desc.meta.description,\n stability: desc.meta.stability,\n sourceType: desc.source.type,\n targets: desc.targets,\n tags: desc.meta.tags,\n }));\n}\n\n/**\n * Generate TypeScript code for presentations registry.\n */\nexport function generatePresentationsRegistry(\n registry: PresentationRegistry\n): GeneratedRegistryCode {\n const presentations = registry.list();\n const imports = new Set<string>();\n const registrations: string[] = [];\n\n for (const pres of presentations) {\n const presVarName =\n pres.meta.key.replace(/\\./g, '_') + `_v${pres.meta.version}`;\n imports.add(\n `import { ${presVarName} } from './${pres.meta.key.split('.')[0]}';`\n );\n registrations.push(` .register(${presVarName})`);\n }\n\n const code = `/**\n * Auto-generated presentations registry.\n * DO NOT EDIT - This file is generated by ContractSpec exporter.\n */\nimport { PresentationRegistry } from '@contractspec/lib.contracts';\n\n${Array.from(imports).join('\\n')}\n\nexport const presentationsRegistry = new PresentationRegistry()\n${registrations.join('\\n')};\n`;\n\n return {\n code,\n fileName: 'presentations-registry.ts',\n };\n}\n"],"mappings":";;;;AA0BA,SAAgB,oBACd,UACwB;AACxB,QAAO,SAAS,MAAM,CAAC,KAAK,UAAU;EACpC,MAAM,KAAK,KAAK;EAChB,SAAS,KAAK,KAAK;EACnB,aAAa,KAAK,KAAK;EACvB,WAAW,KAAK,KAAK;EACrB,YAAY,KAAK,OAAO;EACxB,SAAS,KAAK;EACd,MAAM,KAAK,KAAK;EACjB,EAAE;;;;;AAML,SAAgB,6BACd,aACwB;AACxB,QAAO,YAAY,KAAK,UAAU;EAChC,MAAM,KAAK,KAAK;EAChB,SAAS,KAAK,KAAK;EACnB,aAAa,KAAK,KAAK;EACvB,WAAW,KAAK,KAAK;EACrB,YAAY,KAAK,OAAO;EACxB,SAAS,KAAK;EACd,MAAM,KAAK,KAAK;EACjB,EAAE;;;;;AAML,SAAgB,8BACd,UACuB;CACvB,MAAM,gBAAgB,SAAS,MAAM;CACrC,MAAM,0BAAU,IAAI,KAAa;CACjC,MAAMA,gBAA0B,EAAE;AAElC,MAAK,MAAM,QAAQ,eAAe;EAChC,MAAM,cACJ,KAAK,KAAK,IAAI,QAAQ,OAAO,IAAI,GAAG,KAAK,KAAK,KAAK;AACrD,UAAQ,IACN,YAAY,YAAY,aAAa,KAAK,KAAK,IAAI,MAAM,IAAI,CAAC,GAAG,IAClE;AACD,gBAAc,KAAK,eAAe,YAAY,GAAG;;AAenD,QAAO;EACL,MAbW;;;;;;EAMb,MAAM,KAAK,QAAQ,CAAC,KAAK,KAAK,CAAC;;;EAG/B,cAAc,KAAK,KAAK,CAAC;;EAKvB,UAAU;EACX"}
1
+ {"version":3,"file":"presentations.js","names":[],"sources":["../../../src/openapi/exporter/presentations.ts"],"sourcesContent":["/**\n * Presentations exporter - exports PresentationSpec to OpenAPI extensions.\n */\nimport type {\n PresentationSpec,\n PresentationRegistry,\n Stability,\n} from '@contractspec/lib.contracts';\nimport type { GeneratedRegistryCode } from '../types';\n\n/**\n * Exported presentation structure for OpenAPI extensions.\n */\nexport interface ExportedPresentation {\n name: string;\n version: string;\n description: string; // Changed from description?: string;\n stability: Stability; // Changed from stability?: string;\n sourceType: 'component' | 'blocknotejs';\n targets: string[];\n tags?: string[];\n}\n\n/**\n * Export presentations to OpenAPI extension format.\n */\nexport function exportPresentations(\n registry: PresentationRegistry\n): ExportedPresentation[] {\n return registry.list().map((pres) => ({\n name: pres.meta.key,\n version: pres.meta.version,\n description: pres.meta.description,\n stability: pres.meta.stability,\n sourceType: pres.source.type,\n targets: pres.targets,\n tags: pres.meta.tags,\n }));\n}\n\n/**\n * Export presentations from an array.\n */\nexport function exportPresentationsFromArray(\n descriptors: PresentationSpec[]\n): ExportedPresentation[] {\n return descriptors.map((desc) => ({\n name: desc.meta.key,\n version: desc.meta.version,\n description: desc.meta.description,\n stability: desc.meta.stability,\n sourceType: desc.source.type,\n targets: desc.targets,\n tags: desc.meta.tags,\n }));\n}\n\n/**\n * Generate TypeScript code for presentations registry.\n */\nexport function generatePresentationsRegistry(\n registry: PresentationRegistry\n): GeneratedRegistryCode {\n const presentations = registry.list();\n const imports = new Set<string>();\n const registrations: string[] = [];\n\n for (const pres of presentations) {\n const presVarName =\n pres.meta.key.replace(/\\./g, '_') + `_v${pres.meta.version}`;\n imports.add(\n `import { ${presVarName} } from './${pres.meta.key.split('.')[0]}';`\n );\n registrations.push(` .register(${presVarName})`);\n }\n\n const code = `/**\n * Auto-generated presentations registry.\n * DO NOT EDIT - This file is generated by ContractSpec exporter.\n */\nimport { PresentationRegistry } from '@contractspec/lib.contracts';\n\n${Array.from(imports).join('\\n')}\n\nexport const presentationsRegistry = new PresentationRegistry()\n${registrations.join('\\n')};\n`;\n\n return {\n code,\n fileName: 'presentations-registry.ts',\n };\n}\n"],"mappings":";;;;AA0BA,SAAgB,oBACd,UACwB;AACxB,QAAO,SAAS,MAAM,CAAC,KAAK,UAAU;EACpC,MAAM,KAAK,KAAK;EAChB,SAAS,KAAK,KAAK;EACnB,aAAa,KAAK,KAAK;EACvB,WAAW,KAAK,KAAK;EACrB,YAAY,KAAK,OAAO;EACxB,SAAS,KAAK;EACd,MAAM,KAAK,KAAK;EACjB,EAAE;;;;;AAML,SAAgB,6BACd,aACwB;AACxB,QAAO,YAAY,KAAK,UAAU;EAChC,MAAM,KAAK,KAAK;EAChB,SAAS,KAAK,KAAK;EACnB,aAAa,KAAK,KAAK;EACvB,WAAW,KAAK,KAAK;EACrB,YAAY,KAAK,OAAO;EACxB,SAAS,KAAK;EACd,MAAM,KAAK,KAAK;EACjB,EAAE;;;;;AAML,SAAgB,8BACd,UACuB;CACvB,MAAM,gBAAgB,SAAS,MAAM;CACrC,MAAM,0BAAU,IAAI,KAAa;CACjC,MAAM,gBAA0B,EAAE;AAElC,MAAK,MAAM,QAAQ,eAAe;EAChC,MAAM,cACJ,KAAK,KAAK,IAAI,QAAQ,OAAO,IAAI,GAAG,KAAK,KAAK,KAAK;AACrD,UAAQ,IACN,YAAY,YAAY,aAAa,KAAK,KAAK,IAAI,MAAM,IAAI,CAAC,GAAG,IAClE;AACD,gBAAc,KAAK,eAAe,YAAY,GAAG;;AAenD,QAAO;EACL,MAbW;;;;;;EAMb,MAAM,KAAK,QAAQ,CAAC,KAAK,KAAK,CAAC;;;EAG/B,cAAc,KAAK,KAAK,CAAC;;EAKvB,UAAU;EACX"}
@@ -1 +1 @@
1
- {"version":3,"file":"registries.js","names":["exports: string[]"],"sources":["../../../src/openapi/exporter/registries.ts"],"sourcesContent":["/**\n * Unified registries generator - combines all surface registries.\n */\nimport type { GeneratedRegistryCode } from '../types';\n\n/**\n * Registry generation options.\n */\nexport interface RegistryGenerationOptions {\n operations?: boolean;\n events?: boolean;\n features?: boolean;\n presentations?: boolean;\n forms?: boolean;\n dataViews?: boolean;\n workflows?: boolean;\n}\n\n/**\n * Generate unified index file that exports all registries.\n */\nexport function generateRegistryIndex(\n options: RegistryGenerationOptions = {}\n): GeneratedRegistryCode {\n const {\n operations = true,\n events = true,\n features = true,\n presentations = true,\n forms = true,\n dataViews = true,\n workflows = true,\n } = options;\n\n const exports: string[] = [];\n\n if (operations) {\n exports.push(\"export * from './operations-registry';\");\n }\n if (events) {\n exports.push(\"export * from './events-exports';\");\n }\n if (features) {\n exports.push(\"export * from './features-registry';\");\n }\n if (presentations) {\n exports.push(\"export * from './presentations-registry';\");\n }\n if (forms) {\n exports.push(\"export * from './forms-registry';\");\n }\n if (dataViews) {\n exports.push(\"export * from './dataviews-registry';\");\n }\n if (workflows) {\n exports.push(\"export * from './workflows-registry';\");\n }\n\n const code = `/**\n * Auto-generated registry index.\n * DO NOT EDIT - This file is generated by ContractSpec exporter.\n */\n\n${exports.join('\\n')}\n`;\n\n return {\n code,\n fileName: 'index.ts',\n };\n}\n"],"mappings":";;;;AAqBA,SAAgB,sBACd,UAAqC,EAAE,EAChB;CACvB,MAAM,EACJ,aAAa,MACb,SAAS,MACT,WAAW,MACX,gBAAgB,MAChB,QAAQ,MACR,YAAY,MACZ,YAAY,SACV;CAEJ,MAAMA,UAAoB,EAAE;AAE5B,KAAI,WACF,SAAQ,KAAK,yCAAyC;AAExD,KAAI,OACF,SAAQ,KAAK,oCAAoC;AAEnD,KAAI,SACF,SAAQ,KAAK,uCAAuC;AAEtD,KAAI,cACF,SAAQ,KAAK,4CAA4C;AAE3D,KAAI,MACF,SAAQ,KAAK,oCAAoC;AAEnD,KAAI,UACF,SAAQ,KAAK,wCAAwC;AAEvD,KAAI,UACF,SAAQ,KAAK,wCAAwC;AAWvD,QAAO;EACL,MATW;;;;;EAKb,QAAQ,KAAK,KAAK,CAAC;;EAKjB,UAAU;EACX"}
1
+ {"version":3,"file":"registries.js","names":[],"sources":["../../../src/openapi/exporter/registries.ts"],"sourcesContent":["/**\n * Unified registries generator - combines all surface registries.\n */\nimport type { GeneratedRegistryCode } from '../types';\n\n/**\n * Registry generation options.\n */\nexport interface RegistryGenerationOptions {\n operations?: boolean;\n events?: boolean;\n features?: boolean;\n presentations?: boolean;\n forms?: boolean;\n dataViews?: boolean;\n workflows?: boolean;\n}\n\n/**\n * Generate unified index file that exports all registries.\n */\nexport function generateRegistryIndex(\n options: RegistryGenerationOptions = {}\n): GeneratedRegistryCode {\n const {\n operations = true,\n events = true,\n features = true,\n presentations = true,\n forms = true,\n dataViews = true,\n workflows = true,\n } = options;\n\n const exports: string[] = [];\n\n if (operations) {\n exports.push(\"export * from './operations-registry';\");\n }\n if (events) {\n exports.push(\"export * from './events-exports';\");\n }\n if (features) {\n exports.push(\"export * from './features-registry';\");\n }\n if (presentations) {\n exports.push(\"export * from './presentations-registry';\");\n }\n if (forms) {\n exports.push(\"export * from './forms-registry';\");\n }\n if (dataViews) {\n exports.push(\"export * from './dataviews-registry';\");\n }\n if (workflows) {\n exports.push(\"export * from './workflows-registry';\");\n }\n\n const code = `/**\n * Auto-generated registry index.\n * DO NOT EDIT - This file is generated by ContractSpec exporter.\n */\n\n${exports.join('\\n')}\n`;\n\n return {\n code,\n fileName: 'index.ts',\n };\n}\n"],"mappings":";;;;AAqBA,SAAgB,sBACd,UAAqC,EAAE,EAChB;CACvB,MAAM,EACJ,aAAa,MACb,SAAS,MACT,WAAW,MACX,gBAAgB,MAChB,QAAQ,MACR,YAAY,MACZ,YAAY,SACV;CAEJ,MAAM,UAAoB,EAAE;AAE5B,KAAI,WACF,SAAQ,KAAK,yCAAyC;AAExD,KAAI,OACF,SAAQ,KAAK,oCAAoC;AAEnD,KAAI,SACF,SAAQ,KAAK,uCAAuC;AAEtD,KAAI,cACF,SAAQ,KAAK,4CAA4C;AAE3D,KAAI,MACF,SAAQ,KAAK,oCAAoC;AAEnD,KAAI,UACF,SAAQ,KAAK,wCAAwC;AAEvD,KAAI,UACF,SAAQ,KAAK,wCAAwC;AAWvD,QAAO;EACL,MATW;;;;;EAKb,QAAQ,KAAK,KAAK,CAAC;;EAKjB,UAAU;EACX"}
@@ -1 +1 @@
1
- {"version":3,"file":"workflows.js","names":["registrations: string[]"],"sources":["../../../src/openapi/exporter/workflows.ts"],"sourcesContent":["/**\n * Workflows exporter - exports WorkflowSpec to OpenAPI extensions.\n */\nimport type { WorkflowRegistry } from '@contractspec/lib.contracts';\nimport type { GeneratedRegistryCode } from '../types';\n\n/**\n * Exported workflow structure for OpenAPI extensions.\n */\nexport interface ExportedWorkflow {\n name: string;\n version: string;\n description?: string;\n stability?: string;\n owners?: string[];\n steps: {\n id: string;\n type: 'human' | 'automation' | 'decision';\n label: string;\n }[];\n transitions: {\n from: string;\n to: string;\n label?: string;\n }[];\n}\n\n/**\n * Export workflows to OpenAPI extension format.\n */\nexport function exportWorkflows(\n registry: WorkflowRegistry\n): ExportedWorkflow[] {\n return registry.list().map((wf) => ({\n name: wf.meta.key,\n version: wf.meta.version,\n description: wf.meta.description,\n stability: wf.meta.stability,\n owners: wf.meta.owners,\n steps: wf.definition.steps.map((s) => ({\n id: s.id,\n type: s.type,\n label: s.label,\n })),\n transitions: wf.definition.transitions.map((t) => ({\n from: t.from,\n to: t.to,\n label: t.label,\n })),\n }));\n}\n\n/**\n * Generate TypeScript code for workflows registry.\n */\nexport function generateWorkflowsRegistry(\n registry: WorkflowRegistry\n): GeneratedRegistryCode {\n const workflows = registry.list();\n const imports = new Set<string>();\n const registrations: string[] = [];\n\n for (const wf of workflows) {\n const wfVarName = wf.meta.key.replace(/\\./g, '_') + `_v${wf.meta.version}`;\n imports.add(\n `import { ${wfVarName} } from './${wf.meta.key.split('.')[0]}';`\n );\n registrations.push(` .register(${wfVarName})`);\n }\n\n const code = `/**\n * Auto-generated workflows registry.\n * DO NOT EDIT - This file is generated by ContractSpec exporter.\n */\nimport { WorkflowRegistry } from '@contractspec/lib.contracts';\n\n${Array.from(imports).join('\\n')}\n\nexport const workflowsRegistry = new WorkflowRegistry()\n${registrations.join('\\n')};\n`;\n\n return {\n code,\n fileName: 'workflows-registry.ts',\n };\n}\n"],"mappings":";;;;AA8BA,SAAgB,gBACd,UACoB;AACpB,QAAO,SAAS,MAAM,CAAC,KAAK,QAAQ;EAClC,MAAM,GAAG,KAAK;EACd,SAAS,GAAG,KAAK;EACjB,aAAa,GAAG,KAAK;EACrB,WAAW,GAAG,KAAK;EACnB,QAAQ,GAAG,KAAK;EAChB,OAAO,GAAG,WAAW,MAAM,KAAK,OAAO;GACrC,IAAI,EAAE;GACN,MAAM,EAAE;GACR,OAAO,EAAE;GACV,EAAE;EACH,aAAa,GAAG,WAAW,YAAY,KAAK,OAAO;GACjD,MAAM,EAAE;GACR,IAAI,EAAE;GACN,OAAO,EAAE;GACV,EAAE;EACJ,EAAE;;;;;AAML,SAAgB,0BACd,UACuB;CACvB,MAAM,YAAY,SAAS,MAAM;CACjC,MAAM,0BAAU,IAAI,KAAa;CACjC,MAAMA,gBAA0B,EAAE;AAElC,MAAK,MAAM,MAAM,WAAW;EAC1B,MAAM,YAAY,GAAG,KAAK,IAAI,QAAQ,OAAO,IAAI,GAAG,KAAK,GAAG,KAAK;AACjE,UAAQ,IACN,YAAY,UAAU,aAAa,GAAG,KAAK,IAAI,MAAM,IAAI,CAAC,GAAG,IAC9D;AACD,gBAAc,KAAK,eAAe,UAAU,GAAG;;AAejD,QAAO;EACL,MAbW;;;;;;EAMb,MAAM,KAAK,QAAQ,CAAC,KAAK,KAAK,CAAC;;;EAG/B,cAAc,KAAK,KAAK,CAAC;;EAKvB,UAAU;EACX"}
1
+ {"version":3,"file":"workflows.js","names":[],"sources":["../../../src/openapi/exporter/workflows.ts"],"sourcesContent":["/**\n * Workflows exporter - exports WorkflowSpec to OpenAPI extensions.\n */\nimport type { WorkflowRegistry } from '@contractspec/lib.contracts';\nimport type { GeneratedRegistryCode } from '../types';\n\n/**\n * Exported workflow structure for OpenAPI extensions.\n */\nexport interface ExportedWorkflow {\n name: string;\n version: string;\n description?: string;\n stability?: string;\n owners?: string[];\n steps: {\n id: string;\n type: 'human' | 'automation' | 'decision';\n label: string;\n }[];\n transitions: {\n from: string;\n to: string;\n label?: string;\n }[];\n}\n\n/**\n * Export workflows to OpenAPI extension format.\n */\nexport function exportWorkflows(\n registry: WorkflowRegistry\n): ExportedWorkflow[] {\n return registry.list().map((wf) => ({\n name: wf.meta.key,\n version: wf.meta.version,\n description: wf.meta.description,\n stability: wf.meta.stability,\n owners: wf.meta.owners,\n steps: wf.definition.steps.map((s) => ({\n id: s.id,\n type: s.type,\n label: s.label,\n })),\n transitions: wf.definition.transitions.map((t) => ({\n from: t.from,\n to: t.to,\n label: t.label,\n })),\n }));\n}\n\n/**\n * Generate TypeScript code for workflows registry.\n */\nexport function generateWorkflowsRegistry(\n registry: WorkflowRegistry\n): GeneratedRegistryCode {\n const workflows = registry.list();\n const imports = new Set<string>();\n const registrations: string[] = [];\n\n for (const wf of workflows) {\n const wfVarName = wf.meta.key.replace(/\\./g, '_') + `_v${wf.meta.version}`;\n imports.add(\n `import { ${wfVarName} } from './${wf.meta.key.split('.')[0]}';`\n );\n registrations.push(` .register(${wfVarName})`);\n }\n\n const code = `/**\n * Auto-generated workflows registry.\n * DO NOT EDIT - This file is generated by ContractSpec exporter.\n */\nimport { WorkflowRegistry } from '@contractspec/lib.contracts';\n\n${Array.from(imports).join('\\n')}\n\nexport const workflowsRegistry = new WorkflowRegistry()\n${registrations.join('\\n')};\n`;\n\n return {\n code,\n fileName: 'workflows-registry.ts',\n };\n}\n"],"mappings":";;;;AA8BA,SAAgB,gBACd,UACoB;AACpB,QAAO,SAAS,MAAM,CAAC,KAAK,QAAQ;EAClC,MAAM,GAAG,KAAK;EACd,SAAS,GAAG,KAAK;EACjB,aAAa,GAAG,KAAK;EACrB,WAAW,GAAG,KAAK;EACnB,QAAQ,GAAG,KAAK;EAChB,OAAO,GAAG,WAAW,MAAM,KAAK,OAAO;GACrC,IAAI,EAAE;GACN,MAAM,EAAE;GACR,OAAO,EAAE;GACV,EAAE;EACH,aAAa,GAAG,WAAW,YAAY,KAAK,OAAO;GACjD,MAAM,EAAE;GACR,IAAI,EAAE;GACN,OAAO,EAAE;GACV,EAAE;EACJ,EAAE;;;;;AAML,SAAgB,0BACd,UACuB;CACvB,MAAM,YAAY,SAAS,MAAM;CACjC,MAAM,0BAAU,IAAI,KAAa;CACjC,MAAM,gBAA0B,EAAE;AAElC,MAAK,MAAM,MAAM,WAAW;EAC1B,MAAM,YAAY,GAAG,KAAK,IAAI,QAAQ,OAAO,IAAI,GAAG,KAAK,GAAG,KAAK;AACjE,UAAQ,IACN,YAAY,UAAU,aAAa,GAAG,KAAK,IAAI,MAAM,IAAI,CAAC,GAAG,IAC9D;AACD,gBAAc,KAAK,eAAe,UAAU,GAAG;;AAejD,QAAO;EACL,MAbW;;;;;;EAMb,MAAM,KAAK,QAAQ,CAAC,KAAK,KAAK,CAAC;;;EAG/B,cAAc,KAAK,KAAK,CAAC;;EAKvB,UAAU;EACX"}
@@ -1,4 +1,4 @@
1
- import { ContractSpecExportOptions, ContractSpecExportResult, ContractSpecOpenApiDocument, OpenApiExportOptions, OpenApiServer } from "./types.js";
1
+ import { ContractSpecExportOptions, ContractSpecExportResult, ContractSpecOpenApiDocument, OpenApiExportOptions } from "./types.js";
2
2
  import { defaultRestPath } from "./exporter/operations.js";
3
3
  import { DataViewRegistry, EventSpec, FeatureRegistry, FormRegistry, OperationSpecRegistry, PresentationRegistry, PresentationSpec, WorkflowRegistry } from "@contractspec/lib.contracts";
4
4
  import { AnySchemaModel } from "@contractspec/lib.schema";
@@ -1 +1 @@
1
- {"version":3,"file":"exporter.d.ts","names":[],"sources":["../../src/openapi/exporter.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;AAmDkB,UAJD,sBAAA,CAIC;EACK,UAAA,CAAA,EAJR,qBAIQ;EACb,MAAA,CAAA,EAJC,SAID,CAJW,cAIX,CAAA,EAAA;EACI,QAAA,CAAA,EAJD,eAIC;EACA,aAAA,CAAA,EAJI,oBAIJ;EAAgB,kBAAA,CAAA,EAHP,gBAGO,EAAA;EAUd,KAAA,CAAA,EAZN,YAYM;EACJ,SAAA,CAAA,EAZE,gBAYF;EACD,SAAA,CAAA,EAZG,gBAYH;;AAoBX;;;;AAG2B,iBAzBX,kBAAA,CAyBW,QAAA,EAxBf,qBAwBe,EAAA,OAAA,CAAA,EAvBhB,oBAuBgB,CAAA,EAtBxB,2BAsBwB;AA8H3B;AAWA;AAWA;AAWgB,iBAlKA,kBAAA,CAmKF,UAAA,EAlKA,sBAmKH,EAAA,OAA8B,CAAA,EAlK9B,yBAkK8B,CAAA,EAjKtC,wBAiKsC;;;;iBAnCzB,aAAA,WACJ,iCACD;;;;iBASK,aAAA,WACJ,iCACD;;;;iBASK,kBAAA,aACF,kCACH;;;;iBASK,kBAAA,aACF,kCACH"}
1
+ {"version":3,"file":"exporter.d.ts","names":[],"sources":["../../src/openapi/exporter.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;AAkDkB,UAJD,sBAAA,CAIC;EACK,UAAA,CAAA,EAJR,qBAIQ;EACb,MAAA,CAAA,EAJC,SAID,CAJW,cAIX,CAAA,EAAA;EACI,QAAA,CAAA,EAJD,eAIC;EACA,aAAA,CAAA,EAJI,oBAIJ;EAAgB,kBAAA,CAAA,EAHP,gBAGO,EAAA;EAUd,KAAA,CAAA,EAZN,YAYM;EACJ,SAAA,CAAA,EAZE,gBAYF;EACD,SAAA,CAAA,EAZG,gBAYH;;AAoBX;;;;AAG2B,iBAzBX,kBAAA,CAyBW,QAAA,EAxBf,qBAwBe,EAAA,OAAA,CAAA,EAvBhB,oBAuBgB,CAAA,EAtBxB,2BAsBwB;AA8H3B;AAWA;AAWA;AAWgB,iBAlKA,kBAAA,CAmKF,UAAA,EAlKA,sBAmKH,EAAA,OAA8B,CAAA,EAlK9B,yBAkK8B,CAAA,EAjKtC,wBAiKsC;;;;iBAnCzB,aAAA,WACJ,iCACD;;;;iBASK,aAAA,WACJ,iCACD;;;;iBASK,kBAAA,aACF,kCACH;;;;iBASK,kBAAA,aACF,kCACH"}
@@ -1 +1 @@
1
- {"version":3,"file":"exporter.js","names":["paths: Record<string, Record<string, unknown>>","schemas: Record<string, Record<string, unknown>>","doc: ContractSpecOpenApiDocument","result: ContractSpecExportResult"],"sources":["../../src/openapi/exporter.ts"],"sourcesContent":["/**\n * Export ContractSpec specs to OpenAPI 3.1 format.\n * Refactored to use modular exporters for all surfaces.\n */\nimport type {\n OperationSpecRegistry,\n FeatureRegistry,\n PresentationRegistry,\n FormRegistry,\n DataViewRegistry,\n WorkflowRegistry,\n EventSpec,\n PresentationSpec,\n} from '@contractspec/lib.contracts';\nimport type { AnySchemaModel } from '@contractspec/lib.schema';\nimport type {\n ContractSpecOpenApiDocument,\n OpenApiExportOptions,\n OpenApiServer,\n ContractSpecExportOptions,\n ContractSpecExportResult,\n} from './types';\nimport {\n exportOperations,\n generateOperationsRegistry,\n defaultRestPath as defaultRestPathFn,\n} from './exporter/operations';\nimport { exportEvents, generateEventsExports } from './exporter/events';\nimport { exportFeatures, generateFeaturesRegistry } from './exporter/features';\nimport {\n exportPresentations,\n generatePresentationsRegistry,\n} from './exporter/presentations';\nimport { exportForms, generateFormsRegistry } from './exporter/forms';\nimport {\n exportDataViews,\n generateDataViewsRegistry,\n} from './exporter/data-views';\nimport {\n exportWorkflows,\n generateWorkflowsRegistry,\n} from './exporter/workflows';\nimport { generateRegistryIndex } from './exporter/registries';\n\n/**\n * Input registries for unified export.\n */\nexport interface ContractSpecRegistries {\n operations?: OperationSpecRegistry;\n events?: EventSpec<AnySchemaModel>[];\n features?: FeatureRegistry;\n presentations?: PresentationRegistry;\n presentationsArray?: PresentationSpec[];\n forms?: FormRegistry;\n dataViews?: DataViewRegistry;\n workflows?: WorkflowRegistry;\n}\n\n// Re-export for backwards compatibility\nexport { defaultRestPathFn as defaultRestPath };\n\n/**\n * Export a OperationSpecRegistry to an OpenAPI 3.1 document.\n * @deprecated Use exportContractSpec for full surface support.\n */\nexport function openApiForRegistry(\n registry: OperationSpecRegistry,\n options: OpenApiExportOptions = {}\n): ContractSpecOpenApiDocument {\n const { paths, schemas } = exportOperations(registry);\n\n return {\n openapi: '3.1.0',\n info: {\n title: options.title ?? 'ContractSpec API',\n version: options.version ?? '0.0.0',\n ...(options.description ? { description: options.description } : {}),\n },\n ...(options.servers ? { servers: options.servers } : {}),\n paths,\n components: { schemas },\n };\n}\n\n/**\n * Export all ContractSpec surfaces to OpenAPI document with extensions.\n */\nexport function exportContractSpec(\n registries: ContractSpecRegistries,\n options: ContractSpecExportOptions = {}\n): ContractSpecExportResult {\n const {\n operations: includeOps = true,\n events: includeEvents = true,\n features: includeFeatures = true,\n presentations: includePresentations = true,\n forms: includeForms = true,\n dataViews: includeDataViews = true,\n workflows: includeWorkflows = true,\n generateRegistries = true,\n } = options;\n\n // Build OpenAPI document\n let paths: Record<string, Record<string, unknown>> = {};\n let schemas: Record<string, Record<string, unknown>> = {};\n\n // Export operations\n if (includeOps && registries.operations) {\n const opResult = exportOperations(registries.operations);\n paths = opResult.paths;\n schemas = opResult.schemas;\n }\n\n const doc: ContractSpecOpenApiDocument = {\n openapi: '3.1.0',\n info: {\n title: options.title ?? 'ContractSpec API',\n version: options.version ?? '0.0.0',\n ...(options.description ? { description: options.description } : {}),\n },\n ...(options.servers ? { servers: options.servers } : {}),\n paths,\n components: { schemas },\n };\n\n // Add extensions for other surfaces\n if (includeEvents && registries.events?.length) {\n doc['x-contractspec-events'] = exportEvents(registries.events);\n }\n\n if (includeFeatures && registries.features) {\n doc['x-contractspec-features'] = exportFeatures(registries.features);\n }\n\n if (includePresentations && registries.presentations) {\n doc['x-contractspec-presentations'] = exportPresentations(\n registries.presentations\n );\n }\n\n if (includeForms && registries.forms) {\n doc['x-contractspec-forms'] = exportForms(registries.forms);\n }\n\n if (includeDataViews && registries.dataViews) {\n doc['x-contractspec-dataviews'] = exportDataViews(registries.dataViews);\n }\n\n if (includeWorkflows && registries.workflows) {\n doc['x-contractspec-workflows'] = exportWorkflows(registries.workflows);\n }\n\n const result: ContractSpecExportResult = {\n openApi: doc,\n };\n\n // Generate registry code if requested\n if (generateRegistries) {\n result.registries = {};\n\n if (includeOps && registries.operations) {\n result.registries.operations = generateOperationsRegistry(\n registries.operations\n );\n }\n\n if (includeEvents && registries.events?.length) {\n result.registries.events = generateEventsExports(registries.events);\n }\n\n if (includeFeatures && registries.features) {\n result.registries.features = generateFeaturesRegistry(\n registries.features\n );\n }\n\n if (includePresentations && registries.presentations) {\n result.registries.presentations = generatePresentationsRegistry(\n registries.presentations\n );\n }\n\n if (includeForms && registries.forms) {\n result.registries.forms = generateFormsRegistry(registries.forms);\n }\n\n if (includeDataViews && registries.dataViews) {\n result.registries.dataViews = generateDataViewsRegistry(\n registries.dataViews\n );\n }\n\n if (includeWorkflows && registries.workflows) {\n result.registries.workflows = generateWorkflowsRegistry(\n registries.workflows\n );\n }\n\n // Generate index file\n result.registries.index = generateRegistryIndex({\n operations: includeOps && !!registries.operations,\n events: includeEvents && !!registries.events?.length,\n features: includeFeatures && !!registries.features,\n presentations: includePresentations && !!registries.presentations,\n forms: includeForms && !!registries.forms,\n dataViews: includeDataViews && !!registries.dataViews,\n workflows: includeWorkflows && !!registries.workflows,\n });\n }\n\n return result;\n}\n\n/**\n * Export a OperationSpecRegistry to OpenAPI JSON string.\n */\nexport function openApiToJson(\n registry: OperationSpecRegistry,\n options: OpenApiExportOptions = {}\n): string {\n const doc = openApiForRegistry(registry, options);\n return JSON.stringify(doc, null, 2);\n}\n\n/**\n * Export a OperationSpecRegistry to OpenAPI YAML string.\n */\nexport function openApiToYaml(\n registry: OperationSpecRegistry,\n options: OpenApiExportOptions = {}\n): string {\n const doc = openApiForRegistry(registry, options);\n return jsonToYaml(doc);\n}\n\n/**\n * Export ContractSpec to JSON string (all surfaces).\n */\nexport function contractSpecToJson(\n registries: ContractSpecRegistries,\n options: ContractSpecExportOptions = {}\n): string {\n const result = exportContractSpec(registries, options);\n return JSON.stringify(result.openApi, null, 2);\n}\n\n/**\n * Export ContractSpec to YAML string (all surfaces).\n */\nexport function contractSpecToYaml(\n registries: ContractSpecRegistries,\n options: ContractSpecExportOptions = {}\n): string {\n const result = exportContractSpec(registries, options);\n return jsonToYaml(result.openApi);\n}\n\n/**\n * Simple JSON to YAML conversion.\n */\nfunction jsonToYaml(obj: unknown, indent = 0): string {\n const spaces = ' '.repeat(indent);\n let yaml = '';\n\n if (Array.isArray(obj)) {\n for (const item of obj) {\n if (typeof item === 'object' && item !== null) {\n yaml += `${spaces}-\\n${jsonToYaml(item, indent + 1)}`;\n } else {\n yaml += `${spaces}- ${JSON.stringify(item)}\\n`;\n }\n }\n } else if (typeof obj === 'object' && obj !== null) {\n for (const [key, value] of Object.entries(obj)) {\n if (Array.isArray(value)) {\n yaml += `${spaces}${key}:\\n${jsonToYaml(value, indent + 1)}`;\n } else if (typeof value === 'object' && value !== null) {\n yaml += `${spaces}${key}:\\n${jsonToYaml(value, indent + 1)}`;\n } else {\n yaml += `${spaces}${key}: ${JSON.stringify(value)}\\n`;\n }\n }\n }\n\n return yaml;\n}\n\n// Re-export types for convenience\nexport type {\n OpenApiExportOptions,\n OpenApiServer,\n ContractSpecOpenApiDocument,\n ContractSpecExportOptions,\n ContractSpecExportResult,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"exporter.js","names":[],"sources":["../../src/openapi/exporter.ts"],"sourcesContent":["/**\n * Export ContractSpec specs to OpenAPI 3.1 format.\n * Refactored to use modular exporters for all surfaces.\n */\nimport type {\n OperationSpecRegistry,\n FeatureRegistry,\n PresentationRegistry,\n FormRegistry,\n DataViewRegistry,\n WorkflowRegistry,\n EventSpec,\n PresentationSpec,\n} from '@contractspec/lib.contracts';\nimport type { AnySchemaModel } from '@contractspec/lib.schema';\nimport type {\n ContractSpecOpenApiDocument,\n OpenApiExportOptions,\n ContractSpecExportOptions,\n ContractSpecExportResult,\n} from './types';\nimport {\n exportOperations,\n generateOperationsRegistry,\n defaultRestPath as defaultRestPathFn,\n} from './exporter/operations';\nimport { exportEvents, generateEventsExports } from './exporter/events';\nimport { exportFeatures, generateFeaturesRegistry } from './exporter/features';\nimport {\n exportPresentations,\n generatePresentationsRegistry,\n} from './exporter/presentations';\nimport { exportForms, generateFormsRegistry } from './exporter/forms';\nimport {\n exportDataViews,\n generateDataViewsRegistry,\n} from './exporter/data-views';\nimport {\n exportWorkflows,\n generateWorkflowsRegistry,\n} from './exporter/workflows';\nimport { generateRegistryIndex } from './exporter/registries';\n\n/**\n * Input registries for unified export.\n */\nexport interface ContractSpecRegistries {\n operations?: OperationSpecRegistry;\n events?: EventSpec<AnySchemaModel>[];\n features?: FeatureRegistry;\n presentations?: PresentationRegistry;\n presentationsArray?: PresentationSpec[];\n forms?: FormRegistry;\n dataViews?: DataViewRegistry;\n workflows?: WorkflowRegistry;\n}\n\n// Re-export for backwards compatibility\nexport { defaultRestPathFn as defaultRestPath };\n\n/**\n * Export a OperationSpecRegistry to an OpenAPI 3.1 document.\n * @deprecated Use exportContractSpec for full surface support.\n */\nexport function openApiForRegistry(\n registry: OperationSpecRegistry,\n options: OpenApiExportOptions = {}\n): ContractSpecOpenApiDocument {\n const { paths, schemas } = exportOperations(registry);\n\n return {\n openapi: '3.1.0',\n info: {\n title: options.title ?? 'ContractSpec API',\n version: options.version ?? '0.0.0',\n ...(options.description ? { description: options.description } : {}),\n },\n ...(options.servers ? { servers: options.servers } : {}),\n paths,\n components: { schemas },\n };\n}\n\n/**\n * Export all ContractSpec surfaces to OpenAPI document with extensions.\n */\nexport function exportContractSpec(\n registries: ContractSpecRegistries,\n options: ContractSpecExportOptions = {}\n): ContractSpecExportResult {\n const {\n operations: includeOps = true,\n events: includeEvents = true,\n features: includeFeatures = true,\n presentations: includePresentations = true,\n forms: includeForms = true,\n dataViews: includeDataViews = true,\n workflows: includeWorkflows = true,\n generateRegistries = true,\n } = options;\n\n // Build OpenAPI document\n let paths: Record<string, Record<string, unknown>> = {};\n let schemas: Record<string, Record<string, unknown>> = {};\n\n // Export operations\n if (includeOps && registries.operations) {\n const opResult = exportOperations(registries.operations);\n paths = opResult.paths;\n schemas = opResult.schemas;\n }\n\n const doc: ContractSpecOpenApiDocument = {\n openapi: '3.1.0',\n info: {\n title: options.title ?? 'ContractSpec API',\n version: options.version ?? '0.0.0',\n ...(options.description ? { description: options.description } : {}),\n },\n ...(options.servers ? { servers: options.servers } : {}),\n paths,\n components: { schemas },\n };\n\n // Add extensions for other surfaces\n if (includeEvents && registries.events?.length) {\n doc['x-contractspec-events'] = exportEvents(registries.events);\n }\n\n if (includeFeatures && registries.features) {\n doc['x-contractspec-features'] = exportFeatures(registries.features);\n }\n\n if (includePresentations && registries.presentations) {\n doc['x-contractspec-presentations'] = exportPresentations(\n registries.presentations\n );\n }\n\n if (includeForms && registries.forms) {\n doc['x-contractspec-forms'] = exportForms(registries.forms);\n }\n\n if (includeDataViews && registries.dataViews) {\n doc['x-contractspec-dataviews'] = exportDataViews(registries.dataViews);\n }\n\n if (includeWorkflows && registries.workflows) {\n doc['x-contractspec-workflows'] = exportWorkflows(registries.workflows);\n }\n\n const result: ContractSpecExportResult = {\n openApi: doc,\n };\n\n // Generate registry code if requested\n if (generateRegistries) {\n result.registries = {};\n\n if (includeOps && registries.operations) {\n result.registries.operations = generateOperationsRegistry(\n registries.operations\n );\n }\n\n if (includeEvents && registries.events?.length) {\n result.registries.events = generateEventsExports(registries.events);\n }\n\n if (includeFeatures && registries.features) {\n result.registries.features = generateFeaturesRegistry(\n registries.features\n );\n }\n\n if (includePresentations && registries.presentations) {\n result.registries.presentations = generatePresentationsRegistry(\n registries.presentations\n );\n }\n\n if (includeForms && registries.forms) {\n result.registries.forms = generateFormsRegistry(registries.forms);\n }\n\n if (includeDataViews && registries.dataViews) {\n result.registries.dataViews = generateDataViewsRegistry(\n registries.dataViews\n );\n }\n\n if (includeWorkflows && registries.workflows) {\n result.registries.workflows = generateWorkflowsRegistry(\n registries.workflows\n );\n }\n\n // Generate index file\n result.registries.index = generateRegistryIndex({\n operations: includeOps && !!registries.operations,\n events: includeEvents && !!registries.events?.length,\n features: includeFeatures && !!registries.features,\n presentations: includePresentations && !!registries.presentations,\n forms: includeForms && !!registries.forms,\n dataViews: includeDataViews && !!registries.dataViews,\n workflows: includeWorkflows && !!registries.workflows,\n });\n }\n\n return result;\n}\n\n/**\n * Export a OperationSpecRegistry to OpenAPI JSON string.\n */\nexport function openApiToJson(\n registry: OperationSpecRegistry,\n options: OpenApiExportOptions = {}\n): string {\n const doc = openApiForRegistry(registry, options);\n return JSON.stringify(doc, null, 2);\n}\n\n/**\n * Export a OperationSpecRegistry to OpenAPI YAML string.\n */\nexport function openApiToYaml(\n registry: OperationSpecRegistry,\n options: OpenApiExportOptions = {}\n): string {\n const doc = openApiForRegistry(registry, options);\n return jsonToYaml(doc);\n}\n\n/**\n * Export ContractSpec to JSON string (all surfaces).\n */\nexport function contractSpecToJson(\n registries: ContractSpecRegistries,\n options: ContractSpecExportOptions = {}\n): string {\n const result = exportContractSpec(registries, options);\n return JSON.stringify(result.openApi, null, 2);\n}\n\n/**\n * Export ContractSpec to YAML string (all surfaces).\n */\nexport function contractSpecToYaml(\n registries: ContractSpecRegistries,\n options: ContractSpecExportOptions = {}\n): string {\n const result = exportContractSpec(registries, options);\n return jsonToYaml(result.openApi);\n}\n\n/**\n * Simple JSON to YAML conversion.\n */\nfunction jsonToYaml(obj: unknown, indent = 0): string {\n const spaces = ' '.repeat(indent);\n let yaml = '';\n\n if (Array.isArray(obj)) {\n for (const item of obj) {\n if (typeof item === 'object' && item !== null) {\n yaml += `${spaces}-\\n${jsonToYaml(item, indent + 1)}`;\n } else {\n yaml += `${spaces}- ${JSON.stringify(item)}\\n`;\n }\n }\n } else if (typeof obj === 'object' && obj !== null) {\n for (const [key, value] of Object.entries(obj)) {\n if (Array.isArray(value)) {\n yaml += `${spaces}${key}:\\n${jsonToYaml(value, indent + 1)}`;\n } else if (typeof value === 'object' && value !== null) {\n yaml += `${spaces}${key}:\\n${jsonToYaml(value, indent + 1)}`;\n } else {\n yaml += `${spaces}${key}: ${JSON.stringify(value)}\\n`;\n }\n }\n }\n\n return yaml;\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"events.js","names":[],"sources":["../../../src/openapi/importer/events.ts"],"sourcesContent":["import type { ParsedEvent } from '../types';\nimport { generateImports, generateSchemaModelCode } from '../schema-converter';\nimport { toPascalCase, toValidIdentifier } from '../../common/utils';\nimport type { ContractsrcConfig } from '@contractspec/lib.contracts';\n\n/**\n * Generate code for an event.\n */\nexport function generateEventCode(\n event: ParsedEvent,\n options: ContractsrcConfig\n): string {\n const eventName = toValidIdentifier(event.name);\n const modelName = toPascalCase(eventName) + 'Payload';\n\n const schemaFormat = options.schemaFormat || 'contractspec';\n // Generate payload model inline or referenced?\n // Let's generate the payload schema definition first\n const payloadModel = generateSchemaModelCode(\n event.payload,\n modelName,\n schemaFormat,\n options\n );\n\n const imports = new Set<string>();\n imports.add(\n \"import { defineEvent, type EventSpec } from '@contractspec/lib.contracts';\"\n );\n\n if (payloadModel.imports && payloadModel.imports.length > 0) {\n payloadModel.imports.forEach((i) => imports.add(i));\n } else if (payloadModel.fields && payloadModel.fields.length > 0) {\n const modelImports = generateImports(payloadModel.fields, options);\n // Merge imports - this is a bit hacky string manipulation but works for now\n modelImports\n .split('\\n')\n .filter(Boolean)\n .forEach((i) => imports.add(i));\n }\n\n // If payloadModel is a reference (empty fields and different name), import it\n if (payloadModel.name !== modelName) {\n const modelsDir = `../${options.conventions.models}`;\n const kebabName = payloadModel.name\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n .toLowerCase();\n imports.add(\n `import { ${payloadModel.name} } from '${modelsDir}/${kebabName}';`\n );\n }\n\n const allImports = Array.from(imports).join('\\n');\n\n return `\n${allImports}\n\n${payloadModel.code}\n\nexport const ${eventName} = defineEvent({\n meta: {\n key: '${event.name}',\n version: '1.0.0',\n description: ${JSON.stringify(event.description ?? '')},\n },\n payload: ${payloadModel.name},\n});\n`.trim();\n}\n"],"mappings":";;;;;;;AAQA,SAAgB,kBACd,OACA,SACQ;CACR,MAAM,YAAY,kBAAkB,MAAM,KAAK;CAC/C,MAAM,YAAY,aAAa,UAAU,GAAG;CAE5C,MAAM,eAAe,QAAQ,gBAAgB;CAG7C,MAAM,eAAe,wBACnB,MAAM,SACN,WACA,cACA,QACD;CAED,MAAM,0BAAU,IAAI,KAAa;AACjC,SAAQ,IACN,6EACD;AAED,KAAI,aAAa,WAAW,aAAa,QAAQ,SAAS,EACxD,cAAa,QAAQ,SAAS,MAAM,QAAQ,IAAI,EAAE,CAAC;UAC1C,aAAa,UAAU,aAAa,OAAO,SAAS,EAG7D,CAFqB,gBAAgB,aAAa,QAAQ,QAAQ,CAG/D,MAAM,KAAK,CACX,OAAO,QAAQ,CACf,SAAS,MAAM,QAAQ,IAAI,EAAE,CAAC;AAInC,KAAI,aAAa,SAAS,WAAW;EACnC,MAAM,YAAY,MAAM,QAAQ,YAAY;EAC5C,MAAM,YAAY,aAAa,KAC5B,QAAQ,sBAAsB,QAAQ,CACtC,aAAa;AAChB,UAAQ,IACN,YAAY,aAAa,KAAK,WAAW,UAAU,GAAG,UAAU,IACjE;;AAKH,QAAO;EAFY,MAAM,KAAK,QAAQ,CAAC,KAAK,KAAK,CAGtC;;EAEX,aAAa,KAAK;;eAEL,UAAU;;YAEb,MAAM,KAAK;;mBAEJ,KAAK,UAAU,MAAM,eAAe,GAAG,CAAC;;aAE9C,aAAa,KAAK;;EAE7B,MAAM"}
1
+ {"version":3,"file":"events.js","names":[],"sources":["../../../src/openapi/importer/events.ts"],"sourcesContent":["import type { ParsedEvent } from '../types';\nimport { generateImports, generateSchemaModelCode } from '../schema-converter';\nimport { toPascalCase, toValidIdentifier } from '../../common/utils';\nimport type { ResolvedContractsrcConfig } from '@contractspec/lib.contracts';\n\n/**\n * Generate code for an event.\n */\nexport function generateEventCode(\n event: ParsedEvent,\n options: ResolvedContractsrcConfig\n): string {\n const eventName = toValidIdentifier(event.name);\n const modelName = toPascalCase(eventName) + 'Payload';\n\n const schemaFormat = options.schemaFormat || 'contractspec';\n // Generate payload model inline or referenced?\n // Let's generate the payload schema definition first\n const payloadModel = generateSchemaModelCode(\n event.payload,\n modelName,\n schemaFormat,\n options\n );\n\n const imports = new Set<string>();\n imports.add(\n \"import { defineEvent, type EventSpec } from '@contractspec/lib.contracts';\"\n );\n\n if (payloadModel.imports && payloadModel.imports.length > 0) {\n payloadModel.imports.forEach((i) => imports.add(i));\n } else if (payloadModel.fields && payloadModel.fields.length > 0) {\n const modelImports = generateImports(payloadModel.fields, options);\n // Merge imports - this is a bit hacky string manipulation but works for now\n modelImports\n .split('\\n')\n .filter(Boolean)\n .forEach((i) => imports.add(i));\n }\n\n // If payloadModel is a reference (empty fields and different name), import it\n if (payloadModel.name !== modelName) {\n const modelsDir = `../${options.conventions.models}`;\n const kebabName = payloadModel.name\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n .toLowerCase();\n imports.add(\n `import { ${payloadModel.name} } from '${modelsDir}/${kebabName}';`\n );\n }\n\n const allImports = Array.from(imports).join('\\n');\n\n return `\n${allImports}\n\n${payloadModel.code}\n\nexport const ${eventName} = defineEvent({\n meta: {\n key: '${event.name}',\n version: '1.0.0',\n description: ${JSON.stringify(event.description ?? '')},\n },\n payload: ${payloadModel.name},\n});\n`.trim();\n}\n"],"mappings":";;;;;;;AAQA,SAAgB,kBACd,OACA,SACQ;CACR,MAAM,YAAY,kBAAkB,MAAM,KAAK;CAC/C,MAAM,YAAY,aAAa,UAAU,GAAG;CAE5C,MAAM,eAAe,QAAQ,gBAAgB;CAG7C,MAAM,eAAe,wBACnB,MAAM,SACN,WACA,cACA,QACD;CAED,MAAM,0BAAU,IAAI,KAAa;AACjC,SAAQ,IACN,6EACD;AAED,KAAI,aAAa,WAAW,aAAa,QAAQ,SAAS,EACxD,cAAa,QAAQ,SAAS,MAAM,QAAQ,IAAI,EAAE,CAAC;UAC1C,aAAa,UAAU,aAAa,OAAO,SAAS,EAG7D,CAFqB,gBAAgB,aAAa,QAAQ,QAAQ,CAG/D,MAAM,KAAK,CACX,OAAO,QAAQ,CACf,SAAS,MAAM,QAAQ,IAAI,EAAE,CAAC;AAInC,KAAI,aAAa,SAAS,WAAW;EACnC,MAAM,YAAY,MAAM,QAAQ,YAAY;EAC5C,MAAM,YAAY,aAAa,KAC5B,QAAQ,sBAAsB,QAAQ,CACtC,aAAa;AAChB,UAAQ,IACN,YAAY,aAAa,KAAK,WAAW,UAAU,GAAG,UAAU,IACjE;;AAKH,QAAO;EAFY,MAAM,KAAK,QAAQ,CAAC,KAAK,KAAK,CAGtC;;EAEX,aAAa,KAAK;;eAEL,UAAU;;YAEb,MAAM,KAAK;;mBAEJ,KAAK,UAAU,MAAM,eAAe,GAAG,CAAC;;aAE9C,aAAa,KAAK;;EAE7B,MAAM"}
@@ -1 +1 @@
1
- {"version":3,"file":"generator.js","names":["lines: string[]"],"sources":["../../../src/openapi/importer/generator.ts"],"sourcesContent":["import type { ParsedOperation } from '../types';\nimport { toPascalCase, toSpecKey, toValidIdentifier } from '../../common/utils';\nimport { type GeneratedModel, generateImports } from '../schema-converter';\nimport { inferAuthLevel, inferOpKind } from './analyzer';\nimport type {\n ContractsrcConfig,\n OpenApiSourceConfig,\n} from '@contractspec/lib.contracts';\n\n/**\n * Generate ContractSpec TypeScript code for an operation.\n */\nexport function generateSpecCode(\n operation: ParsedOperation,\n contractspecConfig: ContractsrcConfig,\n options: Partial<OpenApiSourceConfig> = {},\n inputModel: GeneratedModel | null,\n outputModel: GeneratedModel | null,\n queryModel: GeneratedModel | null = null,\n paramsModel: GeneratedModel | null = null,\n headersModel: GeneratedModel | null = null\n): string {\n const specKey = toSpecKey(operation.operationId, options.prefix);\n const kind = inferOpKind(operation.method);\n const auth = inferAuthLevel(operation, options.defaultAuth ?? 'user');\n\n const lines: string[] = [];\n\n // Imports\n lines.push(\n \"import { defineCommand, defineQuery } from '@contractspec/lib.contracts';\"\n );\n if (inputModel || outputModel || queryModel || paramsModel || headersModel) {\n const collectedImports = new Set<string>();\n const models = [\n inputModel,\n outputModel,\n queryModel,\n paramsModel,\n headersModel,\n ].filter((m): m is GeneratedModel => !!m);\n\n // Add explicit imports from generators (e.g. Zod, JsonSchema)\n models.forEach((m) => {\n if (m.imports && m.imports.length > 0) {\n m.imports.forEach((i) => collectedImports.add(i));\n }\n });\n\n // Add legacy fields-based imports (ContractSpec format)\n const legacyModels = models.filter(\n (m) => !m.imports || m.imports.length === 0\n );\n const legacyFields = legacyModels.flatMap((m) => m.fields);\n\n if (legacyFields.length > 0) {\n const legacyImportStr = generateImports(\n legacyFields,\n contractspecConfig,\n false\n );\n legacyImportStr\n .split('\\n')\n .filter(Boolean)\n .forEach((i) => collectedImports.add(i));\n }\n\n if (collectedImports.size > 0) {\n lines.push(Array.from(collectedImports).sort().join('\\n'));\n }\n }\n lines.push('');\n\n // Generate schemas\n const schemaSections = [\n { label: 'Input schema', model: inputModel },\n { label: 'Query schema', model: queryModel },\n { label: 'Path schema', model: paramsModel },\n { label: 'Header schema', model: headersModel },\n { label: 'Output schema', model: outputModel },\n ];\n\n for (const section of schemaSections) {\n if (section.model && section.model.code) {\n lines.push(`// ${section.label}`);\n lines.push(section.model.code);\n lines.push('');\n }\n }\n\n // Generate spec\n const defineFunc = kind === 'command' ? 'defineCommand' : 'defineQuery';\n const safeName = toValidIdentifier(toPascalCase(operation.operationId));\n\n lines.push(`/**`);\n lines.push(` * ${operation.summary ?? operation.operationId}`);\n if (operation.description) {\n lines.push(` *`);\n lines.push(` * ${operation.description}`);\n }\n lines.push(` *`);\n lines.push(\n ` * @source OpenAPI: ${operation.method.toUpperCase()} ${operation.path}`\n );\n lines.push(` */`);\n lines.push(`export const ${safeName}Spec = ${defineFunc}({`);\n\n // Meta\n lines.push(' meta: {');\n lines.push(` key: '${specKey}',`);\n lines.push(\" version: '1.0.0',\");\n lines.push(` stability: '${options.defaultStability ?? 'stable'}',`);\n lines.push(\n ` owners: [${(options.defaultOwners ?? []).map((o) => `'${o}'`).join(', ')}],`\n );\n lines.push(` tags: [${operation.tags.map((t) => `'${t}'`).join(', ')}],`);\n lines.push(\n ` description: ${JSON.stringify(operation.summary ?? operation.operationId)},`\n );\n lines.push(\n ` goal: ${JSON.stringify(operation.description ?? 'Imported from OpenAPI')},`\n );\n lines.push(\n ` context: 'Imported from OpenAPI: ${operation.method.toUpperCase()} ${operation.path}',`\n );\n lines.push(' },');\n\n // IO\n lines.push(' io: {');\n lines.push(` input: ${inputModel?.name ?? 'null'},`);\n if (queryModel) lines.push(` query: ${queryModel.name},`);\n if (paramsModel) lines.push(` params: ${paramsModel.name},`);\n if (headersModel) lines.push(` headers: ${headersModel.name},`);\n\n if (outputModel) {\n lines.push(` output: ${outputModel.name},`);\n } else {\n lines.push(' output: null, // TODO: Define output schema');\n }\n lines.push(' },');\n\n // Policy\n lines.push(' policy: {');\n lines.push(` auth: '${auth}',`);\n lines.push(' },');\n\n // Transport hints\n const httpMethod = operation.method.toUpperCase();\n const restMethod = httpMethod === 'GET' ? 'GET' : 'POST';\n lines.push(' transport: {');\n lines.push(' rest: {');\n lines.push(` method: '${restMethod}',`);\n lines.push(` path: '${operation.path}',`);\n lines.push(' },');\n lines.push(' },');\n\n lines.push('});');\n\n return lines.join('\\n');\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"generator.js","names":[],"sources":["../../../src/openapi/importer/generator.ts"],"sourcesContent":["import type { ParsedOperation } from '../types';\nimport { toPascalCase, toSpecKey, toValidIdentifier } from '../../common/utils';\nimport { type GeneratedModel, generateImports } from '../schema-converter';\nimport { inferAuthLevel, inferOpKind } from './analyzer';\nimport type {\n ResolvedContractsrcConfig,\n OpenApiSourceConfig,\n} from '@contractspec/lib.contracts';\n\n/**\n * Generate ContractSpec TypeScript code for an operation.\n */\nexport function generateSpecCode(\n operation: ParsedOperation,\n contractspecConfig: ResolvedContractsrcConfig,\n options: Partial<OpenApiSourceConfig> = {},\n inputModel: GeneratedModel | null,\n outputModel: GeneratedModel | null,\n queryModel: GeneratedModel | null = null,\n paramsModel: GeneratedModel | null = null,\n headersModel: GeneratedModel | null = null\n): string {\n const specKey = toSpecKey(operation.operationId, options.prefix);\n const kind = inferOpKind(operation.method);\n const auth = inferAuthLevel(operation, options.defaultAuth ?? 'user');\n\n const lines: string[] = [];\n\n // Imports\n lines.push(\n \"import { defineCommand, defineQuery } from '@contractspec/lib.contracts';\"\n );\n if (inputModel || outputModel || queryModel || paramsModel || headersModel) {\n const collectedImports = new Set<string>();\n const models = [\n inputModel,\n outputModel,\n queryModel,\n paramsModel,\n headersModel,\n ].filter((m): m is GeneratedModel => !!m);\n\n // Add explicit imports from generators (e.g. Zod, JsonSchema)\n models.forEach((m) => {\n if (m.imports && m.imports.length > 0) {\n m.imports.forEach((i) => collectedImports.add(i));\n }\n });\n\n // Add legacy fields-based imports (ContractSpec format)\n const legacyModels = models.filter(\n (m) => !m.imports || m.imports.length === 0\n );\n const legacyFields = legacyModels.flatMap((m) => m.fields);\n\n if (legacyFields.length > 0) {\n const legacyImportStr = generateImports(\n legacyFields,\n contractspecConfig,\n false\n );\n legacyImportStr\n .split('\\n')\n .filter(Boolean)\n .forEach((i) => collectedImports.add(i));\n }\n\n if (collectedImports.size > 0) {\n lines.push(Array.from(collectedImports).sort().join('\\n'));\n }\n }\n lines.push('');\n\n // Generate schemas\n const schemaSections = [\n { label: 'Input schema', model: inputModel },\n { label: 'Query schema', model: queryModel },\n { label: 'Path schema', model: paramsModel },\n { label: 'Header schema', model: headersModel },\n { label: 'Output schema', model: outputModel },\n ];\n\n for (const section of schemaSections) {\n if (section.model && section.model.code) {\n lines.push(`// ${section.label}`);\n lines.push(section.model.code);\n lines.push('');\n }\n }\n\n // Generate spec\n const defineFunc = kind === 'command' ? 'defineCommand' : 'defineQuery';\n const safeName = toValidIdentifier(toPascalCase(operation.operationId));\n\n lines.push(`/**`);\n lines.push(` * ${operation.summary ?? operation.operationId}`);\n if (operation.description) {\n lines.push(` *`);\n lines.push(` * ${operation.description}`);\n }\n lines.push(` *`);\n lines.push(\n ` * @source OpenAPI: ${operation.method.toUpperCase()} ${operation.path}`\n );\n lines.push(` */`);\n lines.push(`export const ${safeName}Spec = ${defineFunc}({`);\n\n // Meta\n lines.push(' meta: {');\n lines.push(` key: '${specKey}',`);\n lines.push(\" version: '1.0.0',\");\n lines.push(` stability: '${options.defaultStability ?? 'stable'}',`);\n lines.push(\n ` owners: [${(options.defaultOwners ?? []).map((o) => `'${o}'`).join(', ')}],`\n );\n lines.push(` tags: [${operation.tags.map((t) => `'${t}'`).join(', ')}],`);\n lines.push(\n ` description: ${JSON.stringify(operation.summary ?? operation.operationId)},`\n );\n lines.push(\n ` goal: ${JSON.stringify(operation.description ?? 'Imported from OpenAPI')},`\n );\n lines.push(\n ` context: 'Imported from OpenAPI: ${operation.method.toUpperCase()} ${operation.path}',`\n );\n lines.push(' },');\n\n // IO\n lines.push(' io: {');\n lines.push(` input: ${inputModel?.name ?? 'null'},`);\n if (queryModel) lines.push(` query: ${queryModel.name},`);\n if (paramsModel) lines.push(` params: ${paramsModel.name},`);\n if (headersModel) lines.push(` headers: ${headersModel.name},`);\n\n if (outputModel) {\n lines.push(` output: ${outputModel.name},`);\n } else {\n lines.push(' output: null, // TODO: Define output schema');\n }\n lines.push(' },');\n\n // Policy\n lines.push(' policy: {');\n lines.push(` auth: '${auth}',`);\n lines.push(' },');\n\n // Transport hints\n const httpMethod = operation.method.toUpperCase();\n const restMethod = httpMethod === 'GET' ? 'GET' : 'POST';\n lines.push(' transport: {');\n lines.push(' rest: {');\n lines.push(` method: '${restMethod}',`);\n lines.push(` path: '${operation.path}',`);\n lines.push(' },');\n lines.push(' },');\n\n lines.push('});');\n\n return lines.join('\\n');\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"grouping.js","names":[],"sources":["../../../src/openapi/importer/grouping.ts"],"sourcesContent":["/**\n * Grouping utilities for OpenAPI import/export.\n * Determines output folder structure based on configuration.\n */\nimport type { FolderConventions } from '@contractspec/lib.contracts';\nimport type { ParsedOperation } from '../types';\n\n/**\n * Grouping strategy type (matches ContractSpec config).\n */\ntype GroupingStrategy =\n | 'by-tag'\n | 'by-owner'\n | 'by-domain'\n | 'by-url-path-single'\n | 'by-url-path-multi'\n | 'by-feature'\n | 'none';\n\n/**\n * Grouping rule configuration.\n */\ninterface GroupingRule {\n strategy: GroupingStrategy;\n urlPathLevel?: number;\n pattern?: string;\n}\n\n/**\n * Resolve the group folder for an operation based on grouping config.\n */\nexport function resolveOperationGroupFolder(\n operation: ParsedOperation,\n conventions: FolderConventions\n): string {\n const groupingRule = conventions.operationsGrouping as\n | GroupingRule\n | undefined;\n\n if (!groupingRule || groupingRule.strategy === 'none') {\n return '';\n }\n\n return applyGroupingStrategy(groupingRule, {\n name: operation.operationId,\n tags: operation.tags,\n path: operation.path,\n });\n}\n\n/**\n * Resolve the group folder for a model based on grouping config.\n */\nexport function resolveModelGroupFolder(\n modelName: string,\n conventions: FolderConventions,\n relatedPath?: string,\n relatedTags?: string[]\n): string {\n const groupingRule = conventions.modelsGrouping as GroupingRule | undefined;\n\n if (!groupingRule || groupingRule.strategy === 'none') {\n return '';\n }\n\n return applyGroupingStrategy(groupingRule, {\n name: modelName,\n tags: relatedTags ?? [],\n path: relatedPath,\n });\n}\n\n/**\n * Resolve the group folder for an event based on grouping config.\n */\nexport function resolveEventGroupFolder(\n eventName: string,\n conventions: FolderConventions,\n relatedTags?: string[]\n): string {\n const groupingRule = conventions.eventsGrouping as GroupingRule | undefined;\n\n if (!groupingRule || groupingRule.strategy === 'none') {\n return '';\n }\n\n return applyGroupingStrategy(groupingRule, {\n name: eventName,\n tags: relatedTags ?? [],\n });\n}\n\n/**\n * Apply grouping strategy to extract folder name.\n */\nfunction applyGroupingStrategy(\n rule: GroupingRule,\n context: {\n name: string;\n tags?: string[];\n path?: string;\n owners?: string[];\n }\n): string {\n switch (rule.strategy) {\n case 'by-tag':\n return context.tags?.[0] ?? 'untagged';\n\n case 'by-owner':\n return context.owners?.[0] ?? 'unowned';\n\n case 'by-domain':\n return extractDomain(context.name);\n\n case 'by-url-path-single':\n return extractUrlPathLevel(context.path, 1);\n\n case 'by-url-path-multi':\n return extractUrlPathLevel(context.path, rule.urlPathLevel ?? 2);\n\n case 'by-feature':\n // Use domain extraction for feature grouping\n return extractDomain(context.name);\n\n case 'none':\n default:\n return '';\n }\n}\n\n/**\n * Extract domain from operation/model name.\n * e.g., \"users.create\" -> \"users\"\n */\nfunction extractDomain(name: string): string {\n // Handle camelCase/PascalCase names\n if (name.includes('.')) {\n return name.split('.')[0] ?? 'default';\n }\n if (name.includes('_')) {\n return name.split('_')[0] ?? 'default';\n }\n // Extract from camelCase like \"createUser\" -> \"create\"\n const match = name.match(/^([a-z]+)/i);\n return match?.[1]?.toLowerCase() ?? 'default';\n}\n\n/**\n * Extract URL path segments for grouping.\n */\nfunction extractUrlPathLevel(path: string | undefined, level: number): string {\n if (!path) return 'root';\n const segments = path.split('/').filter(Boolean);\n\n // Filter out path parameters like {id}\n const nonParamSegments = segments.filter((s) => !s.startsWith('{'));\n\n if (nonParamSegments.length === 0) return 'root';\n\n return nonParamSegments.slice(0, level).join('/');\n}\n\n/**\n * Build full output path including group folder.\n */\nexport function buildOutputPath(\n baseDir: string,\n surfaceDir: string,\n groupFolder: string,\n fileName: string\n): string {\n const parts = [baseDir, surfaceDir];\n\n if (groupFolder) {\n parts.push(groupFolder);\n }\n\n parts.push(fileName);\n\n return parts.filter(Boolean).join('/');\n}\n\n/**\n * Determine if feature-based grouping should be applied.\n */\nexport function shouldGroupByFeature(conventions: FolderConventions): boolean {\n return conventions.groupByFeature;\n}\n"],"mappings":";;;;AA+BA,SAAgB,4BACd,WACA,aACQ;CACR,MAAM,eAAe,YAAY;AAIjC,KAAI,CAAC,gBAAgB,aAAa,aAAa,OAC7C,QAAO;AAGT,QAAO,sBAAsB,cAAc;EACzC,MAAM,UAAU;EAChB,MAAM,UAAU;EAChB,MAAM,UAAU;EACjB,CAAC;;;;;AAMJ,SAAgB,wBACd,WACA,aACA,aACA,aACQ;CACR,MAAM,eAAe,YAAY;AAEjC,KAAI,CAAC,gBAAgB,aAAa,aAAa,OAC7C,QAAO;AAGT,QAAO,sBAAsB,cAAc;EACzC,MAAM;EACN,MAAM,eAAe,EAAE;EACvB,MAAM;EACP,CAAC;;;;;AAMJ,SAAgB,wBACd,WACA,aACA,aACQ;CACR,MAAM,eAAe,YAAY;AAEjC,KAAI,CAAC,gBAAgB,aAAa,aAAa,OAC7C,QAAO;AAGT,QAAO,sBAAsB,cAAc;EACzC,MAAM;EACN,MAAM,eAAe,EAAE;EACxB,CAAC;;;;;AAMJ,SAAS,sBACP,MACA,SAMQ;AACR,SAAQ,KAAK,UAAb;EACE,KAAK,SACH,QAAO,QAAQ,OAAO,MAAM;EAE9B,KAAK,WACH,QAAO,QAAQ,SAAS,MAAM;EAEhC,KAAK,YACH,QAAO,cAAc,QAAQ,KAAK;EAEpC,KAAK,qBACH,QAAO,oBAAoB,QAAQ,MAAM,EAAE;EAE7C,KAAK,oBACH,QAAO,oBAAoB,QAAQ,MAAM,KAAK,gBAAgB,EAAE;EAElE,KAAK,aAEH,QAAO,cAAc,QAAQ,KAAK;EAEpC,KAAK;EACL,QACE,QAAO;;;;;;;AAQb,SAAS,cAAc,MAAsB;AAE3C,KAAI,KAAK,SAAS,IAAI,CACpB,QAAO,KAAK,MAAM,IAAI,CAAC,MAAM;AAE/B,KAAI,KAAK,SAAS,IAAI,CACpB,QAAO,KAAK,MAAM,IAAI,CAAC,MAAM;AAI/B,QADc,KAAK,MAAM,aAAa,GACvB,IAAI,aAAa,IAAI;;;;;AAMtC,SAAS,oBAAoB,MAA0B,OAAuB;AAC5E,KAAI,CAAC,KAAM,QAAO;CAIlB,MAAM,mBAHW,KAAK,MAAM,IAAI,CAAC,OAAO,QAAQ,CAGd,QAAQ,MAAM,CAAC,EAAE,WAAW,IAAI,CAAC;AAEnE,KAAI,iBAAiB,WAAW,EAAG,QAAO;AAE1C,QAAO,iBAAiB,MAAM,GAAG,MAAM,CAAC,KAAK,IAAI"}
1
+ {"version":3,"file":"grouping.js","names":[],"sources":["../../../src/openapi/importer/grouping.ts"],"sourcesContent":["/**\n * Grouping utilities for OpenAPI import/export.\n * Determines output folder structure based on configuration.\n */\nimport type { FolderConventions } from '@contractspec/lib.contracts';\nimport type { ParsedOperation } from '../types';\n\n/**\n * Grouping strategy type (matches ContractSpec config).\n */\ntype GroupingStrategy =\n | 'by-tag'\n | 'by-owner'\n | 'by-domain'\n | 'by-url-path-single'\n | 'by-url-path-multi'\n | 'by-feature'\n | 'none';\n\n/**\n * Grouping rule configuration.\n */\ninterface GroupingRule {\n strategy: GroupingStrategy;\n urlPathLevel?: number;\n pattern?: string;\n}\n\n/**\n * Resolve the group folder for an operation based on grouping config.\n */\nexport function resolveOperationGroupFolder(\n operation: ParsedOperation,\n conventions: FolderConventions\n): string {\n const groupingRule = conventions.operationsGrouping as\n | GroupingRule\n | undefined;\n\n if (!groupingRule || groupingRule.strategy === 'none') {\n return '';\n }\n\n return applyGroupingStrategy(groupingRule, {\n name: operation.operationId,\n tags: operation.tags,\n path: operation.path,\n });\n}\n\n/**\n * Resolve the group folder for a model based on grouping config.\n */\nexport function resolveModelGroupFolder(\n modelName: string,\n conventions: FolderConventions,\n relatedPath?: string,\n relatedTags?: string[]\n): string {\n const groupingRule = conventions.modelsGrouping as GroupingRule | undefined;\n\n if (!groupingRule || groupingRule.strategy === 'none') {\n return '';\n }\n\n return applyGroupingStrategy(groupingRule, {\n name: modelName,\n tags: relatedTags ?? [],\n path: relatedPath,\n });\n}\n\n/**\n * Resolve the group folder for an event based on grouping config.\n */\nexport function resolveEventGroupFolder(\n eventName: string,\n conventions: FolderConventions,\n relatedTags?: string[]\n): string {\n const groupingRule = conventions.eventsGrouping as GroupingRule | undefined;\n\n if (!groupingRule || groupingRule.strategy === 'none') {\n return '';\n }\n\n return applyGroupingStrategy(groupingRule, {\n name: eventName,\n tags: relatedTags ?? [],\n });\n}\n\n/**\n * Apply grouping strategy to extract folder name.\n */\nfunction applyGroupingStrategy(\n rule: GroupingRule,\n context: {\n name: string;\n tags?: string[];\n path?: string;\n owners?: string[];\n }\n): string {\n switch (rule.strategy) {\n case 'by-tag':\n return context.tags?.[0] ?? 'untagged';\n\n case 'by-owner':\n return context.owners?.[0] ?? 'unowned';\n\n case 'by-domain':\n return extractDomain(context.name);\n\n case 'by-url-path-single':\n return extractUrlPathLevel(context.path, 1);\n\n case 'by-url-path-multi':\n return extractUrlPathLevel(context.path, rule.urlPathLevel ?? 2);\n\n case 'by-feature':\n // Use domain extraction for feature grouping\n return extractDomain(context.name);\n\n case 'none':\n default:\n return '';\n }\n}\n\n/**\n * Extract domain from operation/model name.\n * e.g., \"users.create\" -> \"users\"\n */\nfunction extractDomain(name: string): string {\n // Handle camelCase/PascalCase names\n if (name.includes('.')) {\n return name.split('.')[0] ?? 'default';\n }\n if (name.includes('_')) {\n return name.split('_')[0] ?? 'default';\n }\n // Extract from camelCase like \"createUser\" -> \"create\"\n const match = name.match(/^([a-z]+)/i);\n return match?.[1]?.toLowerCase() ?? 'default';\n}\n\n/**\n * Extract URL path segments for grouping.\n */\nfunction extractUrlPathLevel(path: string | undefined, level: number): string {\n if (!path) return 'root';\n const segments = path.split('/').filter(Boolean);\n\n // Filter out path parameters like {id}\n const nonParamSegments = segments.filter((s) => !s.startsWith('{'));\n\n if (nonParamSegments.length === 0) return 'root';\n\n return nonParamSegments.slice(0, level).join('/');\n}\n\n/**\n * Build full output path including group folder.\n */\nexport function buildOutputPath(\n baseDir: string,\n surfaceDir: string,\n groupFolder: string,\n fileName: string\n): string {\n const parts = [baseDir, surfaceDir];\n\n if (groupFolder) {\n parts.push(groupFolder);\n }\n\n parts.push(fileName);\n\n return parts.filter(Boolean).join('/');\n}\n\n/**\n * Determine if feature-based grouping should be applied.\n */\nexport function shouldGroupByFeature(conventions: FolderConventions): boolean {\n return conventions.groupByFeature ?? false;\n}\n"],"mappings":";;;;AA+BA,SAAgB,4BACd,WACA,aACQ;CACR,MAAM,eAAe,YAAY;AAIjC,KAAI,CAAC,gBAAgB,aAAa,aAAa,OAC7C,QAAO;AAGT,QAAO,sBAAsB,cAAc;EACzC,MAAM,UAAU;EAChB,MAAM,UAAU;EAChB,MAAM,UAAU;EACjB,CAAC;;;;;AAMJ,SAAgB,wBACd,WACA,aACA,aACA,aACQ;CACR,MAAM,eAAe,YAAY;AAEjC,KAAI,CAAC,gBAAgB,aAAa,aAAa,OAC7C,QAAO;AAGT,QAAO,sBAAsB,cAAc;EACzC,MAAM;EACN,MAAM,eAAe,EAAE;EACvB,MAAM;EACP,CAAC;;;;;AAMJ,SAAgB,wBACd,WACA,aACA,aACQ;CACR,MAAM,eAAe,YAAY;AAEjC,KAAI,CAAC,gBAAgB,aAAa,aAAa,OAC7C,QAAO;AAGT,QAAO,sBAAsB,cAAc;EACzC,MAAM;EACN,MAAM,eAAe,EAAE;EACxB,CAAC;;;;;AAMJ,SAAS,sBACP,MACA,SAMQ;AACR,SAAQ,KAAK,UAAb;EACE,KAAK,SACH,QAAO,QAAQ,OAAO,MAAM;EAE9B,KAAK,WACH,QAAO,QAAQ,SAAS,MAAM;EAEhC,KAAK,YACH,QAAO,cAAc,QAAQ,KAAK;EAEpC,KAAK,qBACH,QAAO,oBAAoB,QAAQ,MAAM,EAAE;EAE7C,KAAK,oBACH,QAAO,oBAAoB,QAAQ,MAAM,KAAK,gBAAgB,EAAE;EAElE,KAAK,aAEH,QAAO,cAAc,QAAQ,KAAK;EAEpC,KAAK;EACL,QACE,QAAO;;;;;;;AAQb,SAAS,cAAc,MAAsB;AAE3C,KAAI,KAAK,SAAS,IAAI,CACpB,QAAO,KAAK,MAAM,IAAI,CAAC,MAAM;AAE/B,KAAI,KAAK,SAAS,IAAI,CACpB,QAAO,KAAK,MAAM,IAAI,CAAC,MAAM;AAI/B,QADc,KAAK,MAAM,aAAa,GACvB,IAAI,aAAa,IAAI;;;;;AAMtC,SAAS,oBAAoB,MAA0B,OAAuB;AAC5E,KAAI,CAAC,KAAM,QAAO;CAIlB,MAAM,mBAHW,KAAK,MAAM,IAAI,CAAC,OAAO,QAAQ,CAGd,QAAQ,MAAM,CAAC,EAAE,WAAW,IAAI,CAAC;AAEnE,KAAI,iBAAiB,WAAW,EAAG,QAAO;AAE1C,QAAO,iBAAiB,MAAM,GAAG,MAAM,CAAC,KAAK,IAAI"}
@@ -1,17 +1,17 @@
1
1
  import { ImportResult } from "../../common/types.js";
2
2
  import { ParseResult, ParsedOperation } from "../types.js";
3
- import { ContractsrcConfig, OpenApiSourceConfig } from "@contractspec/lib.contracts";
3
+ import { OpenApiSourceConfig, ResolvedContractsrcConfig } from "@contractspec/lib.contracts";
4
4
 
5
5
  //#region src/openapi/importer/index.d.ts
6
6
 
7
7
  /**
8
8
  * Import operations from a parsed OpenAPI document.
9
9
  */
10
- declare const importFromOpenApi: (parseResult: ParseResult, contractspecOptions: ContractsrcConfig, importOptions?: Partial<OpenApiSourceConfig>) => ImportResult;
10
+ declare const importFromOpenApi: (parseResult: ParseResult, contractspecOptions: ResolvedContractsrcConfig, importOptions?: Partial<OpenApiSourceConfig>) => ImportResult;
11
11
  /**
12
12
  * Import a single operation to ContractSpec code.
13
13
  */
14
- declare function importOperation(operation: ParsedOperation, options: Partial<OpenApiSourceConfig> | undefined, contractspecOptions: ContractsrcConfig): string;
14
+ declare function importOperation(operation: ParsedOperation, options: Partial<OpenApiSourceConfig> | undefined, contractspecOptions: ResolvedContractsrcConfig): string;
15
15
  //#endregion
16
16
  export { importFromOpenApi, importOperation };
17
17
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/openapi/importer/index.ts"],"sourcesContent":[],"mappings":";;;;;;;;;AAgTgB,cA/QH,iBA+QkB,EAAA,CAAA,WAAA,EA9QhB,WA8QgB,EAAA,mBAAA,EA7QR,iBA6QQ,EAAA,aAAA,CAAA,EA5Qd,OA4Qc,CA5QN,mBA4QM,CAAA,EAAA,GA3Q5B,YA2Q4B;;;;AAGR,iBAHP,eAAA,CAGO,SAAA,EAFV,eAEU,EAAA,OAAA,EADZ,OACY,CADJ,mBACI,CAAA,GAAA,SAAA,EAAA,mBAAA,EAAA,iBAAA,CAAA,EAAA,MAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/openapi/importer/index.ts"],"sourcesContent":[],"mappings":";;;;;;;;;AAgTgB,cA/QH,iBA+QkB,EAAA,CAAA,WAAA,EA9QhB,WA8QgB,EAAA,mBAAA,EA7QR,yBA6QQ,EAAA,aAAA,CAAA,EA5Qd,OA4Qc,CA5QN,mBA4QM,CAAA,EAAA,GA3Q5B,YA2Q4B;;;;AAGR,iBAHP,eAAA,CAGO,SAAA,EAFV,eAEU,EAAA,OAAA,EADZ,OACY,CADJ,mBACI,CAAA,GAAA,SAAA,EAAA,mBAAA,EAAA,yBAAA,CAAA,EAAA,MAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["specs: ImportedOperationSpec[]","skipped: ImportResult['skipped']","errors: ImportResult['errors']","transportHints: OpenApiTransportHints","source: OpenApiSource"],"sources":["../../../src/openapi/importer/index.ts"],"sourcesContent":["import type {\n OpenApiSource,\n OpenApiTransportHints,\n ParsedOperation,\n ParseResult,\n} from '../types';\nimport type { ImportedOperationSpec, ImportResult } from '../../common/types';\nimport { toFileName, toSpecKey } from '../../common/utils';\nimport { generateSchemaModelCode } from '../schema-converter';\nimport { buildInputSchemas, getOutputSchema } from './schemas';\nimport { generateSpecCode } from './generator';\nimport { generateModelCode } from './models';\nimport { generateEventCode } from './events';\nimport {\n resolveEventGroupFolder,\n resolveModelGroupFolder,\n resolveOperationGroupFolder,\n} from './grouping';\nimport type {\n ContractsrcConfig,\n OpenApiSourceConfig,\n} from '@contractspec/lib.contracts';\n\nexport * from './analyzer';\nexport * from './schemas';\nexport * from './generator';\nexport * from './models';\nexport * from './events';\nexport * from './grouping';\n\n/**\n * Import operations from a parsed OpenAPI document.\n */\nexport const importFromOpenApi = (\n parseResult: ParseResult,\n contractspecOptions: ContractsrcConfig,\n importOptions: Partial<OpenApiSourceConfig> = {}\n): ImportResult => {\n const { tags, exclude = [], include } = importOptions;\n const specs: ImportedOperationSpec[] = [];\n const skipped: ImportResult['skipped'] = [];\n const errors: ImportResult['errors'] = [];\n\n for (const operation of parseResult.operations) {\n // Filter by tags if specified\n if (tags && tags.length > 0) {\n const hasMatchingTag = operation.tags.some((t) => tags.includes(t));\n if (!hasMatchingTag) {\n skipped.push({\n sourceId: operation.operationId,\n reason: `No matching tags (has: ${operation.tags.join(', ')})`,\n });\n continue;\n }\n }\n\n // Filter by include/exclude\n if (include && include.length > 0) {\n if (!include.includes(operation.operationId)) {\n skipped.push({\n sourceId: operation.operationId,\n reason: 'Not in include list',\n });\n continue;\n }\n } else if (exclude.includes(operation.operationId)) {\n skipped.push({\n sourceId: operation.operationId,\n reason: 'In exclude list',\n });\n continue;\n }\n\n // Skip deprecated operations by default\n if (\n operation.deprecated &&\n importOptions.defaultStability !== 'deprecated'\n ) {\n skipped.push({\n sourceId: operation.operationId,\n reason: 'Deprecated operation',\n });\n continue;\n }\n\n try {\n // Build input schemas\n const inputSchemas = buildInputSchemas(operation);\n const schemaFormat =\n importOptions.schemaFormat ||\n contractspecOptions.schemaFormat ||\n 'contractspec';\n\n // Generate models for each input source\n const inputModel = inputSchemas.body\n ? generateSchemaModelCode(\n inputSchemas.body,\n `${operation.operationId}Input`,\n schemaFormat,\n contractspecOptions\n )\n : null;\n\n const queryModel = inputSchemas.query\n ? generateSchemaModelCode(\n inputSchemas.query,\n `${operation.operationId}Query`,\n schemaFormat,\n contractspecOptions\n )\n : null;\n\n const paramsModel = inputSchemas.params\n ? generateSchemaModelCode(\n inputSchemas.params,\n `${operation.operationId}Params`,\n schemaFormat,\n contractspecOptions\n )\n : null;\n\n const headersModel = inputSchemas.headers\n ? generateSchemaModelCode(\n inputSchemas.headers,\n `${operation.operationId}Headers`,\n schemaFormat,\n contractspecOptions\n )\n : null;\n\n // Get output schema\n const outputSchema = getOutputSchema(operation);\n let outputModel = outputSchema\n ? generateSchemaModelCode(\n outputSchema,\n `${operation.operationId}Output`,\n schemaFormat,\n contractspecOptions\n )\n : null;\n\n // Filter out empty/comment-only output models ONLY for ContractSpec format\n if (\n outputModel &&\n schemaFormat === 'contractspec' &&\n !outputModel.code.includes('defineSchemaModel')\n ) {\n outputModel = null;\n }\n\n // Generate spec code\n const code = generateSpecCode(\n operation,\n contractspecOptions,\n importOptions,\n inputModel,\n outputModel,\n queryModel,\n paramsModel,\n headersModel\n );\n const specName = toSpecKey(operation.operationId, importOptions.prefix);\n const fileName = toFileName(specName);\n\n // Build transport hints\n const transportHints: OpenApiTransportHints = {\n rest: {\n method:\n operation.method.toUpperCase() as OpenApiTransportHints['rest']['method'],\n path: operation.path,\n params: {\n path: operation.pathParams.map((p) => p.name),\n query: operation.queryParams.map((p) => p.name),\n header: operation.headerParams.map((p) => p.name),\n cookie: operation.cookieParams.map((p) => p.name),\n },\n },\n };\n\n // Build source info\n const source: OpenApiSource = {\n type: 'openapi',\n sourceId: operation.operationId,\n operationId: operation.operationId,\n openApiVersion: parseResult.version,\n importedAt: new Date(),\n };\n\n // Resolve group folder based on config\n const groupFolder = resolveOperationGroupFolder(\n operation,\n contractspecOptions.conventions\n );\n\n specs.push({\n code,\n fileName,\n groupFolder: groupFolder || undefined,\n source,\n transportHints,\n });\n } catch (error) {\n errors.push({\n sourceId: operation.operationId,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n // Import standalone models\n for (const [name, schema] of Object.entries(parseResult.schemas)) {\n try {\n const code = generateModelCode(name, schema, {\n ...contractspecOptions,\n schemaFormat:\n importOptions.schemaFormat || contractspecOptions.schemaFormat,\n });\n const fileName = toFileName(toSpecKey(name, importOptions.prefix));\n const groupFolder = resolveModelGroupFolder(\n name,\n contractspecOptions.conventions\n );\n\n specs.push({\n code,\n fileName,\n groupFolder: groupFolder || undefined,\n source: {\n type: 'openapi',\n sourceId: name,\n operationId: name,\n openApiVersion: parseResult.version,\n importedAt: new Date(),\n } as OpenApiSource,\n transportHints: {},\n });\n } catch (error) {\n errors.push({\n sourceId: name,\n error:\n error instanceof Error\n ? 'Model conversion failed: ' + error.message\n : String(error),\n });\n }\n }\n\n // Import events\n for (const event of parseResult.events) {\n try {\n const code = generateEventCode(event, {\n ...contractspecOptions,\n schemaFormat:\n importOptions.schemaFormat || contractspecOptions.schemaFormat,\n });\n const fileName = toFileName(toSpecKey(event.name, importOptions.prefix));\n const groupFolder = resolveEventGroupFolder(\n event.name,\n contractspecOptions.conventions\n );\n\n specs.push({\n code,\n fileName,\n groupFolder: groupFolder || undefined,\n source: {\n type: 'openapi',\n sourceId: event.name,\n operationId: event.name,\n openApiVersion: parseResult.version,\n importedAt: new Date(),\n } as OpenApiSource,\n transportHints: {},\n });\n } catch (error) {\n errors.push({\n sourceId: event.name,\n error:\n error instanceof Error\n ? 'Event conversion failed: ' + error.message\n : String(error),\n });\n }\n }\n\n return {\n operationSpecs: specs,\n skipped,\n errors,\n summary: {\n total:\n parseResult.operations.length +\n Object.keys(parseResult.schemas).length +\n parseResult.events.length,\n imported: specs.length,\n skipped: skipped.length,\n errors: errors.length,\n },\n };\n};\n\n/**\n * Import a single operation to ContractSpec code.\n */\nexport function importOperation(\n operation: ParsedOperation,\n options: Partial<OpenApiSourceConfig> = {},\n contractspecOptions: ContractsrcConfig\n): string {\n // Build input schemas\n const inputSchemas = buildInputSchemas(operation);\n const schemaFormat =\n options.schemaFormat || contractspecOptions.schemaFormat || 'contractspec';\n\n // Generate models for each input source\n const inputModel = inputSchemas.body\n ? generateSchemaModelCode(\n inputSchemas.body,\n `${operation.operationId}Input`,\n schemaFormat,\n contractspecOptions\n )\n : null;\n\n const queryModel = inputSchemas.query\n ? generateSchemaModelCode(\n inputSchemas.query,\n `${operation.operationId}Query`,\n schemaFormat,\n contractspecOptions\n )\n : null;\n\n const paramsModel = inputSchemas.params\n ? generateSchemaModelCode(\n inputSchemas.params,\n `${operation.operationId}Params`,\n schemaFormat,\n contractspecOptions\n )\n : null;\n\n const headersModel = inputSchemas.headers\n ? generateSchemaModelCode(\n inputSchemas.headers,\n `${operation.operationId}Headers`,\n schemaFormat,\n contractspecOptions\n )\n : null;\n\n const outputSchema = getOutputSchema(operation);\n const outputModel = outputSchema\n ? generateSchemaModelCode(\n outputSchema,\n `${operation.operationId}Output`,\n schemaFormat,\n contractspecOptions\n )\n : null;\n\n return generateSpecCode(\n operation,\n contractspecOptions,\n options,\n inputModel,\n outputModel,\n queryModel,\n paramsModel,\n headersModel\n );\n}\n"],"mappings":";;;;;;;;;;;;;AAiCA,MAAa,qBACX,aACA,qBACA,gBAA8C,EAAE,KAC/B;CACjB,MAAM,EAAE,MAAM,UAAU,EAAE,EAAE,YAAY;CACxC,MAAMA,QAAiC,EAAE;CACzC,MAAMC,UAAmC,EAAE;CAC3C,MAAMC,SAAiC,EAAE;AAEzC,MAAK,MAAM,aAAa,YAAY,YAAY;AAE9C,MAAI,QAAQ,KAAK,SAAS,GAExB;OAAI,CADmB,UAAU,KAAK,MAAM,MAAM,KAAK,SAAS,EAAE,CAAC,EAC9C;AACnB,YAAQ,KAAK;KACX,UAAU,UAAU;KACpB,QAAQ,0BAA0B,UAAU,KAAK,KAAK,KAAK,CAAC;KAC7D,CAAC;AACF;;;AAKJ,MAAI,WAAW,QAAQ,SAAS,GAC9B;OAAI,CAAC,QAAQ,SAAS,UAAU,YAAY,EAAE;AAC5C,YAAQ,KAAK;KACX,UAAU,UAAU;KACpB,QAAQ;KACT,CAAC;AACF;;aAEO,QAAQ,SAAS,UAAU,YAAY,EAAE;AAClD,WAAQ,KAAK;IACX,UAAU,UAAU;IACpB,QAAQ;IACT,CAAC;AACF;;AAIF,MACE,UAAU,cACV,cAAc,qBAAqB,cACnC;AACA,WAAQ,KAAK;IACX,UAAU,UAAU;IACpB,QAAQ;IACT,CAAC;AACF;;AAGF,MAAI;GAEF,MAAM,eAAe,kBAAkB,UAAU;GACjD,MAAM,eACJ,cAAc,gBACd,oBAAoB,gBACpB;GAGF,MAAM,aAAa,aAAa,OAC5B,wBACE,aAAa,MACb,GAAG,UAAU,YAAY,QACzB,cACA,oBACD,GACD;GAEJ,MAAM,aAAa,aAAa,QAC5B,wBACE,aAAa,OACb,GAAG,UAAU,YAAY,QACzB,cACA,oBACD,GACD;GAEJ,MAAM,cAAc,aAAa,SAC7B,wBACE,aAAa,QACb,GAAG,UAAU,YAAY,SACzB,cACA,oBACD,GACD;GAEJ,MAAM,eAAe,aAAa,UAC9B,wBACE,aAAa,SACb,GAAG,UAAU,YAAY,UACzB,cACA,oBACD,GACD;GAGJ,MAAM,eAAe,gBAAgB,UAAU;GAC/C,IAAI,cAAc,eACd,wBACE,cACA,GAAG,UAAU,YAAY,SACzB,cACA,oBACD,GACD;AAGJ,OACE,eACA,iBAAiB,kBACjB,CAAC,YAAY,KAAK,SAAS,oBAAoB,CAE/C,eAAc;GAIhB,MAAM,OAAO,iBACX,WACA,qBACA,eACA,YACA,aACA,YACA,aACA,aACD;GAED,MAAM,WAAW,WADA,UAAU,UAAU,aAAa,cAAc,OAAO,CAClC;GAGrC,MAAMC,iBAAwC,EAC5C,MAAM;IACJ,QACE,UAAU,OAAO,aAAa;IAChC,MAAM,UAAU;IAChB,QAAQ;KACN,MAAM,UAAU,WAAW,KAAK,MAAM,EAAE,KAAK;KAC7C,OAAO,UAAU,YAAY,KAAK,MAAM,EAAE,KAAK;KAC/C,QAAQ,UAAU,aAAa,KAAK,MAAM,EAAE,KAAK;KACjD,QAAQ,UAAU,aAAa,KAAK,MAAM,EAAE,KAAK;KAClD;IACF,EACF;GAGD,MAAMC,SAAwB;IAC5B,MAAM;IACN,UAAU,UAAU;IACpB,aAAa,UAAU;IACvB,gBAAgB,YAAY;IAC5B,4BAAY,IAAI,MAAM;IACvB;GAGD,MAAM,cAAc,4BAClB,WACA,oBAAoB,YACrB;AAED,SAAM,KAAK;IACT;IACA;IACA,aAAa,eAAe;IAC5B;IACA;IACD,CAAC;WACK,OAAO;AACd,UAAO,KAAK;IACV,UAAU,UAAU;IACpB,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;IAC9D,CAAC;;;AAKN,MAAK,MAAM,CAAC,MAAM,WAAW,OAAO,QAAQ,YAAY,QAAQ,CAC9D,KAAI;EACF,MAAM,OAAO,kBAAkB,MAAM,QAAQ;GAC3C,GAAG;GACH,cACE,cAAc,gBAAgB,oBAAoB;GACrD,CAAC;EACF,MAAM,WAAW,WAAW,UAAU,MAAM,cAAc,OAAO,CAAC;EAClE,MAAM,cAAc,wBAClB,MACA,oBAAoB,YACrB;AAED,QAAM,KAAK;GACT;GACA;GACA,aAAa,eAAe;GAC5B,QAAQ;IACN,MAAM;IACN,UAAU;IACV,aAAa;IACb,gBAAgB,YAAY;IAC5B,4BAAY,IAAI,MAAM;IACvB;GACD,gBAAgB,EAAE;GACnB,CAAC;UACK,OAAO;AACd,SAAO,KAAK;GACV,UAAU;GACV,OACE,iBAAiB,QACb,8BAA8B,MAAM,UACpC,OAAO,MAAM;GACpB,CAAC;;AAKN,MAAK,MAAM,SAAS,YAAY,OAC9B,KAAI;EACF,MAAM,OAAO,kBAAkB,OAAO;GACpC,GAAG;GACH,cACE,cAAc,gBAAgB,oBAAoB;GACrD,CAAC;EACF,MAAM,WAAW,WAAW,UAAU,MAAM,MAAM,cAAc,OAAO,CAAC;EACxE,MAAM,cAAc,wBAClB,MAAM,MACN,oBAAoB,YACrB;AAED,QAAM,KAAK;GACT;GACA;GACA,aAAa,eAAe;GAC5B,QAAQ;IACN,MAAM;IACN,UAAU,MAAM;IAChB,aAAa,MAAM;IACnB,gBAAgB,YAAY;IAC5B,4BAAY,IAAI,MAAM;IACvB;GACD,gBAAgB,EAAE;GACnB,CAAC;UACK,OAAO;AACd,SAAO,KAAK;GACV,UAAU,MAAM;GAChB,OACE,iBAAiB,QACb,8BAA8B,MAAM,UACpC,OAAO,MAAM;GACpB,CAAC;;AAIN,QAAO;EACL,gBAAgB;EAChB;EACA;EACA,SAAS;GACP,OACE,YAAY,WAAW,SACvB,OAAO,KAAK,YAAY,QAAQ,CAAC,SACjC,YAAY,OAAO;GACrB,UAAU,MAAM;GAChB,SAAS,QAAQ;GACjB,QAAQ,OAAO;GAChB;EACF;;;;;AAMH,SAAgB,gBACd,WACA,UAAwC,EAAE,EAC1C,qBACQ;CAER,MAAM,eAAe,kBAAkB,UAAU;CACjD,MAAM,eACJ,QAAQ,gBAAgB,oBAAoB,gBAAgB;CAG9D,MAAM,aAAa,aAAa,OAC5B,wBACE,aAAa,MACb,GAAG,UAAU,YAAY,QACzB,cACA,oBACD,GACD;CAEJ,MAAM,aAAa,aAAa,QAC5B,wBACE,aAAa,OACb,GAAG,UAAU,YAAY,QACzB,cACA,oBACD,GACD;CAEJ,MAAM,cAAc,aAAa,SAC7B,wBACE,aAAa,QACb,GAAG,UAAU,YAAY,SACzB,cACA,oBACD,GACD;CAEJ,MAAM,eAAe,aAAa,UAC9B,wBACE,aAAa,SACb,GAAG,UAAU,YAAY,UACzB,cACA,oBACD,GACD;CAEJ,MAAM,eAAe,gBAAgB,UAAU;AAU/C,QAAO,iBACL,WACA,qBACA,SACA,YAbkB,eAChB,wBACE,cACA,GAAG,UAAU,YAAY,SACzB,cACA,oBACD,GACD,MAQF,YACA,aACA,aACD"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/openapi/importer/index.ts"],"sourcesContent":["import type {\n OpenApiSource,\n OpenApiTransportHints,\n ParsedOperation,\n ParseResult,\n} from '../types';\nimport type { ImportedOperationSpec, ImportResult } from '../../common/types';\nimport { toFileName, toSpecKey } from '../../common/utils';\nimport { generateSchemaModelCode } from '../schema-converter';\nimport { buildInputSchemas, getOutputSchema } from './schemas';\nimport { generateSpecCode } from './generator';\nimport { generateModelCode } from './models';\nimport { generateEventCode } from './events';\nimport {\n resolveEventGroupFolder,\n resolveModelGroupFolder,\n resolveOperationGroupFolder,\n} from './grouping';\nimport type {\n ResolvedContractsrcConfig,\n OpenApiSourceConfig,\n} from '@contractspec/lib.contracts';\n\nexport * from './analyzer';\nexport * from './schemas';\nexport * from './generator';\nexport * from './models';\nexport * from './events';\nexport * from './grouping';\n\n/**\n * Import operations from a parsed OpenAPI document.\n */\nexport const importFromOpenApi = (\n parseResult: ParseResult,\n contractspecOptions: ResolvedContractsrcConfig,\n importOptions: Partial<OpenApiSourceConfig> = {}\n): ImportResult => {\n const { tags, exclude = [], include } = importOptions;\n const specs: ImportedOperationSpec[] = [];\n const skipped: ImportResult['skipped'] = [];\n const errors: ImportResult['errors'] = [];\n\n for (const operation of parseResult.operations) {\n // Filter by tags if specified\n if (tags && tags.length > 0) {\n const hasMatchingTag = operation.tags.some((t) => tags.includes(t));\n if (!hasMatchingTag) {\n skipped.push({\n sourceId: operation.operationId,\n reason: `No matching tags (has: ${operation.tags.join(', ')})`,\n });\n continue;\n }\n }\n\n // Filter by include/exclude\n if (include && include.length > 0) {\n if (!include.includes(operation.operationId)) {\n skipped.push({\n sourceId: operation.operationId,\n reason: 'Not in include list',\n });\n continue;\n }\n } else if (exclude.includes(operation.operationId)) {\n skipped.push({\n sourceId: operation.operationId,\n reason: 'In exclude list',\n });\n continue;\n }\n\n // Skip deprecated operations by default\n if (\n operation.deprecated &&\n importOptions.defaultStability !== 'deprecated'\n ) {\n skipped.push({\n sourceId: operation.operationId,\n reason: 'Deprecated operation',\n });\n continue;\n }\n\n try {\n // Build input schemas\n const inputSchemas = buildInputSchemas(operation);\n const schemaFormat =\n importOptions.schemaFormat ||\n contractspecOptions.schemaFormat ||\n 'contractspec';\n\n // Generate models for each input source\n const inputModel = inputSchemas.body\n ? generateSchemaModelCode(\n inputSchemas.body,\n `${operation.operationId}Input`,\n schemaFormat,\n contractspecOptions\n )\n : null;\n\n const queryModel = inputSchemas.query\n ? generateSchemaModelCode(\n inputSchemas.query,\n `${operation.operationId}Query`,\n schemaFormat,\n contractspecOptions\n )\n : null;\n\n const paramsModel = inputSchemas.params\n ? generateSchemaModelCode(\n inputSchemas.params,\n `${operation.operationId}Params`,\n schemaFormat,\n contractspecOptions\n )\n : null;\n\n const headersModel = inputSchemas.headers\n ? generateSchemaModelCode(\n inputSchemas.headers,\n `${operation.operationId}Headers`,\n schemaFormat,\n contractspecOptions\n )\n : null;\n\n // Get output schema\n const outputSchema = getOutputSchema(operation);\n let outputModel = outputSchema\n ? generateSchemaModelCode(\n outputSchema,\n `${operation.operationId}Output`,\n schemaFormat,\n contractspecOptions\n )\n : null;\n\n // Filter out empty/comment-only output models ONLY for ContractSpec format\n if (\n outputModel &&\n schemaFormat === 'contractspec' &&\n !outputModel.code.includes('defineSchemaModel')\n ) {\n outputModel = null;\n }\n\n // Generate spec code\n const code = generateSpecCode(\n operation,\n contractspecOptions,\n importOptions,\n inputModel,\n outputModel,\n queryModel,\n paramsModel,\n headersModel\n );\n const specName = toSpecKey(operation.operationId, importOptions.prefix);\n const fileName = toFileName(specName);\n\n // Build transport hints\n const transportHints: OpenApiTransportHints = {\n rest: {\n method:\n operation.method.toUpperCase() as OpenApiTransportHints['rest']['method'],\n path: operation.path,\n params: {\n path: operation.pathParams.map((p) => p.name),\n query: operation.queryParams.map((p) => p.name),\n header: operation.headerParams.map((p) => p.name),\n cookie: operation.cookieParams.map((p) => p.name),\n },\n },\n };\n\n // Build source info\n const source: OpenApiSource = {\n type: 'openapi',\n sourceId: operation.operationId,\n operationId: operation.operationId,\n openApiVersion: parseResult.version,\n importedAt: new Date(),\n };\n\n // Resolve group folder based on config\n const groupFolder = resolveOperationGroupFolder(\n operation,\n contractspecOptions.conventions\n );\n\n specs.push({\n code,\n fileName,\n groupFolder: groupFolder || undefined,\n source,\n transportHints,\n });\n } catch (error) {\n errors.push({\n sourceId: operation.operationId,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n // Import standalone models\n for (const [name, schema] of Object.entries(parseResult.schemas)) {\n try {\n const code = generateModelCode(name, schema, {\n ...contractspecOptions,\n schemaFormat:\n importOptions.schemaFormat || contractspecOptions.schemaFormat,\n });\n const fileName = toFileName(toSpecKey(name, importOptions.prefix));\n const groupFolder = resolveModelGroupFolder(\n name,\n contractspecOptions.conventions\n );\n\n specs.push({\n code,\n fileName,\n groupFolder: groupFolder || undefined,\n source: {\n type: 'openapi',\n sourceId: name,\n operationId: name,\n openApiVersion: parseResult.version,\n importedAt: new Date(),\n } as OpenApiSource,\n transportHints: {},\n });\n } catch (error) {\n errors.push({\n sourceId: name,\n error:\n error instanceof Error\n ? 'Model conversion failed: ' + error.message\n : String(error),\n });\n }\n }\n\n // Import events\n for (const event of parseResult.events) {\n try {\n const code = generateEventCode(event, {\n ...contractspecOptions,\n schemaFormat:\n importOptions.schemaFormat || contractspecOptions.schemaFormat,\n });\n const fileName = toFileName(toSpecKey(event.name, importOptions.prefix));\n const groupFolder = resolveEventGroupFolder(\n event.name,\n contractspecOptions.conventions\n );\n\n specs.push({\n code,\n fileName,\n groupFolder: groupFolder || undefined,\n source: {\n type: 'openapi',\n sourceId: event.name,\n operationId: event.name,\n openApiVersion: parseResult.version,\n importedAt: new Date(),\n } as OpenApiSource,\n transportHints: {},\n });\n } catch (error) {\n errors.push({\n sourceId: event.name,\n error:\n error instanceof Error\n ? 'Event conversion failed: ' + error.message\n : String(error),\n });\n }\n }\n\n return {\n operationSpecs: specs,\n skipped,\n errors,\n summary: {\n total:\n parseResult.operations.length +\n Object.keys(parseResult.schemas).length +\n parseResult.events.length,\n imported: specs.length,\n skipped: skipped.length,\n errors: errors.length,\n },\n };\n};\n\n/**\n * Import a single operation to ContractSpec code.\n */\nexport function importOperation(\n operation: ParsedOperation,\n options: Partial<OpenApiSourceConfig> = {},\n contractspecOptions: ResolvedContractsrcConfig\n): string {\n // Build input schemas\n const inputSchemas = buildInputSchemas(operation);\n const schemaFormat =\n options.schemaFormat || contractspecOptions.schemaFormat || 'contractspec';\n\n // Generate models for each input source\n const inputModel = inputSchemas.body\n ? generateSchemaModelCode(\n inputSchemas.body,\n `${operation.operationId}Input`,\n schemaFormat,\n contractspecOptions\n )\n : null;\n\n const queryModel = inputSchemas.query\n ? generateSchemaModelCode(\n inputSchemas.query,\n `${operation.operationId}Query`,\n schemaFormat,\n contractspecOptions\n )\n : null;\n\n const paramsModel = inputSchemas.params\n ? generateSchemaModelCode(\n inputSchemas.params,\n `${operation.operationId}Params`,\n schemaFormat,\n contractspecOptions\n )\n : null;\n\n const headersModel = inputSchemas.headers\n ? generateSchemaModelCode(\n inputSchemas.headers,\n `${operation.operationId}Headers`,\n schemaFormat,\n contractspecOptions\n )\n : null;\n\n const outputSchema = getOutputSchema(operation);\n const outputModel = outputSchema\n ? generateSchemaModelCode(\n outputSchema,\n `${operation.operationId}Output`,\n schemaFormat,\n contractspecOptions\n )\n : null;\n\n return generateSpecCode(\n operation,\n contractspecOptions,\n options,\n inputModel,\n outputModel,\n queryModel,\n paramsModel,\n headersModel\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"models.js","names":[],"sources":["../../../src/openapi/importer/models.ts"],"sourcesContent":["import type { OpenApiSchema } from '../types';\nimport { generateImports, generateSchemaModelCode } from '../schema-converter';\nimport { toPascalCase, toValidIdentifier } from '../../common/utils';\nimport type { ContractsrcConfig } from '@contractspec/lib.contracts';\n\n/**\n * Generate code for a standalone model.\n */\nexport function generateModelCode(\n name: string,\n schema: OpenApiSchema,\n options: ContractsrcConfig\n): string {\n const modelName = toPascalCase(toValidIdentifier(name));\n const schemaFormat = options.schemaFormat || 'contractspec';\n\n const model = generateSchemaModelCode(\n schema,\n modelName,\n schemaFormat,\n options\n );\n\n let imports = '';\n if (model.imports && model.imports.length > 0) {\n imports = model.imports.join('\\n');\n } else if (model.fields.length > 0) {\n imports = generateImports(model.fields, options);\n }\n\n return `\n${imports}\n\n${model.code}\n`.trim();\n}\n"],"mappings":";;;;;;;AAQA,SAAgB,kBACd,MACA,QACA,SACQ;CAIR,MAAM,QAAQ,wBACZ,QAJgB,aAAa,kBAAkB,KAAK,CAAC,EAClC,QAAQ,gBAAgB,gBAM3C,QACD;CAED,IAAI,UAAU;AACd,KAAI,MAAM,WAAW,MAAM,QAAQ,SAAS,EAC1C,WAAU,MAAM,QAAQ,KAAK,KAAK;UACzB,MAAM,OAAO,SAAS,EAC/B,WAAU,gBAAgB,MAAM,QAAQ,QAAQ;AAGlD,QAAO;EACP,QAAQ;;EAER,MAAM,KAAK;EACX,MAAM"}
1
+ {"version":3,"file":"models.js","names":[],"sources":["../../../src/openapi/importer/models.ts"],"sourcesContent":["import type { OpenApiSchema } from '../types';\nimport { generateImports, generateSchemaModelCode } from '../schema-converter';\nimport { toPascalCase, toValidIdentifier } from '../../common/utils';\nimport type { ResolvedContractsrcConfig } from '@contractspec/lib.contracts';\n\n/**\n * Generate code for a standalone model.\n */\nexport function generateModelCode(\n name: string,\n schema: OpenApiSchema,\n options: ResolvedContractsrcConfig\n): string {\n const modelName = toPascalCase(toValidIdentifier(name));\n const schemaFormat = options.schemaFormat || 'contractspec';\n\n const model = generateSchemaModelCode(\n schema,\n modelName,\n schemaFormat,\n options\n );\n\n let imports = '';\n if (model.imports && model.imports.length > 0) {\n imports = model.imports.join('\\n');\n } else if (model.fields.length > 0) {\n imports = generateImports(model.fields, options);\n }\n\n return `\n${imports}\n\n${model.code}\n`.trim();\n}\n"],"mappings":";;;;;;;AAQA,SAAgB,kBACd,MACA,QACA,SACQ;CAIR,MAAM,QAAQ,wBACZ,QAJgB,aAAa,kBAAkB,KAAK,CAAC,EAClC,QAAQ,gBAAgB,gBAM3C,QACD;CAED,IAAI,UAAU;AACd,KAAI,MAAM,WAAW,MAAM,QAAQ,SAAS,EAC1C,WAAU,MAAM,QAAQ,KAAK,KAAK;UACzB,MAAM,OAAO,SAAS,EAC/B,WAAU,gBAAgB,MAAM,QAAQ,QAAQ;AAGlD,QAAO;EACP,QAAQ;;EAER,MAAM,KAAK;EACX,MAAM"}
@@ -1 +1 @@
1
- {"version":3,"file":"schemas.js","names":["result: {\n body?: OpenApiSchema;\n query?: OpenApiSchema;\n params?: OpenApiSchema;\n headers?: OpenApiSchema;\n }"],"sources":["../../../src/openapi/importer/schemas.ts"],"sourcesContent":["import type { OpenApiSchema, ParsedOperation } from '../types';\n\n/**\n * Build separate input schemas for each parameter source.\n */\nexport function buildInputSchemas(operation: ParsedOperation): {\n body?: OpenApiSchema;\n query?: OpenApiSchema;\n params?: OpenApiSchema;\n headers?: OpenApiSchema;\n} {\n const result: {\n body?: OpenApiSchema;\n query?: OpenApiSchema;\n params?: OpenApiSchema;\n headers?: OpenApiSchema;\n } = {};\n\n // Path parameters -> params\n if (operation.pathParams.length > 0) {\n result.params = {\n type: 'object',\n properties: operation.pathParams.reduce(\n (acc, p) => {\n acc[p.name] = p.schema;\n return acc;\n },\n {} as Record<string, OpenApiSchema>\n ),\n required: operation.pathParams.map((p) => p.name),\n } as unknown as OpenApiSchema;\n }\n\n // Query parameters -> query\n if (operation.queryParams.length > 0) {\n result.query = {\n type: 'object',\n properties: operation.queryParams.reduce(\n (acc, p) => {\n acc[p.name] = p.schema;\n return acc;\n },\n {} as Record<string, OpenApiSchema>\n ),\n required: operation.queryParams\n .filter((p) => p.required)\n .map((p) => p.name),\n } as unknown as OpenApiSchema;\n }\n\n // Header parameters -> headers\n const excludedHeaders = [\n 'authorization',\n 'content-type',\n 'accept',\n 'user-agent',\n ];\n const actualHeaders = operation.headerParams.filter(\n (p) => !excludedHeaders.includes(p.name.toLowerCase())\n );\n if (actualHeaders.length > 0) {\n result.headers = {\n type: 'object',\n properties: actualHeaders.reduce(\n (acc, p) => {\n acc[p.name] = p.schema;\n return acc;\n },\n {} as Record<string, OpenApiSchema>\n ),\n required: actualHeaders.filter((p) => p.required).map((p) => p.name),\n } as unknown as OpenApiSchema;\n }\n\n // Request body -> body\n if (operation.requestBody?.schema) {\n result.body = operation.requestBody.schema;\n }\n\n return result;\n}\n\n/**\n * Get the output schema from the operation responses.\n */\nexport function getOutputSchema(\n operation: ParsedOperation\n): OpenApiSchema | null {\n // Prefer 200, then 201, then 2xx responses\n const successCodes = ['200', '201', '202', '204'];\n\n for (const code of successCodes) {\n const response = operation.responses[code];\n if (response?.schema) {\n return response.schema;\n }\n }\n\n // Check for any 2xx response\n for (const [code, response] of Object.entries(operation.responses)) {\n if (code.startsWith('2') && response.schema) {\n return response.schema;\n }\n }\n\n return null;\n}\n"],"mappings":";;;;AAKA,SAAgB,kBAAkB,WAKhC;CACA,MAAMA,SAKF,EAAE;AAGN,KAAI,UAAU,WAAW,SAAS,EAChC,QAAO,SAAS;EACd,MAAM;EACN,YAAY,UAAU,WAAW,QAC9B,KAAK,MAAM;AACV,OAAI,EAAE,QAAQ,EAAE;AAChB,UAAO;KAET,EAAE,CACH;EACD,UAAU,UAAU,WAAW,KAAK,MAAM,EAAE,KAAK;EAClD;AAIH,KAAI,UAAU,YAAY,SAAS,EACjC,QAAO,QAAQ;EACb,MAAM;EACN,YAAY,UAAU,YAAY,QAC/B,KAAK,MAAM;AACV,OAAI,EAAE,QAAQ,EAAE;AAChB,UAAO;KAET,EAAE,CACH;EACD,UAAU,UAAU,YACjB,QAAQ,MAAM,EAAE,SAAS,CACzB,KAAK,MAAM,EAAE,KAAK;EACtB;CAIH,MAAM,kBAAkB;EACtB;EACA;EACA;EACA;EACD;CACD,MAAM,gBAAgB,UAAU,aAAa,QAC1C,MAAM,CAAC,gBAAgB,SAAS,EAAE,KAAK,aAAa,CAAC,CACvD;AACD,KAAI,cAAc,SAAS,EACzB,QAAO,UAAU;EACf,MAAM;EACN,YAAY,cAAc,QACvB,KAAK,MAAM;AACV,OAAI,EAAE,QAAQ,EAAE;AAChB,UAAO;KAET,EAAE,CACH;EACD,UAAU,cAAc,QAAQ,MAAM,EAAE,SAAS,CAAC,KAAK,MAAM,EAAE,KAAK;EACrE;AAIH,KAAI,UAAU,aAAa,OACzB,QAAO,OAAO,UAAU,YAAY;AAGtC,QAAO;;;;;AAMT,SAAgB,gBACd,WACsB;AAItB,MAAK,MAAM,QAFU;EAAC;EAAO;EAAO;EAAO;EAAM,EAEhB;EAC/B,MAAM,WAAW,UAAU,UAAU;AACrC,MAAI,UAAU,OACZ,QAAO,SAAS;;AAKpB,MAAK,MAAM,CAAC,MAAM,aAAa,OAAO,QAAQ,UAAU,UAAU,CAChE,KAAI,KAAK,WAAW,IAAI,IAAI,SAAS,OACnC,QAAO,SAAS;AAIpB,QAAO"}
1
+ {"version":3,"file":"schemas.js","names":[],"sources":["../../../src/openapi/importer/schemas.ts"],"sourcesContent":["import type { OpenApiSchema, ParsedOperation } from '../types';\n\n/**\n * Build separate input schemas for each parameter source.\n */\nexport function buildInputSchemas(operation: ParsedOperation): {\n body?: OpenApiSchema;\n query?: OpenApiSchema;\n params?: OpenApiSchema;\n headers?: OpenApiSchema;\n} {\n const result: {\n body?: OpenApiSchema;\n query?: OpenApiSchema;\n params?: OpenApiSchema;\n headers?: OpenApiSchema;\n } = {};\n\n // Path parameters -> params\n if (operation.pathParams.length > 0) {\n result.params = {\n type: 'object',\n properties: operation.pathParams.reduce(\n (acc, p) => {\n acc[p.name] = p.schema;\n return acc;\n },\n {} as Record<string, OpenApiSchema>\n ),\n required: operation.pathParams.map((p) => p.name),\n } as unknown as OpenApiSchema;\n }\n\n // Query parameters -> query\n if (operation.queryParams.length > 0) {\n result.query = {\n type: 'object',\n properties: operation.queryParams.reduce(\n (acc, p) => {\n acc[p.name] = p.schema;\n return acc;\n },\n {} as Record<string, OpenApiSchema>\n ),\n required: operation.queryParams\n .filter((p) => p.required)\n .map((p) => p.name),\n } as unknown as OpenApiSchema;\n }\n\n // Header parameters -> headers\n const excludedHeaders = [\n 'authorization',\n 'content-type',\n 'accept',\n 'user-agent',\n ];\n const actualHeaders = operation.headerParams.filter(\n (p) => !excludedHeaders.includes(p.name.toLowerCase())\n );\n if (actualHeaders.length > 0) {\n result.headers = {\n type: 'object',\n properties: actualHeaders.reduce(\n (acc, p) => {\n acc[p.name] = p.schema;\n return acc;\n },\n {} as Record<string, OpenApiSchema>\n ),\n required: actualHeaders.filter((p) => p.required).map((p) => p.name),\n } as unknown as OpenApiSchema;\n }\n\n // Request body -> body\n if (operation.requestBody?.schema) {\n result.body = operation.requestBody.schema;\n }\n\n return result;\n}\n\n/**\n * Get the output schema from the operation responses.\n */\nexport function getOutputSchema(\n operation: ParsedOperation\n): OpenApiSchema | null {\n // Prefer 200, then 201, then 2xx responses\n const successCodes = ['200', '201', '202', '204'];\n\n for (const code of successCodes) {\n const response = operation.responses[code];\n if (response?.schema) {\n return response.schema;\n }\n }\n\n // Check for any 2xx response\n for (const [code, response] of Object.entries(operation.responses)) {\n if (code.startsWith('2') && response.schema) {\n return response.schema;\n }\n }\n\n return null;\n}\n"],"mappings":";;;;AAKA,SAAgB,kBAAkB,WAKhC;CACA,MAAM,SAKF,EAAE;AAGN,KAAI,UAAU,WAAW,SAAS,EAChC,QAAO,SAAS;EACd,MAAM;EACN,YAAY,UAAU,WAAW,QAC9B,KAAK,MAAM;AACV,OAAI,EAAE,QAAQ,EAAE;AAChB,UAAO;KAET,EAAE,CACH;EACD,UAAU,UAAU,WAAW,KAAK,MAAM,EAAE,KAAK;EAClD;AAIH,KAAI,UAAU,YAAY,SAAS,EACjC,QAAO,QAAQ;EACb,MAAM;EACN,YAAY,UAAU,YAAY,QAC/B,KAAK,MAAM;AACV,OAAI,EAAE,QAAQ,EAAE;AAChB,UAAO;KAET,EAAE,CACH;EACD,UAAU,UAAU,YACjB,QAAQ,MAAM,EAAE,SAAS,CACzB,KAAK,MAAM,EAAE,KAAK;EACtB;CAIH,MAAM,kBAAkB;EACtB;EACA;EACA;EACA;EACD;CACD,MAAM,gBAAgB,UAAU,aAAa,QAC1C,MAAM,CAAC,gBAAgB,SAAS,EAAE,KAAK,aAAa,CAAC,CACvD;AACD,KAAI,cAAc,SAAS,EACzB,QAAO,UAAU;EACf,MAAM;EACN,YAAY,cAAc,QACvB,KAAK,MAAM;AACV,OAAI,EAAE,QAAQ,EAAE;AAChB,UAAO;KAET,EAAE,CACH;EACD,UAAU,cAAc,QAAQ,MAAM,EAAE,SAAS,CAAC,KAAK,MAAM,EAAE,KAAK;EACrE;AAIH,KAAI,UAAU,aAAa,OACzB,QAAO,OAAO,UAAU,YAAY;AAGtC,QAAO;;;;;AAMT,SAAgB,gBACd,WACsB;AAItB,MAAK,MAAM,QAFU;EAAC;EAAO;EAAO;EAAO;EAAM,EAEhB;EAC/B,MAAM,WAAW,UAAU,UAAU;AACrC,MAAI,UAAU,OACZ,QAAO,SAAS;;AAKpB,MAAK,MAAM,CAAC,MAAM,aAAa,OAAO,QAAQ,UAAU,UAAU,CAChE,KAAI,KAAK,WAAW,IAAI,IAAI,SAAS,OACnC,QAAO,SAAS;AAIpB,QAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"document.js","names":["warnings: string[]","operations: ParsedOperation[]","schemas: Record<string, OpenApiSchema>","servers: OpenApiServer[]","events: ParsedEvent[]","content: string","format: 'json' | 'yaml'"],"sources":["../../../src/openapi/parser/document.ts"],"sourcesContent":["import type {\n OpenApiDocument,\n OpenApiParameter,\n OpenApiParseOptions,\n OpenApiSchema,\n OpenApiServer,\n ParsedEvent,\n ParsedOperation,\n ParseResult,\n} from '../types';\nimport type { OpenAPIV3, OpenAPIV3_1 } from 'openapi-types';\nimport {\n detectFormat,\n detectVersion,\n HTTP_METHODS,\n parseOpenApiString,\n} from './utils';\nimport { parseOperation } from './operation';\n\n/**\n * Parse an OpenAPI document into a structured result.\n */\nexport function parseOpenApiDocument(\n doc: OpenApiDocument,\n _options: OpenApiParseOptions = {}\n): ParseResult {\n const version = detectVersion(doc);\n const warnings: string[] = [];\n const operations: ParsedOperation[] = [];\n\n // Parse operations from paths\n for (const [path, pathItem] of Object.entries(doc.paths ?? {})) {\n if (!pathItem) continue;\n\n // Get path-level parameters\n const pathParams = (pathItem as OpenAPIV3.PathItemObject).parameters;\n\n for (const method of HTTP_METHODS) {\n const operation = (pathItem as Record<string, unknown>)[method] as\n | OpenAPIV3.OperationObject\n | OpenAPIV3_1.OperationObject\n | undefined;\n\n if (operation) {\n try {\n operations.push(\n parseOperation(\n doc,\n method,\n path,\n operation,\n pathParams as OpenApiParameter[]\n )\n );\n } catch (error) {\n warnings.push(\n `Failed to parse ${method.toUpperCase()} ${path}: ${error}`\n );\n }\n }\n }\n }\n\n // Extract component schemas\n const schemas: Record<string, OpenApiSchema> = {};\n const components = doc.components;\n if (components?.schemas) {\n for (const [name, schema] of Object.entries(components.schemas)) {\n schemas[name] = schema as OpenApiSchema;\n }\n }\n\n // Parse servers\n // Parse servers\n const servers: OpenApiServer[] = (doc.servers ?? []).map((s) => ({\n url: s.url,\n description: s.description,\n variables: s.variables as OpenApiServer['variables'],\n }));\n\n // Parse webhooks (as events)\n const events: ParsedEvent[] = [];\n if ('webhooks' in doc && doc.webhooks) {\n for (const [name, pathItem] of Object.entries(doc.webhooks)) {\n if (typeof pathItem !== 'object' || !pathItem) continue;\n // Webhooks usually have a POST method defining the payload\n const operation = (pathItem as Record<string, unknown>)['post'] as\n | OpenAPIV3.OperationObject\n | OpenAPIV3_1.OperationObject\n | undefined;\n\n if (operation && operation.requestBody) {\n if ('$ref' in operation.requestBody) {\n throw new Error(`'$ref' isn't supported`);\n }\n // Extract payload schema\n const content = operation.requestBody.content?.['application/json'];\n if (content?.schema) {\n events.push({\n name,\n description: operation.summary || operation.description,\n payload: content.schema,\n });\n }\n }\n }\n }\n\n return {\n document: doc,\n version,\n info: {\n title: doc.info.title,\n version: doc.info.version,\n description: doc.info.description,\n },\n operations,\n schemas,\n servers,\n warnings,\n events,\n };\n}\n\n/**\n * Parse OpenAPI from a file path or URL.\n * Note: This is an async function that requires I/O adapters.\n * For pure parsing, use parseOpenApiString or parseOpenApiDocument.\n */\nexport async function parseOpenApi(\n source: string,\n options: OpenApiParseOptions & {\n fetch?: typeof globalThis.fetch;\n readFile?: (path: string) => Promise<string>;\n } = {}\n): Promise<ParseResult> {\n const {\n fetch: fetchFn = globalThis.fetch,\n readFile,\n timeout = 30000,\n } = options;\n\n let content: string;\n let format: 'json' | 'yaml';\n\n if (source.startsWith('http://') || source.startsWith('https://')) {\n // Fetch from URL\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const response = await fetchFn(source, { signal: controller.signal });\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n content = await response.text();\n } finally {\n clearTimeout(timeoutId);\n }\n\n // Detect format from URL or content\n if (source.endsWith('.yaml') || source.endsWith('.yml')) {\n format = 'yaml';\n } else if (source.endsWith('.json')) {\n format = 'json';\n } else {\n format = detectFormat(content);\n }\n } else {\n // Read from file\n if (!readFile) {\n throw new Error('readFile adapter required for file paths');\n }\n content = await readFile(source);\n\n // Detect format from extension or content\n if (source.endsWith('.yaml') || source.endsWith('.yml')) {\n format = 'yaml';\n } else if (source.endsWith('.json')) {\n format = 'json';\n } else {\n format = detectFormat(content);\n }\n }\n\n const doc = parseOpenApiString(content, format);\n return parseOpenApiDocument(doc, options);\n}\n"],"mappings":";;;;;;;AAsBA,SAAgB,qBACd,KACA,WAAgC,EAAE,EACrB;CACb,MAAM,UAAU,cAAc,IAAI;CAClC,MAAMA,WAAqB,EAAE;CAC7B,MAAMC,aAAgC,EAAE;AAGxC,MAAK,MAAM,CAAC,MAAM,aAAa,OAAO,QAAQ,IAAI,SAAS,EAAE,CAAC,EAAE;AAC9D,MAAI,CAAC,SAAU;EAGf,MAAM,aAAc,SAAsC;AAE1D,OAAK,MAAM,UAAU,cAAc;GACjC,MAAM,YAAa,SAAqC;AAKxD,OAAI,UACF,KAAI;AACF,eAAW,KACT,eACE,KACA,QACA,MACA,WACA,WACD,CACF;YACM,OAAO;AACd,aAAS,KACP,mBAAmB,OAAO,aAAa,CAAC,GAAG,KAAK,IAAI,QACrD;;;;CAOT,MAAMC,UAAyC,EAAE;CACjD,MAAM,aAAa,IAAI;AACvB,KAAI,YAAY,QACd,MAAK,MAAM,CAAC,MAAM,WAAW,OAAO,QAAQ,WAAW,QAAQ,CAC7D,SAAQ,QAAQ;CAMpB,MAAMC,WAA4B,IAAI,WAAW,EAAE,EAAE,KAAK,OAAO;EAC/D,KAAK,EAAE;EACP,aAAa,EAAE;EACf,WAAW,EAAE;EACd,EAAE;CAGH,MAAMC,SAAwB,EAAE;AAChC,KAAI,cAAc,OAAO,IAAI,SAC3B,MAAK,MAAM,CAAC,MAAM,aAAa,OAAO,QAAQ,IAAI,SAAS,EAAE;AAC3D,MAAI,OAAO,aAAa,YAAY,CAAC,SAAU;EAE/C,MAAM,YAAa,SAAqC;AAKxD,MAAI,aAAa,UAAU,aAAa;AACtC,OAAI,UAAU,UAAU,YACtB,OAAM,IAAI,MAAM,yBAAyB;GAG3C,MAAM,UAAU,UAAU,YAAY,UAAU;AAChD,OAAI,SAAS,OACX,QAAO,KAAK;IACV;IACA,aAAa,UAAU,WAAW,UAAU;IAC5C,SAAS,QAAQ;IAClB,CAAC;;;AAMV,QAAO;EACL,UAAU;EACV;EACA,MAAM;GACJ,OAAO,IAAI,KAAK;GAChB,SAAS,IAAI,KAAK;GAClB,aAAa,IAAI,KAAK;GACvB;EACD;EACA;EACA;EACA;EACA;EACD;;;;;;;AAQH,eAAsB,aACpB,QACA,UAGI,EAAE,EACgB;CACtB,MAAM,EACJ,OAAO,UAAU,WAAW,OAC5B,UACA,UAAU,QACR;CAEJ,IAAIC;CACJ,IAAIC;AAEJ,KAAI,OAAO,WAAW,UAAU,IAAI,OAAO,WAAW,WAAW,EAAE;EAEjE,MAAM,aAAa,IAAI,iBAAiB;EACxC,MAAM,YAAY,iBAAiB,WAAW,OAAO,EAAE,QAAQ;AAE/D,MAAI;GACF,MAAM,WAAW,MAAM,QAAQ,QAAQ,EAAE,QAAQ,WAAW,QAAQ,CAAC;AACrE,OAAI,CAAC,SAAS,GACZ,OAAM,IAAI,MAAM,QAAQ,SAAS,OAAO,IAAI,SAAS,aAAa;AAEpE,aAAU,MAAM,SAAS,MAAM;YACvB;AACR,gBAAa,UAAU;;AAIzB,MAAI,OAAO,SAAS,QAAQ,IAAI,OAAO,SAAS,OAAO,CACrD,UAAS;WACA,OAAO,SAAS,QAAQ,CACjC,UAAS;MAET,UAAS,aAAa,QAAQ;QAE3B;AAEL,MAAI,CAAC,SACH,OAAM,IAAI,MAAM,2CAA2C;AAE7D,YAAU,MAAM,SAAS,OAAO;AAGhC,MAAI,OAAO,SAAS,QAAQ,IAAI,OAAO,SAAS,OAAO,CACrD,UAAS;WACA,OAAO,SAAS,QAAQ,CACjC,UAAS;MAET,UAAS,aAAa,QAAQ;;AAKlC,QAAO,qBADK,mBAAmB,SAAS,OAAO,EACd,QAAQ"}
1
+ {"version":3,"file":"document.js","names":[],"sources":["../../../src/openapi/parser/document.ts"],"sourcesContent":["import type {\n OpenApiDocument,\n OpenApiParameter,\n OpenApiParseOptions,\n OpenApiSchema,\n OpenApiServer,\n ParsedEvent,\n ParsedOperation,\n ParseResult,\n} from '../types';\nimport type { OpenAPIV3, OpenAPIV3_1 } from 'openapi-types';\nimport {\n detectFormat,\n detectVersion,\n HTTP_METHODS,\n parseOpenApiString,\n} from './utils';\nimport { parseOperation } from './operation';\n\n/**\n * Parse an OpenAPI document into a structured result.\n */\nexport function parseOpenApiDocument(\n doc: OpenApiDocument,\n _options: OpenApiParseOptions = {}\n): ParseResult {\n const version = detectVersion(doc);\n const warnings: string[] = [];\n const operations: ParsedOperation[] = [];\n\n // Parse operations from paths\n for (const [path, pathItem] of Object.entries(doc.paths ?? {})) {\n if (!pathItem) continue;\n\n // Get path-level parameters\n const pathParams = (pathItem as OpenAPIV3.PathItemObject).parameters;\n\n for (const method of HTTP_METHODS) {\n const operation = (pathItem as Record<string, unknown>)[method] as\n | OpenAPIV3.OperationObject\n | OpenAPIV3_1.OperationObject\n | undefined;\n\n if (operation) {\n try {\n operations.push(\n parseOperation(\n doc,\n method,\n path,\n operation,\n pathParams as OpenApiParameter[]\n )\n );\n } catch (error) {\n warnings.push(\n `Failed to parse ${method.toUpperCase()} ${path}: ${error}`\n );\n }\n }\n }\n }\n\n // Extract component schemas\n const schemas: Record<string, OpenApiSchema> = {};\n const components = doc.components;\n if (components?.schemas) {\n for (const [name, schema] of Object.entries(components.schemas)) {\n schemas[name] = schema as OpenApiSchema;\n }\n }\n\n // Parse servers\n // Parse servers\n const servers: OpenApiServer[] = (doc.servers ?? []).map((s) => ({\n url: s.url,\n description: s.description,\n variables: s.variables as OpenApiServer['variables'],\n }));\n\n // Parse webhooks (as events)\n const events: ParsedEvent[] = [];\n if ('webhooks' in doc && doc.webhooks) {\n for (const [name, pathItem] of Object.entries(doc.webhooks)) {\n if (typeof pathItem !== 'object' || !pathItem) continue;\n // Webhooks usually have a POST method defining the payload\n const operation = (pathItem as Record<string, unknown>)['post'] as\n | OpenAPIV3.OperationObject\n | OpenAPIV3_1.OperationObject\n | undefined;\n\n if (operation && operation.requestBody) {\n if ('$ref' in operation.requestBody) {\n throw new Error(`'$ref' isn't supported`);\n }\n // Extract payload schema\n const content = operation.requestBody.content?.['application/json'];\n if (content?.schema) {\n events.push({\n name,\n description: operation.summary || operation.description,\n payload: content.schema,\n });\n }\n }\n }\n }\n\n return {\n document: doc,\n version,\n info: {\n title: doc.info.title,\n version: doc.info.version,\n description: doc.info.description,\n },\n operations,\n schemas,\n servers,\n warnings,\n events,\n };\n}\n\n/**\n * Parse OpenAPI from a file path or URL.\n * Note: This is an async function that requires I/O adapters.\n * For pure parsing, use parseOpenApiString or parseOpenApiDocument.\n */\nexport async function parseOpenApi(\n source: string,\n options: OpenApiParseOptions & {\n fetch?: typeof globalThis.fetch;\n readFile?: (path: string) => Promise<string>;\n } = {}\n): Promise<ParseResult> {\n const {\n fetch: fetchFn = globalThis.fetch,\n readFile,\n timeout = 30000,\n } = options;\n\n let content: string;\n let format: 'json' | 'yaml';\n\n if (source.startsWith('http://') || source.startsWith('https://')) {\n // Fetch from URL\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const response = await fetchFn(source, { signal: controller.signal });\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n content = await response.text();\n } finally {\n clearTimeout(timeoutId);\n }\n\n // Detect format from URL or content\n if (source.endsWith('.yaml') || source.endsWith('.yml')) {\n format = 'yaml';\n } else if (source.endsWith('.json')) {\n format = 'json';\n } else {\n format = detectFormat(content);\n }\n } else {\n // Read from file\n if (!readFile) {\n throw new Error('readFile adapter required for file paths');\n }\n content = await readFile(source);\n\n // Detect format from extension or content\n if (source.endsWith('.yaml') || source.endsWith('.yml')) {\n format = 'yaml';\n } else if (source.endsWith('.json')) {\n format = 'json';\n } else {\n format = detectFormat(content);\n }\n }\n\n const doc = parseOpenApiString(content, format);\n return parseOpenApiDocument(doc, options);\n}\n"],"mappings":";;;;;;;AAsBA,SAAgB,qBACd,KACA,WAAgC,EAAE,EACrB;CACb,MAAM,UAAU,cAAc,IAAI;CAClC,MAAM,WAAqB,EAAE;CAC7B,MAAM,aAAgC,EAAE;AAGxC,MAAK,MAAM,CAAC,MAAM,aAAa,OAAO,QAAQ,IAAI,SAAS,EAAE,CAAC,EAAE;AAC9D,MAAI,CAAC,SAAU;EAGf,MAAM,aAAc,SAAsC;AAE1D,OAAK,MAAM,UAAU,cAAc;GACjC,MAAM,YAAa,SAAqC;AAKxD,OAAI,UACF,KAAI;AACF,eAAW,KACT,eACE,KACA,QACA,MACA,WACA,WACD,CACF;YACM,OAAO;AACd,aAAS,KACP,mBAAmB,OAAO,aAAa,CAAC,GAAG,KAAK,IAAI,QACrD;;;;CAOT,MAAM,UAAyC,EAAE;CACjD,MAAM,aAAa,IAAI;AACvB,KAAI,YAAY,QACd,MAAK,MAAM,CAAC,MAAM,WAAW,OAAO,QAAQ,WAAW,QAAQ,CAC7D,SAAQ,QAAQ;CAMpB,MAAM,WAA4B,IAAI,WAAW,EAAE,EAAE,KAAK,OAAO;EAC/D,KAAK,EAAE;EACP,aAAa,EAAE;EACf,WAAW,EAAE;EACd,EAAE;CAGH,MAAM,SAAwB,EAAE;AAChC,KAAI,cAAc,OAAO,IAAI,SAC3B,MAAK,MAAM,CAAC,MAAM,aAAa,OAAO,QAAQ,IAAI,SAAS,EAAE;AAC3D,MAAI,OAAO,aAAa,YAAY,CAAC,SAAU;EAE/C,MAAM,YAAa,SAAqC;AAKxD,MAAI,aAAa,UAAU,aAAa;AACtC,OAAI,UAAU,UAAU,YACtB,OAAM,IAAI,MAAM,yBAAyB;GAG3C,MAAM,UAAU,UAAU,YAAY,UAAU;AAChD,OAAI,SAAS,OACX,QAAO,KAAK;IACV;IACA,aAAa,UAAU,WAAW,UAAU;IAC5C,SAAS,QAAQ;IAClB,CAAC;;;AAMV,QAAO;EACL,UAAU;EACV;EACA,MAAM;GACJ,OAAO,IAAI,KAAK;GAChB,SAAS,IAAI,KAAK;GAClB,aAAa,IAAI,KAAK;GACvB;EACD;EACA;EACA;EACA;EACA;EACD;;;;;;;AAQH,eAAsB,aACpB,QACA,UAGI,EAAE,EACgB;CACtB,MAAM,EACJ,OAAO,UAAU,WAAW,OAC5B,UACA,UAAU,QACR;CAEJ,IAAI;CACJ,IAAI;AAEJ,KAAI,OAAO,WAAW,UAAU,IAAI,OAAO,WAAW,WAAW,EAAE;EAEjE,MAAM,aAAa,IAAI,iBAAiB;EACxC,MAAM,YAAY,iBAAiB,WAAW,OAAO,EAAE,QAAQ;AAE/D,MAAI;GACF,MAAM,WAAW,MAAM,QAAQ,QAAQ,EAAE,QAAQ,WAAW,QAAQ,CAAC;AACrE,OAAI,CAAC,SAAS,GACZ,OAAM,IAAI,MAAM,QAAQ,SAAS,OAAO,IAAI,SAAS,aAAa;AAEpE,aAAU,MAAM,SAAS,MAAM;YACvB;AACR,gBAAa,UAAU;;AAIzB,MAAI,OAAO,SAAS,QAAQ,IAAI,OAAO,SAAS,OAAO,CACrD,UAAS;WACA,OAAO,SAAS,QAAQ,CACjC,UAAS;MAET,UAAS,aAAa,QAAQ;QAE3B;AAEL,MAAI,CAAC,SACH,OAAM,IAAI,MAAM,2CAA2C;AAE7D,YAAU,MAAM,SAAS,OAAO;AAGhC,MAAI,OAAO,SAAS,QAAQ,IAAI,OAAO,SAAS,OAAO,CACrD,UAAS;WACA,OAAO,SAAS,QAAQ,CACjC,UAAS;MAET,UAAS,aAAa,QAAQ;;AAKlC,QAAO,qBADK,mBAAmB,SAAS,OAAO,EACd,QAAQ"}
@@ -1 +1 @@
1
- {"version":3,"file":"operation.js","names":["requestBody: ParsedOperation['requestBody']","responses: ParsedOperation['responses']"],"sources":["../../../src/openapi/parser/operation.ts"],"sourcesContent":["import type {\n HttpMethod,\n OpenApiDocument,\n OpenApiParameter,\n OpenApiSchema,\n ParsedOperation,\n} from '../types';\nimport type { OpenAPIV3, OpenAPIV3_1 } from 'openapi-types';\nimport { dereferenceSchema, isReference, resolveRef } from './resolvers';\nimport { parseParameters } from './parameters';\nimport { generateOperationId } from './utils';\n\n/**\n * Parse a single operation.\n */\nexport function parseOperation(\n doc: OpenApiDocument,\n method: HttpMethod,\n path: string,\n operation: OpenAPIV3.OperationObject | OpenAPIV3_1.OperationObject,\n pathParams: OpenApiParameter[] | undefined\n): ParsedOperation {\n // Merge path-level and operation-level parameters\n const allParams = [...(pathParams ?? []), ...(operation.parameters ?? [])];\n const params = parseParameters(doc, allParams as OpenApiParameter[]);\n\n // Parse request body\n let requestBody: ParsedOperation['requestBody'];\n if (operation.requestBody) {\n const body = isReference(operation.requestBody)\n ? resolveRef<OpenAPIV3.RequestBodyObject | OpenAPIV3_1.RequestBodyObject>(\n doc,\n operation.requestBody.$ref\n )\n : operation.requestBody;\n\n if (body) {\n const contentType =\n Object.keys(body.content ?? {})[0] ?? 'application/json';\n const content = body.content?.[contentType];\n if (content?.schema) {\n requestBody = {\n required: body.required ?? false,\n schema:\n dereferenceSchema(doc, content.schema as OpenApiSchema) ??\n ({} as OpenApiSchema),\n contentType,\n };\n }\n }\n }\n\n // Parse responses\n const responses: ParsedOperation['responses'] = {};\n for (const [status, response] of Object.entries(operation.responses ?? {})) {\n const resolved = isReference(response)\n ? resolveRef<OpenAPIV3.ResponseObject | OpenAPIV3_1.ResponseObject>(\n doc,\n response.$ref\n )\n : response;\n\n if (resolved) {\n const contentType = Object.keys(resolved.content ?? {})[0];\n const content = contentType ? resolved.content?.[contentType] : undefined;\n\n responses[status] = {\n description: resolved.description,\n schema: content?.schema\n ? dereferenceSchema(doc, content.schema as OpenApiSchema)\n : undefined,\n contentType,\n };\n }\n }\n\n // Check for x-contractspec extension\n const contractSpecMeta = (operation as Record<string, unknown>)?.[\n 'x-contractspec'\n ] as ParsedOperation['contractSpecMeta'];\n\n return {\n operationId: operation.operationId ?? generateOperationId(method, path),\n method,\n path,\n summary: operation.summary,\n description: operation.description,\n tags: operation.tags ?? [],\n pathParams: params.path,\n queryParams: params.query,\n headerParams: params.header,\n cookieParams: params.cookie,\n requestBody,\n responses,\n deprecated: operation.deprecated ?? false,\n security: operation.security as ParsedOperation['security'],\n contractSpecMeta,\n };\n}\n"],"mappings":";;;;;;;;AAeA,SAAgB,eACd,KACA,QACA,MACA,WACA,YACiB;CAGjB,MAAM,SAAS,gBAAgB,KADb,CAAC,GAAI,cAAc,EAAE,EAAG,GAAI,UAAU,cAAc,EAAE,CAAE,CACN;CAGpE,IAAIA;AACJ,KAAI,UAAU,aAAa;EACzB,MAAM,OAAO,YAAY,UAAU,YAAY,GAC3C,WACE,KACA,UAAU,YAAY,KACvB,GACD,UAAU;AAEd,MAAI,MAAM;GACR,MAAM,cACJ,OAAO,KAAK,KAAK,WAAW,EAAE,CAAC,CAAC,MAAM;GACxC,MAAM,UAAU,KAAK,UAAU;AAC/B,OAAI,SAAS,OACX,eAAc;IACZ,UAAU,KAAK,YAAY;IAC3B,QACE,kBAAkB,KAAK,QAAQ,OAAwB,IACtD,EAAE;IACL;IACD;;;CAMP,MAAMC,YAA0C,EAAE;AAClD,MAAK,MAAM,CAAC,QAAQ,aAAa,OAAO,QAAQ,UAAU,aAAa,EAAE,CAAC,EAAE;EAC1E,MAAM,WAAW,YAAY,SAAS,GAClC,WACE,KACA,SAAS,KACV,GACD;AAEJ,MAAI,UAAU;GACZ,MAAM,cAAc,OAAO,KAAK,SAAS,WAAW,EAAE,CAAC,CAAC;GACxD,MAAM,UAAU,cAAc,SAAS,UAAU,eAAe;AAEhE,aAAU,UAAU;IAClB,aAAa,SAAS;IACtB,QAAQ,SAAS,SACb,kBAAkB,KAAK,QAAQ,OAAwB,GACvD;IACJ;IACD;;;CAKL,MAAM,mBAAoB,YACxB;AAGF,QAAO;EACL,aAAa,UAAU,eAAe,oBAAoB,QAAQ,KAAK;EACvE;EACA;EACA,SAAS,UAAU;EACnB,aAAa,UAAU;EACvB,MAAM,UAAU,QAAQ,EAAE;EAC1B,YAAY,OAAO;EACnB,aAAa,OAAO;EACpB,cAAc,OAAO;EACrB,cAAc,OAAO;EACrB;EACA;EACA,YAAY,UAAU,cAAc;EACpC,UAAU,UAAU;EACpB;EACD"}
1
+ {"version":3,"file":"operation.js","names":[],"sources":["../../../src/openapi/parser/operation.ts"],"sourcesContent":["import type {\n HttpMethod,\n OpenApiDocument,\n OpenApiParameter,\n OpenApiSchema,\n ParsedOperation,\n} from '../types';\nimport type { OpenAPIV3, OpenAPIV3_1 } from 'openapi-types';\nimport { dereferenceSchema, isReference, resolveRef } from './resolvers';\nimport { parseParameters } from './parameters';\nimport { generateOperationId } from './utils';\n\n/**\n * Parse a single operation.\n */\nexport function parseOperation(\n doc: OpenApiDocument,\n method: HttpMethod,\n path: string,\n operation: OpenAPIV3.OperationObject | OpenAPIV3_1.OperationObject,\n pathParams: OpenApiParameter[] | undefined\n): ParsedOperation {\n // Merge path-level and operation-level parameters\n const allParams = [...(pathParams ?? []), ...(operation.parameters ?? [])];\n const params = parseParameters(doc, allParams as OpenApiParameter[]);\n\n // Parse request body\n let requestBody: ParsedOperation['requestBody'];\n if (operation.requestBody) {\n const body = isReference(operation.requestBody)\n ? resolveRef<OpenAPIV3.RequestBodyObject | OpenAPIV3_1.RequestBodyObject>(\n doc,\n operation.requestBody.$ref\n )\n : operation.requestBody;\n\n if (body) {\n const contentType =\n Object.keys(body.content ?? {})[0] ?? 'application/json';\n const content = body.content?.[contentType];\n if (content?.schema) {\n requestBody = {\n required: body.required ?? false,\n schema:\n dereferenceSchema(doc, content.schema as OpenApiSchema) ??\n ({} as OpenApiSchema),\n contentType,\n };\n }\n }\n }\n\n // Parse responses\n const responses: ParsedOperation['responses'] = {};\n for (const [status, response] of Object.entries(operation.responses ?? {})) {\n const resolved = isReference(response)\n ? resolveRef<OpenAPIV3.ResponseObject | OpenAPIV3_1.ResponseObject>(\n doc,\n response.$ref\n )\n : response;\n\n if (resolved) {\n const contentType = Object.keys(resolved.content ?? {})[0];\n const content = contentType ? resolved.content?.[contentType] : undefined;\n\n responses[status] = {\n description: resolved.description,\n schema: content?.schema\n ? dereferenceSchema(doc, content.schema as OpenApiSchema)\n : undefined,\n contentType,\n };\n }\n }\n\n // Check for x-contractspec extension\n const contractSpecMeta = (operation as Record<string, unknown>)?.[\n 'x-contractspec'\n ] as ParsedOperation['contractSpecMeta'];\n\n return {\n operationId: operation.operationId ?? generateOperationId(method, path),\n method,\n path,\n summary: operation.summary,\n description: operation.description,\n tags: operation.tags ?? [],\n pathParams: params.path,\n queryParams: params.query,\n headerParams: params.header,\n cookieParams: params.cookie,\n requestBody,\n responses,\n deprecated: operation.deprecated ?? false,\n security: operation.security as ParsedOperation['security'],\n contractSpecMeta,\n };\n}\n"],"mappings":";;;;;;;;AAeA,SAAgB,eACd,KACA,QACA,MACA,WACA,YACiB;CAGjB,MAAM,SAAS,gBAAgB,KADb,CAAC,GAAI,cAAc,EAAE,EAAG,GAAI,UAAU,cAAc,EAAE,CAAE,CACN;CAGpE,IAAI;AACJ,KAAI,UAAU,aAAa;EACzB,MAAM,OAAO,YAAY,UAAU,YAAY,GAC3C,WACE,KACA,UAAU,YAAY,KACvB,GACD,UAAU;AAEd,MAAI,MAAM;GACR,MAAM,cACJ,OAAO,KAAK,KAAK,WAAW,EAAE,CAAC,CAAC,MAAM;GACxC,MAAM,UAAU,KAAK,UAAU;AAC/B,OAAI,SAAS,OACX,eAAc;IACZ,UAAU,KAAK,YAAY;IAC3B,QACE,kBAAkB,KAAK,QAAQ,OAAwB,IACtD,EAAE;IACL;IACD;;;CAMP,MAAM,YAA0C,EAAE;AAClD,MAAK,MAAM,CAAC,QAAQ,aAAa,OAAO,QAAQ,UAAU,aAAa,EAAE,CAAC,EAAE;EAC1E,MAAM,WAAW,YAAY,SAAS,GAClC,WACE,KACA,SAAS,KACV,GACD;AAEJ,MAAI,UAAU;GACZ,MAAM,cAAc,OAAO,KAAK,SAAS,WAAW,EAAE,CAAC,CAAC;GACxD,MAAM,UAAU,cAAc,SAAS,UAAU,eAAe;AAEhE,aAAU,UAAU;IAClB,aAAa,SAAS;IACtB,QAAQ,SAAS,SACb,kBAAkB,KAAK,QAAQ,OAAwB,GACvD;IACJ;IACD;;;CAKL,MAAM,mBAAoB,YACxB;AAGF,QAAO;EACL,aAAa,UAAU,eAAe,oBAAoB,QAAQ,KAAK;EACvE;EACA;EACA,SAAS,UAAU;EACnB,aAAa,UAAU;EACvB,MAAM,UAAU,QAAQ,EAAE;EAC1B,YAAY,OAAO;EACnB,aAAa,OAAO;EACpB,cAAc,OAAO;EACrB,cAAc,OAAO;EACrB;EACA;EACA,YAAY,UAAU,cAAc;EACpC,UAAU,UAAU;EACpB;EACD"}
@@ -1 +1 @@
1
- {"version":3,"file":"parameters.js","names":["resolved: OpenAPIV3.ParameterObject | OpenAPIV3_1.ParameterObject","parsed: ParsedParameter"],"sources":["../../../src/openapi/parser/parameters.ts"],"sourcesContent":["import type {\n OpenApiDocument,\n OpenApiParameter,\n ParsedParameter,\n OpenApiSchema,\n} from '../types';\nimport type { OpenAPIV3, OpenAPIV3_1 } from 'openapi-types';\nimport { isReference, resolveRef, dereferenceSchema } from './resolvers';\n\n/**\n * Parse parameters from an operation.\n */\nexport function parseParameters(\n doc: OpenApiDocument,\n params: OpenApiParameter[] | undefined\n): {\n path: ParsedParameter[];\n query: ParsedParameter[];\n header: ParsedParameter[];\n cookie: ParsedParameter[];\n} {\n const result = {\n path: [] as ParsedParameter[],\n query: [] as ParsedParameter[],\n header: [] as ParsedParameter[],\n cookie: [] as ParsedParameter[],\n };\n\n if (!params) return result;\n\n for (const param of params) {\n let resolved: OpenAPIV3.ParameterObject | OpenAPIV3_1.ParameterObject;\n\n if (isReference(param)) {\n const ref = resolveRef<\n OpenAPIV3.ParameterObject | OpenAPIV3_1.ParameterObject\n >(doc, param.$ref);\n if (!ref) continue;\n resolved = ref;\n } else {\n resolved = param;\n }\n\n const parsed: ParsedParameter = {\n name: resolved.name,\n in: resolved.in as ParsedParameter['in'],\n required: resolved.required ?? resolved.in === 'path',\n description: resolved.description,\n schema: dereferenceSchema(\n doc,\n resolved.schema as OpenApiSchema\n ) as OpenApiSchema,\n deprecated: resolved.deprecated ?? false,\n };\n\n result[resolved.in as keyof typeof result]?.push(parsed);\n }\n\n return result;\n}\n"],"mappings":";;;;;;AAYA,SAAgB,gBACd,KACA,QAMA;CACA,MAAM,SAAS;EACb,MAAM,EAAE;EACR,OAAO,EAAE;EACT,QAAQ,EAAE;EACV,QAAQ,EAAE;EACX;AAED,KAAI,CAAC,OAAQ,QAAO;AAEpB,MAAK,MAAM,SAAS,QAAQ;EAC1B,IAAIA;AAEJ,MAAI,YAAY,MAAM,EAAE;GACtB,MAAM,MAAM,WAEV,KAAK,MAAM,KAAK;AAClB,OAAI,CAAC,IAAK;AACV,cAAW;QAEX,YAAW;EAGb,MAAMC,SAA0B;GAC9B,MAAM,SAAS;GACf,IAAI,SAAS;GACb,UAAU,SAAS,YAAY,SAAS,OAAO;GAC/C,aAAa,SAAS;GACtB,QAAQ,kBACN,KACA,SAAS,OACV;GACD,YAAY,SAAS,cAAc;GACpC;AAED,SAAO,SAAS,KAA4B,KAAK,OAAO;;AAG1D,QAAO"}
1
+ {"version":3,"file":"parameters.js","names":[],"sources":["../../../src/openapi/parser/parameters.ts"],"sourcesContent":["import type {\n OpenApiDocument,\n OpenApiParameter,\n ParsedParameter,\n OpenApiSchema,\n} from '../types';\nimport type { OpenAPIV3, OpenAPIV3_1 } from 'openapi-types';\nimport { isReference, resolveRef, dereferenceSchema } from './resolvers';\n\n/**\n * Parse parameters from an operation.\n */\nexport function parseParameters(\n doc: OpenApiDocument,\n params: OpenApiParameter[] | undefined\n): {\n path: ParsedParameter[];\n query: ParsedParameter[];\n header: ParsedParameter[];\n cookie: ParsedParameter[];\n} {\n const result = {\n path: [] as ParsedParameter[],\n query: [] as ParsedParameter[],\n header: [] as ParsedParameter[],\n cookie: [] as ParsedParameter[],\n };\n\n if (!params) return result;\n\n for (const param of params) {\n let resolved: OpenAPIV3.ParameterObject | OpenAPIV3_1.ParameterObject;\n\n if (isReference(param)) {\n const ref = resolveRef<\n OpenAPIV3.ParameterObject | OpenAPIV3_1.ParameterObject\n >(doc, param.$ref);\n if (!ref) continue;\n resolved = ref;\n } else {\n resolved = param;\n }\n\n const parsed: ParsedParameter = {\n name: resolved.name,\n in: resolved.in as ParsedParameter['in'],\n required: resolved.required ?? resolved.in === 'path',\n description: resolved.description,\n schema: dereferenceSchema(\n doc,\n resolved.schema as OpenApiSchema\n ) as OpenApiSchema,\n deprecated: resolved.deprecated ?? false,\n };\n\n result[resolved.in as keyof typeof result]?.push(parsed);\n }\n\n return result;\n}\n"],"mappings":";;;;;;AAYA,SAAgB,gBACd,KACA,QAMA;CACA,MAAM,SAAS;EACb,MAAM,EAAE;EACR,OAAO,EAAE;EACT,QAAQ,EAAE;EACV,QAAQ,EAAE;EACX;AAED,KAAI,CAAC,OAAQ,QAAO;AAEpB,MAAK,MAAM,SAAS,QAAQ;EAC1B,IAAI;AAEJ,MAAI,YAAY,MAAM,EAAE;GACtB,MAAM,MAAM,WAEV,KAAK,MAAM,KAAK;AAClB,OAAI,CAAC,IAAK;AACV,cAAW;QAEX,YAAW;EAGb,MAAM,SAA0B;GAC9B,MAAM,SAAS;GACf,IAAI,SAAS;GACb,UAAU,SAAS,YAAY,SAAS,OAAO;GAC/C,aAAa,SAAS;GACtB,QAAQ,kBACN,KACA,SAAS,OACV;GACD,YAAY,SAAS,cAAc;GACpC;AAED,SAAO,SAAS,KAA4B,KAAK,OAAO;;AAG1D,QAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"resolvers.js","names":["current: unknown","newProps: Record<string, OpenApiSchema>"],"sources":["../../../src/openapi/parser/resolvers.ts"],"sourcesContent":["import type { OpenApiDocument, OpenApiSchema } from '../types';\nimport type { OpenAPIV3, OpenAPIV3_1 } from 'openapi-types';\n\n/**\n * Check if a value is a reference object.\n */\nexport function isReference(\n obj: unknown\n): obj is OpenAPIV3.ReferenceObject | OpenAPIV3_1.ReferenceObject {\n return typeof obj === 'object' && obj !== null && '$ref' in obj;\n}\n\n/**\n * Resolve a $ref reference in the document.\n */\nexport function resolveRef<T>(\n doc: OpenApiDocument,\n ref: string\n): T | undefined {\n // Only support local refs for now\n if (!ref.startsWith('#/')) {\n return undefined;\n }\n\n const path = ref.slice(2).split('/');\n let current: unknown = doc;\n\n for (const part of path) {\n if (current === null || current === undefined) return undefined;\n if (typeof current !== 'object') return undefined;\n current = (current as Record<string, unknown>)[part];\n }\n\n return current as T;\n}\n\n/**\n * Resolve a schema, following $ref if needed.\n */\nexport function resolveSchema(\n doc: OpenApiDocument,\n schema: OpenApiSchema | undefined\n): OpenApiSchema | undefined {\n if (!schema) return undefined;\n if (isReference(schema)) {\n return resolveRef<OpenApiSchema>(doc, schema.$ref) ?? schema;\n }\n return schema;\n}\n\n/**\n * Recursively dereference a schema.\n * Replaces all $ref with their resolved values.\n * Preserves `_originalRef` to track where the schema came from.\n */\nexport function dereferenceSchema(\n doc: OpenApiDocument,\n schema: OpenApiSchema | undefined,\n seen = new Set<string>()\n): OpenApiSchema | undefined {\n if (!schema) return undefined;\n\n // Handle references\n if (isReference(schema)) {\n // Avoid infinite recursion for cycles\n if (seen.has(schema.$ref)) {\n return schema; // Keep reference for cycles\n }\n\n // Create new seen set for this branch\n const newSeen = new Set(seen);\n newSeen.add(schema.$ref);\n\n const resolved = resolveRef<OpenApiSchema>(doc, schema.$ref);\n if (!resolved) return schema;\n\n // Recursively dereference the resolved schema\n const dereferenced = dereferenceSchema(doc, resolved, newSeen);\n if (!dereferenced) return schema;\n\n // IMPORTANT: Preserve the original $ref so we can generate correct imports\n // Extract the type name from the $ref (e.g., '#/components/schemas/PaginationMeta' -> 'PaginationMeta')\n const refParts = schema.$ref.split('/');\n const typeName = refParts[refParts.length - 1];\n return {\n ...dereferenced,\n _originalRef: schema.$ref,\n _originalTypeName: typeName,\n } as unknown as OpenApiSchema;\n }\n\n // Deep clone to avoid mutating original doc (if we were modifying in place, but here we return new objects mostly)\n // For simplicity, we just walk properties\n const schemaObj = { ...schema } as Record<string, unknown>;\n\n // Handle nested schemas in properties\n if (schemaObj.properties) {\n const props = schemaObj.properties as Record<string, OpenApiSchema>;\n const newProps: Record<string, OpenApiSchema> = {};\n for (const [key, prop] of Object.entries(props)) {\n newProps[key] = dereferenceSchema(doc, prop, seen) ?? prop;\n }\n schemaObj.properties = newProps;\n }\n\n // Handle nested schema in items (array)\n if (schemaObj.items) {\n schemaObj.items = dereferenceSchema(\n doc,\n schemaObj.items as OpenApiSchema,\n seen\n );\n }\n\n // Handle allOf, anyOf, oneOf\n const combinators = ['allOf', 'anyOf', 'oneOf'];\n for (const comb of combinators) {\n if (Array.isArray(schemaObj[comb])) {\n schemaObj[comb] = (schemaObj[comb] as OpenApiSchema[]).map(\n (s) => dereferenceSchema(doc, s, seen) ?? s\n );\n }\n }\n\n return schemaObj as OpenApiSchema;\n}\n"],"mappings":";;;;AAMA,SAAgB,YACd,KACgE;AAChE,QAAO,OAAO,QAAQ,YAAY,QAAQ,QAAQ,UAAU;;;;;AAM9D,SAAgB,WACd,KACA,KACe;AAEf,KAAI,CAAC,IAAI,WAAW,KAAK,CACvB;CAGF,MAAM,OAAO,IAAI,MAAM,EAAE,CAAC,MAAM,IAAI;CACpC,IAAIA,UAAmB;AAEvB,MAAK,MAAM,QAAQ,MAAM;AACvB,MAAI,YAAY,QAAQ,YAAY,OAAW,QAAO;AACtD,MAAI,OAAO,YAAY,SAAU,QAAO;AACxC,YAAW,QAAoC;;AAGjD,QAAO;;;;;;;AAsBT,SAAgB,kBACd,KACA,QACA,uBAAO,IAAI,KAAa,EACG;AAC3B,KAAI,CAAC,OAAQ,QAAO;AAGpB,KAAI,YAAY,OAAO,EAAE;AAEvB,MAAI,KAAK,IAAI,OAAO,KAAK,CACvB,QAAO;EAIT,MAAM,UAAU,IAAI,IAAI,KAAK;AAC7B,UAAQ,IAAI,OAAO,KAAK;EAExB,MAAM,WAAW,WAA0B,KAAK,OAAO,KAAK;AAC5D,MAAI,CAAC,SAAU,QAAO;EAGtB,MAAM,eAAe,kBAAkB,KAAK,UAAU,QAAQ;AAC9D,MAAI,CAAC,aAAc,QAAO;EAI1B,MAAM,WAAW,OAAO,KAAK,MAAM,IAAI;EACvC,MAAM,WAAW,SAAS,SAAS,SAAS;AAC5C,SAAO;GACL,GAAG;GACH,cAAc,OAAO;GACrB,mBAAmB;GACpB;;CAKH,MAAM,YAAY,EAAE,GAAG,QAAQ;AAG/B,KAAI,UAAU,YAAY;EACxB,MAAM,QAAQ,UAAU;EACxB,MAAMC,WAA0C,EAAE;AAClD,OAAK,MAAM,CAAC,KAAK,SAAS,OAAO,QAAQ,MAAM,CAC7C,UAAS,OAAO,kBAAkB,KAAK,MAAM,KAAK,IAAI;AAExD,YAAU,aAAa;;AAIzB,KAAI,UAAU,MACZ,WAAU,QAAQ,kBAChB,KACA,UAAU,OACV,KACD;AAKH,MAAK,MAAM,QADS;EAAC;EAAS;EAAS;EAAQ,CAE7C,KAAI,MAAM,QAAQ,UAAU,MAAM,CAChC,WAAU,QAAS,UAAU,MAA0B,KACpD,MAAM,kBAAkB,KAAK,GAAG,KAAK,IAAI,EAC3C;AAIL,QAAO"}
1
+ {"version":3,"file":"resolvers.js","names":[],"sources":["../../../src/openapi/parser/resolvers.ts"],"sourcesContent":["import type { OpenApiDocument, OpenApiSchema } from '../types';\nimport type { OpenAPIV3, OpenAPIV3_1 } from 'openapi-types';\n\n/**\n * Check if a value is a reference object.\n */\nexport function isReference(\n obj: unknown\n): obj is OpenAPIV3.ReferenceObject | OpenAPIV3_1.ReferenceObject {\n return typeof obj === 'object' && obj !== null && '$ref' in obj;\n}\n\n/**\n * Resolve a $ref reference in the document.\n */\nexport function resolveRef<T>(\n doc: OpenApiDocument,\n ref: string\n): T | undefined {\n // Only support local refs for now\n if (!ref.startsWith('#/')) {\n return undefined;\n }\n\n const path = ref.slice(2).split('/');\n let current: unknown = doc;\n\n for (const part of path) {\n if (current === null || current === undefined) return undefined;\n if (typeof current !== 'object') return undefined;\n current = (current as Record<string, unknown>)[part];\n }\n\n return current as T;\n}\n\n/**\n * Resolve a schema, following $ref if needed.\n */\nexport function resolveSchema(\n doc: OpenApiDocument,\n schema: OpenApiSchema | undefined\n): OpenApiSchema | undefined {\n if (!schema) return undefined;\n if (isReference(schema)) {\n return resolveRef<OpenApiSchema>(doc, schema.$ref) ?? schema;\n }\n return schema;\n}\n\n/**\n * Recursively dereference a schema.\n * Replaces all $ref with their resolved values.\n * Preserves `_originalRef` to track where the schema came from.\n */\nexport function dereferenceSchema(\n doc: OpenApiDocument,\n schema: OpenApiSchema | undefined,\n seen = new Set<string>()\n): OpenApiSchema | undefined {\n if (!schema) return undefined;\n\n // Handle references\n if (isReference(schema)) {\n // Avoid infinite recursion for cycles\n if (seen.has(schema.$ref)) {\n return schema; // Keep reference for cycles\n }\n\n // Create new seen set for this branch\n const newSeen = new Set(seen);\n newSeen.add(schema.$ref);\n\n const resolved = resolveRef<OpenApiSchema>(doc, schema.$ref);\n if (!resolved) return schema;\n\n // Recursively dereference the resolved schema\n const dereferenced = dereferenceSchema(doc, resolved, newSeen);\n if (!dereferenced) return schema;\n\n // IMPORTANT: Preserve the original $ref so we can generate correct imports\n // Extract the type name from the $ref (e.g., '#/components/schemas/PaginationMeta' -> 'PaginationMeta')\n const refParts = schema.$ref.split('/');\n const typeName = refParts[refParts.length - 1];\n return {\n ...dereferenced,\n _originalRef: schema.$ref,\n _originalTypeName: typeName,\n } as unknown as OpenApiSchema;\n }\n\n // Deep clone to avoid mutating original doc (if we were modifying in place, but here we return new objects mostly)\n // For simplicity, we just walk properties\n const schemaObj = { ...schema } as Record<string, unknown>;\n\n // Handle nested schemas in properties\n if (schemaObj.properties) {\n const props = schemaObj.properties as Record<string, OpenApiSchema>;\n const newProps: Record<string, OpenApiSchema> = {};\n for (const [key, prop] of Object.entries(props)) {\n newProps[key] = dereferenceSchema(doc, prop, seen) ?? prop;\n }\n schemaObj.properties = newProps;\n }\n\n // Handle nested schema in items (array)\n if (schemaObj.items) {\n schemaObj.items = dereferenceSchema(\n doc,\n schemaObj.items as OpenApiSchema,\n seen\n );\n }\n\n // Handle allOf, anyOf, oneOf\n const combinators = ['allOf', 'anyOf', 'oneOf'];\n for (const comb of combinators) {\n if (Array.isArray(schemaObj[comb])) {\n schemaObj[comb] = (schemaObj[comb] as OpenApiSchema[]).map(\n (s) => dereferenceSchema(doc, s, seen) ?? s\n );\n }\n }\n\n return schemaObj as OpenApiSchema;\n}\n"],"mappings":";;;;AAMA,SAAgB,YACd,KACgE;AAChE,QAAO,OAAO,QAAQ,YAAY,QAAQ,QAAQ,UAAU;;;;;AAM9D,SAAgB,WACd,KACA,KACe;AAEf,KAAI,CAAC,IAAI,WAAW,KAAK,CACvB;CAGF,MAAM,OAAO,IAAI,MAAM,EAAE,CAAC,MAAM,IAAI;CACpC,IAAI,UAAmB;AAEvB,MAAK,MAAM,QAAQ,MAAM;AACvB,MAAI,YAAY,QAAQ,YAAY,OAAW,QAAO;AACtD,MAAI,OAAO,YAAY,SAAU,QAAO;AACxC,YAAW,QAAoC;;AAGjD,QAAO;;;;;;;AAsBT,SAAgB,kBACd,KACA,QACA,uBAAO,IAAI,KAAa,EACG;AAC3B,KAAI,CAAC,OAAQ,QAAO;AAGpB,KAAI,YAAY,OAAO,EAAE;AAEvB,MAAI,KAAK,IAAI,OAAO,KAAK,CACvB,QAAO;EAIT,MAAM,UAAU,IAAI,IAAI,KAAK;AAC7B,UAAQ,IAAI,OAAO,KAAK;EAExB,MAAM,WAAW,WAA0B,KAAK,OAAO,KAAK;AAC5D,MAAI,CAAC,SAAU,QAAO;EAGtB,MAAM,eAAe,kBAAkB,KAAK,UAAU,QAAQ;AAC9D,MAAI,CAAC,aAAc,QAAO;EAI1B,MAAM,WAAW,OAAO,KAAK,MAAM,IAAI;EACvC,MAAM,WAAW,SAAS,SAAS,SAAS;AAC5C,SAAO;GACL,GAAG;GACH,cAAc,OAAO;GACrB,mBAAmB;GACpB;;CAKH,MAAM,YAAY,EAAE,GAAG,QAAQ;AAG/B,KAAI,UAAU,YAAY;EACxB,MAAM,QAAQ,UAAU;EACxB,MAAM,WAA0C,EAAE;AAClD,OAAK,MAAM,CAAC,KAAK,SAAS,OAAO,QAAQ,MAAM,CAC7C,UAAS,OAAO,kBAAkB,KAAK,MAAM,KAAK,IAAI;AAExD,YAAU,aAAa;;AAIzB,KAAI,UAAU,MACZ,WAAU,QAAQ,kBAChB,KACA,UAAU,OACV,KACD;AAKH,MAAK,MAAM,QADS;EAAC;EAAS;EAAS;EAAQ,CAE7C,KAAI,MAAM,QAAQ,UAAU,MAAM,CAChC,WAAU,QAAS,UAAU,MAA0B,KACpD,MAAM,kBAAkB,KAAK,GAAG,KAAK,IAAI,EAC3C;AAIL,QAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","names":["HTTP_METHODS: HttpMethod[]","parseYaml"],"sources":["../../../src/openapi/parser/utils.ts"],"sourcesContent":["import { parse as parseYaml } from 'yaml';\nimport type { OpenApiDocument, HttpMethod, OpenApiVersion } from '../types';\n\nexport const HTTP_METHODS: HttpMethod[] = [\n 'get',\n 'post',\n 'put',\n 'delete',\n 'patch',\n 'head',\n 'options',\n 'trace',\n];\n\n/**\n * Parse an OpenAPI document from a string (JSON or YAML).\n */\nexport function parseOpenApiString(\n content: string,\n format: 'json' | 'yaml' = 'json'\n): OpenApiDocument {\n if (format === 'yaml') {\n return parseYaml(content) as OpenApiDocument;\n }\n return JSON.parse(content) as OpenApiDocument;\n}\n\n/**\n * Detect the format of content (JSON or YAML).\n */\nexport function detectFormat(content: string): 'json' | 'yaml' {\n const trimmed = content.trim();\n if (trimmed.startsWith('{') || trimmed.startsWith('[')) {\n return 'json';\n }\n return 'yaml';\n}\n\n/**\n * Detect OpenAPI version from document.\n */\nexport function detectVersion(doc: OpenApiDocument): OpenApiVersion {\n const version = doc.openapi;\n if (version.startsWith('3.1')) {\n return '3.1';\n }\n return '3.0';\n}\n\n/**\n * Generate an operationId if not present.\n */\nexport function generateOperationId(method: HttpMethod, path: string): string {\n // Convert path to camelCase operationId\n const pathParts = path\n .split('/')\n .filter(Boolean)\n .map((part) => {\n // Remove path parameters\n if (part.startsWith('{') && part.endsWith('}')) {\n return (\n 'By' + part.slice(1, -1).charAt(0).toUpperCase() + part.slice(2, -1)\n );\n }\n return part.charAt(0).toUpperCase() + part.slice(1);\n });\n\n return method + pathParts.join('');\n}\n"],"mappings":";;;AAGA,MAAaA,eAA6B;CACxC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;;;;AAKD,SAAgB,mBACd,SACA,SAA0B,QACT;AACjB,KAAI,WAAW,OACb,QAAOC,MAAU,QAAQ;AAE3B,QAAO,KAAK,MAAM,QAAQ;;;;;AAM5B,SAAgB,aAAa,SAAkC;CAC7D,MAAM,UAAU,QAAQ,MAAM;AAC9B,KAAI,QAAQ,WAAW,IAAI,IAAI,QAAQ,WAAW,IAAI,CACpD,QAAO;AAET,QAAO;;;;;AAMT,SAAgB,cAAc,KAAsC;AAElE,KADgB,IAAI,QACR,WAAW,MAAM,CAC3B,QAAO;AAET,QAAO;;;;;AAMT,SAAgB,oBAAoB,QAAoB,MAAsB;AAe5E,QAAO,SAbW,KACf,MAAM,IAAI,CACV,OAAO,QAAQ,CACf,KAAK,SAAS;AAEb,MAAI,KAAK,WAAW,IAAI,IAAI,KAAK,SAAS,IAAI,CAC5C,QACE,OAAO,KAAK,MAAM,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC,aAAa,GAAG,KAAK,MAAM,GAAG,GAAG;AAGxE,SAAO,KAAK,OAAO,EAAE,CAAC,aAAa,GAAG,KAAK,MAAM,EAAE;GACnD,CAEsB,KAAK,GAAG"}
1
+ {"version":3,"file":"utils.js","names":["parseYaml"],"sources":["../../../src/openapi/parser/utils.ts"],"sourcesContent":["import { parse as parseYaml } from 'yaml';\nimport type { OpenApiDocument, HttpMethod, OpenApiVersion } from '../types';\n\nexport const HTTP_METHODS: HttpMethod[] = [\n 'get',\n 'post',\n 'put',\n 'delete',\n 'patch',\n 'head',\n 'options',\n 'trace',\n];\n\n/**\n * Parse an OpenAPI document from a string (JSON or YAML).\n */\nexport function parseOpenApiString(\n content: string,\n format: 'json' | 'yaml' = 'json'\n): OpenApiDocument {\n if (format === 'yaml') {\n return parseYaml(content) as OpenApiDocument;\n }\n return JSON.parse(content) as OpenApiDocument;\n}\n\n/**\n * Detect the format of content (JSON or YAML).\n */\nexport function detectFormat(content: string): 'json' | 'yaml' {\n const trimmed = content.trim();\n if (trimmed.startsWith('{') || trimmed.startsWith('[')) {\n return 'json';\n }\n return 'yaml';\n}\n\n/**\n * Detect OpenAPI version from document.\n */\nexport function detectVersion(doc: OpenApiDocument): OpenApiVersion {\n const version = doc.openapi;\n if (version.startsWith('3.1')) {\n return '3.1';\n }\n return '3.0';\n}\n\n/**\n * Generate an operationId if not present.\n */\nexport function generateOperationId(method: HttpMethod, path: string): string {\n // Convert path to camelCase operationId\n const pathParts = path\n .split('/')\n .filter(Boolean)\n .map((part) => {\n // Remove path parameters\n if (part.startsWith('{') && part.endsWith('}')) {\n return (\n 'By' + part.slice(1, -1).charAt(0).toUpperCase() + part.slice(2, -1)\n );\n }\n return part.charAt(0).toUpperCase() + part.slice(1);\n });\n\n return method + pathParts.join('');\n}\n"],"mappings":";;;AAGA,MAAa,eAA6B;CACxC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;;;;AAKD,SAAgB,mBACd,SACA,SAA0B,QACT;AACjB,KAAI,WAAW,OACb,QAAOA,MAAU,QAAQ;AAE3B,QAAO,KAAK,MAAM,QAAQ;;;;;AAM5B,SAAgB,aAAa,SAAkC;CAC7D,MAAM,UAAU,QAAQ,MAAM;AAC9B,KAAI,QAAQ,WAAW,IAAI,IAAI,QAAQ,WAAW,IAAI,CACpD,QAAO;AAET,QAAO;;;;;AAMT,SAAgB,cAAc,KAAsC;AAElE,KADgB,IAAI,QACR,WAAW,MAAM,CAC3B,QAAO;AAET,QAAO;;;;;AAMT,SAAgB,oBAAoB,QAAoB,MAAsB;AAe5E,QAAO,SAbW,KACf,MAAM,IAAI,CACV,OAAO,QAAQ,CACf,KAAK,SAAS;AAEb,MAAI,KAAK,WAAW,IAAI,IAAI,KAAK,SAAS,IAAI,CAC5C,QACE,OAAO,KAAK,MAAM,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC,aAAa,GAAG,KAAK,MAAM,GAAG,GAAG;AAGxE,SAAO,KAAK,OAAO,EAAE,CAAC,aAAa,GAAG,KAAK,MAAM,EAAE;GACnD,CAEsB,KAAK,GAAG"}
@@ -1,5 +1,5 @@
1
1
  import { OpenApiSchema } from "./types.js";
2
- import { ContractsrcConfig, SchemaFormat } from "@contractspec/lib.contracts";
2
+ import { ResolvedContractsrcConfig, SchemaFormat } from "@contractspec/lib.contracts";
3
3
 
4
4
  //#region src/openapi/schema-converter.d.ts
5
5
 
@@ -61,11 +61,11 @@ declare function getScalarType(schema: OpenApiSchema): string | undefined;
61
61
  /**
62
62
  * Generate code for a schema model using the specified format.
63
63
  */
64
- declare function generateSchemaModelCode(schema: OpenApiSchema, modelName: string, schemaFormat?: SchemaFormat, config?: ContractsrcConfig): GeneratedModel;
64
+ declare function generateSchemaModelCode(schema: OpenApiSchema, modelName: string, schemaFormat?: SchemaFormat, config?: ResolvedContractsrcConfig): GeneratedModel;
65
65
  /**
66
66
  * Generate import statements for a SchemaModel.
67
67
  */
68
- declare function generateImports(fields: SchemaField[], options: ContractsrcConfig, sameDirectory?: boolean): string;
68
+ declare function generateImports(fields: SchemaField[], options: ResolvedContractsrcConfig, sameDirectory?: boolean): string;
69
69
  //#endregion
70
70
  export { GeneratedModel, SchemaField, TypescriptType, generateImports, generateSchemaModelCode, getScalarType, jsonSchemaToType };
71
71
  //# sourceMappingURL=schema-converter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema-converter.d.ts","names":[],"sources":["../../src/openapi/schema-converter.ts"],"sourcesContent":[],"mappings":";;;;;AAkEA;AA+BA;AAiHA;AA2BgB,UA7MC,cAAA,CA6MsB;EAC7B;EAEM,IAAA,EAAA,MAAA;EACL;EACR,QAAA,EAAA,OAAA;EAAc;EAkBD,KAAA,EAAA,OAAA;;;;;;;;;;;UAlNC,WAAA;;;;QAIT;;;;;;gBAMQ;;;;;UAMC,cAAA;;;;;;UAMP;;;;;;;;;iBAyBM,gBAAA,SACN,+BAEP;;;;iBA8Ga,aAAA,SAAsB;;;;iBA2BtB,uBAAA,SACN,iDAEM,uBACL,oBACR;;;;iBAkBa,eAAA,SACN,wBACC"}
1
+ {"version":3,"file":"schema-converter.d.ts","names":[],"sources":["../../src/openapi/schema-converter.ts"],"sourcesContent":[],"mappings":";;;;;AAkEA;AA+BA;AAiHA;AA2BgB,UA7MC,cAAA,CA6MsB;EAC7B;EAEM,IAAA,EAAA,MAAA;EACL;EACR,QAAA,EAAA,OAAA;EAAc;EAkBD,KAAA,EAAA,OAAA;;;;;;;;;;;UAlNC,WAAA;;;;QAIT;;;;;;gBAMQ;;;;;UAMC,cAAA;;;;;;UAMP;;;;;;;;;iBAyBM,gBAAA,SACN,+BAEP;;;;iBA8Ga,aAAA,SAAsB;;;;iBA2BtB,uBAAA,SACN,iDAEM,uBACL,4BACR;;;;iBAkBa,eAAA,SACN,wBACC"}
@@ -1 +1 @@
1
- {"version":3,"file":"schema-converter.js","names":["JSON_SCHEMA_TO_SCALAR: Record<string, string>"],"sources":["../../src/openapi/schema-converter.ts"],"sourcesContent":["/**\n * JSON Schema to SchemaModel conversion utilities.\n * Converts OpenAPI JSON Schema to ContractSpec SchemaModel definitions.\n */\n\nimport { createSchemaGenerator } from './schema-generators';\nimport type {\n SchemaFormat,\n ContractsrcConfig,\n} from '@contractspec/lib.contracts';\nimport type { OpenApiSchema } from './types';\nimport { toPascalCase } from '../common/utils';\n\n/**\n * Map JSON Schema types to ContractSpec ScalarTypeEnum values.\n */\nconst JSON_SCHEMA_TO_SCALAR: Record<string, string> = {\n string: 'ScalarTypeEnum.String_unsecure',\n integer: 'ScalarTypeEnum.Int_unsecure',\n number: 'ScalarTypeEnum.Float_unsecure',\n boolean: 'ScalarTypeEnum.Boolean',\n // Special formats\n 'string:date': 'ScalarTypeEnum.Date',\n 'string:date-time': 'ScalarTypeEnum.DateTime',\n 'string:email': 'ScalarTypeEnum.EmailAddress',\n 'string:uri': 'ScalarTypeEnum.URL',\n 'string:uuid': 'ScalarTypeEnum.ID',\n};\n\n/**\n * TypeScript type representation for code generation.\n */\nexport interface TypescriptType {\n /** The type expression (e.g., \"string\", \"number\", \"MyModel\") */\n type: string;\n /** Whether the type is optional */\n optional: boolean;\n /** Whether the type is an array */\n array: boolean;\n /** Whether this is a primitive type */\n primitive: boolean;\n /** Description for documentation */\n description?: string;\n /** Whether this type is a reference to another schema (needs import) vs inline */\n isReference?: boolean;\n}\n\n/**\n * SchemaModel field representation for code generation.\n */\nexport interface SchemaField {\n /** Field name */\n name: string;\n /** Field type */\n type: TypescriptType;\n /** Scalar type enum value (for FieldType) */\n scalarType?: string;\n /** Enum values if this is an enum type */\n enumValues?: string[];\n /** Nested model if this is an object type */\n nestedModel?: GeneratedModel;\n}\n\n/**\n * Generated model representation.\n */\nexport interface GeneratedModel {\n /** Model name (PascalCase) */\n name: string;\n /** Model description */\n description?: string;\n /** Fields */\n fields: SchemaField[];\n /** Generated TypeScript code */\n code: string;\n /** Required imports */\n imports?: string[];\n}\n\n/**\n * Check if a schema is a reference object.\n */\nfunction isReference(schema: OpenApiSchema): schema is { $ref: string } {\n return typeof schema === 'object' && schema !== null && '$ref' in schema;\n}\n\n/**\n * Extract type name from a $ref.\n */\nfunction typeNameFromRef(ref: string): string {\n const parts = ref.split('/');\n return parts[parts.length - 1] ?? 'Unknown';\n}\n\n/**\n * Convert a JSON Schema to a TypeScript type representation.\n */\nexport function jsonSchemaToType(\n schema: OpenApiSchema,\n name?: string\n): TypescriptType {\n if (isReference(schema)) {\n return {\n type: toPascalCase(typeNameFromRef(schema.$ref)),\n optional: false,\n array: false,\n primitive: false,\n isReference: true,\n };\n }\n\n const schemaObj = schema as Record<string, unknown>;\n const type = schemaObj['type'] as string | undefined;\n const format = schemaObj['format'] as string | undefined;\n const nullable = schemaObj['nullable'] as boolean | undefined;\n\n // Check if this schema was dereferenced from a $ref - use the original type name\n const originalTypeName = schemaObj['_originalTypeName'] as string | undefined;\n if (originalTypeName) {\n return {\n type: toPascalCase(originalTypeName),\n optional: nullable ?? false,\n array: false,\n primitive: false,\n isReference: true,\n };\n }\n\n // Handle arrays\n if (type === 'array') {\n const items = schemaObj['items'] as OpenApiSchema | undefined;\n if (items) {\n const itemType = jsonSchemaToType(items, name);\n return {\n ...itemType,\n array: true,\n optional: nullable ?? false,\n };\n }\n return {\n type: 'unknown',\n optional: nullable ?? false,\n array: true,\n primitive: false,\n isReference: true,\n };\n }\n\n // Handle objects\n if (type === 'object' || schemaObj['properties']) {\n return {\n type: name ? toPascalCase(name) : 'Record<string, unknown>',\n optional: nullable ?? false,\n array: false,\n primitive: false,\n isReference: true,\n };\n }\n\n // Handle enums\n if (schemaObj['enum']) {\n return {\n type: name ? toPascalCase(name) : 'string',\n optional: nullable ?? false,\n array: false,\n primitive: false,\n isReference: true,\n };\n }\n\n // Handle primitives\n const scalarKey = format ? `${type}:${format}` : type;\n if (scalarKey === 'string') {\n return {\n type: 'string',\n optional: nullable ?? false,\n array: false,\n primitive: true,\n };\n }\n if (scalarKey === 'integer' || type === 'number') {\n return {\n type: 'number',\n optional: nullable ?? false,\n array: false,\n primitive: true,\n };\n }\n if (scalarKey === 'boolean') {\n return {\n type: 'boolean',\n optional: nullable ?? false,\n array: false,\n primitive: true,\n };\n }\n\n // Default to unknown\n return {\n type: 'unknown',\n optional: nullable ?? false,\n array: false,\n primitive: false,\n isReference: true,\n };\n}\n\n/**\n * Get the ScalarTypeEnum value for a JSON Schema type.\n */\nexport function getScalarType(schema: OpenApiSchema): string | undefined {\n if (isReference(schema)) {\n return undefined;\n }\n\n const schemaObj = schema as Record<string, unknown>;\n const type = schemaObj['type'] as string | undefined;\n const format = schemaObj['format'] as string | undefined;\n\n if (!type) return undefined;\n\n // For arrays, get the scalar type of the items\n if (type === 'array') {\n const items = schemaObj['items'] as OpenApiSchema | undefined;\n if (items) {\n return getScalarType(items);\n }\n return undefined;\n }\n\n const key = format ? `${type}:${format}` : type;\n return JSON_SCHEMA_TO_SCALAR[key] ?? JSON_SCHEMA_TO_SCALAR[type] ?? undefined;\n}\n\n/**\n * Generate code for a schema model using the specified format.\n */\nexport function generateSchemaModelCode(\n schema: OpenApiSchema,\n modelName: string,\n schemaFormat: SchemaFormat = 'contractspec',\n config?: ContractsrcConfig\n): GeneratedModel {\n const generator = createSchemaGenerator(schemaFormat, config);\n const result = generator.generateModel(schema, modelName, {\n description: (schema as Record<string, unknown>)['description'] as string,\n });\n\n return {\n name: result.name,\n description: (schema as Record<string, unknown>)['description'] as string,\n fields: [], // fields are processed internally by generators now\n code: result.code,\n imports: result.imports,\n };\n}\n\n/**\n * Generate import statements for a SchemaModel.\n */\nexport function generateImports(\n fields: SchemaField[],\n options: ContractsrcConfig,\n sameDirectory = true\n): string {\n const imports = new Set<string>();\n const modelsDir = sameDirectory ? '.' : `../${options.conventions.models}`;\n\n imports.add(\n \"import { defineSchemaModel, ScalarTypeEnum, EnumType } from '@contractspec/lib.schema';\"\n );\n\n for (const field of fields) {\n // Only import fields that are actual references to other schemas (not inline types)\n if (\n field.type.isReference &&\n !field.type.primitive &&\n !field.enumValues &&\n !field.scalarType &&\n !field.nestedModel\n ) {\n // This is a reference to another schema model\n const modelName = field.type.type;\n const kebabName = modelName\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n .toLowerCase();\n imports.add(`import { ${modelName} } from '${modelsDir}/${kebabName}';`);\n }\n }\n\n return Array.from(imports).join('\\n');\n}\n"],"mappings":";;;;;;;;;;;AAgBA,MAAMA,wBAAgD;CACpD,QAAQ;CACR,SAAS;CACT,QAAQ;CACR,SAAS;CAET,eAAe;CACf,oBAAoB;CACpB,gBAAgB;CAChB,cAAc;CACd,eAAe;CAChB;;;;AAuDD,SAAS,YAAY,QAAmD;AACtE,QAAO,OAAO,WAAW,YAAY,WAAW,QAAQ,UAAU;;;;;AAMpE,SAAS,gBAAgB,KAAqB;CAC5C,MAAM,QAAQ,IAAI,MAAM,IAAI;AAC5B,QAAO,MAAM,MAAM,SAAS,MAAM;;;;;AAMpC,SAAgB,iBACd,QACA,MACgB;AAChB,KAAI,YAAY,OAAO,CACrB,QAAO;EACL,MAAM,aAAa,gBAAgB,OAAO,KAAK,CAAC;EAChD,UAAU;EACV,OAAO;EACP,WAAW;EACX,aAAa;EACd;CAGH,MAAM,YAAY;CAClB,MAAM,OAAO,UAAU;CACvB,MAAM,SAAS,UAAU;CACzB,MAAM,WAAW,UAAU;CAG3B,MAAM,mBAAmB,UAAU;AACnC,KAAI,iBACF,QAAO;EACL,MAAM,aAAa,iBAAiB;EACpC,UAAU,YAAY;EACtB,OAAO;EACP,WAAW;EACX,aAAa;EACd;AAIH,KAAI,SAAS,SAAS;EACpB,MAAM,QAAQ,UAAU;AACxB,MAAI,MAEF,QAAO;GACL,GAFe,iBAAiB,OAAO,KAAK;GAG5C,OAAO;GACP,UAAU,YAAY;GACvB;AAEH,SAAO;GACL,MAAM;GACN,UAAU,YAAY;GACtB,OAAO;GACP,WAAW;GACX,aAAa;GACd;;AAIH,KAAI,SAAS,YAAY,UAAU,cACjC,QAAO;EACL,MAAM,OAAO,aAAa,KAAK,GAAG;EAClC,UAAU,YAAY;EACtB,OAAO;EACP,WAAW;EACX,aAAa;EACd;AAIH,KAAI,UAAU,QACZ,QAAO;EACL,MAAM,OAAO,aAAa,KAAK,GAAG;EAClC,UAAU,YAAY;EACtB,OAAO;EACP,WAAW;EACX,aAAa;EACd;CAIH,MAAM,YAAY,SAAS,GAAG,KAAK,GAAG,WAAW;AACjD,KAAI,cAAc,SAChB,QAAO;EACL,MAAM;EACN,UAAU,YAAY;EACtB,OAAO;EACP,WAAW;EACZ;AAEH,KAAI,cAAc,aAAa,SAAS,SACtC,QAAO;EACL,MAAM;EACN,UAAU,YAAY;EACtB,OAAO;EACP,WAAW;EACZ;AAEH,KAAI,cAAc,UAChB,QAAO;EACL,MAAM;EACN,UAAU,YAAY;EACtB,OAAO;EACP,WAAW;EACZ;AAIH,QAAO;EACL,MAAM;EACN,UAAU,YAAY;EACtB,OAAO;EACP,WAAW;EACX,aAAa;EACd;;;;;AAMH,SAAgB,cAAc,QAA2C;AACvE,KAAI,YAAY,OAAO,CACrB;CAGF,MAAM,YAAY;CAClB,MAAM,OAAO,UAAU;CACvB,MAAM,SAAS,UAAU;AAEzB,KAAI,CAAC,KAAM,QAAO;AAGlB,KAAI,SAAS,SAAS;EACpB,MAAM,QAAQ,UAAU;AACxB,MAAI,MACF,QAAO,cAAc,MAAM;AAE7B;;AAIF,QAAO,sBADK,SAAS,GAAG,KAAK,GAAG,WAAW,SACN,sBAAsB,SAAS;;;;;AAMtE,SAAgB,wBACd,QACA,WACA,eAA6B,gBAC7B,QACgB;CAEhB,MAAM,SADY,sBAAsB,cAAc,OAAO,CACpC,cAAc,QAAQ,WAAW,EACxD,aAAc,OAAmC,gBAClD,CAAC;AAEF,QAAO;EACL,MAAM,OAAO;EACb,aAAc,OAAmC;EACjD,QAAQ,EAAE;EACV,MAAM,OAAO;EACb,SAAS,OAAO;EACjB;;;;;AAMH,SAAgB,gBACd,QACA,SACA,gBAAgB,MACR;CACR,MAAM,0BAAU,IAAI,KAAa;CACjC,MAAM,YAAY,gBAAgB,MAAM,MAAM,QAAQ,YAAY;AAElE,SAAQ,IACN,0FACD;AAED,MAAK,MAAM,SAAS,OAElB,KACE,MAAM,KAAK,eACX,CAAC,MAAM,KAAK,aACZ,CAAC,MAAM,cACP,CAAC,MAAM,cACP,CAAC,MAAM,aACP;EAEA,MAAM,YAAY,MAAM,KAAK;EAC7B,MAAM,YAAY,UACf,QAAQ,sBAAsB,QAAQ,CACtC,aAAa;AAChB,UAAQ,IAAI,YAAY,UAAU,WAAW,UAAU,GAAG,UAAU,IAAI;;AAI5E,QAAO,MAAM,KAAK,QAAQ,CAAC,KAAK,KAAK"}
1
+ {"version":3,"file":"schema-converter.js","names":[],"sources":["../../src/openapi/schema-converter.ts"],"sourcesContent":["/**\n * JSON Schema to SchemaModel conversion utilities.\n * Converts OpenAPI JSON Schema to ContractSpec SchemaModel definitions.\n */\n\nimport { createSchemaGenerator } from './schema-generators';\nimport type {\n SchemaFormat,\n ResolvedContractsrcConfig,\n} from '@contractspec/lib.contracts';\nimport type { OpenApiSchema } from './types';\nimport { toPascalCase } from '../common/utils';\n\n/**\n * Map JSON Schema types to ContractSpec ScalarTypeEnum values.\n */\nconst JSON_SCHEMA_TO_SCALAR: Record<string, string> = {\n string: 'ScalarTypeEnum.String_unsecure',\n integer: 'ScalarTypeEnum.Int_unsecure',\n number: 'ScalarTypeEnum.Float_unsecure',\n boolean: 'ScalarTypeEnum.Boolean',\n // Special formats\n 'string:date': 'ScalarTypeEnum.Date',\n 'string:date-time': 'ScalarTypeEnum.DateTime',\n 'string:email': 'ScalarTypeEnum.EmailAddress',\n 'string:uri': 'ScalarTypeEnum.URL',\n 'string:uuid': 'ScalarTypeEnum.ID',\n};\n\n/**\n * TypeScript type representation for code generation.\n */\nexport interface TypescriptType {\n /** The type expression (e.g., \"string\", \"number\", \"MyModel\") */\n type: string;\n /** Whether the type is optional */\n optional: boolean;\n /** Whether the type is an array */\n array: boolean;\n /** Whether this is a primitive type */\n primitive: boolean;\n /** Description for documentation */\n description?: string;\n /** Whether this type is a reference to another schema (needs import) vs inline */\n isReference?: boolean;\n}\n\n/**\n * SchemaModel field representation for code generation.\n */\nexport interface SchemaField {\n /** Field name */\n name: string;\n /** Field type */\n type: TypescriptType;\n /** Scalar type enum value (for FieldType) */\n scalarType?: string;\n /** Enum values if this is an enum type */\n enumValues?: string[];\n /** Nested model if this is an object type */\n nestedModel?: GeneratedModel;\n}\n\n/**\n * Generated model representation.\n */\nexport interface GeneratedModel {\n /** Model name (PascalCase) */\n name: string;\n /** Model description */\n description?: string;\n /** Fields */\n fields: SchemaField[];\n /** Generated TypeScript code */\n code: string;\n /** Required imports */\n imports?: string[];\n}\n\n/**\n * Check if a schema is a reference object.\n */\nfunction isReference(schema: OpenApiSchema): schema is { $ref: string } {\n return typeof schema === 'object' && schema !== null && '$ref' in schema;\n}\n\n/**\n * Extract type name from a $ref.\n */\nfunction typeNameFromRef(ref: string): string {\n const parts = ref.split('/');\n return parts[parts.length - 1] ?? 'Unknown';\n}\n\n/**\n * Convert a JSON Schema to a TypeScript type representation.\n */\nexport function jsonSchemaToType(\n schema: OpenApiSchema,\n name?: string\n): TypescriptType {\n if (isReference(schema)) {\n return {\n type: toPascalCase(typeNameFromRef(schema.$ref)),\n optional: false,\n array: false,\n primitive: false,\n isReference: true,\n };\n }\n\n const schemaObj = schema as Record<string, unknown>;\n const type = schemaObj['type'] as string | undefined;\n const format = schemaObj['format'] as string | undefined;\n const nullable = schemaObj['nullable'] as boolean | undefined;\n\n // Check if this schema was dereferenced from a $ref - use the original type name\n const originalTypeName = schemaObj['_originalTypeName'] as string | undefined;\n if (originalTypeName) {\n return {\n type: toPascalCase(originalTypeName),\n optional: nullable ?? false,\n array: false,\n primitive: false,\n isReference: true,\n };\n }\n\n // Handle arrays\n if (type === 'array') {\n const items = schemaObj['items'] as OpenApiSchema | undefined;\n if (items) {\n const itemType = jsonSchemaToType(items, name);\n return {\n ...itemType,\n array: true,\n optional: nullable ?? false,\n };\n }\n return {\n type: 'unknown',\n optional: nullable ?? false,\n array: true,\n primitive: false,\n isReference: true,\n };\n }\n\n // Handle objects\n if (type === 'object' || schemaObj['properties']) {\n return {\n type: name ? toPascalCase(name) : 'Record<string, unknown>',\n optional: nullable ?? false,\n array: false,\n primitive: false,\n isReference: true,\n };\n }\n\n // Handle enums\n if (schemaObj['enum']) {\n return {\n type: name ? toPascalCase(name) : 'string',\n optional: nullable ?? false,\n array: false,\n primitive: false,\n isReference: true,\n };\n }\n\n // Handle primitives\n const scalarKey = format ? `${type}:${format}` : type;\n if (scalarKey === 'string') {\n return {\n type: 'string',\n optional: nullable ?? false,\n array: false,\n primitive: true,\n };\n }\n if (scalarKey === 'integer' || type === 'number') {\n return {\n type: 'number',\n optional: nullable ?? false,\n array: false,\n primitive: true,\n };\n }\n if (scalarKey === 'boolean') {\n return {\n type: 'boolean',\n optional: nullable ?? false,\n array: false,\n primitive: true,\n };\n }\n\n // Default to unknown\n return {\n type: 'unknown',\n optional: nullable ?? false,\n array: false,\n primitive: false,\n isReference: true,\n };\n}\n\n/**\n * Get the ScalarTypeEnum value for a JSON Schema type.\n */\nexport function getScalarType(schema: OpenApiSchema): string | undefined {\n if (isReference(schema)) {\n return undefined;\n }\n\n const schemaObj = schema as Record<string, unknown>;\n const type = schemaObj['type'] as string | undefined;\n const format = schemaObj['format'] as string | undefined;\n\n if (!type) return undefined;\n\n // For arrays, get the scalar type of the items\n if (type === 'array') {\n const items = schemaObj['items'] as OpenApiSchema | undefined;\n if (items) {\n return getScalarType(items);\n }\n return undefined;\n }\n\n const key = format ? `${type}:${format}` : type;\n return JSON_SCHEMA_TO_SCALAR[key] ?? JSON_SCHEMA_TO_SCALAR[type] ?? undefined;\n}\n\n/**\n * Generate code for a schema model using the specified format.\n */\nexport function generateSchemaModelCode(\n schema: OpenApiSchema,\n modelName: string,\n schemaFormat: SchemaFormat = 'contractspec',\n config?: ResolvedContractsrcConfig\n): GeneratedModel {\n const generator = createSchemaGenerator(schemaFormat, config);\n const result = generator.generateModel(schema, modelName, {\n description: (schema as Record<string, unknown>)['description'] as string,\n });\n\n return {\n name: result.name,\n description: (schema as Record<string, unknown>)['description'] as string,\n fields: [], // fields are processed internally by generators now\n code: result.code,\n imports: result.imports,\n };\n}\n\n/**\n * Generate import statements for a SchemaModel.\n */\nexport function generateImports(\n fields: SchemaField[],\n options: ResolvedContractsrcConfig,\n sameDirectory = true\n): string {\n const imports = new Set<string>();\n const modelsDir = sameDirectory ? '.' : `../${options.conventions.models}`;\n\n imports.add(\n \"import { defineSchemaModel, ScalarTypeEnum, EnumType } from '@contractspec/lib.schema';\"\n );\n\n for (const field of fields) {\n // Only import fields that are actual references to other schemas (not inline types)\n if (\n field.type.isReference &&\n !field.type.primitive &&\n !field.enumValues &&\n !field.scalarType &&\n !field.nestedModel\n ) {\n // This is a reference to another schema model\n const modelName = field.type.type;\n const kebabName = modelName\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n .toLowerCase();\n imports.add(`import { ${modelName} } from '${modelsDir}/${kebabName}';`);\n }\n }\n\n return Array.from(imports).join('\\n');\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["JSON_SCHEMA_TO_SCALAR: Record<string, string>","fields: SchemaField[]","safeModelName","lines: string[]","enumValues: string[] | undefined","nestedModel: GeneratedModel | undefined","zodType: string","jsonSchema: Record<string, unknown>","tsLines: string[]"],"sources":["../../../src/openapi/schema-generators/index.ts"],"sourcesContent":["/**\n * Schema generator factory for multi-format code generation.\n *\n * Provides format-specific generators for OpenAPI to ContractSpec conversion.\n *\n * @module schema-generators\n */\n\nimport type {\n ContractsrcConfig,\n SchemaFormat,\n} from '@contractspec/lib.contracts';\nimport type { OpenApiSchema } from '../types';\nimport {\n type GeneratedModel,\n generateImports,\n getScalarType,\n jsonSchemaToType,\n type SchemaField,\n} from '../schema-converter';\nimport {\n toKebabCase,\n toPascalCase,\n toValidIdentifier,\n} from '../../common/utils';\n\nconst JSON_SCHEMA_TO_SCALAR: Record<string, string> = {\n string: 'ScalarTypeEnum.String_unsecure',\n integer: 'ScalarTypeEnum.Int_unsecure',\n number: 'ScalarTypeEnum.Float_unsecure',\n boolean: 'ScalarTypeEnum.Boolean',\n 'string:date': 'ScalarTypeEnum.Date',\n 'string:date-time': 'ScalarTypeEnum.DateTime',\n 'string:email': 'ScalarTypeEnum.EmailAddress',\n 'string:uri': 'ScalarTypeEnum.URL',\n 'string:uuid': 'ScalarTypeEnum.ID',\n};\n\nfunction isReference(schema: OpenApiSchema): schema is { $ref: string } {\n return typeof schema === 'object' && schema !== null && '$ref' in schema;\n}\n\nfunction typeNameFromRef(ref: string): string {\n const parts = ref.split('/');\n return parts[parts.length - 1] ?? 'Unknown';\n}\n\n/**\n * Generated code output for a model.\n */\nexport interface GeneratedCode {\n /** The generated TypeScript/JSON code */\n code: string;\n /** File name for the generated code */\n fileName: string;\n /** Required imports */\n imports: string[];\n /** The name of the exported symbol */\n name: string;\n}\n\n/**\n * Generated code output for a field.\n */\nexport interface GeneratedFieldCode {\n /** The field code snippet */\n code: string;\n /** Type reference for the field */\n typeRef: string;\n /** Whether this is an optional field */\n isOptional: boolean;\n /** Whether this is an array field */\n isArray: boolean;\n}\n\n/**\n * Interface for format-specific schema generators.\n */\nexport interface SchemaGenerator {\n /** Format this generator produces */\n format: SchemaFormat;\n\n /**\n * Generate code for a complete model/schema.\n */\n generateModel(\n schema: OpenApiSchema,\n name: string,\n options?: { description?: string }\n ): GeneratedCode;\n\n /**\n * Generate code for a single field.\n */\n generateField(\n schema: OpenApiSchema,\n fieldName: string,\n required: boolean\n ): GeneratedFieldCode;\n\n /**\n * Get import statements needed for this generator's output.\n */\n getBaseImports(): string[];\n}\n\n/**\n * Factory function to create a format-specific schema generator.\n *\n * @param format - The target output format\n * @param config - ContractSpec configuration\n * @returns A schema generator for the specified format\n *\n * @example\n * ```typescript\n * const generator = createSchemaGenerator('zod', config);\n * const model = generator.generateModel(openApiSchema, 'User');\n * ```\n */\nexport function createSchemaGenerator(\n format: SchemaFormat,\n config?: ContractsrcConfig\n): SchemaGenerator {\n switch (format) {\n case 'zod':\n return new ZodSchemaGenerator(config);\n case 'json-schema':\n return new JsonSchemaGenerator(config);\n case 'graphql':\n return new GraphQLSchemaGenerator(config);\n case 'contractspec':\n default:\n return new ContractSpecSchemaGenerator(config);\n }\n}\n\n// ============================================================================\n// ContractSpec Generator (default)\n// ============================================================================\n\nexport class ContractSpecSchemaGenerator implements SchemaGenerator {\n format: SchemaFormat = 'contractspec';\n config?: ContractsrcConfig;\n\n constructor(config?: ContractsrcConfig) {\n this.config = config;\n }\n\n generateModel(schema: OpenApiSchema, name: string): GeneratedCode {\n const model = this.generateContractSpecSchema(schema, name);\n\n // Calculate imports for dependencies\n const dependencyImports = this.config\n ? generateImports(model.fields, this.config, false)\n .split('\\n')\n .filter(Boolean)\n : [];\n\n // Add nested model imports?\n // Nested models are inlined in code, but might have refs.\n // generateImports handles fields recursively? No, generateImports iterates top-level fields.\n // But nested models are hoisted, so their fields are not in 'fields' array of parent directly?\n // Wait, GeneratedModel.fields contains 'nestedModel'.\n // generateImports should traverse nested models?\n // The original generateImports does NOT traverse nested models.\n // However, the original code worked, so maybe simple traversal is enough.\n\n return {\n code: model.code,\n fileName: toKebabCase(name) + '.ts',\n imports: [...this.getBaseImports(), ...dependencyImports],\n name: model.name,\n };\n }\n\n generateField(\n schema: OpenApiSchema,\n fieldName: string,\n required: boolean\n ): GeneratedFieldCode {\n const field = this.convertField(schema, fieldName, required);\n\n return {\n code: field.scalarType\n ? `${field.scalarType}()`\n : 'ScalarTypeEnum.String_unsecure()',\n typeRef: field.type.type,\n isOptional: field.type.optional,\n isArray: field.type.array,\n };\n }\n\n getBaseImports(): string[] {\n return [\n \"import { defineSchemaModel, ScalarTypeEnum, EnumType } from '@contractspec/lib.schema';\",\n ];\n }\n\n // Ported logic\n private generateContractSpecSchema(\n schema: OpenApiSchema,\n modelName: string,\n indent = 0\n ): GeneratedModel {\n const spaces = ' '.repeat(indent);\n const fields: SchemaField[] = [];\n\n if (isReference(schema)) {\n return {\n name: toPascalCase(typeNameFromRef(schema.$ref)),\n fields: [],\n code: `// Reference to ${schema.$ref}`,\n };\n }\n\n const schemaObj = schema as Record<string, unknown>;\n const description = schemaObj['description'] as string | undefined;\n const properties = schemaObj['properties'] as\n | Record<string, OpenApiSchema>\n | undefined;\n const required = (schemaObj['required'] as string[]) ?? [];\n\n // Handle enum types\n const enumValues = schemaObj['enum'] as unknown[] | undefined;\n if (enumValues && enumValues.length > 0) {\n const safeModelName = toPascalCase(toValidIdentifier(modelName));\n const enumCode = [\n `${spaces}/**`,\n `${spaces} * Enum type: ${safeModelName}`,\n description ? `${spaces} * ${description}` : null,\n `${spaces} */`,\n `${spaces}export const ${safeModelName} = new EnumType('${safeModelName}', [${enumValues.map((v) => `'${String(v)}'`).join(', ')}]);`,\n ]\n .filter((line) => line !== null)\n .join('\\n');\n\n return {\n name: safeModelName,\n description,\n fields: [],\n code: enumCode,\n };\n }\n\n // Handle primitive types alias\n const schemaType = schemaObj['type'] as string | undefined;\n if (schemaType && !properties && !enumValues) {\n const safeModelName = toPascalCase(toValidIdentifier(modelName));\n const format = schemaObj['format'] as string | undefined;\n const scalarKey = format ? `${schemaType}:${format}` : schemaType;\n const scalarType =\n JSON_SCHEMA_TO_SCALAR[scalarKey] ?? JSON_SCHEMA_TO_SCALAR[schemaType];\n\n if (scalarType) {\n const aliasCode = [\n `${spaces}/**`,\n `${spaces} * Type alias: ${safeModelName}`,\n description ? `${spaces} * ${description}` : null,\n `${spaces} * Underlying type: ${scalarType}`,\n `${spaces} */`,\n `${spaces}export const ${safeModelName} = defineSchemaModel({`,\n `${spaces} name: '${safeModelName}',`,\n description\n ? `${spaces} description: ${JSON.stringify(description)},`\n : null,\n `${spaces} fields: {`,\n `${spaces} value: {`,\n `${spaces} type: ${scalarType}(),`,\n `${spaces} isOptional: false,`,\n `${spaces} },`,\n `${spaces} },`,\n `${spaces}});`,\n ]\n .filter((line) => line !== null)\n .join('\\n');\n\n return {\n name: safeModelName,\n description,\n fields: [],\n code: aliasCode,\n };\n }\n }\n\n // Handle additionalProperties (dictionary)\n const additionalProperties = schemaObj['additionalProperties'];\n if (additionalProperties && !properties) {\n const safeModelName = toPascalCase(toValidIdentifier(modelName));\n\n const dictCode = [\n `${spaces}/**`,\n `${spaces} * Dictionary/Record type: ${safeModelName}`,\n description ? `${spaces} * ${description}` : null,\n `${spaces} * Use as: Record<string, unknown> - access via record[key]`,\n `${spaces} */`,\n `${spaces}export const ${safeModelName} = ScalarTypeEnum.JSONObject();`,\n ]\n .filter((line) => line !== null)\n .join('\\n');\n\n return {\n name: safeModelName,\n description,\n fields: [],\n code: dictCode,\n };\n }\n\n if (!properties) {\n const safeModelName = toPascalCase(toValidIdentifier(modelName));\n const emptyModelCode = [\n `${spaces}export const ${safeModelName} = defineSchemaModel({`,\n `${spaces} name: '${safeModelName}',`,\n description\n ? `${spaces} description: ${JSON.stringify(description)},`\n : null,\n `${spaces} fields: {},`,\n `${spaces}});`,\n ]\n .filter((line) => line !== null)\n .join('\\n');\n\n return {\n name: safeModelName,\n description,\n fields: [],\n code: emptyModelCode,\n };\n }\n\n // Generate fields\n const safeModelName = toPascalCase(toValidIdentifier(modelName));\n for (const [propName, propSchema] of Object.entries(properties)) {\n const isRequired = required.includes(propName);\n fields.push(\n this.convertField(propSchema, propName, isRequired, safeModelName)\n );\n }\n\n // Generate code\n const lines: string[] = [];\n\n // Prepend nested models\n for (const field of fields) {\n if (field.nestedModel) {\n lines.push(field.nestedModel.code);\n lines.push('');\n }\n }\n\n // Model definition\n lines.push(`${spaces}export const ${safeModelName} = defineSchemaModel({`);\n lines.push(`${spaces} name: '${safeModelName}',`);\n if (description) {\n lines.push(`${spaces} description: ${JSON.stringify(description)},`);\n }\n lines.push(`${spaces} fields: {`);\n\n for (const field of fields) {\n const fieldLines = this.generateFieldCodeHelper(field, indent + 2);\n lines.push(fieldLines);\n }\n\n lines.push(`${spaces} },`);\n lines.push(`${spaces}});`);\n\n return {\n name: safeModelName,\n description,\n fields,\n code: lines.join('\\n'),\n imports: [],\n };\n }\n\n private convertField(\n schema: OpenApiSchema,\n fieldName: string,\n required: boolean,\n parentName?: string\n ): SchemaField {\n const type = jsonSchemaToType(schema, fieldName);\n const scalarType = getScalarType(schema);\n\n let enumValues: string[] | undefined;\n let nestedModel: GeneratedModel | undefined;\n\n if (!isReference(schema)) {\n const schemaObj = schema as Record<string, unknown>;\n const enumArr = schemaObj['enum'] as unknown[] | undefined;\n if (enumArr) {\n enumValues = enumArr.map(String);\n }\n\n // Handle nested objects\n if (\n schemaObj['type'] === 'object' &&\n !scalarType &&\n schemaObj['properties'] &&\n !enumValues\n ) {\n const nestedName =\n (parentName ? parentName : '') + toPascalCase(fieldName);\n nestedModel = this.generateContractSpecSchema(schema, nestedName);\n\n type.type = nestedModel.name;\n type.isReference = true;\n }\n }\n\n return {\n name: fieldName,\n type: {\n ...type,\n optional: !required || type.optional,\n description: !isReference(schema)\n ? ((schema as Record<string, unknown>)['description'] as string)\n : undefined,\n },\n scalarType,\n enumValues,\n nestedModel,\n };\n }\n\n private generateFieldCodeHelper(field: SchemaField, indent: number): string {\n const spaces = ' '.repeat(indent);\n const lines: string[] = [];\n\n const isIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(field.name);\n const safeKey = isIdentifier ? field.name : `'${field.name}'`;\n lines.push(`${spaces}${safeKey}: {`);\n\n if (field.enumValues) {\n const enumName = toPascalCase(field.name) + 'Enum';\n lines.push(\n `${spaces} type: new EnumType('${enumName}', [${field.enumValues.map((v) => `'${v}'`).join(', ')}]),`\n );\n } else if (field.scalarType) {\n lines.push(`${spaces} type: ${field.scalarType}(),`);\n } else if (field.nestedModel) {\n lines.push(`${spaces} type: ${field.nestedModel.name},`);\n } else if (field.type.primitive) {\n const fallbackScalar =\n field.type.type === 'number'\n ? 'ScalarTypeEnum.Float_unsecure'\n : field.type.type === 'boolean'\n ? 'ScalarTypeEnum.Boolean_unsecure'\n : 'ScalarTypeEnum.String_unsecure';\n lines.push(`${spaces} type: ${fallbackScalar}(),`);\n } else if (field.type.isReference) {\n lines.push(`${spaces} type: ${field.type.type},`);\n } else {\n lines.push(\n `${spaces} type: ScalarTypeEnum.JSONObject(), // TODO: Define nested model for ${field.type.type}`\n );\n }\n\n lines.push(`${spaces} isOptional: ${field.type.optional},`);\n\n if (field.type.array) {\n lines.push(`${spaces} isArray: true,`);\n }\n\n lines.push(`${spaces}},`);\n\n return lines.join('\\n');\n }\n}\n\n// ============================================================================\n// Zod Generator\n// ============================================================================\n\nexport class ZodSchemaGenerator implements SchemaGenerator {\n format: SchemaFormat = 'zod';\n config?: ContractsrcConfig;\n\n constructor(config?: ContractsrcConfig) {\n this.config = config;\n }\n\n generateModel(\n schema: OpenApiSchema,\n name: string,\n options?: { description?: string }\n ): GeneratedCode {\n const schemaObj = schema as Record<string, unknown>;\n const properties = schemaObj['properties'] as\n | Record<string, OpenApiSchema>\n | undefined;\n const _required = (schemaObj['required'] as string[]) ?? [];\n const description = options?.description ?? schemaObj['description'];\n\n const lines: string[] = [];\n\n if (description) {\n lines.push(`/**`);\n lines.push(` * ${description}`);\n lines.push(` */`);\n }\n\n // Generate Zod Schema\n const schemaName = `${name}Schema`;\n let schemaCode;\n\n if (properties) {\n schemaCode = this.generateZodObject(schemaObj);\n } else {\n schemaCode = 'z.object({})';\n }\n\n lines.push(`export const ${schemaName} = ${schemaCode};`);\n lines.push(``);\n\n // Generate ZodSchemaType wrapper for ContractSpec compatibility\n lines.push(\n `export const ${name} = new ZodSchemaType(${schemaName}, { name: '${name}', description: ${JSON.stringify(description)} });`\n );\n lines.push(``);\n\n // Generate Type\n lines.push(`export type ${name} = z.infer<typeof ${schemaName}>;`);\n\n // Dependencies?\n // Zod generator doesn't currently resolve references recursively or import them\n // This is a limitation: if prop is ref, use z.lazy(() => RefSchema) or similar?\n // For now assuming shallow/primitive or using z.unknown/record for complex stuff\n // Or if Contracts-transformers logic for references is ported.\n // Simplifying: Zod generator relies on primitive mapping for now.\n\n return {\n code: lines.join('\\n'),\n fileName: toKebabCase(name) + '.ts',\n imports: this.getBaseImports(), // Todo: Add dependency imports if references used\n name: name,\n };\n }\n\n generateField(\n schema: OpenApiSchema,\n _fieldName: string,\n required: boolean\n ): GeneratedFieldCode {\n const schemaObj = schema as Record<string, unknown>;\n const type = schemaObj['type'] as string | undefined;\n const format = schemaObj['format'] as string | undefined;\n const nullable = schemaObj['nullable'] as boolean | undefined;\n\n let zodType: string;\n\n if (type === 'object' && schemaObj['properties']) {\n zodType = this.generateZodObject(schemaObj);\n } else {\n zodType = this.mapTypeToZod(type, format);\n\n if (schemaObj['enum']) {\n const enumValues = schemaObj['enum'] as string[];\n zodType = `z.enum([${enumValues.map((v) => `'${v}'`).join(', ')}])`;\n }\n\n if (type === 'array') {\n const items = schemaObj['items'] as OpenApiSchema | undefined;\n if (items) {\n const itemField = this.generateField(items, 'item', true);\n zodType = `z.array(${itemField.code.replace('.optional()', '')})`;\n } else {\n zodType = 'z.array(z.unknown())';\n }\n }\n }\n\n // Add constraints\n if (type === 'string') {\n if (schemaObj['minLength'] !== undefined)\n zodType += `.min(${schemaObj['minLength']})`;\n if (schemaObj['maxLength'] !== undefined)\n zodType += `.max(${schemaObj['maxLength']})`;\n if (schemaObj['pattern'] !== undefined)\n zodType += `.regex(/${schemaObj['pattern']}/)`;\n } else if (type === 'integer' || type === 'number') {\n if (schemaObj['minimum'] !== undefined) {\n zodType +=\n schemaObj['exclusiveMinimum'] === true\n ? `.gt(${schemaObj['minimum']})`\n : `.min(${schemaObj['minimum']})`;\n } else if (typeof schemaObj['exclusiveMinimum'] === 'number') {\n zodType += `.gt(${schemaObj['exclusiveMinimum']})`;\n }\n\n if (schemaObj['maximum'] !== undefined) {\n zodType +=\n schemaObj['exclusiveMaximum'] === true\n ? `.lt(${schemaObj['maximum']})`\n : `.max(${schemaObj['maximum']})`;\n } else if (typeof schemaObj['exclusiveMaximum'] === 'number') {\n zodType += `.lt(${schemaObj['exclusiveMaximum']})`;\n }\n\n if (schemaObj['multipleOf'] !== undefined) {\n zodType += `.step(${schemaObj['multipleOf']})`;\n }\n } else if (type === 'array') {\n if (schemaObj['minItems'] !== undefined)\n zodType += `.min(${schemaObj['minItems']})`;\n if (schemaObj['maxItems'] !== undefined)\n zodType += `.max(${schemaObj['maxItems']})`;\n }\n\n if (schemaObj['default'] !== undefined) {\n zodType += `.default(${JSON.stringify(schemaObj['default'])})`;\n }\n\n if (!required || nullable) {\n zodType = `${zodType}.optional()`;\n }\n\n return {\n code: zodType,\n typeRef: type ?? 'unknown',\n isOptional: !required || Boolean(nullable),\n isArray: type === 'array',\n };\n }\n\n getBaseImports(): string[] {\n return [\n \"import * as z from 'zod';\",\n \"import { ZodSchemaType } from '@contractspec/lib.schema';\",\n ];\n }\n\n private generateZodObject(schemaObj: Record<string, unknown>): string {\n const required = (schemaObj['required'] as string[]) ?? [];\n const properties = schemaObj['properties'] as Record<string, OpenApiSchema>;\n const lines: string[] = ['z.object({'];\n\n for (const [propName, propSchema] of Object.entries(properties)) {\n const isRequired = required.includes(propName);\n const field = this.generateField(propSchema, propName, isRequired);\n // If name is not a valid identifier, quote it\n const safeName = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(propName)\n ? propName\n : `'${propName}'`;\n\n lines.push(` ${safeName}: ${field.code},`);\n }\n\n lines.push('})');\n return lines.join('\\n');\n }\n\n private mapTypeToZod(type?: string, format?: string): string {\n if (format === 'date-time') return 'z.string().datetime()';\n if (format === 'date') return 'z.string().date()';\n if (format === 'email') return 'z.string().email()';\n if (format === 'uri' || format === 'url') return 'z.string().url()';\n if (format === 'uuid') return 'z.string().uuid()';\n\n switch (type) {\n case 'string':\n return 'z.string()';\n case 'integer':\n return 'z.number().int()';\n case 'number':\n return 'z.number()';\n case 'boolean':\n return 'z.boolean()';\n case 'object':\n return 'z.record(z.string(), z.unknown())';\n case 'null':\n return 'z.null()';\n default:\n return 'z.unknown()';\n }\n }\n}\n\n// ============================================================================\n// JSON Schema Generator\n// ============================================================================\n\nexport class JsonSchemaGenerator implements SchemaGenerator {\n format: SchemaFormat = 'json-schema';\n config?: ContractsrcConfig;\n\n constructor(config?: ContractsrcConfig) {\n this.config = config;\n }\n\n generateModel(\n schema: OpenApiSchema,\n name: string,\n options?: { description?: string }\n ): GeneratedCode {\n const schemaObj = schema as Record<string, unknown>;\n const description = options?.description ?? schemaObj['description'];\n\n // Create a clean JSON Schema object\n const jsonSchema: Record<string, unknown> = {\n $schema: 'https://json-schema.org/draft/2020-12/schema',\n title: name,\n ...schemaObj,\n };\n\n if (description) {\n jsonSchema['description'] = description;\n }\n\n const lines: string[] = [];\n lines.push(`/**`);\n lines.push(` * JSON Schema: ${name}`);\n if (description) {\n lines.push(` * ${description}`);\n }\n lines.push(` */`);\n\n const schemaName = `${name}Schema`;\n lines.push(\n `export const ${schemaName} = ${JSON.stringify(jsonSchema, null, 2)} as const;`\n );\n lines.push(``);\n\n // Generate wrapper\n lines.push(`export const ${name} = new JsonSchemaType(${schemaName});`);\n lines.push(``);\n\n // Type derived from JsonSchemaType or similar?\n // Actually JsonSchemaType doesn't strictly infer TS type from JSON schema at compile time easily without other tools.\n // For now, export type as unknown or rely on library.\n lines.push(\n `export type ${name} = unknown; // JSON Schema type inference not fully supported`\n );\n\n return {\n code: lines.join('\\n'),\n fileName: toKebabCase(name) + '.ts',\n imports: this.getBaseImports(), // dependency imports?\n name: name,\n };\n }\n\n generateField(\n schema: OpenApiSchema,\n _fieldName: string,\n required: boolean\n ): GeneratedFieldCode {\n const schemaObj = schema as Record<string, unknown>;\n const type = schemaObj['type'] as string | undefined;\n const nullable = schemaObj['nullable'] as boolean | undefined;\n\n return {\n code: JSON.stringify(schemaObj),\n typeRef: type ?? 'unknown',\n isOptional: !required || Boolean(nullable),\n isArray: type === 'array',\n };\n }\n\n getBaseImports(): string[] {\n return [\"import { JsonSchemaType } from '@contractspec/lib.schema';\"];\n }\n}\n\n// ============================================================================\n// GraphQL Generator\n// ============================================================================\n\nexport class GraphQLSchemaGenerator implements SchemaGenerator {\n format: SchemaFormat = 'graphql';\n config?: ContractsrcConfig;\n\n constructor(config?: ContractsrcConfig) {\n this.config = config;\n }\n\n generateModel(\n schema: OpenApiSchema,\n name: string,\n options?: { description?: string }\n ): GeneratedCode {\n const schemaObj = schema as Record<string, unknown>;\n const properties = schemaObj['properties'] as\n | Record<string, OpenApiSchema>\n | undefined;\n const required = (schemaObj['required'] as string[]) ?? [];\n const description = options?.description ?? schemaObj['description'];\n\n const lines: string[] = [];\n\n if (description) {\n lines.push(`\"\"\"${description}\"\"\"`);\n }\n\n lines.push(`type ${name} {`);\n\n if (properties) {\n for (const [propName, propSchema] of Object.entries(properties)) {\n const isRequired = required.includes(propName);\n const field = this.generateField(propSchema, propName, isRequired);\n const nullMarker = isRequired ? '!' : '';\n lines.push(` ${propName}: ${field.typeRef}${nullMarker}`);\n }\n }\n\n lines.push(`}`);\n\n // Also generate SDL as a string constant\n const sdl = lines.join('\\n');\n const tsLines: string[] = [];\n tsLines.push(`/**`);\n tsLines.push(` * GraphQL type definition: ${name}`);\n tsLines.push(` */`);\n tsLines.push(`export const ${name}TypeDef = \\`${sdl}\\`;`);\n tsLines.push(``);\n tsLines.push(\n `export const ${name} = new GraphQLSchemaType(${name}TypeDef, '${name}');`\n );\n\n return {\n code: tsLines.join('\\n'),\n fileName: toKebabCase(name) + '.ts',\n imports: this.getBaseImports(),\n name: name,\n };\n }\n\n generateField(\n schema: OpenApiSchema,\n _fieldName: string,\n required: boolean\n ): GeneratedFieldCode {\n const schemaObj = schema as Record<string, unknown>;\n const type = schemaObj['type'] as string | undefined;\n const format = schemaObj['format'] as string | undefined;\n const nullable = schemaObj['nullable'] as boolean | undefined;\n\n const gqlType = this.mapTypeToGraphQL(type, format);\n\n return {\n code: gqlType,\n typeRef: gqlType,\n isOptional: !required || Boolean(nullable),\n isArray: type === 'array',\n };\n }\n\n getBaseImports(): string[] {\n return [\"import { GraphQLSchemaType } from '@contractspec/lib.schema';\"];\n }\n\n private mapTypeToGraphQL(type?: string, format?: string): string {\n if (format === 'date-time') return 'DateTime';\n if (format === 'date') return 'Date';\n if (format === 'email') return 'String';\n if (format === 'uri' || format === 'url') return 'String';\n if (format === 'uuid') return 'ID';\n\n switch (type) {\n case 'string':\n return 'String';\n case 'integer':\n return 'Int';\n case 'number':\n return 'Float';\n case 'boolean':\n return 'Boolean';\n case 'object':\n return 'JSON';\n case 'array':\n return '[JSON]';\n default:\n return 'JSON';\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["safeModelName"],"sources":["../../../src/openapi/schema-generators/index.ts"],"sourcesContent":["/**\n * Schema generator factory for multi-format code generation.\n *\n * Provides format-specific generators for OpenAPI to ContractSpec conversion.\n *\n * @module schema-generators\n */\n\nimport type {\n ResolvedContractsrcConfig,\n SchemaFormat,\n} from '@contractspec/lib.contracts';\nimport type { OpenApiSchema } from '../types';\nimport {\n type GeneratedModel,\n generateImports,\n getScalarType,\n jsonSchemaToType,\n type SchemaField,\n} from '../schema-converter';\nimport {\n toKebabCase,\n toPascalCase,\n toValidIdentifier,\n} from '../../common/utils';\n\nconst JSON_SCHEMA_TO_SCALAR: Record<string, string> = {\n string: 'ScalarTypeEnum.String_unsecure',\n integer: 'ScalarTypeEnum.Int_unsecure',\n number: 'ScalarTypeEnum.Float_unsecure',\n boolean: 'ScalarTypeEnum.Boolean',\n 'string:date': 'ScalarTypeEnum.Date',\n 'string:date-time': 'ScalarTypeEnum.DateTime',\n 'string:email': 'ScalarTypeEnum.EmailAddress',\n 'string:uri': 'ScalarTypeEnum.URL',\n 'string:uuid': 'ScalarTypeEnum.ID',\n};\n\nfunction isReference(schema: OpenApiSchema): schema is { $ref: string } {\n return typeof schema === 'object' && schema !== null && '$ref' in schema;\n}\n\nfunction typeNameFromRef(ref: string): string {\n const parts = ref.split('/');\n return parts[parts.length - 1] ?? 'Unknown';\n}\n\n/**\n * Generated code output for a model.\n */\nexport interface GeneratedCode {\n /** The generated TypeScript/JSON code */\n code: string;\n /** File name for the generated code */\n fileName: string;\n /** Required imports */\n imports: string[];\n /** The name of the exported symbol */\n name: string;\n}\n\n/**\n * Generated code output for a field.\n */\nexport interface GeneratedFieldCode {\n /** The field code snippet */\n code: string;\n /** Type reference for the field */\n typeRef: string;\n /** Whether this is an optional field */\n isOptional: boolean;\n /** Whether this is an array field */\n isArray: boolean;\n}\n\n/**\n * Interface for format-specific schema generators.\n */\nexport interface SchemaGenerator {\n /** Format this generator produces */\n format: SchemaFormat;\n\n /**\n * Generate code for a complete model/schema.\n */\n generateModel(\n schema: OpenApiSchema,\n name: string,\n options?: { description?: string }\n ): GeneratedCode;\n\n /**\n * Generate code for a single field.\n */\n generateField(\n schema: OpenApiSchema,\n fieldName: string,\n required: boolean\n ): GeneratedFieldCode;\n\n /**\n * Get import statements needed for this generator's output.\n */\n getBaseImports(): string[];\n}\n\n/**\n * Factory function to create a format-specific schema generator.\n *\n * @param format - The target output format\n * @param config - ContractSpec configuration\n * @returns A schema generator for the specified format\n *\n * @example\n * ```typescript\n * const generator = createSchemaGenerator('zod', config);\n * const model = generator.generateModel(openApiSchema, 'User');\n * ```\n */\nexport function createSchemaGenerator(\n format: SchemaFormat,\n config?: ResolvedContractsrcConfig\n): SchemaGenerator {\n switch (format) {\n case 'zod':\n return new ZodSchemaGenerator(config);\n case 'json-schema':\n return new JsonSchemaGenerator(config);\n case 'graphql':\n return new GraphQLSchemaGenerator(config);\n case 'contractspec':\n default:\n return new ContractSpecSchemaGenerator(config);\n }\n}\n\n// ============================================================================\n// ContractSpec Generator (default)\n// ============================================================================\n\nexport class ContractSpecSchemaGenerator implements SchemaGenerator {\n format: SchemaFormat = 'contractspec';\n config?: ResolvedContractsrcConfig;\n\n constructor(config?: ResolvedContractsrcConfig) {\n this.config = config;\n }\n\n generateModel(schema: OpenApiSchema, name: string): GeneratedCode {\n const model = this.generateContractSpecSchema(schema, name);\n\n // Calculate imports for dependencies\n const dependencyImports = this.config\n ? generateImports(model.fields, this.config, false)\n .split('\\n')\n .filter(Boolean)\n : [];\n\n // Add nested model imports?\n // Nested models are inlined in code, but might have refs.\n // generateImports handles fields recursively? No, generateImports iterates top-level fields.\n // But nested models are hoisted, so their fields are not in 'fields' array of parent directly?\n // Wait, GeneratedModel.fields contains 'nestedModel'.\n // generateImports should traverse nested models?\n // The original generateImports does NOT traverse nested models.\n // However, the original code worked, so maybe simple traversal is enough.\n\n return {\n code: model.code,\n fileName: toKebabCase(name) + '.ts',\n imports: [...this.getBaseImports(), ...dependencyImports],\n name: model.name,\n };\n }\n\n generateField(\n schema: OpenApiSchema,\n fieldName: string,\n required: boolean\n ): GeneratedFieldCode {\n const field = this.convertField(schema, fieldName, required);\n\n return {\n code: field.scalarType\n ? `${field.scalarType}()`\n : 'ScalarTypeEnum.String_unsecure()',\n typeRef: field.type.type,\n isOptional: field.type.optional,\n isArray: field.type.array,\n };\n }\n\n getBaseImports(): string[] {\n return [\n \"import { defineSchemaModel, ScalarTypeEnum, EnumType } from '@contractspec/lib.schema';\",\n ];\n }\n\n // Ported logic\n private generateContractSpecSchema(\n schema: OpenApiSchema,\n modelName: string,\n indent = 0\n ): GeneratedModel {\n const spaces = ' '.repeat(indent);\n const fields: SchemaField[] = [];\n\n if (isReference(schema)) {\n return {\n name: toPascalCase(typeNameFromRef(schema.$ref)),\n fields: [],\n code: `// Reference to ${schema.$ref}`,\n };\n }\n\n const schemaObj = schema as Record<string, unknown>;\n const description = schemaObj['description'] as string | undefined;\n const properties = schemaObj['properties'] as\n | Record<string, OpenApiSchema>\n | undefined;\n const required = (schemaObj['required'] as string[]) ?? [];\n\n // Handle enum types\n const enumValues = schemaObj['enum'] as unknown[] | undefined;\n if (enumValues && enumValues.length > 0) {\n const safeModelName = toPascalCase(toValidIdentifier(modelName));\n const enumCode = [\n `${spaces}/**`,\n `${spaces} * Enum type: ${safeModelName}`,\n description ? `${spaces} * ${description}` : null,\n `${spaces} */`,\n `${spaces}export const ${safeModelName} = new EnumType('${safeModelName}', [${enumValues.map((v) => `'${String(v)}'`).join(', ')}]);`,\n ]\n .filter((line) => line !== null)\n .join('\\n');\n\n return {\n name: safeModelName,\n description,\n fields: [],\n code: enumCode,\n };\n }\n\n // Handle primitive types alias\n const schemaType = schemaObj['type'] as string | undefined;\n if (schemaType && !properties && !enumValues) {\n const safeModelName = toPascalCase(toValidIdentifier(modelName));\n const format = schemaObj['format'] as string | undefined;\n const scalarKey = format ? `${schemaType}:${format}` : schemaType;\n const scalarType =\n JSON_SCHEMA_TO_SCALAR[scalarKey] ?? JSON_SCHEMA_TO_SCALAR[schemaType];\n\n if (scalarType) {\n const aliasCode = [\n `${spaces}/**`,\n `${spaces} * Type alias: ${safeModelName}`,\n description ? `${spaces} * ${description}` : null,\n `${spaces} * Underlying type: ${scalarType}`,\n `${spaces} */`,\n `${spaces}export const ${safeModelName} = defineSchemaModel({`,\n `${spaces} name: '${safeModelName}',`,\n description\n ? `${spaces} description: ${JSON.stringify(description)},`\n : null,\n `${spaces} fields: {`,\n `${spaces} value: {`,\n `${spaces} type: ${scalarType}(),`,\n `${spaces} isOptional: false,`,\n `${spaces} },`,\n `${spaces} },`,\n `${spaces}});`,\n ]\n .filter((line) => line !== null)\n .join('\\n');\n\n return {\n name: safeModelName,\n description,\n fields: [],\n code: aliasCode,\n };\n }\n }\n\n // Handle additionalProperties (dictionary)\n const additionalProperties = schemaObj['additionalProperties'];\n if (additionalProperties && !properties) {\n const safeModelName = toPascalCase(toValidIdentifier(modelName));\n\n const dictCode = [\n `${spaces}/**`,\n `${spaces} * Dictionary/Record type: ${safeModelName}`,\n description ? `${spaces} * ${description}` : null,\n `${spaces} * Use as: Record<string, unknown> - access via record[key]`,\n `${spaces} */`,\n `${spaces}export const ${safeModelName} = ScalarTypeEnum.JSONObject();`,\n ]\n .filter((line) => line !== null)\n .join('\\n');\n\n return {\n name: safeModelName,\n description,\n fields: [],\n code: dictCode,\n };\n }\n\n if (!properties) {\n const safeModelName = toPascalCase(toValidIdentifier(modelName));\n const emptyModelCode = [\n `${spaces}export const ${safeModelName} = defineSchemaModel({`,\n `${spaces} name: '${safeModelName}',`,\n description\n ? `${spaces} description: ${JSON.stringify(description)},`\n : null,\n `${spaces} fields: {},`,\n `${spaces}});`,\n ]\n .filter((line) => line !== null)\n .join('\\n');\n\n return {\n name: safeModelName,\n description,\n fields: [],\n code: emptyModelCode,\n };\n }\n\n // Generate fields\n const safeModelName = toPascalCase(toValidIdentifier(modelName));\n for (const [propName, propSchema] of Object.entries(properties)) {\n const isRequired = required.includes(propName);\n fields.push(\n this.convertField(propSchema, propName, isRequired, safeModelName)\n );\n }\n\n // Generate code\n const lines: string[] = [];\n\n // Prepend nested models\n for (const field of fields) {\n if (field.nestedModel) {\n lines.push(field.nestedModel.code);\n lines.push('');\n }\n }\n\n // Model definition\n lines.push(`${spaces}export const ${safeModelName} = defineSchemaModel({`);\n lines.push(`${spaces} name: '${safeModelName}',`);\n if (description) {\n lines.push(`${spaces} description: ${JSON.stringify(description)},`);\n }\n lines.push(`${spaces} fields: {`);\n\n for (const field of fields) {\n const fieldLines = this.generateFieldCodeHelper(field, indent + 2);\n lines.push(fieldLines);\n }\n\n lines.push(`${spaces} },`);\n lines.push(`${spaces}});`);\n\n return {\n name: safeModelName,\n description,\n fields,\n code: lines.join('\\n'),\n imports: [],\n };\n }\n\n private convertField(\n schema: OpenApiSchema,\n fieldName: string,\n required: boolean,\n parentName?: string\n ): SchemaField {\n const type = jsonSchemaToType(schema, fieldName);\n const scalarType = getScalarType(schema);\n\n let enumValues: string[] | undefined;\n let nestedModel: GeneratedModel | undefined;\n\n if (!isReference(schema)) {\n const schemaObj = schema as Record<string, unknown>;\n const enumArr = schemaObj['enum'] as unknown[] | undefined;\n if (enumArr) {\n enumValues = enumArr.map(String);\n }\n\n // Handle nested objects\n if (\n schemaObj['type'] === 'object' &&\n !scalarType &&\n schemaObj['properties'] &&\n !enumValues\n ) {\n const nestedName =\n (parentName ? parentName : '') + toPascalCase(fieldName);\n nestedModel = this.generateContractSpecSchema(schema, nestedName);\n\n type.type = nestedModel.name;\n type.isReference = true;\n }\n }\n\n return {\n name: fieldName,\n type: {\n ...type,\n optional: !required || type.optional,\n description: !isReference(schema)\n ? ((schema as Record<string, unknown>)['description'] as string)\n : undefined,\n },\n scalarType,\n enumValues,\n nestedModel,\n };\n }\n\n private generateFieldCodeHelper(field: SchemaField, indent: number): string {\n const spaces = ' '.repeat(indent);\n const lines: string[] = [];\n\n const isIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(field.name);\n const safeKey = isIdentifier ? field.name : `'${field.name}'`;\n lines.push(`${spaces}${safeKey}: {`);\n\n if (field.enumValues) {\n const enumName = toPascalCase(field.name) + 'Enum';\n lines.push(\n `${spaces} type: new EnumType('${enumName}', [${field.enumValues.map((v) => `'${v}'`).join(', ')}]),`\n );\n } else if (field.scalarType) {\n lines.push(`${spaces} type: ${field.scalarType}(),`);\n } else if (field.nestedModel) {\n lines.push(`${spaces} type: ${field.nestedModel.name},`);\n } else if (field.type.primitive) {\n const fallbackScalar =\n field.type.type === 'number'\n ? 'ScalarTypeEnum.Float_unsecure'\n : field.type.type === 'boolean'\n ? 'ScalarTypeEnum.Boolean_unsecure'\n : 'ScalarTypeEnum.String_unsecure';\n lines.push(`${spaces} type: ${fallbackScalar}(),`);\n } else if (field.type.isReference) {\n lines.push(`${spaces} type: ${field.type.type},`);\n } else {\n lines.push(\n `${spaces} type: ScalarTypeEnum.JSONObject(), // TODO: Define nested model for ${field.type.type}`\n );\n }\n\n lines.push(`${spaces} isOptional: ${field.type.optional},`);\n\n if (field.type.array) {\n lines.push(`${spaces} isArray: true,`);\n }\n\n lines.push(`${spaces}},`);\n\n return lines.join('\\n');\n }\n}\n\n// ============================================================================\n// Zod Generator\n// ============================================================================\n\nexport class ZodSchemaGenerator implements SchemaGenerator {\n format: SchemaFormat = 'zod';\n config?: ResolvedContractsrcConfig;\n\n constructor(config?: ResolvedContractsrcConfig) {\n this.config = config;\n }\n\n generateModel(\n schema: OpenApiSchema,\n name: string,\n options?: { description?: string }\n ): GeneratedCode {\n const schemaObj = schema as Record<string, unknown>;\n const properties = schemaObj['properties'] as\n | Record<string, OpenApiSchema>\n | undefined;\n const _required = (schemaObj['required'] as string[]) ?? [];\n const description = options?.description ?? schemaObj['description'];\n\n const lines: string[] = [];\n\n if (description) {\n lines.push(`/**`);\n lines.push(` * ${description}`);\n lines.push(` */`);\n }\n\n // Generate Zod Schema\n const schemaName = `${name}Schema`;\n let schemaCode;\n\n if (properties) {\n schemaCode = this.generateZodObject(schemaObj);\n } else {\n schemaCode = 'z.object({})';\n }\n\n lines.push(`export const ${schemaName} = ${schemaCode};`);\n lines.push(``);\n\n // Generate ZodSchemaType wrapper for ContractSpec compatibility\n lines.push(\n `export const ${name} = new ZodSchemaType(${schemaName}, { name: '${name}', description: ${JSON.stringify(description)} });`\n );\n lines.push(``);\n\n // Generate Type\n lines.push(`export type ${name} = z.infer<typeof ${schemaName}>;`);\n\n // Dependencies?\n // Zod generator doesn't currently resolve references recursively or import them\n // This is a limitation: if prop is ref, use z.lazy(() => RefSchema) or similar?\n // For now assuming shallow/primitive or using z.unknown/record for complex stuff\n // Or if Contracts-transformers logic for references is ported.\n // Simplifying: Zod generator relies on primitive mapping for now.\n\n return {\n code: lines.join('\\n'),\n fileName: toKebabCase(name) + '.ts',\n imports: this.getBaseImports(), // Todo: Add dependency imports if references used\n name: name,\n };\n }\n\n generateField(\n schema: OpenApiSchema,\n _fieldName: string,\n required: boolean\n ): GeneratedFieldCode {\n const schemaObj = schema as Record<string, unknown>;\n const type = schemaObj['type'] as string | undefined;\n const format = schemaObj['format'] as string | undefined;\n const nullable = schemaObj['nullable'] as boolean | undefined;\n\n let zodType: string;\n\n if (type === 'object' && schemaObj['properties']) {\n zodType = this.generateZodObject(schemaObj);\n } else {\n zodType = this.mapTypeToZod(type, format);\n\n if (schemaObj['enum']) {\n const enumValues = schemaObj['enum'] as string[];\n zodType = `z.enum([${enumValues.map((v) => `'${v}'`).join(', ')}])`;\n }\n\n if (type === 'array') {\n const items = schemaObj['items'] as OpenApiSchema | undefined;\n if (items) {\n const itemField = this.generateField(items, 'item', true);\n zodType = `z.array(${itemField.code.replace('.optional()', '')})`;\n } else {\n zodType = 'z.array(z.unknown())';\n }\n }\n }\n\n // Add constraints\n if (type === 'string') {\n if (schemaObj['minLength'] !== undefined)\n zodType += `.min(${schemaObj['minLength']})`;\n if (schemaObj['maxLength'] !== undefined)\n zodType += `.max(${schemaObj['maxLength']})`;\n if (schemaObj['pattern'] !== undefined)\n zodType += `.regex(/${schemaObj['pattern']}/)`;\n } else if (type === 'integer' || type === 'number') {\n if (schemaObj['minimum'] !== undefined) {\n zodType +=\n schemaObj['exclusiveMinimum'] === true\n ? `.gt(${schemaObj['minimum']})`\n : `.min(${schemaObj['minimum']})`;\n } else if (typeof schemaObj['exclusiveMinimum'] === 'number') {\n zodType += `.gt(${schemaObj['exclusiveMinimum']})`;\n }\n\n if (schemaObj['maximum'] !== undefined) {\n zodType +=\n schemaObj['exclusiveMaximum'] === true\n ? `.lt(${schemaObj['maximum']})`\n : `.max(${schemaObj['maximum']})`;\n } else if (typeof schemaObj['exclusiveMaximum'] === 'number') {\n zodType += `.lt(${schemaObj['exclusiveMaximum']})`;\n }\n\n if (schemaObj['multipleOf'] !== undefined) {\n zodType += `.step(${schemaObj['multipleOf']})`;\n }\n } else if (type === 'array') {\n if (schemaObj['minItems'] !== undefined)\n zodType += `.min(${schemaObj['minItems']})`;\n if (schemaObj['maxItems'] !== undefined)\n zodType += `.max(${schemaObj['maxItems']})`;\n }\n\n if (schemaObj['default'] !== undefined) {\n zodType += `.default(${JSON.stringify(schemaObj['default'])})`;\n }\n\n if (!required || nullable) {\n zodType = `${zodType}.optional()`;\n }\n\n return {\n code: zodType,\n typeRef: type ?? 'unknown',\n isOptional: !required || Boolean(nullable),\n isArray: type === 'array',\n };\n }\n\n getBaseImports(): string[] {\n return [\n \"import * as z from 'zod';\",\n \"import { ZodSchemaType } from '@contractspec/lib.schema';\",\n ];\n }\n\n private generateZodObject(schemaObj: Record<string, unknown>): string {\n const required = (schemaObj['required'] as string[]) ?? [];\n const properties = schemaObj['properties'] as Record<string, OpenApiSchema>;\n const lines: string[] = ['z.object({'];\n\n for (const [propName, propSchema] of Object.entries(properties)) {\n const isRequired = required.includes(propName);\n const field = this.generateField(propSchema, propName, isRequired);\n // If name is not a valid identifier, quote it\n const safeName = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(propName)\n ? propName\n : `'${propName}'`;\n\n lines.push(` ${safeName}: ${field.code},`);\n }\n\n lines.push('})');\n return lines.join('\\n');\n }\n\n private mapTypeToZod(type?: string, format?: string): string {\n if (format === 'date-time') return 'z.string().datetime()';\n if (format === 'date') return 'z.string().date()';\n if (format === 'email') return 'z.string().email()';\n if (format === 'uri' || format === 'url') return 'z.string().url()';\n if (format === 'uuid') return 'z.string().uuid()';\n\n switch (type) {\n case 'string':\n return 'z.string()';\n case 'integer':\n return 'z.number().int()';\n case 'number':\n return 'z.number()';\n case 'boolean':\n return 'z.boolean()';\n case 'object':\n return 'z.record(z.string(), z.unknown())';\n case 'null':\n return 'z.null()';\n default:\n return 'z.unknown()';\n }\n }\n}\n\n// ============================================================================\n// JSON Schema Generator\n// ============================================================================\n\nexport class JsonSchemaGenerator implements SchemaGenerator {\n format: SchemaFormat = 'json-schema';\n config?: ResolvedContractsrcConfig;\n\n constructor(config?: ResolvedContractsrcConfig) {\n this.config = config;\n }\n\n generateModel(\n schema: OpenApiSchema,\n name: string,\n options?: { description?: string }\n ): GeneratedCode {\n const schemaObj = schema as Record<string, unknown>;\n const description = options?.description ?? schemaObj['description'];\n\n // Create a clean JSON Schema object\n const jsonSchema: Record<string, unknown> = {\n $schema: 'https://json-schema.org/draft/2020-12/schema',\n title: name,\n ...schemaObj,\n };\n\n if (description) {\n jsonSchema['description'] = description;\n }\n\n const lines: string[] = [];\n lines.push(`/**`);\n lines.push(` * JSON Schema: ${name}`);\n if (description) {\n lines.push(` * ${description}`);\n }\n lines.push(` */`);\n\n const schemaName = `${name}Schema`;\n lines.push(\n `export const ${schemaName} = ${JSON.stringify(jsonSchema, null, 2)} as const;`\n );\n lines.push(``);\n\n // Generate wrapper\n lines.push(`export const ${name} = new JsonSchemaType(${schemaName});`);\n lines.push(``);\n\n // Type derived from JsonSchemaType or similar?\n // Actually JsonSchemaType doesn't strictly infer TS type from JSON schema at compile time easily without other tools.\n // For now, export type as unknown or rely on library.\n lines.push(\n `export type ${name} = unknown; // JSON Schema type inference not fully supported`\n );\n\n return {\n code: lines.join('\\n'),\n fileName: toKebabCase(name) + '.ts',\n imports: this.getBaseImports(), // dependency imports?\n name: name,\n };\n }\n\n generateField(\n schema: OpenApiSchema,\n _fieldName: string,\n required: boolean\n ): GeneratedFieldCode {\n const schemaObj = schema as Record<string, unknown>;\n const type = schemaObj['type'] as string | undefined;\n const nullable = schemaObj['nullable'] as boolean | undefined;\n\n return {\n code: JSON.stringify(schemaObj),\n typeRef: type ?? 'unknown',\n isOptional: !required || Boolean(nullable),\n isArray: type === 'array',\n };\n }\n\n getBaseImports(): string[] {\n return [\"import { JsonSchemaType } from '@contractspec/lib.schema';\"];\n }\n}\n\n// ============================================================================\n// GraphQL Generator\n// ============================================================================\n\nexport class GraphQLSchemaGenerator implements SchemaGenerator {\n format: SchemaFormat = 'graphql';\n config?: ResolvedContractsrcConfig;\n\n constructor(config?: ResolvedContractsrcConfig) {\n this.config = config;\n }\n\n generateModel(\n schema: OpenApiSchema,\n name: string,\n options?: { description?: string }\n ): GeneratedCode {\n const schemaObj = schema as Record<string, unknown>;\n const properties = schemaObj['properties'] as\n | Record<string, OpenApiSchema>\n | undefined;\n const required = (schemaObj['required'] as string[]) ?? [];\n const description = options?.description ?? schemaObj['description'];\n\n const lines: string[] = [];\n\n if (description) {\n lines.push(`\"\"\"${description}\"\"\"`);\n }\n\n lines.push(`type ${name} {`);\n\n if (properties) {\n for (const [propName, propSchema] of Object.entries(properties)) {\n const isRequired = required.includes(propName);\n const field = this.generateField(propSchema, propName, isRequired);\n const nullMarker = isRequired ? '!' : '';\n lines.push(` ${propName}: ${field.typeRef}${nullMarker}`);\n }\n }\n\n lines.push(`}`);\n\n // Also generate SDL as a string constant\n const sdl = lines.join('\\n');\n const tsLines: string[] = [];\n tsLines.push(`/**`);\n tsLines.push(` * GraphQL type definition: ${name}`);\n tsLines.push(` */`);\n tsLines.push(`export const ${name}TypeDef = \\`${sdl}\\`;`);\n tsLines.push(``);\n tsLines.push(\n `export const ${name} = new GraphQLSchemaType(${name}TypeDef, '${name}');`\n );\n\n return {\n code: tsLines.join('\\n'),\n fileName: toKebabCase(name) + '.ts',\n imports: this.getBaseImports(),\n name: name,\n };\n }\n\n generateField(\n schema: OpenApiSchema,\n _fieldName: string,\n required: boolean\n ): GeneratedFieldCode {\n const schemaObj = schema as Record<string, unknown>;\n const type = schemaObj['type'] as string | undefined;\n const format = schemaObj['format'] as string | undefined;\n const nullable = schemaObj['nullable'] as boolean | undefined;\n\n const gqlType = this.mapTypeToGraphQL(type, format);\n\n return {\n code: gqlType,\n typeRef: gqlType,\n isOptional: !required || Boolean(nullable),\n isArray: type === 'array',\n };\n }\n\n getBaseImports(): string[] {\n return [\"import { GraphQLSchemaType } from '@contractspec/lib.schema';\"];\n }\n\n private mapTypeToGraphQL(type?: string, format?: string): string {\n if (format === 'date-time') return 'DateTime';\n if (format === 'date') return 'Date';\n if (format === 'email') return 'String';\n if (format === 'uri' || format === 'url') return 'String';\n if (format === 'uuid') return 'ID';\n\n switch (type) {\n case 'string':\n return 'String';\n case 'integer':\n return 'Int';\n case 'number':\n return 'Float';\n case 'boolean':\n return 'Boolean';\n case 'object':\n return 'JSON';\n case 'array':\n return '[JSON]';\n default:\n return 'JSON';\n }\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","names":[],"sources":["../../src/openapi/types.ts"],"sourcesContent":[],"mappings":";;;;;;AAiDA;;AAEI,KA5BQ,cAAA,GA4BI,KAAA,GAAA,KAAA;;;;AAOJ,KA9BA,eAAA,GAAkB,SAAA,CAAU,QA8BlB,GA9B6B,WAAA,CAAY,QA8BzC;AAatB;AAKA;AAgBA;AAgBiB,KA3EL,gBAAA,GACR,SAAA,CAAU,eA0EsB,GAzEhC,WAAA,CAAY,eAyEoB;AAYpC;;;AAgBe,KAhGH,aAAA,GACR,SAAA,CAAU,YA+FC,GA9FX,WAAA,CAAY,YA8FD,GA7FX,SAAA,CAAU,eA6FC,GA5FX,WAAA,CAAY,eA4FD;;;;AAgBA,KAvGH,gBAAA,GACR,SAAA,CAAU,eAsGC,GArGX,WAAA,CAAY,eAqGD,GApGX,SAAA,CAAU,eAoGC,GAnGX,WAAA,CAAY,eAmGD;;;;AAmBE,KAjHL,UAAA,GAiHoB,KAAA,GAAA,MAI1B,GAAA,KAAA,GAAA,QAMI,GAAA,OAAa,GAAA,MAAA,GAAA,SAAA,GAAA,OAAA;AAQvB;;;AAYc,KAlIF,iBAAA,GAkIE,MAAA,GAAA,OAAA,GAAA,QAAA,GAAA,QAAA;;;;AAQJ,UArIO,aAAA,CAqIP;EAAW,GAAA,EAAA,MAAA;EAMJ,WAAA,CAAA,EAAW,MAAA;EAYX,SAAA,CAAA,EApJH,MAoJG,CAAA,MAAsB,EAAA;IAgBtB,OAAA,EAAA,MAAc;IAYd,IAAA,CAAA,EAAA,MAAA,EAAA;IAOL,WAAA,CAAA,EAAA,MAAA;EACY,CAAA,CAAA;;;;;AAqBP,UAhMA,oBAAA,CAgM0B;EAsB1B;EAUA,KAAA,CAAA,EAAA,MAAA;EAEN;EAGM,OAAA,CAAA,EAAA,MAAA;EACJ;EACE,WAAA,CAAA,EAAA,MAAA;EACK;EACR,OAAA,CAAA,EAjOA,aAiOA,EAAA;EACI;EACA,UAAA,CAAA,EAjOD,MAiOC,CAAA,MAAA,EAAA,OAAA,CAAA;;;;;UA3NC,mBAAA;;;;;;;;;;;UAYA,eAAA;;;;UAIP;;;;;;;;;;cAUI;;eAEC;;gBAEC;;gBAEA;;;;YAIJ;;;;aAIC;;aAIE;;;;;;aAOF;;;;;;;;;;;UAYI,eAAA;;;;MAIX;;;;;;UAMI;;;;;;;UAQO,WAAA;;YAEL;;WAED;;;;;;;;cAQG;;WAEH,eAAe;;WAEf;;;;UAID;;;;;UAMO,WAAA;;;;;;WAMN;;;;;UAMM,qBAAA,SAA8B;;;;;;;;;;;;;;;UAgB9B,aAAA,SAAsB;;;kBAGrB;;;;;;;;UASD,2BAAA;;;;;;;YAOL;SACH,eAAe;;aAEX,eAAe;;;;;;;;;;;;;;;;;;UAmBX,yBAAA,SAAkC;;;;;;;;;;;;;;;;;;;;;UAsBlC,qBAAA;;;;;;;;;UAUA,wBAAA;;WAEN;;;iBAGM;aACJ;eACE;oBACK;YACR;gBACI;gBACA;;YAEJ"}
1
+ {"version":3,"file":"types.d.ts","names":[],"sources":["../../src/openapi/types.ts"],"sourcesContent":[],"mappings":";;;;;AAcA;AAKA;AAOA;AACI,KAlBQ,cAAA,GAkBE,KAAA,GAAA,KAAA;;;;AAGiB,KAhBnB,eAAA,GAAkB,SAAA,CAAU,QAgBT,GAhBoB,WAAA,CAAY,QAgBhC;AAK/B;;;AAGI,KAnBQ,gBAAA,GACR,SAAA,CAAU,eAkBA,GAjBV,WAAA,CAAY,eAiBF;;;AAMd;AAaY,KA/BA,aAAA,GACR,SAAA,CAAU,YA8Be,GA7BzB,WAAA,CAAY,YA6Ba,GA5BzB,SAAA,CAAU,eA4Be,GA3BzB,WAAA,CAAY,eA2Ba;AAK7B;AAgBA;AAgBA;AAYiB,KAvEL,gBAAA,GACR,SAAA,CAAU,eAsEkB,GArE5B,WAAA,CAAY,eAqEgB,GApE5B,SAAA,CAAU,eAoEkB,GAnE5B,WAAA,CAAY,eAmEgB;;;;AAkBhB,KAhFJ,UAAA,GAgFI,KAAA,GAAA,MAAA,GAAA,KAAA,GAAA,QAAA,GAAA,OAAA,GAAA,MAAA,GAAA,SAAA,GAAA,OAAA;;;;AAUH,KA7ED,iBAAA,GA6EC,MAAA,GAAA,OAAA,GAAA,QAAA,GAAA,QAAA;;;AAuBb;AAkBiB,UAjHA,aAAA,CAiHW;EAEhB,GAAA,EAAA,MAAA;EAED,WAAA,CAAA,EAAA,MAAA;EAQG,SAAA,CAAA,EA1HA,MA0HA,CAAA,MAAA,EAAA;IAEY,OAAA,EAAA,MAAA;IAAf,IAAA,CAAA,EAAA,MAAA,EAAA;IAEA,WAAA,CAAA,EAAA,MAAA;EAID,CAAA,CAAA;;AAMV;AAYA;AAgBA;AAYiB,UAnKA,oBAAA,CAmK2B;EAOhC;EACY,KAAA,CAAA,EAAA,MAAA;EAAf;EAEmB,OAAA,CAAA,EAAA,MAAA;EAAf;EAAM,WAAA,CAAA,EAAA,MAAA;EAmBF;EAsBA,OAAA,CAAA,EA9ML,aA8MK,EAAqB;EAUrB;EAEN,UAAA,CAAA,EAxNI,MAwNJ,CAAA,MAAA,EAAA,OAAA,CAAA;;;;;AAOC,UAzNK,mBAAA,CAyNL;EACI;EACA,OAAA,CAAA,EAAA,MAAA;EAEJ;EAAqB,WAAA,CAAA,EAAA,OAAA;;;;;;;UAjNhB,eAAA;;;;UAIP;;;;;;;;;;cAUI;;eAEC;;gBAEC;;gBAEA;;;;YAIJ;;;;aAIC;;aAIE;;;;;;aAOF;;;;;;;;;;;UAYI,eAAA;;;;MAIX;;;;;;UAMI;;;;;;;UAQO,WAAA;;YAEL;;WAED;;;;;;;;cAQG;;WAEH,eAAe;;WAEf;;;;UAID;;;;;UAMO,WAAA;;;;;;WAMN;;;;;UAMM,qBAAA,SAA8B;;;;;;;;;;;;;;;UAgB9B,aAAA,SAAsB;;;kBAGrB;;;;;;;;UASD,2BAAA;;;;;;;YAOL;SACH,eAAe;;aAEX,eAAe;;;;;;;;;;;;;;;;;;UAmBX,yBAAA,SAAkC;;;;;;;;;;;;;;;;;;;;;UAsBlC,qBAAA;;;;;;;;;UAUA,wBAAA;;WAEN;;;iBAGM;aACJ;eACE;oBACK;YACR;gBACI;gBACA;;YAEJ"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contractspec/lib.contracts-transformers",
3
- "version": "1.46.2",
3
+ "version": "1.48.0",
4
4
  "description": "Contract format transformations: import/export between ContractSpec and external formats (OpenAPI, AsyncAPI, etc.)",
5
5
  "keywords": [
6
6
  "contractspec",
@@ -25,26 +25,24 @@
25
25
  "test": "bun test"
26
26
  },
27
27
  "dependencies": {
28
- "@contractspec/lib.contracts": "1.46.2",
29
- "@contractspec/lib.schema": "1.46.2",
28
+ "@contractspec/lib.contracts": "1.48.0",
29
+ "@contractspec/lib.schema": "1.48.0",
30
30
  "compare-versions": "^6.1.1",
31
31
  "openapi-types": "^12.1.3",
32
32
  "yaml": "^2.7.1",
33
- "zod": "^4.1.13"
33
+ "zod": "^4.3.5"
34
34
  },
35
35
  "devDependencies": {
36
- "@contractspec/tool.tsdown": "1.46.2",
37
- "@contractspec/tool.typescript": "1.46.2",
38
- "tsdown": "^0.18.3",
36
+ "@contractspec/tool.tsdown": "1.48.0",
37
+ "@contractspec/tool.typescript": "1.48.0",
38
+ "tsdown": "^0.19.0",
39
39
  "typescript": "^5.9.3"
40
40
  },
41
- "main": "./dist/index.js",
42
41
  "types": "./dist/index.d.ts",
43
42
  "files": [
44
43
  "dist",
45
44
  "README.md"
46
45
  ],
47
- "module": "./dist/index.js",
48
46
  "exports": {
49
47
  ".": "./dist/index.js",
50
48
  "./common": "./dist/common/index.js",