@betterstart/cli 0.1.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/plugins/types.ts","../../src/plugins/manager.ts"],"sourcesContent":["/**\n * Plugin system types for @betterstart/cli\n * Re-exports types from config and adds plugin-specific utilities\n */\n\n// Re-export plugin types from config\nexport type {\n BetterstartPlugin,\n CustomGenerator,\n FieldTypeHandler,\n GeneratedFile,\n PluginCommand,\n PluginContext,\n PluginHooks\n} from '../config/types'\n\nimport type { BetterstartPlugin, GeneratedFile, PluginContext } from '../config/types'\n\n// ============================================================================\n// Plugin Lifecycle Events\n// ============================================================================\n\n/**\n * Events emitted during plugin lifecycle\n */\nexport type PluginEvent =\n | 'init'\n | 'beforeGenerate'\n | 'afterGenerate'\n | 'beforeWrite'\n | 'afterWrite'\n | 'error'\n\n/**\n * Event handler type\n */\nexport type PluginEventHandler<T = unknown> = (context: PluginContext, data: T) => Promise<void>\n\n// ============================================================================\n// Plugin Builder\n// ============================================================================\n\n/**\n * Options for creating a plugin\n */\nexport interface CreatePluginOptions {\n name: string\n version: string\n description?: string\n}\n\n/**\n * Plugin builder for fluent API\n */\nexport interface PluginBuilder {\n /** Add an onInit hook */\n onInit(handler: (context: PluginContext) => Promise<void>): PluginBuilder\n\n /** Add an onBeforeGenerate hook */\n onBeforeGenerate(\n handler: (context: PluginContext, schema: unknown) => Promise<void>\n ): PluginBuilder\n\n /** Add an onAfterGenerate hook */\n onAfterGenerate(\n handler: (context: PluginContext, files: GeneratedFile[]) => Promise<void>\n ): PluginBuilder\n\n /** Add a custom generator */\n addGenerator(\n name: string,\n description: string,\n generate: (context: PluginContext, schema: unknown) => Promise<GeneratedFile[]>\n ): PluginBuilder\n\n /** Add a custom field type */\n addFieldType(\n name: string,\n handler: {\n zodType: (field: unknown) => string\n drizzleType: (field: unknown, imports: Set<string>) => string\n typescriptType: (field: unknown, mode: 'input' | 'output') => string\n formComponent?: (field: unknown) => string\n }\n ): PluginBuilder\n\n /** Add a CLI command */\n addCommand(\n name: string,\n description: string,\n options: Array<{ flags: string; description: string; default?: unknown }>,\n handler: (options: Record<string, unknown>) => Promise<void>\n ): PluginBuilder\n\n /** Build the plugin */\n build(): BetterstartPlugin\n}\n\n/**\n * Create a plugin using the builder pattern\n */\nexport function createPlugin(options: CreatePluginOptions): PluginBuilder {\n const plugin: BetterstartPlugin = {\n name: options.name,\n version: options.version,\n description: options.description,\n hooks: {},\n generators: {},\n fieldTypes: {},\n commands: []\n }\n\n const builder: PluginBuilder = {\n onInit(handler) {\n plugin.hooks = plugin.hooks || {}\n plugin.hooks.onInit = handler\n return builder\n },\n\n onBeforeGenerate(handler) {\n plugin.hooks = plugin.hooks || {}\n plugin.hooks.onBeforeGenerate = handler\n return builder\n },\n\n onAfterGenerate(handler) {\n plugin.hooks = plugin.hooks || {}\n plugin.hooks.onAfterGenerate = handler\n return builder\n },\n\n addGenerator(name, description, generate) {\n plugin.generators = plugin.generators || {}\n plugin.generators[name] = { name, description, generate }\n return builder\n },\n\n addFieldType(name, handler) {\n plugin.fieldTypes = plugin.fieldTypes || {}\n plugin.fieldTypes[name] = handler\n return builder\n },\n\n addCommand(name, description, options, handler) {\n plugin.commands = plugin.commands || []\n plugin.commands.push({ name, description, options, handler })\n return builder\n },\n\n build() {\n return plugin\n }\n }\n\n return builder\n}\n\n// ============================================================================\n// Plugin Utilities\n// ============================================================================\n\n/**\n * Check if a plugin has a specific hook\n */\nexport function hasHook(\n plugin: BetterstartPlugin,\n hook: keyof NonNullable<BetterstartPlugin['hooks']>\n): boolean {\n return plugin.hooks !== undefined && typeof plugin.hooks[hook] === 'function'\n}\n\n/**\n * Check if a plugin provides a specific generator\n */\nexport function hasGenerator(plugin: BetterstartPlugin, generatorName: string): boolean {\n return plugin.generators !== undefined && generatorName in plugin.generators\n}\n\n/**\n * Check if a plugin provides a specific field type\n */\nexport function hasFieldType(plugin: BetterstartPlugin, fieldTypeName: string): boolean {\n return plugin.fieldTypes !== undefined && fieldTypeName in plugin.fieldTypes\n}\n\n/**\n * Check if a plugin provides a specific command\n */\nexport function hasCommand(plugin: BetterstartPlugin, commandName: string): boolean {\n return plugin.commands?.some((cmd) => cmd.name === commandName) ?? false\n}\n\n/**\n * Get all generator names from a plugin\n */\nexport function getGeneratorNames(plugin: BetterstartPlugin): string[] {\n return plugin.generators ? Object.keys(plugin.generators) : []\n}\n\n/**\n * Get all field type names from a plugin\n */\nexport function getFieldTypeNames(plugin: BetterstartPlugin): string[] {\n return plugin.fieldTypes ? Object.keys(plugin.fieldTypes) : []\n}\n\n/**\n * Get all command names from a plugin\n */\nexport function getCommandNames(plugin: BetterstartPlugin): string[] {\n return plugin.commands ? plugin.commands.map((cmd) => cmd.name) : []\n}\n","/**\n * Plugin manager for @betterstart/cli\n * Handles plugin registration, lifecycle, and execution\n */\n\nimport type {\n BetterstartPlugin,\n CustomGenerator,\n FieldTypeHandler,\n GeneratedFile,\n PluginCommand,\n PluginContext\n} from '../config/types'\nimport { PluginError } from '../core/errors'\nimport { getLogger } from '../core/logger'\nimport { getCommandNames, getFieldTypeNames, getGeneratorNames, hasHook } from './types'\n\n// ============================================================================\n// Plugin Manager\n// ============================================================================\n\n/**\n * Plugin manager for handling plugin lifecycle and registration\n */\nexport class PluginManager {\n private plugins: Map<string, BetterstartPlugin> = new Map()\n private initialized = false\n\n /**\n * Register a plugin\n */\n register(plugin: BetterstartPlugin): void {\n if (this.plugins.has(plugin.name)) {\n throw new PluginError(`Plugin \"${plugin.name}\" is already registered`, plugin.name)\n }\n\n const logger = getLogger()\n logger.debug(`Registering plugin: ${plugin.name}@${plugin.version}`)\n\n this.plugins.set(plugin.name, plugin)\n }\n\n /**\n * Register multiple plugins\n */\n registerAll(plugins: BetterstartPlugin[]): void {\n for (const plugin of plugins) {\n this.register(plugin)\n }\n }\n\n /**\n * Unregister a plugin\n */\n unregister(pluginName: string): boolean {\n return this.plugins.delete(pluginName)\n }\n\n /**\n * Get a registered plugin by name\n */\n get(pluginName: string): BetterstartPlugin | undefined {\n return this.plugins.get(pluginName)\n }\n\n /**\n * Get all registered plugins\n */\n getAll(): BetterstartPlugin[] {\n return Array.from(this.plugins.values())\n }\n\n /**\n * Check if a plugin is registered\n */\n has(pluginName: string): boolean {\n return this.plugins.has(pluginName)\n }\n\n /**\n * Initialize all plugins\n */\n async initialize(context: PluginContext): Promise<void> {\n if (this.initialized) {\n return\n }\n\n const logger = getLogger()\n\n for (const plugin of this.plugins.values()) {\n if (hasHook(plugin, 'onInit')) {\n try {\n logger.debug(`Initializing plugin: ${plugin.name}`)\n await plugin.hooks!.onInit!(context)\n } catch (error) {\n throw new PluginError(\n `Failed to initialize plugin \"${plugin.name}\": ${error instanceof Error ? error.message : String(error)}`,\n plugin.name,\n { originalError: error }\n )\n }\n }\n }\n\n this.initialized = true\n }\n\n /**\n * Run beforeGenerate hooks on all plugins\n */\n async runBeforeGenerate(context: PluginContext, schema: unknown): Promise<void> {\n const logger = getLogger()\n\n for (const plugin of this.plugins.values()) {\n if (hasHook(plugin, 'onBeforeGenerate')) {\n try {\n logger.debug(`Running beforeGenerate for plugin: ${plugin.name}`)\n await plugin.hooks!.onBeforeGenerate!(context, schema)\n } catch (error) {\n throw new PluginError(\n `Plugin \"${plugin.name}\" failed in beforeGenerate: ${error instanceof Error ? error.message : String(error)}`,\n plugin.name,\n { originalError: error }\n )\n }\n }\n }\n }\n\n /**\n * Run afterGenerate hooks on all plugins\n */\n async runAfterGenerate(context: PluginContext, files: GeneratedFile[]): Promise<void> {\n const logger = getLogger()\n\n for (const plugin of this.plugins.values()) {\n if (hasHook(plugin, 'onAfterGenerate')) {\n try {\n logger.debug(`Running afterGenerate for plugin: ${plugin.name}`)\n await plugin.hooks!.onAfterGenerate!(context, files)\n } catch (error) {\n throw new PluginError(\n `Plugin \"${plugin.name}\" failed in afterGenerate: ${error instanceof Error ? error.message : String(error)}`,\n plugin.name,\n { originalError: error }\n )\n }\n }\n }\n }\n\n // ============================================================================\n // Generator Access\n // ============================================================================\n\n /**\n * Get a generator by name from any registered plugin\n */\n getGenerator(name: string): CustomGenerator | undefined {\n for (const plugin of this.plugins.values()) {\n if (plugin.generators && name in plugin.generators) {\n return plugin.generators[name]\n }\n }\n return undefined\n }\n\n /**\n * Get all generators from all plugins\n */\n getAllGenerators(): Map<string, { plugin: string; generator: CustomGenerator }> {\n const generators = new Map<string, { plugin: string; generator: CustomGenerator }>()\n\n for (const plugin of this.plugins.values()) {\n if (plugin.generators) {\n for (const [name, generator] of Object.entries(plugin.generators)) {\n generators.set(name, { plugin: plugin.name, generator })\n }\n }\n }\n\n return generators\n }\n\n /**\n * Get all generator names\n */\n getGeneratorNames(): string[] {\n const names: string[] = []\n for (const plugin of this.plugins.values()) {\n names.push(...getGeneratorNames(plugin))\n }\n return names\n }\n\n // ============================================================================\n // Field Type Access\n // ============================================================================\n\n /**\n * Get a field type handler by name from any registered plugin\n */\n getFieldType(name: string): FieldTypeHandler | undefined {\n for (const plugin of this.plugins.values()) {\n if (plugin.fieldTypes && name in plugin.fieldTypes) {\n return plugin.fieldTypes[name]\n }\n }\n return undefined\n }\n\n /**\n * Get all field types from all plugins\n */\n getAllFieldTypes(): Map<string, { plugin: string; handler: FieldTypeHandler }> {\n const fieldTypes = new Map<string, { plugin: string; handler: FieldTypeHandler }>()\n\n for (const plugin of this.plugins.values()) {\n if (plugin.fieldTypes) {\n for (const [name, handler] of Object.entries(plugin.fieldTypes)) {\n fieldTypes.set(name, { plugin: plugin.name, handler })\n }\n }\n }\n\n return fieldTypes\n }\n\n /**\n * Get all field type names\n */\n getFieldTypeNames(): string[] {\n const names: string[] = []\n for (const plugin of this.plugins.values()) {\n names.push(...getFieldTypeNames(plugin))\n }\n return names\n }\n\n // ============================================================================\n // Command Access\n // ============================================================================\n\n /**\n * Get a command by name from any registered plugin\n */\n getCommand(name: string): PluginCommand | undefined {\n for (const plugin of this.plugins.values()) {\n if (plugin.commands) {\n const command = plugin.commands.find((cmd) => cmd.name === name)\n if (command) {\n return command\n }\n }\n }\n return undefined\n }\n\n /**\n * Get all commands from all plugins\n */\n getAllCommands(): Map<string, { plugin: string; command: PluginCommand }> {\n const commands = new Map<string, { plugin: string; command: PluginCommand }>()\n\n for (const plugin of this.plugins.values()) {\n if (plugin.commands) {\n for (const command of plugin.commands) {\n commands.set(command.name, { plugin: plugin.name, command })\n }\n }\n }\n\n return commands\n }\n\n /**\n * Get all command names\n */\n getCommandNames(): string[] {\n const names: string[] = []\n for (const plugin of this.plugins.values()) {\n names.push(...getCommandNames(plugin))\n }\n return names\n }\n\n // ============================================================================\n // Utility Methods\n // ============================================================================\n\n /**\n * Get plugin summary\n */\n getSummary(): PluginSummary {\n const plugins: PluginInfo[] = []\n\n for (const plugin of this.plugins.values()) {\n plugins.push({\n name: plugin.name,\n version: plugin.version,\n description: plugin.description,\n generators: getGeneratorNames(plugin),\n fieldTypes: getFieldTypeNames(plugin),\n commands: getCommandNames(plugin)\n })\n }\n\n return {\n count: this.plugins.size,\n plugins\n }\n }\n\n /**\n * Clear all registered plugins\n */\n clear(): void {\n this.plugins.clear()\n this.initialized = false\n }\n}\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface PluginInfo {\n name: string\n version: string\n description?: string\n generators: string[]\n fieldTypes: string[]\n commands: string[]\n}\n\nexport interface PluginSummary {\n count: number\n plugins: PluginInfo[]\n}\n\n// ============================================================================\n// Singleton Instance\n// ============================================================================\n\nlet globalPluginManager: PluginManager | null = null\n\n/**\n * Get the global plugin manager instance\n */\nexport function getPluginManager(): PluginManager {\n if (!globalPluginManager) {\n globalPluginManager = new PluginManager()\n }\n return globalPluginManager\n}\n\n/**\n * Create a new plugin manager instance\n */\nexport function createPluginManager(): PluginManager {\n return new PluginManager()\n}\n\n/**\n * Reset the global plugin manager\n */\nexport function resetPluginManager(): void {\n if (globalPluginManager) {\n globalPluginManager.clear()\n }\n globalPluginManager = null\n}\n"],"mappings":";;;;;;AAqGO,SAAS,aAAa,SAA6C;AACxE,QAAM,SAA4B;AAAA,IAChC,MAAM,QAAQ;AAAA,IACd,SAAS,QAAQ;AAAA,IACjB,aAAa,QAAQ;AAAA,IACrB,OAAO,CAAC;AAAA,IACR,YAAY,CAAC;AAAA,IACb,YAAY,CAAC;AAAA,IACb,UAAU,CAAC;AAAA,EACb;AAEA,QAAM,UAAyB;AAAA,IAC7B,OAAO,SAAS;AACd,aAAO,QAAQ,OAAO,SAAS,CAAC;AAChC,aAAO,MAAM,SAAS;AACtB,aAAO;AAAA,IACT;AAAA,IAEA,iBAAiB,SAAS;AACxB,aAAO,QAAQ,OAAO,SAAS,CAAC;AAChC,aAAO,MAAM,mBAAmB;AAChC,aAAO;AAAA,IACT;AAAA,IAEA,gBAAgB,SAAS;AACvB,aAAO,QAAQ,OAAO,SAAS,CAAC;AAChC,aAAO,MAAM,kBAAkB;AAC/B,aAAO;AAAA,IACT;AAAA,IAEA,aAAa,MAAM,aAAa,UAAU;AACxC,aAAO,aAAa,OAAO,cAAc,CAAC;AAC1C,aAAO,WAAW,IAAI,IAAI,EAAE,MAAM,aAAa,SAAS;AACxD,aAAO;AAAA,IACT;AAAA,IAEA,aAAa,MAAM,SAAS;AAC1B,aAAO,aAAa,OAAO,cAAc,CAAC;AAC1C,aAAO,WAAW,IAAI,IAAI;AAC1B,aAAO;AAAA,IACT;AAAA,IAEA,WAAW,MAAM,aAAaA,UAAS,SAAS;AAC9C,aAAO,WAAW,OAAO,YAAY,CAAC;AACtC,aAAO,SAAS,KAAK,EAAE,MAAM,aAAa,SAAAA,UAAS,QAAQ,CAAC;AAC5D,aAAO;AAAA,IACT;AAAA,IAEA,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AASO,SAAS,QACd,QACA,MACS;AACT,SAAO,OAAO,UAAU,UAAa,OAAO,OAAO,MAAM,IAAI,MAAM;AACrE;AAKO,SAAS,aAAa,QAA2B,eAAgC;AACtF,SAAO,OAAO,eAAe,UAAa,iBAAiB,OAAO;AACpE;AAKO,SAAS,aAAa,QAA2B,eAAgC;AACtF,SAAO,OAAO,eAAe,UAAa,iBAAiB,OAAO;AACpE;AAKO,SAAS,WAAW,QAA2B,aAA8B;AAClF,SAAO,OAAO,UAAU,KAAK,CAAC,QAAQ,IAAI,SAAS,WAAW,KAAK;AACrE;AAKO,SAAS,kBAAkB,QAAqC;AACrE,SAAO,OAAO,aAAa,OAAO,KAAK,OAAO,UAAU,IAAI,CAAC;AAC/D;AAKO,SAAS,kBAAkB,QAAqC;AACrE,SAAO,OAAO,aAAa,OAAO,KAAK,OAAO,UAAU,IAAI,CAAC;AAC/D;AAKO,SAAS,gBAAgB,QAAqC;AACnE,SAAO,OAAO,WAAW,OAAO,SAAS,IAAI,CAAC,QAAQ,IAAI,IAAI,IAAI,CAAC;AACrE;;;AC3LO,IAAM,gBAAN,MAAoB;AAAA,EACjB,UAA0C,oBAAI,IAAI;AAAA,EAClD,cAAc;AAAA;AAAA;AAAA;AAAA,EAKtB,SAAS,QAAiC;AACxC,QAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,GAAG;AACjC,YAAM,IAAI,YAAY,WAAW,OAAO,IAAI,2BAA2B,OAAO,IAAI;AAAA,IACpF;AAEA,UAAM,SAAS,UAAU;AACzB,WAAO,MAAM,uBAAuB,OAAO,IAAI,IAAI,OAAO,OAAO,EAAE;AAEnE,SAAK,QAAQ,IAAI,OAAO,MAAM,MAAM;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,SAAoC;AAC9C,eAAW,UAAU,SAAS;AAC5B,WAAK,SAAS,MAAM;AAAA,IACtB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,YAA6B;AACtC,WAAO,KAAK,QAAQ,OAAO,UAAU;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,YAAmD;AACrD,WAAO,KAAK,QAAQ,IAAI,UAAU;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA,EAKA,SAA8B;AAC5B,WAAO,MAAM,KAAK,KAAK,QAAQ,OAAO,CAAC;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,YAA6B;AAC/B,WAAO,KAAK,QAAQ,IAAI,UAAU;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAW,SAAuC;AACtD,QAAI,KAAK,aAAa;AACpB;AAAA,IACF;AAEA,UAAM,SAAS,UAAU;AAEzB,eAAW,UAAU,KAAK,QAAQ,OAAO,GAAG;AAC1C,UAAI,QAAQ,QAAQ,QAAQ,GAAG;AAC7B,YAAI;AACF,iBAAO,MAAM,wBAAwB,OAAO,IAAI,EAAE;AAClD,gBAAM,OAAO,MAAO,OAAQ,OAAO;AAAA,QACrC,SAAS,OAAO;AACd,gBAAM,IAAI;AAAA,YACR,gCAAgC,OAAO,IAAI,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,YACvG,OAAO;AAAA,YACP,EAAE,eAAe,MAAM;AAAA,UACzB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,SAAK,cAAc;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,kBAAkB,SAAwB,QAAgC;AAC9E,UAAM,SAAS,UAAU;AAEzB,eAAW,UAAU,KAAK,QAAQ,OAAO,GAAG;AAC1C,UAAI,QAAQ,QAAQ,kBAAkB,GAAG;AACvC,YAAI;AACF,iBAAO,MAAM,sCAAsC,OAAO,IAAI,EAAE;AAChE,gBAAM,OAAO,MAAO,iBAAkB,SAAS,MAAM;AAAA,QACvD,SAAS,OAAO;AACd,gBAAM,IAAI;AAAA,YACR,WAAW,OAAO,IAAI,+BAA+B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,YAC3G,OAAO;AAAA,YACP,EAAE,eAAe,MAAM;AAAA,UACzB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAAiB,SAAwB,OAAuC;AACpF,UAAM,SAAS,UAAU;AAEzB,eAAW,UAAU,KAAK,QAAQ,OAAO,GAAG;AAC1C,UAAI,QAAQ,QAAQ,iBAAiB,GAAG;AACtC,YAAI;AACF,iBAAO,MAAM,qCAAqC,OAAO,IAAI,EAAE;AAC/D,gBAAM,OAAO,MAAO,gBAAiB,SAAS,KAAK;AAAA,QACrD,SAAS,OAAO;AACd,gBAAM,IAAI;AAAA,YACR,WAAW,OAAO,IAAI,8BAA8B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,YAC1G,OAAO;AAAA,YACP,EAAE,eAAe,MAAM;AAAA,UACzB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,aAAa,MAA2C;AACtD,eAAW,UAAU,KAAK,QAAQ,OAAO,GAAG;AAC1C,UAAI,OAAO,cAAc,QAAQ,OAAO,YAAY;AAClD,eAAO,OAAO,WAAW,IAAI;AAAA,MAC/B;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAgF;AAC9E,UAAM,aAAa,oBAAI,IAA4D;AAEnF,eAAW,UAAU,KAAK,QAAQ,OAAO,GAAG;AAC1C,UAAI,OAAO,YAAY;AACrB,mBAAW,CAAC,MAAM,SAAS,KAAK,OAAO,QAAQ,OAAO,UAAU,GAAG;AACjE,qBAAW,IAAI,MAAM,EAAE,QAAQ,OAAO,MAAM,UAAU,CAAC;AAAA,QACzD;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,oBAA8B;AAC5B,UAAM,QAAkB,CAAC;AACzB,eAAW,UAAU,KAAK,QAAQ,OAAO,GAAG;AAC1C,YAAM,KAAK,GAAG,kBAAkB,MAAM,CAAC;AAAA,IACzC;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,aAAa,MAA4C;AACvD,eAAW,UAAU,KAAK,QAAQ,OAAO,GAAG;AAC1C,UAAI,OAAO,cAAc,QAAQ,OAAO,YAAY;AAClD,eAAO,OAAO,WAAW,IAAI;AAAA,MAC/B;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,mBAA+E;AAC7E,UAAM,aAAa,oBAAI,IAA2D;AAElF,eAAW,UAAU,KAAK,QAAQ,OAAO,GAAG;AAC1C,UAAI,OAAO,YAAY;AACrB,mBAAW,CAAC,MAAM,OAAO,KAAK,OAAO,QAAQ,OAAO,UAAU,GAAG;AAC/D,qBAAW,IAAI,MAAM,EAAE,QAAQ,OAAO,MAAM,QAAQ,CAAC;AAAA,QACvD;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,oBAA8B;AAC5B,UAAM,QAAkB,CAAC;AACzB,eAAW,UAAU,KAAK,QAAQ,OAAO,GAAG;AAC1C,YAAM,KAAK,GAAG,kBAAkB,MAAM,CAAC;AAAA,IACzC;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,WAAW,MAAyC;AAClD,eAAW,UAAU,KAAK,QAAQ,OAAO,GAAG;AAC1C,UAAI,OAAO,UAAU;AACnB,cAAM,UAAU,OAAO,SAAS,KAAK,CAAC,QAAQ,IAAI,SAAS,IAAI;AAC/D,YAAI,SAAS;AACX,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,iBAA0E;AACxE,UAAM,WAAW,oBAAI,IAAwD;AAE7E,eAAW,UAAU,KAAK,QAAQ,OAAO,GAAG;AAC1C,UAAI,OAAO,UAAU;AACnB,mBAAW,WAAW,OAAO,UAAU;AACrC,mBAAS,IAAI,QAAQ,MAAM,EAAE,QAAQ,OAAO,MAAM,QAAQ,CAAC;AAAA,QAC7D;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,kBAA4B;AAC1B,UAAM,QAAkB,CAAC;AACzB,eAAW,UAAU,KAAK,QAAQ,OAAO,GAAG;AAC1C,YAAM,KAAK,GAAG,gBAAgB,MAAM,CAAC;AAAA,IACvC;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,aAA4B;AAC1B,UAAM,UAAwB,CAAC;AAE/B,eAAW,UAAU,KAAK,QAAQ,OAAO,GAAG;AAC1C,cAAQ,KAAK;AAAA,QACX,MAAM,OAAO;AAAA,QACb,SAAS,OAAO;AAAA,QAChB,aAAa,OAAO;AAAA,QACpB,YAAY,kBAAkB,MAAM;AAAA,QACpC,YAAY,kBAAkB,MAAM;AAAA,QACpC,UAAU,gBAAgB,MAAM;AAAA,MAClC,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,MACL,OAAO,KAAK,QAAQ;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACZ,SAAK,QAAQ,MAAM;AACnB,SAAK,cAAc;AAAA,EACrB;AACF;AAwBA,IAAI,sBAA4C;AAKzC,SAAS,mBAAkC;AAChD,MAAI,CAAC,qBAAqB;AACxB,0BAAsB,IAAI,cAAc;AAAA,EAC1C;AACA,SAAO;AACT;AAKO,SAAS,sBAAqC;AACnD,SAAO,IAAI,cAAc;AAC3B;AAKO,SAAS,qBAA2B;AACzC,MAAI,qBAAqB;AACvB,wBAAoB,MAAM;AAAA,EAC5B;AACA,wBAAsB;AACxB;","names":["options"]}
@@ -0,0 +1,331 @@
1
+ import { a as Logger } from './logger-awLb347n.js';
2
+
3
+ /**
4
+ * Configuration types for the @betterstart/cli package
5
+ * Defines the configuration schema for project setup and generation
6
+ */
7
+ /**
8
+ * Output path configuration for generated files
9
+ */
10
+ interface OutputPaths {
11
+ /** Where to generate server actions (relative to lib path) */
12
+ actions: string;
13
+ /** Where to generate React Query hooks (relative to hooks path) */
14
+ hooks: string;
15
+ /** Where to generate UI components (relative to app path) */
16
+ components: string;
17
+ /** Where to generate admin pages (relative to app path) */
18
+ pages: string;
19
+ /** Where to generate email templates (relative to app path) */
20
+ emails: string;
21
+ }
22
+ /**
23
+ * Project structure paths configuration
24
+ */
25
+ interface ProjectPaths {
26
+ /** Main app directory (e.g., 'apps/web', 'src', '.') */
27
+ app: string;
28
+ /** Database package directory (e.g., 'packages/database', 'src/db') */
29
+ database: string;
30
+ /** Lib package directory (e.g., 'packages/lib', 'src/lib') */
31
+ lib: string;
32
+ /** Hooks package directory (e.g., 'packages/hooks', 'src/hooks') */
33
+ hooks: string;
34
+ /** Schemas directory (e.g., 'schemas', 'src/schemas') */
35
+ schemas: string;
36
+ /** Output paths for generated files */
37
+ output: OutputPaths;
38
+ }
39
+ /**
40
+ * Supported database providers
41
+ */
42
+ type DatabaseProvider = 'drizzle';
43
+ /**
44
+ * Database configuration
45
+ */
46
+ interface DatabaseConfig {
47
+ /** Database ORM provider (currently only 'drizzle' is supported) */
48
+ provider: DatabaseProvider;
49
+ /** Path to the schema file relative to database directory */
50
+ schemaFile: string;
51
+ /** Path to migrations directory relative to database directory */
52
+ migrationsDir: string;
53
+ /** Whether to auto-run migrations after generation */
54
+ autoMigrate: boolean;
55
+ }
56
+ /**
57
+ * Supported UI frameworks
58
+ */
59
+ type UIFramework = 'shadcn';
60
+ /**
61
+ * UI framework configuration
62
+ */
63
+ interface UIConfig {
64
+ /** UI component framework (currently only 'shadcn' is supported) */
65
+ framework: UIFramework;
66
+ /** Component library configuration */
67
+ components: {
68
+ /** Import path for UI components (e.g., '@/components/ui', '@betterstart/admin-ui') */
69
+ path: string;
70
+ /** Import path for admin components (e.g., '@/components/admin', '@betterstart/admin-ui') */
71
+ adminPath: string;
72
+ };
73
+ }
74
+ /**
75
+ * Generator configuration
76
+ */
77
+ interface GeneratorConfig {
78
+ /** Core generators that are always included */
79
+ core: string[];
80
+ /** Optional generators that can be enabled */
81
+ optional: string[];
82
+ }
83
+ /**
84
+ * Generator names type (for convenience)
85
+ */
86
+ type GeneratorName = string;
87
+ /**
88
+ * Plugin lifecycle hooks
89
+ */
90
+ interface PluginHooks {
91
+ /** Called when plugin is initialized */
92
+ onInit?: (context: PluginContext) => Promise<void>;
93
+ /** Called before generation starts */
94
+ onBeforeGenerate?: (context: PluginContext, schema: unknown) => Promise<void>;
95
+ /** Called after generation completes */
96
+ onAfterGenerate?: (context: PluginContext, files: GeneratedFile[]) => Promise<void>;
97
+ }
98
+ /**
99
+ * Plugin context passed to lifecycle hooks
100
+ */
101
+ interface PluginContext {
102
+ /** The resolved configuration */
103
+ config: BetterstartConfig;
104
+ /** Resolved paths */
105
+ paths: ResolvedPaths;
106
+ /** Logger instance */
107
+ logger: Logger;
108
+ }
109
+ /**
110
+ * Generated file metadata
111
+ */
112
+ interface GeneratedFile {
113
+ /** Absolute path to the generated file */
114
+ path: string;
115
+ /** Type of file generated */
116
+ type: 'action' | 'hook' | 'component' | 'page' | 'database' | 'migration' | 'navigation' | 'other';
117
+ /** Whether the file was created or updated */
118
+ operation: 'created' | 'updated' | 'skipped';
119
+ }
120
+ /**
121
+ * Custom field type handler for plugins
122
+ */
123
+ interface FieldTypeHandler {
124
+ /** Generate Zod validation type */
125
+ zodType: (field: unknown) => string;
126
+ /** Generate Drizzle column type */
127
+ drizzleType: (field: unknown, imports: Set<string>) => string;
128
+ /** Generate TypeScript type */
129
+ typescriptType: (field: unknown, mode: 'input' | 'output') => string;
130
+ /** Generate form component */
131
+ formComponent?: (field: unknown) => string;
132
+ }
133
+ /**
134
+ * Custom generator for plugins
135
+ */
136
+ interface CustomGenerator {
137
+ /** Generator name */
138
+ name: string;
139
+ /** Generator description */
140
+ description: string;
141
+ /** Generator function */
142
+ generate: (context: PluginContext, schema: unknown) => Promise<GeneratedFile[]>;
143
+ }
144
+ /**
145
+ * CLI command for plugins
146
+ */
147
+ interface PluginCommand {
148
+ /** Command name */
149
+ name: string;
150
+ /** Command description */
151
+ description: string;
152
+ /** Command options */
153
+ options?: Array<{
154
+ flags: string;
155
+ description: string;
156
+ default?: unknown;
157
+ }>;
158
+ /** Command handler */
159
+ handler: (options: Record<string, unknown>) => Promise<void>;
160
+ }
161
+ /**
162
+ * Plugin definition
163
+ */
164
+ interface BetterstartPlugin {
165
+ /** Plugin name */
166
+ name: string;
167
+ /** Plugin version */
168
+ version: string;
169
+ /** Plugin description */
170
+ description?: string;
171
+ /** Lifecycle hooks */
172
+ hooks?: PluginHooks;
173
+ /** Custom generators provided by this plugin */
174
+ generators?: Record<string, CustomGenerator>;
175
+ /** Custom field types provided by this plugin */
176
+ fieldTypes?: Record<string, FieldTypeHandler>;
177
+ /** CLI commands provided by this plugin */
178
+ commands?: PluginCommand[];
179
+ }
180
+ /**
181
+ * Import path mappings for generated code.
182
+ * These control the `from '...'` part of import statements
183
+ * in all generated TypeScript/React files.
184
+ */
185
+ interface ImportPaths {
186
+ /** Database package import path (e.g., '@betterstart/database', '@/lib/db') */
187
+ database: string;
188
+ /** Admin UI components import path (e.g., '@betterstart/admin-ui', '@/components/ui') */
189
+ adminUi: string;
190
+ /** Public/web UI components import path (e.g., '@betterstart/web-ui', '@/components/ui') */
191
+ webUi: string;
192
+ /** Hooks package import path (e.g., '@betterstart/hooks', '@/hooks') */
193
+ hooks: string;
194
+ /** Utils package import path (e.g., '@betterstart/utils', '@/lib/utils') */
195
+ utils: string;
196
+ /** Types package import path (e.g., '@betterstart/types', '@/types') */
197
+ types: string;
198
+ /** Lib package base import path (e.g., '@betterstart/lib', '@/lib') */
199
+ lib: string;
200
+ /**
201
+ * Pattern for action imports. Use `{name}` as placeholder for the schema name.
202
+ * @example '@betterstart/lib/actions/{name}' (monorepo)
203
+ * @example '@/lib/actions/{name}' (standalone)
204
+ */
205
+ actions: string;
206
+ /** Lib markdown sub-module import path (e.g., '@betterstart/lib/markdown', '@/lib/markdown') */
207
+ libMarkdown: string;
208
+ }
209
+ /**
210
+ * Main configuration for @betterstart/cli
211
+ */
212
+ interface BetterstartConfig {
213
+ /** Project structure paths */
214
+ paths: ProjectPaths;
215
+ /** Import path mappings for generated code */
216
+ imports: ImportPaths;
217
+ /** Database configuration */
218
+ database: DatabaseConfig;
219
+ /** UI framework configuration */
220
+ ui: UIConfig;
221
+ /** Generator configuration */
222
+ generators: GeneratorConfig;
223
+ /** Registered plugins */
224
+ plugins: BetterstartPlugin[];
225
+ }
226
+ /**
227
+ * Partial configuration for user-provided config files
228
+ * All fields are optional and will be merged with defaults
229
+ */
230
+ type UserConfig = DeepPartial<BetterstartConfig>;
231
+ /**
232
+ * Deep partial type utility
233
+ */
234
+ type DeepPartial<T> = {
235
+ [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
236
+ };
237
+ /**
238
+ * Resolved paths with absolute paths
239
+ */
240
+ interface ResolvedPaths {
241
+ /** Project root directory (absolute) */
242
+ root: string;
243
+ /** Main app directory (absolute) */
244
+ app: string;
245
+ /** Database package directory (absolute) */
246
+ database: string;
247
+ /** Lib package directory (absolute) */
248
+ lib: string;
249
+ /** Hooks package directory (absolute) */
250
+ hooks: string;
251
+ /** Schemas directory (absolute) */
252
+ schemas: string;
253
+ /** Output paths for generated files (absolute) */
254
+ output: {
255
+ actions: string;
256
+ hooks: string;
257
+ components: string;
258
+ pages: string;
259
+ emails: string;
260
+ };
261
+ }
262
+ /**
263
+ * Fully resolved configuration with absolute paths
264
+ */
265
+ interface ResolvedConfig extends Omit<BetterstartConfig, 'paths'> {
266
+ /** Resolved paths with absolute paths */
267
+ paths: ResolvedPaths;
268
+ }
269
+ /**
270
+ * Project type detection result
271
+ */
272
+ type ProjectType = 'nextjs-monorepo' | 'nextjs-standalone' | 'custom' | 'unknown';
273
+ /**
274
+ * Preset configuration
275
+ */
276
+ interface Preset {
277
+ /** Preset name */
278
+ name: string;
279
+ /** Preset description */
280
+ description: string;
281
+ /** Detect if this preset applies to the current project */
282
+ detect?: (cwd: string) => boolean | Promise<boolean>;
283
+ /** Configuration for this preset */
284
+ config: UserConfig;
285
+ }
286
+ /**
287
+ * Options passed to generators
288
+ */
289
+ interface GeneratorOptions {
290
+ /** Skip database migration */
291
+ skipMigration?: boolean;
292
+ /** Number of dummy records to generate */
293
+ dummyCount?: number;
294
+ /** Force overwrite existing files */
295
+ force?: boolean;
296
+ /** Specific generators to run (overrides config) */
297
+ generators?: GeneratorName[];
298
+ /** Project root override */
299
+ projectRoot?: string;
300
+ }
301
+ /**
302
+ * CLI init command options
303
+ */
304
+ interface InitOptions {
305
+ /** Preset to use */
306
+ preset?: string;
307
+ /** Skip interactive prompts */
308
+ yes?: boolean;
309
+ /** Project root path */
310
+ cwd?: string;
311
+ }
312
+ /**
313
+ * CLI generate command options
314
+ */
315
+ interface GenerateOptions extends GeneratorOptions {
316
+ /** Schema name to generate */
317
+ schemaName: string;
318
+ }
319
+ /**
320
+ * CLI remove command options
321
+ */
322
+ interface RemoveOptions {
323
+ /** Schema name to remove */
324
+ schemaName: string;
325
+ /** Skip confirmation prompt */
326
+ force?: boolean;
327
+ /** Project root path */
328
+ projectRoot?: string;
329
+ }
330
+
331
+ export type { BetterstartConfig as B, CustomGenerator as C, DatabaseProvider as D, FieldTypeHandler as F, GeneratorConfig as G, ImportPaths as I, OutputPaths as O, Preset as P, ResolvedPaths as R, UserConfig as U, ResolvedConfig as a, ProjectPaths as b, DatabaseConfig as c, UIFramework as d, UIConfig as e, GeneratorName as f, PluginHooks as g, PluginContext as h, GeneratedFile as i, PluginCommand as j, BetterstartPlugin as k, DeepPartial as l, ProjectType as m, GeneratorOptions as n, InitOptions as o, GenerateOptions as p, RemoveOptions as q };
@@ -0,0 +1,232 @@
1
+ type FieldType = 'string' | 'number' | 'boolean' | 'date' | 'timestamp' | 'serial' | 'text' | 'markdown' | 'richtext' | 'decimal' | 'varchar' | 'image' | 'icon' | 'list' | 'group' | 'time' | 'select' | 'tabs' | 'relationship' | 'separator' | 'video' | 'media' | 'curriculum';
2
+ type ColumnType = 'text' | 'badge' | 'date' | 'custom' | 'avatar' | 'link' | 'image' | 'email' | 'number' | 'boolean';
3
+ interface SchemaField {
4
+ name: string;
5
+ type: FieldType;
6
+ label?: string;
7
+ required?: boolean;
8
+ primaryKey?: boolean;
9
+ default?: string | number | boolean;
10
+ format?: string;
11
+ length?: number;
12
+ precision?: number;
13
+ scale?: number;
14
+ maxItems?: number;
15
+ columns?: number;
16
+ fields?: SchemaField[];
17
+ items?: {
18
+ name: string;
19
+ type: FieldType;
20
+ label?: string;
21
+ required?: boolean;
22
+ length?: number;
23
+ };
24
+ options?: {
25
+ label: string;
26
+ value: string;
27
+ }[];
28
+ tabs?: {
29
+ name: string;
30
+ label: string;
31
+ fields: SchemaField[];
32
+ }[];
33
+ hint?: string;
34
+ hidden?: boolean;
35
+ hasIcon?: boolean;
36
+ relationship?: string;
37
+ multiple?: boolean;
38
+ showWhen?: {
39
+ field: string;
40
+ value: boolean | string | number | (string | number)[];
41
+ };
42
+ }
43
+ interface SchemaColumn {
44
+ accessorKey: string;
45
+ header: string;
46
+ type: ColumnType;
47
+ sortable?: boolean;
48
+ component?: string;
49
+ format?: string;
50
+ }
51
+ interface SchemaActions {
52
+ create?: boolean;
53
+ edit?: boolean;
54
+ delete?: boolean;
55
+ draft?: boolean;
56
+ csvImport?: {
57
+ enabled?: boolean;
58
+ matchField?: string;
59
+ };
60
+ }
61
+ /**
62
+ * Search configuration for admin tables
63
+ */
64
+ interface SchemaSearch {
65
+ /** Fields to search across (should be text-type columns) */
66
+ fields: string[];
67
+ }
68
+ /**
69
+ * Filter configuration for admin tables
70
+ */
71
+ interface SchemaFilter {
72
+ /** Field name to filter by */
73
+ field: string;
74
+ /** Label for the filter dropdown */
75
+ label: string;
76
+ /** Filter type (currently only 'select' is supported) */
77
+ type?: 'select';
78
+ }
79
+ /**
80
+ * Auto-slugify configuration
81
+ * Automatically generates URL-friendly slugs from another field
82
+ */
83
+ interface AutoSlugify {
84
+ /** Whether auto-slugification is enabled */
85
+ enabled: boolean;
86
+ /** Source field to generate slug from */
87
+ sourceField: string;
88
+ /** Target field to store the slug */
89
+ targetField: string;
90
+ }
91
+ /**
92
+ * Nested slug lookup configuration
93
+ * Generates functions to look up nested items by slug within a parent entity
94
+ * Example: getChapterBySlug(tutorialSlug, chapterSlug) for chapters nested in tutorial modules
95
+ */
96
+ interface NestedSlugLookup {
97
+ /** Name of the nested entity (e.g., "chapter") - used in function name */
98
+ name: string;
99
+ /** Path to the nested array using dot notation (e.g., "modules.chapters") */
100
+ path: string;
101
+ /** Field name containing the slug in the nested item (default: "slug") */
102
+ slugField?: string;
103
+ }
104
+ interface Schema {
105
+ name: string;
106
+ label: string;
107
+ description: string;
108
+ icon: string;
109
+ fields: SchemaField[];
110
+ columns: SchemaColumn[];
111
+ actions?: SchemaActions;
112
+ /** Search configuration - when provided, enables backend search on the admin table */
113
+ search?: SchemaSearch;
114
+ /** Filter configuration - when provided, enables filters on the admin table */
115
+ filters?: SchemaFilter[];
116
+ /** Auto-slugify configuration - when provided, automatically generates slugs from specified field */
117
+ autoSlugify?: AutoSlugify;
118
+ /** Nested slug lookup configuration - generates functions to look up nested items by slug */
119
+ nestedSlugLookups?: NestedSlugLookup[];
120
+ }
121
+ interface GeneratorOptions {
122
+ skipMigration?: boolean;
123
+ dummyCount?: number;
124
+ force?: boolean;
125
+ }
126
+ interface GenerationResult {
127
+ success: boolean;
128
+ files: string[];
129
+ errors?: string[];
130
+ }
131
+ /**
132
+ * Paths configuration for the monorepo structure
133
+ * All paths are absolute
134
+ */
135
+ interface MonorepoPaths {
136
+ root: string;
137
+ app: string;
138
+ database: string;
139
+ lib: string;
140
+ hooks: string;
141
+ schemas: string;
142
+ data: string;
143
+ }
144
+ /**
145
+ * Form field types supported by the form generator
146
+ */
147
+ type FormFieldType = 'text' | 'textarea' | 'email' | 'phone' | 'number' | 'url' | 'date' | 'select' | 'radio' | 'checkbox' | 'multiselect' | 'file' | 'upload' | 'group' | 'timezone' | 'list' | 'dynamicFields';
148
+ /**
149
+ * Form field definition
150
+ */
151
+ interface FormField {
152
+ name?: string;
153
+ type: FormFieldType;
154
+ label: string;
155
+ placeholder?: string;
156
+ hint?: string;
157
+ required?: boolean;
158
+ defaultValue?: string | number | boolean;
159
+ hidden?: boolean;
160
+ urlParam?: string;
161
+ condition?: string;
162
+ showWhen?: {
163
+ field: string;
164
+ value: string | string[];
165
+ };
166
+ minLength?: number;
167
+ maxLength?: number;
168
+ min?: number;
169
+ max?: number;
170
+ pattern?: string;
171
+ options?: Array<{
172
+ label: string;
173
+ value: string;
174
+ }>;
175
+ accept?: string;
176
+ maxFileSize?: number;
177
+ multiple?: boolean;
178
+ columns?: number;
179
+ fields?: FormField[];
180
+ relationship?: string;
181
+ relationshipField?: string;
182
+ nuqsQueryParam?: string;
183
+ source?: string;
184
+ }
185
+ /**
186
+ * Form step definition for multi-step forms
187
+ */
188
+ interface FormStep {
189
+ name: string;
190
+ label: string;
191
+ description?: string;
192
+ fields: FormField[];
193
+ }
194
+ /**
195
+ * Form actions configuration
196
+ */
197
+ interface FormActions {
198
+ export?: boolean;
199
+ delete?: boolean;
200
+ edit?: boolean;
201
+ }
202
+ /**
203
+ * Form column definition for admin table display
204
+ */
205
+ interface FormColumn {
206
+ accessorKey: string;
207
+ header: string;
208
+ type?: 'text' | 'date' | 'email' | 'number' | 'badge';
209
+ sortable?: boolean;
210
+ }
211
+ /**
212
+ * Form schema definition for generating public forms
213
+ */
214
+ interface FormSchema {
215
+ name: string;
216
+ label: string;
217
+ description: string;
218
+ icon: string;
219
+ submitButtonText?: string;
220
+ successMessage?: string;
221
+ redirectUrl?: string;
222
+ notificationEmail?: string;
223
+ fields?: FormField[];
224
+ steps?: FormStep[];
225
+ columns?: FormColumn[];
226
+ actions?: FormActions;
227
+ mailchimp?: boolean | {
228
+ emailField?: string;
229
+ };
230
+ }
231
+
232
+ export type { AutoSlugify as A, ColumnType as C, FormSchema as F, GeneratorOptions as G, MonorepoPaths as M, NestedSlugLookup as N, Schema as S, SchemaField as a, FieldType as b, SchemaColumn as c, SchemaActions as d, SchemaSearch as e, SchemaFilter as f, GenerationResult as g, FormFieldType as h, FormField as i, FormStep as j, FormActions as k, FormColumn as l };
package/package.json ADDED
@@ -0,0 +1,82 @@
1
+ {
2
+ "name": "@betterstart/cli",
3
+ "version": "0.1.0",
4
+ "description": "Generate admin CRUD interfaces for Next.js projects with Drizzle and shadcn/ui",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ },
13
+ "./config": {
14
+ "import": "./dist/config/index.js",
15
+ "types": "./dist/config/index.d.ts"
16
+ },
17
+ "./core": {
18
+ "import": "./dist/core/index.js",
19
+ "types": "./dist/core/index.d.ts"
20
+ },
21
+ "./plugins": {
22
+ "import": "./dist/plugins/index.js",
23
+ "types": "./dist/plugins/index.d.ts"
24
+ }
25
+ },
26
+ "bin": {
27
+ "betterstart": "./dist/cli.js",
28
+ "bs": "./dist/cli.js"
29
+ },
30
+ "files": [
31
+ "dist"
32
+ ],
33
+ "scripts": {
34
+ "build": "tsup",
35
+ "generate": "tsx bin/generate.ts",
36
+ "generate:form": "tsx bin/generate-form.ts",
37
+ "remove": "tsx bin/remove.ts",
38
+ "remove:form": "tsx bin/remove-form.ts",
39
+ "lint": "biome check",
40
+ "lint:fix": "biome check --write --unsafe",
41
+ "typecheck": "tsc --noEmit",
42
+ "cli": "tsx src/cli/index.ts",
43
+ "test": "vitest run",
44
+ "test:watch": "vitest",
45
+ "test:coverage": "vitest run --coverage",
46
+ "prepublishOnly": "pnpm run build"
47
+ },
48
+ "keywords": [
49
+ "admin",
50
+ "crud",
51
+ "generator",
52
+ "nextjs",
53
+ "drizzle",
54
+ "shadcn",
55
+ "typescript",
56
+ "codegen"
57
+ ],
58
+ "author": "",
59
+ "license": "MIT",
60
+ "engines": {
61
+ "node": ">=22.0.0"
62
+ },
63
+ "publishConfig": {
64
+ "access": "public"
65
+ },
66
+ "devDependencies": {
67
+ "@types/node": "^25.0.3",
68
+ "@vitest/coverage-v8": "^3.0.0",
69
+ "ajv": "^8.17.1",
70
+ "ajv-cli": "^5.0.0",
71
+ "tsup": "^8.5.1",
72
+ "tsx": "^4.21.0",
73
+ "typescript": "^5.9.3",
74
+ "vitest": "^3.0.0"
75
+ },
76
+ "dependencies": {
77
+ "commander": "^12.0.0"
78
+ },
79
+ "peerDependencies": {
80
+ "typescript": ">=5.0.0"
81
+ }
82
+ }