sprint-es 0.0.62 → 0.0.65
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 +64 -15
- package/dist/esm/index.js +64 -15
- package/dist/types/sprint.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/cjs/index.cjs
CHANGED
|
@@ -167,12 +167,15 @@ class Sprint {
|
|
|
167
167
|
res.json(this.generateOpenAPISpec());
|
|
168
168
|
});
|
|
169
169
|
if (this.openapi.swaggerUi.enabled) {
|
|
170
|
+
console.log(`[Sprint] Loading Swagger UI...`);
|
|
170
171
|
import("swagger-ui-express").then((swaggerUi) => {
|
|
172
|
+
console.log(`[Sprint] Swagger UI imported successfully`);
|
|
171
173
|
this.app.use("/swagger", swaggerUi.serve, swaggerUi.setup(void 0, {
|
|
172
174
|
swaggerUrl: "/openapi.json"
|
|
173
175
|
}));
|
|
174
|
-
|
|
175
|
-
|
|
176
|
+
console.log(`[Sprint] Swagger UI mounted at /swagger`);
|
|
177
|
+
}).catch((err) => {
|
|
178
|
+
console.error(`[Sprint] ⚠️ swagger-ui-express error:`, err);
|
|
176
179
|
});
|
|
177
180
|
}
|
|
178
181
|
}
|
|
@@ -181,7 +184,7 @@ class Sprint {
|
|
|
181
184
|
});
|
|
182
185
|
}
|
|
183
186
|
async init() {
|
|
184
|
-
const callerDir = process.
|
|
187
|
+
const callerDir = process.cwd();
|
|
185
188
|
try {
|
|
186
189
|
const middlewaresCandidate = path.isAbsolute(this.middlewaresPath) ? this.middlewaresPath : path.join(callerDir, this.middlewaresPath);
|
|
187
190
|
if (fs.existsSync(middlewaresCandidate) && fs.statSync(middlewaresCandidate).isDirectory()) await this.loadMiddlewares(middlewaresCandidate);
|
|
@@ -191,8 +194,11 @@ class Sprint {
|
|
|
191
194
|
}
|
|
192
195
|
try {
|
|
193
196
|
const routesCandidate = path.isAbsolute(this.routesPath) ? this.routesPath : path.join(callerDir, this.routesPath);
|
|
194
|
-
|
|
195
|
-
|
|
197
|
+
console.log(`[Sprint] Looking for routes at: ${routesCandidate}`);
|
|
198
|
+
if (fs.existsSync(routesCandidate) && fs.statSync(routesCandidate).isDirectory()) {
|
|
199
|
+
console.log(`[Sprint] Routes directory found, loading...`);
|
|
200
|
+
await this.loadRoutes(routesCandidate);
|
|
201
|
+
} else console.log(`[Sprint] Routes folder not found at: ${routesCandidate}, skipping route loading.`);
|
|
196
202
|
} catch (err) {
|
|
197
203
|
console.error("[Sprint] Failed to load routes:", err);
|
|
198
204
|
}
|
|
@@ -333,17 +339,24 @@ class Sprint {
|
|
|
333
339
|
if (!layer.route) continue;
|
|
334
340
|
const route = layer.route;
|
|
335
341
|
for (const routeLayer of route.stack) {
|
|
336
|
-
const
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
342
|
+
const handlers = Array.isArray(routeLayer.handle) ? routeLayer.handle : [routeLayer.handle];
|
|
343
|
+
for (const handler of handlers) {
|
|
344
|
+
const schema = handler.__sprintRouteSchema;
|
|
345
|
+
if (schema) {
|
|
346
|
+
const method = (routeLayer.method || "").toUpperCase();
|
|
347
|
+
if (method) {
|
|
348
|
+
this.registeredRoutes.push({
|
|
349
|
+
method,
|
|
350
|
+
path: finalRoute + route.path,
|
|
351
|
+
schema
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
break;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
345
357
|
}
|
|
346
358
|
}
|
|
359
|
+
console.log(`[Sprint] Registered routes for OpenAPI:`, this.registeredRoutes);
|
|
347
360
|
}
|
|
348
361
|
const routeMiddlewares = this.getMiddlewaresForRoute(routePath);
|
|
349
362
|
if (routeMiddlewares.length > 0) {
|
|
@@ -415,10 +428,16 @@ class Sprint {
|
|
|
415
428
|
}
|
|
416
429
|
generateOpenAPISpec() {
|
|
417
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
|
+
}
|
|
418
437
|
for (const route of this.registeredRoutes || []) {
|
|
419
438
|
const method = route.method.toLowerCase();
|
|
420
439
|
if (!paths[route.path]) paths[route.path] = {};
|
|
421
|
-
|
|
440
|
+
const routeSpec = {
|
|
422
441
|
summary: "Auto generated by Sprint",
|
|
423
442
|
responses: {
|
|
424
443
|
"200": {
|
|
@@ -426,6 +445,36 @@ class Sprint {
|
|
|
426
445
|
}
|
|
427
446
|
}
|
|
428
447
|
};
|
|
448
|
+
if (route.schema?.body && zod) {
|
|
449
|
+
try {
|
|
450
|
+
routeSpec.requestBody = {
|
|
451
|
+
content: {
|
|
452
|
+
"application/json": {
|
|
453
|
+
schema: route.schema.body.schema || route.schema.body._def?.schema?.toJSON?.() || {}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
};
|
|
457
|
+
} catch (e) {
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
if (route.schema?.queryParams && zod) {
|
|
461
|
+
try {
|
|
462
|
+
routeSpec.parameters = [];
|
|
463
|
+
const querySchema = route.schema.queryParams.schema || route.schema.queryParams._def?.schema;
|
|
464
|
+
if (querySchema?.shape) {
|
|
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
|
+
}
|
|
473
|
+
}
|
|
474
|
+
} catch (e) {
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
paths[route.path][method] = routeSpec;
|
|
429
478
|
}
|
|
430
479
|
return {
|
|
431
480
|
openapi: "3.0.0",
|
package/dist/esm/index.js
CHANGED
|
@@ -142,12 +142,15 @@ class Sprint {
|
|
|
142
142
|
res.json(this.generateOpenAPISpec());
|
|
143
143
|
});
|
|
144
144
|
if (this.openapi.swaggerUi.enabled) {
|
|
145
|
+
console.log(`[Sprint] Loading Swagger UI...`);
|
|
145
146
|
import("swagger-ui-express").then((swaggerUi) => {
|
|
147
|
+
console.log(`[Sprint] Swagger UI imported successfully`);
|
|
146
148
|
this.app.use("/swagger", swaggerUi.serve, swaggerUi.setup(void 0, {
|
|
147
149
|
swaggerUrl: "/openapi.json"
|
|
148
150
|
}));
|
|
149
|
-
|
|
150
|
-
|
|
151
|
+
console.log(`[Sprint] Swagger UI mounted at /swagger`);
|
|
152
|
+
}).catch((err) => {
|
|
153
|
+
console.error(`[Sprint] ⚠️ swagger-ui-express error:`, err);
|
|
151
154
|
});
|
|
152
155
|
}
|
|
153
156
|
}
|
|
@@ -156,7 +159,7 @@ class Sprint {
|
|
|
156
159
|
});
|
|
157
160
|
}
|
|
158
161
|
async init() {
|
|
159
|
-
const callerDir = process.
|
|
162
|
+
const callerDir = process.cwd();
|
|
160
163
|
try {
|
|
161
164
|
const middlewaresCandidate = path.isAbsolute(this.middlewaresPath) ? this.middlewaresPath : path.join(callerDir, this.middlewaresPath);
|
|
162
165
|
if (fs.existsSync(middlewaresCandidate) && fs.statSync(middlewaresCandidate).isDirectory()) await this.loadMiddlewares(middlewaresCandidate);
|
|
@@ -166,8 +169,11 @@ class Sprint {
|
|
|
166
169
|
}
|
|
167
170
|
try {
|
|
168
171
|
const routesCandidate = path.isAbsolute(this.routesPath) ? this.routesPath : path.join(callerDir, this.routesPath);
|
|
169
|
-
|
|
170
|
-
|
|
172
|
+
console.log(`[Sprint] Looking for routes at: ${routesCandidate}`);
|
|
173
|
+
if (fs.existsSync(routesCandidate) && fs.statSync(routesCandidate).isDirectory()) {
|
|
174
|
+
console.log(`[Sprint] Routes directory found, loading...`);
|
|
175
|
+
await this.loadRoutes(routesCandidate);
|
|
176
|
+
} else console.log(`[Sprint] Routes folder not found at: ${routesCandidate}, skipping route loading.`);
|
|
171
177
|
} catch (err) {
|
|
172
178
|
console.error("[Sprint] Failed to load routes:", err);
|
|
173
179
|
}
|
|
@@ -308,17 +314,24 @@ class Sprint {
|
|
|
308
314
|
if (!layer.route) continue;
|
|
309
315
|
const route = layer.route;
|
|
310
316
|
for (const routeLayer of route.stack) {
|
|
311
|
-
const
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
317
|
+
const handlers = Array.isArray(routeLayer.handle) ? routeLayer.handle : [routeLayer.handle];
|
|
318
|
+
for (const handler of handlers) {
|
|
319
|
+
const schema = handler.__sprintRouteSchema;
|
|
320
|
+
if (schema) {
|
|
321
|
+
const method = (routeLayer.method || "").toUpperCase();
|
|
322
|
+
if (method) {
|
|
323
|
+
this.registeredRoutes.push({
|
|
324
|
+
method,
|
|
325
|
+
path: finalRoute + route.path,
|
|
326
|
+
schema
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
break;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
320
332
|
}
|
|
321
333
|
}
|
|
334
|
+
console.log(`[Sprint] Registered routes for OpenAPI:`, this.registeredRoutes);
|
|
322
335
|
}
|
|
323
336
|
const routeMiddlewares = this.getMiddlewaresForRoute(routePath);
|
|
324
337
|
if (routeMiddlewares.length > 0) {
|
|
@@ -390,10 +403,16 @@ class Sprint {
|
|
|
390
403
|
}
|
|
391
404
|
generateOpenAPISpec() {
|
|
392
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
|
+
}
|
|
393
412
|
for (const route of this.registeredRoutes || []) {
|
|
394
413
|
const method = route.method.toLowerCase();
|
|
395
414
|
if (!paths[route.path]) paths[route.path] = {};
|
|
396
|
-
|
|
415
|
+
const routeSpec = {
|
|
397
416
|
summary: "Auto generated by Sprint",
|
|
398
417
|
responses: {
|
|
399
418
|
"200": {
|
|
@@ -401,6 +420,36 @@ class Sprint {
|
|
|
401
420
|
}
|
|
402
421
|
}
|
|
403
422
|
};
|
|
423
|
+
if (route.schema?.body && zod) {
|
|
424
|
+
try {
|
|
425
|
+
routeSpec.requestBody = {
|
|
426
|
+
content: {
|
|
427
|
+
"application/json": {
|
|
428
|
+
schema: route.schema.body.schema || route.schema.body._def?.schema?.toJSON?.() || {}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
};
|
|
432
|
+
} catch (e) {
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
if (route.schema?.queryParams && zod) {
|
|
436
|
+
try {
|
|
437
|
+
routeSpec.parameters = [];
|
|
438
|
+
const querySchema = route.schema.queryParams.schema || route.schema.queryParams._def?.schema;
|
|
439
|
+
if (querySchema?.shape) {
|
|
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
|
+
}
|
|
448
|
+
}
|
|
449
|
+
} catch (e) {
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
paths[route.path][method] = routeSpec;
|
|
404
453
|
}
|
|
405
454
|
return {
|
|
406
455
|
openapi: "3.0.0",
|
|
@@ -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;;YAuEM,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;IAyEpB,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"}
|