Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion examples/csharp/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ if (require.main === module) {
console.log("📦 Generating FHIR R4 Core Types...");

const builder = new APIBuilder()
.verbose()
.throwException()
.fromPackage("hl7.fhir.r4.core", "4.0.1")
.csharp("SuperNameSpace", "src/api/writer-generator/csharp/staticFiles")
Expand Down
1 change: 0 additions & 1 deletion examples/typescript-ccda/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ if (require.main === module) {
console.log("📦 Generating FHIR R4 Core Types...");

const builder = new APIBuilder()
.verbose()
.throwException()
.fromPackage("hl7.cda.uv.core", "2.0.1-sd")
.typescript({ withDebugComment: false })
Expand Down
1 change: 0 additions & 1 deletion examples/typescript-r4/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ if (require.main === module) {
console.log("📦 Generating FHIR R4 Core Types...");

const builder = new APIBuilder()
.verbose()
.throwException()
.fromPackage("hl7.fhir.r4.core", "4.0.1")
.typescript({
Expand Down
1 change: 0 additions & 1 deletion examples/typescript-sql-on-fhir/generate.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { APIBuilder } from "../../src/api/builder";

const builder = new APIBuilder()
.verbose()
.throwException()
.typescript({ withDebugComment: false, generateProfile: false })
.fromPackageRef("https://build.fhir.org/ig/FHIR/sql-on-fhir-v2//package.tgz")
Expand Down
16 changes: 7 additions & 9 deletions src/api/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { mkTypeSchemaIndex, type TreeShake, type TypeSchemaIndex, treeShake } fr
import { generateTypeSchemas } from "@typeschema/index";
import { extractNameFromCanonical, packageMetaToFhir, packageMetaToNpm, type TypeSchema } from "@typeschema/types";
import type { TypeSchemaConfig } from "../config";
import { CodegenLogger, createLogger } from "../utils/codegen-logger";
import { CodegenLogger, createLogger, type LogLevel } from "../utils/codegen-logger";
import { TypeScript, type TypeScriptOptions } from "./writer-generator/typescript";
import type { FileBuffer, FileSystemWriter, WriterOptions } from "./writer-generator/writer";

Expand All @@ -24,7 +24,6 @@ import type { FileBuffer, FileSystemWriter, WriterOptions } from "./writer-gener
*/
export interface APIBuilderOptions {
outputDir?: string;
verbose?: boolean;
overwrite?: boolean; // FIXME: remove
cache?: boolean; // FIXME: remove
cleanOutput?: boolean;
Expand All @@ -35,6 +34,8 @@ export interface APIBuilderOptions {
throwException?: boolean;
exportTypeTree?: string;
treeShake?: TreeShake;
/** Log level for the logger. Default: INFO */
logLevel?: LogLevel;
Comment thread
octoshikari marked this conversation as resolved.
}

/**
Expand Down Expand Up @@ -70,7 +71,7 @@ export type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;

type APIBuilderConfig = PartialBy<
Required<APIBuilderOptions>,
"logger" | "typeSchemaConfig" | "typeSchemaOutputDir" | "exportTypeTree" | "treeShake"
"logger" | "typeSchemaConfig" | "typeSchemaOutputDir" | "exportTypeTree" | "treeShake" | "logLevel"
> & {
cleanOutput: boolean;
};
Expand Down Expand Up @@ -188,7 +189,6 @@ export class APIBuilder {
constructor(options: APIBuilderOptions = {}) {
this.options = {
outputDir: options.outputDir || "./generated",
verbose: options.verbose ?? false,
overwrite: options.overwrite ?? true,
cache: options.cache ?? true,
cleanOutput: options.cleanOutput ?? true,
Expand All @@ -206,8 +206,8 @@ export class APIBuilder {
this.logger =
options.logger ||
createLogger({
verbose: this.options.verbose,
prefix: "API",
level: options.logLevel,
});
}

Expand Down Expand Up @@ -259,7 +259,6 @@ export class APIBuilder {
logger: new CodegenLogger({
prefix: "C#",
timestamp: true,
verbose: true,
suppressLoggingLevel: [],
}),
});
Expand Down Expand Up @@ -291,9 +290,8 @@ export class APIBuilder {
return this;
}

verbose(enabled = true): APIBuilder {
this.options.verbose = enabled;
this.logger?.configure({ verbose: enabled });
setLogLevel(level: LogLevel): APIBuilder {
this.logger?.setLevel(level);
return this;
}

Expand Down
1 change: 1 addition & 0 deletions src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* @packageDocumentation
*/

export { LogLevel } from "../utils/codegen-logger";
export type { APIBuilderOptions } from "./builder";
export { APIBuilder } from "./builder";
export type { CSharpGeneratorOptions } from "./writer-generator/csharp/csharp";
Expand Down
2 changes: 0 additions & 2 deletions src/cli/commands/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ export const generateCommand: CommandModule<Record<string, unknown>, GenerateArg

// Create logger for CLI command
const logger = createLogger({
verbose,
prefix: "Generate",
});

Expand All @@ -90,7 +89,6 @@ export const generateCommand: CommandModule<Record<string, unknown>, GenerateArg
// Create API builder with config options
const builder = new APIBuilder({
outputDir: config.outputDir || "./generated",
verbose,
overwrite: config.overwrite ?? true,
cache: config.cache ?? true,
typeSchemaConfig: config.typeSchema,
Expand Down
39 changes: 37 additions & 2 deletions src/cli/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* Modern CLI with subcommands for typeschema and code generation
*/

import { configure, error, header } from "@root/utils/codegen-logger";
import { configure, error, header, LogLevel } from "@root/utils/codegen-logger";
Comment thread
octoshikari marked this conversation as resolved.
import yargs from "yargs";
import { hideBin } from "yargs/helpers";
import { generateCommand } from "./generate";
Expand All @@ -19,16 +19,44 @@ export interface CLIArgv {
config?: string;
verbose?: boolean;
debug?: boolean;
logLevel?: "debug" | "info" | "warn" | "error" | "silent";
}

/**
* Map string log level to LogLevel enum
*/
function parseLogLevel(level: string | undefined): LogLevel | undefined {
if (!level) return undefined;
const levelMap: Record<string, LogLevel> = {
debug: LogLevel.DEBUG,
info: LogLevel.INFO,
warn: LogLevel.WARN,
error: LogLevel.ERROR,
silent: LogLevel.SILENT,
};
return levelMap[level.toLowerCase()];
}

/**
* Middleware to setup logging
*/
async function setupLoggingMiddleware(argv: any) {
// Determine log level: explicit --log-level takes precedence over --verbose/--debug
let level = parseLogLevel(argv.logLevel);

// If no explicit log level, use --verbose or --debug as shortcuts
if (level === undefined) {
if (argv.debug || argv.verbose) {
level = LogLevel.DEBUG;
} else {
level = LogLevel.INFO;
}
}

// Configure the CliLogger with user preferences
configure({
verbose: argv.verbose || argv.debug,
timestamp: argv.debug,
level,
});
}

Expand Down Expand Up @@ -56,6 +84,13 @@ export function createCLI() {
default: false,
global: true,
})
.option("log-level", {
alias: "l",
type: "string",
choices: ["debug", "info", "warn", "error", "silent"] as const,
description: "Set the log level (default: info)",
global: true,
})
.option("config", {
alias: "c",
type: "string",
Expand Down
2 changes: 0 additions & 2 deletions src/cli/commands/typeschema/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ export const generateTypeschemaCommand: CommandModule<Record<string, unknown>, G
},
handler: async (argv) => {
const logger = createLogger({
verbose: argv.verbose,
prefix: "TypeSchema",
});

Expand Down Expand Up @@ -103,7 +102,6 @@ export const generateTypeschemaCommand: CommandModule<Record<string, unknown>, G

// Create TypeSchema generator
const generator = new TypeSchemaGenerator({
verbose: argv.verbose,
treeshake: treeshakeOptions,
});

Expand Down
4 changes: 2 additions & 2 deletions src/typeschema/generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,16 @@ import {
export class TypeSchemaGenerator {
private manager: ReturnType<typeof CanonicalManager>;

// biome-ignore lint/correctness/noUnusedPrivateClassMembers: currently its okay
private options: TypeschemaGeneratorOptions;
private logger?: CodegenLogger;

constructor(options: TypeschemaGeneratorOptions = {}) {
this.options = { verbose: false, ...options };
this.options = { ...options };
this.manager = options.manager || CanonicalManager({ packages: [], workingDir: "tmp/fhir" });
this.logger =
options.logger ||
createLogger({
verbose: this.options.verbose,
prefix: "TypeSchema",
});
}
Expand Down
1 change: 0 additions & 1 deletion src/typeschema/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,6 @@ export const enrichValueSet = (vs: ValueSet, packageMeta: PackageMeta): RichValu
///////////////////////////////////////////////////////////

export interface TypeschemaGeneratorOptions {
verbose?: boolean;
logger?: import("../utils/codegen-logger").CodegenLogger;
treeshake?: string[];
manager?: ReturnType<typeof CanonicalManager> | null;
Expand Down
32 changes: 27 additions & 5 deletions src/utils/codegen-logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ export enum LogLevel {
export interface LogOptions {
prefix?: string;
timestamp?: boolean;
verbose?: boolean;
suppressLoggingLevel?: LogLevel[] | "all";
/** Minimum log level to display. Messages below this level are suppressed. Default: INFO */
level?: LogLevel;
}

/**
Expand All @@ -31,11 +32,19 @@ export class CodegenLogger {
constructor(options: LogOptions = {}) {
this.options = {
timestamp: false,
verbose: false,
level: LogLevel.INFO,
...options,
};
}

/**
* Check if a message at the given level should be logged
*/
private shouldLog(messageLevel: LogLevel): boolean {
const currentLevel = this.options.level ?? LogLevel.INFO;
return messageLevel >= currentLevel;
}

private static consoleLevelsMap: Record<LogLevel, (...data: any[]) => void> = {
[LogLevel.INFO]: console.log,
[LogLevel.WARN]: console.warn,
Expand All @@ -58,6 +67,7 @@ export class CodegenLogger {

private tryWriteToConsole(level: LogLevel, formattedMessage: string): void {
if (this.isSuppressed(level)) return;
if (!this.shouldLog(level)) return;
const logFn = CodegenLogger.consoleLevelsMap[level] || console.log;
logFn(formattedMessage);
}
Expand All @@ -74,8 +84,11 @@ export class CodegenLogger {
*/
error(message: string, error?: Error): void {
if (this.isSuppressed(LogLevel.ERROR)) return;
if (!this.shouldLog(LogLevel.ERROR)) return;
console.error(this.formatMessage("X", message, pc.red));
if (error && this.options.verbose) {
// Show error details if verbose or log level is DEBUG
const showDetails = this.options.level === LogLevel.DEBUG;
if (error && showDetails) {
console.error(pc.red(` ${error.message}`));
if (error.stack) {
console.error(pc.gray(error.stack));
Expand Down Expand Up @@ -105,10 +118,11 @@ export class CodegenLogger {
}

/**
* Debug message (only shows in verbose mode)
* Debug message (only shows when log level is DEBUG or verbose is true)
*/
debug(message: string): void {
if (this.options.verbose) {
// Debug shows if verbose is true OR log level allows DEBUG
if (this.shouldLog(LogLevel.DEBUG)) {
this.tryWriteToConsole(LogLevel.DEBUG, this.formatMessage("🐛", message, pc.magenta));
}
}
Expand Down Expand Up @@ -159,6 +173,14 @@ export class CodegenLogger {
configure(options: Partial<LogOptions>): void {
this.options = { ...this.options, ...options };
}

getLevel(): LogLevel {
return this.options.level ?? LogLevel.INFO;
}

setLevel(level: LogLevel): void {
this.options.level = level;
}
}

/**
Expand Down
2 changes: 1 addition & 1 deletion test/unit/typeschema/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
export type PFS = Partial<FHIRSchema>;
export type PVS = Partial<ValueSet>;

const logger = createLogger({ verbose: true, prefix: "TEST" });
const logger = createLogger({ prefix: "TEST" });

export const r4Package = { name: "hl7.fhir.r4.core", version: "4.0.1" };

Expand Down