or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.mdopenapi30-builder.mdopenapi30-types.mdopenapi31-builder.mdopenapi31-types.mdserver-management.mdspecification-extensions.md

specification-extensions.mddocs/

0

# Specification Extensions

1

2

Support for OpenAPI specification extensions (`x-*` properties) with validation and management utilities.

3

4

## Capabilities

5

6

### Extension Type Definitions

7

8

Core types for working with OpenAPI specification extensions.

9

10

```typescript { .api }

11

/**

12

* Extension name pattern - must start with 'x-'

13

*/

14

type IExtensionName = `x-${string}`;

15

16

/**

17

* Extension value type - can be any value

18

*/

19

type IExtensionType = any;

20

21

/**

22

* Interface for objects supporting specification extensions

23

*/

24

interface ISpecificationExtension {

25

[extensionName: IExtensionName]: IExtensionType;

26

}

27

```

28

29

### SpecificationExtension Class

30

31

Implementation class for managing OpenAPI specification extensions.

32

33

```typescript { .api }

34

/**

35

* Specification extension management class

36

*/

37

class SpecificationExtension implements ISpecificationExtension {

38

[extensionName: IExtensionName]: any;

39

40

/**

41

* Validate if an extension name follows the x- pattern

42

* @param extensionName - Extension name to validate

43

* @returns True if extension name is valid (starts with 'x-')

44

*/

45

static isValidExtension(extensionName: string): boolean;

46

47

/**

48

* Get an extension value by name

49

* @param extensionName - Extension name (must start with 'x-')

50

* @returns Extension value or null if not found

51

* @throws Error if extension name is invalid

52

*/

53

getExtension(extensionName: string): any;

54

55

/**

56

* Add an extension with validation

57

* @param extensionName - Extension name (must start with 'x-')

58

* @param payload - Extension value

59

* @throws Error if extension name is invalid

60

*/

61

addExtension(extensionName: string, payload: any): void;

62

63

/**

64

* List all extension names on this object

65

* @returns Array of extension names

66

*/

67

listExtensions(): string[];

68

}

69

```

70

71

**Usage Examples:**

72

73

```typescript

74

import { SpecificationExtension } from "openapi3-ts";

75

76

// Create extension manager

77

const extensions = new SpecificationExtension();

78

79

// Add extensions

80

extensions.addExtension("x-custom-field", "custom value");

81

extensions.addExtension("x-rate-limit", { requests: 100, window: "1m" });

82

extensions.addExtension("x-internal-id", 12345);

83

84

// Get extension values

85

const customField = extensions.getExtension("x-custom-field");

86

console.log(customField); // "custom value"

87

88

const rateLimit = extensions.getExtension("x-rate-limit");

89

console.log(rateLimit); // { requests: 100, window: "1m" }

90

91

// List all extensions

92

const extensionNames = extensions.listExtensions();

93

console.log(extensionNames); // ["x-custom-field", "x-rate-limit", "x-internal-id"]

94

95

// Validate extension names

96

console.log(SpecificationExtension.isValidExtension("x-valid")); // true

97

console.log(SpecificationExtension.isValidExtension("invalid")); // false

98

99

// Error handling

100

try {

101

extensions.addExtension("invalid-name", "value");

102

} catch (error) {

103

console.error(error.message); // "Invalid specification extension..."

104

}

105

```

106

107

### Utility Functions

108

109

Helper functions for working with extensions on any OpenAPI object.

110

111

```typescript { .api }

112

/**

113

* Get an extension value from any object supporting extensions

114

* @param obj - Object with potential extensions

115

* @param extensionName - Extension name (must start with 'x-')

116

* @returns Extension value or undefined

117

*/

118

function getExtension(

119

obj: ISpecificationExtension | undefined,

120

extensionName: string

121

): any;

122

123

/**

124

* Add an extension to any object supporting extensions

125

* @param obj - Object to add extension to

126

* @param extensionName - Extension name (must start with 'x-')

127

* @param extension - Extension value

128

*/

129

function addExtension(

130

obj: ISpecificationExtension | undefined,

131

extensionName: string,

132

extension: any

133

): void;

134

```

135

136

**Usage Examples:**

137

138

```typescript

139

import { oas30, getExtension, addExtension } from "openapi3-ts";

140

141

// Create OpenAPI objects

142

const schema: oas30.SchemaObject = {

143

type: "object",

144

properties: {

145

id: { type: "integer" }

146

}

147

};

148

149

const operation: oas30.OperationObject = {

150

summary: "Get item",

151

responses: {

152

"200": { description: "Success" }

153

}

154

};

155

156

// Add extensions using utility functions

157

addExtension(schema, "x-database-table", "items");

158

addExtension(schema, "x-validation-level", "strict");

159

160

addExtension(operation, "x-rate-limit", 1000);

161

addExtension(operation, "x-cached", true);

162

163

// Get extensions using utility functions

164

const tableName = getExtension(schema, "x-database-table");

165

console.log(tableName); // "items"

166

167

const rateLimit = getExtension(operation, "x-rate-limit");

168

console.log(rateLimit); // 1000

169

170

// Extensions are accessible as properties too

171

console.log(schema["x-validation-level"]); // "strict"

172

console.log(operation["x-cached"]); // true

173

```

174

175

## Extension Patterns and Examples

176

177

### Common Extension Patterns

178

179

```typescript

180

import { oas30 } from "openapi3-ts";

181

182

// Vendor-specific extensions

183

const spec = oas30.OpenApiBuilder.create()

184

.addTitle("API with Extensions")

185

.addVersion("1.0.0")

186

.getSpec();

187

188

// Add vendor extensions to the root document

189

spec["x-amazon-apigateway-cors"] = {

190

allowOrigins: ["*"],

191

allowMethods: ["GET", "POST"],

192

allowHeaders: ["Content-Type", "Authorization"]

193

};

194

195

spec["x-swagger-ui"] = {

196

theme: "dark",

197

displayRequestDuration: true

198

};

199

200

// Schema-level extensions for code generation

201

const userSchema: oas30.SchemaObject = {

202

type: "object",

203

required: ["id", "name"],

204

properties: {

205

id: { type: "integer", format: "int64" },

206

name: { type: "string" },

207

email: { type: "string", format: "email" }

208

}

209

};

210

211

// Add code generation hints

212

userSchema["x-go-type"] = "User";

213

userSchema["x-java-class"] = "com.example.User";

214

userSchema["x-database-table"] = "users";

215

userSchema["x-tags"] = ["entity", "user"];

216

217

// Operation-level extensions for infrastructure

218

const getUserOperation: oas30.OperationObject = {

219

summary: "Get user by ID",

220

parameters: [

221

{

222

name: "id",

223

in: "path",

224

required: true,

225

schema: { type: "integer" }

226

}

227

],

228

responses: {

229

"200": {

230

description: "User found",

231

content: {

232

"application/json": {

233

schema: { $ref: "#/components/schemas/User" }

234

}

235

}

236

}

237

}

238

};

239

240

// Add infrastructure extensions

241

getUserOperation["x-rate-limit"] = { requests: 100, window: "1m" };

242

getUserOperation["x-cache-ttl"] = 300; // 5 minutes

243

getUserOperation["x-auth-required"] = true;

244

getUserOperation["x-permissions"] = ["user:read"];

245

```

246

247

### Extension Validation and Management

248

249

```typescript

250

import { SpecificationExtension, ISpecificationExtension } from "openapi3-ts";

251

252

// Helper class for managing typed extensions

253

class ExtensionManager {

254

private extensions: ISpecificationExtension = {};

255

256

addRateLimit(requests: number, window: string): void {

257

this.extensions["x-rate-limit"] = { requests, window };

258

}

259

260

addCacheSettings(ttl: number, strategy: string): void {

261

this.extensions["x-cache"] = { ttl, strategy };

262

}

263

264

addVendorConfig(vendor: string, config: object): void {

265

const extensionName = `x-${vendor}-config` as any;

266

if (SpecificationExtension.isValidExtension(extensionName)) {

267

this.extensions[extensionName] = config;

268

}

269

}

270

271

applyTo(target: ISpecificationExtension): void {

272

Object.keys(this.extensions).forEach(key => {

273

if (SpecificationExtension.isValidExtension(key)) {

274

target[key as any] = this.extensions[key as any];

275

}

276

});

277

}

278

279

getExtensions(): ISpecificationExtension {

280

return { ...this.extensions };

281

}

282

}

283

284

// Usage

285

const extManager = new ExtensionManager();

286

extManager.addRateLimit(1000, "1h");

287

extManager.addCacheSettings(600, "lru");

288

extManager.addVendorConfig("aws", {

289

region: "us-east-1",

290

timeout: 30000

291

});

292

293

// Apply to OpenAPI objects

294

const operation: oas30.OperationObject = {

295

summary: "Test operation",

296

responses: { "200": { description: "Success" } }

297

};

298

299

extManager.applyTo(operation);

300

console.log(operation["x-rate-limit"]); // { requests: 1000, window: "1h" }

301

console.log(operation["x-aws-config"]); // { region: "us-east-1", timeout: 30000 }

302

```

303

304

### Extension Integration with Builders

305

306

```typescript

307

import { oas30, SpecificationExtension } from "openapi3-ts";

308

309

// Extend builder with extension support

310

class ExtendedOpenApiBuilder extends oas30.OpenApiBuilder {

311

addExtension(extensionName: string, value: any): ExtendedOpenApiBuilder {

312

if (SpecificationExtension.isValidExtension(extensionName)) {

313

this.rootDoc[extensionName as any] = value;

314

} else {

315

throw new Error(`Invalid extension name: ${extensionName}`);

316

}

317

return this;

318

}

319

320

addSchemaWithExtensions(

321

name: string,

322

schema: oas30.SchemaObject,

323

extensions: { [key: string]: any }

324

): ExtendedOpenApiBuilder {

325

// Add extensions to schema

326

Object.keys(extensions).forEach(key => {

327

if (SpecificationExtension.isValidExtension(key)) {

328

(schema as any)[key] = extensions[key];

329

}

330

});

331

332

return this.addSchema(name, schema) as ExtendedOpenApiBuilder;

333

}

334

335

addOperationWithExtensions(

336

path: string,

337

method: string,

338

operation: oas30.OperationObject,

339

extensions: { [key: string]: any }

340

): ExtendedOpenApiBuilder {

341

// Add extensions to operation

342

Object.keys(extensions).forEach(key => {

343

if (SpecificationExtension.isValidExtension(key)) {

344

(operation as any)[key] = extensions[key];

345

}

346

});

347

348

const pathItem: oas30.PathItemObject = {

349

[method]: operation

350

};

351

352

return this.addPath(path, pathItem) as ExtendedOpenApiBuilder;

353

}

354

}

355

356

// Usage

357

const spec = new ExtendedOpenApiBuilder()

358

.addTitle("Extended API")

359

.addVersion("1.0.0")

360

.addExtension("x-api-id", "api-12345")

361

.addExtension("x-build-info", {

362

version: "1.2.3",

363

buildTime: new Date().toISOString(),

364

gitCommit: "abc123"

365

})

366

.addSchemaWithExtensions("User", {

367

type: "object",

368

properties: {

369

id: { type: "integer" },

370

name: { type: "string" }

371

}

372

}, {

373

"x-database-table": "users",

374

"x-java-class": "com.example.User"

375

})

376

.addOperationWithExtensions("/users", "get", {

377

summary: "List users",

378

responses: {

379

"200": { description: "Success" }

380

}

381

}, {

382

"x-rate-limit": { requests: 100, window: "1m" },

383

"x-cache-ttl": 300

384

})

385

.getSpec();

386

387

console.log(spec["x-api-id"]); // "api-12345"

388

console.log(spec.components?.schemas?.User?.["x-database-table"]); // "users"

389

```

390

391

## Best Practices

392

393

### Extension Naming Conventions

394

395

```typescript

396

// Good extension names

397

const goodExtensions = [

398

"x-internal-id", // kebab-case

399

"x-rate-limit", // descriptive

400

"x-vendor-config", // vendor prefix

401

"x-code-gen-options", // purpose clear

402

];

403

404

// Poor extension names

405

const poorExtensions = [

406

"x-data", // too generic

407

"x-temp", // unclear purpose

408

"x-customField", // camelCase (prefer kebab)

409

"x-123", // starts with number

410

];

411

412

// Validation helper

413

function isGoodExtensionName(name: string): boolean {

414

return SpecificationExtension.isValidExtension(name) &&

415

name.length > 2 &&

416

/^x-[a-z][a-z0-9-]*$/.test(name);

417

}

418

```

419

420

### Type-Safe Extension Handling

421

422

```typescript

423

import { ISpecificationExtension } from "openapi3-ts";

424

425

// Define typed extension interfaces

426

interface RateLimitExtension {

427

"x-rate-limit": {

428

requests: number;

429

window: string;

430

};

431

}

432

433

interface CacheExtension {

434

"x-cache-ttl": number;

435

}

436

437

// Utility types for extension combinations

438

type WithRateLimit<T> = T & RateLimitExtension;

439

type WithCache<T> = T & CacheExtension;

440

type WithBoth<T> = T & RateLimitExtension & CacheExtension;

441

442

// Type-safe extension helpers

443

function addRateLimit<T extends ISpecificationExtension>(

444

obj: T,

445

requests: number,

446

window: string

447

): WithRateLimit<T> {

448

(obj as any)["x-rate-limit"] = { requests, window };

449

return obj as WithRateLimit<T>;

450

}

451

452

function addCache<T extends ISpecificationExtension>(

453

obj: T,

454

ttl: number

455

): WithCache<T> {

456

(obj as any)["x-cache-ttl"] = ttl;

457

return obj as WithCache<T>;

458

}

459

460

// Usage with type safety

461

import { oas30 } from "openapi3-ts";

462

463

let operation: oas30.OperationObject = {

464

summary: "Get user",

465

responses: { "200": { description: "Success" } }

466

};

467

468

// Chain extensions with type safety

469

operation = addCache(addRateLimit(operation, 100, "1m"), 300);

470

471

// TypeScript knows about the extensions

472

console.log(operation["x-rate-limit"].requests); // 100

473

console.log(operation["x-cache-ttl"]); // 300

474

```