@kubb/core 5.0.0-alpha.6 → 5.0.0-alpha.60

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 (72) hide show
  1. package/README.md +3 -2
  2. package/dist/PluginDriver-Bc0HQM8V.js +948 -0
  3. package/dist/PluginDriver-Bc0HQM8V.js.map +1 -0
  4. package/dist/PluginDriver-Dyl2fwfQ.cjs +1039 -0
  5. package/dist/PluginDriver-Dyl2fwfQ.cjs.map +1 -0
  6. package/dist/index.cjs +691 -1798
  7. package/dist/index.cjs.map +1 -1
  8. package/dist/index.d.ts +279 -265
  9. package/dist/index.js +678 -1765
  10. package/dist/index.js.map +1 -1
  11. package/dist/mocks.cjs +138 -0
  12. package/dist/mocks.cjs.map +1 -0
  13. package/dist/mocks.d.ts +74 -0
  14. package/dist/mocks.js +133 -0
  15. package/dist/mocks.js.map +1 -0
  16. package/dist/types-i0b4_23K.d.ts +1903 -0
  17. package/package.json +51 -57
  18. package/src/FileManager.ts +110 -0
  19. package/src/FileProcessor.ts +86 -0
  20. package/src/Kubb.ts +205 -130
  21. package/src/PluginDriver.ts +424 -0
  22. package/src/constants.ts +20 -47
  23. package/src/createAdapter.ts +25 -0
  24. package/src/createKubb.ts +527 -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/defineMiddleware.ts +59 -0
  30. package/src/defineParser.ts +45 -0
  31. package/src/definePlugin.ts +78 -7
  32. package/src/defineResolver.ts +521 -0
  33. package/src/devtools.ts +14 -14
  34. package/src/index.ts +13 -17
  35. package/src/mocks.ts +171 -0
  36. package/src/renderNode.ts +35 -0
  37. package/src/storages/fsStorage.ts +40 -11
  38. package/src/storages/memoryStorage.ts +4 -3
  39. package/src/types.ts +738 -218
  40. package/src/utils/diagnostics.ts +4 -1
  41. package/src/utils/isInputPath.ts +10 -0
  42. package/src/utils/packageJSON.ts +99 -0
  43. package/dist/PluginManager-vZodFEMe.d.ts +0 -1056
  44. package/dist/chunk-ByKO4r7w.cjs +0 -38
  45. package/dist/hooks.cjs +0 -60
  46. package/dist/hooks.cjs.map +0 -1
  47. package/dist/hooks.d.ts +0 -64
  48. package/dist/hooks.js +0 -56
  49. package/dist/hooks.js.map +0 -1
  50. package/src/BarrelManager.ts +0 -74
  51. package/src/PackageManager.ts +0 -180
  52. package/src/PluginManager.ts +0 -667
  53. package/src/PromiseManager.ts +0 -40
  54. package/src/build.ts +0 -419
  55. package/src/config.ts +0 -56
  56. package/src/defineAdapter.ts +0 -22
  57. package/src/defineStorage.ts +0 -56
  58. package/src/errors.ts +0 -1
  59. package/src/hooks/index.ts +0 -4
  60. package/src/hooks/useKubb.ts +0 -55
  61. package/src/hooks/useMode.ts +0 -11
  62. package/src/hooks/usePlugin.ts +0 -11
  63. package/src/hooks/usePluginManager.ts +0 -11
  64. package/src/utils/FunctionParams.ts +0 -155
  65. package/src/utils/TreeNode.ts +0 -215
  66. package/src/utils/executeStrategies.ts +0 -81
  67. package/src/utils/formatters.ts +0 -56
  68. package/src/utils/getBarrelFiles.ts +0 -79
  69. package/src/utils/getConfigs.ts +0 -30
  70. package/src/utils/getPlugins.ts +0 -23
  71. package/src/utils/linters.ts +0 -25
  72. package/src/utils/resolveOptions.ts +0 -93
package/package.json CHANGED
@@ -1,50 +1,29 @@
1
1
  {
2
2
  "name": "@kubb/core",
3
- "version": "5.0.0-alpha.6",
3
+ "version": "5.0.0-alpha.60",
4
4
  "description": "Core functionality for Kubb's plugin-based code generation system, providing the foundation for transforming OpenAPI specifications.",
5
5
  "keywords": [
6
- "typescript",
7
- "plugins",
8
- "plugin-system",
9
- "plugin-framework",
6
+ "ast",
10
7
  "code-generator",
11
8
  "codegen",
12
- "ast",
9
+ "core-library",
13
10
  "file-system",
11
+ "kubb",
12
+ "oas",
14
13
  "openapi",
14
+ "plugin-framework",
15
+ "plugin-system",
16
+ "plugins",
15
17
  "swagger",
16
- "oas",
17
- "core-library",
18
- "kubb"
18
+ "typescript"
19
19
  ],
20
+ "license": "MIT",
21
+ "author": "stijnvanhulle",
20
22
  "repository": {
21
23
  "type": "git",
22
24
  "url": "git+https://github.com/kubb-labs/kubb.git",
23
25
  "directory": "packages/core"
24
26
  },
25
- "license": "MIT",
26
- "author": "stijnvanhulle",
27
- "sideEffects": false,
28
- "type": "module",
29
- "exports": {
30
- ".": {
31
- "import": "./dist/index.js",
32
- "require": "./dist/index.cjs"
33
- },
34
- "./hooks": {
35
- "import": "./dist/hooks.js",
36
- "require": "./dist/hooks.cjs"
37
- },
38
- "./package.json": "./package.json"
39
- },
40
- "types": "./dist/index.d.ts",
41
- "typesVersions": {
42
- "*": {
43
- "hooks": [
44
- "./dist/hooks.d.ts"
45
- ]
46
- }
47
- },
48
27
  "files": [
49
28
  "src",
50
29
  "schemas",
@@ -56,41 +35,56 @@
56
35
  "!/**/__tests__/**",
57
36
  "!/**/__snapshots__/**"
58
37
  ],
59
- "size-limit": [
60
- {
61
- "path": "./dist/*.js",
62
- "limit": "510 KiB",
63
- "gzip": true
38
+ "type": "module",
39
+ "sideEffects": false,
40
+ "main": "./dist/index.cjs",
41
+ "module": "./dist/index.js",
42
+ "types": "./dist/index.d.ts",
43
+ "typesVersions": {
44
+ "*": {
45
+ "mocks": [
46
+ "./dist/mocks.d.ts"
47
+ ]
64
48
  }
65
- ],
49
+ },
50
+ "exports": {
51
+ ".": {
52
+ "import": "./dist/index.js",
53
+ "require": "./dist/index.cjs"
54
+ },
55
+ "./mocks": {
56
+ "import": "./dist/mocks.js",
57
+ "require": "./dist/mocks.cjs"
58
+ },
59
+ "./package.json": "./package.json"
60
+ },
61
+ "publishConfig": {
62
+ "access": "public",
63
+ "registry": "https://registry.npmjs.org/"
64
+ },
66
65
  "dependencies": {
67
- "@kubb/fabric-core": "0.14.0",
68
- "@kubb/react-fabric": "0.14.0",
69
- "empathic": "^2.0.0",
70
66
  "fflate": "^0.8.2",
71
- "remeda": "^2.33.6",
72
- "semver": "^7.7.4",
73
- "tinyexec": "^1.0.4",
74
- "@kubb/ast": "5.0.0-alpha.6"
67
+ "tinyexec": "^1.1.1",
68
+ "@kubb/ast": "5.0.0-alpha.60"
75
69
  },
76
70
  "devDependencies": {
77
- "@types/semver": "^7.7.1",
78
71
  "p-limit": "^7.3.0",
79
- "@internals/utils": "0.0.0"
72
+ "@internals/utils": "0.0.0",
73
+ "@kubb/renderer-jsx": "5.0.0-alpha.60"
80
74
  },
81
75
  "peerDependencies": {
82
- "@kubb/fabric-core": "0.14.0",
83
- "@kubb/react-fabric": "0.14.0"
76
+ "@kubb/renderer-jsx": "5.0.0-alpha.60"
84
77
  },
78
+ "size-limit": [
79
+ {
80
+ "path": "./dist/*.js",
81
+ "limit": "510 KiB",
82
+ "gzip": true
83
+ }
84
+ ],
85
85
  "engines": {
86
86
  "node": ">=22"
87
87
  },
88
- "publishConfig": {
89
- "access": "public",
90
- "registry": "https://registry.npmjs.org/"
91
- },
92
- "main": "./dist/index.cjs",
93
- "module": "./dist/index.js",
94
88
  "inlinedDependencies": {
95
89
  "p-limit": "7.3.0",
96
90
  "yocto-queue": "1.2.2"
@@ -98,8 +92,8 @@
98
92
  "scripts": {
99
93
  "build": "tsdown && size-limit",
100
94
  "clean": "npx rimraf ./dist",
101
- "lint": "bun biome lint .",
102
- "lint:fix": "bun biome lint --fix --unsafe .",
95
+ "lint": "oxlint .",
96
+ "lint:fix": "oxlint --fix .",
103
97
  "release": "pnpm publish --no-git-check",
104
98
  "release:canary": "bash ../../.github/canary.sh && node ../../scripts/build.js canary && pnpm publish --no-git-check",
105
99
  "start": "tsdown --watch",
@@ -0,0 +1,110 @@
1
+ import type { FileNode } from '@kubb/ast'
2
+ import { createFile } from '@kubb/ast'
3
+
4
+ function mergeFile<TMeta extends object = object>(a: FileNode<TMeta>, b: FileNode<TMeta>): FileNode<TMeta> {
5
+ return {
6
+ ...a,
7
+ sources: [...(a.sources || []), ...(b.sources || [])],
8
+ imports: [...(a.imports || []), ...(b.imports || [])],
9
+ exports: [...(a.exports || []), ...(b.exports || [])],
10
+ }
11
+ }
12
+
13
+ /**
14
+ * Collapses a list of files so that duplicates sharing the same `path` are merged
15
+ * in arrival order. Keeps the original order of first occurrence.
16
+ */
17
+ function mergeFilesByPath(files: ReadonlyArray<FileNode>): Map<string, FileNode> {
18
+ const merged = new Map<string, FileNode>()
19
+ for (const file of files) {
20
+ const existing = merged.get(file.path)
21
+ merged.set(file.path, existing ? mergeFile(existing, file) : file)
22
+ }
23
+ return merged
24
+ }
25
+
26
+ /**
27
+ * In-memory file store for generated files.
28
+ *
29
+ * Files with the same `path` are merged — sources, imports, and exports are concatenated.
30
+ * The `files` getter returns all stored files sorted by path length (shortest first).
31
+ *
32
+ * @example
33
+ * ```ts
34
+ * import { FileManager } from '@kubb/core'
35
+ *
36
+ * const manager = new FileManager()
37
+ * manager.upsert(myFile)
38
+ * console.log(manager.files) // all stored files
39
+ * ```
40
+ */
41
+ export class FileManager {
42
+ readonly #cache = new Map<string, FileNode>()
43
+ #filesCache: Array<FileNode> | null = null
44
+
45
+ /**
46
+ * Adds one or more files. Incoming files with the same path are merged
47
+ * (sources/imports/exports concatenated), but existing cache entries are
48
+ * replaced — use {@link upsert} when you want to merge into the cache too.
49
+ */
50
+ add(...files: Array<FileNode>): Array<FileNode> {
51
+ return this.#store(files, false)
52
+ }
53
+
54
+ /**
55
+ * Adds or merges one or more files.
56
+ * If a file with the same path already exists in the cache, its
57
+ * sources/imports/exports are merged into the incoming file.
58
+ */
59
+ upsert(...files: Array<FileNode>): Array<FileNode> {
60
+ return this.#store(files, true)
61
+ }
62
+
63
+ #store(files: ReadonlyArray<FileNode>, mergeExisting: boolean): Array<FileNode> {
64
+ const resolvedFiles: Array<FileNode> = []
65
+ for (const file of mergeFilesByPath(files).values()) {
66
+ const existing = mergeExisting ? this.#cache.get(file.path) : undefined
67
+ const resolvedFile = createFile(existing ? mergeFile(existing, file) : file)
68
+ this.#cache.set(resolvedFile.path, resolvedFile)
69
+ resolvedFiles.push(resolvedFile)
70
+ }
71
+ this.#filesCache = null
72
+ return resolvedFiles
73
+ }
74
+
75
+ getByPath(path: string): FileNode | null {
76
+ return this.#cache.get(path) ?? null
77
+ }
78
+
79
+ deleteByPath(path: string): void {
80
+ this.#cache.delete(path)
81
+ this.#filesCache = null
82
+ }
83
+
84
+ clear(): void {
85
+ this.#cache.clear()
86
+ this.#filesCache = null
87
+ }
88
+
89
+ /**
90
+ * All stored files, sorted by path length (shorter paths first).
91
+ */
92
+ get files(): Array<FileNode> {
93
+ if (this.#filesCache) {
94
+ return this.#filesCache
95
+ }
96
+
97
+ this.#filesCache = [...this.#cache.values()].sort((a, b) => {
98
+ const lenDiff = a.path.length - b.path.length
99
+ if (lenDiff !== 0) return lenDiff
100
+ // Within the same length bucket, index.ts barrel files go last so other
101
+ // files are always processed before their barrel file.
102
+ const aIsIndex = a.path.endsWith('/index.ts') || a.path === 'index.ts'
103
+ const bIsIndex = b.path.endsWith('/index.ts') || b.path === 'index.ts'
104
+ if (aIsIndex && !bIsIndex) return 1
105
+ if (!aIsIndex && bIsIndex) return -1
106
+ return 0
107
+ })
108
+ return this.#filesCache
109
+ }
110
+ }
@@ -0,0 +1,86 @@
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
+ * @internal
34
+ */
35
+ export class FileProcessor {
36
+ readonly #limit = pLimit(PARALLEL_CONCURRENCY_LIMIT)
37
+
38
+ async parse(file: FileNode, { parsers, extension }: ParseOptions = {}): Promise<string> {
39
+ const parseExtName = extension?.[file.extname] || undefined
40
+
41
+ if (!parsers || !file.extname) {
42
+ return joinSources(file)
43
+ }
44
+
45
+ const parser = parsers.get(file.extname)
46
+
47
+ if (!parser) {
48
+ return joinSources(file)
49
+ }
50
+
51
+ return parser.parse(file, { extname: parseExtName })
52
+ }
53
+
54
+ async run(files: Array<FileNode>, { parsers, mode = 'sequential', extension, onStart, onEnd, onUpdate }: RunOptions = {}): Promise<Array<FileNode>> {
55
+ await onStart?.(files)
56
+
57
+ const total = files.length
58
+ let processed = 0
59
+
60
+ const processOne = async (file: FileNode) => {
61
+ const source = await this.parse(file, { extension, parsers })
62
+ const currentProcessed = ++processed
63
+ const percentage = (currentProcessed / total) * 100
64
+
65
+ await onUpdate?.({
66
+ file,
67
+ source,
68
+ processed: currentProcessed,
69
+ percentage,
70
+ total,
71
+ })
72
+ }
73
+
74
+ if (mode === 'sequential') {
75
+ for (const file of files) {
76
+ await processOne(file)
77
+ }
78
+ } else {
79
+ await Promise.all(files.map((file) => this.#limit(() => processOne(file))))
80
+ }
81
+
82
+ await onEnd?.(files)
83
+
84
+ return files
85
+ }
86
+ }