···11+import type { RangeOptions, SemVer } from 'semver';
22+import * as semver from 'semver';
33+44+export type Package = {
55+ /**
66+ * Get the installed version of a package.
77+ * @param name The name of the package to get the version for.
88+ * @returns A SemVer object containing version information, or undefined if the package is not installed
99+ * or the version string is invalid.
1010+ */
1111+ getVersion: (name: string) => SemVer | undefined;
1212+ /**
1313+ * Check if a given package is installed in the project.
1414+ * @param name The name of the package to check.
1515+ */
1616+ isInstalled: (name: string) => boolean;
1717+ /**
1818+ * Check if the installed version of a package or a given SemVer object satisfies a semver range.
1919+ * @param nameOrVersion The name of the package to check, or a SemVer object.
2020+ * @param range The semver range to check against.
2121+ * @returns True if the version satisfies the range, false otherwise.
2222+ */
2323+ satisfies: (
2424+ nameOrVersion: string | SemVer,
2525+ range: string,
2626+ optionsOrLoose?: boolean | RangeOptions,
2727+ ) => boolean;
2828+};
2929+3030+export const packageFactory = (
3131+ dependencies: Record<string, string>,
3232+): Package => ({
3333+ getVersion: (name) => {
3434+ const version = dependencies[name];
3535+ try {
3636+ if (version) {
3737+ return semver.parse(version) || undefined;
3838+ }
3939+ } catch {
4040+ // noop
4141+ }
4242+ return;
4343+ },
4444+ isInstalled: (name) => Boolean(dependencies[name]),
4545+ satisfies: (nameOrVersion, range, optionsOrLoose) => {
4646+ const version =
4747+ typeof nameOrVersion === 'string'
4848+ ? dependencies[nameOrVersion]
4949+ : nameOrVersion;
5050+ return version ? semver.satisfies(version, range, optionsOrLoose) : false;
5151+ },
5252+});
···4141 Performance.start('createClient');
42424343 Performance.start('config');
4444- for (const result of await initConfigs(resolvedConfig)) {
4444+ const configResults = await initConfigs(resolvedConfig);
4545+ for (const result of configResults.results) {
4546 configs.push(result.config);
4647 if (result.errors.length) {
4748 throw result.errors[0];
···5455 Performance.end('handlebars');
55565657 const clients = await Promise.all(
5757- configs.map((config) => pCreateClient({ config, templates })),
5858+ configs.map((config) =>
5959+ pCreateClient({
6060+ config,
6161+ dependencies: configResults.dependencies,
6262+ templates,
6363+ }),
6464+ ),
5865 );
5966 const result = clients.filter((client) => Boolean(client)) as ReadonlyArray<
6067 Client | IR.Context
+19-1
packages/openapi-ts/src/ir/context.ts
···11import path from 'node:path';
2233+import type { Package } from '../config/utils/package';
44+import { packageFactory } from '../config/utils/package';
35import { GeneratedFile } from '../generate/file';
46import type { PluginConfigMap } from '../plugins/config';
57import { PluginInstance } from '../plugins/shared/utils/instance';
···4749 */
4850 public ir: IR.Model = {};
4951 /**
5252+ * The package metadata and utilities for the current context, constructed
5353+ * from the provided dependencies. Used for managing package-related
5454+ * information such as name, version, and dependency resolution during
5555+ * code generation.
5656+ */
5757+ public package: Package;
5858+ /**
5059 * A map of registered plugin instances, keyed by plugin name. Plugins are
5160 * registered through the `registerPlugin` method and can be accessed by
5261 * their configured name from the config.
···5968 */
6069 public spec: Spec;
61706262- constructor({ config, spec }: { config: Config; spec: Spec }) {
7171+ constructor({
7272+ config,
7373+ dependencies,
7474+ spec,
7575+ }: {
7676+ config: Config;
7777+ dependencies: Record<string, string>;
7878+ spec: Spec;
7979+ }) {
6380 this.config = config;
8181+ this.package = packageFactory(dependencies);
6482 this.spec = spec;
6583 }
6684
···1313 private handler: Plugin.Config<T>['handler'];
1414 public name: T['resolvedConfig']['name'];
1515 public output: Required<T['config']>['output'];
1616+ /**
1717+ * The package metadata and utilities for the current context, constructed
1818+ * from the provided dependencies. Used for managing package-related
1919+ * information such as name, version, and dependency resolution during
2020+ * code generation.
2121+ */
2222+ public package: IR.Context['package'];
16231724 public constructor(
1825 props: Pick<
···3239 this.handler = props.handler;
3340 this.name = props.name;
3441 this.output = props.output;
4242+ this.package = props.context.package;
3543 }
36443745 public createFile(file: IR.ContextFile) {
+5-3
packages/openapi-ts/src/plugins/types.d.ts
···11-import type { ValueToObject } from '../config/utils';
11+import type { ValueToObject } from '../config/utils/config';
22+import type { Package } from '../config/utils/package';
23import type { OpenApi as LegacyOpenApi } from '../openApi';
34import type { Client as LegacyClient } from '../types/client';
45import type { Files } from '../types/utils';
···35363637type PluginTag = 'client' | 'transformer' | 'validator';
37383838-export interface PluginContext {
3939+export type PluginContext = {
4040+ package: Package;
3941 pluginByTag: <T extends AnyPluginName | boolean = AnyPluginName>(
4042 tag: PluginTag,
4143 props?: {
···4446 },
4547 ) => Exclude<T, boolean> | undefined;
4648 valueToObject: ValueToObject;
4747-}
4949+};
48504951type BaseApi = Record<string, unknown>;
5052
···44import type { IR } from '../../ir/types';
55import { createSchemaComment } from '../shared/utils/schema';
66import { identifiers, zodId } from './constants';
77-import type { ZodSchema } from './plugin';
77+import type { ZodSchema } from './shared/types';
88import type { ZodPlugin } from './types';
991010export const exportZodSchema = ({
···11-import { operationResponsesMap } from '../../ir/operation';
22-import type { IR } from '../../ir/types';
33-import { buildName } from '../../openApi/shared/utils/name';
44-import { zodId } from './constants';
55-import { exportZodSchema } from './export';
11+import { operationResponsesMap } from '../../../ir/operation';
22+import type { IR } from '../../../ir/types';
33+import { buildName } from '../../../openApi/shared/utils/name';
44+import { zodId } from '../constants';
55+import { exportZodSchema } from '../export';
66+import type { ZodPlugin } from '../types';
67import type { State } from './plugin';
78import { schemaToZodSchema } from './plugin';
88-import type { ZodPlugin } from './types';
991010export const operationToZodSchema = ({
1111 operation,