sprint-es 0.0.65 → 0.0.66
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/cjs/index.cjs +81 -28
- package/dist/esm/index.js +81 -28
- package/dist/types/sprint.d.ts +2 -0
- package/dist/types/sprint.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/cjs/index.cjs
CHANGED
|
@@ -163,9 +163,6 @@ class Sprint {
|
|
|
163
163
|
this.routesLoaded = this.init();
|
|
164
164
|
this.routesLoaded.then(() => {
|
|
165
165
|
if (this.openapi.generateOnBuild) {
|
|
166
|
-
this.app.get("/openapi.json", (_, res) => {
|
|
167
|
-
res.json(this.generateOpenAPISpec());
|
|
168
|
-
});
|
|
169
166
|
if (this.openapi.swaggerUi.enabled) {
|
|
170
167
|
console.log(`[Sprint] Loading Swagger UI...`);
|
|
171
168
|
import("swagger-ui-express").then((swaggerUi) => {
|
|
@@ -178,6 +175,9 @@ class Sprint {
|
|
|
178
175
|
console.error(`[Sprint] ⚠️ swagger-ui-express error:`, err);
|
|
179
176
|
});
|
|
180
177
|
}
|
|
178
|
+
this.app.get("/openapi.json", (_, res) => {
|
|
179
|
+
res.json(this.generateOpenAPISpec());
|
|
180
|
+
});
|
|
181
181
|
}
|
|
182
182
|
if (finalConfig.autoListen) this.listen();
|
|
183
183
|
});
|
|
@@ -428,12 +428,6 @@ class Sprint {
|
|
|
428
428
|
}
|
|
429
429
|
generateOpenAPISpec() {
|
|
430
430
|
const paths = {};
|
|
431
|
-
let zod;
|
|
432
|
-
try {
|
|
433
|
-
zod = require("zod");
|
|
434
|
-
} catch (e) {
|
|
435
|
-
console.warn("[Sprint] Zod not available for OpenAPI schema generation");
|
|
436
|
-
}
|
|
437
431
|
for (const route of this.registeredRoutes || []) {
|
|
438
432
|
const method = route.method.toLowerCase();
|
|
439
433
|
if (!paths[route.path]) paths[route.path] = {};
|
|
@@ -445,33 +439,30 @@ class Sprint {
|
|
|
445
439
|
}
|
|
446
440
|
}
|
|
447
441
|
};
|
|
448
|
-
if (route.schema?.body
|
|
442
|
+
if (route.schema?.body) {
|
|
449
443
|
try {
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
444
|
+
const bodySchema = this.zodSchemaToOpenAPI(route.schema.body);
|
|
445
|
+
if (Object.keys(bodySchema).length > 0) {
|
|
446
|
+
routeSpec.requestBody = {
|
|
447
|
+
content: {
|
|
448
|
+
"application/json": {
|
|
449
|
+
schema: bodySchema
|
|
450
|
+
}
|
|
454
451
|
}
|
|
455
|
-
}
|
|
456
|
-
}
|
|
452
|
+
};
|
|
453
|
+
}
|
|
457
454
|
} catch (e) {
|
|
455
|
+
console.warn("[Sprint] Failed to convert body schema:", e);
|
|
458
456
|
}
|
|
459
457
|
}
|
|
460
|
-
if (route.schema?.queryParams
|
|
458
|
+
if (route.schema?.queryParams) {
|
|
461
459
|
try {
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
for (const [key, value] of Object.entries(querySchema.shape)) {
|
|
466
|
-
routeSpec.parameters.push({
|
|
467
|
-
name: key,
|
|
468
|
-
in: "query",
|
|
469
|
-
required: !value.isOptional?.(),
|
|
470
|
-
schema: value._def?.typeName ? { type: "string" } : {}
|
|
471
|
-
});
|
|
472
|
-
}
|
|
460
|
+
const params = this.zodParamsToOpenAPI(route.schema.queryParams);
|
|
461
|
+
if (params.length > 0) {
|
|
462
|
+
routeSpec.parameters = params;
|
|
473
463
|
}
|
|
474
464
|
} catch (e) {
|
|
465
|
+
console.warn("[Sprint] Failed to convert query params schema:", e);
|
|
475
466
|
}
|
|
476
467
|
}
|
|
477
468
|
paths[route.path][method] = routeSpec;
|
|
@@ -485,6 +476,68 @@ class Sprint {
|
|
|
485
476
|
paths
|
|
486
477
|
};
|
|
487
478
|
}
|
|
479
|
+
zodSchemaToOpenAPI(schema) {
|
|
480
|
+
if (!schema) return {};
|
|
481
|
+
if (schema._def?.typeName === "ZodObject" || schema.shape) {
|
|
482
|
+
const shape = schema.shape || schema._def?.shape();
|
|
483
|
+
if (!shape) return {};
|
|
484
|
+
const properties = {};
|
|
485
|
+
const required = [];
|
|
486
|
+
for (const [key, value] of Object.entries(shape)) {
|
|
487
|
+
const zodDef = value._def;
|
|
488
|
+
const typeName = zodDef?.typeName;
|
|
489
|
+
let propSchema = {};
|
|
490
|
+
if (typeName === "ZodString") {
|
|
491
|
+
propSchema = { type: "string" };
|
|
492
|
+
} else if (typeName === "ZodNumber") {
|
|
493
|
+
propSchema = { type: "number" };
|
|
494
|
+
} else if (typeName === "ZodBoolean") {
|
|
495
|
+
propSchema = { type: "boolean" };
|
|
496
|
+
} else if (typeName === "ZodArray") {
|
|
497
|
+
propSchema = { type: "array", items: this.zodSchemaToOpenAPI(zodDef?.type) };
|
|
498
|
+
} else if (typeName === "ZodObject") {
|
|
499
|
+
propSchema = this.zodSchemaToOpenAPI(zodDef?.type);
|
|
500
|
+
} else if (typeName === "ZodOptional") {
|
|
501
|
+
continue;
|
|
502
|
+
} else {
|
|
503
|
+
propSchema = { type: "string" };
|
|
504
|
+
}
|
|
505
|
+
properties[key] = propSchema;
|
|
506
|
+
if (!zodDef?.isOptional && typeName !== "ZodOptional") {
|
|
507
|
+
required.push(key);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
return { type: "object", properties, required: required.length > 0 ? required : void 0 };
|
|
511
|
+
}
|
|
512
|
+
return {};
|
|
513
|
+
}
|
|
514
|
+
zodParamsToOpenAPI(schema) {
|
|
515
|
+
if (!schema) return [];
|
|
516
|
+
const params = [];
|
|
517
|
+
const shape = schema.shape || schema._def?.shape();
|
|
518
|
+
if (!shape) return [];
|
|
519
|
+
for (const [key, value] of Object.entries(shape)) {
|
|
520
|
+
const zodDef = value._def;
|
|
521
|
+
const typeName = zodDef?.typeName;
|
|
522
|
+
let paramSchema = {};
|
|
523
|
+
if (typeName === "ZodString") {
|
|
524
|
+
paramSchema = { type: "string" };
|
|
525
|
+
} else if (typeName === "ZodNumber") {
|
|
526
|
+
paramSchema = { type: "number" };
|
|
527
|
+
} else if (typeName === "ZodBoolean") {
|
|
528
|
+
paramSchema = { type: "boolean" };
|
|
529
|
+
} else {
|
|
530
|
+
paramSchema = { type: "string" };
|
|
531
|
+
}
|
|
532
|
+
params.push({
|
|
533
|
+
name: key,
|
|
534
|
+
in: "query",
|
|
535
|
+
required: !zodDef?.isOptional,
|
|
536
|
+
schema: paramSchema
|
|
537
|
+
});
|
|
538
|
+
}
|
|
539
|
+
return params;
|
|
540
|
+
}
|
|
488
541
|
// HTTP Methods (prefix is applied automatically).
|
|
489
542
|
get(path2, handler) {
|
|
490
543
|
return this.app.get(this.applyPrefix(path2), handler);
|
package/dist/esm/index.js
CHANGED
|
@@ -138,9 +138,6 @@ class Sprint {
|
|
|
138
138
|
this.routesLoaded = this.init();
|
|
139
139
|
this.routesLoaded.then(() => {
|
|
140
140
|
if (this.openapi.generateOnBuild) {
|
|
141
|
-
this.app.get("/openapi.json", (_, res) => {
|
|
142
|
-
res.json(this.generateOpenAPISpec());
|
|
143
|
-
});
|
|
144
141
|
if (this.openapi.swaggerUi.enabled) {
|
|
145
142
|
console.log(`[Sprint] Loading Swagger UI...`);
|
|
146
143
|
import("swagger-ui-express").then((swaggerUi) => {
|
|
@@ -153,6 +150,9 @@ class Sprint {
|
|
|
153
150
|
console.error(`[Sprint] ⚠️ swagger-ui-express error:`, err);
|
|
154
151
|
});
|
|
155
152
|
}
|
|
153
|
+
this.app.get("/openapi.json", (_, res) => {
|
|
154
|
+
res.json(this.generateOpenAPISpec());
|
|
155
|
+
});
|
|
156
156
|
}
|
|
157
157
|
if (finalConfig.autoListen) this.listen();
|
|
158
158
|
});
|
|
@@ -403,12 +403,6 @@ class Sprint {
|
|
|
403
403
|
}
|
|
404
404
|
generateOpenAPISpec() {
|
|
405
405
|
const paths = {};
|
|
406
|
-
let zod;
|
|
407
|
-
try {
|
|
408
|
-
zod = require("zod");
|
|
409
|
-
} catch (e) {
|
|
410
|
-
console.warn("[Sprint] Zod not available for OpenAPI schema generation");
|
|
411
|
-
}
|
|
412
406
|
for (const route of this.registeredRoutes || []) {
|
|
413
407
|
const method = route.method.toLowerCase();
|
|
414
408
|
if (!paths[route.path]) paths[route.path] = {};
|
|
@@ -420,33 +414,30 @@ class Sprint {
|
|
|
420
414
|
}
|
|
421
415
|
}
|
|
422
416
|
};
|
|
423
|
-
if (route.schema?.body
|
|
417
|
+
if (route.schema?.body) {
|
|
424
418
|
try {
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
419
|
+
const bodySchema = this.zodSchemaToOpenAPI(route.schema.body);
|
|
420
|
+
if (Object.keys(bodySchema).length > 0) {
|
|
421
|
+
routeSpec.requestBody = {
|
|
422
|
+
content: {
|
|
423
|
+
"application/json": {
|
|
424
|
+
schema: bodySchema
|
|
425
|
+
}
|
|
429
426
|
}
|
|
430
|
-
}
|
|
431
|
-
}
|
|
427
|
+
};
|
|
428
|
+
}
|
|
432
429
|
} catch (e) {
|
|
430
|
+
console.warn("[Sprint] Failed to convert body schema:", e);
|
|
433
431
|
}
|
|
434
432
|
}
|
|
435
|
-
if (route.schema?.queryParams
|
|
433
|
+
if (route.schema?.queryParams) {
|
|
436
434
|
try {
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
for (const [key, value] of Object.entries(querySchema.shape)) {
|
|
441
|
-
routeSpec.parameters.push({
|
|
442
|
-
name: key,
|
|
443
|
-
in: "query",
|
|
444
|
-
required: !value.isOptional?.(),
|
|
445
|
-
schema: value._def?.typeName ? { type: "string" } : {}
|
|
446
|
-
});
|
|
447
|
-
}
|
|
435
|
+
const params = this.zodParamsToOpenAPI(route.schema.queryParams);
|
|
436
|
+
if (params.length > 0) {
|
|
437
|
+
routeSpec.parameters = params;
|
|
448
438
|
}
|
|
449
439
|
} catch (e) {
|
|
440
|
+
console.warn("[Sprint] Failed to convert query params schema:", e);
|
|
450
441
|
}
|
|
451
442
|
}
|
|
452
443
|
paths[route.path][method] = routeSpec;
|
|
@@ -460,6 +451,68 @@ class Sprint {
|
|
|
460
451
|
paths
|
|
461
452
|
};
|
|
462
453
|
}
|
|
454
|
+
zodSchemaToOpenAPI(schema) {
|
|
455
|
+
if (!schema) return {};
|
|
456
|
+
if (schema._def?.typeName === "ZodObject" || schema.shape) {
|
|
457
|
+
const shape = schema.shape || schema._def?.shape();
|
|
458
|
+
if (!shape) return {};
|
|
459
|
+
const properties = {};
|
|
460
|
+
const required = [];
|
|
461
|
+
for (const [key, value] of Object.entries(shape)) {
|
|
462
|
+
const zodDef = value._def;
|
|
463
|
+
const typeName = zodDef?.typeName;
|
|
464
|
+
let propSchema = {};
|
|
465
|
+
if (typeName === "ZodString") {
|
|
466
|
+
propSchema = { type: "string" };
|
|
467
|
+
} else if (typeName === "ZodNumber") {
|
|
468
|
+
propSchema = { type: "number" };
|
|
469
|
+
} else if (typeName === "ZodBoolean") {
|
|
470
|
+
propSchema = { type: "boolean" };
|
|
471
|
+
} else if (typeName === "ZodArray") {
|
|
472
|
+
propSchema = { type: "array", items: this.zodSchemaToOpenAPI(zodDef?.type) };
|
|
473
|
+
} else if (typeName === "ZodObject") {
|
|
474
|
+
propSchema = this.zodSchemaToOpenAPI(zodDef?.type);
|
|
475
|
+
} else if (typeName === "ZodOptional") {
|
|
476
|
+
continue;
|
|
477
|
+
} else {
|
|
478
|
+
propSchema = { type: "string" };
|
|
479
|
+
}
|
|
480
|
+
properties[key] = propSchema;
|
|
481
|
+
if (!zodDef?.isOptional && typeName !== "ZodOptional") {
|
|
482
|
+
required.push(key);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
return { type: "object", properties, required: required.length > 0 ? required : void 0 };
|
|
486
|
+
}
|
|
487
|
+
return {};
|
|
488
|
+
}
|
|
489
|
+
zodParamsToOpenAPI(schema) {
|
|
490
|
+
if (!schema) return [];
|
|
491
|
+
const params = [];
|
|
492
|
+
const shape = schema.shape || schema._def?.shape();
|
|
493
|
+
if (!shape) return [];
|
|
494
|
+
for (const [key, value] of Object.entries(shape)) {
|
|
495
|
+
const zodDef = value._def;
|
|
496
|
+
const typeName = zodDef?.typeName;
|
|
497
|
+
let paramSchema = {};
|
|
498
|
+
if (typeName === "ZodString") {
|
|
499
|
+
paramSchema = { type: "string" };
|
|
500
|
+
} else if (typeName === "ZodNumber") {
|
|
501
|
+
paramSchema = { type: "number" };
|
|
502
|
+
} else if (typeName === "ZodBoolean") {
|
|
503
|
+
paramSchema = { type: "boolean" };
|
|
504
|
+
} else {
|
|
505
|
+
paramSchema = { type: "string" };
|
|
506
|
+
}
|
|
507
|
+
params.push({
|
|
508
|
+
name: key,
|
|
509
|
+
in: "query",
|
|
510
|
+
required: !zodDef?.isOptional,
|
|
511
|
+
schema: paramSchema
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
return params;
|
|
515
|
+
}
|
|
463
516
|
// HTTP Methods (prefix is applied automatically).
|
|
464
517
|
get(path2, handler) {
|
|
465
518
|
return this.app.get(this.applyPrefix(path2), handler);
|
package/dist/types/sprint.d.ts
CHANGED
|
@@ -34,6 +34,8 @@ export declare class Sprint {
|
|
|
34
34
|
/** Applies prefix to a path */
|
|
35
35
|
private applyPrefix;
|
|
36
36
|
private generateOpenAPISpec;
|
|
37
|
+
private zodSchemaToOpenAPI;
|
|
38
|
+
private zodParamsToOpenAPI;
|
|
37
39
|
get(path: string, handler: Handler): express.Application;
|
|
38
40
|
post(path: string, handler: Handler): express.Application;
|
|
39
41
|
put(path: string, handler: Handler): express.Application;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sprint.d.ts","sourceRoot":"","sources":["../../src/sprint.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,OAAO,EAA+B,gBAAgB,EAAoB,MAAM,SAAS,CAAC;AACnG,OAAO,OAAO,EAAE,EAAE,WAAW,EAAoD,MAAM,SAAS,CAAC;AAejG,eAAO,MAAM,aAAa,SAAQ,CAAC;AACnC,eAAO,MAAM,YAAY,SAAS,CAAC;AAwCnC,qBAAa,MAAM;IACR,GAAG,EAAE,WAAW,CAAC;IACxB,OAAO,CAAC,IAAI,CAAwD;IACpE,OAAO,CAAC,UAAU,CAAsB;IACxC,OAAO,CAAC,eAAe,CAA2B;IAClD,OAAO,CAAC,YAAY,CAAwB;IAC5C,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,YAAY,CAAiB;IACrC,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,iBAAiB,CAA0B;IACnD,OAAO,CAAC,OAAO,CAUb;IACF,OAAO,CAAC,gBAAgB,CAIhB;;
|
|
1
|
+
{"version":3,"file":"sprint.d.ts","sourceRoot":"","sources":["../../src/sprint.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,OAAO,EAA+B,gBAAgB,EAAoB,MAAM,SAAS,CAAC;AACnG,OAAO,OAAO,EAAE,EAAE,WAAW,EAAoD,MAAM,SAAS,CAAC;AAejG,eAAO,MAAM,aAAa,SAAQ,CAAC;AACnC,eAAO,MAAM,YAAY,SAAS,CAAC;AAwCnC,qBAAa,MAAM;IACR,GAAG,EAAE,WAAW,CAAC;IACxB,OAAO,CAAC,IAAI,CAAwD;IACpE,OAAO,CAAC,UAAU,CAAsB;IACxC,OAAO,CAAC,eAAe,CAA2B;IAClD,OAAO,CAAC,YAAY,CAAwB;IAC5C,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,YAAY,CAAiB;IACrC,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,iBAAiB,CAA0B;IACnD,OAAO,CAAC,OAAO,CAUb;IACF,OAAO,CAAC,gBAAgB,CAIhB;;YAwEM,IAAI;IAkClB,OAAO,CAAC,YAAY;IAiDpB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IA4B9B;;OAEG;YACW,eAAe;IAgC7B,OAAO,CAAC,eAAe;YAcT,UAAU;YAoFV,YAAY;IAmB1B,OAAO,CAAC,YAAY;IAgCpB,+BAA+B;IAC/B,OAAO,CAAC,WAAW;IAKnB,OAAO,CAAC,mBAAmB;IA4D3B,OAAO,CAAC,kBAAkB;IAgD1B,OAAO,CAAC,kBAAkB;IAoCnB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IAClC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IACnC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IAClC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IACrC,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IACpC,GAAG,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,GAAG,gBAAgB,EAAE,YAAY,CAAC,EAAE,OAAO;IAYlF,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,IAAI,GAAG,IAAI;CA0DzC"}
|