enlace-openapi 0.0.1-beta.4 → 0.0.1-beta.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -84,7 +84,7 @@ function typeToSchema(type, ctx) {
84
84
  );
85
85
  const hasNull = type.types.some((t) => t.flags & import_typescript.default.TypeFlags.Null);
86
86
  if (nonNullTypes.length === 1 && hasNull) {
87
- const schema = typeToSchema(nonNullTypes[0], ctx);
87
+ const schema = typeToSchema(nonNullTypes[0], { ...ctx, depth: ctx.depth + 1 });
88
88
  return { ...schema, nullable: true };
89
89
  }
90
90
  if (nonNullTypes.every((t) => t.isStringLiteral())) {
@@ -99,19 +99,20 @@ function typeToSchema(type, ctx) {
99
99
  enum: nonNullTypes.map((t) => t.value)
100
100
  };
101
101
  }
102
+ const nextCtx = { ...ctx, depth: ctx.depth + 1 };
102
103
  return {
103
- oneOf: nonNullTypes.map((t) => typeToSchema(t, ctx))
104
+ oneOf: nonNullTypes.map((t) => typeToSchema(t, nextCtx))
104
105
  };
105
106
  }
106
107
  if (type.isIntersection()) {
107
- return intersectionTypeToSchema(type, ctx);
108
+ return intersectionTypeToSchema(type, { ...ctx, depth: ctx.depth + 1 });
108
109
  }
109
110
  if (checker.isArrayType(type)) {
110
111
  const typeArgs = type.typeArguments;
111
112
  if (typeArgs?.[0]) {
112
113
  return {
113
114
  type: "array",
114
- items: typeToSchema(typeArgs[0], ctx)
115
+ items: typeToSchema(typeArgs[0], { ...ctx, depth: ctx.depth + 1 })
115
116
  };
116
117
  }
117
118
  return { type: "array" };
@@ -417,12 +418,17 @@ function formDataTypeToSchema(formDataType, ctx) {
417
418
  function generateOpenAPISpec(endpoints, schemas, options = {}) {
418
419
  const { title = "API", version = "1.0.0", description, baseUrl } = options;
419
420
  const paths = {};
421
+ const tagSet = /* @__PURE__ */ new Set();
420
422
  for (const endpoint of endpoints) {
421
423
  if (!paths[endpoint.path]) {
422
424
  paths[endpoint.path] = {};
423
425
  }
424
426
  const pathItem = paths[endpoint.path];
425
- const operation = createOperation(endpoint);
427
+ const tag = getTagFromPath(endpoint.path);
428
+ const operation = createOperation(endpoint, tag);
429
+ if (tag) {
430
+ tagSet.add(tag);
431
+ }
426
432
  pathItem[endpoint.method] = operation;
427
433
  if (endpoint.pathParams.length > 0 && !pathItem.parameters) {
428
434
  pathItem.parameters = endpoint.pathParams.map((param) => ({
@@ -433,6 +439,7 @@ function generateOpenAPISpec(endpoints, schemas, options = {}) {
433
439
  }));
434
440
  }
435
441
  }
442
+ const tags = [...tagSet].sort().map((name) => ({ name }));
436
443
  const spec = {
437
444
  openapi: "3.0.0",
438
445
  info: {
@@ -447,6 +454,9 @@ function generateOpenAPISpec(endpoints, schemas, options = {}) {
447
454
  if (baseUrl) {
448
455
  spec.servers = [{ url: baseUrl }];
449
456
  }
457
+ if (tags.length > 0) {
458
+ spec.tags = tags;
459
+ }
450
460
  if (schemas.size > 0) {
451
461
  spec.components = {
452
462
  schemas: Object.fromEntries(schemas)
@@ -454,7 +464,15 @@ function generateOpenAPISpec(endpoints, schemas, options = {}) {
454
464
  }
455
465
  return spec;
456
466
  }
457
- function createOperation(endpoint) {
467
+ function getTagFromPath(path2) {
468
+ const segments = path2.split("/").filter(Boolean);
469
+ const firstSegment = segments[0];
470
+ if (!firstSegment || firstSegment.startsWith("{")) {
471
+ return void 0;
472
+ }
473
+ return firstSegment;
474
+ }
475
+ function createOperation(endpoint, tag) {
458
476
  const operation = {
459
477
  responses: {
460
478
  "200": {
@@ -462,6 +480,9 @@ function createOperation(endpoint) {
462
480
  }
463
481
  }
464
482
  };
483
+ if (tag) {
484
+ operation.tags = [tag];
485
+ }
465
486
  if (hasContent(endpoint.responseSchema)) {
466
487
  operation.responses["200"].content = {
467
488
  "application/json": {
package/dist/cli.mjs CHANGED
@@ -61,7 +61,7 @@ function typeToSchema(type, ctx) {
61
61
  );
62
62
  const hasNull = type.types.some((t) => t.flags & ts.TypeFlags.Null);
63
63
  if (nonNullTypes.length === 1 && hasNull) {
64
- const schema = typeToSchema(nonNullTypes[0], ctx);
64
+ const schema = typeToSchema(nonNullTypes[0], { ...ctx, depth: ctx.depth + 1 });
65
65
  return { ...schema, nullable: true };
66
66
  }
67
67
  if (nonNullTypes.every((t) => t.isStringLiteral())) {
@@ -76,19 +76,20 @@ function typeToSchema(type, ctx) {
76
76
  enum: nonNullTypes.map((t) => t.value)
77
77
  };
78
78
  }
79
+ const nextCtx = { ...ctx, depth: ctx.depth + 1 };
79
80
  return {
80
- oneOf: nonNullTypes.map((t) => typeToSchema(t, ctx))
81
+ oneOf: nonNullTypes.map((t) => typeToSchema(t, nextCtx))
81
82
  };
82
83
  }
83
84
  if (type.isIntersection()) {
84
- return intersectionTypeToSchema(type, ctx);
85
+ return intersectionTypeToSchema(type, { ...ctx, depth: ctx.depth + 1 });
85
86
  }
86
87
  if (checker.isArrayType(type)) {
87
88
  const typeArgs = type.typeArguments;
88
89
  if (typeArgs?.[0]) {
89
90
  return {
90
91
  type: "array",
91
- items: typeToSchema(typeArgs[0], ctx)
92
+ items: typeToSchema(typeArgs[0], { ...ctx, depth: ctx.depth + 1 })
92
93
  };
93
94
  }
94
95
  return { type: "array" };
@@ -394,12 +395,17 @@ function formDataTypeToSchema(formDataType, ctx) {
394
395
  function generateOpenAPISpec(endpoints, schemas, options = {}) {
395
396
  const { title = "API", version = "1.0.0", description, baseUrl } = options;
396
397
  const paths = {};
398
+ const tagSet = /* @__PURE__ */ new Set();
397
399
  for (const endpoint of endpoints) {
398
400
  if (!paths[endpoint.path]) {
399
401
  paths[endpoint.path] = {};
400
402
  }
401
403
  const pathItem = paths[endpoint.path];
402
- const operation = createOperation(endpoint);
404
+ const tag = getTagFromPath(endpoint.path);
405
+ const operation = createOperation(endpoint, tag);
406
+ if (tag) {
407
+ tagSet.add(tag);
408
+ }
403
409
  pathItem[endpoint.method] = operation;
404
410
  if (endpoint.pathParams.length > 0 && !pathItem.parameters) {
405
411
  pathItem.parameters = endpoint.pathParams.map((param) => ({
@@ -410,6 +416,7 @@ function generateOpenAPISpec(endpoints, schemas, options = {}) {
410
416
  }));
411
417
  }
412
418
  }
419
+ const tags = [...tagSet].sort().map((name) => ({ name }));
413
420
  const spec = {
414
421
  openapi: "3.0.0",
415
422
  info: {
@@ -424,6 +431,9 @@ function generateOpenAPISpec(endpoints, schemas, options = {}) {
424
431
  if (baseUrl) {
425
432
  spec.servers = [{ url: baseUrl }];
426
433
  }
434
+ if (tags.length > 0) {
435
+ spec.tags = tags;
436
+ }
427
437
  if (schemas.size > 0) {
428
438
  spec.components = {
429
439
  schemas: Object.fromEntries(schemas)
@@ -431,7 +441,15 @@ function generateOpenAPISpec(endpoints, schemas, options = {}) {
431
441
  }
432
442
  return spec;
433
443
  }
434
- function createOperation(endpoint) {
444
+ function getTagFromPath(path2) {
445
+ const segments = path2.split("/").filter(Boolean);
446
+ const firstSegment = segments[0];
447
+ if (!firstSegment || firstSegment.startsWith("{")) {
448
+ return void 0;
449
+ }
450
+ return firstSegment;
451
+ }
452
+ function createOperation(endpoint, tag) {
435
453
  const operation = {
436
454
  responses: {
437
455
  "200": {
@@ -439,6 +457,9 @@ function createOperation(endpoint) {
439
457
  }
440
458
  }
441
459
  };
460
+ if (tag) {
461
+ operation.tags = [tag];
462
+ }
442
463
  if (hasContent(endpoint.responseSchema)) {
443
464
  operation.responses["200"].content = {
444
465
  "application/json": {
package/dist/index.d.mts CHANGED
@@ -56,6 +56,10 @@ type OpenAPIPathItem = {
56
56
  delete?: OpenAPIOperation;
57
57
  parameters?: OpenAPIParameter[];
58
58
  };
59
+ type OpenAPITag = {
60
+ name: string;
61
+ description?: string;
62
+ };
59
63
  type OpenAPISpec = {
60
64
  openapi: "3.0.0";
61
65
  info: {
@@ -67,6 +71,7 @@ type OpenAPISpec = {
67
71
  url: string;
68
72
  description?: string;
69
73
  }[];
74
+ tags?: OpenAPITag[];
70
75
  paths: Record<string, OpenAPIPathItem>;
71
76
  components?: {
72
77
  schemas?: Record<string, JSONSchema>;
@@ -105,4 +110,4 @@ type GeneratorOptions = {
105
110
  };
106
111
  declare function generateOpenAPISpec(endpoints: ParsedEndpoint[], schemas: Map<string, JSONSchema>, options?: GeneratorOptions): OpenAPISpec;
107
112
 
108
- export { type CLIOptions, type JSONSchema, type OpenAPIOperation, type OpenAPIParameter, type OpenAPIPathItem, type OpenAPIRequestBody, type OpenAPISpec, type ParsedEndpoint, generateOpenAPISpec, parseSchema };
113
+ export { type CLIOptions, type JSONSchema, type OpenAPIOperation, type OpenAPIParameter, type OpenAPIPathItem, type OpenAPIRequestBody, type OpenAPISpec, type OpenAPITag, type ParsedEndpoint, generateOpenAPISpec, parseSchema };
package/dist/index.d.ts CHANGED
@@ -56,6 +56,10 @@ type OpenAPIPathItem = {
56
56
  delete?: OpenAPIOperation;
57
57
  parameters?: OpenAPIParameter[];
58
58
  };
59
+ type OpenAPITag = {
60
+ name: string;
61
+ description?: string;
62
+ };
59
63
  type OpenAPISpec = {
60
64
  openapi: "3.0.0";
61
65
  info: {
@@ -67,6 +71,7 @@ type OpenAPISpec = {
67
71
  url: string;
68
72
  description?: string;
69
73
  }[];
74
+ tags?: OpenAPITag[];
70
75
  paths: Record<string, OpenAPIPathItem>;
71
76
  components?: {
72
77
  schemas?: Record<string, JSONSchema>;
@@ -105,4 +110,4 @@ type GeneratorOptions = {
105
110
  };
106
111
  declare function generateOpenAPISpec(endpoints: ParsedEndpoint[], schemas: Map<string, JSONSchema>, options?: GeneratorOptions): OpenAPISpec;
107
112
 
108
- export { type CLIOptions, type JSONSchema, type OpenAPIOperation, type OpenAPIParameter, type OpenAPIPathItem, type OpenAPIRequestBody, type OpenAPISpec, type ParsedEndpoint, generateOpenAPISpec, parseSchema };
113
+ export { type CLIOptions, type JSONSchema, type OpenAPIOperation, type OpenAPIParameter, type OpenAPIPathItem, type OpenAPIRequestBody, type OpenAPISpec, type OpenAPITag, type ParsedEndpoint, generateOpenAPISpec, parseSchema };
package/dist/index.js CHANGED
@@ -92,7 +92,7 @@ function typeToSchema(type, ctx) {
92
92
  );
93
93
  const hasNull = type.types.some((t) => t.flags & import_typescript.default.TypeFlags.Null);
94
94
  if (nonNullTypes.length === 1 && hasNull) {
95
- const schema = typeToSchema(nonNullTypes[0], ctx);
95
+ const schema = typeToSchema(nonNullTypes[0], { ...ctx, depth: ctx.depth + 1 });
96
96
  return { ...schema, nullable: true };
97
97
  }
98
98
  if (nonNullTypes.every((t) => t.isStringLiteral())) {
@@ -107,19 +107,20 @@ function typeToSchema(type, ctx) {
107
107
  enum: nonNullTypes.map((t) => t.value)
108
108
  };
109
109
  }
110
+ const nextCtx = { ...ctx, depth: ctx.depth + 1 };
110
111
  return {
111
- oneOf: nonNullTypes.map((t) => typeToSchema(t, ctx))
112
+ oneOf: nonNullTypes.map((t) => typeToSchema(t, nextCtx))
112
113
  };
113
114
  }
114
115
  if (type.isIntersection()) {
115
- return intersectionTypeToSchema(type, ctx);
116
+ return intersectionTypeToSchema(type, { ...ctx, depth: ctx.depth + 1 });
116
117
  }
117
118
  if (checker.isArrayType(type)) {
118
119
  const typeArgs = type.typeArguments;
119
120
  if (typeArgs?.[0]) {
120
121
  return {
121
122
  type: "array",
122
- items: typeToSchema(typeArgs[0], ctx)
123
+ items: typeToSchema(typeArgs[0], { ...ctx, depth: ctx.depth + 1 })
123
124
  };
124
125
  }
125
126
  return { type: "array" };
@@ -425,12 +426,17 @@ function formDataTypeToSchema(formDataType, ctx) {
425
426
  function generateOpenAPISpec(endpoints, schemas, options = {}) {
426
427
  const { title = "API", version = "1.0.0", description, baseUrl } = options;
427
428
  const paths = {};
429
+ const tagSet = /* @__PURE__ */ new Set();
428
430
  for (const endpoint of endpoints) {
429
431
  if (!paths[endpoint.path]) {
430
432
  paths[endpoint.path] = {};
431
433
  }
432
434
  const pathItem = paths[endpoint.path];
433
- const operation = createOperation(endpoint);
435
+ const tag = getTagFromPath(endpoint.path);
436
+ const operation = createOperation(endpoint, tag);
437
+ if (tag) {
438
+ tagSet.add(tag);
439
+ }
434
440
  pathItem[endpoint.method] = operation;
435
441
  if (endpoint.pathParams.length > 0 && !pathItem.parameters) {
436
442
  pathItem.parameters = endpoint.pathParams.map((param) => ({
@@ -441,6 +447,7 @@ function generateOpenAPISpec(endpoints, schemas, options = {}) {
441
447
  }));
442
448
  }
443
449
  }
450
+ const tags = [...tagSet].sort().map((name) => ({ name }));
444
451
  const spec = {
445
452
  openapi: "3.0.0",
446
453
  info: {
@@ -455,6 +462,9 @@ function generateOpenAPISpec(endpoints, schemas, options = {}) {
455
462
  if (baseUrl) {
456
463
  spec.servers = [{ url: baseUrl }];
457
464
  }
465
+ if (tags.length > 0) {
466
+ spec.tags = tags;
467
+ }
458
468
  if (schemas.size > 0) {
459
469
  spec.components = {
460
470
  schemas: Object.fromEntries(schemas)
@@ -462,7 +472,15 @@ function generateOpenAPISpec(endpoints, schemas, options = {}) {
462
472
  }
463
473
  return spec;
464
474
  }
465
- function createOperation(endpoint) {
475
+ function getTagFromPath(path2) {
476
+ const segments = path2.split("/").filter(Boolean);
477
+ const firstSegment = segments[0];
478
+ if (!firstSegment || firstSegment.startsWith("{")) {
479
+ return void 0;
480
+ }
481
+ return firstSegment;
482
+ }
483
+ function createOperation(endpoint, tag) {
466
484
  const operation = {
467
485
  responses: {
468
486
  "200": {
@@ -470,6 +488,9 @@ function createOperation(endpoint) {
470
488
  }
471
489
  }
472
490
  };
491
+ if (tag) {
492
+ operation.tags = [tag];
493
+ }
473
494
  if (hasContent(endpoint.responseSchema)) {
474
495
  operation.responses["200"].content = {
475
496
  "application/json": {
package/dist/index.mjs CHANGED
@@ -55,7 +55,7 @@ function typeToSchema(type, ctx) {
55
55
  );
56
56
  const hasNull = type.types.some((t) => t.flags & ts.TypeFlags.Null);
57
57
  if (nonNullTypes.length === 1 && hasNull) {
58
- const schema = typeToSchema(nonNullTypes[0], ctx);
58
+ const schema = typeToSchema(nonNullTypes[0], { ...ctx, depth: ctx.depth + 1 });
59
59
  return { ...schema, nullable: true };
60
60
  }
61
61
  if (nonNullTypes.every((t) => t.isStringLiteral())) {
@@ -70,19 +70,20 @@ function typeToSchema(type, ctx) {
70
70
  enum: nonNullTypes.map((t) => t.value)
71
71
  };
72
72
  }
73
+ const nextCtx = { ...ctx, depth: ctx.depth + 1 };
73
74
  return {
74
- oneOf: nonNullTypes.map((t) => typeToSchema(t, ctx))
75
+ oneOf: nonNullTypes.map((t) => typeToSchema(t, nextCtx))
75
76
  };
76
77
  }
77
78
  if (type.isIntersection()) {
78
- return intersectionTypeToSchema(type, ctx);
79
+ return intersectionTypeToSchema(type, { ...ctx, depth: ctx.depth + 1 });
79
80
  }
80
81
  if (checker.isArrayType(type)) {
81
82
  const typeArgs = type.typeArguments;
82
83
  if (typeArgs?.[0]) {
83
84
  return {
84
85
  type: "array",
85
- items: typeToSchema(typeArgs[0], ctx)
86
+ items: typeToSchema(typeArgs[0], { ...ctx, depth: ctx.depth + 1 })
86
87
  };
87
88
  }
88
89
  return { type: "array" };
@@ -388,12 +389,17 @@ function formDataTypeToSchema(formDataType, ctx) {
388
389
  function generateOpenAPISpec(endpoints, schemas, options = {}) {
389
390
  const { title = "API", version = "1.0.0", description, baseUrl } = options;
390
391
  const paths = {};
392
+ const tagSet = /* @__PURE__ */ new Set();
391
393
  for (const endpoint of endpoints) {
392
394
  if (!paths[endpoint.path]) {
393
395
  paths[endpoint.path] = {};
394
396
  }
395
397
  const pathItem = paths[endpoint.path];
396
- const operation = createOperation(endpoint);
398
+ const tag = getTagFromPath(endpoint.path);
399
+ const operation = createOperation(endpoint, tag);
400
+ if (tag) {
401
+ tagSet.add(tag);
402
+ }
397
403
  pathItem[endpoint.method] = operation;
398
404
  if (endpoint.pathParams.length > 0 && !pathItem.parameters) {
399
405
  pathItem.parameters = endpoint.pathParams.map((param) => ({
@@ -404,6 +410,7 @@ function generateOpenAPISpec(endpoints, schemas, options = {}) {
404
410
  }));
405
411
  }
406
412
  }
413
+ const tags = [...tagSet].sort().map((name) => ({ name }));
407
414
  const spec = {
408
415
  openapi: "3.0.0",
409
416
  info: {
@@ -418,6 +425,9 @@ function generateOpenAPISpec(endpoints, schemas, options = {}) {
418
425
  if (baseUrl) {
419
426
  spec.servers = [{ url: baseUrl }];
420
427
  }
428
+ if (tags.length > 0) {
429
+ spec.tags = tags;
430
+ }
421
431
  if (schemas.size > 0) {
422
432
  spec.components = {
423
433
  schemas: Object.fromEntries(schemas)
@@ -425,7 +435,15 @@ function generateOpenAPISpec(endpoints, schemas, options = {}) {
425
435
  }
426
436
  return spec;
427
437
  }
428
- function createOperation(endpoint) {
438
+ function getTagFromPath(path2) {
439
+ const segments = path2.split("/").filter(Boolean);
440
+ const firstSegment = segments[0];
441
+ if (!firstSegment || firstSegment.startsWith("{")) {
442
+ return void 0;
443
+ }
444
+ return firstSegment;
445
+ }
446
+ function createOperation(endpoint, tag) {
429
447
  const operation = {
430
448
  responses: {
431
449
  "200": {
@@ -433,6 +451,9 @@ function createOperation(endpoint) {
433
451
  }
434
452
  }
435
453
  };
454
+ if (tag) {
455
+ operation.tags = [tag];
456
+ }
436
457
  if (hasContent(endpoint.responseSchema)) {
437
458
  operation.responses["200"].content = {
438
459
  "application/json": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "enlace-openapi",
3
- "version": "0.0.1-beta.4",
3
+ "version": "0.0.1-beta.6",
4
4
  "license": "MIT",
5
5
  "bin": {
6
6
  "enlace-openapi": "./dist/cli.mjs"