
Research
/Security News
737 Chrome VPN Extensions Linked to Brand Impersonation and Browser Traffic Redirection
The campaign amassed more than 75,000 installs by targeting Russian-speaking users seeking access to blocked services.
@ng-forge/openapi-generator
Advanced tools
Generate @ng-forge/dynamic-forms configurations from OpenAPI specs
Converts OpenAPI 3.x specifications into @ng-forge/dynamic-forms FormConfig objects and TypeScript interfaces.
1. Write (or already have) an OpenAPI 3.x spec:
# openapi.yaml
openapi: '3.0.3'
info:
title: My API
version: '1.0'
paths:
/users/register:
post:
operationId: registerUser
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [email, password]
properties:
email:
type: string
format: email
password:
type: string
format: password
minLength: 8
bio:
type: string
maxLength: 500
2. Run the generator:
npx @ng-forge/openapi-generator --spec openapi.yaml --output src/generated
3. Import and use in your Angular component:
import { DynamicForm } from '@ng-forge/dynamic-forms';
import { registerUserFormConfig } from './generated/forms';
import type { RegisterUserFormValue } from './generated/types';
@Component({
imports: [DynamicForm],
template: `<form [dynamic-form]="formConfig" (submitted)="onSubmit($event)"></form>`,
})
export class RegisterComponent {
formConfig = registerUserFormConfig;
onSubmit(value: RegisterUserFormValue) {
this.http.post('/users/register', value).subscribe();
}
}
The form needs a UI adapter registered once in your app providers, for example
provideDynamicForm(...withMaterialFields()). See any@ng-forge/dynamic-forms-*adapter package for setup.
The generator produces a typed FormConfig and a matching TypeScript interface:
register-user.form.tsimport type { FormConfig } from '@ng-forge/dynamic-forms';
export const registerUserFormConfig = {
fields: [
{
key: 'email',
type: 'input',
label: 'Email',
props: { type: 'email' },
validators: [{ type: 'required' }, { type: 'email' }],
},
{
key: 'password',
type: 'input',
label: 'Password',
props: { type: 'password' },
validators: [{ type: 'required' }, { type: 'minLength', value: 8 }],
},
{
key: 'bio',
type: 'textarea',
label: 'Bio',
validators: [{ type: 'maxLength', value: 500 }],
},
],
} as const satisfies FormConfig;
register-user.types.tsexport interface RegisterUserFormValue {
email: string;
password: string;
bio?: string;
}
npm install @ng-forge/openapi-generator
ng-forge-generator --spec openapi.yaml --output src/generated
| Option | Description |
|---|---|
--spec <path> | Path to OpenAPI spec file (required) |
--output <path> | Output directory for generated files (required) |
--interactive <mode> | full (prompt for endpoints + ambiguous types) or none (auto-select). Default: full |
--endpoints <list> | Comma-separated endpoints, e.g. "POST:/users,PUT:/users/{id}" |
--read-only | Generate GET endpoint forms with all fields disabled |
--barrel-extension <ext> | Extension in barrel re-exports. Accepts "" (default — no extension) or a dot-prefixed value like ".js" (for Node ESM). Pass "" to reset |
--watch | Watch spec file for changes and regenerate |
--config <path> | Directory for .ng-forge-generator.json config (defaults to --output) |
--dry-run | List files that would be generated without writing them |
--skip-existing | Skip files that already exist on disk |
--verbose | Show detailed output including field mapping decisions |
--quiet | Suppress info output; still shows success summary, warnings, and errors |
--interactive full (default): Prompts the user to select endpoints (all pre-checked) and resolve ambiguous field types. Automatically falls back to none in non-TTY environments (e.g., CI pipelines).--interactive none: No prompts. Uses --endpoints flag, saved config, or auto-selects all endpoints. GET endpoints with top-level array responses are always skipped.# Interactive mode (default) — prompts for endpoint selection and field types
ng-forge-generator --spec openapi.yaml --output src/generated
# Non-interactive for CI — auto-selects POST/PUT/PATCH
ng-forge-generator --spec openapi.yaml --output src/generated --interactive none
# Specific endpoints only
ng-forge-generator --spec openapi.yaml --output src/generated \
--interactive none --endpoints "POST:/users,PUT:/users/{id}"
# Generate GET endpoints with disabled (read-only) fields
ng-forge-generator --spec openapi.yaml --output src/generated --interactive none --read-only
# Node ESM / moduleResolution nodenext — emit .js extensions in barrel files
ng-forge-generator --spec openapi.yaml --output src/generated --barrel-extension .js
# Preview without writing
ng-forge-generator --spec openapi.yaml --output src/generated --dry-run
# Watch for changes
ng-forge-generator --spec openapi.yaml --output src/generated --watch
# Verbose output for debugging field mapping
ng-forge-generator --spec openapi.yaml --output src/generated --interactive none --verbose
# Quiet mode for CI pipelines
ng-forge-generator --spec openapi.yaml --output src/generated --interactive none --quiet
| OpenAPI Type | Format/Constraint | Form Field Type | Ambiguous? |
|---|---|---|---|
string | -- | input (text) | Yes: textarea |
string | email | input (email) | No |
string | password | input (password) | No |
string | uri / url | input (url) | No |
string | date / date-time | datepicker | No |
string | time | input (time) | No |
string + enum | -- | select | Yes: radio |
string + maxLength <= 100 | -- | input (text) | No |
string + maxLength > 200 | -- | textarea | No |
integer / number | -- | input (number) | Yes: slider |
boolean | -- | checkbox | Yes: toggle |
array + enum items | -- | multi-checkbox | No |
array + object items | -- | array (template) | No |
array + primitive items | -- | array (single template) | No |
object | -- | group | No |
description, notes, comment, bio, body, content, summary, message, text are resolved to textarea (overrides ambiguous text input).phone, tel, telephone, mobile, fax, cell are resolved to input type tel.| OpenAPI Constraint | Form Validator |
|---|---|
required | required |
minLength | minLength |
maxLength | maxLength |
minimum | min |
maximum | max |
pattern | pattern |
format: email | email |
minItems (array) | minLength |
maxItems (array) | maxLength |
x-ng-forge-type: Override the generated field type entirely (e.g., x-ng-forge-type: color-picker).x-enum-labels: Custom human-readable labels for enum values. Supports array format ['Label 1', 'Label 2'] or object format { value1: 'Label 1', value2: 'Label 2' }.allOf (Schema Composition)The generator merges all schemas in an allOf array into a single flat set of properties. This is commonly used for inheritance-style schemas:
NewPet:
allOf:
- $ref: '#/components/schemas/Pet' # base properties
- type: object
properties:
ownerEmail: # additional properties
type: string
format: email
The generated form includes all properties from Pet plus ownerEmail, as if they were declared in a single schema.
oneOf + discriminator (Polymorphic Forms)When a schema uses oneOf with a discriminator, the generator creates a conditional form:
Payment:
oneOf:
- $ref: '#/components/schemas/CreditCardPayment'
- $ref: '#/components/schemas/BankTransferPayment'
discriminator:
propertyName: paymentMethod
mapping:
credit_card: '#/components/schemas/CreditCardPayment'
bank_transfer: '#/components/schemas/BankTransferPayment'
This produces:
paymentMethod)logic based on the discriminator valuePaymentCreditCard, PaymentBankTransfer) combined as a union typeWhen a property references a discriminator schema (e.g., method: { $ref: '#/components/schemas/Payment' }), the generator wraps the discriminator fields inside a group field for that property.
--read-only: GET endpoint fields are generated with disabled: true, and array fields have no add/remove buttons.The --watch flag starts a file watcher on the spec file. When the spec changes:
--watch to select themCtrl+C to stop watchingWatch mode is useful during API-first development workflows where the spec is being actively edited.
A .ng-forge-generator.json config file is saved in the output directory (or the --config directory). It stores:
METHOD:/path pairs to generate"registerUser.acceptTerms": "checkbox")index.ts re-exports (empty by default)This enables reproducible non-interactive re-runs. On subsequent runs, the generator reuses saved decisions without prompting.
<output>/
├── forms/
│ ├── <endpoint>.form.ts # FormConfig objects
│ └── index.ts # Barrel exports
├── types/
│ ├── <endpoint>.types.ts # TypeScript interfaces
│ └── index.ts # Barrel exports
└── .ng-forge-generator.json # Config
operationId: kebab-cased operationId (e.g., createPet -> create-pet.form.ts)operationId: method + path (e.g., POST /users/register -> post-users-register.form.ts)By default, generated index.ts barrel files re-export modules without a file extension:
// forms/index.ts
export * from './create-pet.form';
export * from './update-pet.form';
This matches the typical Angular app setup (moduleResolution: bundler). For Node ESM consumers running with moduleResolution: node16 or nodenext, pass --barrel-extension .js to emit fully-qualified ESM imports.
The selected extension persists in .ng-forge-generator.json (only when non-empty) so future runs keep your choice. To clear a previously-saved .js and return to the default, pass --barrel-extension "" or delete the barrelExtension key from the config file.
Migrating from pre-1.x: Earlier versions emitted
.jssuffixes by default. Upgrading will change generated barrel output for users who had not explicitly configured this — pass--barrel-extension .json your next run to preserve the old behavior.
The package exports all core functions for programmatic use:
// Parse and dereference an OpenAPI 3.x spec file
parseOpenAPISpec(specPath: string): Promise<OpenAPISpec>
// Extract GET/POST/PUT/PATCH endpoints with their schemas
extractEndpoints(spec: OpenAPISpec): EndpointInfo[]
// Walk a schema, merging allOf and resolving discriminators
walkSchema(schema: SchemaObject, requiredFields?: string[]): WalkedSchema
// Map a single schema property to a form field type
mapSchemaToFieldType(schema: SchemaObject): FieldTypeResult
// Map schema constraints to form validators
mapSchemaToValidators(schema: SchemaObject, required: boolean): ValidatorConfig[]
// Map an entire schema to an array of FieldConfig objects
mapSchemaToFields(schema: SchemaObject, requiredFields: string[], options?: MappingOptions): MappingResult
// Generate a TypeScript FormConfig source string from fields
generateFormConfig(fields: FieldConfig[], options: FormConfigGeneratorOptions): string
// Generate a TypeScript interface source string from a schema
generateInterface(schema: SchemaObject, options: InterfaceGeneratorOptions): string
// Generate an index.ts barrel file. `options.extension` controls the re-export
// suffix (default: '' — no extension; use '.js' for Node ESM/nodenext).
generateBarrel(fileNames: string[], options?: BarrelOptions): string
// Write generated files to disk (with change detection and skip-existing support)
writeGeneratedFiles(outputDir: string, files: GeneratedFile[], options?: WriteOptions): Promise<WriteResult>
// Load/save the .ng-forge-generator.json config file
loadConfig(dir: string): Promise<GeneratorConfig | null>
saveConfig(dir: string, config: GeneratorConfig): Promise<void>
input instead of textarea?Plain string fields without a format are ambiguous — they could be a short text input or a long textarea. The generator resolves this by:
maxLength constraint: <= 100 → input, > 200 → textarea, between 100-200 → ambiguousdescription, notes, bio, message, etc. → textarea--interactive full): you choose--interactive none): falls back to inputTo force a specific type, use the x-ng-forge-type extension on the property in your spec.
GET endpoints with top-level array responses are always skipped since they don't map to a single form. For all other GET endpoints, forms are generated by default with editable fields.
To make GET endpoint fields read-only, use --read-only.
application/json, multipart/form-data, and application/x-www-form-urlencoded, in that preference order when an endpoint declares more than one.
Binary file properties (type: string, format: binary, including arrays of them) are skipped with a warning since there is no file upload field type yet. An endpoint whose body contains only binary properties produces no form and is skipped entirely.
Only OpenAPI 3.x specs are supported. Convert Swagger 2.0 specs using converter.swagger.io or the swagger2openapi npm package.
The generator saves your choices to .ng-forge-generator.json. Subsequent runs with --interactive none reuse those decisions automatically. To reset, delete the config file.
| Code | Meaning |
|---|---|
0 | Success |
1 | Error (parse failure, no endpoints found/selected, invalid options) |
FAQs
Generate @ng-forge/dynamic-forms configurations from OpenAPI specs
We found that @ng-forge/openapi-generator demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
/Security News
The campaign amassed more than 75,000 installs by targeting Russian-speaking users seeking access to blocked services.

Company News
Open source maintainers are under more pressure than ever. We're raising our open source program from the Team plan to the Business plan, free.

Security News
The supply chain control that delays freshly published gems now covers lockfile generation and gem vendoring in Ruby projects.