@betterstart/cli 0.1.1 → 0.1.3
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/dist/{chunk-G4KI4DVB.js → chunk-EIH4RRIJ.js} +5 -1
- package/dist/chunk-EIH4RRIJ.js.map +1 -0
- package/dist/{chunk-J2XUG4RG.js → chunk-QLVSHP7X.js} +8 -2
- package/dist/chunk-QLVSHP7X.js.map +1 -0
- package/dist/cli.js +15 -2
- package/dist/cli.js.map +1 -1
- package/dist/config/index.js +1 -1
- package/dist/core/index.js +1 -1
- package/dist/index.d.ts +8 -2
- package/dist/index.js +8 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-G4KI4DVB.js.map +0 -1
- package/dist/chunk-J2XUG4RG.js.map +0 -1
|
@@ -30,6 +30,9 @@ function initPaths(startDir) {
|
|
|
30
30
|
};
|
|
31
31
|
return _paths;
|
|
32
32
|
}
|
|
33
|
+
function setPaths(paths) {
|
|
34
|
+
_paths = paths;
|
|
35
|
+
}
|
|
33
36
|
function getPaths() {
|
|
34
37
|
if (!_paths) {
|
|
35
38
|
return initPaths();
|
|
@@ -160,6 +163,7 @@ function singularizeLabel(label) {
|
|
|
160
163
|
|
|
161
164
|
export {
|
|
162
165
|
initPaths,
|
|
166
|
+
setPaths,
|
|
163
167
|
getPaths,
|
|
164
168
|
getProjectRoot,
|
|
165
169
|
initImportResolver,
|
|
@@ -176,4 +180,4 @@ export {
|
|
|
176
180
|
quotePropertyName,
|
|
177
181
|
singularizeLabel
|
|
178
182
|
};
|
|
179
|
-
//# sourceMappingURL=chunk-
|
|
183
|
+
//# sourceMappingURL=chunk-EIH4RRIJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils.ts"],"sourcesContent":["// Utility functions for the codemod system\n\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport { ImportResolver } from './config/import-resolver'\nimport { MONOREPO_IMPORT_PATHS } from './config/presets'\nimport type { BetterstartConfig } from './config/types'\nimport type { MonorepoPaths } from './types'\n\n// Store monorepo paths globally (set during CLI initialization)\nlet _paths: MonorepoPaths | null = null\n\n/**\n * Initialize paths for the monorepo\n * Detects monorepo root and sets up all package paths\n */\nexport function initPaths(startDir?: string): MonorepoPaths {\n const cwd = startDir || process.cwd()\n\n // Find monorepo root by looking for turbo.json or pnpm-workspace.yaml\n let root = cwd\n while (root !== '/') {\n if (\n fs.existsSync(path.join(root, 'turbo.json')) ||\n fs.existsSync(path.join(root, 'pnpm-workspace.yaml'))\n ) {\n break\n }\n root = path.dirname(root)\n }\n\n if (root === '/') {\n throw new Error('Could not find monorepo root (no turbo.json or pnpm-workspace.yaml found)')\n }\n\n _paths = {\n root,\n app: path.join(root, 'apps/web'),\n database: path.join(root, 'packages/database'),\n lib: path.join(root, 'packages/lib'),\n hooks: path.join(root, 'packages/hooks'),\n schemas: path.join(root, 'packages/codegen/src/schemas'),\n data: path.join(root, 'packages/data')\n }\n\n return _paths\n}\n\n/**\n * Set pre-resolved paths (e.g., from config-based resolution)\n * This allows the CLI to seed paths from the config system\n * so that generators work in both monorepo and standalone projects.\n */\nexport function setPaths(paths: MonorepoPaths): void {\n _paths = paths\n}\n\n/**\n * Get monorepo paths (must call initPaths or setPaths first)\n */\nexport function getPaths(): MonorepoPaths {\n if (!_paths) {\n return initPaths()\n }\n return _paths\n}\n\n/**\n * Get the monorepo root directory\n * @deprecated Use getPaths().root instead\n */\nexport function getProjectRoot(): string {\n return getPaths().app\n}\n\n// Store import resolver globally (set during CLI initialization)\nlet _importResolver: ImportResolver | null = null\n\n/**\n * Initialize the import resolver from config\n */\nexport function initImportResolver(config: BetterstartConfig): ImportResolver {\n _importResolver = new ImportResolver(config.imports)\n return _importResolver\n}\n\n/**\n * Get the import resolver (must call initImportResolver first, or falls back to monorepo defaults)\n */\nexport function getImportResolver(): ImportResolver {\n if (!_importResolver) {\n _importResolver = new ImportResolver(MONOREPO_IMPORT_PATHS)\n }\n return _importResolver\n}\n\n/**\n * Convert a string to PascalCase\n */\nexport function toPascalCase(str: string): string {\n return str\n .split(/[-_\\s]+/)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join('')\n}\n\n/**\n * Convert a string to camelCase\n */\nexport function toCamelCase(str: string): string {\n const pascal = toPascalCase(str)\n return pascal.charAt(0).toLowerCase() + pascal.slice(1)\n}\n\n/**\n * Convert a string to kebab-case\n */\nexport function toKebabCase(str: string): string {\n return str\n .replace(/([a-z])([A-Z])/g, '$1-$2')\n .replace(/[\\s_]+/g, '-')\n .toLowerCase()\n}\n\n/**\n * Convert a string to snake_case\n */\nexport function toSnakeCase(str: string): string {\n return str\n .replace(/([a-z])([A-Z])/g, '$1_$2')\n .replace(/[\\s-]+/g, '_')\n .toLowerCase()\n}\n\n/**\n * Convert a string to SCREAMING_SNAKE_CASE\n */\nexport function toScreamingSnakeCase(str: string): string {\n return str\n .replace(/([a-z])([A-Z])/g, '$1_$2')\n .replace(/[\\s-]+/g, '_')\n .toUpperCase()\n}\n\n/**\n * Ensure a directory exists, create it if it doesn't\n */\nexport function ensureDir(dirPath: string): void {\n if (!fs.existsSync(dirPath)) {\n fs.mkdirSync(dirPath, { recursive: true })\n }\n}\n\n/**\n * Format a timestamp for migration files\n */\nexport function getMigrationTimestamp(): string {\n const now = new Date()\n const year = now.getFullYear()\n const month = String(now.getMonth() + 1).padStart(2, '0')\n const day = String(now.getDate()).padStart(2, '0')\n const hours = String(now.getHours()).padStart(2, '0')\n const minutes = String(now.getMinutes()).padStart(2, '0')\n const seconds = String(now.getSeconds()).padStart(2, '0')\n return `${year}${month}${day}${hours}${minutes}${seconds}`\n}\n\n/**\n * Check if a word is already plural\n */\nfunction isPlural(str: string): boolean {\n const pluralPatterns = [\n /ies$/,\n /ves$/,\n /ses$/,\n /xes$/,\n /zes$/,\n /ches$/,\n /shes$/,\n /men$/,\n /people$/\n ]\n\n for (const pattern of pluralPatterns) {\n if (pattern.test(str)) {\n return true\n }\n }\n\n if (str.endsWith('s') && !str.endsWith('ss')) {\n return true\n }\n\n return false\n}\n\n/**\n * Pluralize a string\n */\nexport function pluralize(str: string): string {\n if (isPlural(str)) {\n return str\n }\n\n if (str.endsWith('y') && !['ay', 'ey', 'iy', 'oy', 'uy'].some((v) => str.endsWith(v))) {\n return `${str.slice(0, -1)}ies`\n }\n if (str.endsWith('s') || str.endsWith('x') || str.endsWith('ch') || str.endsWith('sh')) {\n return `${str}es`\n }\n if (str.endsWith('f')) {\n return `${str.slice(0, -1)}ves`\n }\n if (str.endsWith('fe')) {\n return `${str.slice(0, -2)}ves`\n }\n return `${str}s`\n}\n\n/**\n * Singularize a string\n */\nexport function singularize(str: string): string {\n if (!isPlural(str)) {\n return str\n }\n\n if (str.endsWith('ies')) {\n return `${str.slice(0, -3)}y`\n }\n if (str.endsWith('ves')) {\n return `${str.slice(0, -3)}f`\n }\n if (\n str.endsWith('sses') ||\n str.endsWith('xes') ||\n str.endsWith('ches') ||\n str.endsWith('shes') ||\n str.endsWith('zes')\n ) {\n return str.slice(0, -2)\n }\n if (str.endsWith('s') && !str.endsWith('ss')) {\n return str.slice(0, -1)\n }\n return str\n}\n\n/**\n * Quote a property name if it's not a valid JavaScript identifier.\n * Properties with hyphens, spaces, or starting with numbers need quotes.\n */\nexport function quotePropertyName(name: string): string {\n // Valid JS identifier: starts with letter/underscore/$, contains only letters/numbers/underscore/$\n const validIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/\n if (validIdentifier.test(name)) {\n return name\n }\n return `'${name}'`\n}\n\n/**\n * Singularize a label (e.g., \"Trusted Companies\" -> \"Trusted Company\")\n * Handles display labels with proper capitalization\n */\nexport function singularizeLabel(label: string): string {\n const words = label.split(' ')\n if (words.length === 0) {\n return label\n }\n\n // Singularize the last word\n const lastWord = words[words.length - 1]\n const lastWordLower = lastWord.toLowerCase()\n const singularLastWordLower = singularize(lastWordLower)\n\n // Preserve capitalization of the last word\n const capitalizedSingular =\n lastWord[0] === lastWord[0].toUpperCase()\n ? singularLastWordLower.charAt(0).toUpperCase() + singularLastWordLower.slice(1)\n : singularLastWordLower\n\n return [...words.slice(0, -1), capitalizedSingular].join(' ')\n}\n"],"mappings":"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","names":[]}
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
// src/config/loader.ts
|
|
12
12
|
import fs from "fs";
|
|
13
13
|
import path from "path";
|
|
14
|
+
import { fileURLToPath } from "url";
|
|
14
15
|
var CONFIG_FILE_NAMES = [
|
|
15
16
|
"betterstart.config.ts",
|
|
16
17
|
"betterstart.config.js",
|
|
@@ -38,7 +39,12 @@ async function loadConfigFile(configPath) {
|
|
|
38
39
|
}
|
|
39
40
|
if (ext === ".ts") {
|
|
40
41
|
const { createJiti } = await import("jiti");
|
|
41
|
-
const
|
|
42
|
+
const alias = {};
|
|
43
|
+
try {
|
|
44
|
+
alias["@betterstart/cli"] = fileURLToPath(import.meta.resolve("@betterstart/cli"));
|
|
45
|
+
} catch {
|
|
46
|
+
}
|
|
47
|
+
const jiti = createJiti(import.meta.url, { alias });
|
|
42
48
|
const module = await jiti.import(configPath);
|
|
43
49
|
return module.default || module;
|
|
44
50
|
}
|
|
@@ -226,4 +232,4 @@ export {
|
|
|
226
232
|
validateConfig,
|
|
227
233
|
checkPaths
|
|
228
234
|
};
|
|
229
|
-
//# sourceMappingURL=chunk-
|
|
235
|
+
//# sourceMappingURL=chunk-QLVSHP7X.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/config/loader.ts"],"sourcesContent":["/**\n * Configuration loader for @betterstart/cli\n * Handles loading, merging, and resolving configuration\n */\n\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { ConfigurationError } from '../core/errors'\nimport { getLogger } from '../core/logger'\nimport { detectPreset, getDefaultConfig, getPreset } from './presets'\nimport type { BetterstartConfig, ResolvedConfig, ResolvedPaths, UserConfig } from './types'\n\n// ============================================================================\n// Configuration File Names\n// ============================================================================\n\n/**\n * Supported configuration file names (in priority order)\n */\nexport const CONFIG_FILE_NAMES = [\n 'betterstart.config.ts',\n 'betterstart.config.js',\n 'betterstart.config.mjs',\n 'betterstart.config.json',\n '.betterstartrc.json',\n '.betterstartrc'\n]\n\n// ============================================================================\n// Configuration Loading\n// ============================================================================\n\n/**\n * Find the configuration file in a directory\n * @param cwd - Directory to search in\n * @returns Path to the config file or undefined if not found\n */\nexport function findConfigFile(cwd: string): string | undefined {\n for (const fileName of CONFIG_FILE_NAMES) {\n const filePath = path.join(cwd, fileName)\n if (fs.existsSync(filePath)) {\n return filePath\n }\n }\n return undefined\n}\n\n/**\n * Load configuration from a file\n * @param configPath - Path to the configuration file\n * @returns The loaded configuration\n */\nexport async function loadConfigFile(configPath: string): Promise<UserConfig> {\n const ext = path.extname(configPath)\n const logger = getLogger()\n\n try {\n if (ext === '.json' || configPath.endsWith('.betterstartrc')) {\n // Load JSON config\n const content = fs.readFileSync(configPath, 'utf-8')\n return JSON.parse(content) as UserConfig\n }\n\n if (ext === '.ts') {\n // Use jiti to transpile TypeScript config at runtime\n const { createJiti } = await import('jiti')\n // Alias @betterstart/cli so jiti can resolve it even when the CLI\n // is invoked via npx and isn't installed in the project's node_modules\n const alias: Record<string, string> = {}\n try {\n alias['@betterstart/cli'] = fileURLToPath(import.meta.resolve('@betterstart/cli'))\n } catch {\n // Not critical — config may not import from us\n }\n const jiti = createJiti(import.meta.url, { alias })\n const module = await jiti.import(configPath)\n return ((module as Record<string, unknown>).default || module) as UserConfig\n }\n\n if (ext === '.js' || ext === '.mjs') {\n const configUrl = `file://${configPath}`\n const module = await import(configUrl)\n return (module.default || module) as UserConfig\n }\n\n throw new ConfigurationError(`Unsupported config file type: ${ext}`, { path: configPath })\n } catch (error) {\n if (error instanceof ConfigurationError) {\n throw error\n }\n logger.error(`Failed to load config file: ${configPath}`)\n throw new ConfigurationError(\n `Failed to load configuration from ${configPath}: ${error instanceof Error ? error.message : String(error)}`,\n { path: configPath, originalError: error }\n )\n }\n}\n\n/**\n * Deep merge two configuration objects\n * Arrays are replaced, not merged\n */\nfunction deepMerge<T extends Record<string, unknown>>(base: T, override: Partial<T>): T {\n const result = { ...base }\n\n for (const key of Object.keys(override) as Array<keyof T>) {\n const baseValue = base[key]\n const overrideValue = override[key]\n\n if (overrideValue === undefined) {\n continue\n }\n\n if (\n typeof baseValue === 'object' &&\n baseValue !== null &&\n !Array.isArray(baseValue) &&\n typeof overrideValue === 'object' &&\n overrideValue !== null &&\n !Array.isArray(overrideValue)\n ) {\n // Recursively merge objects\n result[key] = deepMerge(\n baseValue as Record<string, unknown>,\n overrideValue as Record<string, unknown>\n ) as T[keyof T]\n } else {\n // Replace arrays and primitives\n result[key] = overrideValue as T[keyof T]\n }\n }\n\n return result\n}\n\n/**\n * Load configuration from a directory\n * Automatically finds and loads the config file, or uses defaults\n *\n * @param cwd - Directory to load config from (defaults to process.cwd())\n * @param presetName - Optional preset name to use as base\n * @returns The loaded and merged configuration\n */\nexport async function loadConfig(cwd?: string, presetName?: string): Promise<BetterstartConfig> {\n const workingDir = cwd || process.cwd()\n const logger = getLogger()\n\n // Get base configuration from preset or auto-detection\n let baseConfig: UserConfig\n if (presetName) {\n const preset = getPreset(presetName)\n if (!preset) {\n throw new ConfigurationError(`Unknown preset: ${presetName}`, {\n availablePresets: ['nextjs-monorepo', 'nextjs-standalone', 'custom']\n })\n }\n baseConfig = preset.config\n logger.debug(`Using preset: ${presetName}`)\n } else {\n baseConfig = getDefaultConfig(workingDir)\n const detectedPreset = detectPreset(workingDir)\n logger.debug(`Auto-detected preset: ${detectedPreset.name}`)\n }\n\n // Look for config file\n const configPath = findConfigFile(workingDir)\n let userConfig: UserConfig = {}\n\n if (configPath) {\n logger.debug(`Loading config from: ${configPath}`)\n userConfig = await loadConfigFile(configPath)\n }\n\n // Merge configurations\n const mergedConfig = deepMerge(\n baseConfig as Record<string, unknown>,\n userConfig as Record<string, unknown>\n )\n\n return mergedConfig as unknown as BetterstartConfig\n}\n\n// ============================================================================\n// Path Resolution\n// ============================================================================\n\n/**\n * Find the project root directory\n * Looks for common root indicators (package.json, pnpm-workspace.yaml, turbo.json)\n *\n * @param startDir - Directory to start searching from\n * @returns The project root directory\n */\nexport function findProjectRoot(startDir: string): string {\n let currentDir = path.resolve(startDir)\n const _rootIndicators = ['pnpm-workspace.yaml', 'turbo.json', 'package.json']\n\n // Walk up the directory tree\n while (currentDir !== path.dirname(currentDir)) {\n // Check for monorepo root indicators first\n if (\n fs.existsSync(path.join(currentDir, 'pnpm-workspace.yaml')) ||\n fs.existsSync(path.join(currentDir, 'turbo.json'))\n ) {\n return currentDir\n }\n\n // Check for package.json\n if (fs.existsSync(path.join(currentDir, 'package.json'))) {\n // If there's a package.json but no monorepo indicators,\n // check if parent has monorepo indicators\n const parentDir = path.dirname(currentDir)\n if (\n fs.existsSync(path.join(parentDir, 'pnpm-workspace.yaml')) ||\n fs.existsSync(path.join(parentDir, 'turbo.json'))\n ) {\n return parentDir\n }\n // Otherwise, this package.json is our root\n return currentDir\n }\n\n currentDir = path.dirname(currentDir)\n }\n\n // Fallback to start directory\n return path.resolve(startDir)\n}\n\n/**\n * Resolve configuration paths to absolute paths\n *\n * @param config - The configuration to resolve\n * @param projectRoot - The project root directory\n * @returns Configuration with resolved absolute paths\n */\nexport function resolvePaths(config: BetterstartConfig, projectRoot: string): ResolvedPaths {\n const root = path.resolve(projectRoot)\n\n // Resolve main paths\n const appPath = path.resolve(root, config.paths.app)\n const databasePath = path.resolve(root, config.paths.database)\n const libPath = path.resolve(root, config.paths.lib)\n const hooksPath = path.resolve(root, config.paths.hooks)\n const schemasPath = path.resolve(root, config.paths.schemas)\n\n // Resolve output paths relative to their parent packages\n const outputPaths = {\n actions: path.resolve(libPath, config.paths.output.actions),\n hooks: path.resolve(hooksPath, config.paths.output.hooks),\n components: path.resolve(appPath, config.paths.output.components),\n pages: path.resolve(appPath, config.paths.output.pages),\n emails: path.resolve(appPath, config.paths.output.emails)\n }\n\n return {\n root,\n app: appPath,\n database: databasePath,\n lib: libPath,\n hooks: hooksPath,\n schemas: schemasPath,\n output: outputPaths\n }\n}\n\n/**\n * Fully resolve configuration including paths\n *\n * @param config - The configuration to resolve\n * @param projectRoot - The project root directory (optional, auto-detected if not provided)\n * @returns Fully resolved configuration\n */\nexport function resolveConfig(config: BetterstartConfig, projectRoot?: string): ResolvedConfig {\n const root = projectRoot || findProjectRoot(process.cwd())\n const resolvedPaths = resolvePaths(config, root)\n\n return {\n ...config,\n paths: resolvedPaths\n }\n}\n\n// ============================================================================\n// Configuration Helper\n// ============================================================================\n\n/**\n * Helper function for defining configuration in betterstart.config.ts\n * Provides type checking and autocomplete\n *\n * @example\n * ```ts\n * // betterstart.config.ts\n * import { defineConfig } from '@betterstart/cli'\n *\n * export default defineConfig({\n * paths: {\n * app: 'apps/web',\n * database: 'packages/database'\n * }\n * })\n * ```\n */\nexport function defineConfig(config: UserConfig): UserConfig {\n return config\n}\n\n// ============================================================================\n// Validation\n// ============================================================================\n\n/**\n * Validate a configuration\n * @param config - The configuration to validate\n * @returns Array of validation errors (empty if valid)\n */\nexport function validateConfig(config: BetterstartConfig): string[] {\n const errors: string[] = []\n\n // Validate paths\n if (!config.paths) {\n errors.push('Configuration must have a \"paths\" object')\n } else {\n if (!config.paths.app) errors.push('paths.app is required')\n if (!config.paths.database) errors.push('paths.database is required')\n if (!config.paths.lib) errors.push('paths.lib is required')\n if (!config.paths.hooks) errors.push('paths.hooks is required')\n if (!config.paths.schemas) errors.push('paths.schemas is required')\n }\n\n // Validate database config\n if (!config.database) {\n errors.push('Configuration must have a \"database\" object')\n } else {\n if (config.database.provider !== 'drizzle') {\n errors.push('database.provider must be \"drizzle\"')\n }\n }\n\n // Validate UI config\n if (!config.ui) {\n errors.push('Configuration must have a \"ui\" object')\n } else {\n if (config.ui.framework !== 'shadcn') {\n errors.push('ui.framework must be \"shadcn\"')\n }\n }\n\n return errors\n}\n\n/**\n * Check if resolved paths exist and are accessible\n * @param paths - The resolved paths to check\n * @returns Object with path existence status\n */\nexport function checkPaths(paths: ResolvedPaths): Record<keyof ResolvedPaths, boolean> {\n const exists = (p: string) => {\n try {\n fs.accessSync(p)\n return true\n } catch {\n return false\n }\n }\n\n return {\n root: exists(paths.root),\n app: exists(paths.app),\n database: exists(paths.database),\n lib: exists(paths.lib),\n hooks: exists(paths.hooks),\n schemas: exists(paths.schemas),\n output: {\n actions: exists(paths.output.actions),\n hooks: exists(paths.output.hooks),\n components: exists(paths.output.components),\n pages: exists(paths.output.pages),\n emails: exists(paths.output.emails)\n }\n } as unknown as Record<keyof ResolvedPaths, boolean>\n}\n"],"mappings":";;;;;;;;;;;AAKA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAavB,IAAM,oBAAoB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAWO,SAAS,eAAe,KAAiC;AAC9D,aAAW,YAAY,mBAAmB;AACxC,UAAM,WAAW,KAAK,KAAK,KAAK,QAAQ;AACxC,QAAI,GAAG,WAAW,QAAQ,GAAG;AAC3B,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAOA,eAAsB,eAAe,YAAyC;AAC5E,QAAM,MAAM,KAAK,QAAQ,UAAU;AACnC,QAAM,SAAS,UAAU;AAEzB,MAAI;AACF,QAAI,QAAQ,WAAW,WAAW,SAAS,gBAAgB,GAAG;AAE5D,YAAM,UAAU,GAAG,aAAa,YAAY,OAAO;AACnD,aAAO,KAAK,MAAM,OAAO;AAAA,IAC3B;AAEA,QAAI,QAAQ,OAAO;AAEjB,YAAM,EAAE,WAAW,IAAI,MAAM,OAAO,MAAM;AAG1C,YAAM,QAAgC,CAAC;AACvC,UAAI;AACF,cAAM,kBAAkB,IAAI,cAAc,YAAY,QAAQ,kBAAkB,CAAC;AAAA,MACnF,QAAQ;AAAA,MAER;AACA,YAAM,OAAO,WAAW,YAAY,KAAK,EAAE,MAAM,CAAC;AAClD,YAAM,SAAS,MAAM,KAAK,OAAO,UAAU;AAC3C,aAAS,OAAmC,WAAW;AAAA,IACzD;AAEA,QAAI,QAAQ,SAAS,QAAQ,QAAQ;AACnC,YAAM,YAAY,UAAU,UAAU;AACtC,YAAM,SAAS,MAAM,OAAO;AAC5B,aAAQ,OAAO,WAAW;AAAA,IAC5B;AAEA,UAAM,IAAI,mBAAmB,iCAAiC,GAAG,IAAI,EAAE,MAAM,WAAW,CAAC;AAAA,EAC3F,SAAS,OAAO;AACd,QAAI,iBAAiB,oBAAoB;AACvC,YAAM;AAAA,IACR;AACA,WAAO,MAAM,+BAA+B,UAAU,EAAE;AACxD,UAAM,IAAI;AAAA,MACR,qCAAqC,UAAU,KAAK,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MAC1G,EAAE,MAAM,YAAY,eAAe,MAAM;AAAA,IAC3C;AAAA,EACF;AACF;AAMA,SAAS,UAA6C,MAAS,UAAyB;AACtF,QAAM,SAAS,EAAE,GAAG,KAAK;AAEzB,aAAW,OAAO,OAAO,KAAK,QAAQ,GAAqB;AACzD,UAAM,YAAY,KAAK,GAAG;AAC1B,UAAM,gBAAgB,SAAS,GAAG;AAElC,QAAI,kBAAkB,QAAW;AAC/B;AAAA,IACF;AAEA,QACE,OAAO,cAAc,YACrB,cAAc,QACd,CAAC,MAAM,QAAQ,SAAS,KACxB,OAAO,kBAAkB,YACzB,kBAAkB,QAClB,CAAC,MAAM,QAAQ,aAAa,GAC5B;AAEA,aAAO,GAAG,IAAI;AAAA,QACZ;AAAA,QACA;AAAA,MACF;AAAA,IACF,OAAO;AAEL,aAAO,GAAG,IAAI;AAAA,IAChB;AAAA,EACF;AAEA,SAAO;AACT;AAUA,eAAsB,WAAW,KAAc,YAAiD;AAC9F,QAAM,aAAa,OAAO,QAAQ,IAAI;AACtC,QAAM,SAAS,UAAU;AAGzB,MAAI;AACJ,MAAI,YAAY;AACd,UAAM,SAAS,UAAU,UAAU;AACnC,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,mBAAmB,mBAAmB,UAAU,IAAI;AAAA,QAC5D,kBAAkB,CAAC,mBAAmB,qBAAqB,QAAQ;AAAA,MACrE,CAAC;AAAA,IACH;AACA,iBAAa,OAAO;AACpB,WAAO,MAAM,iBAAiB,UAAU,EAAE;AAAA,EAC5C,OAAO;AACL,iBAAa,iBAAiB,UAAU;AACxC,UAAM,iBAAiB,aAAa,UAAU;AAC9C,WAAO,MAAM,yBAAyB,eAAe,IAAI,EAAE;AAAA,EAC7D;AAGA,QAAM,aAAa,eAAe,UAAU;AAC5C,MAAI,aAAyB,CAAC;AAE9B,MAAI,YAAY;AACd,WAAO,MAAM,wBAAwB,UAAU,EAAE;AACjD,iBAAa,MAAM,eAAe,UAAU;AAAA,EAC9C;AAGA,QAAM,eAAe;AAAA,IACnB;AAAA,IACA;AAAA,EACF;AAEA,SAAO;AACT;AAaO,SAAS,gBAAgB,UAA0B;AACxD,MAAI,aAAa,KAAK,QAAQ,QAAQ;AACtC,QAAM,kBAAkB,CAAC,uBAAuB,cAAc,cAAc;AAG5E,SAAO,eAAe,KAAK,QAAQ,UAAU,GAAG;AAE9C,QACE,GAAG,WAAW,KAAK,KAAK,YAAY,qBAAqB,CAAC,KAC1D,GAAG,WAAW,KAAK,KAAK,YAAY,YAAY,CAAC,GACjD;AACA,aAAO;AAAA,IACT;AAGA,QAAI,GAAG,WAAW,KAAK,KAAK,YAAY,cAAc,CAAC,GAAG;AAGxD,YAAM,YAAY,KAAK,QAAQ,UAAU;AACzC,UACE,GAAG,WAAW,KAAK,KAAK,WAAW,qBAAqB,CAAC,KACzD,GAAG,WAAW,KAAK,KAAK,WAAW,YAAY,CAAC,GAChD;AACA,eAAO;AAAA,MACT;AAEA,aAAO;AAAA,IACT;AAEA,iBAAa,KAAK,QAAQ,UAAU;AAAA,EACtC;AAGA,SAAO,KAAK,QAAQ,QAAQ;AAC9B;AASO,SAAS,aAAa,QAA2B,aAAoC;AAC1F,QAAM,OAAO,KAAK,QAAQ,WAAW;AAGrC,QAAM,UAAU,KAAK,QAAQ,MAAM,OAAO,MAAM,GAAG;AACnD,QAAM,eAAe,KAAK,QAAQ,MAAM,OAAO,MAAM,QAAQ;AAC7D,QAAM,UAAU,KAAK,QAAQ,MAAM,OAAO,MAAM,GAAG;AACnD,QAAM,YAAY,KAAK,QAAQ,MAAM,OAAO,MAAM,KAAK;AACvD,QAAM,cAAc,KAAK,QAAQ,MAAM,OAAO,MAAM,OAAO;AAG3D,QAAM,cAAc;AAAA,IAClB,SAAS,KAAK,QAAQ,SAAS,OAAO,MAAM,OAAO,OAAO;AAAA,IAC1D,OAAO,KAAK,QAAQ,WAAW,OAAO,MAAM,OAAO,KAAK;AAAA,IACxD,YAAY,KAAK,QAAQ,SAAS,OAAO,MAAM,OAAO,UAAU;AAAA,IAChE,OAAO,KAAK,QAAQ,SAAS,OAAO,MAAM,OAAO,KAAK;AAAA,IACtD,QAAQ,KAAK,QAAQ,SAAS,OAAO,MAAM,OAAO,MAAM;AAAA,EAC1D;AAEA,SAAO;AAAA,IACL;AAAA,IACA,KAAK;AAAA,IACL,UAAU;AAAA,IACV,KAAK;AAAA,IACL,OAAO;AAAA,IACP,SAAS;AAAA,IACT,QAAQ;AAAA,EACV;AACF;AASO,SAAS,cAAc,QAA2B,aAAsC;AAC7F,QAAM,OAAO,eAAe,gBAAgB,QAAQ,IAAI,CAAC;AACzD,QAAM,gBAAgB,aAAa,QAAQ,IAAI;AAE/C,SAAO;AAAA,IACL,GAAG;AAAA,IACH,OAAO;AAAA,EACT;AACF;AAuBO,SAAS,aAAa,QAAgC;AAC3D,SAAO;AACT;AAWO,SAAS,eAAe,QAAqC;AAClE,QAAM,SAAmB,CAAC;AAG1B,MAAI,CAAC,OAAO,OAAO;AACjB,WAAO,KAAK,0CAA0C;AAAA,EACxD,OAAO;AACL,QAAI,CAAC,OAAO,MAAM,IAAK,QAAO,KAAK,uBAAuB;AAC1D,QAAI,CAAC,OAAO,MAAM,SAAU,QAAO,KAAK,4BAA4B;AACpE,QAAI,CAAC,OAAO,MAAM,IAAK,QAAO,KAAK,uBAAuB;AAC1D,QAAI,CAAC,OAAO,MAAM,MAAO,QAAO,KAAK,yBAAyB;AAC9D,QAAI,CAAC,OAAO,MAAM,QAAS,QAAO,KAAK,2BAA2B;AAAA,EACpE;AAGA,MAAI,CAAC,OAAO,UAAU;AACpB,WAAO,KAAK,6CAA6C;AAAA,EAC3D,OAAO;AACL,QAAI,OAAO,SAAS,aAAa,WAAW;AAC1C,aAAO,KAAK,qCAAqC;AAAA,IACnD;AAAA,EACF;AAGA,MAAI,CAAC,OAAO,IAAI;AACd,WAAO,KAAK,uCAAuC;AAAA,EACrD,OAAO;AACL,QAAI,OAAO,GAAG,cAAc,UAAU;AACpC,aAAO,KAAK,+BAA+B;AAAA,IAC7C;AAAA,EACF;AAEA,SAAO;AACT;AAOO,SAAS,WAAW,OAA4D;AACrF,QAAM,SAAS,CAAC,MAAc;AAC5B,QAAI;AACF,SAAG,WAAW,CAAC;AACf,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM,OAAO,MAAM,IAAI;AAAA,IACvB,KAAK,OAAO,MAAM,GAAG;AAAA,IACrB,UAAU,OAAO,MAAM,QAAQ;AAAA,IAC/B,KAAK,OAAO,MAAM,GAAG;AAAA,IACrB,OAAO,OAAO,MAAM,KAAK;AAAA,IACzB,SAAS,OAAO,MAAM,OAAO;AAAA,IAC7B,QAAQ;AAAA,MACN,SAAS,OAAO,MAAM,OAAO,OAAO;AAAA,MACpC,OAAO,OAAO,MAAM,OAAO,KAAK;AAAA,MAChC,YAAY,OAAO,MAAM,OAAO,UAAU;AAAA,MAC1C,OAAO,OAAO,MAAM,OAAO,KAAK;AAAA,MAChC,QAAQ,OAAO,MAAM,OAAO,MAAM;AAAA,IACpC;AAAA,EACF;AACF;","names":[]}
|
package/dist/cli.js
CHANGED
|
@@ -3,11 +3,13 @@ import {
|
|
|
3
3
|
findProjectRoot,
|
|
4
4
|
loadConfig,
|
|
5
5
|
resolveConfig
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-QLVSHP7X.js";
|
|
7
7
|
import {
|
|
8
|
+
initImportResolver,
|
|
9
|
+
setPaths,
|
|
8
10
|
toKebabCase,
|
|
9
11
|
toPascalCase
|
|
10
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-EIH4RRIJ.js";
|
|
11
13
|
import {
|
|
12
14
|
detectPreset,
|
|
13
15
|
getPresetNames,
|
|
@@ -68,6 +70,17 @@ Make sure the schema file exists at: ${schemaPath}`);
|
|
|
68
70
|
}
|
|
69
71
|
logger.success("Schema validated");
|
|
70
72
|
logger.info("\n\u{1F4E6} Generating files...\n");
|
|
73
|
+
const monorepoPaths = {
|
|
74
|
+
root: resolvedConfig.paths.root,
|
|
75
|
+
app: resolvedConfig.paths.app,
|
|
76
|
+
database: resolvedConfig.paths.database,
|
|
77
|
+
lib: resolvedConfig.paths.lib,
|
|
78
|
+
hooks: resolvedConfig.paths.hooks,
|
|
79
|
+
schemas: resolvedConfig.paths.schemas,
|
|
80
|
+
data: path.join(resolvedConfig.paths.root, "packages/data")
|
|
81
|
+
};
|
|
82
|
+
setPaths(monorepoPaths);
|
|
83
|
+
initImportResolver(resolvedConfig);
|
|
71
84
|
const { generate } = await import("./index.js");
|
|
72
85
|
await generate(name, {
|
|
73
86
|
skipMigration: options.skipMigration,
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/index.ts","../src/cli/commands/generate.ts","../src/cli/commands/init.ts","../src/cli/commands/remove.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * CLI entry point for @betterstart/cli\n */\n\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { Command } from 'commander'\nimport { createConsoleLogger, setLogger } from '../core/logger'\nimport { generateCommand } from './commands/generate'\nimport { initCommand } from './commands/init'\nimport { removeCommand } from './commands/remove'\n\n// Read version from package.json\nfunction getVersion(): string {\n try {\n const __dirname = path.dirname(fileURLToPath(import.meta.url))\n // Try dist layout first (built), then source layout\n for (const rel of ['../../package.json', '../package.json']) {\n const pkgPath = path.resolve(__dirname, rel)\n if (fs.existsSync(pkgPath)) {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'))\n return pkg.version ?? '0.0.0'\n }\n }\n } catch {\n // Fallback\n }\n return '0.0.0'\n}\n\n// Set up console logger\nsetLogger(createConsoleLogger())\n\n/**\n * Create the CLI program\n */\nfunction createProgram(): Command {\n const program = new Command()\n\n program\n .name('betterstart')\n .description('Generate admin CRUD interfaces for your Next.js project')\n .version(getVersion())\n\n // Add commands\n program.addCommand(initCommand())\n program.addCommand(generateCommand())\n program.addCommand(removeCommand())\n\n return program\n}\n\n/**\n * Run the CLI\n */\nexport async function run(args?: string[]): Promise<void> {\n const program = createProgram()\n\n try {\n await program.parseAsync(args || process.argv)\n } catch (error) {\n if (error instanceof Error) {\n console.error(`\\nError: ${error.message}`)\n } else {\n console.error('\\nAn unexpected error occurred')\n }\n process.exit(1)\n }\n}\n\n// Always run when this file is executed\nrun()\n","/**\n * CLI generate command\n * Generates code from a schema\n */\n\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport { Command } from 'commander'\nimport { findProjectRoot, loadConfig, resolveConfig } from '../../config'\nimport { SchemaValidationError } from '../../core/errors'\nimport { getLogger } from '../../core/logger'\nimport type { Schema } from '../../types'\n\n/**\n * Create the generate command\n */\nexport function generateCommand(): Command {\n const command = new Command('generate')\n .alias('g')\n .description('Generate code from a schema')\n .argument('<name>', 'Schema name to generate')\n .option('--skip-migration', 'Skip database migration')\n .option('-f, --force', 'Overwrite existing files')\n .option('--cwd <path>', 'Project root path')\n .option('--generators <generators>', 'Comma-separated list of generators to run')\n .action(async (name, options) => {\n const logger = getLogger()\n const cwd = options.cwd ? path.resolve(options.cwd) : process.cwd()\n\n logger.info('\\n🚀 Betterstart Generator\\n')\n\n try {\n // Find project root and load config\n const projectRoot = findProjectRoot(cwd)\n logger.info(`📁 Project root: ${projectRoot}`)\n\n const config = await loadConfig(projectRoot)\n const resolvedConfig = resolveConfig(config, projectRoot)\n logger.info(`📄 Loading schema: ${name}.json`)\n\n // Find schema file\n const schemaPath = path.join(resolvedConfig.paths.schemas, `${name}.json`)\n\n if (!fs.existsSync(schemaPath)) {\n logger.error(`Schema file not found: ${schemaPath}`)\n logger.info(`\\nMake sure the schema file exists at: ${schemaPath}`)\n logger.info('You can create a schema using:')\n logger.info(` echo '{}' > ${schemaPath}`)\n process.exit(1)\n }\n\n // Load and parse schema\n let schema: Schema\n try {\n const schemaContent = fs.readFileSync(schemaPath, 'utf-8')\n schema = JSON.parse(schemaContent)\n } catch (error) {\n logger.error(\n `Failed to parse schema: ${error instanceof Error ? error.message : String(error)}`\n )\n process.exit(1)\n }\n\n // Validate schema\n const validationErrors = validateSchema(schema)\n if (validationErrors.length > 0) {\n throw new SchemaValidationError('Schema validation failed', validationErrors, {\n schemaPath\n })\n }\n\n logger.success('Schema validated')\n logger.info('\\n📦 Generating files...\\n')\n\n // For now, we'll import the existing generate function\n // In the full refactoring, this would use the new generator system\n const { generate } = await import('../../index')\n\n await generate(name, {\n skipMigration: options.skipMigration,\n force: options.force\n })\n } catch (error) {\n if (error instanceof SchemaValidationError) {\n logger.error('\\nSchema validation failed:\\n')\n for (const validationError of error.validationErrors) {\n logger.error(` - ${validationError}`)\n }\n } else if (error instanceof Error) {\n logger.error(`\\n${error.message}`)\n }\n process.exit(1)\n }\n })\n\n return command\n}\n\n/**\n * Validate schema structure\n */\nfunction validateSchema(schema: Schema): string[] {\n const errors: string[] = []\n\n if (!schema.name || typeof schema.name !== 'string') {\n errors.push('Schema must have a valid \"name\" field')\n }\n\n if (!schema.label || typeof schema.label !== 'string') {\n errors.push('Schema must have a valid \"label\" field')\n }\n\n if (!schema.description || typeof schema.description !== 'string') {\n errors.push('Schema must have a valid \"description\" field')\n }\n\n if (!schema.icon || typeof schema.icon !== 'string') {\n errors.push('Schema must have a valid \"icon\" field')\n }\n\n if (!Array.isArray(schema.fields) || schema.fields.length === 0) {\n errors.push('Schema must have at least one field')\n }\n\n if (!Array.isArray(schema.columns) || schema.columns.length === 0) {\n errors.push('Schema must have at least one column')\n }\n\n // Validate fields\n for (const field of schema.fields || []) {\n if (field.type === 'separator') {\n continue\n }\n if (!field.name || !field.type) {\n errors.push(`Field is missing required properties: ${JSON.stringify(field)}`)\n }\n }\n\n return errors\n}\n","/**\n * CLI init command\n * Initializes betterstart in a project\n */\n\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport { Command } from 'commander'\nimport { findProjectRoot } from '../../config'\nimport { detectPreset, getPresetNames, presets } from '../../config/presets'\nimport { getLogger } from '../../core/logger'\n\n/**\n * Create the init command\n */\nexport function initCommand(): Command {\n const command = new Command('init')\n .description('Initialize betterstart in your project')\n .option('-p, --preset <preset>', 'Use a preset configuration')\n .option('-y, --yes', 'Skip interactive prompts and use defaults')\n .option('--cwd <path>', 'Project root path')\n .action(async (options) => {\n const logger = getLogger()\n const cwd = options.cwd ? path.resolve(options.cwd) : process.cwd()\n\n logger.info('\\n🚀 Initializing betterstart...\\n')\n\n // Find project root\n const projectRoot = findProjectRoot(cwd)\n logger.info(`📁 Project root: ${projectRoot}`)\n\n // Check if config already exists\n const configPath = path.join(projectRoot, 'betterstart.config.ts')\n if (fs.existsSync(configPath)) {\n logger.warn('Configuration file already exists: betterstart.config.ts')\n\n if (!options.yes) {\n logger.info('Use --yes to overwrite')\n return\n }\n }\n\n // Detect or use specified preset\n let presetName = options.preset\n if (!presetName) {\n const detected = detectPreset(projectRoot)\n presetName = detected.name\n logger.info(`🔍 Detected project type: ${presetName}`)\n } else {\n if (!getPresetNames().includes(presetName)) {\n logger.error(`Unknown preset: ${presetName}`)\n logger.info(`Available presets: ${getPresetNames().join(', ')}`)\n process.exit(1)\n }\n logger.info(`📋 Using preset: ${presetName}`)\n }\n\n const preset = presets[presetName]\n\n // Generate config file content\n const configContent = generateConfigFile(presetName, preset.config)\n\n // Write config file\n fs.writeFileSync(configPath, configContent)\n logger.success(`Created: betterstart.config.ts`)\n\n // Create schemas directory if it doesn't exist\n const schemasDir = path.join(projectRoot, preset.config.paths?.schemas || 'schemas')\n if (!fs.existsSync(schemasDir)) {\n fs.mkdirSync(schemasDir, { recursive: true })\n logger.success(`Created: ${preset.config.paths?.schemas || 'schemas'}/`)\n }\n\n // Create example schema\n const exampleSchemaPath = path.join(schemasDir, 'example.json')\n if (!fs.existsSync(exampleSchemaPath)) {\n fs.writeFileSync(exampleSchemaPath, generateExampleSchema())\n logger.success('Created: example.json (sample schema)')\n }\n\n logger.info('\\n✅ Initialization complete!\\n')\n logger.info('Next steps:')\n logger.info(' 1. Review betterstart.config.ts and adjust paths if needed')\n logger.info(' 2. Create your schema in the schemas directory')\n logger.info(' 3. Run: npx betterstart generate <schema-name>')\n logger.info('')\n })\n\n return command\n}\n\n/**\n * Generate the config file content\n */\nfunction generateConfigFile(presetName: string, _config: unknown): string {\n // For monorepo preset, use a simpler config since most paths are defaults\n if (presetName === 'nextjs-monorepo') {\n return `import { defineConfig } from '@betterstart/cli'\n\nexport default defineConfig({\n // Using nextjs-monorepo preset defaults\n // Customize paths if your project structure differs:\n // paths: {\n // app: 'apps/web',\n // database: 'packages/database',\n // lib: 'packages/lib',\n // hooks: 'packages/hooks',\n // schemas: 'schemas',\n // }\n})\n`\n }\n\n // For standalone preset\n if (presetName === 'nextjs-standalone') {\n return `import { defineConfig } from '@betterstart/cli'\n\nexport default defineConfig({\n // Import paths for generated code\n // Customize these to match your project structure:\n imports: {\n database: '@/lib/db',\n adminUi: '@/components/ui',\n webUi: '@/components/ui',\n hooks: '@/hooks',\n utils: '@/lib/utils',\n types: '@/types',\n lib: '@/lib',\n actions: '@/lib/actions/{name}',\n libMarkdown: '@/lib/markdown'\n },\n // Customize paths if your project structure differs:\n // paths: {\n // app: '.',\n // database: '.',\n // lib: '.',\n // hooks: '.',\n // schemas: 'schemas',\n // output: {\n // actions: 'src/actions',\n // hooks: 'src/hooks',\n // components: 'src/components/admin',\n // pages: 'src/app/(admin)/admin',\n // emails: 'src/emails'\n // }\n // }\n})\n`\n }\n\n // For custom preset, include all paths\n return `import { defineConfig } from '@betterstart/cli'\n\nexport default defineConfig({\n // Import paths for generated code\n imports: {\n database: '@/lib/db',\n adminUi: '@/components/ui',\n webUi: '@/components/ui',\n hooks: '@/hooks',\n utils: '@/lib/utils',\n types: '@/types',\n lib: '@/lib',\n actions: '@/lib/actions/{name}',\n libMarkdown: '@/lib/markdown'\n },\n paths: {\n app: '.',\n database: '.',\n lib: '.',\n hooks: '.',\n schemas: 'schemas',\n output: {\n actions: 'src/actions',\n hooks: 'src/hooks',\n components: 'src/components/admin',\n pages: 'src/app/(admin)/admin',\n emails: 'src/emails'\n }\n },\n database: {\n provider: 'drizzle',\n schemaFile: 'src/db/schema.ts',\n migrationsDir: 'src/db/migrations',\n autoMigrate: true\n },\n ui: {\n framework: 'shadcn',\n components: {\n path: '@/components/ui',\n adminPath: '@/components/admin'\n }\n }\n})\n`\n}\n\n/**\n * Generate an example schema\n */\nfunction generateExampleSchema(): string {\n return JSON.stringify(\n {\n $schema: './schema.json',\n name: 'posts',\n label: 'Posts',\n description: 'Blog posts and articles',\n icon: 'FileText',\n fields: [\n {\n name: 'title',\n type: 'string',\n label: 'Title',\n required: true,\n length: 255\n },\n {\n name: 'slug',\n type: 'string',\n label: 'Slug',\n required: true,\n length: 255\n },\n {\n name: 'content',\n type: 'markdown',\n label: 'Content',\n required: true\n },\n {\n name: 'published',\n type: 'boolean',\n label: 'Published',\n default: false\n }\n ],\n columns: [\n {\n accessorKey: 'title',\n header: 'Title',\n type: 'text',\n sortable: true\n },\n {\n accessorKey: 'slug',\n header: 'Slug',\n type: 'text'\n },\n {\n accessorKey: 'published',\n header: 'Status',\n type: 'badge'\n },\n {\n accessorKey: 'createdAt',\n header: 'Created',\n type: 'date',\n sortable: true\n }\n ],\n actions: {\n create: true,\n edit: true,\n delete: true\n }\n },\n null,\n 2\n )\n}\n","/**\n * CLI remove command\n * Removes generated files for a schema\n */\n\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport readline from 'node:readline'\nimport { Command } from 'commander'\nimport { findProjectRoot, loadConfig, resolveConfig } from '../../config'\nimport { getLogger } from '../../core/logger'\nimport { toKebabCase, toPascalCase } from '../../utils'\n\n/**\n * Create the remove command\n */\nexport function removeCommand(): Command {\n const command = new Command('remove')\n .alias('rm')\n .description('Remove generated files for a schema')\n .argument('<name>', 'Schema name to remove')\n .option('-f, --force', 'Skip confirmation prompt')\n .option('--cwd <path>', 'Project root path')\n .action(async (name, options) => {\n const logger = getLogger()\n const cwd = options.cwd ? path.resolve(options.cwd) : process.cwd()\n\n logger.info('\\n🗑️ Betterstart Remove\\n')\n\n try {\n // Find project root and load config\n const projectRoot = findProjectRoot(cwd)\n const config = await loadConfig(projectRoot)\n const resolvedConfig = resolveConfig(config, projectRoot)\n\n const kebabName = toKebabCase(name)\n const _pascalName = toPascalCase(name)\n\n // Collect files to remove\n const filesToRemove: string[] = []\n\n // Admin pages directory\n const adminPagesDir = path.join(resolvedConfig.paths.output.pages, kebabName)\n if (fs.existsSync(adminPagesDir)) {\n filesToRemove.push(adminPagesDir)\n }\n\n // Server actions file\n const actionsFile = path.join(resolvedConfig.paths.output.actions, `${kebabName}.ts`)\n if (fs.existsSync(actionsFile)) {\n filesToRemove.push(actionsFile)\n }\n\n // Hook file\n const hookFile = path.join(resolvedConfig.paths.output.hooks, `use-${kebabName}.ts`)\n if (fs.existsSync(hookFile)) {\n filesToRemove.push(hookFile)\n }\n\n if (filesToRemove.length === 0) {\n logger.warn(`No generated files found for schema: ${name}`)\n return\n }\n\n // Show files to remove\n logger.info('The following files will be removed:\\n')\n for (const file of filesToRemove) {\n const relativePath = path.relative(projectRoot, file)\n const isDir = fs.statSync(file).isDirectory()\n logger.info(` ${isDir ? '📁' : '📄'} ${relativePath}${isDir ? '/' : ''}`)\n }\n\n // Confirm removal\n if (!options.force) {\n const confirmed = await confirm('\\nAre you sure you want to remove these files?')\n if (!confirmed) {\n logger.info('\\nRemoval cancelled.')\n return\n }\n }\n\n // Remove files\n logger.info('')\n for (const file of filesToRemove) {\n const relativePath = path.relative(projectRoot, file)\n const isDir = fs.statSync(file).isDirectory()\n\n if (isDir) {\n fs.rmSync(file, { recursive: true, force: true })\n } else {\n fs.unlinkSync(file)\n }\n\n logger.success(`Removed: ${relativePath}`)\n }\n\n logger.info('\\n✅ Removal complete!')\n logger.info('\\nNote: The following may need manual cleanup:')\n logger.info(' - Database table (run a migration to drop it)')\n logger.info(' - Navigation entries in navigation.json')\n logger.info(' - Any imports referencing removed files')\n } catch (error) {\n if (error instanceof Error) {\n logger.error(`\\n${error.message}`)\n }\n process.exit(1)\n }\n })\n\n return command\n}\n\n/**\n * Prompt for confirmation\n */\nasync function confirm(message: string): Promise<boolean> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout\n })\n\n return new Promise((resolve) => {\n rl.question(`${message} (y/N) `, (answer) => {\n rl.close()\n resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes')\n })\n })\n}\n"],"mappings":"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","names":["fs","path","Command","fs","path","Command","Command","path","fs","fs","path","Command","Command","path","fs","path","fs","Command"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli/index.ts","../src/cli/commands/generate.ts","../src/cli/commands/init.ts","../src/cli/commands/remove.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * CLI entry point for @betterstart/cli\n */\n\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { Command } from 'commander'\nimport { createConsoleLogger, setLogger } from '../core/logger'\nimport { generateCommand } from './commands/generate'\nimport { initCommand } from './commands/init'\nimport { removeCommand } from './commands/remove'\n\n// Read version from package.json\nfunction getVersion(): string {\n try {\n const __dirname = path.dirname(fileURLToPath(import.meta.url))\n // Try dist layout first (built), then source layout\n for (const rel of ['../../package.json', '../package.json']) {\n const pkgPath = path.resolve(__dirname, rel)\n if (fs.existsSync(pkgPath)) {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'))\n return pkg.version ?? '0.0.0'\n }\n }\n } catch {\n // Fallback\n }\n return '0.0.0'\n}\n\n// Set up console logger\nsetLogger(createConsoleLogger())\n\n/**\n * Create the CLI program\n */\nfunction createProgram(): Command {\n const program = new Command()\n\n program\n .name('betterstart')\n .description('Generate admin CRUD interfaces for your Next.js project')\n .version(getVersion())\n\n // Add commands\n program.addCommand(initCommand())\n program.addCommand(generateCommand())\n program.addCommand(removeCommand())\n\n return program\n}\n\n/**\n * Run the CLI\n */\nexport async function run(args?: string[]): Promise<void> {\n const program = createProgram()\n\n try {\n await program.parseAsync(args || process.argv)\n } catch (error) {\n if (error instanceof Error) {\n console.error(`\\nError: ${error.message}`)\n } else {\n console.error('\\nAn unexpected error occurred')\n }\n process.exit(1)\n }\n}\n\n// Always run when this file is executed\nrun()\n","/**\n * CLI generate command\n * Generates code from a schema\n */\n\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport { Command } from 'commander'\nimport { findProjectRoot, loadConfig, resolveConfig } from '../../config'\nimport { SchemaValidationError } from '../../core/errors'\nimport { getLogger } from '../../core/logger'\nimport type { MonorepoPaths, Schema } from '../../types'\nimport { initImportResolver, setPaths } from '../../utils'\n\n/**\n * Create the generate command\n */\nexport function generateCommand(): Command {\n const command = new Command('generate')\n .alias('g')\n .description('Generate code from a schema')\n .argument('<name>', 'Schema name to generate')\n .option('--skip-migration', 'Skip database migration')\n .option('-f, --force', 'Overwrite existing files')\n .option('--cwd <path>', 'Project root path')\n .option('--generators <generators>', 'Comma-separated list of generators to run')\n .action(async (name, options) => {\n const logger = getLogger()\n const cwd = options.cwd ? path.resolve(options.cwd) : process.cwd()\n\n logger.info('\\n🚀 Betterstart Generator\\n')\n\n try {\n // Find project root and load config\n const projectRoot = findProjectRoot(cwd)\n logger.info(`📁 Project root: ${projectRoot}`)\n\n const config = await loadConfig(projectRoot)\n const resolvedConfig = resolveConfig(config, projectRoot)\n logger.info(`📄 Loading schema: ${name}.json`)\n\n // Find schema file\n const schemaPath = path.join(resolvedConfig.paths.schemas, `${name}.json`)\n\n if (!fs.existsSync(schemaPath)) {\n logger.error(`Schema file not found: ${schemaPath}`)\n logger.info(`\\nMake sure the schema file exists at: ${schemaPath}`)\n logger.info('You can create a schema using:')\n logger.info(` echo '{}' > ${schemaPath}`)\n process.exit(1)\n }\n\n // Load and parse schema\n let schema: Schema\n try {\n const schemaContent = fs.readFileSync(schemaPath, 'utf-8')\n schema = JSON.parse(schemaContent)\n } catch (error) {\n logger.error(\n `Failed to parse schema: ${error instanceof Error ? error.message : String(error)}`\n )\n process.exit(1)\n }\n\n // Validate schema\n const validationErrors = validateSchema(schema)\n if (validationErrors.length > 0) {\n throw new SchemaValidationError('Schema validation failed', validationErrors, {\n schemaPath\n })\n }\n\n logger.success('Schema validated')\n logger.info('\\n📦 Generating files...\\n')\n\n // Seed global paths and import resolver from resolved config\n // so generators work in both monorepo and standalone projects\n const monorepoPaths: MonorepoPaths = {\n root: resolvedConfig.paths.root,\n app: resolvedConfig.paths.app,\n database: resolvedConfig.paths.database,\n lib: resolvedConfig.paths.lib,\n hooks: resolvedConfig.paths.hooks,\n schemas: resolvedConfig.paths.schemas,\n data: path.join(resolvedConfig.paths.root, 'packages/data')\n }\n setPaths(monorepoPaths)\n initImportResolver(resolvedConfig)\n\n const { generate } = await import('../../index')\n\n await generate(name, {\n skipMigration: options.skipMigration,\n force: options.force\n })\n } catch (error) {\n if (error instanceof SchemaValidationError) {\n logger.error('\\nSchema validation failed:\\n')\n for (const validationError of error.validationErrors) {\n logger.error(` - ${validationError}`)\n }\n } else if (error instanceof Error) {\n logger.error(`\\n${error.message}`)\n }\n process.exit(1)\n }\n })\n\n return command\n}\n\n/**\n * Validate schema structure\n */\nfunction validateSchema(schema: Schema): string[] {\n const errors: string[] = []\n\n if (!schema.name || typeof schema.name !== 'string') {\n errors.push('Schema must have a valid \"name\" field')\n }\n\n if (!schema.label || typeof schema.label !== 'string') {\n errors.push('Schema must have a valid \"label\" field')\n }\n\n if (!schema.description || typeof schema.description !== 'string') {\n errors.push('Schema must have a valid \"description\" field')\n }\n\n if (!schema.icon || typeof schema.icon !== 'string') {\n errors.push('Schema must have a valid \"icon\" field')\n }\n\n if (!Array.isArray(schema.fields) || schema.fields.length === 0) {\n errors.push('Schema must have at least one field')\n }\n\n if (!Array.isArray(schema.columns) || schema.columns.length === 0) {\n errors.push('Schema must have at least one column')\n }\n\n // Validate fields\n for (const field of schema.fields || []) {\n if (field.type === 'separator') {\n continue\n }\n if (!field.name || !field.type) {\n errors.push(`Field is missing required properties: ${JSON.stringify(field)}`)\n }\n }\n\n return errors\n}\n","/**\n * CLI init command\n * Initializes betterstart in a project\n */\n\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport { Command } from 'commander'\nimport { findProjectRoot } from '../../config'\nimport { detectPreset, getPresetNames, presets } from '../../config/presets'\nimport { getLogger } from '../../core/logger'\n\n/**\n * Create the init command\n */\nexport function initCommand(): Command {\n const command = new Command('init')\n .description('Initialize betterstart in your project')\n .option('-p, --preset <preset>', 'Use a preset configuration')\n .option('-y, --yes', 'Skip interactive prompts and use defaults')\n .option('--cwd <path>', 'Project root path')\n .action(async (options) => {\n const logger = getLogger()\n const cwd = options.cwd ? path.resolve(options.cwd) : process.cwd()\n\n logger.info('\\n🚀 Initializing betterstart...\\n')\n\n // Find project root\n const projectRoot = findProjectRoot(cwd)\n logger.info(`📁 Project root: ${projectRoot}`)\n\n // Check if config already exists\n const configPath = path.join(projectRoot, 'betterstart.config.ts')\n if (fs.existsSync(configPath)) {\n logger.warn('Configuration file already exists: betterstart.config.ts')\n\n if (!options.yes) {\n logger.info('Use --yes to overwrite')\n return\n }\n }\n\n // Detect or use specified preset\n let presetName = options.preset\n if (!presetName) {\n const detected = detectPreset(projectRoot)\n presetName = detected.name\n logger.info(`🔍 Detected project type: ${presetName}`)\n } else {\n if (!getPresetNames().includes(presetName)) {\n logger.error(`Unknown preset: ${presetName}`)\n logger.info(`Available presets: ${getPresetNames().join(', ')}`)\n process.exit(1)\n }\n logger.info(`📋 Using preset: ${presetName}`)\n }\n\n const preset = presets[presetName]\n\n // Generate config file content\n const configContent = generateConfigFile(presetName, preset.config)\n\n // Write config file\n fs.writeFileSync(configPath, configContent)\n logger.success(`Created: betterstart.config.ts`)\n\n // Create schemas directory if it doesn't exist\n const schemasDir = path.join(projectRoot, preset.config.paths?.schemas || 'schemas')\n if (!fs.existsSync(schemasDir)) {\n fs.mkdirSync(schemasDir, { recursive: true })\n logger.success(`Created: ${preset.config.paths?.schemas || 'schemas'}/`)\n }\n\n // Create example schema\n const exampleSchemaPath = path.join(schemasDir, 'example.json')\n if (!fs.existsSync(exampleSchemaPath)) {\n fs.writeFileSync(exampleSchemaPath, generateExampleSchema())\n logger.success('Created: example.json (sample schema)')\n }\n\n logger.info('\\n✅ Initialization complete!\\n')\n logger.info('Next steps:')\n logger.info(' 1. Review betterstart.config.ts and adjust paths if needed')\n logger.info(' 2. Create your schema in the schemas directory')\n logger.info(' 3. Run: npx betterstart generate <schema-name>')\n logger.info('')\n })\n\n return command\n}\n\n/**\n * Generate the config file content\n */\nfunction generateConfigFile(presetName: string, _config: unknown): string {\n // For monorepo preset, use a simpler config since most paths are defaults\n if (presetName === 'nextjs-monorepo') {\n return `import { defineConfig } from '@betterstart/cli'\n\nexport default defineConfig({\n // Using nextjs-monorepo preset defaults\n // Customize paths if your project structure differs:\n // paths: {\n // app: 'apps/web',\n // database: 'packages/database',\n // lib: 'packages/lib',\n // hooks: 'packages/hooks',\n // schemas: 'schemas',\n // }\n})\n`\n }\n\n // For standalone preset\n if (presetName === 'nextjs-standalone') {\n return `import { defineConfig } from '@betterstart/cli'\n\nexport default defineConfig({\n // Import paths for generated code\n // Customize these to match your project structure:\n imports: {\n database: '@/lib/db',\n adminUi: '@/components/ui',\n webUi: '@/components/ui',\n hooks: '@/hooks',\n utils: '@/lib/utils',\n types: '@/types',\n lib: '@/lib',\n actions: '@/lib/actions/{name}',\n libMarkdown: '@/lib/markdown'\n },\n // Customize paths if your project structure differs:\n // paths: {\n // app: '.',\n // database: '.',\n // lib: '.',\n // hooks: '.',\n // schemas: 'schemas',\n // output: {\n // actions: 'src/actions',\n // hooks: 'src/hooks',\n // components: 'src/components/admin',\n // pages: 'src/app/(admin)/admin',\n // emails: 'src/emails'\n // }\n // }\n})\n`\n }\n\n // For custom preset, include all paths\n return `import { defineConfig } from '@betterstart/cli'\n\nexport default defineConfig({\n // Import paths for generated code\n imports: {\n database: '@/lib/db',\n adminUi: '@/components/ui',\n webUi: '@/components/ui',\n hooks: '@/hooks',\n utils: '@/lib/utils',\n types: '@/types',\n lib: '@/lib',\n actions: '@/lib/actions/{name}',\n libMarkdown: '@/lib/markdown'\n },\n paths: {\n app: '.',\n database: '.',\n lib: '.',\n hooks: '.',\n schemas: 'schemas',\n output: {\n actions: 'src/actions',\n hooks: 'src/hooks',\n components: 'src/components/admin',\n pages: 'src/app/(admin)/admin',\n emails: 'src/emails'\n }\n },\n database: {\n provider: 'drizzle',\n schemaFile: 'src/db/schema.ts',\n migrationsDir: 'src/db/migrations',\n autoMigrate: true\n },\n ui: {\n framework: 'shadcn',\n components: {\n path: '@/components/ui',\n adminPath: '@/components/admin'\n }\n }\n})\n`\n}\n\n/**\n * Generate an example schema\n */\nfunction generateExampleSchema(): string {\n return JSON.stringify(\n {\n $schema: './schema.json',\n name: 'posts',\n label: 'Posts',\n description: 'Blog posts and articles',\n icon: 'FileText',\n fields: [\n {\n name: 'title',\n type: 'string',\n label: 'Title',\n required: true,\n length: 255\n },\n {\n name: 'slug',\n type: 'string',\n label: 'Slug',\n required: true,\n length: 255\n },\n {\n name: 'content',\n type: 'markdown',\n label: 'Content',\n required: true\n },\n {\n name: 'published',\n type: 'boolean',\n label: 'Published',\n default: false\n }\n ],\n columns: [\n {\n accessorKey: 'title',\n header: 'Title',\n type: 'text',\n sortable: true\n },\n {\n accessorKey: 'slug',\n header: 'Slug',\n type: 'text'\n },\n {\n accessorKey: 'published',\n header: 'Status',\n type: 'badge'\n },\n {\n accessorKey: 'createdAt',\n header: 'Created',\n type: 'date',\n sortable: true\n }\n ],\n actions: {\n create: true,\n edit: true,\n delete: true\n }\n },\n null,\n 2\n )\n}\n","/**\n * CLI remove command\n * Removes generated files for a schema\n */\n\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport readline from 'node:readline'\nimport { Command } from 'commander'\nimport { findProjectRoot, loadConfig, resolveConfig } from '../../config'\nimport { getLogger } from '../../core/logger'\nimport { toKebabCase, toPascalCase } from '../../utils'\n\n/**\n * Create the remove command\n */\nexport function removeCommand(): Command {\n const command = new Command('remove')\n .alias('rm')\n .description('Remove generated files for a schema')\n .argument('<name>', 'Schema name to remove')\n .option('-f, --force', 'Skip confirmation prompt')\n .option('--cwd <path>', 'Project root path')\n .action(async (name, options) => {\n const logger = getLogger()\n const cwd = options.cwd ? path.resolve(options.cwd) : process.cwd()\n\n logger.info('\\n🗑️ Betterstart Remove\\n')\n\n try {\n // Find project root and load config\n const projectRoot = findProjectRoot(cwd)\n const config = await loadConfig(projectRoot)\n const resolvedConfig = resolveConfig(config, projectRoot)\n\n const kebabName = toKebabCase(name)\n const _pascalName = toPascalCase(name)\n\n // Collect files to remove\n const filesToRemove: string[] = []\n\n // Admin pages directory\n const adminPagesDir = path.join(resolvedConfig.paths.output.pages, kebabName)\n if (fs.existsSync(adminPagesDir)) {\n filesToRemove.push(adminPagesDir)\n }\n\n // Server actions file\n const actionsFile = path.join(resolvedConfig.paths.output.actions, `${kebabName}.ts`)\n if (fs.existsSync(actionsFile)) {\n filesToRemove.push(actionsFile)\n }\n\n // Hook file\n const hookFile = path.join(resolvedConfig.paths.output.hooks, `use-${kebabName}.ts`)\n if (fs.existsSync(hookFile)) {\n filesToRemove.push(hookFile)\n }\n\n if (filesToRemove.length === 0) {\n logger.warn(`No generated files found for schema: ${name}`)\n return\n }\n\n // Show files to remove\n logger.info('The following files will be removed:\\n')\n for (const file of filesToRemove) {\n const relativePath = path.relative(projectRoot, file)\n const isDir = fs.statSync(file).isDirectory()\n logger.info(` ${isDir ? '📁' : '📄'} ${relativePath}${isDir ? '/' : ''}`)\n }\n\n // Confirm removal\n if (!options.force) {\n const confirmed = await confirm('\\nAre you sure you want to remove these files?')\n if (!confirmed) {\n logger.info('\\nRemoval cancelled.')\n return\n }\n }\n\n // Remove files\n logger.info('')\n for (const file of filesToRemove) {\n const relativePath = path.relative(projectRoot, file)\n const isDir = fs.statSync(file).isDirectory()\n\n if (isDir) {\n fs.rmSync(file, { recursive: true, force: true })\n } else {\n fs.unlinkSync(file)\n }\n\n logger.success(`Removed: ${relativePath}`)\n }\n\n logger.info('\\n✅ Removal complete!')\n logger.info('\\nNote: The following may need manual cleanup:')\n logger.info(' - Database table (run a migration to drop it)')\n logger.info(' - Navigation entries in navigation.json')\n logger.info(' - Any imports referencing removed files')\n } catch (error) {\n if (error instanceof Error) {\n logger.error(`\\n${error.message}`)\n }\n process.exit(1)\n }\n })\n\n return command\n}\n\n/**\n * Prompt for confirmation\n */\nasync function confirm(message: string): Promise<boolean> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout\n })\n\n return new Promise((resolve) => {\n rl.question(`${message} (y/N) `, (answer) => {\n rl.close()\n resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes')\n })\n })\n}\n"],"mappings":"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","names":["fs","path","Command","fs","path","Command","Command","path","fs","fs","path","Command","Command","path","fs","path","fs","Command"]}
|
package/dist/config/index.js
CHANGED
package/dist/core/index.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -191,7 +191,13 @@ declare const extractFileName: (registryPath: string) => string;
|
|
|
191
191
|
*/
|
|
192
192
|
declare function initPaths(startDir?: string): MonorepoPaths;
|
|
193
193
|
/**
|
|
194
|
-
*
|
|
194
|
+
* Set pre-resolved paths (e.g., from config-based resolution)
|
|
195
|
+
* This allows the CLI to seed paths from the config system
|
|
196
|
+
* so that generators work in both monorepo and standalone projects.
|
|
197
|
+
*/
|
|
198
|
+
declare function setPaths(paths: MonorepoPaths): void;
|
|
199
|
+
/**
|
|
200
|
+
* Get monorepo paths (must call initPaths or setPaths first)
|
|
195
201
|
*/
|
|
196
202
|
declare function getPaths(): MonorepoPaths;
|
|
197
203
|
/**
|
|
@@ -263,4 +269,4 @@ declare function validateSchema(schema: Schema): string[];
|
|
|
263
269
|
*/
|
|
264
270
|
declare function generate(schemaName: string, options?: GeneratorOptions): Promise<void>;
|
|
265
271
|
|
|
266
|
-
export { type AddComponentOptions, DEFAULT_TARGET, FormSchema, GeneratorOptions, MonorepoPaths, type RegistryFile, type RegistryIndex, type RegistryItem, Schema, SchemaField, TARGET_CONFIGS, type TargetConfig, type TargetPackage, addAllComponents, addComponents, ensureDir, ensureIdField, exportExists, extractFileName, fetchComponent, fetchIndex, flattenFields, generate, generateActions, generateCache, generateColumns, generateCreatePage, generateDatabase, generateEditPage, generateEmailTemplate, generateForm$1 as generateForm, generateFormActions, generateFormAdminPages, generateFormComponent, generateFormDatabase, generateFormHook, generateHook, generatePage, generatePageContent, generateForm as generatePublicForm, generateTable, getAvailableComponents, getImportResolver, getMigrationTimestamp, getPaths, getProjectRoot, initImportResolver, initPaths, listComponents, pluralize, quotePropertyName, resolveRegistryDeps, singularize, singularizeLabel, toCamelCase, toKebabCase, toPascalCase, toScreamingSnakeCase, toSnakeCase, transformSource, tryFetchComponent, updateExports, updateFormNavigation, updateNavigation, validateSchema };
|
|
272
|
+
export { type AddComponentOptions, DEFAULT_TARGET, FormSchema, GeneratorOptions, MonorepoPaths, type RegistryFile, type RegistryIndex, type RegistryItem, Schema, SchemaField, TARGET_CONFIGS, type TargetConfig, type TargetPackage, addAllComponents, addComponents, ensureDir, ensureIdField, exportExists, extractFileName, fetchComponent, fetchIndex, flattenFields, generate, generateActions, generateCache, generateColumns, generateCreatePage, generateDatabase, generateEditPage, generateEmailTemplate, generateForm$1 as generateForm, generateFormActions, generateFormAdminPages, generateFormComponent, generateFormDatabase, generateFormHook, generateHook, generatePage, generatePageContent, generateForm as generatePublicForm, generateTable, getAvailableComponents, getImportResolver, getMigrationTimestamp, getPaths, getProjectRoot, initImportResolver, initPaths, listComponents, pluralize, quotePropertyName, resolveRegistryDeps, setPaths, singularize, singularizeLabel, toCamelCase, toKebabCase, toPascalCase, toScreamingSnakeCase, toSnakeCase, transformSource, tryFetchComponent, updateExports, updateFormNavigation, updateNavigation, validateSchema };
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
findProjectRoot,
|
|
4
4
|
loadConfig,
|
|
5
5
|
resolveConfig
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-QLVSHP7X.js";
|
|
7
7
|
import {
|
|
8
8
|
ensureDir,
|
|
9
9
|
getImportResolver,
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
initPaths,
|
|
15
15
|
pluralize,
|
|
16
16
|
quotePropertyName,
|
|
17
|
+
setPaths,
|
|
17
18
|
singularize,
|
|
18
19
|
singularizeLabel,
|
|
19
20
|
toCamelCase,
|
|
@@ -21,7 +22,7 @@ import {
|
|
|
21
22
|
toPascalCase,
|
|
22
23
|
toScreamingSnakeCase,
|
|
23
24
|
toSnakeCase
|
|
24
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-EIH4RRIJ.js";
|
|
25
26
|
import "./chunk-NKRQYAS6.js";
|
|
26
27
|
import "./chunk-WY6BC55D.js";
|
|
27
28
|
|
|
@@ -2970,6 +2971,7 @@ ${junctionDef}`;
|
|
|
2970
2971
|
}
|
|
2971
2972
|
}
|
|
2972
2973
|
updatedContent = updateImports(updatedContent, requiredImports, needsSql.value);
|
|
2974
|
+
ensureDir(path5.dirname(schemaFilePath));
|
|
2973
2975
|
fs5.writeFileSync(schemaFilePath, updatedContent, "utf-8");
|
|
2974
2976
|
}
|
|
2975
2977
|
function removePreviousMigrations(schemaName, migrationDir) {
|
|
@@ -7445,6 +7447,7 @@ async function updateFormNavigation(schema, options) {
|
|
|
7445
7447
|
...users ? [users] : []
|
|
7446
7448
|
];
|
|
7447
7449
|
const code = generateNavigationCode(navigation);
|
|
7450
|
+
ensureDir(path10.dirname(navFilePath));
|
|
7448
7451
|
fs10.writeFileSync(navFilePath, code, "utf-8");
|
|
7449
7452
|
}
|
|
7450
7453
|
|
|
@@ -10153,6 +10156,7 @@ async function updateNavigation(schema, options) {
|
|
|
10153
10156
|
];
|
|
10154
10157
|
}
|
|
10155
10158
|
const code = generateNavigationCode2(navigation);
|
|
10159
|
+
ensureDir(path13.dirname(navFilePath));
|
|
10156
10160
|
fs13.writeFileSync(navFilePath, code, "utf-8");
|
|
10157
10161
|
}
|
|
10158
10162
|
|
|
@@ -11162,7 +11166,7 @@ function validateSchema(schema) {
|
|
|
11162
11166
|
return errors;
|
|
11163
11167
|
}
|
|
11164
11168
|
async function generate(schemaName, options = {}) {
|
|
11165
|
-
const paths =
|
|
11169
|
+
const paths = getPaths();
|
|
11166
11170
|
const projectRoot = findProjectRoot(process.cwd());
|
|
11167
11171
|
const config = await loadConfig(projectRoot);
|
|
11168
11172
|
const resolvedConfig = resolveConfig(config, projectRoot);
|
|
@@ -11360,6 +11364,7 @@ export {
|
|
|
11360
11364
|
pluralize,
|
|
11361
11365
|
quotePropertyName,
|
|
11362
11366
|
resolveRegistryDeps,
|
|
11367
|
+
setPaths,
|
|
11363
11368
|
singularize,
|
|
11364
11369
|
singularizeLabel,
|
|
11365
11370
|
toCamelCase,
|