@kubb/core 5.0.0-alpha.4 → 5.0.0-alpha.41

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 (71) hide show
  1. package/dist/PluginDriver-BQwm8hDd.cjs +1729 -0
  2. package/dist/PluginDriver-BQwm8hDd.cjs.map +1 -0
  3. package/dist/PluginDriver-CgXFtmNP.js +1617 -0
  4. package/dist/PluginDriver-CgXFtmNP.js.map +1 -0
  5. package/dist/index.cjs +915 -1901
  6. package/dist/index.cjs.map +1 -1
  7. package/dist/index.d.ts +268 -264
  8. package/dist/index.js +894 -1863
  9. package/dist/index.js.map +1 -1
  10. package/dist/mocks.cjs +164 -0
  11. package/dist/mocks.cjs.map +1 -0
  12. package/dist/mocks.d.ts +74 -0
  13. package/dist/mocks.js +159 -0
  14. package/dist/mocks.js.map +1 -0
  15. package/dist/types-C6NCtNqM.d.ts +2151 -0
  16. package/package.json +11 -14
  17. package/src/FileManager.ts +131 -0
  18. package/src/FileProcessor.ts +84 -0
  19. package/src/Kubb.ts +174 -85
  20. package/src/PluginDriver.ts +941 -0
  21. package/src/constants.ts +33 -43
  22. package/src/createAdapter.ts +25 -0
  23. package/src/createKubb.ts +605 -0
  24. package/src/createPlugin.ts +31 -0
  25. package/src/createRenderer.ts +57 -0
  26. package/src/createStorage.ts +58 -0
  27. package/src/defineGenerator.ts +88 -100
  28. package/src/defineLogger.ts +13 -3
  29. package/src/defineParser.ts +45 -0
  30. package/src/definePlugin.ts +90 -7
  31. package/src/defineResolver.ts +453 -0
  32. package/src/devtools.ts +14 -14
  33. package/src/index.ts +12 -17
  34. package/src/mocks.ts +234 -0
  35. package/src/renderNode.ts +35 -0
  36. package/src/storages/fsStorage.ts +29 -9
  37. package/src/storages/memoryStorage.ts +2 -2
  38. package/src/types.ts +821 -152
  39. package/src/utils/TreeNode.ts +47 -9
  40. package/src/utils/diagnostics.ts +4 -1
  41. package/src/utils/executeStrategies.ts +16 -13
  42. package/src/utils/getBarrelFiles.ts +88 -15
  43. package/src/utils/isInputPath.ts +10 -0
  44. package/src/utils/packageJSON.ts +75 -0
  45. package/dist/chunk-ByKO4r7w.cjs +0 -38
  46. package/dist/hooks.cjs +0 -50
  47. package/dist/hooks.cjs.map +0 -1
  48. package/dist/hooks.d.ts +0 -49
  49. package/dist/hooks.js +0 -46
  50. package/dist/hooks.js.map +0 -1
  51. package/dist/types-Bbh1o0yW.d.ts +0 -1057
  52. package/src/BarrelManager.ts +0 -74
  53. package/src/PackageManager.ts +0 -180
  54. package/src/PluginManager.ts +0 -668
  55. package/src/PromiseManager.ts +0 -40
  56. package/src/build.ts +0 -420
  57. package/src/config.ts +0 -56
  58. package/src/defineAdapter.ts +0 -22
  59. package/src/defineStorage.ts +0 -56
  60. package/src/errors.ts +0 -1
  61. package/src/hooks/index.ts +0 -8
  62. package/src/hooks/useKubb.ts +0 -22
  63. package/src/hooks/useMode.ts +0 -11
  64. package/src/hooks/usePlugin.ts +0 -11
  65. package/src/hooks/usePluginManager.ts +0 -11
  66. package/src/utils/FunctionParams.ts +0 -155
  67. package/src/utils/formatters.ts +0 -56
  68. package/src/utils/getConfigs.ts +0 -30
  69. package/src/utils/getPlugins.ts +0 -23
  70. package/src/utils/linters.ts +0 -25
  71. package/src/utils/resolveOptions.ts +0 -93
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubb/core",
3
- "version": "5.0.0-alpha.4",
3
+ "version": "5.0.0-alpha.41",
4
4
  "description": "Core functionality for Kubb's plugin-based code generation system, providing the foundation for transforming OpenAPI specifications.",
5
5
  "keywords": [
6
6
  "typescript",
@@ -31,17 +31,17 @@
31
31
  "import": "./dist/index.js",
32
32
  "require": "./dist/index.cjs"
33
33
  },
34
- "./hooks": {
35
- "import": "./dist/hooks.js",
36
- "require": "./dist/hooks.cjs"
34
+ "./mocks": {
35
+ "import": "./dist/mocks.js",
36
+ "require": "./dist/mocks.cjs"
37
37
  },
38
38
  "./package.json": "./package.json"
39
39
  },
40
40
  "types": "./dist/index.d.ts",
41
41
  "typesVersions": {
42
42
  "*": {
43
- "hooks": [
44
- "./dist/hooks.d.ts"
43
+ "mocks": [
44
+ "./dist/mocks.d.ts"
45
45
  ]
46
46
  }
47
47
  },
@@ -64,14 +64,12 @@
64
64
  }
65
65
  ],
66
66
  "dependencies": {
67
- "@kubb/fabric-core": "0.13.3",
68
- "@kubb/react-fabric": "0.13.3",
69
- "empathic": "^2.0.0",
70
67
  "fflate": "^0.8.2",
71
- "remeda": "^2.33.6",
68
+ "remeda": "^2.33.7",
72
69
  "semver": "^7.7.4",
73
- "tinyexec": "^1.0.4",
74
- "@kubb/ast": "5.0.0-alpha.4"
70
+ "tinyexec": "^1.1.1",
71
+ "@kubb/ast": "5.0.0-alpha.41",
72
+ "@kubb/renderer-jsx": "5.0.0-alpha.41"
75
73
  },
76
74
  "devDependencies": {
77
75
  "@types/semver": "^7.7.1",
@@ -79,8 +77,7 @@
79
77
  "@internals/utils": "0.0.0"
80
78
  },
81
79
  "peerDependencies": {
82
- "@kubb/fabric-core": "0.13.3",
83
- "@kubb/react-fabric": "0.13.3"
80
+ "@kubb/renderer-jsx": "5.0.0-alpha.41"
84
81
  },
85
82
  "engines": {
86
83
  "node": ">=22"
@@ -0,0 +1,131 @@
1
+ import { trimExtName } from '@internals/utils'
2
+ import type { FileNode } from '@kubb/ast'
3
+ import { createFile } from '@kubb/ast'
4
+
5
+ function mergeFile<TMeta extends object = object>(a: FileNode<TMeta>, b: FileNode<TMeta>): FileNode<TMeta> {
6
+ return {
7
+ ...a,
8
+ sources: [...(a.sources || []), ...(b.sources || [])],
9
+ imports: [...(a.imports || []), ...(b.imports || [])],
10
+ exports: [...(a.exports || []), ...(b.exports || [])],
11
+ }
12
+ }
13
+
14
+ /**
15
+ * In-memory file store for generated files.
16
+ *
17
+ * Files with the same `path` are merged — sources, imports, and exports are concatenated.
18
+ * The `files` getter returns all stored files sorted by path length (shortest first).
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * import { FileManager } from '@kubb/core'
23
+ *
24
+ * const manager = new FileManager()
25
+ * manager.upsert(myFile)
26
+ * console.log(manager.files) // all stored files
27
+ * ```
28
+ */
29
+ export class FileManager {
30
+ readonly #cache = new Map<string, FileNode>()
31
+ #filesCache: Array<FileNode> | null = null
32
+
33
+ /**
34
+ * Adds one or more files. Files with the same path are merged — sources, imports,
35
+ * and exports from all calls with the same path are concatenated together.
36
+ */
37
+ add(...files: Array<FileNode>): Array<FileNode> {
38
+ const resolvedFiles: Array<FileNode> = []
39
+ const mergedFiles = new Map<string, FileNode>()
40
+
41
+ files.forEach((file) => {
42
+ const existing = mergedFiles.get(file.path)
43
+ if (existing) {
44
+ mergedFiles.set(file.path, mergeFile(existing, file))
45
+ } else {
46
+ mergedFiles.set(file.path, file)
47
+ }
48
+ })
49
+
50
+ for (const file of mergedFiles.values()) {
51
+ const resolvedFile = createFile(file)
52
+ this.#cache.set(resolvedFile.path, resolvedFile)
53
+ this.#filesCache = null
54
+ resolvedFiles.push(resolvedFile)
55
+ }
56
+
57
+ return resolvedFiles
58
+ }
59
+
60
+ /**
61
+ * Adds or merges one or more files.
62
+ * If a file with the same path already exists, its sources/imports/exports are merged together.
63
+ */
64
+ upsert(...files: Array<FileNode>): Array<FileNode> {
65
+ const resolvedFiles: Array<FileNode> = []
66
+ const mergedFiles = new Map<string, FileNode>()
67
+
68
+ files.forEach((file) => {
69
+ const existing = mergedFiles.get(file.path)
70
+ if (existing) {
71
+ mergedFiles.set(file.path, mergeFile(existing, file))
72
+ } else {
73
+ mergedFiles.set(file.path, file)
74
+ }
75
+ })
76
+
77
+ for (const file of mergedFiles.values()) {
78
+ const existing = this.#cache.get(file.path)
79
+ const merged = existing ? mergeFile(existing, file) : file
80
+ const resolvedFile = createFile(merged)
81
+ this.#cache.set(resolvedFile.path, resolvedFile)
82
+ this.#filesCache = null
83
+ resolvedFiles.push(resolvedFile)
84
+ }
85
+
86
+ return resolvedFiles
87
+ }
88
+
89
+ getByPath(path: string): FileNode | null {
90
+ return this.#cache.get(path) ?? null
91
+ }
92
+
93
+ deleteByPath(path: string): void {
94
+ this.#cache.delete(path)
95
+ this.#filesCache = null
96
+ }
97
+
98
+ clear(): void {
99
+ this.#cache.clear()
100
+ this.#filesCache = null
101
+ }
102
+
103
+ /**
104
+ * All stored files, sorted by path length (shorter paths first).
105
+ * Barrel/index files (e.g. index.ts) are sorted last within each length bucket.
106
+ */
107
+ get files(): Array<FileNode> {
108
+ if (this.#filesCache) {
109
+ return this.#filesCache
110
+ }
111
+
112
+ const keys = [...this.#cache.keys()].sort((a, b) => {
113
+ if (a.length !== b.length) return a.length - b.length
114
+ const aIsIndex = trimExtName(a).endsWith('index')
115
+ const bIsIndex = trimExtName(b).endsWith('index')
116
+ if (aIsIndex !== bIsIndex) return aIsIndex ? 1 : -1
117
+ return 0
118
+ })
119
+
120
+ const files: Array<FileNode> = []
121
+ for (const key of keys) {
122
+ const file = this.#cache.get(key)
123
+ if (file) {
124
+ files.push(file)
125
+ }
126
+ }
127
+
128
+ this.#filesCache = files
129
+ return files
130
+ }
131
+ }
@@ -0,0 +1,84 @@
1
+ import type { CodeNode, FileNode } from '@kubb/ast'
2
+ import { extractStringsFromNodes } from '@kubb/ast'
3
+ import pLimit from 'p-limit'
4
+ import { PARALLEL_CONCURRENCY_LIMIT } from './constants.ts'
5
+ import type { Parser } from './defineParser.ts'
6
+
7
+ type ParseOptions = {
8
+ parsers?: Map<FileNode['extname'], Parser>
9
+ extension?: Record<FileNode['extname'], FileNode['extname'] | ''>
10
+ }
11
+
12
+ type RunOptions = ParseOptions & {
13
+ /**
14
+ * @default 'sequential'
15
+ */
16
+ mode?: 'sequential' | 'parallel'
17
+ onStart?: (files: Array<FileNode>) => Promise<void> | void
18
+ onEnd?: (files: Array<FileNode>) => Promise<void> | void
19
+ onUpdate?: (params: { file: FileNode; source?: string; processed: number; total: number; percentage: number }) => Promise<void> | void
20
+ }
21
+
22
+ function joinSources(file: FileNode): string {
23
+ return file.sources
24
+ .map((item) => extractStringsFromNodes(item.nodes as Array<CodeNode>))
25
+ .filter(Boolean)
26
+ .join('\n\n')
27
+ }
28
+
29
+ /**
30
+ * Converts a single file to a string using the registered parsers.
31
+ * Falls back to joining source values when no matching parser is found.
32
+ */
33
+ export class FileProcessor {
34
+ readonly #limit = pLimit(PARALLEL_CONCURRENCY_LIMIT)
35
+
36
+ async parse(file: FileNode, { parsers, extension }: ParseOptions = {}): Promise<string> {
37
+ const parseExtName = extension?.[file.extname] || undefined
38
+
39
+ if (!parsers || !file.extname) {
40
+ return joinSources(file)
41
+ }
42
+
43
+ const parser = parsers.get(file.extname)
44
+
45
+ if (!parser) {
46
+ return joinSources(file)
47
+ }
48
+
49
+ return parser.parse(file, { extname: parseExtName })
50
+ }
51
+
52
+ async run(files: Array<FileNode>, { parsers, mode = 'sequential', extension, onStart, onEnd, onUpdate }: RunOptions = {}): Promise<Array<FileNode>> {
53
+ await onStart?.(files)
54
+
55
+ const total = files.length
56
+ let processed = 0
57
+
58
+ const processOne = async (file: FileNode) => {
59
+ const source = await this.parse(file, { extension, parsers })
60
+ const currentProcessed = ++processed
61
+ const percentage = (currentProcessed / total) * 100
62
+
63
+ await onUpdate?.({
64
+ file,
65
+ source,
66
+ processed: currentProcessed,
67
+ percentage,
68
+ total,
69
+ })
70
+ }
71
+
72
+ if (mode === 'sequential') {
73
+ for (const file of files) {
74
+ await processOne(file)
75
+ }
76
+ } else {
77
+ await Promise.all(files.map((file) => this.#limit(() => processOne(file))))
78
+ }
79
+
80
+ await onEnd?.(files)
81
+
82
+ return files
83
+ }
84
+ }