@kubb/core
Advanced tools
Comparing version 0.20.0 to 0.21.0
@@ -1,21 +0,4 @@ | ||
interface Cache<TCache = any> { | ||
delete(id: string): boolean; | ||
get<T = TCache>(id: string): T; | ||
has(id: string): boolean; | ||
set<T = TCache>(id: string, value: T): void; | ||
} | ||
declare function createPluginCache(cache: any): Cache; | ||
import EventEmitter from 'events'; | ||
type Listener<T> = (value?: T) => void; | ||
declare class Emitter<TValue = unknown, TTopics = unknown> { | ||
private readonly listeners; | ||
private readonly topics?; | ||
constructor(topics?: TTopics[]); | ||
emit(...params: [topic: TTopics, value?: TValue] | [value?: TValue]): void; | ||
subscribe: (cb: Listener<TValue>) => () => void; | ||
on(topic: TTopics, cb: Listener<TValue>): () => boolean; | ||
destroy: () => void; | ||
} | ||
interface EmittedFile { | ||
type EmittedFile = { | ||
/** | ||
@@ -39,16 +22,64 @@ * equal to importee when getting passed through resolveId | ||
options?: Record<string, any>; | ||
}; | ||
type UserFile = { | ||
/** | ||
* Name to be used to dynamicly create the fileName(based on input.path) | ||
*/ | ||
name?: string; | ||
/** | ||
* FileName will be the end result so no input.path will not be added | ||
*/ | ||
fileName?: string; | ||
source?: string; | ||
}; | ||
type File = { | ||
/** | ||
* Name to be used to dynamicly create the fileName(based on input.path) | ||
*/ | ||
name: string; | ||
/** | ||
* FileName will be the end result so no input.path will not be added | ||
*/ | ||
fileName: string; | ||
source: string; | ||
}; | ||
type UUID = string; | ||
type CacheStore = { | ||
id: UUID; | ||
file: File; | ||
status: Status; | ||
}; | ||
type Status = 'new' | 'success' | 'removed'; | ||
declare class FileManager { | ||
private cache; | ||
emitter: EventEmitter; | ||
events: { | ||
emitFile: (id: string, file: File) => void; | ||
emitStatusChange: (file: File) => void; | ||
emitStatusChangeById: (id: string, status: Status) => void; | ||
emitSuccess: () => void; | ||
emitRemove: (id: string, file: File) => void; | ||
onAdd: (callback: (id: string, file: File) => void) => VoidFunction; | ||
onStatusChange: (callback: (file: File) => void) => VoidFunction; | ||
onStatusChangeById: (id: string, callback: (status: Status) => void) => VoidFunction; | ||
onSuccess: (callback: () => void) => VoidFunction; | ||
onRemove: (id: string, callback: (file: File) => void) => VoidFunction; | ||
}; | ||
constructor(); | ||
private getCache; | ||
private getCountOfStatus; | ||
add(userFile: UserFile): Promise<File>; | ||
setStatus(id: UUID, status: Status): void; | ||
get(id: UUID): File | undefined; | ||
remove(id: UUID): void; | ||
} | ||
type EmitFile = (emittedFile: EmittedFile) => void; | ||
type Topics = 'new' | 'delete' | 'end'; | ||
declare class FileEmitter { | ||
private readonly emitter; | ||
private readonly filesByReferenceId; | ||
constructor(emitter?: Emitter<EmittedFile, Topics>); | ||
emitFile(emitedFile: EmittedFile): Promise<EmittedFile>; | ||
delete(fileReferenceId: string): void; | ||
subscribe(...params: Parameters<typeof this$1.emitter['subscribe']>): void; | ||
on(...params: Parameters<typeof this$1.emitter['on']>): void; | ||
private assignReferenceId; | ||
getEmittedFile: (fileReferenceId?: string | null) => EmittedFile | undefined; | ||
interface Cache<TCache = any> { | ||
delete(id: string): boolean; | ||
get<T = TCache>(id: string): T; | ||
has(id: string): boolean; | ||
set<T = TCache>(id: string, value: T): void; | ||
} | ||
declare function createPluginCache(cache: any): Cache; | ||
@@ -133,6 +164,7 @@ type MaybePromise<T> = Promise<T> | T; | ||
cache: Cache; | ||
emitFile: FileEmitter['emitFile']; | ||
emitFile: (emitedFile: EmittedFile) => Promise<File>; | ||
resolveId: (importee: string, importer?: string, options?: Record<string, any>) => MaybePromise<string | null | undefined>; | ||
resolveIdForPlugin: (pluginName: string) => PluginContext['resolveId']; | ||
load: (id: string) => MaybePromise<TransformResult | void>; | ||
addToRoot: (emittedFile: EmittedFile) => void; | ||
addToRoot: (file: File) => void; | ||
}; | ||
@@ -175,2 +207,13 @@ type ValidationResult = true | { | ||
type KubbPluginFactory<T extends PluginFactoryOptions = PluginFactoryOptions> = (options: T['options']) => T['nested'] extends true ? Array<KubbPlugin<T>> : KubbPlugin<T>; | ||
declare function createPlugin<T extends PluginFactoryOptions = PluginFactoryOptions>(factory: KubbPluginFactory<T>): (options: T['options']) => T["nested"] extends true ? KubbPlugin<T>[] : KubbPlugin<T>; | ||
type Options = { | ||
config: PluginContext['config']; | ||
fileManager: FileManager; | ||
resolveId: PluginContext['resolveId']; | ||
resolveIdForPlugin: PluginContext['resolveIdForPlugin']; | ||
load: PluginContext['load']; | ||
}; | ||
type CorePluginOptions = PluginFactoryOptions<Options, false, PluginContext>; | ||
declare const isPromise: <T>(result: MaybePromise<T>) => result is Promise<T>; | ||
@@ -191,3 +234,3 @@ | ||
plugins: KubbPlugin[]; | ||
readonly fileEmitter: FileEmitter; | ||
readonly fileManager: FileManager; | ||
private readonly logger?; | ||
@@ -201,5 +244,6 @@ private readonly config; | ||
}); | ||
emitFile(...params: Parameters<FileEmitter['emitFile']>): Promise<EmittedFile>; | ||
resolveId: (source: string, importer: string, meta: Record<string, any> | undefined) => Promise<string | null | undefined>; | ||
resolveId: (importee: string, importer: string, options: Record<string, any> | undefined) => Promise<string | null | undefined>; | ||
resolveIdForPlugin: (pluginName: string) => (importee: string, importer: string, options: Record<string, any> | undefined) => Promise<string | null | undefined>; | ||
load: (id: string) => Promise<TransformResult>; | ||
hookForPlugin<H extends PluginLifecycleHooks>(pluginName: string, hookName: H, parameters: Parameters<PluginLifecycle[H]>, skipped?: ReadonlySet<KubbPlugin> | null): Promise<ReturnType<PluginLifecycle[H]> | null>; | ||
hookFirst<H extends PluginLifecycleHooks>(hookName: H, parameters: Parameters<PluginLifecycle[H]>, skipped?: ReadonlySet<KubbPlugin> | null): Promise<ReturnType<PluginLifecycle[H]> | null>; | ||
@@ -231,12 +275,2 @@ hookParallel<H extends PluginLifecycleHooks, TOuput = void>(hookName: H, parameters?: Parameters<PluginLifecycle[H]> | undefined): Promise<Awaited<TOuput>[]>; | ||
type KubbPluginFactory<T extends PluginFactoryOptions = PluginFactoryOptions> = (options: T['options']) => T['nested'] extends true ? Array<KubbPlugin<T>> : KubbPlugin<T>; | ||
declare function createPlugin<T extends PluginFactoryOptions = PluginFactoryOptions>(factory: KubbPluginFactory<T>): (options: T['options']) => T["nested"] extends true ? KubbPlugin<T>[] : KubbPlugin<T>; | ||
type Options = { | ||
config: PluginContext['config']; | ||
fileEmitter: FileEmitter; | ||
resolveId: PluginContext['resolveId']; | ||
load: PluginContext['load']; | ||
}; | ||
type CorePluginOptions = PluginFactoryOptions<Options, false, PluginContext>; | ||
export { Argument0, CLIOptions, Cache, CorePluginOptions, EmitFile, EmittedFile, Emitter, FileEmitter, KubbConfig, KubbPlugin, KubbUserConfig, Listener, LogLevel, LogType, Logger, MaybePromise, PluginContext, PluginDriver, PluginFactoryOptions, PluginLifecycle, PluginLifecycleHooks, TransformResult, ValidationResult, build, createPlugin, createPluginCache, build as default, defineConfig, format, getRelativePath, hooks, isPromise, write }; | ||
export { Argument0, CLIOptions, Cache, CacheStore, CorePluginOptions, EmittedFile, File, FileManager, KubbConfig, KubbPlugin, KubbUserConfig, LogLevel, LogType, Logger, MaybePromise, PluginContext, PluginDriver, PluginFactoryOptions, PluginLifecycle, PluginLifecycleHooks, Status, TransformResult, UUID, UserFile, ValidationResult, build, createPlugin, createPluginCache, build as default, defineConfig, format, getRelativePath, hooks, isPromise, write }; |
@@ -8,90 +8,7 @@ 'use strict'; | ||
var prettier = require('prettier'); | ||
var EventEmitter = require('events'); | ||
var crypto = require('crypto'); | ||
// src/build.ts | ||
// src/utils/Emitter.ts | ||
var Emitter = class { | ||
listeners = /* @__PURE__ */ new Set(); | ||
topics; | ||
constructor(topics) { | ||
this.topics = topics; | ||
} | ||
emit(...params) { | ||
const isTopic = (value) => !!this.topics?.includes(value); | ||
if (isTopic(params[0])) { | ||
this.listeners.forEach((listener) => { | ||
if (listener.topic === params[0]) { | ||
listener.cb(params[1]); | ||
} | ||
}); | ||
return; | ||
} | ||
this.listeners.forEach((listener) => listener.cb(params[0])); | ||
} | ||
subscribe = (cb) => { | ||
const listener = { | ||
topic: void 0, | ||
cb | ||
}; | ||
this.listeners.add(listener); | ||
return () => this.listeners.delete(listener); | ||
}; | ||
on(topic, cb) { | ||
const listener = { | ||
topic, | ||
cb | ||
}; | ||
this.listeners.add(listener); | ||
return () => this.listeners.delete(listener); | ||
} | ||
destroy = () => this.listeners.clear(); | ||
}; | ||
// src/utils/FileEmitter.ts | ||
var FileEmitter = class { | ||
emitter; | ||
filesByReferenceId = /* @__PURE__ */ new Map(); | ||
constructor(emitter = new Emitter(["delete", "end", "new"])) { | ||
this.emitter = emitter; | ||
} | ||
emitFile(emitedFile) { | ||
this.assignReferenceId(emitedFile, emitedFile.id); | ||
this.emitter.emit("new", emitedFile); | ||
return new Promise((resolve) => { | ||
const subscribe = this.emitter.on("delete", (deletedFile) => { | ||
if (deletedFile?.id && deletedFile?.id === emitedFile.id) { | ||
resolve(deletedFile); | ||
return subscribe(); | ||
} | ||
return void 0; | ||
}); | ||
}); | ||
} | ||
delete(fileReferenceId) { | ||
const deletedFile = this.filesByReferenceId.get(fileReferenceId); | ||
this.filesByReferenceId.delete(fileReferenceId); | ||
if (this.filesByReferenceId.size === 0) { | ||
this.emitter.emit("end"); | ||
} | ||
return this.emitter.emit("delete", deletedFile); | ||
} | ||
subscribe(...params) { | ||
this.emitter.subscribe(...params); | ||
} | ||
on(...params) { | ||
this.emitter.on(...params); | ||
} | ||
assignReferenceId(emittedFile, fileReferenceId) { | ||
if (fileReferenceId) { | ||
this.filesByReferenceId.set(fileReferenceId, emittedFile); | ||
} | ||
} | ||
getEmittedFile = (fileReferenceId) => { | ||
if (!fileReferenceId) { | ||
return void 0; | ||
} | ||
return this.filesByReferenceId.get(fileReferenceId); | ||
}; | ||
}; | ||
// src/utils/isPromise.ts | ||
@@ -179,3 +96,3 @@ var isPromise = (result) => { | ||
var definePlugin = createPlugin((options) => { | ||
const { fileEmitter, resolveId, load } = options; | ||
const { fileManager, resolveId, resolveIdForPlugin, load } = options; | ||
const indexFiles = []; | ||
@@ -188,12 +105,14 @@ const api = { | ||
const resolvedId = await resolveId(emittedFile.id, emittedFile.importer, emittedFile.options); | ||
const id = resolvedId || emittedFile.importer || emittedFile.id; | ||
return fileEmitter.emitFile({ | ||
...emittedFile, | ||
id | ||
const fileName = resolvedId || emittedFile.importer || emittedFile.id; | ||
return fileManager.add({ | ||
fileName, | ||
name: emittedFile.name, | ||
source: emittedFile.source | ||
}); | ||
}, | ||
addToRoot: (emittedFile) => { | ||
indexFiles.push(emittedFile); | ||
addToRoot: (file) => { | ||
indexFiles.push(file); | ||
}, | ||
resolveId, | ||
resolveIdForPlugin, | ||
load, | ||
@@ -211,3 +130,3 @@ cache: createPluginCache(/* @__PURE__ */ Object.create(null)) | ||
indexFiles.forEach((item) => { | ||
index += `export * from "${getRelativePath(path2.resolve(this.config.root, this.config.output.path), item.id)}"; | ||
index += `export * from "${getRelativePath(path2.resolve(this.config.root, this.config.output.path), item.fileName)}"; | ||
`; | ||
@@ -226,2 +145,112 @@ }); | ||
// src/managers/utils/getFileManagerEvents.ts | ||
var keys = { | ||
getEmitFileKey: () => `emit-file`, | ||
getStatusChangeKey: () => `status-change`, | ||
getStatusChangeByIdKey: (id) => `${id}-status-change`, | ||
getSuccessKey: () => `success`, | ||
getRemoveKey: (id) => `${id}remove` | ||
}; | ||
var getFileManagerEvents = (emitter) => { | ||
return { | ||
emitFile: (id, file) => { | ||
emitter.emit(keys.getEmitFileKey(), id, file); | ||
}, | ||
emitStatusChange: (file) => { | ||
emitter.emit(keys.getStatusChangeKey(), file); | ||
}, | ||
emitStatusChangeById: (id, status) => { | ||
emitter.emit(keys.getStatusChangeByIdKey(id), status); | ||
}, | ||
emitSuccess: () => { | ||
emitter.emit(keys.getSuccessKey()); | ||
}, | ||
emitRemove: (id, file) => { | ||
emitter.emit(keys.getRemoveKey(id), file); | ||
}, | ||
onAdd: (callback) => { | ||
emitter.on(keys.getEmitFileKey(), callback); | ||
return () => emitter.removeListener(keys.getEmitFileKey(), callback); | ||
}, | ||
onStatusChange: (callback) => { | ||
emitter.on(keys.getStatusChangeKey(), callback); | ||
return () => emitter.removeListener(keys.getStatusChangeKey(), callback); | ||
}, | ||
onStatusChangeById: (id, callback) => { | ||
emitter.on(keys.getStatusChangeByIdKey(id), callback); | ||
return () => emitter.removeListener(keys.getStatusChangeByIdKey(id), callback); | ||
}, | ||
onSuccess: (callback) => { | ||
emitter.on(keys.getSuccessKey(), callback); | ||
return () => emitter.removeListener(keys.getSuccessKey(), callback); | ||
}, | ||
onRemove: (id, callback) => { | ||
emitter.on(keys.getRemoveKey(id), callback); | ||
return () => emitter.removeListener(keys.getRemoveKey(id), callback); | ||
} | ||
}; | ||
}; | ||
// src/managers/FileManager.ts | ||
var FileManager = class { | ||
cache = /* @__PURE__ */ new Map(); | ||
emitter = new EventEmitter(); | ||
events = getFileManagerEvents(this.emitter); | ||
constructor() { | ||
this.events.onStatusChange(() => { | ||
if (this.getCountOfStatus("removed") === this.cache.size) { | ||
this.events.emitSuccess(); | ||
} | ||
}); | ||
} | ||
getCache(id) { | ||
return this.cache.get(id); | ||
} | ||
getCountOfStatus(status) { | ||
let count = 0; | ||
this.cache.forEach((item) => { | ||
if (item.status === status) { | ||
count++; | ||
} | ||
}); | ||
return count; | ||
} | ||
add(userFile) { | ||
const file = { | ||
...userFile | ||
}; | ||
const cacheItem = { id: crypto.randomUUID(), file, status: "new" }; | ||
this.cache.set(cacheItem.id, cacheItem); | ||
this.events.emitFile(cacheItem.id, file); | ||
return new Promise((resolve) => { | ||
const unsubscribe = this.events.onRemove(cacheItem.id, (file2) => { | ||
resolve(file2); | ||
unsubscribe(); | ||
}); | ||
}); | ||
} | ||
setStatus(id, status) { | ||
const cacheItem = this.getCache(id); | ||
if (!cacheItem) { | ||
return; | ||
} | ||
cacheItem.status = status; | ||
this.cache.set(id, cacheItem); | ||
this.events.emitStatusChange(cacheItem.file); | ||
this.events.emitStatusChangeById(id, status); | ||
} | ||
get(id) { | ||
const cacheItem = this.getCache(id); | ||
return cacheItem?.file; | ||
} | ||
remove(id) { | ||
const cacheItem = this.getCache(id); | ||
if (!cacheItem) { | ||
return; | ||
} | ||
this.setStatus(id, "removed"); | ||
this.events.emitRemove(id, cacheItem.file); | ||
} | ||
}; | ||
// src/utils/PluginDriver.ts | ||
@@ -240,3 +269,3 @@ var hookNames = { | ||
plugins; | ||
fileEmitter = new FileEmitter(); | ||
fileManager = new FileManager(); | ||
logger; | ||
@@ -248,16 +277,33 @@ config; | ||
this.config = config; | ||
this.emitFile = this.fileEmitter.emitFile.bind(this.fileEmitter); | ||
this.core = definePlugin({ config, fileEmitter: this.fileEmitter, load: this.load, resolveId: this.resolveId }); | ||
this.core = definePlugin({ | ||
config, | ||
fileManager: this.fileManager, | ||
load: this.load, | ||
resolveId: this.resolveId, | ||
resolveIdForPlugin: this.resolveIdForPlugin | ||
}); | ||
this.plugins = [this.core, ...config.plugins || []]; | ||
} | ||
emitFile(...params) { | ||
return this.fileEmitter.emitFile(...params); | ||
} | ||
resolveId = (source, importer, meta) => { | ||
return this.hookFirst("resolveId", [source, importer, meta]); | ||
resolveId = (importee, importer, options) => { | ||
return this.hookFirst("resolveId", [importee, importer, options]); | ||
}; | ||
resolveIdForPlugin = (pluginName) => (importee, importer, options) => { | ||
return this.hookForPlugin(pluginName, "resolveId", [importee, importer, options]); | ||
}; | ||
load = async (id) => { | ||
const result = await this.hookFirst("load", [id]); | ||
return result; | ||
return this.hookFirst("load", [id]); | ||
}; | ||
hookForPlugin(pluginName, hookName, parameters, skipped) { | ||
let promise = Promise.resolve(null); | ||
for (const plugin of this.getSortedPlugins(hookName, pluginName)) { | ||
if (skipped && skipped.has(plugin)) | ||
continue; | ||
promise = promise.then((result) => { | ||
if (result != null) | ||
return result; | ||
return this.run("hookFirst", hookName, parameters, plugin); | ||
}); | ||
} | ||
return promise; | ||
} | ||
hookFirst(hookName, parameters, skipped) { | ||
@@ -308,4 +354,8 @@ let promise = Promise.resolve(null); | ||
} | ||
getSortedPlugins(_hookName) { | ||
return [...this.plugins]; | ||
getSortedPlugins(_hookName, pluginName) { | ||
const sortedPlugins = [...this.plugins]; | ||
if (pluginName) { | ||
return sortedPlugins.filter((item) => item.name === pluginName); | ||
} | ||
return sortedPlugins; | ||
} | ||
@@ -375,12 +425,9 @@ run(strategy, hookName, parameters, plugin) { | ||
} | ||
pluginDriver.fileEmitter.on("new", async (emittedFile) => { | ||
if (!emittedFile) { | ||
return; | ||
pluginDriver.fileManager.events.onAdd(async (id, file) => { | ||
let fileName = file.fileName; | ||
let { name: name2, source: code } = file; | ||
if (!fileName && name2) { | ||
fileName = path2.resolve(config.root, config.output.path, name2); | ||
} | ||
const { id } = emittedFile; | ||
if (!id) { | ||
throw new Error("No id could be transformed, please add id to emitFile or use resolveId"); | ||
} | ||
let { source: code } = emittedFile; | ||
const loadedResult = await pluginDriver.hookFirst("load", [id]); | ||
const loadedResult = await pluginDriver.hookFirst("load", [fileName]); | ||
if (loadedResult) { | ||
@@ -390,14 +437,14 @@ code = loadedResult; | ||
if (code) { | ||
const transformedCode = await pluginDriver.hookReduceArg0("transform", [code, id], transformReducer); | ||
await pluginDriver.hookParallel("writeFile", [transformedCode, id]); | ||
pluginDriver.fileEmitter.delete(emittedFile.id); | ||
const transformedCode = await pluginDriver.hookReduceArg0("transform", [code, fileName], transformReducer); | ||
await pluginDriver.hookParallel("writeFile", [transformedCode, fileName]); | ||
pluginDriver.fileManager.setStatus(id, "success"); | ||
pluginDriver.fileManager.remove(id); | ||
} | ||
}); | ||
await pluginDriver.hookParallel("buildStart", [config]); | ||
pluginDriver.emitFile({ | ||
id: config.input.path, | ||
name: void 0, | ||
pluginDriver.fileManager.add({ | ||
fileName: path2.resolve(config.root, config.input.path), | ||
source: input | ||
}); | ||
pluginDriver.fileEmitter.on("end", async () => { | ||
pluginDriver.fileManager.events.onSuccess(async () => { | ||
await pluginDriver.hookParallel("buildEnd"); | ||
@@ -425,4 +472,3 @@ setTimeout(() => { | ||
exports.Emitter = Emitter; | ||
exports.FileEmitter = FileEmitter; | ||
exports.FileManager = FileManager; | ||
exports.PluginDriver = PluginDriver; | ||
@@ -429,0 +475,0 @@ exports.build = build; |
{ | ||
"name": "@kubb/core", | ||
"version": "0.20.0", | ||
"version": "0.21.0", | ||
"description": "Generator core", | ||
@@ -36,2 +36,3 @@ "repository": { | ||
"change-case": "^4.1.2", | ||
"events": "^3.3.0", | ||
"fs-extra": "^11.1.0", | ||
@@ -38,0 +39,0 @@ "prettier": "^2.8.1", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
105775
1235
5
+ Addedevents@^3.3.0
+ Addedevents@3.3.0(transitive)