@kubb/core 1.1.6 → 1.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,13 @@
1
1
  {
2
2
  "name": "@kubb/core",
3
- "version": "1.1.6",
3
+ "version": "1.1.8",
4
4
  "description": "Generator core",
5
+ "keywords": [
6
+ "typescript",
7
+ "plugins",
8
+ "kubb",
9
+ "codegen"
10
+ ],
5
11
  "repository": {
6
12
  "type": "git",
7
13
  "url": "git://github.com/kubb-project/kubb.git",
@@ -9,17 +15,8 @@
9
15
  },
10
16
  "license": "MIT",
11
17
  "author": "Stijn Van Hulle <stijn@stijnvanhulle.be",
12
- "keywords": [
13
- "typescript",
14
- "plugins",
15
- "kubb",
16
- "codegen"
17
- ],
18
18
  "sideEffects": false,
19
19
  "type": "module",
20
- "main": "dist/index.js",
21
- "module": "dist/index.js",
22
- "types": "./dist/index.d.ts",
23
20
  "exports": {
24
21
  ".": {
25
22
  "types": "./dist/index.d.ts",
@@ -29,6 +26,9 @@
29
26
  },
30
27
  "./package.json": "./package.json"
31
28
  },
29
+ "main": "dist/index.js",
30
+ "module": "dist/index.js",
31
+ "types": "./dist/index.d.ts",
32
32
  "typesVersions": {
33
33
  "*": {}
34
34
  },
@@ -43,29 +43,35 @@
43
43
  "change-case": "^4.1.2",
44
44
  "directory-tree": "^3.5.1",
45
45
  "rimraf": "^5.0.1",
46
- "@kubb/ts-codegen": "1.1.6"
46
+ "@kubb/ts-codegen": "1.1.8"
47
47
  },
48
48
  "devDependencies": {
49
- "tsup": "^6.7.0",
49
+ "eslint": "^8.42.0",
50
50
  "ora": "^6.3.1",
51
- "typescript": "^5.1.3"
51
+ "tsup": "^6.7.0",
52
+ "typescript": "^5.1.3",
53
+ "@kubb/eslint-config": "0.1.0",
54
+ "@kubb/tsup-config": "0.1.0",
55
+ "@kubb/typescript-config": "0.1.0"
56
+ },
57
+ "packageManager": "pnpm@8.3.0",
58
+ "engines": {
59
+ "node": ">=18",
60
+ "pnpm": ">=8.3.0"
52
61
  },
53
62
  "publishConfig": {
54
63
  "access": "public",
55
64
  "registry": "https://registry.npmjs.org/"
56
65
  },
57
- "engines": {
58
- "node": ">=18",
59
- "pnpm": ">=8"
60
- },
61
66
  "scripts": {
62
67
  "build": "tsup",
63
- "start": "tsup --watch",
68
+ "clean": "rimraf ./dist",
69
+ "lint": "eslint \"**/*.{ts,tsx}\"",
70
+ "lint-fix": "eslint \"**/*.{ts,tsx}\" --quiet --fix",
64
71
  "release": "pnpm publish --no-git-check",
65
- "pre-commit": "echo 'pre-commit not configured'",
66
- "pre-push": "pnpm typecheck",
72
+ "start": "tsup --watch",
67
73
  "test": "vitest --passWithNoTests",
68
- "upgrade": "pnpm update",
69
- "typecheck": "tsc -p ./tsconfig.json --noEmit --emitDeclarationOnly false"
74
+ "typecheck": "tsc -p ./tsconfig.json --noEmit --emitDeclarationOnly false",
75
+ "upgrade": "pnpm update"
70
76
  }
71
77
  }
package/src/build.ts CHANGED
@@ -1,14 +1,14 @@
1
1
  /* eslint-disable no-async-promise-executor */
2
+ import { getFileSource } from './managers/fileManager/index.ts'
2
3
  import { PluginManager } from './managers/pluginManager/index.ts'
3
4
  import { clean, isURL, read } from './utils/index.ts'
4
- import { getFileSource } from './managers/fileManager/index.ts'
5
5
  import { isPromise } from './utils/isPromise.ts'
6
6
 
7
- import type { OnExecute } from './managers/pluginManager/index.ts'
7
+ import type { Ora } from 'ora'
8
8
  import type { File } from './managers/fileManager/index.ts'
9
+ import type { OnExecute } from './managers/pluginManager/index.ts'
10
+ import type { BuildOutput, KubbPlugin, LogLevel, PluginContext, TransformResult } from './types.ts'
9
11
  import type { QueueTask } from './utils/index.ts'
10
- import type { PluginContext, TransformResult, LogLevel, KubbPlugin, BuildOutput } from './types.ts'
11
- import type { Ora } from 'ora'
12
12
 
13
13
  export type Logger = {
14
14
  log: (message: string, logLevel: LogLevel) => void
@@ -36,7 +36,7 @@ export async function build(options: BuildOptions): Promise<BuildOutput> {
36
36
  await read(config.input.path)
37
37
  }
38
38
  } catch (e: any) {
39
- throw new Error('Cannot read file defined in `input.path` or set with --input in the CLI of your Kubb config', { cause: e })
39
+ throw new Error('Cannot read file/URL defined in `input.path` or set with --input in the CLI of your Kubb config', { cause: e })
40
40
  }
41
41
 
42
42
  if (config.output.clean) {
package/src/config.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { MaybePromise, KubbUserConfig, CLIOptions } from './types.ts'
1
+ import type { CLIOptions, KubbUserConfig, MaybePromise } from './types.ts'
2
2
 
3
3
  /**
4
4
  * Type helper to make it easier to use kubb.config.js
@@ -1,4 +1,5 @@
1
1
  import { Generator } from './Generator.ts'
2
+
2
3
  /**
3
4
  * Abstract class that contains the building blocks for plugins to create their own SchemaGenerator
4
5
  */
@@ -1,9 +1,9 @@
1
1
  import crypto from 'node:crypto'
2
2
 
3
- import { write, read } from '../../utils/index.ts'
3
+ import { read, write } from '../../utils/index.ts'
4
4
 
5
- import type { QueueTask, Queue } from '../../utils/index.ts'
6
- import type { CacheStore, UUID, Status, File } from './types.ts'
5
+ import type { Queue, QueueTask } from '../../utils/index.ts'
6
+ import type { CacheStore, File, Status, UUID } from './types.ts'
7
7
 
8
8
  export class FileManager {
9
9
  private cache: Map<CacheStore['id'], CacheStore> = new Map()
@@ -1,29 +1,31 @@
1
1
  import pathParser from 'node:path'
2
2
 
3
- import { createImportDeclaration, createExportDeclaration, print } from '@kubb/ts-codegen'
3
+ import { createExportDeclaration, createImportDeclaration, print } from '@kubb/ts-codegen'
4
4
 
5
5
  import { TreeNode } from '../../utils/index.ts'
6
6
 
7
- import type { PathMode, TreeNodeOptions } from '../../utils/index.ts'
8
- import type { Path } from '../../types.ts'
9
7
  import type ts from 'typescript'
8
+ import type { Path } from '../../types.ts'
9
+ import type { PathMode, TreeNodeOptions } from '../../utils/index.ts'
10
10
  import type { File } from './types.ts'
11
11
 
12
- export function writeIndexes(root: string, options: TreeNodeOptions) {
13
- const tree = TreeNode.build<{ type: PathMode; path: Path; name: string }>(root, { extensions: /\.ts/, ...options })
12
+ type TreeNodeData = { type: PathMode; path: Path; name: string }
13
+
14
+ export function writeIndexes(root: string, options: TreeNodeOptions = {}): File[] | null {
15
+ const tree = TreeNode.build<TreeNodeData>(root, { extensions: /\.ts/, ...options })
14
16
 
15
17
  if (!tree) {
16
- return undefined
18
+ return null
17
19
  }
18
20
 
19
- const fileReducer = (files: File[], item: typeof tree) => {
20
- if (!item.children) {
21
+ const fileReducer = (files: File[], currentTree: typeof tree) => {
22
+ if (!currentTree.children) {
21
23
  return []
22
24
  }
23
25
 
24
- if (item.children?.length > 1) {
25
- const path = pathParser.resolve(item.data.path, 'index.ts')
26
- const exports = item.children
26
+ if (currentTree.children?.length > 1) {
27
+ const path = pathParser.resolve(currentTree.data.path, 'index.ts')
28
+ const exports = currentTree.children
27
29
  .map((file) => {
28
30
  if (!file) {
29
31
  return undefined
@@ -47,8 +49,8 @@ export function writeIndexes(root: string, options: TreeNodeOptions) {
47
49
  exports,
48
50
  })
49
51
  } else {
50
- item.children?.forEach((child) => {
51
- const path = pathParser.resolve(item.data.path, 'index.ts')
52
+ currentTree.children?.forEach((child) => {
53
+ const path = pathParser.resolve(currentTree.data.path, 'index.ts')
52
54
  const importPath = child.data.type === 'directory' ? `./${child.data.name}` : `./${child.data.name.replace(/\.[^.]*$/, '')}`
53
55
 
54
56
  files.push({
@@ -60,7 +62,7 @@ export function writeIndexes(root: string, options: TreeNodeOptions) {
60
62
  })
61
63
  }
62
64
 
63
- item.children.forEach((childItem) => {
65
+ currentTree.children.forEach((childItem) => {
64
66
  fileReducer(files, childItem)
65
67
  })
66
68
 
@@ -72,11 +74,8 @@ export function writeIndexes(root: string, options: TreeNodeOptions) {
72
74
  return files
73
75
  }
74
76
 
75
- export function combineFiles(files: Array<File | null>) {
76
- return files.filter(Boolean).reduce((acc, curr: File | null) => {
77
- if (!curr) {
78
- return acc
79
- }
77
+ export function combineFiles(files: Array<File | null>): File[] {
78
+ return (files.filter(Boolean) as File[]).reduce((acc, curr: File) => {
80
79
  const prevIndex = acc.findIndex((item) => item.path === curr.path)
81
80
 
82
81
  if (prevIndex !== -1) {
@@ -95,7 +94,7 @@ export function combineFiles(files: Array<File | null>) {
95
94
  }, [] as File[])
96
95
  }
97
96
 
98
- export function getFileSource(file: File) {
97
+ export function getFileSource(file: File): string {
99
98
  let { source } = file
100
99
 
101
100
  // TODO make generic check
@@ -106,21 +105,22 @@ export function getFileSource(file: File) {
106
105
  const exports: File['exports'] = []
107
106
 
108
107
  file.imports?.forEach((curr) => {
109
- const exists = imports.find((imp) => imp.path === curr.path)
110
- if (!exists) {
108
+ const existingImport = imports.find((imp) => imp.path === curr.path)
109
+
110
+ if (!existingImport) {
111
111
  imports.push({
112
112
  ...curr,
113
113
  name: Array.isArray(curr.name) ? [...new Set(curr.name)] : curr.name,
114
114
  })
115
115
  }
116
116
 
117
- if (exists && !Array.isArray(exists.name) && exists.name !== curr.name) {
117
+ if (existingImport && !Array.isArray(existingImport.name) && existingImport.name !== curr.name) {
118
118
  imports.push(curr)
119
119
  }
120
120
 
121
- if (exists && Array.isArray(exists.name)) {
121
+ if (existingImport && Array.isArray(existingImport.name)) {
122
122
  if (Array.isArray(curr.name)) {
123
- exists.name = [...new Set([...exists.name, ...curr.name])]
123
+ existingImport.name = [...new Set([...existingImport.name, ...curr.name])]
124
124
  }
125
125
  }
126
126
  })
@@ -151,7 +151,7 @@ export function getFileSource(file: File) {
151
151
  const importSource = print(importNodes)
152
152
 
153
153
  const exportNodes = exports.reduce((prev, curr) => {
154
- return [...prev, createExportDeclaration({ name: curr.name, path: curr.path, asAlias: curr.asAlias })]
154
+ return [...prev, createExportDeclaration({ name: curr.name, path: curr.path, isTypeOnly: curr.isTypeOnly, asAlias: curr.asAlias })]
155
155
  }, [] as ts.ExportDeclaration[])
156
156
  const exportSource = print(exportNodes)
157
157
 
@@ -2,18 +2,17 @@
2
2
  /* eslint-disable no-await-in-loop */
3
3
  /* eslint-disable no-restricted-syntax */
4
4
 
5
- import { PluginError } from './PluginError.ts'
6
- import { ParallelPluginError } from './ParallelPluginError.ts'
7
-
8
5
  import { definePlugin } from '../../plugin.ts'
9
- import { FileManager } from '../fileManager/FileManager.ts'
10
- import { Queue } from '../../utils/Queue.ts'
11
6
  import { isPromise } from '../../utils/isPromise.ts'
7
+ import { Queue } from '../../utils/Queue.ts'
8
+ import { FileManager } from '../fileManager/FileManager.ts'
9
+ import { ParallelPluginError } from './ParallelPluginError.ts'
10
+ import { PluginError } from './PluginError.ts'
12
11
 
13
- import type { QueueTask } from '../../utils/Queue.ts'
14
- import type { Argument0, Strategy, Executer, OnExecute, ParseResult, SafeParseResult } from './types.ts'
15
- import type { KubbConfig, KubbPlugin, PluginLifecycleHooks, PluginLifecycle, MaybePromise, ResolvePathParams, ResolveNameParams } from '../../types.ts'
16
12
  import type { CorePluginOptions } from '../../plugin.ts'
13
+ import type { KubbConfig, KubbPlugin, MaybePromise, PluginLifecycle, PluginLifecycleHooks, ResolveNameParams, ResolvePathParams } from '../../types.ts'
14
+ import type { QueueTask } from '../../utils/Queue.ts'
15
+ import type { Argument0, Executer, OnExecute, ParseResult, SafeParseResult, Strategy } from './types.ts'
17
16
 
18
17
  // inspired by: https://github.com/rollup/rollup/blob/master/src/utils/PluginDriver.ts#
19
18
 
@@ -218,7 +217,7 @@ export class PluginManager {
218
217
  break
219
218
  }
220
219
  }
221
- return parseResult as SafeParseResult<H>
220
+ return parseResult
222
221
  }
223
222
 
224
223
  /**
@@ -1,5 +1,6 @@
1
- import type { PluginManager } from './PluginManager.ts'
2
1
  import type { KubbPlugin, PluginLifecycle, PluginLifecycleHooks } from '../../types.ts'
2
+ import type { PluginManager } from './PluginManager.ts'
3
+
3
4
  /**
4
5
  * Get the type of the first argument in a function.
5
6
  * @example Arg0<(a: string, b: number) => void> -> string
package/src/plugin.ts CHANGED
@@ -2,9 +2,9 @@ import pathParser from 'node:path'
2
2
 
3
3
  import { createPluginCache, getStackTrace, transformReservedWord } from './utils/index.ts'
4
4
 
5
- import type { Executer } from './managers/index.ts'
6
5
  import type { FileManager } from './managers/fileManager/FileManager.ts'
7
- import type { PluginContext, KubbPlugin, PluginFactoryOptions, PluginLifecycleHooks } from './types.ts'
6
+ import type { Executer } from './managers/index.ts'
7
+ import type { KubbPlugin, PluginContext, PluginFactoryOptions, PluginLifecycleHooks } from './types.ts'
8
8
 
9
9
  type KubbPluginFactory<T extends PluginFactoryOptions = PluginFactoryOptions> = (
10
10
  options: T['options']
package/src/types.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable @typescript-eslint/no-empty-interface */
2
+ import type { File, FileManager } from './managers/fileManager/index.ts'
2
3
  import type { PluginManager, SafeParseResult } from './managers/index.ts'
3
- import type { FileManager, File } from './managers/fileManager/index.ts'
4
4
  import type { Cache } from './utils/cache.ts'
5
5
 
6
6
  export interface Register {}
@@ -1,5 +1,7 @@
1
1
  import dirTree from 'directory-tree'
2
2
 
3
+ import { getPathMode } from '../utils/read.ts'
4
+
3
5
  import type { DirectoryTree, DirectoryTreeOptions } from 'directory-tree'
4
6
 
5
7
  export type TreeNodeOptions = DirectoryTreeOptions
@@ -26,13 +28,17 @@ export class TreeNode<T = unknown> {
26
28
  return child
27
29
  }
28
30
 
29
- find(data: T) {
31
+ find(data?: T): TreeNode<T> | null {
32
+ if (!data) {
33
+ return null
34
+ }
35
+
30
36
  if (data === this.data) {
31
37
  return this
32
38
  }
33
39
 
34
- if (this.children) {
35
- for (let i = 0, { length } = this.children, target: unknown = null; i < length; i++) {
40
+ if (this.children?.length) {
41
+ for (let i = 0, { length } = this.children, target: TreeNode<T> | null = null; i < length; i++) {
36
42
  target = this.children[i].find(data)
37
43
  if (target) {
38
44
  return target
@@ -43,7 +49,7 @@ export class TreeNode<T = unknown> {
43
49
  return null
44
50
  }
45
51
 
46
- leaves(): TreeNode<T>[] {
52
+ get leaves(): TreeNode<T>[] {
47
53
  if (!this.children || this.children.length === 0) {
48
54
  // this is a leaf
49
55
  return [this]
@@ -54,17 +60,17 @@ export class TreeNode<T = unknown> {
54
60
  if (this.children) {
55
61
  for (let i = 0, { length } = this.children; i < length; i++) {
56
62
  // eslint-disable-next-line prefer-spread
57
- leaves.push.apply(leaves, this.children[i].leaves())
63
+ leaves.push.apply(leaves, this.children[i].leaves)
58
64
  }
59
65
  }
60
66
  return leaves
61
67
  }
62
68
 
63
- root(): TreeNode<T> {
69
+ get root(): TreeNode<T> {
64
70
  if (!this.parent) {
65
71
  return this
66
72
  }
67
- return this.parent.root()
73
+ return this.parent.root
68
74
  }
69
75
 
70
76
  forEach(callback: (treeNode: TreeNode<T>) => void): this {
@@ -86,26 +92,31 @@ export class TreeNode<T = unknown> {
86
92
  }
87
93
 
88
94
  public static build<T = unknown>(path: string, options: TreeNodeOptions = {}): TreeNode<T> | null {
89
- const filteredTree = dirTree(path, { extensions: options?.extensions, exclude: options.exclude })
95
+ try {
96
+ const exclude = Array.isArray(options.exclude) ? options.exclude : ([options.exclude].filter(Boolean) as RegExp[])
97
+ const filteredTree = dirTree(path, { extensions: options.extensions, exclude: [/node_modules/, ...exclude] })
90
98
 
91
- if (!filteredTree) {
92
- return null
93
- }
99
+ if (!filteredTree) {
100
+ return null
101
+ }
94
102
 
95
- const treeNode = new TreeNode({ name: filteredTree.name, path: filteredTree.path, type: filteredTree.type })
103
+ const treeNode = new TreeNode({ name: filteredTree.name, path: filteredTree.path, type: filteredTree.type || getPathMode(filteredTree.path) })
96
104
 
97
- const recurse = (node: typeof treeNode, item: DirectoryTree) => {
98
- const subNode = node.addChild({ name: item.name, path: item.path, type: item.type })
105
+ const recurse = (node: typeof treeNode, item: DirectoryTree) => {
106
+ const subNode = node.addChild({ name: item.name, path: item.path, type: item.type || getPathMode(item.path) })
99
107
 
100
- if (item.children?.length) {
101
- item.children?.forEach((child) => {
102
- recurse(subNode, child)
103
- })
108
+ if (item.children?.length) {
109
+ item.children?.forEach((child) => {
110
+ recurse(subNode, child)
111
+ })
112
+ }
104
113
  }
105
- }
106
114
 
107
- filteredTree.children?.forEach((child) => recurse(treeNode, child))
115
+ filteredTree.children?.forEach((child) => recurse(treeNode, child))
108
116
 
109
- return treeNode as TreeNode<T>
117
+ return treeNode as TreeNode<T>
118
+ } catch (e) {
119
+ throw new Error('Something went wrong with creating index files with the TreehNode class', { cause: e })
120
+ }
110
121
  }
111
122
  }
@@ -9,7 +9,7 @@ export function getStackTrace(belowFn?: Function): NodeJS.CallSite[] {
9
9
  Error.prepareStackTrace = function prepareStackTrace(dummyObject, v8StackTrace) {
10
10
  return v8StackTrace
11
11
  }
12
- Error.captureStackTrace(dummyObject, belowFn || getStackTrace)
12
+ Error.captureStackTrace(dummyObject as object, belowFn || getStackTrace)
13
13
 
14
14
  const v8StackTrace = dummyObject.stack
15
15
  Error.prepareStackTrace = v8Handler
@@ -15,3 +15,4 @@ export * from './clean.ts'
15
15
  export * from './TreeNode.ts'
16
16
  export * from './transformReservedWord.ts'
17
17
  export * from './getStackTrace.ts'
18
+ export * from './uniqueId.ts'
package/src/utils/read.ts CHANGED
@@ -1,17 +1,19 @@
1
- import pathParser from 'node:path'
2
1
  import { promises as fs } from 'node:fs'
2
+ import pathParser from 'node:path'
3
3
 
4
- function slash(path: string) {
4
+ function slash(path: string, platform: 'windows' | 'mac' | 'linux' = 'linux') {
5
5
  const isExtendedLengthPath = /^\\\\\?\\/.test(path)
6
6
 
7
- if (isExtendedLengthPath) {
8
- return path
7
+ if (isExtendedLengthPath || platform === 'linux' || platform === 'mac') {
8
+ // linux and mac
9
+ return path.replace('../', '').trimEnd()
9
10
  }
10
11
 
11
- return path.replace(/\\/g, '/')
12
+ // windows
13
+ return path.replace(/\\/g, '/').replace('../', '').trimEnd()
12
14
  }
13
15
 
14
- export function getRelativePath(rootDir?: string | null, filePath?: string | null) {
16
+ export function getRelativePath(rootDir?: string | null, filePath?: string | null, platform: 'windows' | 'mac' | 'linux' = 'linux') {
15
17
  if (!rootDir || !filePath) {
16
18
  throw new Error(`Root and file should be filled in when retrieving the relativePath, ${rootDir} ${filePath}`)
17
19
  }
@@ -20,7 +22,7 @@ export function getRelativePath(rootDir?: string | null, filePath?: string | nul
20
22
 
21
23
  // On Windows, paths are separated with a "\"
22
24
  // However, web browsers use "/" no matter the platform
23
- const path = slash(relativePath).replace('../', '').trimEnd()
25
+ const path = slash(relativePath, platform)
24
26
 
25
27
  if (path.startsWith('../')) {
26
28
  return path.replace(pathParser.basename(path), pathParser.basename(path, pathParser.extname(filePath)))
@@ -39,10 +41,5 @@ export function getPathMode(path: string | undefined | null): PathMode {
39
41
  }
40
42
 
41
43
  export async function read(path: string) {
42
- try {
43
- return fs.readFile(path, { encoding: 'utf8' })
44
- } catch (err) {
45
- console.error(err)
46
- throw err
47
- }
44
+ return fs.readFile(path, { encoding: 'utf8' })
48
45
  }
@@ -0,0 +1,5 @@
1
+ export const uniqueId = (
2
+ (counter) =>
3
+ (str = '') =>
4
+ `${str}${++counter}`
5
+ )(0)