0
# Utility Functions
1
2
Helper functions for type detection, schema validation, input processing, and URL handling that support the core OAS Normalize functionality.
3
4
## Capabilities
5
6
### Type Detection Functions
7
8
Functions for detecting and identifying different types of inputs and API definition formats.
9
10
```typescript { .api }
11
/**
12
* Determine the type of a given variable
13
* @param obj - Input to analyze
14
* @returns Input type or false if unrecognized
15
*/
16
function getType(obj: any): 'buffer' | 'json' | 'path' | 'string-json' | 'string-yaml' | 'url' | false;
17
18
/**
19
* Determine if a given variable is a Buffer
20
* @param obj - Object to test
21
* @returns True if obj is a Buffer
22
*/
23
function isBuffer(obj: any): boolean;
24
```
25
26
**Usage Examples:**
27
28
```typescript
29
import { getType, isBuffer } from "oas-normalize/lib/utils";
30
31
// Detect different input types
32
console.log(getType('https://api.example.com/spec.json')); // 'url'
33
console.log(getType('./local-spec.yaml')); // 'path'
34
console.log(getType('{"openapi": "3.0.0"}')); // 'string-json'
35
console.log(getType('openapi: 3.0.0\ninfo:')); // 'string-yaml'
36
console.log(getType({ openapi: '3.0.0' })); // 'json'
37
38
// Buffer detection
39
const buffer = Buffer.from('openapi: 3.0.0');
40
console.log(isBuffer(buffer)); // true
41
console.log(getType(buffer)); // 'buffer'
42
```
43
44
### API Definition Type Functions
45
46
Functions for identifying and validating different API specification formats.
47
48
```typescript { .api }
49
/**
50
* Determine if a given schema is an OpenAPI definition
51
* @param schema - Schema object to test
52
* @returns True if schema is OpenAPI format
53
*/
54
function isOpenAPI(schema: Record<string, unknown>): boolean;
55
56
/**
57
* Determine if a given schema is a Swagger definition
58
* @param schema - Schema object to test
59
* @returns True if schema is Swagger format
60
*/
61
function isSwagger(schema: Record<string, unknown>): boolean;
62
63
/**
64
* Determine if a given schema is a Postman collection
65
* @param schema - Schema object to test
66
* @returns True if schema is Postman collection
67
*/
68
function isPostman(schema: Record<string, unknown>): boolean;
69
70
/**
71
* Determine if a given schema is any supported API definition
72
* @param schema - Schema object to test
73
* @returns True if schema is a supported API format
74
*/
75
function isAPIDefinition(schema: Record<string, unknown>): boolean;
76
77
/**
78
* Retrieve the specific type of API definition
79
* @param schema - Schema object to analyze
80
* @returns Specific API definition type
81
*/
82
function getAPIDefinitionType(schema: Record<string, unknown>): 'openapi' | 'postman' | 'swagger' | 'unknown';
83
```
84
85
**Usage Examples:**
86
87
```typescript
88
import {
89
isOpenAPI,
90
isSwagger,
91
isPostman,
92
isAPIDefinition,
93
getAPIDefinitionType
94
} from "oas-normalize/lib/utils";
95
96
// OpenAPI detection
97
const openapi = { openapi: '3.0.0', info: { title: 'API' } };
98
console.log(isOpenAPI(openapi)); // true
99
console.log(getAPIDefinitionType(openapi)); // 'openapi'
100
101
// Swagger detection
102
const swagger = { swagger: '2.0', info: { title: 'API' } };
103
console.log(isSwagger(swagger)); // true
104
console.log(getAPIDefinitionType(swagger)); // 'swagger'
105
106
// Postman collection detection
107
const postman = {
108
info: { name: 'Collection' },
109
item: [{ name: 'Request' }]
110
};
111
console.log(isPostman(postman)); // true
112
console.log(getAPIDefinitionType(postman)); // 'postman'
113
114
// Generic API definition check
115
console.log(isAPIDefinition(openapi)); // true
116
console.log(isAPIDefinition(swagger)); // true
117
console.log(isAPIDefinition(postman)); // true
118
console.log(isAPIDefinition({ random: 'object' })); // false
119
```
120
121
### Data Processing Functions
122
123
Functions for converting and processing different data formats.
124
125
```typescript { .api }
126
/**
127
* Convert a YAML blob or stringified JSON object into a JSON object
128
* @param string - Input string or object to convert
129
* @returns Parsed JSON object
130
*/
131
function stringToJSON(string: Record<string, unknown> | string): Record<string, unknown>;
132
```
133
134
**Usage Examples:**
135
136
```typescript
137
import { stringToJSON } from "oas-normalize/lib/utils";
138
139
// JSON string conversion
140
const jsonString = '{"openapi": "3.0.0", "info": {"title": "API"}}';
141
const jsonObj = stringToJSON(jsonString);
142
console.log(jsonObj.openapi); // "3.0.0"
143
144
// YAML string conversion
145
const yamlString = `
146
openapi: 3.0.0
147
info:
148
title: My API
149
version: 1.0.0
150
paths:
151
/users:
152
get:
153
summary: List users
154
`;
155
const yamlObj = stringToJSON(yamlString);
156
console.log(yamlObj.info.title); // "My API"
157
158
// Object pass-through
159
const existingObj = { openapi: '3.1.0' };
160
const result = stringToJSON(existingObj);
161
console.log(result === existingObj); // true (same reference)
162
```
163
164
### URL Processing Functions
165
166
Functions for preparing and processing URLs for API requests.
167
168
```typescript { .api }
169
/**
170
* Deconstruct a URL into a payload for a fetch request
171
* Handles authentication and GitHub URL conversion
172
* @param url - URL to prepare
173
* @returns Object with processed URL and fetch options
174
*/
175
function prepareURL(url: string): {
176
options: RequestInit;
177
url: string;
178
};
179
```
180
181
**Usage Examples:**
182
183
```typescript
184
import { prepareURL } from "oas-normalize/lib/utils";
185
186
// Basic URL preparation
187
const basic = prepareURL('https://api.example.com/openapi.json');
188
console.log(basic.url); // "https://api.example.com/openapi.json"
189
console.log(basic.options); // {}
190
191
// URL with authentication
192
const withAuth = prepareURL('https://user:pass@api.example.com/spec.yaml');
193
console.log(withAuth.url); // "https://api.example.com/spec.yaml" (credentials removed)
194
console.log(withAuth.options.headers); // { Authorization: "Basic dXNlcjpwYXNz" }
195
196
// GitHub blob URL conversion
197
const github = prepareURL('https://github.com/user/repo/blob/main/openapi.yaml');
198
console.log(github.url); // "https://raw.githubusercontent.com/user/repo/main/openapi.yaml"
199
console.log(github.options); // {}
200
```
201
202
## Detailed Function Behavior
203
204
### getType Function Logic
205
206
The `getType` function uses several heuristics to determine input type:
207
208
```typescript
209
// Detection logic examples
210
getType(Buffer.from('data')); // 'buffer' - Uses isBuffer check
211
getType({ key: 'value' }); // 'json' - Object type
212
getType('{"key": "value"}'); // 'string-json' - Starts with whitespace + '{'
213
getType('key: value\nother: data'); // 'string-yaml' - Contains newlines
214
getType('https://example.com'); // 'url' - Starts with 'http'
215
getType('./file.yaml'); // 'path' - Default for strings not matching above
216
getType(123); // false - Unsupported type
217
```
218
219
### API Definition Detection
220
221
Each format has specific detection logic:
222
223
```typescript
224
// OpenAPI detection - looks for 'openapi' property
225
isOpenAPI({ openapi: '3.0.0' }); // true
226
isOpenAPI({ swagger: '2.0' }); // false
227
228
// Swagger detection - looks for 'swagger' property
229
isSwagger({ swagger: '2.0' }); // true
230
isSwagger({ openapi: '3.0.0' }); // false
231
232
// Postman detection - requires both 'info' and 'item' properties
233
isPostman({ info: {}, item: [] }); // true
234
isPostman({ info: {} }); // false (missing item)
235
isPostman({ item: [] }); // false (missing info)
236
```
237
238
### URL Processing Features
239
240
The `prepareURL` function handles several URL transformations:
241
242
```typescript
243
// Authentication extraction
244
const authUrl = 'https://user:password@api.example.com/spec.json';
245
const prepared = prepareURL(authUrl);
246
// URL: "https://api.example.com/spec.json"
247
// Options: { headers: { Authorization: "Basic dXNlcjpwYXNzd29yZA==" } }
248
249
// GitHub blob to raw conversion
250
const blobUrl = 'https://github.com/owner/repo/blob/branch/file.yaml';
251
const githubPrepared = prepareURL(blobUrl);
252
// URL: "https://raw.githubusercontent.com/owner/repo/branch/file.yaml"
253
254
// Regular URLs pass through unchanged
255
const normalUrl = 'https://api.example.com/openapi.json';
256
const normalPrepared = prepareURL(normalUrl);
257
// URL: unchanged, Options: {}
258
```
259
260
## Integration Patterns
261
262
### Type-Safe Input Handling
263
264
```typescript
265
import { getType, stringToJSON, isAPIDefinition } from "oas-normalize/lib/utils";
266
267
function processAPIInput(input: any): Record<string, unknown> {
268
const inputType = getType(input);
269
270
switch (inputType) {
271
case 'json':
272
return input;
273
274
case 'string-json':
275
case 'string-yaml':
276
return stringToJSON(input);
277
278
case 'buffer':
279
return stringToJSON(input.toString());
280
281
case 'url':
282
throw new Error('URL inputs require async processing');
283
284
case 'path':
285
throw new Error('Path inputs require file system access');
286
287
default:
288
throw new Error(`Unsupported input type: ${inputType || 'unknown'}`);
289
}
290
}
291
292
// Usage
293
try {
294
const schema = processAPIInput('{"openapi": "3.0.0"}');
295
if (isAPIDefinition(schema)) {
296
console.log('Valid API definition detected');
297
}
298
} catch (error) {
299
console.error('Input processing failed:', error.message);
300
}
301
```
302
303
### Custom Format Detection
304
305
```typescript
306
import { isOpenAPI, isSwagger, isPostman } from "oas-normalize/lib/utils";
307
308
function analyzeAPIFormat(schema: Record<string, unknown>) {
309
const analysis = {
310
format: 'unknown',
311
version: 'unknown',
312
features: [] as string[]
313
};
314
315
if (isOpenAPI(schema)) {
316
analysis.format = 'openapi';
317
analysis.version = (schema.openapi as string) || 'unknown';
318
319
if (schema.webhooks) analysis.features.push('webhooks');
320
if (schema.components?.callbacks) analysis.features.push('callbacks');
321
322
} else if (isSwagger(schema)) {
323
analysis.format = 'swagger';
324
analysis.version = (schema.swagger as string) || 'unknown';
325
326
if (schema.definitions) analysis.features.push('definitions');
327
if (schema.securityDefinitions) analysis.features.push('security');
328
329
} else if (isPostman(schema)) {
330
analysis.format = 'postman';
331
332
// Extract version from schema URL if available
333
const schemaUrl = (schema.info as any)?.schema;
334
if (schemaUrl) {
335
const versionMatch = schemaUrl.match(/v([0-9.]+)/);
336
if (versionMatch) analysis.version = versionMatch[1];
337
}
338
339
if ((schema.auth as any)) analysis.features.push('authentication');
340
if ((schema.variable as any)) analysis.features.push('variables');
341
}
342
343
return analysis;
344
}
345
346
// Usage
347
const analysis = analyzeAPIFormat(apiSpec);
348
console.log(`Format: ${analysis.format} v${analysis.version}`);
349
console.log(`Features: ${analysis.features.join(', ')}`);
350
```
351
352
### URL Processing Pipeline
353
354
```typescript
355
import { prepareURL } from "oas-normalize/lib/utils";
356
357
async function fetchAPISpec(url: string): Promise<Record<string, unknown>> {
358
const { url: processedUrl, options } = prepareURL(url);
359
360
try {
361
const response = await fetch(processedUrl, {
362
...options,
363
headers: {
364
'Accept': 'application/json, application/yaml, text/yaml',
365
...options.headers
366
}
367
});
368
369
if (!response.ok) {
370
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
371
}
372
373
const contentType = response.headers.get('content-type') || '';
374
const text = await response.text();
375
376
// Process based on content type
377
if (contentType.includes('json')) {
378
return JSON.parse(text);
379
} else {
380
// Assume YAML for other content types
381
return stringToJSON(text);
382
}
383
384
} catch (error) {
385
throw new Error(`Failed to fetch API spec from ${url}: ${error.message}`);
386
}
387
}
388
389
// Usage
390
try {
391
const spec = await fetchAPISpec('https://github.com/user/repo/blob/main/api.yaml');
392
console.log('Successfully fetched and parsed API spec');
393
} catch (error) {
394
console.error('Fetch failed:', error.message);
395
}
396
```