mirror of
https://github.com/Lifeforge-app/lifeforge.git
synced 2026-03-03 02:27:00 +00:00
refactor(cli): replace logging utility with new logger implementation, update logging calls across modules
This commit is contained in:
@@ -9,7 +9,6 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"tar": "^7.5.2",
|
||||
"axios": "^1.12.2",
|
||||
"chalk": "^5.6.2",
|
||||
"commander": "^14.0.2",
|
||||
"concurrently": "^9.2.1",
|
||||
@@ -19,13 +18,13 @@
|
||||
"handlebars": "^4.7.8",
|
||||
"lodash": "^4.17.21",
|
||||
"openai": "^6.7.0",
|
||||
"ora": "^9.0.0",
|
||||
"pocketbase": "^0.26.3",
|
||||
"prettier": "^3.7.4",
|
||||
"prompts": "^2.4.2",
|
||||
"semver": "^7.7.3",
|
||||
"shared": "workspace:*",
|
||||
"zod": "^4.3.5"
|
||||
"zod": "^4.3.5",
|
||||
"@lifeforge/log": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/crypto-js": "^4.2.2",
|
||||
@@ -34,4 +33,4 @@
|
||||
"@types/semver": "^7.7.1",
|
||||
"@types/tar": "^6.1.13"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import chalk from 'chalk'
|
||||
import { Command } from 'commander'
|
||||
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
const LOGO = `
|
||||
╭─────────────────────────────────────╮
|
||||
│ │
|
||||
@@ -131,8 +133,8 @@ export function configureHelp(program: Command): void {
|
||||
|
||||
// Custom error formatting
|
||||
program.configureOutput({
|
||||
outputError: (str, write) => {
|
||||
write(chalk.red(`\n ❌ ${str.trim()}\n`))
|
||||
outputError: str => {
|
||||
logger.error(str.trim())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { LOG_LEVELS } from '@lifeforge/log'
|
||||
import { Command, program } from 'commander'
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
import Logging, { LOG_LEVELS } from '../utils/logging'
|
||||
import logger, { setLogLevel } from '@/utils/logger'
|
||||
|
||||
import { commands } from './commands'
|
||||
import { configureHelp } from './help'
|
||||
|
||||
@@ -38,12 +40,24 @@ export function setupCLI(): void {
|
||||
`Set log level (${LOG_LEVELS.join(', ')})`,
|
||||
'info'
|
||||
)
|
||||
.hook('preAction', thisCommand => {
|
||||
.hook('preAction', (thisCommand, actionCommand) => {
|
||||
const level = thisCommand.opts().logLevel as (typeof LOG_LEVELS)[number]
|
||||
|
||||
if (LOG_LEVELS.includes(level)) {
|
||||
Logging.setLevel(level)
|
||||
setLogLevel(level)
|
||||
}
|
||||
|
||||
// Build full command path (e.g., "modules list")
|
||||
const commandPath: string[] = []
|
||||
|
||||
let cmd: Command | null = actionCommand
|
||||
|
||||
while (cmd && cmd !== program) {
|
||||
commandPath.unshift(cmd.name())
|
||||
cmd = cmd.parent
|
||||
}
|
||||
|
||||
logger.debug(`Executing command "${commandPath.join(' ')}"`)
|
||||
})
|
||||
|
||||
setupCommands(program)
|
||||
|
||||
@@ -3,7 +3,7 @@ import weekOfYear from 'dayjs/plugin/weekOfYear'
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
dayjs.extend(weekOfYear)
|
||||
|
||||
@@ -30,7 +30,7 @@ export default function createChangelogHandler(year?: string, week?: string) {
|
||||
const currentWeek = Number(week) || dayjs().week()
|
||||
|
||||
if (!fs.existsSync(CHANGELOG_PATH)) {
|
||||
Logging.error(`Changelog directory not found at path: ${CHANGELOG_PATH}`)
|
||||
logger.error(`Changelog directory not found at path: ${CHANGELOG_PATH}`)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ export default function createChangelogHandler(year?: string, week?: string) {
|
||||
const filePath = `${yearPath}/${String(currentWeek).padStart(2, '0')}.mdx`
|
||||
|
||||
if (fs.existsSync(filePath)) {
|
||||
Logging.error(
|
||||
logger.error(
|
||||
`Changelog file for year ${targetYear} week ${currentWeek} already exists at path: ${filePath}`
|
||||
)
|
||||
process.exit(1)
|
||||
@@ -51,5 +51,5 @@ export default function createChangelogHandler(year?: string, week?: string) {
|
||||
|
||||
fs.writeFileSync(filePath, boilerPlate)
|
||||
|
||||
Logging.success(`Created changelog file at path: ${filePath}`)
|
||||
logger.success(`Created changelog file at path: ${filePath}`)
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import chalk from 'chalk'
|
||||
import fs from 'fs'
|
||||
import os from 'os'
|
||||
import path from 'path'
|
||||
@@ -5,7 +6,7 @@ import path from 'path'
|
||||
import { PB_BINARY_PATH, PB_DIR } from '@/constants/db'
|
||||
import executeCommand from '@/utils/commands'
|
||||
import { isDockerMode } from '@/utils/helpers'
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
const PB_VERSION = '0.35.0'
|
||||
|
||||
@@ -16,13 +17,13 @@ const PB_VERSION = '0.35.0'
|
||||
export async function downloadPocketBaseBinary(): Promise<void> {
|
||||
// Skip in Docker mode - binary is provided by the container
|
||||
if (isDockerMode()) {
|
||||
Logging.debug('Docker mode detected, skipping binary download')
|
||||
logger.debug('Docker mode detected, skipping binary download')
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if (fs.existsSync(PB_BINARY_PATH)) {
|
||||
Logging.debug('PocketBase binary already exists, skipping download')
|
||||
logger.debug('PocketBase binary already exists, skipping download')
|
||||
|
||||
return
|
||||
}
|
||||
@@ -42,7 +43,7 @@ export async function downloadPocketBaseBinary(): Promise<void> {
|
||||
osName = 'windows'
|
||||
break
|
||||
default:
|
||||
Logging.actionableError(
|
||||
logger.actionableError(
|
||||
`Unsupported platform: ${platform}`,
|
||||
'PocketBase supports darwin, linux, and windows'
|
||||
)
|
||||
@@ -62,7 +63,7 @@ export async function downloadPocketBaseBinary(): Promise<void> {
|
||||
archName = 'amd64'
|
||||
break
|
||||
default:
|
||||
Logging.actionableError(
|
||||
logger.actionableError(
|
||||
`Unsupported architecture: ${arch}`,
|
||||
'PocketBase supports arm64 and amd64'
|
||||
)
|
||||
@@ -71,8 +72,8 @@ export async function downloadPocketBaseBinary(): Promise<void> {
|
||||
|
||||
const downloadUrl = `https://github.com/pocketbase/pocketbase/releases/download/v${PB_VERSION}/pocketbase_${PB_VERSION}_${osName}_${archName}.zip`
|
||||
|
||||
Logging.info(
|
||||
`Downloading PocketBase ${Logging.highlight(`v${PB_VERSION}`)} for ${osName}/${archName}...`
|
||||
logger.info(
|
||||
`Downloading PocketBase ${chalk.blue(`v${PB_VERSION}`)} for ${osName}/${archName}...`
|
||||
)
|
||||
|
||||
try {
|
||||
@@ -91,7 +92,7 @@ export async function downloadPocketBaseBinary(): Promise<void> {
|
||||
|
||||
fs.writeFileSync(zipPath, Buffer.from(arrayBuffer))
|
||||
|
||||
Logging.debug('Download complete, extracting...')
|
||||
logger.debug('Download complete, extracting...')
|
||||
|
||||
// Extract using unzip command
|
||||
executeCommand(`unzip -o "${zipPath}" -d "${PB_DIR}"`, {
|
||||
@@ -101,7 +102,7 @@ export async function downloadPocketBaseBinary(): Promise<void> {
|
||||
// Clean up zip file and unnecessary files
|
||||
fs.unlinkSync(zipPath)
|
||||
|
||||
const changelogPath = path.join(PB_DIR, 'CHANGELogging.md')
|
||||
const changelogPath = path.join(PB_DIR, 'CHANGElogger.md')
|
||||
|
||||
const licensePath = path.join(PB_DIR, 'LICENSE.md')
|
||||
|
||||
@@ -113,11 +114,9 @@ export async function downloadPocketBaseBinary(): Promise<void> {
|
||||
fs.chmodSync(PB_BINARY_PATH, 0o755)
|
||||
}
|
||||
|
||||
Logging.success(
|
||||
`Downloaded PocketBase ${Logging.highlight(`v${PB_VERSION}`)}`
|
||||
)
|
||||
logger.success(`Downloaded PocketBase ${chalk.blue(`v${PB_VERSION}`)}`)
|
||||
} catch (error) {
|
||||
Logging.actionableError(
|
||||
logger.actionableError(
|
||||
`Failed to download PocketBase: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
||||
'Check your internet connection and try again'
|
||||
)
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import chalk from 'chalk'
|
||||
import fs from 'fs'
|
||||
|
||||
import { PB_BINARY_PATH, PB_DATA_DIR, PB_KWARGS } from '@/constants/db'
|
||||
import executeCommand from '@/utils/commands'
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
/**
|
||||
* Validates that PocketBase data directory doesn't already exist
|
||||
@@ -13,8 +14,8 @@ export function validatePocketBaseNotInitialized(
|
||||
const pbInitialized = fs.existsSync(PB_DATA_DIR)
|
||||
|
||||
if (pbInitialized && exitOnFailure) {
|
||||
Logging.actionableError(
|
||||
`PocketBase is already initialized in ${Logging.highlight(PB_DATA_DIR)}, aborting.`,
|
||||
logger.actionableError(
|
||||
`PocketBase is already initialized in ${chalk.blue(PB_DATA_DIR)}, aborting.`,
|
||||
'If you want to re-initialize, please remove the existing pb_data folder in the database directory.'
|
||||
)
|
||||
process.exit(1)
|
||||
@@ -30,7 +31,7 @@ export function createPocketBaseSuperuser(
|
||||
email: string,
|
||||
password: string
|
||||
): void {
|
||||
Logging.debug(`Creating superuser with email ${Logging.highlight(email)}...`)
|
||||
logger.debug(`Creating superuser with email ${chalk.blue(email)}...`)
|
||||
|
||||
try {
|
||||
const result = executeCommand(
|
||||
@@ -45,9 +46,9 @@ export function createPocketBaseSuperuser(
|
||||
throw new Error(result.replace(/^Error:\s*/, ''))
|
||||
}
|
||||
|
||||
Logging.success('Created superuser')
|
||||
logger.success('Created superuser')
|
||||
} catch (error) {
|
||||
Logging.actionableError(
|
||||
logger.actionableError(
|
||||
`Failed to create superuser: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
||||
'Check your PocketBase configuration and try again'
|
||||
)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { LOG_LEVELS } from '@lifeforge/log'
|
||||
|
||||
import { PB_BINARY_PATH, PB_KWARGS } from '@/constants/db'
|
||||
import executeCommand from '@/utils/commands'
|
||||
import Logging, { LEVEL_ORDER } from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
/**
|
||||
* Runs `pocketbase migrate up` to apply all pending migrations in the migrations directory.
|
||||
@@ -11,11 +13,14 @@ import Logging, { LEVEL_ORDER } from '@/utils/logging'
|
||||
* @throws Error if the migration command fails
|
||||
*/
|
||||
export default function applyStagedMigration(): void {
|
||||
Logging.debug('Applying pending migrations...')
|
||||
logger.debug('Applying pending migrations...')
|
||||
|
||||
executeCommand(`${PB_BINARY_PATH} migrate up ${PB_KWARGS.join(' ')}`, {
|
||||
stdio: Logging.level > LEVEL_ORDER.debug ? 'pipe' : 'inherit'
|
||||
stdio:
|
||||
LOG_LEVELS.indexOf(logger.level) > LOG_LEVELS.indexOf('debug')
|
||||
? 'pipe'
|
||||
: 'inherit'
|
||||
})
|
||||
|
||||
Logging.debug('Migrations applied successfully')
|
||||
logger.debug('Migrations applied successfully')
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import path from 'path'
|
||||
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
import { getSchemaFiles } from '../../utils'
|
||||
|
||||
@@ -45,7 +45,7 @@ export default async function buildIdToNameMap(
|
||||
}
|
||||
}
|
||||
|
||||
Logging.debug(`Built ID-to-name map with ${idToNameMap.size} collections`)
|
||||
logger.debug(`Built ID-to-name map with ${idToNameMap.size} collections`)
|
||||
|
||||
return idToNameMap
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import fs from 'fs'
|
||||
import prettier from 'prettier'
|
||||
|
||||
import { PB_BINARY_PATH, PB_KWARGS } from '@/constants/db'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
import { PRETTIER_OPTIONS } from '../../utils'
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import Logging from '@/utils/logging'
|
||||
import chalk from 'chalk'
|
||||
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
import applyMigrations from './applyMigrations'
|
||||
import createSingleMigration from './createSingleMigration'
|
||||
@@ -41,7 +43,7 @@ export default async function stageMigration(
|
||||
}>,
|
||||
idToNameMap: Map<string, string>
|
||||
) {
|
||||
Logging.debug(`Phase ${index + 1}: Creating ${phase} migrations...`)
|
||||
logger.debug(`Phase ${index + 1}: Creating ${phase} migrations...`)
|
||||
|
||||
const phaseFn = generateContentMap[phase]
|
||||
|
||||
@@ -52,15 +54,13 @@ export default async function stageMigration(
|
||||
phaseFn(schema, idToNameMap)
|
||||
)
|
||||
|
||||
Logging.debug(
|
||||
`Created ${phase} migration for ${Logging.highlight(moduleName)}`
|
||||
)
|
||||
logger.debug(`Created ${phase} migration for ${chalk.blue(moduleName)}`)
|
||||
} catch (error) {
|
||||
const errorMessage =
|
||||
error instanceof Error ? error.message : String(error)
|
||||
|
||||
throw new Error(
|
||||
`Failed to create ${phase} migration for ${Logging.highlight(moduleName)}: ${errorMessage}`
|
||||
`Failed to create ${phase} migration for ${chalk.blue(moduleName)}: ${errorMessage}`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import Logging from '@/utils/logging'
|
||||
import chalk from 'chalk'
|
||||
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
import { listSchemaPaths } from './listSchemaPaths'
|
||||
import { matchCollectionToModule } from './matchCollectionToModule'
|
||||
@@ -25,20 +27,23 @@ export default async function buildModuleCollectionsMap(
|
||||
|
||||
const allModules = listSchemaPaths()
|
||||
|
||||
Logging.debug(
|
||||
`Found ${Logging.highlight(String(allModules.length))} modules with schema files`
|
||||
logger.debug(
|
||||
`Found ${chalk.blue(String(allModules.length))} modules with schema files`
|
||||
)
|
||||
|
||||
let matchedCount = 0
|
||||
let unmatchedCount = 0
|
||||
|
||||
for (const collection of collections) {
|
||||
const matchingModuleDir = await matchCollectionToModule(allModules, collection)
|
||||
const matchingModuleDir = await matchCollectionToModule(
|
||||
allModules,
|
||||
collection
|
||||
)
|
||||
|
||||
if (!matchingModuleDir) {
|
||||
unmatchedCount++
|
||||
Logging.debug(
|
||||
`Collection ${Logging.highlight(collection.name as string)} has no matching module`
|
||||
logger.debug(
|
||||
`Collection ${chalk.blue(collection.name as string)} has no matching module`
|
||||
)
|
||||
continue
|
||||
}
|
||||
@@ -52,8 +57,8 @@ export default async function buildModuleCollectionsMap(
|
||||
moduleCollectionsMap[matchingModuleDir].push(collection)
|
||||
}
|
||||
|
||||
Logging.debug(
|
||||
`Matched ${Logging.highlight(String(matchedCount))} collections to modules, ${unmatchedCount} unmatched`
|
||||
logger.debug(
|
||||
`Matched ${chalk.blue(String(matchedCount))} collections to modules, ${unmatchedCount} unmatched`
|
||||
)
|
||||
|
||||
return moduleCollectionsMap
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
import normalizePackage from '@/utils/normalizePackage'
|
||||
|
||||
/**
|
||||
@@ -33,7 +33,7 @@ export default function filterCollectionsMap(
|
||||
: moduleCollectionsMap
|
||||
|
||||
if (targetModule && Object.keys(filteredModuleCollectionsMap).length === 0) {
|
||||
Logging.error(`Module "${shortName}" not found or has no collections`)
|
||||
logger.error(`Module "${shortName}" not found or has no collections`)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
/**
|
||||
* PocketBase field definition with common properties.
|
||||
@@ -64,7 +64,7 @@ function convertFieldToZodSchema(field: PocketBaseField): string | null {
|
||||
const converter = FIELD_TYPE_MAPPING[field.type]
|
||||
|
||||
if (!converter) {
|
||||
Logging.warn(
|
||||
logger.warn(
|
||||
`Unknown field type '${field.type}' for field '${field.name}'. Skipping.`
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import chalk from 'chalk'
|
||||
|
||||
import { isDockerMode } from '@/utils/helpers'
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
import getPBInstance from '@/utils/pocketbase'
|
||||
|
||||
/**
|
||||
@@ -19,11 +21,11 @@ import getPBInstance from '@/utils/pocketbase'
|
||||
* // Returns: [{ name: 'calendar__events', type: 'base', ... }, ...]
|
||||
*/
|
||||
export default async function getCollectionsFromPB() {
|
||||
Logging.debug('Connecting to PocketBase...')
|
||||
logger.debug('Connecting to PocketBase...')
|
||||
|
||||
const { pb, killPB } = await getPBInstance(!isDockerMode())
|
||||
|
||||
Logging.debug('Fetching all collections...')
|
||||
logger.debug('Fetching all collections...')
|
||||
|
||||
const allCollections = await pb.collections.getFullList()
|
||||
|
||||
@@ -33,8 +35,8 @@ export default async function getCollectionsFromPB() {
|
||||
collection => !collection.system
|
||||
)
|
||||
|
||||
Logging.debug(
|
||||
`Found ${Logging.highlight(String(allCollections.length))} collections, ${Logging.highlight(String(nonSystemCollections.length))} non-system`
|
||||
logger.debug(
|
||||
`Found ${chalk.blue(String(allCollections.length))} collections, ${chalk.blue(String(nonSystemCollections.length))} non-system`
|
||||
)
|
||||
|
||||
return nonSystemCollections
|
||||
|
||||
@@ -2,7 +2,7 @@ import fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
import { ROOT_DIR } from '@/constants/constants'
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
/**
|
||||
* Discovers all module directories that contain schema files.
|
||||
@@ -38,7 +38,7 @@ export function listSchemaPaths(): string[] {
|
||||
.flat()
|
||||
.map(entry => path.dirname(entry).replace(/\/server$/, ''))
|
||||
} catch (error) {
|
||||
Logging.error(`Failed to read modules directory: ${error}`)
|
||||
logger.error(`Failed to read modules directory: ${error}`)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
import buildIdToNameMap from '../functions/migration-generation/buildIdToNameMap'
|
||||
import stageMigration from '../functions/migration-generation/stageMigrations'
|
||||
@@ -26,13 +26,13 @@ export async function generateMigrationsHandler(
|
||||
await stageMigration(phase, Number(index), importedSchemas, idToNameMap)
|
||||
}
|
||||
|
||||
Logging.success('Migrations generated successfully')
|
||||
logger.success('Migrations generated successfully')
|
||||
} catch (error) {
|
||||
Logging.actionableError(
|
||||
logger.actionableError(
|
||||
'Migration script failed',
|
||||
'Check the schema definitions and PocketBase configuration'
|
||||
)
|
||||
Logging.debug(
|
||||
logger.debug(
|
||||
`Error details: ${error instanceof Error ? error.message : String(error)}`
|
||||
)
|
||||
process.exit(1)
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import Logging from '@/utils/logging'
|
||||
import chalk from 'chalk'
|
||||
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
import buildModuleCollectionsMap from '../functions/schema-generation/buildModuleCollectionsMap'
|
||||
import filterCollectionsMap from '../functions/schema-generation/filterCollectionsMap'
|
||||
@@ -13,9 +15,7 @@ export async function generateSchemaHandler(
|
||||
targetModule?: string
|
||||
): Promise<void> {
|
||||
if (targetModule) {
|
||||
Logging.debug(
|
||||
`Generating schema for module: ${Logging.highlight(targetModule)}`
|
||||
)
|
||||
logger.debug(`Generating schema for module: ${chalk.blue(targetModule)}`)
|
||||
}
|
||||
|
||||
const collections = await getCollectionsFromPB()
|
||||
@@ -27,7 +27,7 @@ export async function generateSchemaHandler(
|
||||
const entries = Object.entries(filteredMap)
|
||||
|
||||
if (entries.length === 0) {
|
||||
Logging.warn('No modules found to generate schemas for')
|
||||
logger.warn('No modules found to generate schemas for')
|
||||
|
||||
return
|
||||
}
|
||||
@@ -36,8 +36,8 @@ export async function generateSchemaHandler(
|
||||
entries.map(async ([modulePath, moduleCollections]) => {
|
||||
const collectionCount = moduleCollections.length
|
||||
|
||||
Logging.debug(
|
||||
`Writing ${Logging.highlight(String(collectionCount))} collections for module ${Logging.dim(modulePath)}`
|
||||
logger.debug(
|
||||
`Writing ${chalk.blue(String(collectionCount))} collections for module ${chalk.dim(modulePath)}`
|
||||
)
|
||||
|
||||
await writeFormattedFile(
|
||||
@@ -54,7 +54,7 @@ export async function generateSchemaHandler(
|
||||
})
|
||||
)
|
||||
|
||||
Logging.success(
|
||||
`Generated schemas for ${Logging.highlight(String(entries.length))} modules`
|
||||
logger.success(
|
||||
`Generated schemas for ${chalk.blue(String(entries.length))} modules`
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getEnvVars } from '@/utils/helpers'
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
import { checkRunningPBInstances } from '@/utils/pocketbase'
|
||||
|
||||
import { downloadPocketBaseBinary } from '../functions/database-initialization/download-pocketbase'
|
||||
@@ -25,5 +25,5 @@ export async function initializeDatabaseHandler() {
|
||||
|
||||
generateMigrationsHandler()
|
||||
|
||||
Logging.success('Database initialized successfully')
|
||||
logger.success('Database initialized successfully')
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import path from 'path'
|
||||
import prettier from 'prettier'
|
||||
|
||||
import { ROOT_DIR } from '@/constants/constants'
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
import { PRETTIER_OPTIONS } from './constants'
|
||||
|
||||
@@ -27,7 +27,7 @@ export async function writeFormattedFile(
|
||||
|
||||
fs.writeFileSync(filePath, formattedContent)
|
||||
} catch (error) {
|
||||
Logging.error(`Failed to write file ${filePath}: ${error}`)
|
||||
logger.error(`Failed to write file ${filePath}: ${error}`)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
@@ -64,7 +64,7 @@ export function getSchemaFiles(targetModule?: string): string[] {
|
||||
.map((schemaPath: string) => getModuleName(schemaPath))
|
||||
.join(', ')
|
||||
|
||||
Logging.error(
|
||||
logger.error(
|
||||
`Module "${targetModule}" not found. Available modules: ${availableModules}`
|
||||
)
|
||||
process.exit(1)
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import chalk from 'chalk'
|
||||
import { execSync } from 'child_process'
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
import { PB_BINARY_PATH, PB_KWARGS, PB_MIGRATIONS_DIR } from '@/constants/db'
|
||||
import { isDockerMode } from '@/utils/helpers'
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
/**
|
||||
* Cleans up old migrations.
|
||||
@@ -14,7 +15,7 @@ export async function cleanupOldMigrations(
|
||||
targetModule?: string
|
||||
): Promise<void> {
|
||||
try {
|
||||
Logging.debug('Cleaning up old migrations directory...')
|
||||
logger.debug('Cleaning up old migrations directory...')
|
||||
|
||||
if (!targetModule) {
|
||||
fs.rmSync(PB_MIGRATIONS_DIR, { recursive: true, force: true })
|
||||
@@ -49,8 +50,8 @@ export async function cleanupOldMigrations(
|
||||
file.endsWith(`_${targetModule}.js`)
|
||||
).length
|
||||
|
||||
Logging.debug(
|
||||
`Removed ${Logging.highlight(String(removedCount))} old migrations for module ${Logging.highlight(targetModule)}.`
|
||||
logger.debug(
|
||||
`Removed ${chalk.blue(String(removedCount))} old migrations for module ${chalk.blue(targetModule)}.`
|
||||
)
|
||||
}
|
||||
} catch {
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import chalk from 'chalk'
|
||||
import fs from 'fs'
|
||||
|
||||
import { PB_BINARY_PATH, PB_KWARGS } from '@/constants/db'
|
||||
import executeCommand from '@/utils/commands'
|
||||
import { checkPortInUse, delay, killExistingProcess } from '@/utils/helpers'
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
/**
|
||||
* Service command configurations
|
||||
@@ -24,7 +25,7 @@ export const SERVICE_COMMANDS: Record<string, ServiceConfig> = {
|
||||
}
|
||||
|
||||
if (checkPortInUse(8090)) {
|
||||
Logging.actionableError(
|
||||
logger.actionableError(
|
||||
'No Pocketbase instance found running, but port 8090 is already in use.',
|
||||
'Please free up the port. Are you using the port for another application? (e.g., port forwarding, etc.)'
|
||||
)
|
||||
@@ -32,9 +33,9 @@ export const SERVICE_COMMANDS: Record<string, ServiceConfig> = {
|
||||
}
|
||||
|
||||
if (!fs.existsSync(PB_BINARY_PATH)) {
|
||||
Logging.actionableError(
|
||||
logger.actionableError(
|
||||
`PocketBase binary does not exist: ${PB_BINARY_PATH}`,
|
||||
`Please run "${Logging.highlight('bun forge db init')}" to initialize the database`
|
||||
`Please run "${chalk.blue('bun forge db init')}" to initialize the database`
|
||||
)
|
||||
process.exit(1)
|
||||
}
|
||||
@@ -57,7 +58,7 @@ export const SERVICE_COMMANDS: Record<string, ServiceConfig> = {
|
||||
const PORT = process.env.PORT || '3636'
|
||||
|
||||
if (checkPortInUse(Number(PORT))) {
|
||||
Logging.actionableError(
|
||||
logger.actionableError(
|
||||
`Port ${PORT} is already in use.`,
|
||||
'Please free up the port or set a different PORT environment variable.'
|
||||
)
|
||||
|
||||
@@ -3,7 +3,7 @@ import concurrently from 'concurrently'
|
||||
import { PROJECTS } from '@/commands/project/constants/projects'
|
||||
import executeCommand from '@/utils/commands'
|
||||
import { getEnvVars } from '@/utils/helpers'
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
import { SERVICE_COMMANDS } from '../config/commands'
|
||||
import getConcurrentServices from './getConcurrentServices'
|
||||
@@ -61,11 +61,11 @@ export async function startAllServices(): Promise<void> {
|
||||
prefixColors: ['cyan', 'green', 'magenta']
|
||||
})
|
||||
} catch (error) {
|
||||
Logging.actionableError(
|
||||
logger.actionableError(
|
||||
'Failed to start all services',
|
||||
'Ensure PocketBase is properly configured and all dependencies are installed'
|
||||
)
|
||||
Logging.debug(`Error details: ${error}`)
|
||||
logger.debug(`Error details: ${error}`)
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import Logging from '@/utils/logging'
|
||||
import chalk from 'chalk'
|
||||
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
import SERVICES from '../constants/services'
|
||||
import {
|
||||
@@ -8,31 +10,31 @@ import {
|
||||
|
||||
export function devHandler(service: string, extraArgs: string[] = []): void {
|
||||
if (!service) {
|
||||
Logging.info('Starting all services...')
|
||||
logger.info('Starting all services...')
|
||||
startAllServices()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if (!SERVICES.includes(service as (typeof SERVICES)[number])) {
|
||||
Logging.error(`Unknown service: ${service}`)
|
||||
logger.error(`Unknown service: ${service}`)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
Logging.info(`Starting ${Logging.highlight(service)} service...`)
|
||||
logger.info(`Starting ${chalk.blue(service)} service...`)
|
||||
|
||||
if (extraArgs.length > 0) {
|
||||
Logging.debug(`Extra arguments: ${extraArgs.join(' ')}`)
|
||||
logger.debug(`Extra arguments: ${extraArgs.join(' ')}`)
|
||||
}
|
||||
|
||||
try {
|
||||
startSingleService(service, extraArgs)
|
||||
} catch (error) {
|
||||
Logging.actionableError(
|
||||
`Failed to start ${Logging.highlight(service)} service`,
|
||||
logger.actionableError(
|
||||
`Failed to start ${chalk.blue(service)} service`,
|
||||
'Check if all required dependencies are installed and environment variables are set'
|
||||
)
|
||||
Logging.debug(`Error details: ${error}`)
|
||||
logger.debug(`Error details: ${error}`)
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ROOT_DIR } from '@/constants/constants'
|
||||
import executeCommand from '@/utils/commands'
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
const REQUIRED_CONTAINERS = [
|
||||
'lifeforge-db',
|
||||
@@ -8,8 +8,6 @@ const REQUIRED_CONTAINERS = [
|
||||
'lifeforge-client'
|
||||
]
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Checks if Docker is available and LifeForge containers are initialized.
|
||||
* @returns true if Docker is ready, false otherwise
|
||||
@@ -19,7 +17,7 @@ export default function checkDockerReady(): boolean {
|
||||
// Check if Docker is running
|
||||
executeCommand('docker info', { stdio: 'pipe' })
|
||||
} catch {
|
||||
Logging.actionableError(
|
||||
logger.actionableError(
|
||||
'Docker is not running',
|
||||
'Start Docker Desktop or the Docker daemon first'
|
||||
)
|
||||
@@ -36,13 +34,12 @@ export default function checkDockerReady(): boolean {
|
||||
|
||||
const runningContainers = result.split('\n').map(name => name.trim())
|
||||
|
||||
const missingContainers = REQUIRED_CONTAINERS
|
||||
.filter(
|
||||
const missingContainers = REQUIRED_CONTAINERS.filter(
|
||||
container => !runningContainers.includes(container)
|
||||
)
|
||||
|
||||
if (missingContainers.length > 0) {
|
||||
Logging.actionableError(
|
||||
logger.actionableError(
|
||||
`LifeForge containers not running: ${missingContainers.join(', ')}`,
|
||||
'Run "docker compose up -d" first to start the containers'
|
||||
)
|
||||
@@ -50,7 +47,7 @@ export default function checkDockerReady(): boolean {
|
||||
return false
|
||||
}
|
||||
} catch {
|
||||
Logging.actionableError(
|
||||
logger.actionableError(
|
||||
'Failed to check Docker containers',
|
||||
'Ensure Docker is running and docker-compose.yaml exists'
|
||||
)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ROOT_DIR } from '@/constants/constants'
|
||||
import executeCommand from '@/utils/commands'
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
import checkDockerReady from '../functions/checkDockerReady'
|
||||
|
||||
@@ -28,29 +28,29 @@ export async function migrateHandler(options: MigrateOptions): Promise<void> {
|
||||
const execOptions = { cwd: ROOT_DIR, stdio: 'inherit' as const }
|
||||
|
||||
try {
|
||||
Logging.info('Starting Docker migration sequence...')
|
||||
logger.info('Starting Docker migration sequence...')
|
||||
|
||||
// Step 1: Stop server
|
||||
Logging.info('Stopping server...')
|
||||
logger.info('Stopping server...')
|
||||
executeCommand('docker compose stop server', execOptions)
|
||||
|
||||
// Step 2: Run migrations (unless skipped)
|
||||
if (!options.skipMigrations) {
|
||||
Logging.info('Regenerating and applying migrations...')
|
||||
logger.info('Regenerating and applying migrations...')
|
||||
executeCommand('docker compose run --rm db-init', execOptions)
|
||||
} else {
|
||||
Logging.info('Skipping migrations (--skip-migrations)')
|
||||
logger.info('Skipping migrations (--skip-migrations)')
|
||||
}
|
||||
|
||||
// Step 3: Restart server
|
||||
Logging.info('Restarting server...')
|
||||
logger.info('Restarting server...')
|
||||
executeCommand('docker compose up -d server', execOptions)
|
||||
|
||||
Logging.success('Docker migration complete!')
|
||||
Logging.info('Refresh the browser to load updated modules')
|
||||
logger.success('Docker migration complete!')
|
||||
logger.info('Refresh the browser to load updated modules')
|
||||
} catch (error) {
|
||||
Logging.error('Docker migration failed')
|
||||
Logging.debug(
|
||||
logger.error('Docker migration failed')
|
||||
logger.debug(
|
||||
`Error details: ${error instanceof Error ? error.message : String(error)}`
|
||||
)
|
||||
process.exit(1)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
import getPBInstance from '@/utils/pocketbase'
|
||||
|
||||
async function ensureLocaleNotInUse(shortName: string) {
|
||||
Logging.debug('Checking if locale is in use...')
|
||||
logger.debug('Checking if locale is in use...')
|
||||
|
||||
const { pb, killPB } = await getPBInstance()
|
||||
|
||||
@@ -11,7 +11,7 @@ async function ensureLocaleNotInUse(shortName: string) {
|
||||
killPB?.()
|
||||
|
||||
if (user.language === shortName) {
|
||||
Logging.actionableError(
|
||||
logger.actionableError(
|
||||
`Cannot uninstall locale "${shortName}"`,
|
||||
'This language is currently selected. Change your language first.'
|
||||
)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
import normalizePackage from '@/utils/normalizePackage'
|
||||
|
||||
import { listLocalesWithMeta } from './listLocales'
|
||||
@@ -7,7 +7,7 @@ function getPackagesToCheck(langCode?: string) {
|
||||
const localePackages = listLocalesWithMeta()
|
||||
|
||||
if (!localePackages.length) {
|
||||
Logging.info('No locales installed')
|
||||
logger.info('No locales installed')
|
||||
|
||||
process.exit(0)
|
||||
}
|
||||
@@ -19,7 +19,7 @@ function getPackagesToCheck(langCode?: string) {
|
||||
: localePackages
|
||||
|
||||
if (!packagesToCheck?.length) {
|
||||
Logging.actionableError(
|
||||
logger.actionableError(
|
||||
`Locale "${langCode}" is not installed`,
|
||||
'Run "bun forge locales list" to see installed locales'
|
||||
)
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import Logging from '@/utils/logging'
|
||||
import chalk from 'chalk'
|
||||
|
||||
import logger from '@/utils/logger'
|
||||
import { getRegistryUrl } from '@/utils/registry'
|
||||
|
||||
interface LocaleUpgrade {
|
||||
@@ -47,14 +49,14 @@ async function getUpgrades(
|
||||
}
|
||||
|
||||
if (!upgrades.length) {
|
||||
Logging.info('All locales are up to date')
|
||||
logger.info('All locales are up to date')
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
Logging.info('Available upgrades:')
|
||||
logger.info('Available upgrades:')
|
||||
upgrades.forEach(u =>
|
||||
Logging.print(
|
||||
` ${Logging.highlight(u.name)}: ${u.current} → ${Logging.green(u.latest)}`
|
||||
logger.print(
|
||||
` ${chalk.blue(u.name)}: ${u.current} → ${chalk.green(u.latest)}`
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
import { LOCALES_DIR } from '@/constants/constants'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
export function listLocales(): string[] {
|
||||
return fs.readdirSync(LOCALES_DIR).filter(dir => {
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import Logging from '@/utils/logging'
|
||||
import chalk from 'chalk'
|
||||
|
||||
import logger from '@/utils/logger'
|
||||
import getPBInstance from '@/utils/pocketbase'
|
||||
|
||||
import { listLocales } from './listLocales'
|
||||
@@ -7,7 +9,7 @@ async function setFirstLangInDB(shortName: string) {
|
||||
const installedLocales = listLocales()
|
||||
|
||||
if (installedLocales.length === 1) {
|
||||
Logging.debug('This is the first locale, setting as default...')
|
||||
logger.debug('This is the first locale, setting as default...')
|
||||
|
||||
const { pb, killPB } = await getPBInstance()
|
||||
|
||||
@@ -15,7 +17,7 @@ async function setFirstLangInDB(shortName: string) {
|
||||
|
||||
await pb.collection('users').update(user.id, { language: shortName })
|
||||
|
||||
Logging.info(`Set ${Logging.highlight(shortName)} as default language`)
|
||||
logger.info(`Set ${chalk.blue(shortName)} as default language`)
|
||||
killPB?.()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
interface LocalePackageJson {
|
||||
name?: string
|
||||
@@ -55,11 +55,11 @@ export function validateLocaleStructure(localePath: string) {
|
||||
}
|
||||
|
||||
if (errors.length > 0) {
|
||||
Logging.error('Locale validation failed:')
|
||||
errors.forEach(err => Logging.error(` - ${err}`))
|
||||
logger.error('Locale validation failed:')
|
||||
errors.forEach(err => logger.error(` - ${err}`))
|
||||
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
warnings.forEach(warn => Logging.warn(` - ${warn}`))
|
||||
warnings.forEach(warn => logger.warn(` - ${warn}`))
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import chalk from 'chalk'
|
||||
import fs from 'fs'
|
||||
|
||||
import { installPackage } from '@/utils/commands'
|
||||
import initGitRepository from '@/utils/initGitRepository'
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
import normalizePackage from '@/utils/normalizePackage'
|
||||
|
||||
import setFirstLangInDB from '../functions/setFirstLangInDB'
|
||||
@@ -14,15 +15,15 @@ export async function installLocaleHandler(langCode: string): Promise<void> {
|
||||
)
|
||||
|
||||
if (!/^@lifeforge\/lang-[a-z]{2}(-[A-Z]{2})?$/i.test(fullName)) {
|
||||
Logging.actionableError(
|
||||
`Invalid locale name: ${Logging.highlight(langCode)}`,
|
||||
logger.actionableError(
|
||||
`Invalid locale name: ${chalk.blue(langCode)}`,
|
||||
'Locale names should follow the format "xx" or "xx-XX", where "xx" is a two-letter language code and "XX" is a two-letter country code.'
|
||||
)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
if (fs.existsSync(targetDir)) {
|
||||
Logging.actionableError(
|
||||
logger.actionableError(
|
||||
`Locale already exists at locales/${shortName}`,
|
||||
`Remove it first with: bun forge locales uninstall ${shortName}`
|
||||
)
|
||||
@@ -30,7 +31,7 @@ export async function installLocaleHandler(langCode: string): Promise<void> {
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
Logging.info(`Installing ${Logging.highlight(fullName)}...`)
|
||||
logger.info(`Installing ${chalk.blue(fullName)}...`)
|
||||
|
||||
try {
|
||||
installPackage(fullName, targetDir)
|
||||
@@ -38,10 +39,10 @@ export async function installLocaleHandler(langCode: string): Promise<void> {
|
||||
|
||||
await setFirstLangInDB(shortName)
|
||||
|
||||
Logging.success(`Installed ${Logging.highlight(fullName)}`)
|
||||
logger.success(`Installed ${chalk.blue(fullName)}`)
|
||||
} catch (error) {
|
||||
Logging.actionableError(
|
||||
`Failed to install ${Logging.highlight(fullName)}`,
|
||||
logger.actionableError(
|
||||
`Failed to install ${chalk.blue(fullName)}`,
|
||||
'Make sure the locale exists in the registry'
|
||||
)
|
||||
throw error
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import Logging from '@/utils/logging'
|
||||
import chalk from 'chalk'
|
||||
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
import { listLocalesWithMeta } from '../functions/listLocales'
|
||||
|
||||
@@ -6,19 +8,19 @@ export function listLocalesHandler(): void {
|
||||
const locales = listLocalesWithMeta()
|
||||
|
||||
if (locales.length === 0) {
|
||||
Logging.info('No language packs installed')
|
||||
Logging.info(
|
||||
logger.info('No language packs installed')
|
||||
logger.info(
|
||||
'Use "bun forge locales install <lang>" to install a language pack'
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
Logging.info(`Installed language packs (${locales.length}):`)
|
||||
logger.info(`Installed language packs (${locales.length}):`)
|
||||
|
||||
for (const locale of locales.sort((a, b) => a.name.localeCompare(b.name))) {
|
||||
Logging.print(
|
||||
` ${Logging.highlight(locale.name)} - ${locale.displayName} (v.${locale.version})`
|
||||
logger.print(
|
||||
` ${chalk.blue(locale.name)} - ${locale.displayName} (v.${locale.version})`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import chalk from 'chalk'
|
||||
import fs from 'fs'
|
||||
|
||||
import bumpPackageVersion, {
|
||||
revertPackageVersion
|
||||
} from '@/utils/bumpPackageVersion'
|
||||
import executeCommand from '@/utils/commands'
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
import normalizePackage from '@/utils/normalizePackage'
|
||||
|
||||
import { validateMaintainerAccess } from '../../../utils/github-cli'
|
||||
@@ -18,7 +19,7 @@ export async function publishLocaleHandler(
|
||||
const { fullName, targetDir } = normalizePackage(langCode, 'locale')
|
||||
|
||||
if (!fs.existsSync(targetDir)) {
|
||||
Logging.actionableError(
|
||||
logger.actionableError(
|
||||
`Locale "${langCode}" not found in locales/`,
|
||||
'Run "bun forge locales list" to see available locales'
|
||||
)
|
||||
@@ -26,23 +27,23 @@ export async function publishLocaleHandler(
|
||||
return
|
||||
}
|
||||
|
||||
Logging.info('Validating locale structure...')
|
||||
logger.info('Validating locale structure...')
|
||||
validateLocaleStructure(targetDir)
|
||||
|
||||
const auth = await checkAuth()
|
||||
|
||||
if (options?.official) {
|
||||
Logging.info('Validating maintainer access...')
|
||||
logger.info('Validating maintainer access...')
|
||||
validateMaintainerAccess(auth.username ?? '')
|
||||
}
|
||||
|
||||
const { oldVersion, newVersion } = bumpPackageVersion(targetDir)
|
||||
|
||||
Logging.info(
|
||||
`Bumped version: ${Logging.highlight(oldVersion)} → ${Logging.highlight(newVersion)}`
|
||||
logger.info(
|
||||
`Bumped version: ${chalk.blue(oldVersion)} → ${chalk.blue(newVersion)}`
|
||||
)
|
||||
|
||||
Logging.info(`Publishing ${Logging.highlight(fullName)}...`)
|
||||
logger.info(`Publishing ${chalk.blue(fullName)}...`)
|
||||
|
||||
try {
|
||||
executeCommand(`npm publish --registry ${getRegistryUrl()}`, {
|
||||
@@ -50,12 +51,12 @@ export async function publishLocaleHandler(
|
||||
stdio: 'inherit'
|
||||
})
|
||||
|
||||
Logging.success(`Published ${Logging.highlight(fullName)}`)
|
||||
logger.success(`Published ${chalk.blue(fullName)}`)
|
||||
} catch (error) {
|
||||
revertPackageVersion(targetDir, oldVersion)
|
||||
|
||||
Logging.actionableError(
|
||||
`Failed to publish ${Logging.highlight(fullName)}`,
|
||||
logger.actionableError(
|
||||
`Failed to publish ${chalk.blue(fullName)}`,
|
||||
'Check if you are properly authenticated with the registry'
|
||||
)
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import chalk from 'chalk'
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
import { ROOT_DIR } from '@/constants/constants'
|
||||
import { bunInstall } from '@/utils/commands'
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
import normalizePackage from '@/utils/normalizePackage'
|
||||
import { findPackageName, removeDependency } from '@/utils/packageJson'
|
||||
|
||||
@@ -18,7 +19,7 @@ export async function uninstallLocaleHandler(langCode: string): Promise<void> {
|
||||
const found = findPackageName(fullName)
|
||||
|
||||
if (!found) {
|
||||
Logging.actionableError(
|
||||
logger.actionableError(
|
||||
`Locale "${shortName}" is not installed`,
|
||||
'Run "bun forge locales list" to see installed locales'
|
||||
)
|
||||
@@ -28,7 +29,7 @@ export async function uninstallLocaleHandler(langCode: string): Promise<void> {
|
||||
|
||||
await ensureLocaleNotInUse(shortName)
|
||||
|
||||
Logging.info(`Uninstalling ${Logging.highlight(fullName)}...`)
|
||||
logger.info(`Uninstalling ${chalk.blue(fullName)}...`)
|
||||
|
||||
const symlinkPath = path.join(ROOT_DIR, 'node_modules', fullName)
|
||||
|
||||
@@ -39,5 +40,5 @@ export async function uninstallLocaleHandler(langCode: string): Promise<void> {
|
||||
|
||||
bunInstall()
|
||||
|
||||
Logging.success(`Uninstalled ${Logging.highlight(fullName)}`)
|
||||
logger.success(`Uninstalled ${chalk.blue(fullName)}`)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import chalk from 'chalk'
|
||||
|
||||
import { bunInstall, installPackage } from '@/utils/commands'
|
||||
import { confirmAction } from '@/utils/helpers'
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
import normalizePackage from '@/utils/normalizePackage'
|
||||
|
||||
import { checkAuth } from '../../../utils/registry'
|
||||
@@ -19,7 +21,7 @@ export async function upgradeLocaleHandler(langCode?: string): Promise<void> {
|
||||
let upgradedCount = 0
|
||||
|
||||
for (const upgrade of upgrades) {
|
||||
Logging.info(`Upgrading ${Logging.highlight(upgrade.name)}...`)
|
||||
logger.info(`Upgrading ${chalk.blue(upgrade.name)}...`)
|
||||
|
||||
try {
|
||||
installPackage(
|
||||
@@ -27,18 +29,16 @@ export async function upgradeLocaleHandler(langCode?: string): Promise<void> {
|
||||
normalizePackage(upgrade.name, 'locale').targetDir
|
||||
)
|
||||
|
||||
Logging.success(`Upgraded ${Logging.highlight(upgrade.name)}`)
|
||||
logger.success(`Upgraded ${chalk.blue(upgrade.name)}`)
|
||||
upgradedCount++
|
||||
} catch (error) {
|
||||
Logging.error(
|
||||
`Failed to upgrade ${Logging.highlight(upgrade.name)}: ${error}`
|
||||
)
|
||||
logger.error(`Failed to upgrade ${chalk.blue(upgrade.name)}: ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
if (upgradedCount > 0) {
|
||||
bunInstall()
|
||||
Logging.success(
|
||||
logger.success(
|
||||
`Upgraded ${upgradedCount} locale${upgradedCount > 1 ? 's' : ''}`
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
import { readRootPackageJson } from '@/utils/packageJson'
|
||||
|
||||
import normalizePackage from '../../../utils/normalizePackage'
|
||||
@@ -47,7 +47,7 @@ export default function listModules(
|
||||
}
|
||||
|
||||
if (exitIfNoModule && Object.keys(modules).length === 0) {
|
||||
Logging.info('No @lifeforge/* modules found. Exiting...')
|
||||
logger.info('No @lifeforge/* modules found. Exiting...')
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
import chalk from 'chalk'
|
||||
|
||||
/**
|
||||
* Extract username and module name from a package name format
|
||||
@@ -18,8 +19,8 @@ export function parsePackageName(
|
||||
|
||||
if (!withoutScope.includes('--')) {
|
||||
if (!isLibModule) {
|
||||
Logging.actionableError(
|
||||
`Invalid package name: ${Logging.highlight(packageName)}`,
|
||||
logger.actionableError(
|
||||
`Invalid package name: ${chalk.blue(packageName)}`,
|
||||
'Package name must include "--" separator (e.g., username--module-name)'
|
||||
)
|
||||
process.exit(1)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import prompts from 'prompts'
|
||||
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
export async function promptModuleCategory(): Promise<string> {
|
||||
const response = await prompts(
|
||||
@@ -19,7 +19,7 @@ export async function promptModuleCategory(): Promise<string> {
|
||||
},
|
||||
{
|
||||
onCancel: () => {
|
||||
Logging.error('Module creation cancelled by user.')
|
||||
logger.error('Module creation cancelled by user.')
|
||||
process.exit(0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import prompts from 'prompts'
|
||||
import z from 'zod'
|
||||
|
||||
import { fetchAI } from '@/utils/ai'
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
export async function promptModuleDescription(): Promise<{
|
||||
en: string
|
||||
@@ -26,7 +26,7 @@ export async function promptModuleDescription(): Promise<{
|
||||
},
|
||||
{
|
||||
onCancel: () => {
|
||||
Logging.error('Module creation cancelled by user.')
|
||||
logger.error('Module creation cancelled by user.')
|
||||
process.exit(0)
|
||||
}
|
||||
}
|
||||
@@ -53,7 +53,7 @@ export async function promptModuleDescription(): Promise<{
|
||||
})
|
||||
|
||||
if (!translationResponse) {
|
||||
Logging.warn(
|
||||
logger.warn(
|
||||
"Failed to translate description. Please edit it manually in the module's localization files."
|
||||
)
|
||||
|
||||
@@ -66,7 +66,7 @@ export async function promptModuleDescription(): Promise<{
|
||||
}
|
||||
|
||||
for (const [key, value] of Object.entries(translationResponse)) {
|
||||
Logging.debug(`Translated module description [${key}]: ${value}`)
|
||||
logger.debug(`Translated module description [${key}]: ${value}`)
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -2,7 +2,7 @@ import prompts from 'prompts'
|
||||
import z from 'zod'
|
||||
|
||||
import { fetchAI } from '@/utils/ai'
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
import listModules from '../listModules'
|
||||
|
||||
@@ -34,7 +34,7 @@ export async function promptForModuleName(moduleName?: string): Promise<{
|
||||
},
|
||||
{
|
||||
onCancel: () => {
|
||||
Logging.error('Module creation cancelled by user.')
|
||||
logger.error('Module creation cancelled by user.')
|
||||
process.exit(0)
|
||||
}
|
||||
}
|
||||
@@ -64,7 +64,7 @@ export async function promptForModuleName(moduleName?: string): Promise<{
|
||||
})
|
||||
|
||||
if (!translationResponse) {
|
||||
Logging.warn(
|
||||
logger.warn(
|
||||
"Failed to translate module name. Please edit it manually in the module's localization files."
|
||||
)
|
||||
|
||||
@@ -77,7 +77,7 @@ export async function promptForModuleName(moduleName?: string): Promise<{
|
||||
}
|
||||
|
||||
for (const [key, value] of Object.entries(translationResponse)) {
|
||||
Logging.debug(`Translated module name [${key}]: ${value}`)
|
||||
logger.debug(`Translated module name [${key}]: ${value}`)
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -2,9 +2,10 @@ import fs from 'fs'
|
||||
import prompts from 'prompts'
|
||||
|
||||
import { ROOT_DIR } from '@/constants/constants'
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
import { AVAILABLE_TEMPLATE_MODULE_TYPES } from '../../handlers/createModuleHandler'
|
||||
import chalk from 'chalk'
|
||||
|
||||
export async function promptModuleType(): Promise<
|
||||
keyof typeof AVAILABLE_TEMPLATE_MODULE_TYPES
|
||||
@@ -16,14 +17,14 @@ export async function promptModuleType(): Promise<
|
||||
message: 'Select the type of module to create:',
|
||||
choices: Object.entries(AVAILABLE_TEMPLATE_MODULE_TYPES).map(
|
||||
([value, title]) => ({
|
||||
title: `${title} ${Logging.dim(`(${value})`)}`,
|
||||
title: `${title} ${chalk.dim(`(${value})`)}`,
|
||||
value
|
||||
})
|
||||
)
|
||||
},
|
||||
{
|
||||
onCancel: () => {
|
||||
Logging.error('Module creation cancelled by user.')
|
||||
logger.error('Module creation cancelled by user.')
|
||||
process.exit(0)
|
||||
}
|
||||
}
|
||||
@@ -38,26 +39,26 @@ export function checkModuleTypeAvailability(
|
||||
const templateDir = `${ROOT_DIR}/tools/src/templates/${moduleType}`
|
||||
|
||||
if (!fs.existsSync(templateDir)) {
|
||||
Logging.error(
|
||||
logger.error(
|
||||
`Template for module type "${moduleType}" does not exist at path: ${templateDir}`
|
||||
)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
Logging.debug(
|
||||
logger.debug(
|
||||
`Template for module type "${moduleType}" found at path: ${templateDir}`
|
||||
)
|
||||
|
||||
const files = fs.readdirSync(templateDir)
|
||||
|
||||
if (files.length === 0) {
|
||||
Logging.error(
|
||||
logger.error(
|
||||
`Template directory for module type "${moduleType}" is empty at path: ${templateDir}`
|
||||
)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
Logging.debug(
|
||||
logger.debug(
|
||||
`Template for module type "${moduleType}" is available and ready to use.`
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,26 +1,22 @@
|
||||
import axios from 'axios'
|
||||
import ora from 'ora'
|
||||
import prompts from 'prompts'
|
||||
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
export default async function selectIcon(): Promise<string> {
|
||||
const iconCollections = (
|
||||
await axios.get<
|
||||
Record<
|
||||
string,
|
||||
{
|
||||
name: string
|
||||
total: number
|
||||
categories?: Record<string, string[]>
|
||||
uncategorized?: string[]
|
||||
}
|
||||
>
|
||||
>('https://api.iconify.design/collections')
|
||||
).data
|
||||
const iconCollections = (await fetch(
|
||||
'https://api.iconify.design/collections'
|
||||
).then(res => res.json())) as Record<
|
||||
string,
|
||||
{
|
||||
name: string
|
||||
total: number
|
||||
categories?: Record<string, string[]>
|
||||
uncategorized?: string[]
|
||||
}
|
||||
>
|
||||
|
||||
if (!iconCollections) {
|
||||
Logging.error('Failed to fetch icon collections from Iconify.')
|
||||
logger.error('Failed to fetch icon collections from Iconify.')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
@@ -55,39 +51,32 @@ export default async function selectIcon(): Promise<string> {
|
||||
)
|
||||
|
||||
if (!moduleIconCollection.iconCollection) {
|
||||
Logging.error('Please select a valid icon set.')
|
||||
logger.error('Please select a valid icon set.')
|
||||
continue
|
||||
}
|
||||
|
||||
if (cancelled) {
|
||||
Logging.error('Icon selection cancelled by user.')
|
||||
logger.error('Icon selection cancelled by user.')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const spinner2 = ora('Fetching icons from Iconify...').start()
|
||||
|
||||
let icons: {
|
||||
[key: string]: string[]
|
||||
}[] = []
|
||||
|
||||
try {
|
||||
icons = (
|
||||
await axios(
|
||||
`https://api.iconify.design/collection?prefix=${moduleIconCollection.iconCollection}`
|
||||
)
|
||||
).data
|
||||
icons = await fetch(
|
||||
`https://api.iconify.design/collection?prefix=${moduleIconCollection.iconCollection}`
|
||||
).then(res => res.json())
|
||||
} catch (error) {
|
||||
spinner2.fail('Failed to fetch icons from Iconify.')
|
||||
Logging.error(
|
||||
logger.error(
|
||||
`Error fetching icons for collection ${moduleIconCollection.iconCollection}: ${error}`
|
||||
)
|
||||
continue
|
||||
}
|
||||
|
||||
spinner2.stop()
|
||||
|
||||
if (!icons) {
|
||||
Logging.error('Failed to fetch icons from Iconify.')
|
||||
logger.error('Failed to fetch icons from Iconify.')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
@@ -167,7 +156,7 @@ export default async function selectIcon(): Promise<string> {
|
||||
)
|
||||
|
||||
if (cancelled2) {
|
||||
Logging.error('Icon selection cancelled by user.')
|
||||
logger.error('Icon selection cancelled by user.')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import _ from 'lodash'
|
||||
import path from 'path'
|
||||
|
||||
import { SERVER_ROUTES_DIR } from '@/constants/constants'
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
import normalizePackage from '../../../../utils/normalizePackage'
|
||||
import listModules from '../listModules'
|
||||
@@ -28,7 +28,7 @@ export default function generateRouteRegistry() {
|
||||
})
|
||||
.join('\n')
|
||||
|
||||
let registry = `// AUTO-GENERATED - DO NOT EDIT
|
||||
const registry = `// AUTO-GENERATED - DO NOT EDIT
|
||||
import { forgeRouter } from '@functions/routes'
|
||||
|
||||
const appRoutes = forgeRouter({
|
||||
@@ -40,5 +40,5 @@ export default appRoutes
|
||||
|
||||
fs.writeFileSync(SERVER_ROUTES_DIR, registry)
|
||||
|
||||
Logging.success('Generated route registry')
|
||||
logger.success('Generated route registry')
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import _ from 'lodash'
|
||||
import path from 'path'
|
||||
|
||||
import { SERVER_SCHEMA_DIR } from '@/constants/constants'
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
import normalizePackage from '../../../../utils/normalizePackage'
|
||||
import listModules from '../listModules'
|
||||
@@ -41,5 +41,5 @@ export default SCHEMAS
|
||||
|
||||
fs.writeFileSync(SERVER_SCHEMA_DIR, registry)
|
||||
|
||||
Logging.success('Generated schema registry')
|
||||
logger.success('Generated schema registry')
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import Handlebars from 'handlebars'
|
||||
import _ from 'lodash'
|
||||
|
||||
import { ROOT_DIR } from '@/constants/constants'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
import type { AVAILABLE_TEMPLATE_MODULE_TYPES } from '../../handlers/createModuleHandler'
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import path from 'path'
|
||||
import z from 'zod'
|
||||
|
||||
import { validateMaintainerAccess } from '@/utils/github-cli'
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
import { checkAuth } from '@/utils/registry'
|
||||
|
||||
export default async function validateModuleAuthor(modulePath: string) {
|
||||
@@ -17,7 +17,7 @@ export default async function validateModuleAuthor(modulePath: string) {
|
||||
)
|
||||
|
||||
if (!packageJson.success) {
|
||||
Logging.actionableError(
|
||||
logger.actionableError(
|
||||
'Invalid package.json',
|
||||
'Please fix the package.json file'
|
||||
)
|
||||
@@ -32,7 +32,7 @@ export default async function validateModuleAuthor(modulePath: string) {
|
||||
if (usernamePrefix === 'lifeforge') {
|
||||
validateMaintainerAccess(auth.username || '')
|
||||
} else {
|
||||
Logging.actionableError(
|
||||
logger.actionableError(
|
||||
`Cannot publish as "${auth.username}" - package belongs to "${usernamePrefix}"`,
|
||||
`You can only publish packages starting with @lifeforge/${auth.username}--`
|
||||
)
|
||||
|
||||
@@ -2,7 +2,7 @@ import fs from 'fs'
|
||||
import path from 'path'
|
||||
import z from 'zod'
|
||||
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
const MODULE_STRUCTURE: Array<{
|
||||
type: 'folder' | 'file'
|
||||
@@ -102,9 +102,9 @@ export default async function validateModuleStructure(
|
||||
}
|
||||
|
||||
if (errors.length > 0) {
|
||||
Logging.error('Module validation failed:')
|
||||
logger.error('Module validation failed:')
|
||||
errors.forEach(error => {
|
||||
Logging.error(` ✗ ${error}`)
|
||||
logger.error(` ✗ ${error}`)
|
||||
})
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import chalk from 'chalk'
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
import executeCommand from '@/utils/commands'
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
import normalizePackage from '@/utils/normalizePackage'
|
||||
|
||||
import listModules from '../functions/listModules'
|
||||
@@ -30,9 +31,7 @@ export async function buildModuleHandler(moduleName?: string): Promise<void> {
|
||||
|
||||
// Check if module folder exists
|
||||
if (!fs.existsSync(targetDir)) {
|
||||
Logging.error(
|
||||
`Module ${Logging.highlight(shortName)} not found at ${targetDir}`
|
||||
)
|
||||
logger.error(`Module ${chalk.blue(shortName)} not found at ${targetDir}`)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -45,14 +44,14 @@ export async function buildModuleHandler(moduleName?: string): Promise<void> {
|
||||
const hasServer = fs.existsSync(serverIndexPath)
|
||||
|
||||
if (!hasClient && !hasServer) {
|
||||
Logging.debug(`Skipping ${shortName} (no client or server)`)
|
||||
logger.debug(`Skipping ${shortName} (no client or server)`)
|
||||
skippedCount++
|
||||
continue
|
||||
}
|
||||
|
||||
// Build client
|
||||
if (hasClient) {
|
||||
Logging.info(`Building ${Logging.highlight(shortName)} client...`)
|
||||
logger.info(`Building ${chalk.blue(shortName)} client...`)
|
||||
|
||||
try {
|
||||
executeCommand('bun run build:client', {
|
||||
@@ -61,13 +60,13 @@ export async function buildModuleHandler(moduleName?: string): Promise<void> {
|
||||
})
|
||||
clientBuiltCount++
|
||||
} catch (error) {
|
||||
Logging.error(`Failed to build ${shortName} client: ${error}`)
|
||||
logger.error(`Failed to build ${shortName} client: ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
// Build server
|
||||
if (hasServer) {
|
||||
Logging.info(`Building ${Logging.highlight(shortName)} server...`)
|
||||
logger.info(`Building ${chalk.blue(shortName)} server...`)
|
||||
|
||||
try {
|
||||
executeCommand('bun run build:server', {
|
||||
@@ -76,18 +75,18 @@ export async function buildModuleHandler(moduleName?: string): Promise<void> {
|
||||
})
|
||||
serverBuiltCount++
|
||||
} catch (error) {
|
||||
Logging.error(`Failed to build ${shortName} server: ${error}`)
|
||||
logger.error(`Failed to build ${shortName} server: ${error}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (clientBuiltCount > 0 || serverBuiltCount > 0) {
|
||||
Logging.success(
|
||||
`Built ${Logging.highlight(String(clientBuiltCount))} client bundle${clientBuiltCount !== 1 ? 's' : ''}, ${Logging.highlight(String(serverBuiltCount))} server bundle${serverBuiltCount !== 1 ? 's' : ''}`
|
||||
logger.success(
|
||||
`Built ${chalk.blue(String(clientBuiltCount))} client bundle${clientBuiltCount !== 1 ? 's' : ''}, ${chalk.blue(String(serverBuiltCount))} server bundle${serverBuiltCount !== 1 ? 's' : ''}`
|
||||
)
|
||||
}
|
||||
|
||||
if (skippedCount > 0 && !moduleName) {
|
||||
Logging.info(`Skipped ${skippedCount} modules without builds`)
|
||||
logger.info(`Skipped ${skippedCount} modules without builds`)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import chalk from 'chalk'
|
||||
import fs from 'fs'
|
||||
import os from 'os'
|
||||
import path from 'path'
|
||||
@@ -6,7 +7,7 @@ import { pipeline } from 'stream/promises'
|
||||
import { extract } from 'tar'
|
||||
import { createGunzip } from 'zlib'
|
||||
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
import normalizePackage from '@/utils/normalizePackage'
|
||||
import { checkPackageExists, getPackageTarballUrl } from '@/utils/registry'
|
||||
|
||||
@@ -134,54 +135,50 @@ function printDiff(moduleName: string, diff: FileDiff): boolean {
|
||||
diff.added.length > 0 || diff.modified.length > 0 || diff.deleted.length > 0
|
||||
|
||||
if (!hasChanges) {
|
||||
Logging.print(
|
||||
` ${Logging.green('✓')} ${Logging.highlight(moduleName)} ${Logging.dim('is in sync')}`
|
||||
logger.print(
|
||||
` ${chalk.green('✓')} ${chalk.blue(moduleName)} ${chalk.dim('is in sync')}`
|
||||
)
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
Logging.print(` ${Logging.yellow('!')} ${Logging.highlight(moduleName)}`)
|
||||
logger.print(` ${chalk.yellow('!')} ${chalk.blue(moduleName)}`)
|
||||
|
||||
if (diff.added.length > 0) {
|
||||
Logging.print(Logging.green(` + ${diff.added.length} added locally`))
|
||||
logger.print(chalk.green(` + ${diff.added.length} added locally`))
|
||||
|
||||
for (const file of diff.added.slice(0, 5)) {
|
||||
Logging.print(Logging.dim(` ${file}`))
|
||||
logger.print(chalk.dim(` ${file}`))
|
||||
}
|
||||
|
||||
if (diff.added.length > 5) {
|
||||
Logging.print(
|
||||
Logging.dim(` ... and ${diff.added.length - 5} more`)
|
||||
)
|
||||
logger.print(chalk.dim(` ... and ${diff.added.length - 5} more`))
|
||||
}
|
||||
}
|
||||
|
||||
if (diff.modified.length > 0) {
|
||||
Logging.print(Logging.yellow(` ~ ${diff.modified.length} modified`))
|
||||
logger.print(chalk.yellow(` ~ ${diff.modified.length} modified`))
|
||||
|
||||
for (const file of diff.modified.slice(0, 5)) {
|
||||
Logging.print(Logging.dim(` ${file}`))
|
||||
logger.print(chalk.dim(` ${file}`))
|
||||
}
|
||||
|
||||
if (diff.modified.length > 5) {
|
||||
Logging.print(
|
||||
Logging.dim(` ... and ${diff.modified.length - 5} more`)
|
||||
logger.print(
|
||||
chalk.dim(` ... and ${diff.modified.length - 5} more`)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (diff.deleted.length > 0) {
|
||||
Logging.print(Logging.red(` - ${diff.deleted.length} deleted locally`))
|
||||
logger.print(chalk.red(` - ${diff.deleted.length} deleted locally`))
|
||||
|
||||
for (const file of diff.deleted.slice(0, 5)) {
|
||||
Logging.print(Logging.dim(` ${file}`))
|
||||
logger.print(chalk.dim(` ${file}`))
|
||||
}
|
||||
|
||||
if (diff.deleted.length > 5) {
|
||||
Logging.print(
|
||||
Logging.dim(` ... and ${diff.deleted.length - 5} more`)
|
||||
)
|
||||
logger.print(chalk.dim(` ... and ${diff.deleted.length - 5} more`))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,8 +194,8 @@ async function compareModule(packageName: string): Promise<boolean | null> {
|
||||
const { fullName, shortName, targetDir } = normalizePackage(packageName)
|
||||
|
||||
if (!fs.existsSync(targetDir)) {
|
||||
Logging.actionableError(
|
||||
`Module ${Logging.highlight(shortName)} is not installed`,
|
||||
logger.actionableError(
|
||||
`Module ${chalk.blue(shortName)} is not installed`,
|
||||
'Run "bun forge modules list" to see installed modules'
|
||||
)
|
||||
|
||||
@@ -206,8 +203,8 @@ async function compareModule(packageName: string): Promise<boolean | null> {
|
||||
}
|
||||
|
||||
if (!(await checkPackageExists(fullName))) {
|
||||
Logging.print(
|
||||
` ${Logging.dim('○')} ${Logging.highlight(shortName)} ${Logging.dim('(not published)')}`
|
||||
logger.print(
|
||||
` ${chalk.dim('○')} ${chalk.blue(shortName)} ${chalk.dim('(not published)')}`
|
||||
)
|
||||
|
||||
return null
|
||||
@@ -216,7 +213,7 @@ async function compareModule(packageName: string): Promise<boolean | null> {
|
||||
const tarballUrl = await getPackageTarballUrl(fullName)
|
||||
|
||||
if (!tarballUrl) {
|
||||
Logging.warn(`Could not get tarball URL for ${Logging.highlight(fullName)}`)
|
||||
logger.warn(`Could not get tarball URL for ${chalk.blue(fullName)}`)
|
||||
|
||||
return null
|
||||
}
|
||||
@@ -224,7 +221,7 @@ async function compareModule(packageName: string): Promise<boolean | null> {
|
||||
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'forge-compare-'))
|
||||
|
||||
try {
|
||||
Logging.debug(`Downloading ${Logging.highlight(fullName)} from registry...`)
|
||||
logger.debug(`Downloading ${chalk.blue(fullName)} from registry...`)
|
||||
|
||||
await downloadAndExtractTarball(tarballUrl, tempDir)
|
||||
|
||||
@@ -250,9 +247,9 @@ async function compareModule(packageName: string): Promise<boolean | null> {
|
||||
*/
|
||||
export async function compareModuleHandler(moduleName?: string): Promise<void> {
|
||||
if (moduleName) {
|
||||
Logging.print('')
|
||||
logger.print('')
|
||||
await compareModule(moduleName)
|
||||
Logging.print('')
|
||||
logger.print('')
|
||||
|
||||
return
|
||||
}
|
||||
@@ -260,13 +257,13 @@ export async function compareModuleHandler(moduleName?: string): Promise<void> {
|
||||
const modules = listModules()
|
||||
|
||||
if (Object.keys(modules).length === 0) {
|
||||
Logging.print('No modules installed')
|
||||
logger.print('No modules installed')
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
Logging.print(
|
||||
`\nComparing ${Logging.highlight(String(Object.keys(modules).length))} modules with registry...\n`
|
||||
logger.print(
|
||||
`\nComparing ${chalk.blue(String(Object.keys(modules).length))} modules with registry...\n`
|
||||
)
|
||||
|
||||
let changedCount = 0
|
||||
@@ -279,13 +276,13 @@ export async function compareModuleHandler(moduleName?: string): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
Logging.print('')
|
||||
logger.print('')
|
||||
|
||||
if (changedCount === 0) {
|
||||
Logging.success('All modules are in sync with the registry')
|
||||
logger.success('All modules are in sync with the registry')
|
||||
} else {
|
||||
Logging.warn(
|
||||
`${Logging.highlight(String(changedCount))} module${changedCount > 1 ? 's' : ''} have local changes`
|
||||
logger.warn(
|
||||
`${chalk.blue(String(changedCount))} module${changedCount > 1 ? 's' : ''} have local changes`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
import { registerHandlebarsHelpers } from '../functions/templates'
|
||||
|
||||
@@ -12,7 +12,7 @@ export const AVAILABLE_TEMPLATE_MODULE_TYPES = {
|
||||
} as const
|
||||
|
||||
export async function createModuleHandler(moduleName?: string): Promise<void> {
|
||||
Logging.info('Work in progress...')
|
||||
logger.info('Work in progress...')
|
||||
// checkRunningPBInstances()
|
||||
// const moduleNameWithTranslation = await promptForModuleName(moduleName)
|
||||
// const moduleType = await promptModuleType()
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import chalk from 'chalk'
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
@@ -6,7 +7,7 @@ import { installPackage } from '@/utils/commands'
|
||||
import { smartReloadServer } from '@/utils/docker'
|
||||
import { isDockerMode } from '@/utils/helpers'
|
||||
import initGitRepository from '@/utils/initGitRepository'
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
import normalizePackage from '@/utils/normalizePackage'
|
||||
import { checkPackageExists } from '@/utils/registry'
|
||||
|
||||
@@ -37,15 +38,15 @@ export async function installModuleHandler(
|
||||
const { fullName, shortName, targetDir } = normalizePackage(moduleName)
|
||||
|
||||
if (!/^@lifeforge\/[a-z0-9-_]+--[a-z0-9-_]+$/i.test(fullName)) {
|
||||
Logging.actionableError(
|
||||
`Invalid module name: ${Logging.highlight(moduleName)}`,
|
||||
logger.actionableError(
|
||||
`Invalid module name: ${chalk.blue(moduleName)}`,
|
||||
'Module names can only contain letters, numbers, hyphens, and underscores.'
|
||||
)
|
||||
continue
|
||||
}
|
||||
|
||||
if (fs.existsSync(targetDir)) {
|
||||
Logging.actionableError(
|
||||
logger.actionableError(
|
||||
`Module already exists at apps/${shortName}`,
|
||||
`Remove it first with: bun forge modules uninstall ${shortName}`
|
||||
)
|
||||
@@ -53,28 +54,28 @@ export async function installModuleHandler(
|
||||
}
|
||||
|
||||
if (!(await checkPackageExists(fullName))) {
|
||||
Logging.actionableError(
|
||||
`Module ${Logging.highlight(fullName)} does not exist in registry`,
|
||||
logger.actionableError(
|
||||
`Module ${chalk.blue(fullName)} does not exist in registry`,
|
||||
'Check the module name and try again'
|
||||
)
|
||||
continue
|
||||
}
|
||||
|
||||
Logging.debug(`Installing ${Logging.highlight(fullName)}...`)
|
||||
logger.debug(`Installing ${chalk.blue(fullName)}...`)
|
||||
|
||||
installPackage(fullName, targetDir)
|
||||
initGitRepository(targetDir)
|
||||
|
||||
installed.push(moduleName)
|
||||
|
||||
Logging.success(`Installed ${Logging.highlight(fullName)}`)
|
||||
logger.success(`Installed ${chalk.blue(fullName)}`)
|
||||
}
|
||||
|
||||
if (installed.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
Logging.debug('Regenerating registries...')
|
||||
logger.debug('Regenerating registries...')
|
||||
generateRouteRegistry()
|
||||
generateSchemaRegistry()
|
||||
|
||||
@@ -89,7 +90,7 @@ export async function installModuleHandler(
|
||||
const { targetDir } = normalizePackage(moduleName)
|
||||
|
||||
if (fs.existsSync(path.join(targetDir, 'server', 'schema.ts'))) {
|
||||
Logging.debug(`Generating database migrations for ${moduleName}...`)
|
||||
logger.debug(`Generating database migrations for ${moduleName}...`)
|
||||
generateMigrationsHandler(moduleName)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import Logging from '@/utils/logging'
|
||||
import chalk from 'chalk'
|
||||
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
import listModules from '../functions/listModules'
|
||||
|
||||
@@ -11,22 +13,20 @@ export async function listModulesHandler(): Promise<void> {
|
||||
const totalCount = Object.keys(modules).length
|
||||
|
||||
if (totalCount === 0) {
|
||||
Logging.print('No modules installed')
|
||||
Logging.print(
|
||||
Logging.dim(' Run "bun forge modules install <name>" to install one')
|
||||
logger.print('No modules installed')
|
||||
logger.print(
|
||||
chalk.dim(' Run "bun forge modules install <name>" to install one')
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
Logging.print(
|
||||
`${Logging.highlight(String(totalCount))} installed module${totalCount > 1 ? 's' : ''}:\n`
|
||||
logger.print(
|
||||
`${chalk.blue(String(totalCount))} installed module${totalCount > 1 ? 's' : ''}:\n`
|
||||
)
|
||||
|
||||
Object.entries(modules).forEach(([name, info]) => {
|
||||
Logging.print(
|
||||
` ${Logging.highlight(name)} ${Logging.dim(`v${info.version}`)}`
|
||||
)
|
||||
Logging.print(` ${Logging.dim(info.displayName)}`)
|
||||
logger.print(` ${chalk.blue(name)} ${chalk.dim(`v${info.version}`)}`)
|
||||
logger.print(` ${chalk.dim(info.displayName)}`)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import chalk from 'chalk'
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
import { ROOT_DIR } from '@/constants/constants'
|
||||
import executeCommand from '@/utils/commands'
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
import bumpPackageVersion, {
|
||||
revertPackageVersion
|
||||
@@ -26,26 +27,26 @@ export async function publishModuleHandler(moduleName: string): Promise<void> {
|
||||
const modulePath = path.join(ROOT_DIR, 'apps', moduleName)
|
||||
|
||||
if (!fs.existsSync(modulePath)) {
|
||||
Logging.actionableError(
|
||||
`Module ${Logging.highlight(moduleName)} not found in apps/`,
|
||||
logger.actionableError(
|
||||
`Module ${chalk.blue(moduleName)} not found in apps/`,
|
||||
'Make sure the module exists in the apps directory'
|
||||
)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
Logging.debug('Validating module structure...')
|
||||
logger.debug('Validating module structure...')
|
||||
await validateModuleStructure(modulePath)
|
||||
|
||||
Logging.debug('Validating module author...')
|
||||
logger.debug('Validating module author...')
|
||||
await validateModuleAuthor(modulePath)
|
||||
|
||||
const { oldVersion, newVersion } = bumpPackageVersion(modulePath)
|
||||
|
||||
Logging.print(
|
||||
` Version: ${Logging.dim(oldVersion)} ${Logging.dim('→')} ${Logging.green(newVersion)}`
|
||||
logger.print(
|
||||
` Version: ${chalk.dim(oldVersion)} ${chalk.dim('→')} ${chalk.green(newVersion)}`
|
||||
)
|
||||
|
||||
Logging.debug(`Publishing ${Logging.highlight(moduleName)}...`)
|
||||
logger.debug(`Publishing ${chalk.blue(moduleName)}...`)
|
||||
|
||||
try {
|
||||
executeCommand(`npm publish --registry ${getRegistryUrl()}`, {
|
||||
@@ -53,17 +54,17 @@ export async function publishModuleHandler(moduleName: string): Promise<void> {
|
||||
stdio: 'pipe'
|
||||
})
|
||||
|
||||
Logging.success(
|
||||
`Published ${Logging.highlight(moduleName)} ${Logging.dim(`v${newVersion}`)}`
|
||||
logger.success(
|
||||
`Published ${chalk.blue(moduleName)} ${chalk.dim(`v${newVersion}`)}`
|
||||
)
|
||||
} catch (error) {
|
||||
revertPackageVersion(modulePath, oldVersion)
|
||||
|
||||
Logging.actionableError(
|
||||
`Publish failed for ${Logging.highlight(moduleName)}`,
|
||||
logger.actionableError(
|
||||
`Publish failed for ${chalk.blue(moduleName)}`,
|
||||
'Check npm authentication and try again'
|
||||
)
|
||||
Logging.debug(`Error: ${error}`)
|
||||
logger.debug(`Error: ${error}`)
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import chalk from 'chalk'
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
import { ROOT_DIR } from '@/constants/constants'
|
||||
import { bunInstall } from '@/utils/commands'
|
||||
import { smartReloadServer } from '@/utils/docker'
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
import normalizePackage from '@/utils/normalizePackage'
|
||||
import { findPackageName, removeDependency } from '@/utils/packageJson'
|
||||
|
||||
@@ -33,14 +34,14 @@ export async function uninstallModuleHandler(
|
||||
const { targetDir, fullName } = normalizePackage(moduleName)
|
||||
|
||||
if (!findPackageName(fullName)) {
|
||||
Logging.actionableError(
|
||||
`Module ${Logging.highlight(fullName)} is not installed`,
|
||||
logger.actionableError(
|
||||
`Module ${chalk.blue(fullName)} is not installed`,
|
||||
'Run "bun forge modules list" to see installed modules'
|
||||
)
|
||||
continue
|
||||
}
|
||||
|
||||
Logging.debug(`Uninstalling ${Logging.highlight(fullName)}...`)
|
||||
logger.debug(`Uninstalling ${chalk.blue(fullName)}...`)
|
||||
|
||||
removeDependency(fullName)
|
||||
|
||||
@@ -51,7 +52,7 @@ export async function uninstallModuleHandler(
|
||||
|
||||
uninstalled.push(moduleName)
|
||||
|
||||
Logging.success(`Uninstalled ${Logging.highlight(fullName)}`)
|
||||
logger.success(`Uninstalled ${chalk.blue(fullName)}`)
|
||||
}
|
||||
|
||||
if (uninstalled.length === 0) {
|
||||
@@ -60,7 +61,7 @@ export async function uninstallModuleHandler(
|
||||
|
||||
bunInstall()
|
||||
|
||||
Logging.debug('Regenerating registries...')
|
||||
logger.debug('Regenerating registries...')
|
||||
generateRouteRegistry()
|
||||
generateSchemaRegistry()
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import chalk from 'chalk'
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import semver from 'semver'
|
||||
|
||||
import { generateMigrationsHandler } from '@/commands/db/handlers/generateMigrationsHandler'
|
||||
import { installPackage } from '@/utils/commands'
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
import normalizePackage from '@/utils/normalizePackage'
|
||||
import { getPackageLatestVersion } from '@/utils/registry'
|
||||
|
||||
@@ -29,21 +30,21 @@ async function upgradeModule(
|
||||
const latestVersion = await getPackageLatestVersion(fullName)
|
||||
|
||||
if (!latestVersion) {
|
||||
Logging.warn(`Could not check registry for ${Logging.highlight(fullName)}`)
|
||||
logger.warn(`Could not check registry for ${chalk.blue(fullName)}`)
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
if (semver.eq(currentVersion, latestVersion)) {
|
||||
Logging.print(
|
||||
` ${Logging.dim('•')} ${Logging.highlight(packageName)} ${Logging.dim(`v${currentVersion} is up to date`)}`
|
||||
logger.print(
|
||||
` ${chalk.dim('•')} ${chalk.blue(packageName)} ${chalk.dim(`v${currentVersion} is up to date`)}`
|
||||
)
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
Logging.debug(
|
||||
`Upgrading ${Logging.highlight(packageName)} from ${currentVersion} to ${latestVersion}...`
|
||||
logger.debug(
|
||||
`Upgrading ${chalk.blue(packageName)} from ${currentVersion} to ${latestVersion}...`
|
||||
)
|
||||
|
||||
const backupPath = path.join(path.dirname(targetDir), `${packageName}.backup`)
|
||||
@@ -60,17 +61,17 @@ async function upgradeModule(
|
||||
|
||||
fs.rmSync(backupPath, { recursive: true, force: true })
|
||||
|
||||
Logging.print(
|
||||
` ${Logging.green('↑')} ${Logging.highlight(packageName)} ${Logging.dim(`${currentVersion} →`)} ${Logging.green(latestVersion)}`
|
||||
logger.print(
|
||||
` ${chalk.green('↑')} ${chalk.blue(packageName)} ${chalk.dim(`${currentVersion} →`)} ${chalk.green(latestVersion)}`
|
||||
)
|
||||
|
||||
return true
|
||||
} catch (error) {
|
||||
Logging.error(`Failed to upgrade ${Logging.highlight(fullName)}: ${error}`)
|
||||
logger.error(`Failed to upgrade ${chalk.blue(fullName)}: ${error}`)
|
||||
|
||||
if (fs.existsSync(backupPath)) {
|
||||
fs.renameSync(backupPath, targetDir)
|
||||
Logging.debug('Restored backup after failed upgrade')
|
||||
logger.debug('Restored backup after failed upgrade')
|
||||
}
|
||||
|
||||
return false
|
||||
@@ -96,8 +97,8 @@ export async function upgradeModuleHandler(moduleName?: string): Promise<void> {
|
||||
const mod = modules[fullName]
|
||||
|
||||
if (!mod) {
|
||||
Logging.actionableError(
|
||||
`Module ${Logging.highlight(moduleName)} is not installed`,
|
||||
logger.actionableError(
|
||||
`Module ${chalk.blue(moduleName)} is not installed`,
|
||||
'Run "bun forge modules list" to see installed modules'
|
||||
)
|
||||
process.exit(1)
|
||||
@@ -109,8 +110,8 @@ export async function upgradeModuleHandler(moduleName?: string): Promise<void> {
|
||||
upgraded.push(fullName)
|
||||
}
|
||||
} else {
|
||||
Logging.print(
|
||||
`Checking ${Logging.highlight(String(Object.keys(modules).length))} modules for updates...\n`
|
||||
logger.print(
|
||||
`Checking ${chalk.blue(String(Object.keys(modules).length))} modules for updates...\n`
|
||||
)
|
||||
|
||||
for (const [name, { version }] of Object.entries(modules)) {
|
||||
@@ -123,8 +124,8 @@ export async function upgradeModuleHandler(moduleName?: string): Promise<void> {
|
||||
}
|
||||
|
||||
if (upgraded.length > 0) {
|
||||
Logging.print('')
|
||||
Logging.debug('Regenerating registries...')
|
||||
logger.print('')
|
||||
logger.debug('Regenerating registries...')
|
||||
|
||||
generateRouteRegistry()
|
||||
generateSchemaRegistry()
|
||||
@@ -136,11 +137,11 @@ export async function upgradeModuleHandler(moduleName?: string): Promise<void> {
|
||||
|
||||
generateMigrationsHandler()
|
||||
|
||||
Logging.success(
|
||||
`Upgraded ${Logging.highlight(String(upgraded.length))} module${upgraded.length > 1 ? 's' : ''}`
|
||||
logger.success(
|
||||
`Upgraded ${chalk.blue(String(upgraded.length))} module${upgraded.length > 1 ? 's' : ''}`
|
||||
)
|
||||
} else if (!moduleName) {
|
||||
Logging.print('')
|
||||
Logging.success('All modules are up to date')
|
||||
logger.print('')
|
||||
logger.success('All modules are up to date')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
import { PROJECTS } from '../constants/projects'
|
||||
|
||||
@@ -26,7 +26,7 @@ export function validateProjectArguments(projects: string[] | undefined): void {
|
||||
const validation = validateProjects(projects, validProjects)
|
||||
|
||||
if (!validation.isValid) {
|
||||
Logging.actionableError(
|
||||
logger.actionableError(
|
||||
`Invalid project(s): ${validation.invalidProjects.join(', ')}`,
|
||||
'Available projects: ' + validProjects.join(', ')
|
||||
)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
export const ROOT_DIR = import.meta.dirname.split('/tools')[0]
|
||||
|
||||
const GENERATED_DIR = path.join(
|
||||
|
||||
@@ -3,7 +3,7 @@ import fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
import { getEnvVar, isDockerMode } from '@/utils/helpers'
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
import { ROOT_DIR } from './constants'
|
||||
|
||||
@@ -36,7 +36,7 @@ if (!isDockerMode()) {
|
||||
try {
|
||||
fs.accessSync(PB_DIR)
|
||||
} catch (error) {
|
||||
Logging.error(`PB_DIR is not accessible: ${error}`)
|
||||
logger.error(`PB_DIR is not accessible: ${error}`)
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import path from 'path'
|
||||
|
||||
import { runCLI, setupCLI } from './cli/setup'
|
||||
import { ROOT_DIR } from './constants/constants'
|
||||
import Logging from './utils/logging'
|
||||
import logger from './utils/logger'
|
||||
|
||||
/**
|
||||
* LifeForge Forge - Build and development tool for LifeForge projects
|
||||
@@ -22,7 +22,7 @@ const envPath = path.resolve(ROOT_DIR, 'env/.env.local')
|
||||
if (fs.existsSync(envPath)) {
|
||||
dotenv.config({ path: envPath, quiet: true })
|
||||
} else {
|
||||
Logging.warn(
|
||||
logger.warn(
|
||||
`Environment file not found at ${envPath}. Continuing without loading environment variables from file.`
|
||||
)
|
||||
}
|
||||
@@ -32,5 +32,5 @@ try {
|
||||
setupCLI()
|
||||
runCLI()
|
||||
} catch (error) {
|
||||
Logging.error(`Unexpected error occurred: ${error}`)
|
||||
logger.error(`Unexpected error occurred: ${error}`)
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import chalk from 'chalk'
|
||||
import CryptoJS from 'crypto-js'
|
||||
import OpenAI from 'openai'
|
||||
import type { ResponseInput } from 'openai/resources/responses/responses.mjs'
|
||||
import ora from 'ora'
|
||||
import z from 'zod'
|
||||
|
||||
import { getEnvVars } from './helpers'
|
||||
import Logging from './logging'
|
||||
import logger from './logger'
|
||||
import getPBInstance from './pocketbase'
|
||||
import { zodTextFormat } from './zodResponseFormat'
|
||||
|
||||
@@ -39,7 +39,7 @@ export async function getAPIKey(): Promise<string | null> {
|
||||
CryptoJS.enc.Utf8
|
||||
)
|
||||
} catch {
|
||||
Logging.error('Failed to decrypt OpenAI API key.')
|
||||
logger.error('Failed to decrypt OpenAI API key.')
|
||||
|
||||
return null
|
||||
} finally {
|
||||
@@ -64,7 +64,7 @@ export async function fetchAI<T extends z.ZodTypeAny>({
|
||||
const apiKey = await getAPIKey()
|
||||
|
||||
if (!apiKey) {
|
||||
Logging.error('OpenAI API key not found.')
|
||||
logger.error('OpenAI API key not found.')
|
||||
|
||||
return null
|
||||
}
|
||||
@@ -73,7 +73,7 @@ export async function fetchAI<T extends z.ZodTypeAny>({
|
||||
apiKey
|
||||
})
|
||||
|
||||
const spinner = ora('Fetching AI response...').start()
|
||||
logger.debug(`Using OpenAI model: ${model}`)
|
||||
|
||||
const completion = await client.responses.parse({
|
||||
model,
|
||||
@@ -85,9 +85,13 @@ export async function fetchAI<T extends z.ZodTypeAny>({
|
||||
|
||||
const parsedResponse = completion.output_parsed
|
||||
|
||||
spinner.stop()
|
||||
logger.debug(
|
||||
`Received response with length ${chalk.green(completion.output.length)} from OpenAI API and parsed successfully.`
|
||||
)
|
||||
|
||||
if (!parsedResponse) {
|
||||
logger.error('Failed to parse response from OpenAI API.')
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import fs from 'fs'
|
||||
import semver from 'semver'
|
||||
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
/**
|
||||
* Bumps the patch version in a module's package.json file.
|
||||
*
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { LOG_LEVELS, type LogLevel } from '@lifeforge/log'
|
||||
import { type IOType, spawnSync } from 'child_process'
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
import { ROOT_DIR } from '@/constants/constants'
|
||||
|
||||
import Logging, { LEVEL_ORDER } from './logging'
|
||||
import logger from './logger'
|
||||
import { addDependency } from './packageJson'
|
||||
|
||||
interface CommandExecutionOptions {
|
||||
@@ -33,7 +34,7 @@ export default function executeCommand(
|
||||
try {
|
||||
cmd = typeof command === 'function' ? command() : command
|
||||
} catch (error) {
|
||||
Logging.actionableError(
|
||||
logger.actionableError(
|
||||
`Failed to generate command: ${error}`,
|
||||
'Check the command generation logic for errors'
|
||||
)
|
||||
@@ -41,7 +42,7 @@ export default function executeCommand(
|
||||
}
|
||||
|
||||
try {
|
||||
Logging.debug(`Executing: ${cmd}`)
|
||||
logger.debug(`Executing: ${cmd}`)
|
||||
|
||||
const [toBeExecuted, ...args] = cmd.split(' ')
|
||||
|
||||
@@ -61,7 +62,7 @@ export default function executeCommand(
|
||||
}
|
||||
|
||||
if (!options.stdio || options.stdio === 'inherit') {
|
||||
Logging.debug(`Completed: ${cmd}`)
|
||||
logger.debug(`Completed: ${cmd}`)
|
||||
}
|
||||
|
||||
return result.stdout?.toString().trim() || ''
|
||||
@@ -70,11 +71,11 @@ export default function executeCommand(
|
||||
throw error
|
||||
}
|
||||
|
||||
Logging.actionableError(
|
||||
logger.actionableError(
|
||||
`Command execution failed: ${cmd}`,
|
||||
'Check if the command exists and you have the necessary permissions'
|
||||
)
|
||||
Logging.debug(`Error details: ${error}`)
|
||||
logger.debug(`Error details: ${error}`)
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
@@ -85,7 +86,11 @@ export default function executeCommand(
|
||||
export function bunInstall() {
|
||||
executeCommand('bun install', {
|
||||
cwd: ROOT_DIR,
|
||||
stdio: Logging.level > LEVEL_ORDER['debug'] ? 'pipe' : 'inherit'
|
||||
stdio:
|
||||
LOG_LEVELS.indexOf(logger.instance.level as LogLevel) >
|
||||
LOG_LEVELS.indexOf('debug')
|
||||
? 'pipe'
|
||||
: 'inherit'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -103,25 +108,29 @@ export function installPackage(fullName: string, targetDir: string) {
|
||||
fs.rmSync(targetDir, { recursive: true, force: true })
|
||||
}
|
||||
|
||||
Logging.debug(`Installing ${Logging.highlight(fullName)} from registry...`)
|
||||
logger.debug(`Installing ${fullName} from registry...`)
|
||||
|
||||
executeCommand(`bun add ${fullName}@latest`, {
|
||||
cwd: ROOT_DIR,
|
||||
stdio: Logging.level > LEVEL_ORDER['info'] ? 'pipe' : 'inherit'
|
||||
stdio:
|
||||
LOG_LEVELS.indexOf(logger.instance.level as LogLevel) >
|
||||
LOG_LEVELS.indexOf('info')
|
||||
? 'pipe'
|
||||
: 'inherit'
|
||||
})
|
||||
|
||||
const installedPath = path.join(ROOT_DIR, 'node_modules', fullName)
|
||||
|
||||
if (!fs.existsSync(installedPath)) {
|
||||
Logging.actionableError(
|
||||
`Failed to install ${Logging.highlight(fullName)}`,
|
||||
logger.actionableError(
|
||||
`Failed to install ${fullName}`,
|
||||
'Check if the package exists in the registry'
|
||||
)
|
||||
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
Logging.debug(`Copying ${Logging.highlight(fullName)} to ${targetDir}...`)
|
||||
logger.debug(`Copying ${fullName} to ${targetDir}...`)
|
||||
|
||||
fs.cpSync(installedPath, targetDir, { recursive: true, dereference: true })
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { execSync } from 'child_process'
|
||||
|
||||
import { isDockerMode } from './helpers'
|
||||
import Logging from './logging'
|
||||
import logger from './logger'
|
||||
|
||||
const SERVER_CONTAINER = 'lifeforge-server'
|
||||
|
||||
@@ -40,7 +40,7 @@ export function isContainerRunning(containerName: string): boolean {
|
||||
*/
|
||||
export function restartServerContainer(): void {
|
||||
if (isDockerMode()) {
|
||||
Logging.warn('Cannot restart Docker from inside a container')
|
||||
logger.warn('Cannot restart Docker from inside a container')
|
||||
|
||||
return
|
||||
}
|
||||
@@ -50,17 +50,17 @@ export function restartServerContainer(): void {
|
||||
}
|
||||
|
||||
if (!isContainerRunning(SERVER_CONTAINER)) {
|
||||
Logging.debug('Server container not running, skipping restart')
|
||||
logger.debug('Server container not running, skipping restart')
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
Logging.info('Restarting Docker server container...')
|
||||
logger.info('Restarting Docker server container...')
|
||||
execSync(`docker restart ${SERVER_CONTAINER}`, { stdio: 'inherit' })
|
||||
Logging.success('Server container restarted')
|
||||
logger.success('Server container restarted')
|
||||
} catch (error) {
|
||||
Logging.error(`Failed to restart Docker server: ${error}`)
|
||||
logger.error(`Failed to restart Docker server: ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,6 +76,6 @@ export function smartReloadServer(): void {
|
||||
if (isDockerRunning() && isContainerRunning(SERVER_CONTAINER)) {
|
||||
restartServerContainer()
|
||||
} else {
|
||||
Logging.info('Refresh the browser to load module changes')
|
||||
logger.info('Refresh the browser to load module changes')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
import executeCommand from './commands'
|
||||
|
||||
@@ -22,13 +22,13 @@ export function validateMaintainerAccess(username: string): void {
|
||||
return
|
||||
}
|
||||
|
||||
Logging.warn(
|
||||
logger.warn(
|
||||
'Failed to verify maintainer access. Ensure you are authenticated with "gh auth login".'
|
||||
)
|
||||
|
||||
process.exit(1)
|
||||
} catch (error) {
|
||||
Logging.actionableError(
|
||||
logger.actionableError(
|
||||
`Failed to check maintainer access for ${username}.`,
|
||||
`Error: ${error instanceof Error ? error.message : String(error)}`
|
||||
)
|
||||
@@ -74,7 +74,7 @@ export function getGithubUser(): { name: string; email: string } | null {
|
||||
|
||||
return null
|
||||
} catch (error) {
|
||||
Logging.debug(`Failed to fetch GitHub user info: ${error}`)
|
||||
logger.debug(`Failed to fetch GitHub user info: ${error}`)
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { spawnSync } from 'child_process'
|
||||
import prompts from 'prompts'
|
||||
|
||||
import executeCommand from './commands'
|
||||
import Logging from './logging'
|
||||
import logger from './logger'
|
||||
|
||||
/**
|
||||
* Validates and retrieves multiple required environment variables.
|
||||
@@ -29,7 +29,7 @@ export function getEnvVars<const T extends readonly string[]>(
|
||||
}
|
||||
|
||||
if (missing.length > 0) {
|
||||
Logging.actionableError(
|
||||
logger.actionableError(
|
||||
`Missing required environment variables: ${missing.join(', ')}`,
|
||||
'Use the "forge db init" command to set up the environment variables, or set them manually in your env/.env.local file'
|
||||
)
|
||||
@@ -58,7 +58,7 @@ export function getEnvVar(varName: string, fallback?: string): string {
|
||||
return fallback
|
||||
}
|
||||
|
||||
Logging.actionableError(
|
||||
logger.actionableError(
|
||||
`Missing required environment variable: ${varName}`,
|
||||
'Use the "forge db init" command to set up the environment variables, or set them manually in your env/.env.local file'
|
||||
)
|
||||
@@ -78,9 +78,7 @@ export function killExistingProcess(
|
||||
if (typeof processKeywordOrPID === 'number') {
|
||||
process.kill(processKeywordOrPID)
|
||||
|
||||
Logging.debug(
|
||||
`Killed process with PID: ${Logging.highlight(String(processKeywordOrPID))}`
|
||||
)
|
||||
logger.debug(`Killed process with PID: ${String(processKeywordOrPID)}`)
|
||||
|
||||
return
|
||||
}
|
||||
@@ -93,8 +91,8 @@ export function killExistingProcess(
|
||||
if (serverInstance) {
|
||||
executeCommand(`pkill -f "${processKeywordOrPID}"`)
|
||||
|
||||
Logging.debug(
|
||||
`Killed process matching keyword: ${Logging.highlight(processKeywordOrPID)} (PID: ${Logging.highlight(serverInstance)})`
|
||||
logger.debug(
|
||||
`Killed process matching keyword: ${processKeywordOrPID} (PID: ${serverInstance})`
|
||||
)
|
||||
|
||||
return parseInt(serverInstance, 10)
|
||||
|
||||
@@ -2,7 +2,7 @@ import fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
import executeCommand from '@/utils/commands'
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
/**
|
||||
* Initializes a git repository in the target directory and sets up the remote.
|
||||
@@ -30,7 +30,7 @@ export default function initGitRepository(targetDir: string): void {
|
||||
return
|
||||
}
|
||||
|
||||
Logging.info(`Initializing git repository...`)
|
||||
logger.info(`Initializing git repository...`)
|
||||
|
||||
try {
|
||||
executeCommand('git init', { cwd: targetDir, stdio: 'pipe' })
|
||||
@@ -47,8 +47,8 @@ export default function initGitRepository(targetDir: string): void {
|
||||
{ cwd: targetDir, stdio: 'pipe' }
|
||||
)
|
||||
|
||||
Logging.debug(`Git repository initialized with remote: ${repoUrl}`)
|
||||
logger.debug(`Git repository initialized with remote: ${repoUrl}`)
|
||||
} catch (error) {
|
||||
Logging.debug(`Failed to initialize git repository: ${error}`)
|
||||
logger.debug(`Failed to initialize git repository: ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
22
tools/src/utils/logger.ts
Normal file
22
tools/src/utils/logger.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { type LogLevel } from '@lifeforge/log'
|
||||
import { type CLILogger, createCLILogger } from '@lifeforge/log/cli'
|
||||
|
||||
let loggerInstance: CLILogger | null = null
|
||||
|
||||
function getLogger(): CLILogger {
|
||||
if (!loggerInstance) {
|
||||
loggerInstance = createCLILogger()
|
||||
}
|
||||
|
||||
return loggerInstance
|
||||
}
|
||||
|
||||
export function setLogLevel(level: LogLevel): void {
|
||||
const logger = getLogger()
|
||||
|
||||
logger.setLevel(level)
|
||||
}
|
||||
|
||||
const logger = getLogger()
|
||||
|
||||
export default logger
|
||||
@@ -1,153 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||
// @ts-ignore- Lazy to fix the TS config stuff
|
||||
import { LoggingService } from '@server/core/functions/logging/loggingService'
|
||||
import chalk from 'chalk'
|
||||
|
||||
export const LOG_LEVELS = ['debug', 'info', 'warn', 'error', 'fatal'] as const
|
||||
|
||||
export const LEVEL_ORDER = {
|
||||
debug: 1,
|
||||
info: 2,
|
||||
warn: 3,
|
||||
error: 4,
|
||||
fatal: 5
|
||||
}
|
||||
|
||||
type LogLevel = keyof typeof LEVEL_ORDER
|
||||
|
||||
/**
|
||||
* CLI Logging service that wraps the server's LoggingService
|
||||
* Provides consistent logging across the entire CLI with file persistence
|
||||
*/
|
||||
export default class Logging {
|
||||
private static readonly SERVICE_NAME = 'CLI'
|
||||
public static level: number = LEVEL_ORDER['info']
|
||||
|
||||
static setLevel(level: LogLevel): void {
|
||||
Logging.level = LEVEL_ORDER[level]
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
// Formatting Utilities
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
|
||||
/** Format text as bold */
|
||||
static bold(text: string): string {
|
||||
return chalk.bold(text)
|
||||
}
|
||||
|
||||
/** Format text as dim/muted */
|
||||
static dim(text: string): string {
|
||||
return chalk.dim(text)
|
||||
}
|
||||
|
||||
/** Format text as highlighted (bold blue) - for important values */
|
||||
static highlight(text: string): string {
|
||||
return chalk.bold.blue(text)
|
||||
}
|
||||
|
||||
/** Format text as green - for success/positive items */
|
||||
static green(text: string): string {
|
||||
return chalk.green(text)
|
||||
}
|
||||
|
||||
/** Format text as yellow - for warnings */
|
||||
static yellow(text: string): string {
|
||||
return chalk.yellow(text)
|
||||
}
|
||||
|
||||
/** Format text as red - for errors */
|
||||
static red(text: string): string {
|
||||
return chalk.red(text)
|
||||
}
|
||||
|
||||
/** Format text as cyan - for info/neutral items */
|
||||
static cyan(text: string): string {
|
||||
return chalk.cyan(text)
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
// Core Logging Methods
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Log an informational message
|
||||
*/
|
||||
static info(message: string): void {
|
||||
if (Logging.level > LEVEL_ORDER['info']) {
|
||||
return
|
||||
}
|
||||
|
||||
LoggingService.info(message, this.SERVICE_NAME)
|
||||
}
|
||||
|
||||
/**
|
||||
* Log an error message with consistent formatting
|
||||
*/
|
||||
static error(message: string, details?: string): void {
|
||||
if (Logging.level > LEVEL_ORDER['error']) {
|
||||
return
|
||||
}
|
||||
|
||||
const formattedMessage = details ? `${message}: ${details}` : message
|
||||
|
||||
LoggingService.error(formattedMessage, this.SERVICE_NAME)
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a warning message
|
||||
*/
|
||||
static warn(message: string): void {
|
||||
if (Logging.level > LEVEL_ORDER['warn']) {
|
||||
return
|
||||
}
|
||||
|
||||
LoggingService.warn(message, this.SERVICE_NAME)
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a debug message
|
||||
*/
|
||||
static debug(message: string): void {
|
||||
if (Logging.level > LEVEL_ORDER['debug']) {
|
||||
return
|
||||
}
|
||||
|
||||
LoggingService.debug(message, this.SERVICE_NAME)
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a success message with green checkmark
|
||||
*/
|
||||
static success(message: string): void {
|
||||
if (Logging.level > LEVEL_ORDER['info']) {
|
||||
return
|
||||
}
|
||||
|
||||
LoggingService.info(`${chalk.green('✔')} ${message}`, this.SERVICE_NAME)
|
||||
}
|
||||
|
||||
/**
|
||||
* Print raw output without log prefix (for lists, tables, etc.)
|
||||
* Respects log level - only prints if info level is enabled
|
||||
*/
|
||||
static print(message: string): void {
|
||||
if (Logging.level > LEVEL_ORDER['info']) {
|
||||
return
|
||||
}
|
||||
|
||||
console.log(message)
|
||||
}
|
||||
|
||||
/**
|
||||
* Log an actionable error with next steps
|
||||
*/
|
||||
static actionableError(message: string, suggestion: string): void {
|
||||
if (Logging.level > LEVEL_ORDER['error']) {
|
||||
return
|
||||
}
|
||||
|
||||
this.error(chalk.red(message))
|
||||
this.info(chalk.yellow(`Suggestion: ${suggestion}`))
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
import { ROOT_DIR } from '@/constants/constants'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
type PackageType = 'module' | 'locale'
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import path from 'path'
|
||||
|
||||
import { ROOT_DIR } from '@/constants/constants'
|
||||
|
||||
import Logging from './logging'
|
||||
import logger from './logger'
|
||||
|
||||
interface PackageJson {
|
||||
name?: string
|
||||
@@ -29,14 +29,14 @@ export function readRootPackageJson(): PackageJson {
|
||||
* @param packageJson The JSON object to write to the root package.json file.
|
||||
*/
|
||||
export function writeRootPackageJson(packageJson: PackageJson): void {
|
||||
Logging.debug(`Writing root package.json`)
|
||||
logger.debug(`Writing root package.json`)
|
||||
|
||||
fs.writeFileSync(
|
||||
ROOT_PACKAGE_JSON_DIR,
|
||||
JSON.stringify(packageJson, null, 2) + '\n'
|
||||
)
|
||||
|
||||
Logging.debug(`Wrote root package.json`)
|
||||
logger.debug(`Wrote root package.json`)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,7 +49,7 @@ export function addDependency(
|
||||
packageName: string,
|
||||
version = 'workspace:*'
|
||||
): void {
|
||||
Logging.debug(`Adding workspace dependency: ${packageName}`)
|
||||
logger.debug(`Adding workspace dependency: ${packageName}`)
|
||||
|
||||
const packageJson = readRootPackageJson()
|
||||
|
||||
@@ -61,7 +61,7 @@ export function addDependency(
|
||||
|
||||
writeRootPackageJson(packageJson)
|
||||
|
||||
Logging.debug(`Added workspace dependency: ${packageName}`)
|
||||
logger.debug(`Added workspace dependency: ${packageName}`)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,7 +70,7 @@ export function addDependency(
|
||||
* @param packageName The name of the package to remove as a dependency.
|
||||
*/
|
||||
export function removeDependency(packageName: string): void {
|
||||
Logging.debug(`Removing workspace dependency: ${packageName}`)
|
||||
logger.debug(`Removing workspace dependency: ${packageName}`)
|
||||
|
||||
const packageJson = readRootPackageJson()
|
||||
|
||||
@@ -79,7 +79,7 @@ export function removeDependency(packageName: string): void {
|
||||
writeRootPackageJson(packageJson)
|
||||
}
|
||||
|
||||
Logging.debug(`Removed workspace dependency: ${packageName}`)
|
||||
logger.debug(`Removed workspace dependency: ${packageName}`)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,7 +89,7 @@ export function removeDependency(packageName: string): void {
|
||||
* @returns The package name if found, or null if not found
|
||||
*/
|
||||
export function findPackageName(name: string): string | null {
|
||||
Logging.debug(`Finding package name: ${name}`)
|
||||
logger.debug(`Finding package name: ${name}`)
|
||||
|
||||
const packageJson = readRootPackageJson()
|
||||
|
||||
@@ -97,13 +97,13 @@ export function findPackageName(name: string): string | null {
|
||||
|
||||
for (const dep of Object.keys(dependencies)) {
|
||||
if (dep === name) {
|
||||
Logging.debug(`Found package name: ${name}`)
|
||||
logger.debug(`Found package name: ${name}`)
|
||||
|
||||
return dep
|
||||
}
|
||||
}
|
||||
|
||||
Logging.debug(`Package name not found: ${name}`)
|
||||
logger.debug(`Package name not found: ${name}`)
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import PocketBase from 'pocketbase'
|
||||
|
||||
import { PB_BINARY_PATH, PB_KWARGS } from '@/constants/db'
|
||||
import { getEnvVars } from '@/utils/helpers'
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
import executeCommand from './commands'
|
||||
import { killExistingProcess } from './helpers'
|
||||
@@ -61,7 +61,7 @@ export function checkRunningPBInstances(exitOnError = true): boolean {
|
||||
|
||||
if (validPids.length > 0) {
|
||||
if (exitOnError) {
|
||||
Logging.actionableError(
|
||||
logger.actionableError(
|
||||
`PocketBase is already running (PID: ${validPids.join(', ')})`,
|
||||
'Stop the existing instance with "pkill -f pocketbase" before proceeding'
|
||||
)
|
||||
@@ -84,7 +84,7 @@ export function checkRunningPBInstances(exitOnError = true): boolean {
|
||||
* @throws Rejects if the server fails to start or encounters an error
|
||||
*/
|
||||
export async function startPBServer(): Promise<number> {
|
||||
Logging.debug('Starting PocketBase server...')
|
||||
logger.debug('Starting PocketBase server...')
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const pbProcess = spawn(PB_BINARY_PATH, ['serve', ...PB_KWARGS], {
|
||||
@@ -101,12 +101,12 @@ export async function startPBServer(): Promise<number> {
|
||||
}
|
||||
|
||||
if (output.includes('Server started')) {
|
||||
Logging.debug(`PocketBase server started (PID: ${pbProcess.pid})`)
|
||||
logger.debug(`PocketBase server started (PID: ${pbProcess.pid})`)
|
||||
resolve(pbProcess.pid!)
|
||||
}
|
||||
|
||||
if (output.includes('bind: address already in use')) {
|
||||
Logging.actionableError(
|
||||
logger.actionableError(
|
||||
'Port 8090 is already in use',
|
||||
'Run "pkill -f pocketbase" to stop existing instances, or check for other apps using port 8090'
|
||||
)
|
||||
@@ -117,18 +117,18 @@ export async function startPBServer(): Promise<number> {
|
||||
pbProcess.stderr?.on('data', data => {
|
||||
const error = data.toString().trim()
|
||||
|
||||
Logging.debug(`PocketBase stderr: ${error}`)
|
||||
logger.debug(`PocketBase stderr: ${error}`)
|
||||
reject(new Error(error))
|
||||
})
|
||||
|
||||
pbProcess.on('error', error => {
|
||||
Logging.debug(`PocketBase spawn error: ${error.message}`)
|
||||
logger.debug(`PocketBase spawn error: ${error.message}`)
|
||||
reject(error)
|
||||
})
|
||||
|
||||
pbProcess.on('exit', code => {
|
||||
if (code !== 0) {
|
||||
Logging.debug(`PocketBase exited with code ${code}`)
|
||||
logger.debug(`PocketBase exited with code ${code}`)
|
||||
reject(new Error(`PocketBase process exited with code ${code}`))
|
||||
}
|
||||
})
|
||||
@@ -145,7 +145,7 @@ export async function startPocketbase(): Promise<(() => void) | null> {
|
||||
const pbRunning = checkRunningPBInstances(false)
|
||||
|
||||
if (pbRunning) {
|
||||
Logging.debug('PocketBase is already running')
|
||||
logger.debug('PocketBase is already running')
|
||||
|
||||
return null
|
||||
}
|
||||
@@ -156,7 +156,7 @@ export async function startPocketbase(): Promise<(() => void) | null> {
|
||||
killExistingProcess(pbPid)
|
||||
}
|
||||
} catch (error) {
|
||||
Logging.actionableError(
|
||||
logger.actionableError(
|
||||
`Failed to start PocketBase server: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
||||
'Run "bun forge db init" to initialize the database or check if the PocketBase binary exists'
|
||||
)
|
||||
@@ -199,7 +199,7 @@ export default async function getPBInstance(createNewInstance = true): Promise<{
|
||||
killPB
|
||||
}
|
||||
} catch (error) {
|
||||
Logging.actionableError(
|
||||
logger.actionableError(
|
||||
`Authentication failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
||||
'Check PB_EMAIL and PB_PASSWORD in env/.env.local are correct'
|
||||
)
|
||||
|
||||
@@ -2,7 +2,7 @@ import fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
import { ROOT_DIR } from '@/constants/constants'
|
||||
import Logging from '@/utils/logging'
|
||||
import logger from '@/utils/logger'
|
||||
|
||||
import executeCommand from './commands'
|
||||
|
||||
@@ -79,7 +79,7 @@ export async function checkAuth(): Promise<{
|
||||
|
||||
throw new Error('Not authenticated')
|
||||
} catch {
|
||||
Logging.warn('Not authenticated. Please login first.')
|
||||
logger.warn('Not authenticated. Please login first.')
|
||||
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
@@ -6,9 +6,6 @@
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"./src/*"
|
||||
],
|
||||
"@server/*": [
|
||||
"../server/src/*"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user