@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,81 @@
1
+ /**
2
+ * Logger abstraction for the codegen package
3
+ * Replaces direct console.log calls to support library usage and testing
4
+ */
5
+ /**
6
+ * Log levels
7
+ */
8
+ type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';
9
+ /**
10
+ * Logger interface
11
+ */
12
+ interface Logger {
13
+ debug(message: string, ...args: unknown[]): void;
14
+ info(message: string, ...args: unknown[]): void;
15
+ warn(message: string, ...args: unknown[]): void;
16
+ error(message: string, ...args: unknown[]): void;
17
+ success(message: string, ...args: unknown[]): void;
18
+ /**
19
+ * Log a step in a process (e.g., "1️⃣ Generating database schema...")
20
+ */
21
+ step(stepNumber: number, message: string): void;
22
+ /**
23
+ * Log a completed step
24
+ */
25
+ stepComplete(message: string): void;
26
+ /**
27
+ * Set the log level
28
+ */
29
+ setLevel(level: LogLevel): void;
30
+ /**
31
+ * Get the current log level
32
+ */
33
+ getLevel(): LogLevel;
34
+ }
35
+ /**
36
+ * Buffered logger that stores log messages for later retrieval
37
+ */
38
+ interface LogEntry {
39
+ level: LogLevel | 'success' | 'step' | 'stepComplete';
40
+ message: string;
41
+ args: unknown[];
42
+ timestamp: Date;
43
+ }
44
+ /**
45
+ * Create a console logger
46
+ */
47
+ declare function createConsoleLogger(level?: LogLevel): Logger;
48
+ /**
49
+ * Create a silent logger (for testing or library usage)
50
+ */
51
+ declare function createSilentLogger(): Logger;
52
+ /**
53
+ * Create a buffered logger (for testing)
54
+ */
55
+ declare function createBufferedLogger(level?: LogLevel): Logger & {
56
+ getEntries(): LogEntry[];
57
+ clear(): void;
58
+ };
59
+ /**
60
+ * Get the global logger
61
+ */
62
+ declare function getLogger(): Logger;
63
+ /**
64
+ * Set the global logger
65
+ */
66
+ declare function setLogger(logger: Logger): void;
67
+ /**
68
+ * Reset the global logger to the default console logger
69
+ */
70
+ declare function resetLogger(): void;
71
+ declare const logger: {
72
+ readonly debug: (message: string, ...args: unknown[]) => void;
73
+ readonly info: (message: string, ...args: unknown[]) => void;
74
+ readonly warn: (message: string, ...args: unknown[]) => void;
75
+ readonly error: (message: string, ...args: unknown[]) => void;
76
+ readonly success: (message: string, ...args: unknown[]) => void;
77
+ readonly step: (stepNumber: number, message: string) => void;
78
+ readonly stepComplete: (message: string) => void;
79
+ };
80
+
81
+ export { type LogLevel as L, type Logger as a, type LogEntry as b, createConsoleLogger as c, createSilentLogger as d, createBufferedLogger as e, getLogger as g, logger as l, resetLogger as r, setLogger as s };
@@ -0,0 +1,213 @@
1
+ import { k as BetterstartPlugin, h as PluginContext, i as GeneratedFile, C as CustomGenerator, F as FieldTypeHandler, j as PluginCommand } from '../types-BouTOvVr.js';
2
+ export { g as PluginHooks } from '../types-BouTOvVr.js';
3
+ import '../logger-awLb347n.js';
4
+
5
+ /**
6
+ * Plugin manager for @betterstart/cli
7
+ * Handles plugin registration, lifecycle, and execution
8
+ */
9
+
10
+ /**
11
+ * Plugin manager for handling plugin lifecycle and registration
12
+ */
13
+ declare class PluginManager {
14
+ private plugins;
15
+ private initialized;
16
+ /**
17
+ * Register a plugin
18
+ */
19
+ register(plugin: BetterstartPlugin): void;
20
+ /**
21
+ * Register multiple plugins
22
+ */
23
+ registerAll(plugins: BetterstartPlugin[]): void;
24
+ /**
25
+ * Unregister a plugin
26
+ */
27
+ unregister(pluginName: string): boolean;
28
+ /**
29
+ * Get a registered plugin by name
30
+ */
31
+ get(pluginName: string): BetterstartPlugin | undefined;
32
+ /**
33
+ * Get all registered plugins
34
+ */
35
+ getAll(): BetterstartPlugin[];
36
+ /**
37
+ * Check if a plugin is registered
38
+ */
39
+ has(pluginName: string): boolean;
40
+ /**
41
+ * Initialize all plugins
42
+ */
43
+ initialize(context: PluginContext): Promise<void>;
44
+ /**
45
+ * Run beforeGenerate hooks on all plugins
46
+ */
47
+ runBeforeGenerate(context: PluginContext, schema: unknown): Promise<void>;
48
+ /**
49
+ * Run afterGenerate hooks on all plugins
50
+ */
51
+ runAfterGenerate(context: PluginContext, files: GeneratedFile[]): Promise<void>;
52
+ /**
53
+ * Get a generator by name from any registered plugin
54
+ */
55
+ getGenerator(name: string): CustomGenerator | undefined;
56
+ /**
57
+ * Get all generators from all plugins
58
+ */
59
+ getAllGenerators(): Map<string, {
60
+ plugin: string;
61
+ generator: CustomGenerator;
62
+ }>;
63
+ /**
64
+ * Get all generator names
65
+ */
66
+ getGeneratorNames(): string[];
67
+ /**
68
+ * Get a field type handler by name from any registered plugin
69
+ */
70
+ getFieldType(name: string): FieldTypeHandler | undefined;
71
+ /**
72
+ * Get all field types from all plugins
73
+ */
74
+ getAllFieldTypes(): Map<string, {
75
+ plugin: string;
76
+ handler: FieldTypeHandler;
77
+ }>;
78
+ /**
79
+ * Get all field type names
80
+ */
81
+ getFieldTypeNames(): string[];
82
+ /**
83
+ * Get a command by name from any registered plugin
84
+ */
85
+ getCommand(name: string): PluginCommand | undefined;
86
+ /**
87
+ * Get all commands from all plugins
88
+ */
89
+ getAllCommands(): Map<string, {
90
+ plugin: string;
91
+ command: PluginCommand;
92
+ }>;
93
+ /**
94
+ * Get all command names
95
+ */
96
+ getCommandNames(): string[];
97
+ /**
98
+ * Get plugin summary
99
+ */
100
+ getSummary(): PluginSummary;
101
+ /**
102
+ * Clear all registered plugins
103
+ */
104
+ clear(): void;
105
+ }
106
+ interface PluginInfo {
107
+ name: string;
108
+ version: string;
109
+ description?: string;
110
+ generators: string[];
111
+ fieldTypes: string[];
112
+ commands: string[];
113
+ }
114
+ interface PluginSummary {
115
+ count: number;
116
+ plugins: PluginInfo[];
117
+ }
118
+ /**
119
+ * Get the global plugin manager instance
120
+ */
121
+ declare function getPluginManager(): PluginManager;
122
+ /**
123
+ * Create a new plugin manager instance
124
+ */
125
+ declare function createPluginManager(): PluginManager;
126
+ /**
127
+ * Reset the global plugin manager
128
+ */
129
+ declare function resetPluginManager(): void;
130
+
131
+ /**
132
+ * Plugin system types for @betterstart/cli
133
+ * Re-exports types from config and adds plugin-specific utilities
134
+ */
135
+
136
+ /**
137
+ * Events emitted during plugin lifecycle
138
+ */
139
+ type PluginEvent = 'init' | 'beforeGenerate' | 'afterGenerate' | 'beforeWrite' | 'afterWrite' | 'error';
140
+ /**
141
+ * Event handler type
142
+ */
143
+ type PluginEventHandler<T = unknown> = (context: PluginContext, data: T) => Promise<void>;
144
+ /**
145
+ * Options for creating a plugin
146
+ */
147
+ interface CreatePluginOptions {
148
+ name: string;
149
+ version: string;
150
+ description?: string;
151
+ }
152
+ /**
153
+ * Plugin builder for fluent API
154
+ */
155
+ interface PluginBuilder {
156
+ /** Add an onInit hook */
157
+ onInit(handler: (context: PluginContext) => Promise<void>): PluginBuilder;
158
+ /** Add an onBeforeGenerate hook */
159
+ onBeforeGenerate(handler: (context: PluginContext, schema: unknown) => Promise<void>): PluginBuilder;
160
+ /** Add an onAfterGenerate hook */
161
+ onAfterGenerate(handler: (context: PluginContext, files: GeneratedFile[]) => Promise<void>): PluginBuilder;
162
+ /** Add a custom generator */
163
+ addGenerator(name: string, description: string, generate: (context: PluginContext, schema: unknown) => Promise<GeneratedFile[]>): PluginBuilder;
164
+ /** Add a custom field type */
165
+ addFieldType(name: string, handler: {
166
+ zodType: (field: unknown) => string;
167
+ drizzleType: (field: unknown, imports: Set<string>) => string;
168
+ typescriptType: (field: unknown, mode: 'input' | 'output') => string;
169
+ formComponent?: (field: unknown) => string;
170
+ }): PluginBuilder;
171
+ /** Add a CLI command */
172
+ addCommand(name: string, description: string, options: Array<{
173
+ flags: string;
174
+ description: string;
175
+ default?: unknown;
176
+ }>, handler: (options: Record<string, unknown>) => Promise<void>): PluginBuilder;
177
+ /** Build the plugin */
178
+ build(): BetterstartPlugin;
179
+ }
180
+ /**
181
+ * Create a plugin using the builder pattern
182
+ */
183
+ declare function createPlugin(options: CreatePluginOptions): PluginBuilder;
184
+ /**
185
+ * Check if a plugin has a specific hook
186
+ */
187
+ declare function hasHook(plugin: BetterstartPlugin, hook: keyof NonNullable<BetterstartPlugin['hooks']>): boolean;
188
+ /**
189
+ * Check if a plugin provides a specific generator
190
+ */
191
+ declare function hasGenerator(plugin: BetterstartPlugin, generatorName: string): boolean;
192
+ /**
193
+ * Check if a plugin provides a specific field type
194
+ */
195
+ declare function hasFieldType(plugin: BetterstartPlugin, fieldTypeName: string): boolean;
196
+ /**
197
+ * Check if a plugin provides a specific command
198
+ */
199
+ declare function hasCommand(plugin: BetterstartPlugin, commandName: string): boolean;
200
+ /**
201
+ * Get all generator names from a plugin
202
+ */
203
+ declare function getGeneratorNames(plugin: BetterstartPlugin): string[];
204
+ /**
205
+ * Get all field type names from a plugin
206
+ */
207
+ declare function getFieldTypeNames(plugin: BetterstartPlugin): string[];
208
+ /**
209
+ * Get all command names from a plugin
210
+ */
211
+ declare function getCommandNames(plugin: BetterstartPlugin): string[];
212
+
213
+ export { BetterstartPlugin, type CreatePluginOptions, CustomGenerator, FieldTypeHandler, GeneratedFile, type PluginBuilder, PluginCommand, PluginContext, type PluginEvent, type PluginEventHandler, type PluginInfo, PluginManager, type PluginSummary, createPlugin, createPluginManager, getCommandNames, getFieldTypeNames, getGeneratorNames, getPluginManager, hasCommand, hasFieldType, hasGenerator, hasHook, resetPluginManager };
@@ -0,0 +1,365 @@
1
+ import {
2
+ PluginError,
3
+ getLogger
4
+ } from "../chunk-WY6BC55D.js";
5
+
6
+ // src/plugins/types.ts
7
+ function createPlugin(options) {
8
+ const plugin = {
9
+ name: options.name,
10
+ version: options.version,
11
+ description: options.description,
12
+ hooks: {},
13
+ generators: {},
14
+ fieldTypes: {},
15
+ commands: []
16
+ };
17
+ const builder = {
18
+ onInit(handler) {
19
+ plugin.hooks = plugin.hooks || {};
20
+ plugin.hooks.onInit = handler;
21
+ return builder;
22
+ },
23
+ onBeforeGenerate(handler) {
24
+ plugin.hooks = plugin.hooks || {};
25
+ plugin.hooks.onBeforeGenerate = handler;
26
+ return builder;
27
+ },
28
+ onAfterGenerate(handler) {
29
+ plugin.hooks = plugin.hooks || {};
30
+ plugin.hooks.onAfterGenerate = handler;
31
+ return builder;
32
+ },
33
+ addGenerator(name, description, generate) {
34
+ plugin.generators = plugin.generators || {};
35
+ plugin.generators[name] = { name, description, generate };
36
+ return builder;
37
+ },
38
+ addFieldType(name, handler) {
39
+ plugin.fieldTypes = plugin.fieldTypes || {};
40
+ plugin.fieldTypes[name] = handler;
41
+ return builder;
42
+ },
43
+ addCommand(name, description, options2, handler) {
44
+ plugin.commands = plugin.commands || [];
45
+ plugin.commands.push({ name, description, options: options2, handler });
46
+ return builder;
47
+ },
48
+ build() {
49
+ return plugin;
50
+ }
51
+ };
52
+ return builder;
53
+ }
54
+ function hasHook(plugin, hook) {
55
+ return plugin.hooks !== void 0 && typeof plugin.hooks[hook] === "function";
56
+ }
57
+ function hasGenerator(plugin, generatorName) {
58
+ return plugin.generators !== void 0 && generatorName in plugin.generators;
59
+ }
60
+ function hasFieldType(plugin, fieldTypeName) {
61
+ return plugin.fieldTypes !== void 0 && fieldTypeName in plugin.fieldTypes;
62
+ }
63
+ function hasCommand(plugin, commandName) {
64
+ return plugin.commands?.some((cmd) => cmd.name === commandName) ?? false;
65
+ }
66
+ function getGeneratorNames(plugin) {
67
+ return plugin.generators ? Object.keys(plugin.generators) : [];
68
+ }
69
+ function getFieldTypeNames(plugin) {
70
+ return plugin.fieldTypes ? Object.keys(plugin.fieldTypes) : [];
71
+ }
72
+ function getCommandNames(plugin) {
73
+ return plugin.commands ? plugin.commands.map((cmd) => cmd.name) : [];
74
+ }
75
+
76
+ // src/plugins/manager.ts
77
+ var PluginManager = class {
78
+ plugins = /* @__PURE__ */ new Map();
79
+ initialized = false;
80
+ /**
81
+ * Register a plugin
82
+ */
83
+ register(plugin) {
84
+ if (this.plugins.has(plugin.name)) {
85
+ throw new PluginError(`Plugin "${plugin.name}" is already registered`, plugin.name);
86
+ }
87
+ const logger = getLogger();
88
+ logger.debug(`Registering plugin: ${plugin.name}@${plugin.version}`);
89
+ this.plugins.set(plugin.name, plugin);
90
+ }
91
+ /**
92
+ * Register multiple plugins
93
+ */
94
+ registerAll(plugins) {
95
+ for (const plugin of plugins) {
96
+ this.register(plugin);
97
+ }
98
+ }
99
+ /**
100
+ * Unregister a plugin
101
+ */
102
+ unregister(pluginName) {
103
+ return this.plugins.delete(pluginName);
104
+ }
105
+ /**
106
+ * Get a registered plugin by name
107
+ */
108
+ get(pluginName) {
109
+ return this.plugins.get(pluginName);
110
+ }
111
+ /**
112
+ * Get all registered plugins
113
+ */
114
+ getAll() {
115
+ return Array.from(this.plugins.values());
116
+ }
117
+ /**
118
+ * Check if a plugin is registered
119
+ */
120
+ has(pluginName) {
121
+ return this.plugins.has(pluginName);
122
+ }
123
+ /**
124
+ * Initialize all plugins
125
+ */
126
+ async initialize(context) {
127
+ if (this.initialized) {
128
+ return;
129
+ }
130
+ const logger = getLogger();
131
+ for (const plugin of this.plugins.values()) {
132
+ if (hasHook(plugin, "onInit")) {
133
+ try {
134
+ logger.debug(`Initializing plugin: ${plugin.name}`);
135
+ await plugin.hooks.onInit(context);
136
+ } catch (error) {
137
+ throw new PluginError(
138
+ `Failed to initialize plugin "${plugin.name}": ${error instanceof Error ? error.message : String(error)}`,
139
+ plugin.name,
140
+ { originalError: error }
141
+ );
142
+ }
143
+ }
144
+ }
145
+ this.initialized = true;
146
+ }
147
+ /**
148
+ * Run beforeGenerate hooks on all plugins
149
+ */
150
+ async runBeforeGenerate(context, schema) {
151
+ const logger = getLogger();
152
+ for (const plugin of this.plugins.values()) {
153
+ if (hasHook(plugin, "onBeforeGenerate")) {
154
+ try {
155
+ logger.debug(`Running beforeGenerate for plugin: ${plugin.name}`);
156
+ await plugin.hooks.onBeforeGenerate(context, schema);
157
+ } catch (error) {
158
+ throw new PluginError(
159
+ `Plugin "${plugin.name}" failed in beforeGenerate: ${error instanceof Error ? error.message : String(error)}`,
160
+ plugin.name,
161
+ { originalError: error }
162
+ );
163
+ }
164
+ }
165
+ }
166
+ }
167
+ /**
168
+ * Run afterGenerate hooks on all plugins
169
+ */
170
+ async runAfterGenerate(context, files) {
171
+ const logger = getLogger();
172
+ for (const plugin of this.plugins.values()) {
173
+ if (hasHook(plugin, "onAfterGenerate")) {
174
+ try {
175
+ logger.debug(`Running afterGenerate for plugin: ${plugin.name}`);
176
+ await plugin.hooks.onAfterGenerate(context, files);
177
+ } catch (error) {
178
+ throw new PluginError(
179
+ `Plugin "${plugin.name}" failed in afterGenerate: ${error instanceof Error ? error.message : String(error)}`,
180
+ plugin.name,
181
+ { originalError: error }
182
+ );
183
+ }
184
+ }
185
+ }
186
+ }
187
+ // ============================================================================
188
+ // Generator Access
189
+ // ============================================================================
190
+ /**
191
+ * Get a generator by name from any registered plugin
192
+ */
193
+ getGenerator(name) {
194
+ for (const plugin of this.plugins.values()) {
195
+ if (plugin.generators && name in plugin.generators) {
196
+ return plugin.generators[name];
197
+ }
198
+ }
199
+ return void 0;
200
+ }
201
+ /**
202
+ * Get all generators from all plugins
203
+ */
204
+ getAllGenerators() {
205
+ const generators = /* @__PURE__ */ new Map();
206
+ for (const plugin of this.plugins.values()) {
207
+ if (plugin.generators) {
208
+ for (const [name, generator] of Object.entries(plugin.generators)) {
209
+ generators.set(name, { plugin: plugin.name, generator });
210
+ }
211
+ }
212
+ }
213
+ return generators;
214
+ }
215
+ /**
216
+ * Get all generator names
217
+ */
218
+ getGeneratorNames() {
219
+ const names = [];
220
+ for (const plugin of this.plugins.values()) {
221
+ names.push(...getGeneratorNames(plugin));
222
+ }
223
+ return names;
224
+ }
225
+ // ============================================================================
226
+ // Field Type Access
227
+ // ============================================================================
228
+ /**
229
+ * Get a field type handler by name from any registered plugin
230
+ */
231
+ getFieldType(name) {
232
+ for (const plugin of this.plugins.values()) {
233
+ if (plugin.fieldTypes && name in plugin.fieldTypes) {
234
+ return plugin.fieldTypes[name];
235
+ }
236
+ }
237
+ return void 0;
238
+ }
239
+ /**
240
+ * Get all field types from all plugins
241
+ */
242
+ getAllFieldTypes() {
243
+ const fieldTypes = /* @__PURE__ */ new Map();
244
+ for (const plugin of this.plugins.values()) {
245
+ if (plugin.fieldTypes) {
246
+ for (const [name, handler] of Object.entries(plugin.fieldTypes)) {
247
+ fieldTypes.set(name, { plugin: plugin.name, handler });
248
+ }
249
+ }
250
+ }
251
+ return fieldTypes;
252
+ }
253
+ /**
254
+ * Get all field type names
255
+ */
256
+ getFieldTypeNames() {
257
+ const names = [];
258
+ for (const plugin of this.plugins.values()) {
259
+ names.push(...getFieldTypeNames(plugin));
260
+ }
261
+ return names;
262
+ }
263
+ // ============================================================================
264
+ // Command Access
265
+ // ============================================================================
266
+ /**
267
+ * Get a command by name from any registered plugin
268
+ */
269
+ getCommand(name) {
270
+ for (const plugin of this.plugins.values()) {
271
+ if (plugin.commands) {
272
+ const command = plugin.commands.find((cmd) => cmd.name === name);
273
+ if (command) {
274
+ return command;
275
+ }
276
+ }
277
+ }
278
+ return void 0;
279
+ }
280
+ /**
281
+ * Get all commands from all plugins
282
+ */
283
+ getAllCommands() {
284
+ const commands = /* @__PURE__ */ new Map();
285
+ for (const plugin of this.plugins.values()) {
286
+ if (plugin.commands) {
287
+ for (const command of plugin.commands) {
288
+ commands.set(command.name, { plugin: plugin.name, command });
289
+ }
290
+ }
291
+ }
292
+ return commands;
293
+ }
294
+ /**
295
+ * Get all command names
296
+ */
297
+ getCommandNames() {
298
+ const names = [];
299
+ for (const plugin of this.plugins.values()) {
300
+ names.push(...getCommandNames(plugin));
301
+ }
302
+ return names;
303
+ }
304
+ // ============================================================================
305
+ // Utility Methods
306
+ // ============================================================================
307
+ /**
308
+ * Get plugin summary
309
+ */
310
+ getSummary() {
311
+ const plugins = [];
312
+ for (const plugin of this.plugins.values()) {
313
+ plugins.push({
314
+ name: plugin.name,
315
+ version: plugin.version,
316
+ description: plugin.description,
317
+ generators: getGeneratorNames(plugin),
318
+ fieldTypes: getFieldTypeNames(plugin),
319
+ commands: getCommandNames(plugin)
320
+ });
321
+ }
322
+ return {
323
+ count: this.plugins.size,
324
+ plugins
325
+ };
326
+ }
327
+ /**
328
+ * Clear all registered plugins
329
+ */
330
+ clear() {
331
+ this.plugins.clear();
332
+ this.initialized = false;
333
+ }
334
+ };
335
+ var globalPluginManager = null;
336
+ function getPluginManager() {
337
+ if (!globalPluginManager) {
338
+ globalPluginManager = new PluginManager();
339
+ }
340
+ return globalPluginManager;
341
+ }
342
+ function createPluginManager() {
343
+ return new PluginManager();
344
+ }
345
+ function resetPluginManager() {
346
+ if (globalPluginManager) {
347
+ globalPluginManager.clear();
348
+ }
349
+ globalPluginManager = null;
350
+ }
351
+ export {
352
+ PluginManager,
353
+ createPlugin,
354
+ createPluginManager,
355
+ getCommandNames,
356
+ getFieldTypeNames,
357
+ getGeneratorNames,
358
+ getPluginManager,
359
+ hasCommand,
360
+ hasFieldType,
361
+ hasGenerator,
362
+ hasHook,
363
+ resetPluginManager
364
+ };
365
+ //# sourceMappingURL=index.js.map