azurajs 3.0.2 → 3.0.4
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/README.md +32 -0
- package/dist/IpResolver-BVgnGnpf.d.mts +5 -0
- package/dist/IpResolver-BVgnGnpf.d.ts +5 -0
- package/dist/SwaggerPlugin-C0UZTjaZ.d.ts +6 -0
- package/dist/SwaggerPlugin-wr9S4SRG.d.mts +6 -0
- package/dist/cookies/index.d.mts +7 -0
- package/dist/cookies/index.d.ts +7 -0
- package/dist/cookies/index.js +38 -0
- package/dist/cookies/index.js.map +1 -0
- package/dist/cookies/index.mjs +35 -0
- package/dist/cookies/index.mjs.map +1 -0
- package/dist/core/index.d.mts +18 -27
- package/dist/core/index.d.ts +18 -27
- package/dist/core/index.js +214 -14
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +214 -14
- package/dist/core/index.mjs.map +1 -1
- package/dist/cors/index.d.mts +7 -0
- package/dist/cors/index.d.ts +7 -0
- package/dist/cors/index.js +52 -0
- package/dist/cors/index.js.map +1 -0
- package/dist/cors/index.mjs +50 -0
- package/dist/cors/index.mjs.map +1 -0
- package/dist/decorators/index.d.mts +2 -0
- package/dist/decorators/index.d.ts +2 -0
- package/dist/decorators/index.js +25 -0
- package/dist/decorators/index.js.map +1 -1
- package/dist/decorators/index.mjs +24 -1
- package/dist/decorators/index.mjs.map +1 -1
- package/dist/decorators-B6l3CbxC.d.ts +13 -0
- package/dist/decorators-D5nY109r.d.mts +13 -0
- package/dist/http-error/index.d.mts +18 -0
- package/dist/http-error/index.d.ts +18 -0
- package/dist/http-error/index.js +81 -0
- package/dist/http-error/index.js.map +1 -0
- package/dist/http-error/index.mjs +79 -0
- package/dist/http-error/index.mjs.map +1 -0
- package/dist/index-j6QGMhZU.d.mts +30 -0
- package/dist/index-tpPZS_UK.d.ts +30 -0
- package/dist/index.d.mts +16 -5
- package/dist/index.d.ts +16 -5
- package/dist/index.js +1178 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1176 -15
- package/dist/index.mjs.map +1 -1
- package/dist/infra/index.d.mts +6 -0
- package/dist/infra/index.d.ts +6 -0
- package/dist/infra/index.js +162 -0
- package/dist/infra/index.js.map +1 -0
- package/dist/infra/index.mjs +159 -0
- package/dist/infra/index.mjs.map +1 -0
- package/dist/{Logger-iEQNVVSc.d.mts → logger/index.d.mts} +2 -1
- package/dist/{Logger-iEQNVVSc.d.ts → logger/index.d.ts} +2 -1
- package/dist/logger/index.js +123 -0
- package/dist/logger/index.js.map +1 -0
- package/dist/logger/index.mjs +120 -0
- package/dist/logger/index.mjs.map +1 -0
- package/dist/plugins/index.d.mts +8 -6
- package/dist/plugins/index.d.ts +8 -6
- package/dist/plugins/index.js +1101 -0
- package/dist/plugins/index.js.map +1 -1
- package/dist/plugins/index.mjs +1101 -1
- package/dist/plugins/index.mjs.map +1 -1
- package/dist/rate-limit/index.d.mts +7 -0
- package/dist/rate-limit/index.d.ts +7 -0
- package/dist/rate-limit/index.js +81 -0
- package/dist/rate-limit/index.js.map +1 -0
- package/dist/rate-limit/index.mjs +79 -0
- package/dist/rate-limit/index.mjs.map +1 -0
- package/dist/router/index.d.mts +4 -0
- package/dist/router/index.d.ts +4 -0
- package/dist/router/index.js +218 -0
- package/dist/router/index.js.map +1 -0
- package/dist/router/index.mjs +216 -0
- package/dist/router/index.mjs.map +1 -0
- package/dist/routes.type-DZO5VBW2.d.mts +58 -0
- package/dist/routes.type-DzHNkCag.d.ts +58 -0
- package/dist/swagger/index.d.mts +30 -0
- package/dist/swagger/index.d.ts +30 -0
- package/dist/swagger/index.js +1136 -0
- package/dist/swagger/index.js.map +1 -0
- package/dist/swagger/index.mjs +1126 -0
- package/dist/swagger/index.mjs.map +1 -0
- package/dist/swagger/swagger-ui-modern.html +894 -0
- package/dist/swagger.type-Bfn5nGR8.d.mts +42 -0
- package/dist/swagger.type-CfDbFCZC.d.ts +42 -0
- package/dist/types/index.d.mts +5 -58
- package/dist/types/index.d.ts +5 -58
- package/dist/utils/index.d.mts +7 -72
- package/dist/utils/index.d.ts +7 -72
- package/dist/validators/index.d.mts +48 -0
- package/dist/validators/index.d.ts +48 -0
- package/dist/validators/index.js +144 -0
- package/dist/validators/index.js.map +1 -0
- package/dist/validators/index.mjs +141 -0
- package/dist/validators/index.mjs.map +1 -0
- package/package.json +86 -2
- package/src/cookies/index.ts +1 -0
- package/src/core/index.ts +1 -0
- package/src/core/router.ts +26 -15
- package/src/core/server.ts +64 -14
- package/src/cors/index.ts +2 -0
- package/src/decorators/index.ts +2 -0
- package/src/http-error/index.ts +1 -0
- package/src/infra/index.ts +3 -0
- package/src/logger/index.ts +1 -0
- package/src/plugins/SwaggerPlugin.ts +45 -0
- package/src/plugins/index.ts +1 -0
- package/src/rate-limit/index.ts +2 -0
- package/src/router/index.ts +1 -0
- package/src/swagger/constants.ts +8 -0
- package/src/swagger/decorators.ts +35 -0
- package/src/swagger/index.ts +10 -0
- package/src/swagger/openapi-builder.ts +199 -0
- package/src/swagger/swagger-ui-html.ts +24 -0
- package/src/swagger/swagger-ui-modern.html +894 -0
- package/src/swagger/swagger-ui-template.ts +5 -0
- package/src/types/index.ts +7 -0
- package/src/types/swagger.type.ts +36 -0
- package/src/validators/index.ts +4 -0
package/dist/core/index.mjs
CHANGED
|
@@ -181,31 +181,37 @@ var Router = class {
|
|
|
181
181
|
return path;
|
|
182
182
|
}
|
|
183
183
|
getAllRoutes() {
|
|
184
|
+
return this.getRouteDocuments().map(({ method, path }) => ({ method, path }));
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Todas as rotas com metadados (ex.: OpenAPI) associados ao handler.
|
|
188
|
+
*/
|
|
189
|
+
getRouteDocuments() {
|
|
184
190
|
const routes = [];
|
|
185
|
-
for (const [key] of this.staticRoutes) {
|
|
191
|
+
for (const [key, stored] of this.staticRoutes) {
|
|
186
192
|
const [method, path] = key.split(":", 2);
|
|
187
|
-
routes.push({ method, path });
|
|
193
|
+
routes.push({ method, path, meta: stored.meta });
|
|
188
194
|
}
|
|
189
|
-
this.
|
|
195
|
+
this.collectRoutesWithMeta(this.root, "", routes);
|
|
190
196
|
return routes;
|
|
191
197
|
}
|
|
192
|
-
|
|
193
|
-
for (const [method] of node.handlers) {
|
|
194
|
-
routes.push({ method, path: prefix || "/" });
|
|
198
|
+
collectRoutesWithMeta(node, prefix, routes) {
|
|
199
|
+
for (const [method, stored] of node.handlers) {
|
|
200
|
+
routes.push({ method, path: prefix || "/", meta: stored.meta });
|
|
195
201
|
}
|
|
196
202
|
for (const [seg, child] of node.children) {
|
|
197
|
-
this.
|
|
203
|
+
this.collectRoutesWithMeta(child, `${prefix}/${seg}`, routes);
|
|
198
204
|
}
|
|
199
205
|
if (node.paramChild) {
|
|
200
|
-
this.
|
|
206
|
+
this.collectRoutesWithMeta(
|
|
201
207
|
node.paramChild,
|
|
202
208
|
`${prefix}/:${node.paramChild.paramName}`,
|
|
203
209
|
routes
|
|
204
210
|
);
|
|
205
211
|
}
|
|
206
212
|
if (node.wildcardHandler) {
|
|
207
|
-
for (const [method] of node.wildcardHandler) {
|
|
208
|
-
routes.push({ method, path: `${prefix}
|
|
213
|
+
for (const [method, stored] of node.wildcardHandler) {
|
|
214
|
+
routes.push({ method, path: `${prefix}/*`, meta: stored.meta });
|
|
209
215
|
}
|
|
210
216
|
}
|
|
211
217
|
}
|
|
@@ -613,7 +619,174 @@ function clearCookieHeader(name, options = {}) {
|
|
|
613
619
|
});
|
|
614
620
|
}
|
|
615
621
|
|
|
622
|
+
// src/swagger/constants.ts
|
|
623
|
+
var API_TAGS_KEY = "azura:api-tags";
|
|
624
|
+
var METHOD_TAGS_KEY = "azura:swagger-method-tags";
|
|
625
|
+
var API_OPERATION_KEY = "azura:swagger-operation";
|
|
626
|
+
|
|
627
|
+
// src/swagger/openapi-builder.ts
|
|
628
|
+
function resolveInfo(options) {
|
|
629
|
+
return options.info ?? {
|
|
630
|
+
title: "AzuraJS API",
|
|
631
|
+
version: "1.0.0",
|
|
632
|
+
description: "Generated OpenAPI specification"
|
|
633
|
+
};
|
|
634
|
+
}
|
|
635
|
+
function toOpenApiPath(path) {
|
|
636
|
+
if (path === "/") return "/";
|
|
637
|
+
const mapped = path.split("/").map((seg) => {
|
|
638
|
+
if (seg === "*") return "{wildcard}";
|
|
639
|
+
return seg.startsWith(":") ? `{${seg.slice(1)}}` : seg;
|
|
640
|
+
}).join("/").replace(/\/{2,}/g, "/");
|
|
641
|
+
if (mapped.endsWith("/*")) {
|
|
642
|
+
return mapped.slice(0, -2) + "/{wildcard}";
|
|
643
|
+
}
|
|
644
|
+
return mapped;
|
|
645
|
+
}
|
|
646
|
+
function pathParametersFromTemplate(path) {
|
|
647
|
+
const re = /\{([^}]+)\}/g;
|
|
648
|
+
const out = [];
|
|
649
|
+
let m;
|
|
650
|
+
const seen = /* @__PURE__ */ new Set();
|
|
651
|
+
while ((m = re.exec(path)) !== null) {
|
|
652
|
+
const name = m[1];
|
|
653
|
+
if (seen.has(name)) continue;
|
|
654
|
+
seen.add(name);
|
|
655
|
+
out.push({
|
|
656
|
+
name,
|
|
657
|
+
in: "path",
|
|
658
|
+
required: true,
|
|
659
|
+
schema: { type: "string" }
|
|
660
|
+
});
|
|
661
|
+
}
|
|
662
|
+
return out;
|
|
663
|
+
}
|
|
664
|
+
function defaultResponses(meta) {
|
|
665
|
+
if (meta?.responses && Object.keys(meta.responses).length > 0) {
|
|
666
|
+
const out = {};
|
|
667
|
+
for (const [code, r] of Object.entries(meta.responses)) {
|
|
668
|
+
out[String(code)] = {
|
|
669
|
+
description: r.description,
|
|
670
|
+
...r.schema ? { content: { "application/json": { schema: r.schema } } } : {}
|
|
671
|
+
};
|
|
672
|
+
}
|
|
673
|
+
return out;
|
|
674
|
+
}
|
|
675
|
+
return {
|
|
676
|
+
"200": {
|
|
677
|
+
description: "Successful response",
|
|
678
|
+
content: {
|
|
679
|
+
"application/json": {
|
|
680
|
+
schema: { type: "object", additionalProperties: true }
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
};
|
|
685
|
+
}
|
|
686
|
+
function mergeParameters(meta, pathParams) {
|
|
687
|
+
const fromMeta = meta?.parameters ?? [];
|
|
688
|
+
const names = new Set(pathParams.map((p) => p.name));
|
|
689
|
+
const rest = fromMeta.filter((p) => !(p.in === "path" && names.has(p.name)));
|
|
690
|
+
const mapped = fromMeta.filter((p) => p.in === "path").map((p) => ({
|
|
691
|
+
name: p.name,
|
|
692
|
+
in: "path",
|
|
693
|
+
required: p.required ?? true,
|
|
694
|
+
description: p.description,
|
|
695
|
+
schema: p.schema ?? { type: p.type ?? "string" }
|
|
696
|
+
}));
|
|
697
|
+
const pathMerged = [...pathParams];
|
|
698
|
+
for (const m of mapped) {
|
|
699
|
+
if (!pathMerged.find((x) => x.name === m.name)) pathMerged.push(m);
|
|
700
|
+
}
|
|
701
|
+
return [...pathMerged, ...rest.map((p) => mapParameter(p))];
|
|
702
|
+
}
|
|
703
|
+
function mapParameter(p) {
|
|
704
|
+
const base = {
|
|
705
|
+
name: p.name,
|
|
706
|
+
in: p.in,
|
|
707
|
+
required: p.required ?? (p.in === "path" ? true : false),
|
|
708
|
+
description: p.description
|
|
709
|
+
};
|
|
710
|
+
if (p.in === "body") {
|
|
711
|
+
return {
|
|
712
|
+
...base,
|
|
713
|
+
content: {
|
|
714
|
+
"application/json": {
|
|
715
|
+
schema: p.schema ?? { type: "object" }
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
};
|
|
719
|
+
}
|
|
720
|
+
return {
|
|
721
|
+
...base,
|
|
722
|
+
schema: p.schema ?? { type: p.type ?? "string" }
|
|
723
|
+
};
|
|
724
|
+
}
|
|
725
|
+
function operationIdFor(method, oPath) {
|
|
726
|
+
const slug = oPath.replace(/[/{}\-*]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "");
|
|
727
|
+
return `${method.toLowerCase()}_${slug || "root"}`;
|
|
728
|
+
}
|
|
729
|
+
function operationForMethod(method, oPath, meta) {
|
|
730
|
+
const op = {
|
|
731
|
+
operationId: operationIdFor(method, oPath),
|
|
732
|
+
summary: meta?.summary ?? `${method} ${oPath}`,
|
|
733
|
+
...meta?.description ? { description: meta.description } : {},
|
|
734
|
+
...meta?.deprecated ? { deprecated: true } : {},
|
|
735
|
+
...meta?.tags?.length ? { tags: meta.tags } : {},
|
|
736
|
+
...meta?.security?.length ? { security: meta.security } : {}
|
|
737
|
+
};
|
|
738
|
+
if (["POST", "PUT", "PATCH"].includes(method) && !meta?.parameters?.some((x) => x.in === "body")) {
|
|
739
|
+
op.requestBody = {
|
|
740
|
+
content: {
|
|
741
|
+
"application/json": {
|
|
742
|
+
schema: { type: "object", additionalProperties: true }
|
|
743
|
+
}
|
|
744
|
+
},
|
|
745
|
+
required: false
|
|
746
|
+
};
|
|
747
|
+
}
|
|
748
|
+
op.responses = defaultResponses(meta);
|
|
749
|
+
return op;
|
|
750
|
+
}
|
|
751
|
+
function buildOpenApiDocument(routes, options) {
|
|
752
|
+
const info = resolveInfo(options);
|
|
753
|
+
const prefix = options.pathPrefix ?? "";
|
|
754
|
+
const paths = {};
|
|
755
|
+
const seen = /* @__PURE__ */ new Set();
|
|
756
|
+
for (const r of routes) {
|
|
757
|
+
const full = prefix + r.path;
|
|
758
|
+
const oPath = toOpenApiPath(full);
|
|
759
|
+
const key = `${r.method}:${oPath}`;
|
|
760
|
+
if (seen.has(key)) continue;
|
|
761
|
+
seen.add(key);
|
|
762
|
+
const pathParams = pathParametersFromTemplate(oPath);
|
|
763
|
+
const op = operationForMethod(r.method, oPath, r.meta);
|
|
764
|
+
const parameters = mergeParameters(r.meta, pathParams);
|
|
765
|
+
if (parameters.length) op.parameters = parameters;
|
|
766
|
+
const methodLc = r.method.toLowerCase();
|
|
767
|
+
if (!paths[oPath]) paths[oPath] = {};
|
|
768
|
+
paths[oPath][methodLc] = op;
|
|
769
|
+
}
|
|
770
|
+
return {
|
|
771
|
+
openapi: "3.0.3",
|
|
772
|
+
info: {
|
|
773
|
+
title: info.title,
|
|
774
|
+
version: info.version,
|
|
775
|
+
...info.description ? { description: info.description } : {},
|
|
776
|
+
...info.contact ? { contact: info.contact } : {},
|
|
777
|
+
...info.license ? { license: info.license } : {}
|
|
778
|
+
},
|
|
779
|
+
...options.servers?.length ? { servers: options.servers } : {},
|
|
780
|
+
paths
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
|
|
616
784
|
// src/core/server.ts
|
|
785
|
+
function isRouteDocumentMeta(o) {
|
|
786
|
+
if (!o || typeof o !== "object" || Array.isArray(o)) return false;
|
|
787
|
+
const x = o;
|
|
788
|
+
return "summary" in x || "description" in x || "tags" in x || "deprecated" in x || "parameters" in x || "responses" in x || "security" in x || "produces" in x || "consumes" in x;
|
|
789
|
+
}
|
|
617
790
|
var CONTROLLER_META_KEY = "azura:controller";
|
|
618
791
|
var ROUTES_META_KEY = "azura:routes";
|
|
619
792
|
var PARAMS_META_KEY = "azura:params";
|
|
@@ -702,9 +875,19 @@ var AzuraServer = class {
|
|
|
702
875
|
return this;
|
|
703
876
|
}
|
|
704
877
|
route(method, path, handlers) {
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
878
|
+
let meta;
|
|
879
|
+
let list = handlers;
|
|
880
|
+
const last = list[list.length - 1];
|
|
881
|
+
if (list.length >= 2 && isRouteDocumentMeta(last)) {
|
|
882
|
+
meta = last;
|
|
883
|
+
list = list.slice(0, -1);
|
|
884
|
+
}
|
|
885
|
+
if (list.length === 0) {
|
|
886
|
+
throw new Error(`Route ${method} ${path} requires a handler function`);
|
|
887
|
+
}
|
|
888
|
+
const routeHandler = list[list.length - 1];
|
|
889
|
+
const middlewares = list.slice(0, -1);
|
|
890
|
+
this.router.add(method, path, routeHandler, middlewares, meta);
|
|
708
891
|
return this;
|
|
709
892
|
}
|
|
710
893
|
register(...controllers) {
|
|
@@ -717,6 +900,7 @@ var AzuraServer = class {
|
|
|
717
900
|
const instance = new Controller();
|
|
718
901
|
const prefix = Reflect.getMetadata?.(CONTROLLER_META_KEY, Controller) ?? "";
|
|
719
902
|
const controllerMiddlewares = Reflect.getMetadata?.("azura:middlewares", Controller) ?? [];
|
|
903
|
+
const controllerTags = Reflect.getMetadata?.(API_TAGS_KEY, Controller) ?? [];
|
|
720
904
|
const prototype = Controller.prototype;
|
|
721
905
|
const propertyNames = Object.getOwnPropertyNames(prototype).filter(
|
|
722
906
|
(p) => p !== "constructor"
|
|
@@ -732,6 +916,14 @@ var AzuraServer = class {
|
|
|
732
916
|
const paramsMeta = Reflect.getMetadata?.(PARAMS_META_KEY, prototype, propertyKey) ?? [];
|
|
733
917
|
const routeMiddlewares = Reflect.getMetadata?.("azura:middlewares", prototype, propertyKey) ?? [];
|
|
734
918
|
const allMiddlewares = [...controllerMiddlewares, ...routeMiddlewares];
|
|
919
|
+
const methodTags = Reflect.getMetadata?.(METHOD_TAGS_KEY, prototype, propertyKey) ?? [];
|
|
920
|
+
const opExtra = Reflect.getMetadata?.(API_OPERATION_KEY, prototype, propertyKey) ?? {};
|
|
921
|
+
const tagList = [...controllerTags, ...methodTags, ...routeMeta.meta?.tags ?? []];
|
|
922
|
+
const mergedMeta = (() => {
|
|
923
|
+
const m = { ...routeMeta.meta, ...opExtra };
|
|
924
|
+
if (tagList.length) m.tags = tagList;
|
|
925
|
+
return Object.keys(m).length ? m : void 0;
|
|
926
|
+
})();
|
|
735
927
|
const handler = async (req, res) => {
|
|
736
928
|
const args = this.resolveParams(paramsMeta, req, res);
|
|
737
929
|
const result = await instance[propertyKey](...args);
|
|
@@ -743,7 +935,7 @@ var AzuraServer = class {
|
|
|
743
935
|
}
|
|
744
936
|
}
|
|
745
937
|
};
|
|
746
|
-
this.router.add(routeMeta.method, fullPath, handler, allMiddlewares,
|
|
938
|
+
this.router.add(routeMeta.method, fullPath, handler, allMiddlewares, mergedMeta);
|
|
747
939
|
}
|
|
748
940
|
}
|
|
749
941
|
resolveParams(paramsMeta, req, res) {
|
|
@@ -1097,6 +1289,14 @@ var AzuraServer = class {
|
|
|
1097
1289
|
getRoutes() {
|
|
1098
1290
|
return this.router.getAllRoutes();
|
|
1099
1291
|
}
|
|
1292
|
+
/** Rotas com metadados OpenAPI (para Swagger ou export manual). */
|
|
1293
|
+
getRouteDocuments() {
|
|
1294
|
+
return this.router.getRouteDocuments();
|
|
1295
|
+
}
|
|
1296
|
+
/** Gera documento OpenAPI 3.0 a partir das rotas registadas. */
|
|
1297
|
+
getOpenApiDocument(options = {}) {
|
|
1298
|
+
return buildOpenApiDocument(this.getRouteDocuments(), options);
|
|
1299
|
+
}
|
|
1100
1300
|
};
|
|
1101
1301
|
|
|
1102
1302
|
export { AzuraServer, Router };
|