result = super.postProcessAllModels(objs);
+ if (isExpressZodFramework()) {
+ TypeScriptExpressZodUtils.annotateModels(result, this.openAPI, this::toModelName);
+ }
+ return result;
+ }
+
@Override
public String apiDocFileFolder() {
return (outputFolder + "/" + apiDocPath).replace('/', File.separatorChar);
@@ -455,13 +480,19 @@ public String getHelp() {
public void processOpts() {
super.processOpts();
+ additionalProperties.putIfAbsent(FRAMEWORK_SWITCH, FRAMEWORKS[0]);
+
+ if (isExpressZodFramework()) {
+ configureExpressZodFramework();
+ return;
+ }
+
// change package names
apiPackage = this.apiPackage + ".apis";
testPackage = this.testPackage + ".tests";
additionalProperties.put("apiDocPath", apiDocPath);
- additionalProperties.putIfAbsent(FRAMEWORK_SWITCH, FRAMEWORKS[0]);
supportingFiles.add(new SupportingFile("index.mustache", "index.ts"));
String httpLibName = this.getHttpLibForFramework(additionalProperties.get(FRAMEWORK_SWITCH).toString());
@@ -532,9 +563,59 @@ private String getHttpLibForFramework(String object) {
return this.frameworkToHttpLibMap.get(object);
}
+ private boolean isExpressZodFramework() {
+ return EXPRESS_ZOD_FRAMEWORK.equals(additionalProperties.get(FRAMEWORK_SWITCH));
+ }
+
+ /**
+ * Configure the {@code express-zod} framework: a typed HTTP client with Zod
+ * response validation matching the {@code typescript-express-zod-server} generator.
+ * Everything is emitted as supporting files from the {@code express-zod/} template
+ * subtree; the heavy post-processing lives in {@link TypeScriptExpressZodClientUtils}
+ * and {@link TypeScriptExpressZodUtils}.
+ */
+ private void configureExpressZodFramework() {
+ // These options only affect the fetch-api/jquery template set.
+ for (String option : new String[]{PLATFORM_SWITCH, USE_RXJS_SWITCH, USE_INVERSIFY_SWITCH,
+ USE_OBJECT_PARAMS_SWITCH, ENUM_TYPE_SWITCH, IMPORT_FILE_EXTENSION_SWITCH,
+ FILE_CONTENT_DATA_TYPE}) {
+ if (additionalProperties.containsKey(option)) {
+ LOGGER.warn("Option '{}' is not supported by framework 'express-zod' and will be ignored.", option);
+ }
+ }
+
+ // Restore the AbstractTypeScriptClientCodegen mappings that this class's
+ // constructor overrides: express-zod DTOs carry dates as strings over the wire
+ // and treat free-form objects as `object`.
+ typeMapping.put("object", "object");
+ typeMapping.put("DateTime", "string");
+
+ apiPackage = "";
+ modelPackage = "";
+
+ supportingFiles.clear();
+ modelTemplateFiles.clear();
+ apiTemplateFiles.clear();
+ apiDocTemplateFiles.clear();
+
+ String dir = EXPRESS_ZOD_FRAMEWORK + File.separator;
+ supportingFiles.add(new SupportingFile(dir + "types.mustache", "", "types.ts"));
+ supportingFiles.add(new SupportingFile(dir + "schemas.mustache", "", "schemas.ts"));
+ supportingFiles.add(new SupportingFile(dir + "dtos" + File.separator + "types.mustache", "dtos", "types.ts"));
+ supportingFiles.add(new SupportingFile(dir + "dtos" + File.separator + "mappers.mustache", "dtos", "mappers.ts"));
+ supportingFiles.add(new SupportingFile(dir + "dtos" + File.separator + "index.mustache", "dtos", "index.ts"));
+ supportingFiles.add(new SupportingFile(dir + "http-client.mustache", "", "http-client.ts"));
+ supportingFiles.add(new SupportingFile(dir + "index.mustache", "", "index.ts"));
+ }
+
@Override
public String getTypeDeclaration(Schema p) {
+ if (isExpressZodFramework()) {
+ // express-zod emits no HttpFile symbol and keeps the abstract base's
+ // type declarations (parity with the typescript-express-zod-server generator).
+ return super.getTypeDeclaration(p);
+ }
if (ModelUtils.isMapSchema(p)) {
Schema> inner = getSchemaAdditionalProperties(p);
String postfix = "";
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptExpressZodClientUtils.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptExpressZodClientUtils.java
new file mode 100644
index 000000000000..b583a2dfd87b
--- /dev/null
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptExpressZodClientUtils.java
@@ -0,0 +1,428 @@
+package org.openapitools.codegen.languages;
+
+import org.openapitools.codegen.CodegenMediaType;
+import org.openapitools.codegen.CodegenModel;
+import org.openapitools.codegen.CodegenOperation;
+import org.openapitools.codegen.CodegenParameter;
+import org.openapitools.codegen.CodegenProperty;
+import org.openapitools.codegen.CodegenResponse;
+import org.openapitools.codegen.model.ApiInfoMap;
+import org.openapitools.codegen.model.OperationMap;
+import org.openapitools.codegen.model.OperationsMap;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import static org.openapitools.codegen.utils.StringUtils.camelize;
+
+/**
+ * Client-side post-processing for the {@code express-zod} framework of the unified
+ * {@code typescript} generator. Holds the logic that used to live in the standalone
+ * {@code typescript-express-zod-client} generator so {@code TypeScriptClientCodegen}
+ * only needs thin, framework-guarded delegation calls.
+ *
+ * Logic shared with the {@code typescript-express-zod-server} generator (Zod
+ * expression building, model annotation, shape resolution, topological sorting)
+ * lives in {@link TypeScriptExpressZodUtils}.
+ */
+final class TypeScriptExpressZodClientUtils {
+ private TypeScriptExpressZodClientUtils() {
+ }
+
+ /**
+ * Operation post-processing: URL templates, service names, fetch methods, params
+ * types, and per-parameter Zod vendor extensions.
+ */
+ static OperationsMap postProcessOperations(OperationsMap operations) {
+ OperationMap objs = operations.getOperations();
+ List ops = objs.getOperation();
+
+ for (CodegenOperation op : ops) {
+ // Build URL template for JS template literals:
+ // /recipe/{recipeId} -> /recipe/${encodeURIComponent(params.recipeId)}
+ String urlTemplate = op.path.replaceAll(
+ "\\{([^}]+)\\}",
+ "\\${encodeURIComponent(String(params.$1))}"
+ );
+ op.vendorExtensions.put("x-url-template", urlTemplate);
+
+ // Determine the service name from the tag
+ if (op.tags != null && !op.tags.isEmpty()) {
+ String tag = op.tags.get(0).getName();
+ String serviceName = camelize(tag) + "Service";
+ op.vendorExtensions.put("x-service-name", serviceName);
+ }
+
+ // Set fetch method only for non-GET (GET is fetch default)
+ String httpMethodUpper = op.httpMethod.toUpperCase(Locale.ENGLISH);
+ if (!"GET".equals(httpMethodUpper)) {
+ op.vendorExtensions.put("x-fetch-method", httpMethodUpper);
+ }
+
+ // Response Zod schema / wire type / mapper are resolved (array/map/primitive
+ // aware) in postProcessSupportingFileData via TypeScriptExpressZodUtils.
+
+ // Build params type name
+ String paramsType = camelize(op.operationId) + "Params";
+ op.vendorExtensions.put("x-params-type", paramsType);
+
+ // Check if all params are optional
+ boolean allParamsOptional = true;
+ for (CodegenParameter param : op.allParams) {
+ if (param.required) {
+ allParamsOptional = false;
+ break;
+ }
+ }
+ op.vendorExtensions.put("x-all-params-optional", allParamsOptional);
+
+ // Body param info
+ boolean hasBodyParam = op.bodyParam != null;
+ op.vendorExtensions.put("x-has-body-param", hasBodyParam);
+ if (hasBodyParam) {
+ String bodyParamName = op.bodyParam.paramName;
+ if (bodyParamName == null || bodyParamName.isEmpty()) {
+ bodyParamName = "body";
+ }
+ op.vendorExtensions.put("x-body-param-name", bodyParamName);
+ }
+
+ boolean hasNoParams = op.pathParams.isEmpty() && op.queryParams.isEmpty() && op.bodyParam == null;
+ op.vendorExtensions.put("x-has-no-params", hasNoParams);
+
+ // Add vendor extensions to each parameter for Zod schema building
+ for (CodegenParameter param : op.allParams) {
+ addZodVendorExtensions(param);
+ }
+ }
+
+ return operations;
+ }
+
+ /**
+ * Add Zod-specific vendor extensions to a parameter.
+ */
+ private static void addZodVendorExtensions(CodegenParameter param) {
+ String zodType = buildZodType(param);
+ param.vendorExtensions.put("x-zod-type", zodType);
+
+ // Track if the query param name differs from the camelCase name
+ if (param.isQueryParam && !param.baseName.equals(param.paramName)) {
+ param.vendorExtensions.put("x-original-name", param.baseName);
+ param.vendorExtensions.put("x-has-different-name", true);
+ }
+ }
+
+ /**
+ * Build a Zod type expression for a parameter. This is the client variant; the
+ * server's {@code buildZodType} differs (inline z.enum branch) and unifying the
+ * two would change generated output — deferred as a follow-up.
+ */
+ static String buildZodType(CodegenParameter param) {
+ StringBuilder zod = new StringBuilder();
+
+ if (param.isEnum) {
+ zod.append(camelize(param.dataType) + "Schema");
+ } else if (!param.isPrimitiveType && param.dataType != null && !param.isArray
+ && !param.isBodyParam && !param.isModel) {
+ zod.append(camelize(param.dataType) + "Schema");
+ } else if (param.isInteger || param.isLong) {
+ zod.append("z.coerce.number().int()");
+ if (param.minimum != null) {
+ zod.append(".gte(").append(param.minimum).append(")");
+ }
+ if (param.maximum != null) {
+ zod.append(".lte(").append(param.maximum).append(")");
+ }
+ } else if (param.isNumber || param.isFloat || param.isDouble) {
+ zod.append("z.number()");
+ if (param.minimum != null) {
+ zod.append(".gte(").append(param.minimum).append(")");
+ }
+ if (param.maximum != null) {
+ zod.append(".lte(").append(param.maximum).append(")");
+ }
+ } else if (param.isBoolean) {
+ zod.append("z.boolean()");
+ } else if (param.isString) {
+ zod.append("z.string()");
+ if (param.maxLength != null) {
+ zod.append(".max(").append(param.maxLength).append(")");
+ }
+ if (param.minLength != null) {
+ zod.append(".min(").append(param.minLength).append(")");
+ }
+ } else if (param.isArray && param.items != null) {
+ zod.append(TypeScriptExpressZodUtils.zodExpr(param.items)).append(".array()");
+ } else if (param.isMap && param.additionalProperties != null) {
+ zod.append("z.record(z.string(), ")
+ .append(TypeScriptExpressZodUtils.zodExpr(param.additionalProperties))
+ .append(")");
+ } else if (param.isModel || param.isBodyParam) {
+ // Bodies whose schema dereferences to a bare primitive (e.g. a $ref'd enum
+ // handled as string by fromRequestBody) carry a primitive dataType with the
+ // primitive flags unset — camelize(dataType)+"Schema" would fabricate an
+ // unresolved symbol like StringSchema.
+ if ("string".equals(param.dataType)) {
+ zod.append("z.string()");
+ } else if ("number".equals(param.dataType)) {
+ zod.append("z.number()");
+ } else if ("boolean".equals(param.dataType)) {
+ zod.append("z.boolean()");
+ } else {
+ zod.append(camelize(param.dataType) + "Schema");
+ }
+ } else {
+ zod.append("z.string()");
+ if (param.maxLength != null) {
+ zod.append(".max(").append(param.maxLength).append(")");
+ }
+ }
+
+ if (!param.required) {
+ zod.append(".optional()");
+ }
+
+ return zod.toString();
+ }
+
+ /**
+ * Bundle builder for the supporting-file templates: services, flat operation list,
+ * resolved response/body shapes, SSE stream operations, ModelError inspection, and
+ * topologically sorted models.
+ */
+ @SuppressWarnings("unchecked")
+ static Map postProcessSupportingFileData(Map bundle) {
+ List allOps = ((ApiInfoMap) bundle.get("apiInfo")).getApis();
+
+ // Collect all unique services
+ Map>> serviceMap = new LinkedHashMap<>();
+
+ for (OperationsMap opsMap : allOps) {
+ OperationMap operationMap = opsMap.getOperations();
+ List ops = operationMap.getOperation();
+
+ for (CodegenOperation op : ops) {
+ String serviceName = (String) op.vendorExtensions.getOrDefault("x-service-name", "DefaultService");
+
+ serviceMap.computeIfAbsent(serviceName, k -> new ArrayList<>());
+
+ Map opInfo = new HashMap<>();
+ String operationIdPascal = camelize(op.operationId);
+ // Resolve response/body shapes (array/map/primitive aware). The client converts
+ // wire json -> domain (FROM_WIRE) and domain -> wire before sending (TO_WIRE).
+ TypeScriptExpressZodUtils.Resolved rr = op.returnType != null
+ ? TypeScriptExpressZodUtils.resolveResponse(
+ op, TypeScriptExpressZodUtils.Direction.FROM_WIRE)
+ : null;
+ TypeScriptExpressZodUtils.Resolved rb = op.bodyParam != null
+ ? TypeScriptExpressZodUtils.resolveBody(
+ op.bodyParam, TypeScriptExpressZodUtils.Direction.TO_WIRE,
+ buildZodType(op.bodyParam))
+ : null;
+ opInfo.put("operationId", op.operationId);
+ opInfo.put("operationIdPascal", operationIdPascal);
+ opInfo.put("description", op.summary != null ? op.summary : op.notes);
+ opInfo.put("httpMethod", op.httpMethod.toLowerCase(Locale.ENGLISH));
+ opInfo.put("httpMethodUpper", op.httpMethod.toUpperCase(Locale.ENGLISH));
+ opInfo.put("serviceName", serviceName);
+ opInfo.put("returnType", op.returnType);
+ opInfo.put("hasParams", !op.allParams.isEmpty());
+ opInfo.put("hasNoParams", op.allParams.isEmpty());
+ opInfo.put("allParamsOptional", op.vendorExtensions.get("x-all-params-optional"));
+
+ // URL template for JS template literals
+ opInfo.put("urlTemplate", op.vendorExtensions.get("x-url-template"));
+
+ // Fetch method (only for non-GET)
+ opInfo.put("fetchMethod", op.vendorExtensions.get("x-fetch-method"));
+ opInfo.put("hasFetchMethod", op.vendorExtensions.containsKey("x-fetch-method"));
+
+ // Params info
+ List> pathParams = new ArrayList<>();
+ for (CodegenParameter p : op.pathParams) {
+ Map pm = new HashMap<>();
+ pm.put("name", p.paramName);
+ pm.put("baseName", p.baseName);
+ pm.put("zodType", buildZodType(p));
+ pm.put("dataType", p.dataType);
+ pathParams.add(pm);
+ }
+ opInfo.put("pathParams", pathParams);
+ opInfo.put("hasPathParams", !pathParams.isEmpty());
+
+ List> queryParams = new ArrayList<>();
+ for (CodegenParameter p : op.queryParams) {
+ Map qm = new HashMap<>();
+ qm.put("name", p.paramName);
+ qm.put("baseName", p.baseName);
+ qm.put("hasDifferentName", !p.baseName.equals(p.paramName));
+ qm.put("zodType", buildZodType(p));
+ qm.put("dataType", p.dataType);
+ qm.put("required", p.required);
+ qm.put("isEnum", p.isEnum);
+ queryParams.add(qm);
+ }
+ opInfo.put("queryParams", queryParams);
+ opInfo.put("hasQueryParams", !queryParams.isEmpty());
+
+ if (op.bodyParam != null) {
+ Map body = new HashMap<>();
+ body.put("name", op.vendorExtensions.get("x-body-param-name"));
+ body.put("dataType", op.bodyParam.dataType);
+ body.put("required", op.bodyParam.required);
+ opInfo.put("bodyParam", body);
+ opInfo.put("hasBodyParam", true);
+ // Convert the domain body -> wire before JSON.stringify. Identity (x) => x
+ // for bare primitives so the template can always call it as a function.
+ // When the body can be undefined (optional requestBody, or params itself
+ // optional), guard the mapper so absent bodies keep the old
+ // JSON.stringify(undefined) -> no-body behavior instead of crashing.
+ String bodyMapFn = rb.mapFn != null ? rb.mapFn : "(x) => x";
+ boolean bodyMayBeUndefined = !op.bodyParam.required
+ || Boolean.TRUE.equals(op.vendorExtensions.get("x-all-params-optional"));
+ if (rb.mapFn != null && bodyMayBeUndefined) {
+ bodyMapFn = "(b) => b === undefined ? undefined : (" + rb.mapFn + ")(b)";
+ }
+ opInfo.put("bodyMapFn", bodyMapFn);
+ } else {
+ opInfo.put("hasBodyParam", false);
+ }
+
+ // Response info. The response Zod schema is emitted as a per-operation const
+ // in schemas.ts, and the parsed wire payload is converted to domain via mapFn
+ // (identity (x) => x for bare primitives, so it can always be called as a function).
+ opInfo.put("responseType", op.returnType);
+ if (rr != null) {
+ opInfo.put("responseSchema", operationIdPascal + "ResponseSchema");
+ opInfo.put("responseZodExpr", rr.zod);
+ opInfo.put("responseDtoMapper", rr.mapFn != null ? rr.mapFn : "(x) => x");
+ opInfo.put("responseDtoGeneric", rr.dtoGeneric);
+ // Domain type qualified for http-client.ts (which imports types); e.g.
+ // types.Pet[], { [key: string]: number }, string.
+ opInfo.put("responseDomainGeneric", rr.domainGeneric);
+ }
+
+ // SSE detection
+ boolean hasSSE = false;
+ for (CodegenResponse response : op.responses) {
+ if (response.is2xx && response.getContent() != null) {
+ CodegenMediaType sseMt = response.getContent().get("text/event-stream");
+ if (sseMt != null && sseMt.getSchema() != null) {
+ hasSSE = true;
+ String sseType = sseMt.getSchema().getComplexType();
+ if (sseType == null) sseType = sseMt.getSchema().getDataType();
+ opInfo.put("sseType", sseType);
+ opInfo.put("sseDtoType", sseType + "Dto");
+ opInfo.put("sseDtoMapper", "mapFrom" + sseType + "Dto");
+ opInfo.put("sseSchema", sseType + "Schema");
+ opInfo.put("streamOperationId", op.operationId + "Stream");
+ break;
+ }
+ }
+ }
+ opInfo.put("hasSSE", hasSSE);
+
+ serviceMap.get(serviceName).add(opInfo);
+ }
+ }
+
+ // Convert service map to list for Mustache iteration
+ List> services = new ArrayList<>();
+ for (Map.Entry>> entry : serviceMap.entrySet()) {
+ Map svc = new HashMap<>();
+ svc.put("name", entry.getKey());
+ svc.put("operations", entry.getValue());
+ boolean serviceHasSSE = entry.getValue().stream()
+ .anyMatch(op -> Boolean.TRUE.equals(op.get("hasSSE")));
+ svc.put("hasSSE", serviceHasSSE);
+ services.add(svc);
+ }
+ bundle.put("services", services);
+
+ // Collect all operations flat
+ List> allOperations = new ArrayList<>();
+ for (Map svc : services) {
+ List> ops = (List>) svc.get("operations");
+ allOperations.addAll(ops);
+ }
+ allOperations.sort(Comparator.comparing(o -> (String) o.get("operationId")));
+ bundle.put("allOperations", allOperations);
+
+ boolean anySSE = allOperations.stream()
+ .anyMatch(op -> Boolean.TRUE.equals(op.get("hasSSE")));
+ bundle.put("hasAnySSE", anySSE);
+
+ // Topologically sort models
+ List models = (List) bundle.get("models");
+ if (models != null) {
+ bundle.put("models", TypeScriptExpressZodUtils.topologicallySortModels(models));
+ }
+
+ // Inspect ModelError schema and expose error-shape template variables
+ if (models != null) {
+ for (Object modelEntry : models) {
+ Map entry = (Map) modelEntry;
+ CodegenModel cm = (CodegenModel) entry.get("model");
+ if (cm != null && "ModelError".equals(cm.classname)) {
+ // Determine the message field name: prefer "message", then "title",
+ // then first required string property, fallback to "message"
+ String messageField = null;
+ String firstRequiredString = null;
+ boolean hasCode = false;
+ boolean hasSource = false;
+
+ for (CodegenProperty prop : cm.vars) {
+ if ("code".equals(prop.name)) {
+ hasCode = true;
+ }
+ if ("source".equals(prop.name)) {
+ hasSource = true;
+ }
+ if (prop.required && prop.isString) {
+ if ("message".equals(prop.name)) {
+ messageField = "message";
+ } else if ("title".equals(prop.name) && messageField == null) {
+ messageField = "title";
+ }
+ if (firstRequiredString == null) {
+ firstRequiredString = prop.name;
+ }
+ }
+ }
+
+ if (messageField == null) {
+ messageField = firstRequiredString != null ? firstRequiredString : "message";
+ }
+
+ bundle.put("errorMessageField", messageField);
+ bundle.put("errorHasCode", hasCode);
+ bundle.put("errorHasSource", hasSource);
+ break;
+ }
+ }
+ }
+
+ // Flag whether any model is a discriminated union, so the DTO mappers can
+ // conditionally import ZodError (thrown from mapFrom*Dto default branches).
+ boolean hasDiscriminatedUnion = false;
+ if (models != null) {
+ for (Object modelEntry : models) {
+ Map entry = (Map) modelEntry;
+ CodegenModel cm = (CodegenModel) entry.get("model");
+ if (cm != null && cm.vendorExtensions.containsKey("x-is-discriminated-union")) {
+ hasDiscriminatedUnion = true;
+ break;
+ }
+ }
+ }
+ bundle.put("hasDiscriminatedUnion", hasDiscriminatedUnion);
+
+ return bundle;
+ }
+}
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptExpressZodServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptExpressZodServerCodegen.java
new file mode 100644
index 000000000000..ca53b65647f8
--- /dev/null
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptExpressZodServerCodegen.java
@@ -0,0 +1,621 @@
+package org.openapitools.codegen.languages;
+
+import org.openapitools.codegen.*;
+import org.openapitools.codegen.meta.GeneratorMetadata;
+import org.openapitools.codegen.meta.Stability;
+import org.openapitools.codegen.model.ModelMap;
+import org.openapitools.codegen.model.ModelsMap;
+import org.openapitools.codegen.model.OperationMap;
+import org.openapitools.codegen.model.OperationsMap;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.util.*;
+import java.util.stream.Collectors;
+
+import static org.openapitools.codegen.utils.StringUtils.camelize;
+
+public class TypeScriptExpressZodServerCodegen extends AbstractTypeScriptClientCodegen {
+ private final Logger LOGGER = LoggerFactory.getLogger(TypeScriptExpressZodServerCodegen.class);
+
+ public TypeScriptExpressZodServerCodegen() {
+ super();
+
+ generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata)
+ .stability(Stability.EXPERIMENTAL)
+ .build();
+
+ outputFolder = "generated-code" + File.separator + "typescript-express-zod-server";
+ embeddedTemplateDir = templateDir = "typescript-express-zod-server";
+
+ // We generate everything via supporting files, not per-model/per-api
+ modelTemplateFiles.put("model.mustache", ".ts");
+ apiTemplateFiles.put("api.mustache", ".ts");
+
+ apiPackage = "";
+ modelPackage = "";
+ }
+
+ @Override
+ public CodegenType getTag() {
+ return CodegenType.SERVER;
+ }
+
+ @Override
+ public String getName() {
+ return "typescript-express-zod-server";
+ }
+
+ @Override
+ public String getHelp() {
+ return "Generates a TypeScript Express server with Zod validation.";
+ }
+
+ @Override
+ public void processOpts() {
+ super.processOpts();
+
+ supportingFiles.clear();
+ modelTemplateFiles.clear();
+ apiTemplateFiles.clear();
+
+ supportingFiles.add(new SupportingFile("types.mustache", "", "types.ts"));
+ supportingFiles.add(new SupportingFile("schemas.mustache", "", "schemas.ts"));
+ supportingFiles.add(new SupportingFile("dtos" + File.separator + "types.mustache", "dtos", "types.ts"));
+ supportingFiles.add(new SupportingFile("dtos" + File.separator + "mappers.mustache", "dtos", "mappers.ts"));
+ supportingFiles.add(new SupportingFile("express" + File.separator + "handlers.mustache", "express", "handlers.ts"));
+ supportingFiles.add(new SupportingFile("express" + File.separator + "types.mustache", "express", "types.ts"));
+ supportingFiles.add(new SupportingFile("express" + File.separator + "router-factory.mustache", "express", "router-factory.ts"));
+ supportingFiles.add(new SupportingFile("express" + File.separator + "errors.mustache", "express", "errors.ts"));
+ supportingFiles.add(new SupportingFile("express" + File.separator + "auth-middleware.mustache", "express", "auth-middleware.ts"));
+ supportingFiles.add(new SupportingFile("express" + File.separator + "index.mustache", "express", "index.ts"));
+ supportingFiles.add(new SupportingFile("dtos" + File.separator + "index.mustache", "dtos", "index.ts"));
+ supportingFiles.add(new SupportingFile("index.mustache", "", "index.ts"));
+ }
+
+ @Override
+ public OperationsMap postProcessOperationsWithModels(OperationsMap operations, List allModels) {
+ OperationMap objs = operations.getOperations();
+ List ops = objs.getOperation();
+
+ for (CodegenOperation op : ops) {
+ // Convert {param} to :param for Express routing
+ op.path = op.path.replaceAll("\\{([^}]+)\\}", ":$1");
+ // Escape reserved path-to-regexp v8 characters for Express v5 compatibility
+ op.path = escapeExpressReservedChars(op.path);
+
+ // Add vendor extensions for template use
+ op.vendorExtensions.put("x-express-path", op.path);
+ op.vendorExtensions.put("x-http-method-lower", op.httpMethod.toLowerCase(Locale.ENGLISH));
+
+ // Build the handler name: handle + PascalCase(operationId)
+ String handlerName = "handle" + camelize(op.operationId);
+ op.vendorExtensions.put("x-handler-name", handlerName);
+
+ // Determine the service name from the tag
+ if (op.tags != null && !op.tags.isEmpty()) {
+ String tag = op.tags.get(0).getName();
+ String serviceName = camelize(tag) + "Service";
+ op.vendorExtensions.put("x-service-name", serviceName);
+ op.vendorExtensions.put("x-service-getter", "get" + serviceName);
+ }
+
+ // Response Zod schema / wire type / mapper are resolved (array/map/primitive
+ // aware) in postProcessSupportingFileData via TypeScriptExpressZodUtils.
+
+ // Mark whether this operation has only path params, only query params, etc.
+ boolean hasOnlyPathParams = !op.pathParams.isEmpty() && op.queryParams.isEmpty() && op.bodyParam == null;
+ boolean hasOnlyQueryParams = op.pathParams.isEmpty() && !op.queryParams.isEmpty() && op.bodyParam == null;
+ boolean hasBodyParam = op.bodyParam != null;
+ boolean hasNoParams = op.pathParams.isEmpty() && op.queryParams.isEmpty() && op.bodyParam == null;
+
+ op.vendorExtensions.put("x-has-no-params", hasNoParams);
+ op.vendorExtensions.put("x-has-body-param", hasBodyParam);
+
+ // Build params schema name
+ String paramsType = camelize(op.operationId) + "Params";
+ op.vendorExtensions.put("x-params-type", paramsType);
+ op.vendorExtensions.put("x-params-schema", paramsType + "Schema");
+
+ // Check if all params are optional (for optional parse)
+ boolean allParamsOptional = true;
+ for (CodegenParameter param : op.allParams) {
+ if (param.required) {
+ allParamsOptional = false;
+ break;
+ }
+ }
+ op.vendorExtensions.put("x-all-params-optional", allParamsOptional);
+
+ // The body Zod schema / wire type / mapper are resolved (array/map/primitive
+ // aware) in postProcessSupportingFileData; here we only fix the body param name.
+ if (op.bodyParam != null) {
+ // Get the request body name from x-codegen-request-body-name or default to "body"
+ String bodyParamName = op.bodyParam.paramName;
+ if (bodyParamName == null || bodyParamName.isEmpty()) {
+ bodyParamName = "body";
+ }
+ op.vendorExtensions.put("x-body-param-name", bodyParamName);
+ }
+
+ // Add vendor extensions to each parameter for Zod schema building
+ for (CodegenParameter param : op.allParams) {
+ addZodVendorExtensions(param);
+ }
+
+ // Build RequestHandler type generics
+ buildRequestHandlerType(op);
+ }
+
+ return operations;
+ }
+
+ /**
+ * Add Zod-specific vendor extensions to a parameter.
+ */
+ private void addZodVendorExtensions(CodegenParameter param) {
+ String zodType = buildZodType(param);
+ param.vendorExtensions.put("x-zod-type", zodType);
+
+ // Track if the query param name differs from the camelCase name
+ if (param.isQueryParam && !param.baseName.equals(param.paramName)) {
+ param.vendorExtensions.put("x-original-name", param.baseName);
+ param.vendorExtensions.put("x-has-different-name", true);
+ }
+ }
+
+ /**
+ * Build a Zod type expression for a parameter.
+ */
+ private String buildZodType(CodegenParameter param) {
+ StringBuilder zod = new StringBuilder();
+
+ if (param.isEnum && param.allowableValues != null) {
+ List> values = (List>) param.allowableValues.get("values");
+ if (values != null && !values.isEmpty()) {
+ StringBuilder sb = new StringBuilder("z.enum([");
+ for (int i = 0; i < values.size(); i++) {
+ if (i > 0) sb.append(", ");
+ sb.append("'").append(values.get(i)).append("'");
+ }
+ sb.append("])");
+ zod.append(sb);
+ // Array-of-enum params (e.g. a repeated query param) — the param itself is
+ // flagged isEnum, so wrap the enum in .array() to match the Array type.
+ if (param.isArray) {
+ zod.append(".array()");
+ }
+ } else {
+ zod.append(camelize(param.dataType) + "Schema");
+ }
+ } else if (!param.isPrimitiveType && param.dataType != null && !param.isArray
+ && !param.isBodyParam && !param.isModel) {
+ // Reference to a non-primitive type (e.g., enum via $ref)
+ zod.append(camelize(param.dataType) + "Schema");
+ } else if (param.isInteger || param.isLong) {
+ zod.append("z.coerce.number().int()");
+ if (param.minimum != null) {
+ zod.append(".gte(").append(param.minimum).append(")");
+ }
+ if (param.maximum != null) {
+ zod.append(".lte(").append(param.maximum).append(")");
+ }
+ } else if (param.isNumber || param.isFloat || param.isDouble) {
+ zod.append("z.number()");
+ if (param.minimum != null) {
+ zod.append(".gte(").append(param.minimum).append(")");
+ }
+ if (param.maximum != null) {
+ zod.append(".lte(").append(param.maximum).append(")");
+ }
+ } else if (param.isBoolean) {
+ zod.append("z.boolean()");
+ } else if (param.isString) {
+ zod.append("z.string()");
+ if (param.maxLength != null) {
+ zod.append(".max(").append(param.maxLength).append(")");
+ }
+ if (param.minLength != null) {
+ zod.append(".min(").append(param.minLength).append(")");
+ }
+ } else if (param.isArray && param.items != null) {
+ zod.append(TypeScriptExpressZodUtils.zodExpr(param.items)).append(".array()");
+ } else if (param.isMap && param.additionalProperties != null) {
+ zod.append("z.record(z.string(), ")
+ .append(TypeScriptExpressZodUtils.zodExpr(param.additionalProperties))
+ .append(")");
+ } else if (param.isModel || param.isBodyParam) {
+ // Bodies whose schema dereferences to a bare primitive (e.g. a $ref'd enum
+ // handled as string by fromRequestBody) carry a primitive dataType with the
+ // primitive flags unset — camelize(dataType)+"Schema" would fabricate an
+ // unresolved symbol like StringSchema.
+ if ("string".equals(param.dataType)) {
+ zod.append("z.string()");
+ } else if ("number".equals(param.dataType)) {
+ zod.append("z.number()");
+ } else if ("boolean".equals(param.dataType)) {
+ zod.append("z.boolean()");
+ } else {
+ // Reference the model schema
+ zod.append(camelize(param.dataType) + "Schema");
+ }
+ } else {
+ zod.append("z.string()");
+ if (param.maxLength != null) {
+ zod.append(".max(").append(param.maxLength).append(")");
+ }
+ }
+
+ if (!param.required) {
+ zod.append(".optional()");
+ }
+
+ return zod.toString();
+ }
+
+ /**
+ * Build the Express RequestHandler type generics for an operation.
+ */
+ private void buildRequestHandlerType(CodegenOperation op) {
+ // Params type (path params)
+ StringBuilder paramsType = new StringBuilder("{");
+ if (!op.pathParams.isEmpty()) {
+ paramsType = new StringBuilder("{\n");
+ for (int i = 0; i < op.pathParams.size(); i++) {
+ CodegenParameter p = op.pathParams.get(i);
+ paramsType.append(" ").append(p.paramName).append(": string");
+ if (i < op.pathParams.size() - 1) paramsType.append(",");
+ paramsType.append("\n");
+ }
+ paramsType.append(" }");
+ } else {
+ paramsType.append("}");
+ }
+ op.vendorExtensions.put("x-params-generic", paramsType.toString());
+
+ // Query type
+ StringBuilder queryType = new StringBuilder("{");
+ if (!op.queryParams.isEmpty()) {
+ queryType = new StringBuilder("{\n");
+ for (int i = 0; i < op.queryParams.size(); i++) {
+ CodegenParameter p = op.queryParams.get(i);
+ String qName = p.baseName.contains("-") ? "\"" + p.baseName + "\"" : p.baseName;
+ queryType.append(" ").append(qName).append("?: string");
+ if (i < op.queryParams.size() - 1) queryType.append(",");
+ queryType.append("\n");
+ }
+ queryType.append(" }");
+ } else {
+ queryType.append("}");
+ }
+ op.vendorExtensions.put("x-query-generic", queryType.toString());
+
+ // The body and response wire (DTO) generics for the RequestHandler type are resolved
+ // (array/map/primitive aware) in postProcessSupportingFileData; see resolveBody/resolveResponse.
+ }
+
+ @Override
+ public Map postProcessAllModels(Map objs) {
+ Map result = super.postProcessAllModels(objs);
+
+ // Zod/union/intersection/ref annotations shared with the express-zod client
+ // (the `express-zod` framework of the `typescript` generator).
+ TypeScriptExpressZodUtils.annotateModels(result, this.openAPI, this::toModelName);
+
+ // Second pass: Make discriminator properties required in Zod schemas.
+ // Discriminator properties must not be .optional() so that the inferred
+ // type from z.discriminatedUnion matches the generated TypeScript types.
+ for (ModelsMap entry : result.values()) {
+ for (ModelMap mo : entry.getModels()) {
+ CodegenModel cm = mo.getModel();
+ if (cm.vendorExtensions.containsKey("x-is-discriminated-union") && cm.discriminator != null) {
+ String discPropName = cm.discriminator.getPropertyBaseName();
+ if (cm.oneOf != null) {
+ for (String memberName : cm.oneOf) {
+ ModelsMap memberModelsMap = result.get(memberName);
+ if (memberModelsMap != null) {
+ for (ModelMap mm : memberModelsMap.getModels()) {
+ for (CodegenProperty prop : mm.getModel().vars) {
+ if (prop.baseName.equals(discPropName) || prop.name.equals(discPropName)) {
+ String zodFull = (String) prop.vendorExtensions.get("x-zod-full");
+ if (zodFull != null && zodFull.endsWith(".optional()")) {
+ prop.vendorExtensions.put("x-zod-full",
+ zodFull.substring(0, zodFull.length() - ".optional()".length()));
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Escape characters that are reserved in path-to-regexp v8 (used by Express v5).
+ * Reserved chars: ( ) [ ] ? + !
+ * These are escaped with backslash in the generated TypeScript source.
+ * Double-backslash is used so that Mustache renders \\( in TS, which JS evaluates to \( at runtime.
+ * Parameter segments (:paramName) are left untouched.
+ * This is backward-compatible with Express v4 (path-to-regexp 0.1.x also treats \( as literal).
+ */
+ private String escapeExpressReservedChars(String path) {
+ StringBuilder result = new StringBuilder();
+ int i = 0;
+ while (i < path.length()) {
+ char c = path.charAt(i);
+ if (c == ':') {
+ // Skip over :paramName segment
+ result.append(c);
+ i++;
+ while (i < path.length() && (Character.isLetterOrDigit(path.charAt(i)) || path.charAt(i) == '_')) {
+ result.append(path.charAt(i));
+ i++;
+ }
+ } else if ("()[]?+!".indexOf(c) >= 0) {
+ result.append("\\\\").append(c);
+ i++;
+ } else {
+ result.append(c);
+ i++;
+ }
+ }
+ return result.toString();
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Map postProcessSupportingFileData(Map bundle) {
+ bundle = super.postProcessSupportingFileData(bundle);
+
+ // Build service map from operations for the types template
+ List allOps = ((org.openapitools.codegen.model.ApiInfoMap) bundle.get("apiInfo")).getApis();
+
+ // Collect all unique services
+ Map>> serviceMap = new LinkedHashMap<>();
+ // Collect all unique paths for router
+ Map>> pathMap = new LinkedHashMap<>();
+
+ for (OperationsMap opsMap : allOps) {
+ OperationMap operationMap = opsMap.getOperations();
+ List ops = operationMap.getOperation();
+
+ for (CodegenOperation op : ops) {
+ String serviceName = (String) op.vendorExtensions.getOrDefault("x-service-name", "DefaultService");
+ String serviceGetter = (String) op.vendorExtensions.getOrDefault("x-service-getter", "getDefaultService");
+
+ serviceMap.computeIfAbsent(serviceName, k -> new ArrayList<>());
+
+ Map opInfo = new HashMap<>();
+ String operationIdPascal = camelize(op.operationId);
+ // Resolve response/body shapes (array/map/primitive aware). The server maps
+ // domain results -> wire (TO_WIRE) and req.body wire -> domain (FROM_WIRE).
+ TypeScriptExpressZodUtils.Resolved rr = op.returnType != null
+ ? TypeScriptExpressZodUtils.resolveResponse(
+ op, TypeScriptExpressZodUtils.Direction.TO_WIRE)
+ : null;
+ TypeScriptExpressZodUtils.Resolved rb = op.bodyParam != null
+ ? TypeScriptExpressZodUtils.resolveBody(
+ op.bodyParam, TypeScriptExpressZodUtils.Direction.FROM_WIRE,
+ buildZodType(op.bodyParam))
+ : null;
+ opInfo.put("operationId", op.operationId);
+ opInfo.put("operationIdPascal", operationIdPascal);
+ opInfo.put("description", op.summary != null ? op.summary : op.notes);
+ opInfo.put("path", op.path);
+ opInfo.put("httpMethod", op.httpMethod.toLowerCase(Locale.ENGLISH));
+ opInfo.put("httpMethodUpper", op.httpMethod.toUpperCase(Locale.ENGLISH));
+ opInfo.put("handlerName", op.vendorExtensions.get("x-handler-name"));
+ opInfo.put("serviceName", serviceName);
+ opInfo.put("serviceGetter", serviceGetter);
+ opInfo.put("returnType", op.returnType);
+ opInfo.put("hasParams", !op.allParams.isEmpty());
+ opInfo.put("hasNoParams", op.allParams.isEmpty());
+ opInfo.put("allParamsOptional", op.vendorExtensions.get("x-all-params-optional"));
+
+ // Build params info
+ List> pathParams = new ArrayList<>();
+ for (CodegenParameter p : op.pathParams) {
+ Map pm = new HashMap<>();
+ pm.put("name", p.paramName);
+ pm.put("baseName", p.baseName);
+ pm.put("zodType", buildZodType(p));
+ pm.put("dataType", p.dataType);
+ pathParams.add(pm);
+ }
+ opInfo.put("pathParams", pathParams);
+ opInfo.put("hasPathParams", !pathParams.isEmpty());
+
+ List> queryParams = new ArrayList<>();
+ for (CodegenParameter p : op.queryParams) {
+ Map qm = new HashMap<>();
+ qm.put("name", p.paramName);
+ qm.put("baseName", p.baseName);
+ qm.put("hasDifferentName", !p.baseName.equals(p.paramName));
+ qm.put("zodType", buildZodType(p));
+ qm.put("dataType", p.dataType);
+ qm.put("required", p.required);
+ qm.put("isEnum", p.isEnum);
+ queryParams.add(qm);
+ }
+ opInfo.put("queryParams", queryParams);
+ opInfo.put("hasQueryParams", !queryParams.isEmpty());
+
+ if (op.bodyParam != null) {
+ Map body = new HashMap<>();
+ body.put("name", op.vendorExtensions.get("x-body-param-name"));
+ body.put("dataType", op.bodyParam.dataType);
+ body.put("required", op.bodyParam.required);
+ // Zod schema for the body field (array/map/primitive aware) and the
+ // wire->domain mapper function applied to req.body. mapFn is null for
+ // bare primitives (identity), in which case the template passes req.body through.
+ body.put("zodExpr", rb.zod);
+ // The mapper runs on RAW req.body before Zod validation, so guard by
+ // shape: a malformed body must fall through to the schema (ZodError ->
+ // 400) instead of crashing in the mapper (TypeError -> 500).
+ String bodyMapFn = rb.mapFn;
+ if (bodyMapFn != null) {
+ if (op.bodyParam.isArray) {
+ bodyMapFn = "(b) => Array.isArray(b) ? (" + rb.mapFn + ")(b) : b";
+ } else if (op.bodyParam.isMap) {
+ bodyMapFn = "(b) => b !== null && typeof b === \"object\" && !Array.isArray(b) ? (" + rb.mapFn + ")(b) : b";
+ } else {
+ bodyMapFn = "(b) => b == null ? b : (" + rb.mapFn + ")(b)";
+ }
+ }
+ body.put("mapFn", bodyMapFn);
+ opInfo.put("bodyParam", body);
+ opInfo.put("hasBodyParam", true);
+ } else {
+ opInfo.put("hasBodyParam", false);
+ }
+
+ // Auth permission from x-auth-permission vendor extension
+ opInfo.put("permission", op.vendorExtensions.get("x-auth-permission"));
+
+ // Response info. The response Zod schema is emitted as a per-operation
+ // const in schemas.ts (so array/map/primitive shapes have a real symbol to
+ // reference), and the payload is converted via mapFn (null => passthrough).
+ opInfo.put("responseType", op.returnType);
+ if (rr != null) {
+ opInfo.put("responseSchema", operationIdPascal + "ResponseSchema");
+ opInfo.put("responseZodExpr", rr.zod);
+ opInfo.put("responseDtoMapper", rr.mapFn);
+ // Domain type qualified for use outside types.ts (e.g. the SSE branch's
+ // result cast in handlers.ts): types.Pet[], { [key: string]: number }, string.
+ opInfo.put("responseDomainGeneric", rr.domainGeneric);
+ }
+
+ // SSE detection
+ boolean hasSSE = false;
+ for (CodegenResponse response : op.responses) {
+ if (response.is2xx && response.getContent() != null) {
+ CodegenMediaType sseMt = response.getContent().get("text/event-stream");
+ if (sseMt != null && sseMt.getSchema() != null) {
+ hasSSE = true;
+ String sseType = sseMt.getSchema().getComplexType();
+ if (sseType == null) sseType = sseMt.getSchema().getDataType();
+ opInfo.put("sseType", sseType);
+ opInfo.put("sseDtoType", sseType + "Dto");
+ opInfo.put("sseDtoMapper", "mapTo" + sseType + "Dto");
+ opInfo.put("sseSchema", sseType + "Schema");
+ break;
+ }
+ }
+ }
+ opInfo.put("hasSSE", hasSSE);
+
+ // RequestHandler type generics
+ opInfo.put("paramsGeneric", op.vendorExtensions.get("x-params-generic"));
+ opInfo.put("queryGeneric", op.vendorExtensions.get("x-query-generic"));
+ // Wire (DTO) generics for the express RequestHandler type, resolved for
+ // array/map/primitive shapes (e.g. dtos.PetDto[], { [key: string]: number }).
+ opInfo.put("bodyGeneric", rb != null ? rb.dtoGeneric : "unknown");
+ opInfo.put("responseGeneric", rr != null ? rr.dtoGeneric : "any");
+
+ serviceMap.get(serviceName).add(opInfo);
+
+ // Group by path for router
+ String expressPath = op.path;
+ pathMap.computeIfAbsent(expressPath, k -> new ArrayList<>());
+ pathMap.get(expressPath).add(opInfo);
+ }
+ }
+
+ // Convert service map to list for Mustache iteration
+ List> services = new ArrayList<>();
+ for (Map.Entry>> entry : serviceMap.entrySet()) {
+ Map svc = new HashMap<>();
+ svc.put("name", entry.getKey());
+ svc.put("getter", "get" + entry.getKey());
+ svc.put("operations", entry.getValue());
+ services.add(svc);
+ }
+ bundle.put("services", services);
+
+ // Convert path map to list for router template
+ List> routes = new ArrayList<>();
+ for (Map.Entry>> entry : pathMap.entrySet()) {
+ Map route = new HashMap<>();
+ route.put("path", entry.getKey());
+ route.put("operations", entry.getValue());
+
+ // Build the allowed methods list
+ Set methods = new TreeSet<>();
+ methods.add("OPTIONS");
+ for (Map opInfo : entry.getValue()) {
+ String method = ((String) opInfo.get("httpMethodUpper"));
+ methods.add(method);
+ if ("GET".equals(method)) methods.add("HEAD");
+ }
+ route.put("allowedMethods", String.join(", ", methods));
+ routes.add(route);
+ }
+
+ // Sort routes: most specific (longer, more segments) first to avoid Express routing conflicts
+ routes.sort((a, b) -> {
+ String pathA = (String) a.get("path");
+ String pathB = (String) b.get("path");
+ // Count segments
+ long segA = pathA.chars().filter(c -> c == '/').count();
+ long segB = pathB.chars().filter(c -> c == '/').count();
+ if (segA != segB) return Long.compare(segB, segA); // more segments first
+ // Prefer static segments over parameterized ones
+ boolean aHasParam = pathA.contains(":");
+ boolean bHasParam = pathB.contains(":");
+ if (aHasParam != bHasParam) return aHasParam ? 1 : -1; // static first at same depth
+ return pathA.compareTo(pathB);
+ });
+
+ bundle.put("routes", routes);
+
+ // Collect all operations flat for handlers template
+ List> allOperations = new ArrayList<>();
+ for (Map svc : services) {
+ @SuppressWarnings("unchecked")
+ List> ops = (List>) svc.get("operations");
+ allOperations.addAll(ops);
+ }
+ // Sort operations alphabetically by operationId
+ allOperations.sort(Comparator.comparing(o -> (String) o.get("operationId")));
+ bundle.put("allOperations", allOperations);
+
+ // Build auth operations list for auth-middleware template
+ List> authOperations = allOperations.stream()
+ .filter(op -> op.get("permission") != null)
+ .collect(Collectors.toList());
+ bundle.put("authOperations", authOperations);
+ bundle.put("hasAuthOperations", !authOperations.isEmpty());
+
+ // Topologically sort models so that referenced schemas are declared before they are used
+ @SuppressWarnings("unchecked")
+ List models = (List) bundle.get("models");
+ if (models != null) {
+ bundle.put("models", TypeScriptExpressZodUtils.topologicallySortModels(models));
+ }
+
+ // Flag whether any model is a discriminated union, so templates can
+ // conditionally import ZodError (thrown from mapFrom*Dto default branches).
+ boolean hasDiscriminatedUnion = false;
+ if (models != null) {
+ for (Object modelEntry : models) {
+ @SuppressWarnings("unchecked")
+ Map entry = (Map) modelEntry;
+ CodegenModel cm = (CodegenModel) entry.get("model");
+ if (cm != null && cm.vendorExtensions.containsKey("x-is-discriminated-union")) {
+ hasDiscriminatedUnion = true;
+ break;
+ }
+ }
+ }
+ bundle.put("hasDiscriminatedUnion", hasDiscriminatedUnion);
+
+ return bundle;
+ }
+}
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptExpressZodUtils.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptExpressZodUtils.java
new file mode 100644
index 000000000000..1a25afa38f12
--- /dev/null
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptExpressZodUtils.java
@@ -0,0 +1,645 @@
+package org.openapitools.codegen.languages;
+
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.media.Schema;
+import org.openapitools.codegen.CodegenDiscriminator;
+import org.openapitools.codegen.CodegenModel;
+import org.openapitools.codegen.CodegenOperation;
+import org.openapitools.codegen.CodegenParameter;
+import org.openapitools.codegen.CodegenProperty;
+import org.openapitools.codegen.model.ModelMap;
+import org.openapitools.codegen.model.ModelsMap;
+import org.openapitools.codegen.utils.ModelUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+
+import static org.openapitools.codegen.utils.StringUtils.camelize;
+
+/**
+ * Shared helpers for the {@code typescript-express-zod-server} generator and the
+ * {@code express-zod} framework of the unified {@code typescript} generator
+ * ({@link TypeScriptClientCodegen}).
+ *
+ * The server generator and the client framework live in different classes, so the
+ * recursive Zod builder, the model annotation pass, the topological model sort, and the
+ * array/map/primitive DTO resolution would otherwise be duplicated and free to diverge.
+ * Keeping that logic here — the highest-risk, must-stay-identical part — is the single
+ * source of truth. Client-only post-processing lives in
+ * {@link TypeScriptExpressZodClientUtils}.
+ */
+final class TypeScriptExpressZodUtils {
+ private TypeScriptExpressZodUtils() {
+ }
+
+ /** Direction of a DTO mapping: domain->wire ({@code mapTo*Dto}) or wire->domain ({@code mapFrom*Dto}). */
+ enum Direction {
+ TO_WIRE, FROM_WIRE
+ }
+
+ /** Resolution of a body/response shape into its Zod schema, wire (DTO) type, and mapper. */
+ static final class Resolved {
+ /** Zod schema expression, e.g. {@code PetSchema.array()}. */
+ final String zod;
+ /** Over-the-wire TypeScript type, e.g. {@code dtos.PetDto[]}. */
+ final String dtoGeneric;
+ /** Domain TypeScript type qualified for use outside {@code types.ts}, e.g. {@code types.Pet[]}. */
+ final String domainGeneric;
+ /** Function expression converting between domain and wire, or {@code null} for identity/passthrough. */
+ final String mapFn;
+
+ Resolved(String zod, String dtoGeneric, String domainGeneric, String mapFn) {
+ this.zod = zod;
+ this.dtoGeneric = dtoGeneric;
+ this.domainGeneric = domainGeneric;
+ this.mapFn = mapFn;
+ }
+ }
+
+ // ---------------------------------------------------------------------
+ // Recursive Zod expression builder
+ // ---------------------------------------------------------------------
+
+ /**
+ * Build a Zod type expression for a model/response property. Handles enums, arrays,
+ * maps ({@code z.record}), $refs, and primitives (with numeric/length constraints).
+ */
+ static String zodExpr(CodegenProperty prop) {
+ if (prop == null) {
+ return "z.any()";
+ }
+
+ // Enum properties with allowable values.
+ if (prop.isEnum && prop.allowableValues != null) {
+ List> values = (List>) prop.allowableValues.get("values");
+ if (values != null && values.size() == 1) {
+ // Single-value enum = literal.
+ return "z.literal(\"" + values.get(0) + "\")";
+ }
+ if (prop.complexType != null) {
+ // Multi-value enum referenced via $ref — reference the enum schema.
+ return camelize(prop.complexType) + "Schema";
+ }
+ if (values != null) {
+ StringBuilder sb = new StringBuilder("z.enum([");
+ for (int i = 0; i < values.size(); i++) {
+ if (i > 0) sb.append(", ");
+ sb.append("\"").append(values.get(i)).append("\"");
+ }
+ sb.append("])");
+ return sb.toString();
+ }
+ }
+
+ // Arrays (before the complexType check, to handle Array).
+ // Nullable items get `.nullable()` to match the TS type (`Array`
+ // from getTypeDeclaration); top-level nullability of model properties is
+ // applied externally via x-zod-full.
+ if (prop.isArray && prop.items != null) {
+ String item = zodExpr(prop.items);
+ if (prop.items.isNullable) item += ".nullable()";
+ return item + ".array()";
+ }
+
+ // Maps / free-form objects with a typed value (additionalProperties). Zod v4
+ // requires the two-arg z.record(keyType, valueType) signature.
+ if (prop.isMap && prop.additionalProperties != null) {
+ String value = zodExpr(prop.additionalProperties);
+ if (prop.additionalProperties.isNullable) value += ".nullable()";
+ return "z.record(z.string(), " + value + ")";
+ }
+
+ // $ref to another model or enum type.
+ if (prop.complexType != null) {
+ return camelize(prop.complexType) + "Schema";
+ }
+
+ // Primitive types.
+ if (prop.isInteger || prop.isLong) {
+ StringBuilder sb = new StringBuilder("z.coerce.number().int()");
+ if (prop.minimum != null) sb.append(".gte(").append(prop.minimum).append(")");
+ if (prop.maximum != null) sb.append(".lte(").append(prop.maximum).append(")");
+ return sb.toString();
+ }
+ if (prop.isNumber || prop.isFloat || prop.isDouble) {
+ StringBuilder sb = new StringBuilder("z.number()");
+ if (prop.minimum != null) sb.append(".gte(").append(prop.minimum).append(")");
+ if (prop.maximum != null) sb.append(".lte(").append(prop.maximum).append(")");
+ return sb.toString();
+ }
+ if (prop.isBoolean) {
+ return "z.boolean()";
+ }
+ if (prop.isString) {
+ StringBuilder sb = new StringBuilder("z.string()");
+ if (prop.maxLength != null) sb.append(".max(").append(prop.maxLength).append(")");
+ if (prop.minLength != null) sb.append(".min(").append(prop.minLength).append(")");
+ return sb.toString();
+ }
+
+ // Fallback.
+ return "z.any()";
+ }
+
+ // ---------------------------------------------------------------------
+ // Shared model post-processing
+ // ---------------------------------------------------------------------
+
+ /**
+ * Annotate all models with the vendor extensions the express-zod templates rely on:
+ * per-property Zod expressions ({@code x-zod-type}/{@code x-zod-full}), discriminated
+ * unions ({@code x-is-discriminated-union}/{@code x-mapped-models}), non-discriminated
+ * oneOf unions ({@code x-is-union}/{@code x-union-members}), allOf intersections
+ * ({@code x-is-intersection}/{@code x-intersection-parents}/{@code x-has-own-properties}),
+ * enum/object $ref flags, DTO/schema names, and single-value enum literals.
+ *
+ * {@code openAPI} and {@code toModelName} are passed in because this class has no
+ * access to the codegen's protected state; callers use {@code this.openAPI} and
+ * {@code this::toModelName}.
+ */
+ static void annotateModels(Map result, OpenAPI openAPI,
+ Function toModelName) {
+ // Collect enum model names (enums don't need DTO mappers)
+ Set enumModelNames = new HashSet<>();
+ for (ModelsMap modEntry : result.values()) {
+ for (ModelMap innerMo : modEntry.getModels()) {
+ CodegenModel innerCm = innerMo.getModel();
+ if (innerCm.isEnum) {
+ enumModelNames.add(innerCm.classname);
+ }
+ }
+ }
+
+ for (ModelsMap entry : result.values()) {
+ for (ModelMap mo : entry.getModels()) {
+ CodegenModel cm = mo.getModel();
+
+ // Add Zod vendor extensions to each property
+ for (CodegenProperty prop : cm.vars) {
+ addZodVendorExtensions(prop);
+ }
+
+ // Look up original schema from OAS spec (shared by oneOf and allOf detection)
+ Map allSchemas = ModelUtils.getSchemas(openAPI);
+ Schema origSchema = null;
+ for (Map.Entry schemaEntry : allSchemas.entrySet()) {
+ if (toModelName.apply(schemaEntry.getKey()).equals(cm.classname)) {
+ origSchema = schemaEntry.getValue();
+ break;
+ }
+ }
+
+ // Determine if this is a discriminated union
+ if (cm.discriminator != null && cm.oneOf != null && !cm.oneOf.isEmpty()) {
+ cm.vendorExtensions.put("x-is-discriminated-union", true);
+ cm.vendorExtensions.put("x-discriminator-property", cm.discriminator.getPropertyBaseName());
+
+ List> mappedTypes = new ArrayList<>();
+
+ if (cm.discriminator.getMappedModels() != null && !cm.discriminator.getMappedModels().isEmpty()) {
+ // Use explicit mappings from the discriminator
+ for (CodegenDiscriminator.MappedModel mm : cm.discriminator.getMappedModels()) {
+ Map mapped = new HashMap<>();
+ mapped.put("modelName", mm.getModelName());
+ mapped.put("mappingName", mm.getMappingName());
+ mappedTypes.add(mapped);
+ }
+ } else {
+ // Build mappings from oneOf members by inspecting their discriminator property
+ for (String memberName : cm.oneOf) {
+ Map mapped = new HashMap<>();
+ mapped.put("modelName", memberName);
+ // Try to find the discriminator value from the member model's literal property
+ String discValue = findDiscriminatorValue(memberName, cm.discriminator.getPropertyBaseName(), result);
+ mapped.put("mappingName", discValue != null ? discValue : memberName);
+ mappedTypes.add(mapped);
+ }
+ }
+ cm.vendorExtensions.put("x-mapped-models", mappedTypes);
+ }
+
+ // Detect non-discriminated oneOf unions from the original OAS spec
+ if (cm.discriminator == null && !cm.vendorExtensions.containsKey("x-is-discriminated-union")) {
+ if (origSchema != null && origSchema.getOneOf() != null && !origSchema.getOneOf().isEmpty()) {
+ cm.vendorExtensions.put("x-is-union", true);
+
+ // Collect member classnames
+ List memberNames = new ArrayList<>();
+ for (Object memberObj : origSchema.getOneOf()) {
+ Schema memberSchema = (Schema) memberObj;
+ String ref = memberSchema.get$ref();
+ if (ref != null) {
+ memberNames.add(toModelName.apply(ModelUtils.getSimpleRef(ref)));
+ }
+ }
+
+ // Collect property sets per member to find distinguishing properties
+ Map> memberPropSets = new LinkedHashMap<>();
+ for (String memberName : memberNames) {
+ Set props = new LinkedHashSet<>();
+ ModelsMap memberModels = result.get(memberName);
+ if (memberModels != null) {
+ for (ModelMap mm : memberModels.getModels()) {
+ for (CodegenProperty prop : mm.getModel().vars) {
+ props.add(prop.name);
+ }
+ }
+ }
+ memberPropSets.put(memberName, props);
+ }
+
+ // Build x-union-members list with distinguishing properties
+ List> members = new ArrayList<>();
+ for (int i = 0; i < memberNames.size(); i++) {
+ String memberName = memberNames.get(i);
+ Map info = new HashMap<>();
+ info.put("modelName", memberName);
+
+ if (i < memberNames.size() - 1) {
+ // Find a property unique to this member
+ Set myProps = memberPropSets.getOrDefault(memberName, Collections.emptySet());
+ for (String prop : myProps) {
+ boolean unique = true;
+ for (Map.Entry> other : memberPropSets.entrySet()) {
+ if (!other.getKey().equals(memberName) && other.getValue().contains(prop)) {
+ unique = false;
+ break;
+ }
+ }
+ if (unique) {
+ info.put("hasDistinguishingProperty", true);
+ info.put("distinguishingProperty", prop);
+ break;
+ }
+ }
+ }
+ // Last member is always the fallback (no distinguishing property needed)
+ members.add(info);
+ }
+
+ cm.vendorExtensions.put("x-union-members", members);
+ }
+ }
+
+ // Detect allOf intersection types
+ if (origSchema != null && origSchema.getAllOf() != null && !origSchema.getAllOf().isEmpty()) {
+ List parentNames = new ArrayList<>();
+ for (Object member : origSchema.getAllOf()) {
+ Schema memberSchema = (Schema) member;
+ if (memberSchema.get$ref() != null) {
+ parentNames.add(toModelName.apply(ModelUtils.getSimpleRef(memberSchema.get$ref())));
+ }
+ }
+
+ if (!parentNames.isEmpty()) {
+ cm.vendorExtensions.put("x-is-intersection", true);
+
+ List> parents = new ArrayList<>();
+ Set parentPropertyNames = new HashSet<>();
+ for (String parentName : parentNames) {
+ Map parentInfo = new HashMap<>();
+ parentInfo.put("modelName", parentName);
+ parents.add(parentInfo);
+
+ ModelsMap parentModels = result.get(parentName);
+ if (parentModels != null) {
+ for (ModelMap pmm : parentModels.getModels()) {
+ for (CodegenProperty prop : pmm.getModel().vars) {
+ parentPropertyNames.add(prop.name);
+ }
+ }
+ }
+ }
+ cm.vendorExtensions.put("x-intersection-parents", parents);
+
+ boolean hasOwnProperties = false;
+ for (CodegenProperty prop : cm.vars) {
+ if (!parentPropertyNames.contains(prop.name)) {
+ prop.vendorExtensions.put("x-is-own-property", true);
+ hasOwnProperties = true;
+ }
+ }
+ cm.vendorExtensions.put("x-has-own-properties", hasOwnProperties);
+ }
+ }
+
+ // Check if model has properties that reference other object models
+ // (not enums - enums are identity-mapped and don't need DTO mappers)
+ for (CodegenProperty prop : cm.vars) {
+ if (prop.complexType != null && !prop.isArray) {
+ if (enumModelNames.contains(prop.complexType)) {
+ // Reference to an enum type - mark for DTO template to use types. prefix
+ prop.vendorExtensions.put("x-is-enum-ref", true);
+ prop.vendorExtensions.put("x-enum-type", prop.complexType);
+ } else {
+ // Reference to an object type - needs DTO mapper
+ prop.vendorExtensions.put("x-is-ref", true);
+ prop.vendorExtensions.put("x-ref-type", prop.complexType);
+ }
+ } else if (prop.isArray && prop.items != null && prop.items.complexType != null) {
+ if (enumModelNames.contains(prop.items.complexType)) {
+ prop.vendorExtensions.put("x-is-enum-ref", true);
+ prop.vendorExtensions.put("x-enum-type", prop.items.complexType);
+ } else {
+ prop.vendorExtensions.put("x-is-ref", true);
+ prop.vendorExtensions.put("x-ref-type", prop.items.complexType);
+ }
+ }
+ }
+
+ // Add DTO-related vendor extensions
+ cm.vendorExtensions.put("x-dto-name", cm.classname + "Dto");
+ cm.vendorExtensions.put("x-schema-name", cm.classname + "Schema");
+
+ // Check if has single-value enum properties (literal types)
+ for (CodegenProperty prop : cm.vars) {
+ if (prop.isEnum && prop.allowableValues != null) {
+ List> values = (List>) prop.allowableValues.get("values");
+ if (values != null && values.size() == 1) {
+ prop.vendorExtensions.put("x-is-literal", true);
+ prop.vendorExtensions.put("x-literal-value", values.get(0).toString());
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Add Zod-specific vendor extensions to a model property: the bare Zod expression
+ * ({@code x-zod-type}) and the full expression including nullability and optionality
+ * ({@code x-zod-full}).
+ */
+ private static void addZodVendorExtensions(CodegenProperty prop) {
+ String zodType = zodExpr(prop);
+ prop.vendorExtensions.put("x-zod-type", zodType);
+
+ String fullZod = zodType;
+ if (prop.isNullable) {
+ fullZod = fullZod + ".nullable()";
+ }
+ if (!prop.required) {
+ fullZod = fullZod + ".optional()";
+ }
+ prop.vendorExtensions.put("x-zod-full", fullZod);
+ }
+
+ /**
+ * Find the discriminator property's literal value in a member model.
+ * E.g., for UserLoginPrincipal with discriminator "kind", returns "USER_LOGIN".
+ */
+ private static String findDiscriminatorValue(String modelName, String discriminatorProperty,
+ Map allModels) {
+ ModelsMap modelsMap = allModels.get(modelName);
+ if (modelsMap == null) return null;
+
+ for (ModelMap mo : modelsMap.getModels()) {
+ CodegenModel cm = mo.getModel();
+ for (CodegenProperty prop : cm.vars) {
+ if (prop.baseName.equals(discriminatorProperty) || prop.name.equals(discriminatorProperty)) {
+ if (prop.isEnum && prop.allowableValues != null) {
+ List> values = (List>) prop.allowableValues.get("values");
+ if (values != null && values.size() == 1) {
+ return values.get(0).toString();
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Topologically sort models so that leaf types (enums, simple objects) come before
+ * models that reference them. This ensures correct declaration order in generated schemas.
+ */
+ @SuppressWarnings("unchecked")
+ static List topologicallySortModels(List models) {
+ // Build maps from classname to model entry and dependencies
+ Map modelByName = new LinkedHashMap<>();
+ Map> dependencies = new LinkedHashMap<>();
+
+ for (Object modelEntry : models) {
+ Map entry = (Map) modelEntry;
+ CodegenModel cm = (CodegenModel) entry.get("model");
+ if (cm == null) continue;
+
+ modelByName.put(cm.classname, modelEntry);
+
+ Set deps = new LinkedHashSet<>();
+ for (CodegenProperty prop : cm.vars) {
+ if (prop.complexType != null) {
+ deps.add(prop.complexType);
+ }
+ if (prop.isArray && prop.items != null && prop.items.complexType != null) {
+ deps.add(prop.items.complexType);
+ }
+ }
+ // oneOf dependencies
+ if (cm.oneOf != null) {
+ deps.addAll(cm.oneOf);
+ }
+ // Also include non-discriminated union member dependencies
+ if (cm.vendorExtensions.containsKey("x-union-members")) {
+ List> unionMembers =
+ (List>) cm.vendorExtensions.get("x-union-members");
+ for (Map member : unionMembers) {
+ deps.add((String) member.get("modelName"));
+ }
+ }
+ // Also include allOf intersection parent dependencies
+ if (cm.vendorExtensions.containsKey("x-intersection-parents")) {
+ List> intersectionParents =
+ (List>) cm.vendorExtensions.get("x-intersection-parents");
+ for (Map parent : intersectionParents) {
+ deps.add(parent.get("modelName"));
+ }
+ }
+ // Remove self-references
+ deps.remove(cm.classname);
+ dependencies.put(cm.classname, deps);
+ }
+
+ // DFS-based topological sort
+ List sorted = new ArrayList<>();
+ Set visited = new LinkedHashSet<>();
+ Set visiting = new LinkedHashSet<>();
+
+ for (String name : modelByName.keySet()) {
+ if (!visited.contains(name)) {
+ topoVisit(name, modelByName, dependencies, visited, visiting, sorted);
+ }
+ }
+
+ return sorted;
+ }
+
+ private static void topoVisit(String name, Map modelByName,
+ Map> dependencies,
+ Set visited, Set visiting, List sorted) {
+ if (visited.contains(name)) return;
+ if (visiting.contains(name)) return; // cycle detected, break it
+ visiting.add(name);
+
+ Set deps = dependencies.getOrDefault(name, Collections.emptySet());
+ for (String dep : deps) {
+ if (modelByName.containsKey(dep)) {
+ topoVisit(dep, modelByName, dependencies, visited, visiting, sorted);
+ }
+ }
+
+ visiting.remove(name);
+ visited.add(name);
+ if (modelByName.containsKey(name)) {
+ sorted.add(modelByName.get(name));
+ }
+ }
+
+ // ---------------------------------------------------------------------
+ // Response / body shape resolution
+ // ---------------------------------------------------------------------
+
+ /**
+ * Resolve an operation's response ({@code returnType}) into a Zod schema, wire type,
+ * and mapper. {@code dir} is {@code TO_WIRE} on the server (domain result -> wire)
+ * and {@code FROM_WIRE} on the client (wire json -> domain).
+ */
+ static Resolved resolveResponse(CodegenOperation op, Direction dir) {
+ CodegenProperty rp = op.returnProperty;
+ String zod = zodExpr(rp);
+ if (rp == null) {
+ // DefaultCodegen assigns returnType and returnProperty together, so this is
+ // unreachable when callers guard on returnType != null; identity as a defensive
+ // fallback rather than fabricating a "Dto" symbol.
+ return new Resolved(zod, op.returnType, op.returnType, null);
+ }
+ Shape shape = shapeOf(rp, dir, 0);
+ return new Resolved(zod, shape.dtoType, shape.domainType, shape.mapper);
+ }
+
+ /**
+ * Resolve a request body parameter into a wire type and mapper. {@code zod} is the
+ * body's Zod expression (built by the caller's parameter builder). {@code dir} is
+ * {@code FROM_WIRE} on the server (req.body -> domain) and {@code TO_WIRE} on the
+ * client (domain -> wire before send).
+ */
+ static Resolved resolveBody(CodegenParameter body, Direction dir, String zod) {
+ Shape shape;
+ if (body.isArray && body.items != null) {
+ shape = arrayShape(body.items, dir, 0);
+ } else if (body.isMap && body.additionalProperties != null) {
+ shape = mapShape(body.additionalProperties, dir, 0);
+ } else if (body.isModel) {
+ // For a scalar model body, CodegenParameter.dataType is the classname of the
+ // referenced model (e.g. "Pet"). Bodies that dereference to a primitive (e.g.
+ // a $ref'd enum handled as string by fromRequestBody) have isModel=false.
+ shape = new Shape("dtos." + body.dataType + "Dto", "types." + body.dataType,
+ "mappers." + mapPrefix(dir) + body.dataType + "Dto");
+ } else {
+ // Bare primitive: domain == wire, identity mapping.
+ shape = new Shape(body.dataType, body.dataType, null);
+ }
+ return new Resolved(zod, shape.dtoType, shape.domainType, shape.mapper);
+ }
+
+ /** Wire type, domain type, and mapper (null => identity) for a resolved shape. */
+ private static final class Shape {
+ final String dtoType;
+ final String domainType;
+ final String mapper;
+
+ Shape(String dtoType, String domainType, String mapper) {
+ this.dtoType = dtoType;
+ this.domainType = domainType;
+ this.mapper = mapper;
+ }
+ }
+
+ /**
+ * Recursively resolve a property's shape. Containers recurse into their element/value
+ * type (so nested shapes like {@code Array>} or map-of-array compose
+ * correctly); {@code depth} suffixes lambda parameters to avoid shadowing.
+ *
+ * Note: container properties carry the innermost ref in {@code complexType}
+ * (DefaultCodegen.updatePropertyForArray/Map), so isArray/isMap MUST be checked
+ * before the complexType leaf branches.
+ */
+ private static Shape shapeOf(CodegenProperty p, Direction dir, int depth) {
+ if (p.isArray && p.items != null) {
+ return arrayShape(p.items, dir, depth);
+ }
+ if (p.isMap && p.additionalProperties != null) {
+ return mapShape(p.additionalProperties, dir, depth);
+ }
+ if (p.complexType != null && !p.isEnum && !p.isEnumRef) {
+ // Object model — has a generated Dto + mappers. $ref'd enums set isEnumRef
+ // (not isEnum) and get neither, so they must not take this branch.
+ return new Shape("dtos." + p.complexType + "Dto", "types." + p.complexType,
+ "mappers." + mapPrefix(dir) + p.complexType + "Dto");
+ }
+ if (p.complexType != null) {
+ // Enum (inline via isEnum or $ref via isEnumRef) — domain == wire, identity.
+ return new Shape("types." + p.complexType, "types." + p.complexType, null);
+ }
+ // Primitive or free-form object — domain == wire, identity.
+ return new Shape(p.dataType, p.dataType, null);
+ }
+
+ private static Shape arrayShape(CodegenProperty items, Direction dir, int depth) {
+ Shape inner = shapeOf(items, dir, depth + 1);
+ String dtoElem = inner.dtoType;
+ String domainElem = inner.domainType;
+ String elemMapper = inner.mapper;
+ if (items.isNullable) {
+ // Match getTypeDeclaration's Array and skip nulls when mapping.
+ dtoElem = "(" + dtoElem + " | null)";
+ domainElem = "(" + domainElem + " | null)";
+ if (elemMapper != null) {
+ elemMapper = nullSafe(elemMapper, depth);
+ }
+ }
+ String mapper = elemMapper == null
+ ? null
+ : "(xs" + depth + ") => xs" + depth + ".map(" + elemMapper + ")";
+ return new Shape(dtoElem + "[]", domainElem + "[]", mapper);
+ }
+
+ private static Shape mapShape(CodegenProperty values, Direction dir, int depth) {
+ Shape inner = shapeOf(values, dir, depth + 1);
+ String dtoVal = inner.dtoType;
+ String domainVal = inner.domainType;
+ String valMapper = inner.mapper;
+ if (values.isNullable) {
+ dtoVal = dtoVal + " | null";
+ domainVal = domainVal + " | null";
+ if (valMapper != null) {
+ valMapper = nullSafe(valMapper, depth);
+ }
+ }
+ String mapper = valMapper == null
+ ? null
+ : "(m" + depth + ") => Object.fromEntries(Object.entries(m" + depth
+ + ").map(([k" + depth + ", v" + depth + "]) => [k" + depth
+ + ", (" + valMapper + ")(v" + depth + ")]))";
+ return new Shape("{ [key: string]: " + dtoVal + " }",
+ "{ [key: string]: " + domainVal + " }", mapper);
+ }
+
+ /** Wrap a mapper so null/undefined elements pass through untouched. */
+ private static String nullSafe(String mapper, int depth) {
+ String e = "e" + depth;
+ return "(" + e + ") => " + e + " == null ? " + e + " : (" + mapper + ")(" + e + ")";
+ }
+
+ private static String mapPrefix(Direction dir) {
+ return dir == Direction.TO_WIRE ? "mapTo" : "mapFrom";
+ }
+}
diff --git a/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig b/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig
index 57a8381c0c22..9fa6ec5de1d1 100644
--- a/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig
+++ b/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig
@@ -155,6 +155,7 @@ org.openapitools.codegen.languages.TypeScriptClientCodegen
org.openapitools.codegen.languages.TypeScriptAngularClientCodegen
org.openapitools.codegen.languages.TypeScriptAureliaClientCodegen
org.openapitools.codegen.languages.TypeScriptAxiosClientCodegen
+org.openapitools.codegen.languages.TypeScriptExpressZodServerCodegen
org.openapitools.codegen.languages.TypeScriptFetchClientCodegen
org.openapitools.codegen.languages.TypeScriptInversifyClientCodegen
org.openapitools.codegen.languages.TypeScriptJqueryClientCodegen
diff --git a/modules/openapi-generator/src/main/resources/typescript-express-zod-server/api.mustache b/modules/openapi-generator/src/main/resources/typescript-express-zod-server/api.mustache
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/modules/openapi-generator/src/main/resources/typescript-express-zod-server/dtos/index.mustache b/modules/openapi-generator/src/main/resources/typescript-express-zod-server/dtos/index.mustache
new file mode 100644
index 000000000000..cfd0927bbd2b
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/typescript-express-zod-server/dtos/index.mustache
@@ -0,0 +1,2 @@
+export * from "./types";
+export * from "./mappers";
diff --git a/modules/openapi-generator/src/main/resources/typescript-express-zod-server/dtos/mappers.mustache b/modules/openapi-generator/src/main/resources/typescript-express-zod-server/dtos/mappers.mustache
new file mode 100644
index 000000000000..ab2668275e7f
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/typescript-express-zod-server/dtos/mappers.mustache
@@ -0,0 +1,146 @@
+/**
+ * This code was generated by openapi-generator (typescript-express-zod-server).
+ *
+ * Changes to this file may cause incorrect behavior and will be lost if
+ * the code is regenerated.
+ */
+
+{{#hasDiscriminatedUnion}}
+import { ZodError } from "zod";
+
+{{/hasDiscriminatedUnion}}
+import type * as types from "../types";
+import type * as dtos from "./types";
+
+function compact(obj: T): T {
+ return Object.keys(obj).reduce((acc, key) => {
+ const value = obj[key as keyof T];
+ if (value !== undefined) {
+ acc[key as keyof T] = value;
+ }
+ return acc;
+ }, {} as T);
+}
+
+{{#models}}
+{{#model}}
+{{^isEnum}}
+{{#vendorExtensions.x-is-discriminated-union}}
+export function mapFrom{{classname}}Dto(dto: dtos.{{classname}}Dto): types.{{classname}} {
+ switch (dto.{{{vendorExtensions.x-discriminator-property}}}) {
+{{#vendorExtensions.x-mapped-models}}
+ case "{{mappingName}}":
+ return mapFrom{{modelName}}Dto(dto);
+{{/vendorExtensions.x-mapped-models}}
+ default:
+ // Unknown discriminator on inbound (wire -> domain) data is a client
+ // input error: throw a ZodError so the caller maps it to a 4xx response.
+ throw new ZodError([
+ {
+ code: "custom",
+ path: ["{{{vendorExtensions.x-discriminator-property}}}"],
+ message: `Unknown {{classname}} discriminator: ${(dto as { {{{vendorExtensions.x-discriminator-property}}}?: unknown }).{{{vendorExtensions.x-discriminator-property}}}}`,
+ },
+ ]);
+ }
+}
+
+export function mapTo{{classname}}Dto(obj: types.{{classname}}): dtos.{{classname}}Dto {
+ switch (obj.{{{vendorExtensions.x-discriminator-property}}}) {
+{{#vendorExtensions.x-mapped-models}}
+ case "{{mappingName}}":
+ return mapTo{{modelName}}Dto(obj);
+{{/vendorExtensions.x-mapped-models}}
+ default:
+ throw new Error(
+ `Unknown {{classname}} discriminator: ${(obj as { {{{vendorExtensions.x-discriminator-property}}}?: unknown }).{{{vendorExtensions.x-discriminator-property}}}}`,
+ );
+ }
+}
+
+{{/vendorExtensions.x-is-discriminated-union}}
+{{#vendorExtensions.x-is-union}}
+export function mapFrom{{classname}}Dto(dto: dtos.{{classname}}Dto): types.{{classname}} {
+{{#vendorExtensions.x-union-members}}
+{{#hasDistinguishingProperty}}
+ if ('{{distinguishingProperty}}' in dto) return mapFrom{{modelName}}Dto(dto as dtos.{{modelName}}Dto);
+{{/hasDistinguishingProperty}}
+{{^hasDistinguishingProperty}}
+ return mapFrom{{modelName}}Dto(dto as dtos.{{modelName}}Dto);
+{{/hasDistinguishingProperty}}
+{{/vendorExtensions.x-union-members}}
+}
+
+export function mapTo{{classname}}Dto(obj: types.{{classname}}): dtos.{{classname}}Dto {
+{{#vendorExtensions.x-union-members}}
+{{#hasDistinguishingProperty}}
+ if ('{{distinguishingProperty}}' in obj) return mapTo{{modelName}}Dto(obj as types.{{modelName}});
+{{/hasDistinguishingProperty}}
+{{^hasDistinguishingProperty}}
+ return mapTo{{modelName}}Dto(obj as any);
+{{/hasDistinguishingProperty}}
+{{/vendorExtensions.x-union-members}}
+}
+
+{{/vendorExtensions.x-is-union}}
+{{^vendorExtensions.x-is-discriminated-union}}
+{{^vendorExtensions.x-is-union}}
+{{#hasVars}}
+export function mapFrom{{classname}}Dto(
+ dto: dtos.{{classname}}Dto,
+): types.{{classname}} {
+ return compact({
+{{#vars}}
+{{#vendorExtensions.x-is-ref}}
+{{#isArray}}
+ {{name}}:
+ dto.{{name}} == null
+ ? dto.{{name}}
+ : dto.{{name}}.map(mapFrom{{vendorExtensions.x-ref-type}}Dto),
+{{/isArray}}
+{{^isArray}}
+ {{name}}:
+ dto.{{name}} == null
+ ? dto.{{name}}
+ : mapFrom{{vendorExtensions.x-ref-type}}Dto(dto.{{name}}),
+{{/isArray}}
+{{/vendorExtensions.x-is-ref}}
+{{^vendorExtensions.x-is-ref}}
+ {{name}}: dto.{{name}},
+{{/vendorExtensions.x-is-ref}}
+{{/vars}}
+ });
+}
+
+export function mapTo{{classname}}Dto(
+ obj: types.{{classname}},
+): dtos.{{classname}}Dto {
+ return compact({
+{{#vars}}
+{{#vendorExtensions.x-is-ref}}
+{{#isArray}}
+ {{name}}:
+ obj.{{name}} == null
+ ? obj.{{name}}
+ : obj.{{name}}.map(mapTo{{vendorExtensions.x-ref-type}}Dto),
+{{/isArray}}
+{{^isArray}}
+ {{name}}:
+ obj.{{name}} == null
+ ? obj.{{name}}
+ : mapTo{{vendorExtensions.x-ref-type}}Dto(obj.{{name}}),
+{{/isArray}}
+{{/vendorExtensions.x-is-ref}}
+{{^vendorExtensions.x-is-ref}}
+ {{name}}: obj.{{name}},
+{{/vendorExtensions.x-is-ref}}
+{{/vars}}
+ });
+}
+
+{{/hasVars}}
+{{/vendorExtensions.x-is-union}}
+{{/vendorExtensions.x-is-discriminated-union}}
+{{/isEnum}}
+{{/model}}
+{{/models}}
diff --git a/modules/openapi-generator/src/main/resources/typescript-express-zod-server/dtos/types.mustache b/modules/openapi-generator/src/main/resources/typescript-express-zod-server/dtos/types.mustache
new file mode 100644
index 000000000000..9438e0969616
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/typescript-express-zod-server/dtos/types.mustache
@@ -0,0 +1,124 @@
+/**
+ * This code was generated by openapi-generator (typescript-express-zod-server).
+ *
+ * Changes to this file may cause incorrect behavior and will be lost if
+ * the code is regenerated.
+ */
+
+import type * as types from "../types";
+
+{{#models}}
+{{#model}}
+{{#isEnum}}
+{{! Enums don't need a DTO - they're used directly from the types module }}
+{{/isEnum}}
+{{^isEnum}}
+{{#vendorExtensions.x-is-discriminated-union}}
+/** The over-the-wire representation of the {@link types.{{classname}}|{{classname}}} type. */
+export type {{classname}}Dto = {{#vendorExtensions.x-mapped-models}}{{modelName}}Dto{{^-last}} | {{/-last}}{{/vendorExtensions.x-mapped-models}};
+
+{{/vendorExtensions.x-is-discriminated-union}}
+{{^vendorExtensions.x-is-discriminated-union}}
+{{#vendorExtensions.x-is-union}}
+/** The over-the-wire representation of the {@link types.{{classname}}|{{classname}}} type. */
+export type {{classname}}Dto = {{#vendorExtensions.x-union-members}}{{modelName}}Dto{{^-last}} | {{/-last}}{{/vendorExtensions.x-union-members}};
+
+{{/vendorExtensions.x-is-union}}
+{{^vendorExtensions.x-is-union}}
+{{#vendorExtensions.x-is-intersection}}
+/** The over-the-wire representation of the {@link types.{{classname}}|{{classname}}} type. */
+{{#vendorExtensions.x-has-own-properties}}
+export type {{classname}}Dto = {
+{{#vars}}
+{{#vendorExtensions.x-is-own-property}}
+{{#vendorExtensions.x-is-literal}}
+ {{name}}: "{{{vendorExtensions.x-literal-value}}}";
+{{/vendorExtensions.x-is-literal}}
+{{^vendorExtensions.x-is-literal}}
+{{#vendorExtensions.x-is-enum-ref}}
+{{#isArray}}
+ {{name}}{{^required}}?{{/required}}: types.{{{vendorExtensions.x-enum-type}}}[]{{#isNullable}} | null{{/isNullable}};
+{{/isArray}}
+{{^isArray}}
+ {{name}}{{^required}}?{{/required}}: types.{{{vendorExtensions.x-enum-type}}}{{#isNullable}} | null{{/isNullable}};
+{{/isArray}}
+{{/vendorExtensions.x-is-enum-ref}}
+{{^vendorExtensions.x-is-enum-ref}}
+{{#isArray}}
+{{#vendorExtensions.x-is-ref}}
+ {{name}}{{^required}}?{{/required}}: {{{vendorExtensions.x-ref-type}}}Dto[]{{#isNullable}} | null{{/isNullable}};
+{{/vendorExtensions.x-is-ref}}
+{{^vendorExtensions.x-is-ref}}
+ {{name}}{{^required}}?{{/required}}: {{{dataType}}}{{#isNullable}} | null{{/isNullable}};
+{{/vendorExtensions.x-is-ref}}
+{{/isArray}}
+{{^isArray}}
+{{#vendorExtensions.x-is-ref}}
+ {{name}}{{^required}}?{{/required}}: {{{vendorExtensions.x-ref-type}}}Dto{{#isNullable}} | null{{/isNullable}};
+{{/vendorExtensions.x-is-ref}}
+{{^vendorExtensions.x-is-ref}}
+ {{name}}{{^required}}?{{/required}}: {{{dataType}}}{{#isNullable}} | null{{/isNullable}};
+{{/vendorExtensions.x-is-ref}}
+{{/isArray}}
+{{/vendorExtensions.x-is-enum-ref}}
+{{/vendorExtensions.x-is-literal}}
+{{/vendorExtensions.x-is-own-property}}
+{{/vars}}
+}{{#vendorExtensions.x-intersection-parents}} & {{modelName}}Dto{{/vendorExtensions.x-intersection-parents}};
+{{/vendorExtensions.x-has-own-properties}}
+{{^vendorExtensions.x-has-own-properties}}
+export type {{classname}}Dto = {{#vendorExtensions.x-intersection-parents}}{{modelName}}Dto{{^-last}} & {{/-last}}{{/vendorExtensions.x-intersection-parents}};
+{{/vendorExtensions.x-has-own-properties}}
+
+{{/vendorExtensions.x-is-intersection}}
+{{^vendorExtensions.x-is-intersection}}
+{{#hasVars}}
+/** The over-the-wire representation of the {@link types.{{classname}}|{{classname}}} type. */
+export type {{classname}}Dto = {
+{{#vars}}
+{{#vendorExtensions.x-is-literal}}
+ {{name}}: "{{{vendorExtensions.x-literal-value}}}";
+{{/vendorExtensions.x-is-literal}}
+{{^vendorExtensions.x-is-literal}}
+{{#vendorExtensions.x-is-enum-ref}}
+{{#isArray}}
+ {{name}}{{^required}}?{{/required}}: types.{{{vendorExtensions.x-enum-type}}}[]{{#isNullable}} | null{{/isNullable}};
+{{/isArray}}
+{{^isArray}}
+ {{name}}{{^required}}?{{/required}}: types.{{{vendorExtensions.x-enum-type}}}{{#isNullable}} | null{{/isNullable}};
+{{/isArray}}
+{{/vendorExtensions.x-is-enum-ref}}
+{{^vendorExtensions.x-is-enum-ref}}
+{{#isArray}}
+{{#vendorExtensions.x-is-ref}}
+ {{name}}{{^required}}?{{/required}}: {{{vendorExtensions.x-ref-type}}}Dto[]{{#isNullable}} | null{{/isNullable}};
+{{/vendorExtensions.x-is-ref}}
+{{^vendorExtensions.x-is-ref}}
+ {{name}}{{^required}}?{{/required}}: {{{dataType}}}{{#isNullable}} | null{{/isNullable}};
+{{/vendorExtensions.x-is-ref}}
+{{/isArray}}
+{{^isArray}}
+{{#vendorExtensions.x-is-ref}}
+ {{name}}{{^required}}?{{/required}}: {{{vendorExtensions.x-ref-type}}}Dto{{#isNullable}} | null{{/isNullable}};
+{{/vendorExtensions.x-is-ref}}
+{{^vendorExtensions.x-is-ref}}
+ {{name}}{{^required}}?{{/required}}: {{{dataType}}}{{#isNullable}} | null{{/isNullable}};
+{{/vendorExtensions.x-is-ref}}
+{{/isArray}}
+{{/vendorExtensions.x-is-enum-ref}}
+{{/vendorExtensions.x-is-literal}}
+{{/vars}}
+};
+
+{{/hasVars}}
+{{^hasVars}}
+/** The over-the-wire representation of the {@link types.{{classname}}|{{classname}}} type. */
+export type {{classname}}Dto = types.{{classname}};
+
+{{/hasVars}}
+{{/vendorExtensions.x-is-intersection}}
+{{/vendorExtensions.x-is-union}}
+{{/vendorExtensions.x-is-discriminated-union}}
+{{/isEnum}}
+{{/model}}
+{{/models}}
diff --git a/modules/openapi-generator/src/main/resources/typescript-express-zod-server/express/auth-middleware.mustache b/modules/openapi-generator/src/main/resources/typescript-express-zod-server/express/auth-middleware.mustache
new file mode 100644
index 000000000000..9455ab64e0bc
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/typescript-express-zod-server/express/auth-middleware.mustache
@@ -0,0 +1,58 @@
+{{#hasAuthOperations}}
+/**
+ * This code was generated by openapi-generator (typescript-express-zod-server).
+ *
+ * Changes to this file may cause incorrect behavior and will be lost if
+ * the code is regenerated.
+ */
+
+import type { RequestHandler } from "express";
+import { handledException } from "./errors";
+import type { Middleware } from "./types";
+
+export type PermissionGrantResolver = (params: {
+ role: string;
+ permission: string;
+}) => Promise;
+
+const requirePermissionGrant = (
+ permission: string,
+ resolver: PermissionGrantResolver
+): RequestHandler => {
+ return async (req, _, next) => {
+ if (!req.principal) {
+ return next(
+ handledException(401, [
+ { title: "Unauthorized", status: 401, code: "UNAUTHORIZED" },
+ ])
+ );
+ }
+
+ const role = req.principal.role;
+ const hasPermission = await resolver({ role, permission });
+
+ if (hasPermission) {
+ next();
+ } else {
+ next(
+ handledException(403, [
+ {
+ title: "Forbidden",
+ status: 403,
+ code: "FORBIDDEN",
+ detail: `You do not have permission to perform this action. Required permission: ${permission}`,
+ },
+ ])
+ );
+ }
+ };
+};
+
+export const authMiddleware = (
+ resolver: PermissionGrantResolver
+): Middleware => ({
+{{#authOperations}}
+ {{operationId}}: requirePermissionGrant("{{permission}}", resolver),
+{{/authOperations}}
+});
+{{/hasAuthOperations}}
diff --git a/modules/openapi-generator/src/main/resources/typescript-express-zod-server/express/errors.mustache b/modules/openapi-generator/src/main/resources/typescript-express-zod-server/express/errors.mustache
new file mode 100644
index 000000000000..b37504ff8a1a
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/typescript-express-zod-server/express/errors.mustache
@@ -0,0 +1,71 @@
+import type { ZodIssue } from "zod";
+
+import type * as types from "../types";
+
+export function methodNotAllowed(): MethodNotAllowedError {
+ return {
+ code: "METHOD_NOT_ALLOWED",
+ status: 405,
+ title: "Method Not Allowed",
+ };
+}
+
+export function isMethodNotAllowed(error: any): error is MethodNotAllowedError {
+ return typeof error === "object" && error !== null && error.code === "METHOD_NOT_ALLOWED";
+}
+
+export type MethodNotAllowedError = {
+ code: "METHOD_NOT_ALLOWED";
+ status: number;
+ title: string;
+};
+
+export function validationErrors(
+ status: 400 | 500,
+ errors: ZodIssue[],
+): ValidationErrorsError {
+ return { code: "VALIDATION_ERRORS", status, errors };
+}
+
+export function isValidationErrors(error: any): error is ValidationErrorsError {
+ return typeof error === "object" && error !== null && error.code === "VALIDATION_ERRORS";
+}
+
+export type ValidationErrorsError = {
+ code: "VALIDATION_ERRORS";
+ status: number;
+ errors: ZodIssue[];
+};
+
+export function handledException(
+ status: number,
+ errors: types.ModelError[],
+): HandledExceptionError {
+ return { code: "HANDLED_EXCEPTION", status, errors };
+}
+
+export function isHandledException(error: any): error is HandledExceptionError {
+ return typeof error === "object" && error !== null && error.code === "HANDLED_EXCEPTION";
+}
+
+export type HandledExceptionError = {
+ code: "HANDLED_EXCEPTION";
+ status: number;
+ errors: types.ModelError[];
+};
+
+export function unhandledException(exception: any): UnhandledExceptionError {
+ return { code: "UNHANDLED_EXCEPTION", status: 500, exception };
+}
+
+export function isUnhandledException(
+ error: any,
+): error is UnhandledExceptionError {
+ return typeof error === "object" && error !== null && error.code === "UNHANDLED_EXCEPTION";
+}
+
+export type UnhandledExceptionError = {
+ code: "UNHANDLED_EXCEPTION";
+ status: number;
+ exception: any;
+};
diff --git a/modules/openapi-generator/src/main/resources/typescript-express-zod-server/express/handlers.mustache b/modules/openapi-generator/src/main/resources/typescript-express-zod-server/express/handlers.mustache
new file mode 100644
index 000000000000..e744a98a0875
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/typescript-express-zod-server/express/handlers.mustache
@@ -0,0 +1,187 @@
+/**
+ * This code was generated by openapi-generator (typescript-express-zod-server).
+ *
+ * Changes to this file may cause incorrect behavior and will be lost if
+ * the code is regenerated.
+ */
+
+import type { Request, Response, NextFunction } from "express";
+import { ZodError } from "zod";
+
+import type * as types from "../types";
+import * as schemas from "../schemas";
+import * as mappers from "../dtos/mappers";
+
+import * as errors from "./errors";
+import type * as expressTypes from "./types";
+
+{{#allOperations}}
+/** {{httpMethodUpper}} {{path}} */
+export const {{handlerName}} =
+ (
+ getService: (req: Request, res: Response) => types.{{serviceName}},
+ ): expressTypes.{{operationIdPascal}}RequestHandler =>
+ async (req, res, next) => {
+ try {
+{{#hasParams}}
+ // Parse parameters from request
+{{#hasNoParams}}
+{{/hasNoParams}}
+{{^hasNoParams}}
+{{#allParamsOptional}}
+ const params: types.{{operationIdPascal}}Params | undefined =
+ schemas.{{operationIdPascal}}ParamsSchema.optional().parse({
+{{/allParamsOptional}}
+{{^allParamsOptional}}
+ const params: types.{{operationIdPascal}}Params =
+ schemas.{{operationIdPascal}}ParamsSchema.parse({
+{{/allParamsOptional}}
+{{#pathParams}}
+ {{name}}: req.params.{{name}},
+{{/pathParams}}
+{{#queryParams}}
+{{#hasDifferentName}}
+ {{name}}: req.query["{{baseName}}"],
+{{/hasDifferentName}}
+{{^hasDifferentName}}
+ {{name}}: req.query.{{baseName}},
+{{/hasDifferentName}}
+{{/queryParams}}
+{{#hasBodyParam}}
+ {{bodyParam.name}}: {{#bodyParam.mapFn}}({{{bodyParam.mapFn}}})(req.body){{/bodyParam.mapFn}}{{^bodyParam.mapFn}}req.body{{/bodyParam.mapFn}},
+{{/hasBodyParam}}
+ });
+
+{{/hasNoParams}}
+{{/hasParams}}
+ // Execute service method
+ const service = getService(req, res);
+{{#hasSSE}}
+ const invoked: unknown = service.{{operationId}}({{#hasParams}}params{{/hasParams}});
+ // Support services that return an async iterable directly or a promise resolving to one.
+ const result: unknown =
+ invoked != null &&
+ typeof (invoked as { then?: unknown }).then === "function" &&
+ !(Symbol.asyncIterator in Object(invoked))
+ ? await invoked
+ : invoked;
+
+ if (Symbol.asyncIterator in Object(result)) {
+ res.setHeader("Content-Type", "text/event-stream");
+ res.setHeader("Cache-Control", "no-cache");
+ res.setHeader("Connection", "keep-alive");
+ res.setHeader("X-Accel-Buffering", "no");
+ res.flushHeaders();
+ res.socket?.setNoDelay(true);
+ try {
+ for await (const chunk of result as AsyncIterable) {
+ const dto = mappers.{{{sseDtoMapper}}}(chunk);
+ res.write(`id: ${dto.id}\nevent: ${dto.event}\ndata: ${JSON.stringify(dto.data)}\n\n`);
+ if (typeof (res as any).flush === "function") (res as any).flush();
+ }
+ } catch (streamErr) {
+ res.write(`event: error\ndata: ${JSON.stringify({ message: streamErr instanceof Error ? streamErr.message : "Stream error" })}\n\n`);
+ } finally {
+ res.end();
+ }
+ } else {
+ const resolved = await (result as Promise<{{{responseDomainGeneric}}}>);
+ const status = getHttpStatus(200, resolved);
+ if (isError(resolved)) {
+ next(errors.handledException(status, resolved.errors));
+ } else {
+ return sendResponse(
+ res,
+ next,
+ status,
+ {{#responseDtoMapper}}({{{responseDtoMapper}}})(resolved){{/responseDtoMapper}}{{^responseDtoMapper}}resolved{{/responseDtoMapper}},
+{{#responseSchema}}
+ (payload) => schemas.{{{responseSchema}}}.parse(payload),
+{{/responseSchema}}
+ );
+ }
+ }
+{{/hasSSE}}
+{{^hasSSE}}
+ const result = await service.{{operationId}}({{#hasParams}}params{{/hasParams}});
+ const status = getHttpStatus(200, result);
+ if (isError(result)) {
+ next(errors.handledException(status, result.errors));
+ } else {
+ return sendResponse(
+ res,
+ next,
+ status,
+ {{#responseDtoMapper}}({{{responseDtoMapper}}})(result){{/responseDtoMapper}}{{^responseDtoMapper}}result{{/responseDtoMapper}},
+{{#responseSchema}}
+ (payload) => schemas.{{{responseSchema}}}.parse(payload),
+{{/responseSchema}}
+ );
+ }
+{{/hasSSE}}
+ } catch (err) {
+ if (err instanceof ZodError) {
+ const statusCode = res.headersSent ? 500 : 400;
+ return next(errors.validationErrors(statusCode, err.issues));
+ } else {
+ next(errors.unhandledException(err));
+ }
+ }
+ };
+
+{{/allOperations}}
+/**
+ * Send a successful response, optionally validating the wire payload first.
+ *
+ * Validation runs BEFORE the payload is committed, so a schema mismatch never
+ * ships invalid data to the client. A mismatch is a server-side contract
+ * violation: it is surfaced as a structured validation error with a 5xx status,
+ * preserving the Zod issue details.
+ */
+function sendResponse(
+ res: Response,
+ next: NextFunction,
+ status: number,
+ payload: unknown,
+ validate?: (payload: unknown) => void,
+): void {
+ if (validate) {
+ try {
+ validate(payload);
+ } catch (err) {
+ if (err instanceof ZodError) {
+ return next(errors.validationErrors(500, err.issues));
+ }
+ return next(errors.unhandledException(err));
+ }
+ }
+ res.status(status).json(payload);
+}
+
+type ErrorResult = {
+ errors: types.ModelError[];
+ data?: unknown;
+};
+
+function isError(result: unknown): result is ErrorResult {
+ if (typeof result !== "object" || result === null || !("errors" in result)) {
+ return false;
+ }
+ const candidate = result as Record;
+ if (!Array.isArray(candidate.errors) || candidate.errors.length === 0) {
+ return false;
+ }
+ return !("data" in result) ||
+ candidate.data === undefined ||
+ (Array.isArray(candidate.data) && candidate.data.length === 0);
+}
+
+function getHttpStatus(success: number, result: unknown): number {
+ if (!isError(result)) return success;
+ return result.errors.reduce((max, item) => {
+ const status = (item as Record)["status"];
+ if (status === undefined) return success;
+ const value = typeof status === "string" ? Number(status) : typeof status === "number" ? status : NaN;
+ return !Number.isNaN(value) && value > max ? value : max;
+ }, success);
+}
diff --git a/modules/openapi-generator/src/main/resources/typescript-express-zod-server/express/index.mustache b/modules/openapi-generator/src/main/resources/typescript-express-zod-server/express/index.mustache
new file mode 100644
index 000000000000..057078aeffb6
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/typescript-express-zod-server/express/index.mustache
@@ -0,0 +1,7 @@
+{{#hasAuthOperations}}
+export * from "./auth-middleware";
+{{/hasAuthOperations}}
+export * from "./errors";
+export * from "./handlers";
+export * from "./router-factory";
+export * from "./types";
diff --git a/modules/openapi-generator/src/main/resources/typescript-express-zod-server/express/router-factory.mustache b/modules/openapi-generator/src/main/resources/typescript-express-zod-server/express/router-factory.mustache
new file mode 100644
index 000000000000..9b22c698d261
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/typescript-express-zod-server/express/router-factory.mustache
@@ -0,0 +1,146 @@
+/**
+ * This code was generated by openapi-generator (typescript-express-zod-server).
+ *
+ * Changes to this file may cause incorrect behavior and will be lost if
+ * the code is regenerated.
+ */
+
+import { Router, type RequestHandler } from "express";
+
+import * as handlers from "./handlers";
+import * as errors from "./errors";
+import type * as expressTypes from "./types";
+
+export function getRouter({
+ schema,
+{{#services}}
+ {{getter}},
+{{/services}}
+ middleware,
+ handlerOverrides,
+ swaggerUiVersion = "3.51.1",
+}: expressTypes.RouterFactoryInput): Router {
+ const router = Router();
+ const methodNotAllowed: (allow: string) => RequestHandler =
+ (allow) => (_req, res, next) => {
+ res.set("Allow", allow);
+ return next(errors.methodNotAllowed());
+ };
+
+ function handlersFor<
+ TName extends Exclude<
+ keyof expressTypes.Middleware,
+ "_onlySwaggerUI" | "_exceptSwaggerUI"
+ >,
+ >(methodName: TName, defaultHandler: RequestHandler): RequestHandler[] {
+ return [
+ ...getMiddleware(middleware, methodName),
+ ...getHandlers(handlerOverrides?.[methodName], defaultHandler),
+ ];
+ }
+
+{{#routes}}
+ router
+ .route("{{{path}}}")
+{{#operations}}
+ .{{httpMethod}}(
+ handlersFor(
+ "{{operationId}}",
+ handlers.{{handlerName}}({{serviceGetter}}),
+ ),
+ )
+{{/operations}}
+ .options((_, res) => {
+ res.set("Allow", "{{{allowedMethods}}}").sendStatus(204);
+ })
+ .all(methodNotAllowed("{{{allowedMethods}}}"));
+
+{{/routes}}
+ router
+ .route("/")
+ .get(...getMiddleware(middleware, "_onlySwaggerUI"), (_, res) => {
+ const swaggerUiUrl = `https://unpkg.com/swagger-ui-dist@${swaggerUiVersion}/`;
+ res.send(`
+
+
+
+ API Documentation
+
+
+
+
+
+ CONTENT NOT LOADED
+
+
+
+ `);
+ })
+ .options((_, res) => {
+ res.set("Allow", "GET, HEAD, OPTIONS").sendStatus(204);
+ })
+ .all(methodNotAllowed("GET, HEAD, OPTIONS"));
+ return router;
+}
+/**
+ * Gets a list of middleware functions for a given name from the supplied middleware object(s).
+ * If no middleware objects are supplied, an empty array is returned.
+ * Handlers are returned in the order they are defined in the middleware object(s).
+ * @param middleware - The middleware object(s) to extract middleware from
+ * @param name - The name of the service method to get middleware for
+ * @returns An array of {@link RequestHandler|express.RequestHandler} functions
+ */
+function getMiddleware(
+ middleware: expressTypes.Middleware | expressTypes.Middleware[] | undefined,
+ name: keyof expressTypes.Middleware,
+): RequestHandler[] {
+ if (!middleware) return [];
+ const middlewareArray = Array.isArray(middleware) ? middleware : [middleware];
+
+ return middlewareArray.flatMap((m) => {
+ const exceptSwaggerUI =
+ m._exceptSwaggerUI && name !== "_onlySwaggerUI"
+ ? m._exceptSwaggerUI
+ : [];
+
+ const handler = m[name];
+ const base = handler ? handler : [];
+ const baseArray = Array.isArray(base) ? base : [base];
+ const exceptArray = Array.isArray(exceptSwaggerUI)
+ ? exceptSwaggerUI
+ : [exceptSwaggerUI];
+ return [...baseArray, ...exceptArray];
+ });
+}
+
+/**
+ * Gets a list of handlers for a given service method.
+ * If overrides are provided, they are used in place of the default handler.
+ * If no overrides are provided, the default handler is used.
+ * @param overrides - The handler(s) to use in place of the default handler
+ * @param defaultHandler - The default handler to use if no overrides are provided
+ * @returns An array of {@link RequestHandler|express.RequestHandler} functions
+ */
+function getHandlers(
+ overrides: RequestHandler | RequestHandler[] | undefined,
+ defaultHandler: RequestHandler,
+): RequestHandler[] {
+ if (!overrides) return [defaultHandler];
+ return Array.isArray(overrides) ? overrides : [overrides];
+}
diff --git a/modules/openapi-generator/src/main/resources/typescript-express-zod-server/express/types.mustache b/modules/openapi-generator/src/main/resources/typescript-express-zod-server/express/types.mustache
new file mode 100644
index 000000000000..1ccb6b330b49
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/typescript-express-zod-server/express/types.mustache
@@ -0,0 +1,59 @@
+/**
+ * This code was generated by openapi-generator (typescript-express-zod-server).
+ *
+ * Changes to this file may cause incorrect behavior and will be lost if
+ * the code is regenerated.
+ */
+
+import type { Request, Response, RequestHandler } from "express";
+
+import type * as types from "../types";
+import type * as dtos from "../dtos/types";
+
+export type RouterFactoryInput = {
+ /** OpenAPI schema as a JSON object */
+ schema: any;
+
+{{#services}}
+ {{getter}}: (
+ req: Request,
+ res: Response,
+ ) => types.{{name}};
+{{/services}}
+
+ middleware?: Middleware | Middleware[];
+ handlerOverrides?: HandlerOverrides;
+ swaggerUiVersion?: string;
+};
+
+export type Middleware = {
+ /** Middleware to be applied to the Swagger UI handler. */
+ _onlySwaggerUI?: RequestHandler | RequestHandler[];
+ /** Middleware to be applied to all handlers _except_ Swagger UI after any other method-specific middleware. */
+ _exceptSwaggerUI?: RequestHandler | RequestHandler[];
+{{#allOperations}}
+ {{operationId}}?:
+ | {{operationIdPascal}}RequestHandler
+ | {{operationIdPascal}}RequestHandler[];
+{{/allOperations}}
+};
+
+/**
+ * Per-operation handler replacements. Unlike {@link Middleware}, the
+ * Swagger-UI scopes (`_onlySwaggerUI` / `_exceptSwaggerUI`) are not valid here
+ * because they are ignored when resolving handler overrides.
+ */
+export type HandlerOverrides = Omit<
+ Middleware,
+ "_onlySwaggerUI" | "_exceptSwaggerUI"
+>;
+
+{{#allOperations}}
+export type {{operationIdPascal}}RequestHandler = RequestHandler<
+ {{{paramsGeneric}}},
+ {{{responseGeneric}}},
+ {{{bodyGeneric}}},
+ {{{queryGeneric}}}
+>;
+
+{{/allOperations}}
diff --git a/modules/openapi-generator/src/main/resources/typescript-express-zod-server/index.mustache b/modules/openapi-generator/src/main/resources/typescript-express-zod-server/index.mustache
new file mode 100644
index 000000000000..019e4c35bb62
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/typescript-express-zod-server/index.mustache
@@ -0,0 +1,4 @@
+export * from "./types";
+export * from "./schemas";
+export * from "./dtos";
+export * from "./express";
diff --git a/modules/openapi-generator/src/main/resources/typescript-express-zod-server/model.mustache b/modules/openapi-generator/src/main/resources/typescript-express-zod-server/model.mustache
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/modules/openapi-generator/src/main/resources/typescript-express-zod-server/schemas.mustache b/modules/openapi-generator/src/main/resources/typescript-express-zod-server/schemas.mustache
new file mode 100644
index 000000000000..5ff186b06921
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/typescript-express-zod-server/schemas.mustache
@@ -0,0 +1,85 @@
+/**
+ * This code was generated by openapi-generator (typescript-express-zod-server).
+ *
+ * Changes to this file may cause incorrect behavior and will be lost if
+ * the code is regenerated.
+ */
+
+import { z } from "zod";
+
+{{#models}}
+{{#model}}
+{{#isEnum}}
+export const {{classname}}Schema = z.enum([{{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}}]);
+
+{{/isEnum}}
+{{^isEnum}}
+{{#vendorExtensions.x-is-discriminated-union}}
+export const {{classname}}Schema = z.discriminatedUnion("{{{vendorExtensions.x-discriminator-property}}}", [
+{{#vendorExtensions.x-mapped-models}}
+ {{modelName}}Schema,
+{{/vendorExtensions.x-mapped-models}}
+]);
+
+{{/vendorExtensions.x-is-discriminated-union}}
+{{^vendorExtensions.x-is-discriminated-union}}
+{{#vendorExtensions.x-is-union}}
+export const {{classname}}Schema = z.union([
+{{#vendorExtensions.x-union-members}}
+ {{modelName}}Schema,
+{{/vendorExtensions.x-union-members}}
+]);
+
+{{/vendorExtensions.x-is-union}}
+{{^vendorExtensions.x-is-union}}
+{{#vendorExtensions.x-is-intersection}}
+export const {{classname}}Schema = z.object({
+{{#vars}}
+{{#vendorExtensions.x-is-own-property}}
+ {{name}}: {{{vendorExtensions.x-zod-full}}},
+{{/vendorExtensions.x-is-own-property}}
+{{/vars}}
+}){{#vendorExtensions.x-intersection-parents}}.extend({{modelName}}Schema.shape){{/vendorExtensions.x-intersection-parents}};
+
+{{/vendorExtensions.x-is-intersection}}
+{{^vendorExtensions.x-is-intersection}}
+{{#hasVars}}
+export const {{classname}}Schema = z.object({
+{{#vars}}
+ {{name}}: {{{vendorExtensions.x-zod-full}}},
+{{/vars}}
+});
+
+{{/hasVars}}
+{{^hasVars}}
+export const {{classname}}Schema = z.object({}).catchall(z.unknown());
+
+{{/hasVars}}
+{{/vendorExtensions.x-is-intersection}}
+{{/vendorExtensions.x-is-union}}
+{{/vendorExtensions.x-is-discriminated-union}}
+{{/isEnum}}
+{{/model}}
+{{/models}}
+{{#allOperations}}
+{{#hasParams}}
+export const {{operationIdPascal}}ParamsSchema = z.object({
+{{#pathParams}}
+ {{name}}: {{{zodType}}},
+{{/pathParams}}
+{{#queryParams}}
+ {{name}}: {{{zodType}}},
+{{/queryParams}}
+{{#hasBodyParam}}
+ {{bodyParam.name}}: {{{bodyParam.zodExpr}}},
+{{/hasBodyParam}}
+});
+
+{{/hasParams}}
+{{/allOperations}}
+{{#allOperations}}
+{{#responseType}}
+export const {{operationIdPascal}}ResponseSchema = {{{responseZodExpr}}};
+
+{{/responseType}}
+{{/allOperations}}
diff --git a/modules/openapi-generator/src/main/resources/typescript-express-zod-server/types.mustache b/modules/openapi-generator/src/main/resources/typescript-express-zod-server/types.mustache
new file mode 100644
index 000000000000..ee9b46919b53
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/typescript-express-zod-server/types.mustache
@@ -0,0 +1,121 @@
+/**
+ * This code was generated by openapi-generator (typescript-express-zod-server).
+ *
+ * Changes to this file may cause incorrect behavior and will be lost if
+ * the code is regenerated.
+ */
+
+{{#services}}
+/** Interface for the {{name}} */
+export interface {{name}} {
+{{#operations}}
+ /** {{{description}}} */
+{{#hasSSE}}
+ {{operationId}}({{#hasParams}}params{{#allParamsOptional}}?{{/allParamsOptional}}: {{operationIdPascal}}Params{{/hasParams}}): Promise<{{#responseType}}{{{responseType}}}{{/responseType}}{{^responseType}}void{{/responseType}}> | AsyncIterable<{{{sseType}}}>;
+{{/hasSSE}}
+{{^hasSSE}}
+ {{operationId}}({{#hasParams}}params{{#allParamsOptional}}?{{/allParamsOptional}}: {{operationIdPascal}}Params{{/hasParams}}): Promise<{{#responseType}}{{{responseType}}}{{/responseType}}{{^responseType}}void{{/responseType}}>;
+{{/hasSSE}}
+
+{{/operations}}
+}
+
+{{/services}}
+{{#allOperations}}
+{{#hasParams}}
+export type {{operationIdPascal}}Params = {
+{{#pathParams}}
+ /** {{baseName}} */
+ {{name}}: {{{dataType}}};
+{{/pathParams}}
+{{#queryParams}}
+ /** {{baseName}} */
+ {{name}}{{^required}}?{{/required}}: {{{dataType}}};
+{{/queryParams}}
+{{#hasBodyParam}}
+ /** {{bodyParam.name}} */
+ {{bodyParam.name}}{{^bodyParam.required}}?{{/bodyParam.required}}: {{{bodyParam.dataType}}};
+{{/hasBodyParam}}
+};
+
+{{/hasParams}}
+{{/allOperations}}
+{{#models}}
+{{#model}}
+{{#isEnum}}
+export type {{classname}} = {{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}} | {{/-last}}{{/enumVars}}{{/allowableValues}};
+
+{{/isEnum}}
+{{^isEnum}}
+{{#vendorExtensions.x-is-discriminated-union}}
+{{#description}}
+/** {{{.}}} */
+{{/description}}
+export type {{classname}} = {{#vendorExtensions.x-mapped-models}}{{modelName}}{{^-last}} | {{/-last}}{{/vendorExtensions.x-mapped-models}};
+
+{{#vendorExtensions.x-mapped-models}}
+export function is{{modelName}}(obj: {{classname}}): obj is {{modelName}} {
+ return obj.{{{vendorExtensions.x-discriminator-property}}} === "{{mappingName}}";
+}
+
+{{/vendorExtensions.x-mapped-models}}
+{{/vendorExtensions.x-is-discriminated-union}}
+{{^vendorExtensions.x-is-discriminated-union}}
+{{#vendorExtensions.x-is-union}}
+{{#description}}
+/** {{{.}}} */
+{{/description}}
+export type {{classname}} = {{#vendorExtensions.x-union-members}}{{modelName}}{{^-last}} | {{/-last}}{{/vendorExtensions.x-union-members}};
+
+{{/vendorExtensions.x-is-union}}
+{{^vendorExtensions.x-is-union}}
+{{#vendorExtensions.x-is-intersection}}
+{{#description}}
+/** {{{.}}} */
+{{/description}}
+{{#vendorExtensions.x-has-own-properties}}
+export type {{classname}} = {
+{{#vars}}
+{{#vendorExtensions.x-is-own-property}}
+{{#description}}
+ /** {{{.}}} */
+{{/description}}
+{{#vendorExtensions.x-is-literal}}
+ {{name}}: "{{{vendorExtensions.x-literal-value}}}";
+{{/vendorExtensions.x-is-literal}}
+{{^vendorExtensions.x-is-literal}}
+ {{name}}{{^required}}?{{/required}}: {{{dataType}}}{{#isNullable}} | null{{/isNullable}};
+{{/vendorExtensions.x-is-literal}}
+{{/vendorExtensions.x-is-own-property}}
+{{/vars}}
+}{{#vendorExtensions.x-intersection-parents}} & {{modelName}}{{/vendorExtensions.x-intersection-parents}};
+{{/vendorExtensions.x-has-own-properties}}
+{{^vendorExtensions.x-has-own-properties}}
+export type {{classname}} = {{#vendorExtensions.x-intersection-parents}}{{modelName}}{{^-last}} & {{/-last}}{{/vendorExtensions.x-intersection-parents}};
+{{/vendorExtensions.x-has-own-properties}}
+
+{{/vendorExtensions.x-is-intersection}}
+{{^vendorExtensions.x-is-intersection}}
+{{#description}}
+/** {{{.}}} */
+{{/description}}
+export type {{classname}} = {
+{{#vars}}
+{{#description}}
+ /** {{{.}}} */
+{{/description}}
+{{#vendorExtensions.x-is-literal}}
+ {{name}}: "{{{vendorExtensions.x-literal-value}}}";
+{{/vendorExtensions.x-is-literal}}
+{{^vendorExtensions.x-is-literal}}
+ {{name}}{{^required}}?{{/required}}: {{{dataType}}}{{#isNullable}} | null{{/isNullable}};
+{{/vendorExtensions.x-is-literal}}
+{{/vars}}
+};
+
+{{/vendorExtensions.x-is-intersection}}
+{{/vendorExtensions.x-is-union}}
+{{/vendorExtensions.x-is-discriminated-union}}
+{{/isEnum}}
+{{/model}}
+{{/models}}
diff --git a/modules/openapi-generator/src/main/resources/typescript/express-zod/dtos/index.mustache b/modules/openapi-generator/src/main/resources/typescript/express-zod/dtos/index.mustache
new file mode 100644
index 000000000000..be223c7d1e00
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/typescript/express-zod/dtos/index.mustache
@@ -0,0 +1,9 @@
+/**
+ * This code was generated by openapi-generator (typescript, framework 'express-zod').
+ *
+ * Changes to this file may cause incorrect behavior and will be lost if
+ * the code is regenerated.
+ */
+
+export * from "./types";
+export * from "./mappers";
diff --git a/modules/openapi-generator/src/main/resources/typescript/express-zod/dtos/mappers.mustache b/modules/openapi-generator/src/main/resources/typescript/express-zod/dtos/mappers.mustache
new file mode 100644
index 000000000000..f867c75e4494
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/typescript/express-zod/dtos/mappers.mustache
@@ -0,0 +1,148 @@
+/**
+ * This code was generated by openapi-generator (typescript, framework 'express-zod').
+ *
+ * Changes to this file may cause incorrect behavior and will be lost if
+ * the code is regenerated.
+ */
+
+{{#hasDiscriminatedUnion}}
+import { ZodError } from "zod";
+
+{{/hasDiscriminatedUnion}}
+import type * as types from "../types";
+import type * as dtos from "./types";
+
+function compact(obj: T): T {
+ return Object.keys(obj).reduce((acc, key) => {
+ const value = obj[key as keyof T];
+ if (value !== undefined) {
+ acc[key as keyof T] = value;
+ }
+ return acc;
+ }, {} as T);
+}
+
+{{#models}}
+{{#model}}
+{{^isEnum}}
+{{#vendorExtensions.x-is-discriminated-union}}
+export function mapFrom{{classname}}Dto(dto: dtos.{{classname}}Dto): types.{{classname}} {
+ switch (dto.{{{vendorExtensions.x-discriminator-property}}}) {
+{{#vendorExtensions.x-mapped-models}}
+ case "{{mappingName}}":
+ return mapFrom{{modelName}}Dto(dto);
+{{/vendorExtensions.x-mapped-models}}
+ default:
+ // On the client this maps a server response: an unknown discriminator
+ // means the server returned a variant not described by the spec. Surface
+ // it through the same ZodError channel the client already uses for
+ // response validation, so mapZodError (and any user override) applies.
+ throw new ZodError([
+ {
+ code: "custom",
+ path: ["{{{vendorExtensions.x-discriminator-property}}}"],
+ message: `Unexpected {{classname}} discriminator in server response: ${(dto as { {{{vendorExtensions.x-discriminator-property}}}?: unknown }).{{{vendorExtensions.x-discriminator-property}}}}`,
+ },
+ ]);
+ }
+}
+
+export function mapTo{{classname}}Dto(obj: types.{{classname}}): dtos.{{classname}}Dto {
+ switch (obj.{{{vendorExtensions.x-discriminator-property}}}) {
+{{#vendorExtensions.x-mapped-models}}
+ case "{{mappingName}}":
+ return mapTo{{modelName}}Dto(obj);
+{{/vendorExtensions.x-mapped-models}}
+ default:
+ throw new Error(
+ `Unknown {{classname}} discriminator: ${(obj as { {{{vendorExtensions.x-discriminator-property}}}?: unknown }).{{{vendorExtensions.x-discriminator-property}}}}`,
+ );
+ }
+}
+
+{{/vendorExtensions.x-is-discriminated-union}}
+{{#vendorExtensions.x-is-union}}
+export function mapFrom{{classname}}Dto(dto: dtos.{{classname}}Dto): types.{{classname}} {
+{{#vendorExtensions.x-union-members}}
+{{#hasDistinguishingProperty}}
+ if ('{{distinguishingProperty}}' in dto) return mapFrom{{modelName}}Dto(dto as dtos.{{modelName}}Dto);
+{{/hasDistinguishingProperty}}
+{{^hasDistinguishingProperty}}
+ return mapFrom{{modelName}}Dto(dto as dtos.{{modelName}}Dto);
+{{/hasDistinguishingProperty}}
+{{/vendorExtensions.x-union-members}}
+}
+
+export function mapTo{{classname}}Dto(obj: types.{{classname}}): dtos.{{classname}}Dto {
+{{#vendorExtensions.x-union-members}}
+{{#hasDistinguishingProperty}}
+ if ('{{distinguishingProperty}}' in obj) return mapTo{{modelName}}Dto(obj as types.{{modelName}});
+{{/hasDistinguishingProperty}}
+{{^hasDistinguishingProperty}}
+ return mapTo{{modelName}}Dto(obj as any);
+{{/hasDistinguishingProperty}}
+{{/vendorExtensions.x-union-members}}
+}
+
+{{/vendorExtensions.x-is-union}}
+{{^vendorExtensions.x-is-discriminated-union}}
+{{^vendorExtensions.x-is-union}}
+{{#hasVars}}
+export function mapFrom{{classname}}Dto(
+ dto: dtos.{{classname}}Dto,
+): types.{{classname}} {
+ return compact({
+{{#vars}}
+{{#vendorExtensions.x-is-ref}}
+{{#isArray}}
+ {{name}}:
+ dto.{{name}} == null
+ ? dto.{{name}}
+ : dto.{{name}}.map(mapFrom{{vendorExtensions.x-ref-type}}Dto),
+{{/isArray}}
+{{^isArray}}
+ {{name}}:
+ dto.{{name}} == null
+ ? dto.{{name}}
+ : mapFrom{{vendorExtensions.x-ref-type}}Dto(dto.{{name}}),
+{{/isArray}}
+{{/vendorExtensions.x-is-ref}}
+{{^vendorExtensions.x-is-ref}}
+ {{name}}: dto.{{name}},
+{{/vendorExtensions.x-is-ref}}
+{{/vars}}
+ });
+}
+
+export function mapTo{{classname}}Dto(
+ obj: types.{{classname}},
+): dtos.{{classname}}Dto {
+ return compact({
+{{#vars}}
+{{#vendorExtensions.x-is-ref}}
+{{#isArray}}
+ {{name}}:
+ obj.{{name}} == null
+ ? obj.{{name}}
+ : obj.{{name}}.map(mapTo{{vendorExtensions.x-ref-type}}Dto),
+{{/isArray}}
+{{^isArray}}
+ {{name}}:
+ obj.{{name}} == null
+ ? obj.{{name}}
+ : mapTo{{vendorExtensions.x-ref-type}}Dto(obj.{{name}}),
+{{/isArray}}
+{{/vendorExtensions.x-is-ref}}
+{{^vendorExtensions.x-is-ref}}
+ {{name}}: obj.{{name}},
+{{/vendorExtensions.x-is-ref}}
+{{/vars}}
+ });
+}
+
+{{/hasVars}}
+{{/vendorExtensions.x-is-union}}
+{{/vendorExtensions.x-is-discriminated-union}}
+{{/isEnum}}
+{{/model}}
+{{/models}}
diff --git a/modules/openapi-generator/src/main/resources/typescript/express-zod/dtos/types.mustache b/modules/openapi-generator/src/main/resources/typescript/express-zod/dtos/types.mustache
new file mode 100644
index 000000000000..9210dc2eb574
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/typescript/express-zod/dtos/types.mustache
@@ -0,0 +1,124 @@
+/**
+ * This code was generated by openapi-generator (typescript, framework 'express-zod').
+ *
+ * Changes to this file may cause incorrect behavior and will be lost if
+ * the code is regenerated.
+ */
+
+import type * as types from "../types";
+
+{{#models}}
+{{#model}}
+{{#isEnum}}
+{{! Enums don't need a DTO - they're used directly from the types module }}
+{{/isEnum}}
+{{^isEnum}}
+{{#vendorExtensions.x-is-discriminated-union}}
+/** The over-the-wire representation of the {@link types.{{classname}}|{{classname}}} type. */
+export type {{classname}}Dto = {{#vendorExtensions.x-mapped-models}}{{modelName}}Dto{{^-last}} | {{/-last}}{{/vendorExtensions.x-mapped-models}};
+
+{{/vendorExtensions.x-is-discriminated-union}}
+{{^vendorExtensions.x-is-discriminated-union}}
+{{#vendorExtensions.x-is-union}}
+/** The over-the-wire representation of the {@link types.{{classname}}|{{classname}}} type. */
+export type {{classname}}Dto = {{#vendorExtensions.x-union-members}}{{modelName}}Dto{{^-last}} | {{/-last}}{{/vendorExtensions.x-union-members}};
+
+{{/vendorExtensions.x-is-union}}
+{{^vendorExtensions.x-is-union}}
+{{#vendorExtensions.x-is-intersection}}
+/** The over-the-wire representation of the {@link types.{{classname}}|{{classname}}} type. */
+{{#vendorExtensions.x-has-own-properties}}
+export type {{classname}}Dto = {
+{{#vars}}
+{{#vendorExtensions.x-is-own-property}}
+{{#vendorExtensions.x-is-literal}}
+ {{name}}: "{{{vendorExtensions.x-literal-value}}}";
+{{/vendorExtensions.x-is-literal}}
+{{^vendorExtensions.x-is-literal}}
+{{#vendorExtensions.x-is-enum-ref}}
+{{#isArray}}
+ {{name}}{{^required}}?{{/required}}: types.{{{vendorExtensions.x-enum-type}}}[]{{#isNullable}} | null{{/isNullable}};
+{{/isArray}}
+{{^isArray}}
+ {{name}}{{^required}}?{{/required}}: types.{{{vendorExtensions.x-enum-type}}}{{#isNullable}} | null{{/isNullable}};
+{{/isArray}}
+{{/vendorExtensions.x-is-enum-ref}}
+{{^vendorExtensions.x-is-enum-ref}}
+{{#isArray}}
+{{#vendorExtensions.x-is-ref}}
+ {{name}}{{^required}}?{{/required}}: {{{vendorExtensions.x-ref-type}}}Dto[]{{#isNullable}} | null{{/isNullable}};
+{{/vendorExtensions.x-is-ref}}
+{{^vendorExtensions.x-is-ref}}
+ {{name}}{{^required}}?{{/required}}: {{{dataType}}}{{#isNullable}} | null{{/isNullable}};
+{{/vendorExtensions.x-is-ref}}
+{{/isArray}}
+{{^isArray}}
+{{#vendorExtensions.x-is-ref}}
+ {{name}}{{^required}}?{{/required}}: {{{vendorExtensions.x-ref-type}}}Dto{{#isNullable}} | null{{/isNullable}};
+{{/vendorExtensions.x-is-ref}}
+{{^vendorExtensions.x-is-ref}}
+ {{name}}{{^required}}?{{/required}}: {{{dataType}}}{{#isNullable}} | null{{/isNullable}};
+{{/vendorExtensions.x-is-ref}}
+{{/isArray}}
+{{/vendorExtensions.x-is-enum-ref}}
+{{/vendorExtensions.x-is-literal}}
+{{/vendorExtensions.x-is-own-property}}
+{{/vars}}
+}{{#vendorExtensions.x-intersection-parents}} & {{modelName}}Dto{{/vendorExtensions.x-intersection-parents}};
+{{/vendorExtensions.x-has-own-properties}}
+{{^vendorExtensions.x-has-own-properties}}
+export type {{classname}}Dto = {{#vendorExtensions.x-intersection-parents}}{{modelName}}Dto{{^-last}} & {{/-last}}{{/vendorExtensions.x-intersection-parents}};
+{{/vendorExtensions.x-has-own-properties}}
+
+{{/vendorExtensions.x-is-intersection}}
+{{^vendorExtensions.x-is-intersection}}
+{{#hasVars}}
+/** The over-the-wire representation of the {@link types.{{classname}}|{{classname}}} type. */
+export type {{classname}}Dto = {
+{{#vars}}
+{{#vendorExtensions.x-is-literal}}
+ {{name}}: "{{{vendorExtensions.x-literal-value}}}";
+{{/vendorExtensions.x-is-literal}}
+{{^vendorExtensions.x-is-literal}}
+{{#vendorExtensions.x-is-enum-ref}}
+{{#isArray}}
+ {{name}}{{^required}}?{{/required}}: types.{{{vendorExtensions.x-enum-type}}}[]{{#isNullable}} | null{{/isNullable}};
+{{/isArray}}
+{{^isArray}}
+ {{name}}{{^required}}?{{/required}}: types.{{{vendorExtensions.x-enum-type}}}{{#isNullable}} | null{{/isNullable}};
+{{/isArray}}
+{{/vendorExtensions.x-is-enum-ref}}
+{{^vendorExtensions.x-is-enum-ref}}
+{{#isArray}}
+{{#vendorExtensions.x-is-ref}}
+ {{name}}{{^required}}?{{/required}}: {{{vendorExtensions.x-ref-type}}}Dto[]{{#isNullable}} | null{{/isNullable}};
+{{/vendorExtensions.x-is-ref}}
+{{^vendorExtensions.x-is-ref}}
+ {{name}}{{^required}}?{{/required}}: {{{dataType}}}{{#isNullable}} | null{{/isNullable}};
+{{/vendorExtensions.x-is-ref}}
+{{/isArray}}
+{{^isArray}}
+{{#vendorExtensions.x-is-ref}}
+ {{name}}{{^required}}?{{/required}}: {{{vendorExtensions.x-ref-type}}}Dto{{#isNullable}} | null{{/isNullable}};
+{{/vendorExtensions.x-is-ref}}
+{{^vendorExtensions.x-is-ref}}
+ {{name}}{{^required}}?{{/required}}: {{{dataType}}}{{#isNullable}} | null{{/isNullable}};
+{{/vendorExtensions.x-is-ref}}
+{{/isArray}}
+{{/vendorExtensions.x-is-enum-ref}}
+{{/vendorExtensions.x-is-literal}}
+{{/vars}}
+};
+
+{{/hasVars}}
+{{^hasVars}}
+/** The over-the-wire representation of the {@link types.{{classname}}|{{classname}}} type. */
+export type {{classname}}Dto = types.{{classname}};
+
+{{/hasVars}}
+{{/vendorExtensions.x-is-intersection}}
+{{/vendorExtensions.x-is-union}}
+{{/vendorExtensions.x-is-discriminated-union}}
+{{/isEnum}}
+{{/model}}
+{{/models}}
diff --git a/modules/openapi-generator/src/main/resources/typescript/express-zod/http-client.mustache b/modules/openapi-generator/src/main/resources/typescript/express-zod/http-client.mustache
new file mode 100644
index 000000000000..7cc658a75e79
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/typescript/express-zod/http-client.mustache
@@ -0,0 +1,241 @@
+/**
+ * This code was generated by openapi-generator (typescript, framework 'express-zod').
+ *
+ * Changes to this file may cause incorrect behavior and will be lost if
+ * the code is regenerated.
+ */
+
+import * as types from "./types";
+import * as dtos from "./dtos/types";
+import * as mappers from "./dtos/mappers";
+import * as schemas from "./schemas";
+import { ZodError } from "zod";
+
+/** Minimal fetch-like interface for making HTTP requests. */
+export interface FetchLike {
+ (resource: string, init?: {
+ method?: string;
+ headers?: Record;
+ body?: string;
+ }): Promise<{ json(): Promise; status: number }>;
+}
+
+{{#hasAnySSE}}
+/** Fetch-like interface for SSE responses. Returns raw response with readable body stream. */
+export interface StreamFetchLike {
+ (resource: string, init?: {
+ method?: string;
+ headers?: Record;
+ body?: string;
+ }): Promise<{ body: ReadableStream | null; status: number }>;
+}
+
+{{/hasAnySSE}}
+/** Options for configuring an HTTP client. */
+export interface ClientOptions {
+ /** Base URL prefix prepended to all request paths (e.g. "https://api.example.com"). */
+ root?: string;
+ /** Custom mapper for Zod validation errors on the response. */
+ mapZodError?: (err: ZodError) => types.ModelError[];
+ /** Custom mapper for unhandled exceptions. */
+ mapUnhandledException?: (err: unknown) => types.ModelError[];
+{{#hasAnySSE}}
+ /** Fetch function for SSE streaming. Typically the same fetch used for regular requests. */
+ streamFetch?: StreamFetchLike;
+{{/hasAnySSE}}
+}
+
+function defaultMapZodError(err: ZodError): types.ModelError[] {
+ return err.issues.map((issue) => ({
+ {{errorMessageField}}: issue.message,
+{{#errorHasCode}}
+ code: String(issue.code),
+{{/errorHasCode}}
+{{#errorHasSource}}
+ source: { pointer: issue.path.join("/") },
+{{/errorHasSource}}
+ }));
+}
+
+function defaultMapUnhandledException(err: unknown): types.ModelError[] {
+ const message = err instanceof Error ? err.message : String(err);
+ return [{ {{errorMessageField}}: message }];
+}
+
+{{#hasAnySSE}}
+async function* parseSSEStream(
+ body: ReadableStream,
+ schema: { parse(data: unknown): TDto },
+ mapper: (dto: TDto) => TDomain,
+): AsyncGenerator {
+ const reader = body.getReader();
+ const decoder = new TextDecoder();
+ let buffer = "";
+ try {
+ while (true) {
+ const { done, value } = await reader.read();
+ if (done) break;
+ buffer += decoder.decode(value, { stream: true });
+ // Normalize CRLF / CR line endings to LF per the SSE spec.
+ buffer = buffer.replace(/\r\n|\r/g, "\n");
+ const parts = buffer.split("\n\n");
+ buffer = parts.pop() ?? "";
+ for (const part of parts) {
+ if (!part.trim()) continue;
+ let id = "";
+ let event = "";
+ const dataLines: string[] = [];
+ for (const line of part.split("\n")) {
+ if (line.startsWith(":")) continue; // comment line
+ const colonIdx = line.indexOf(":");
+ const field = colonIdx === -1 ? line : line.slice(0, colonIdx);
+ let val = colonIdx === -1 ? "" : line.slice(colonIdx + 1);
+ // A single leading space after the colon is part of the delimiter.
+ if (val.startsWith(" ")) val = val.slice(1);
+ switch (field) {
+ case "id":
+ id = val;
+ break;
+ case "event":
+ event = val;
+ break;
+ case "data":
+ dataLines.push(val);
+ break;
+ }
+ }
+ if (dataLines.length === 0) continue;
+ try {
+ const envelope = {
+ id,
+ event,
+ // Multiple data: lines are joined with newlines per the SSE spec.
+ data: JSON.parse(dataLines.join("\n")),
+ };
+ yield mapper(schema.parse(envelope));
+ } catch { /* skip malformed events */ }
+ }
+ }
+ } finally {
+ reader.releaseLock();
+ }
+}
+
+{{/hasAnySSE}}
+{{#services}}
+/** HTTP client for the {{name}} */
+export class Http{{name}} implements types.{{name}} {
+ private fetch: FetchLike;
+ private root: string;
+ private mapZodError: (err: ZodError) => types.ModelError[];
+ private mapUnhandledException: (err: unknown) => types.ModelError[];
+{{#hasSSE}}
+ private streamFetch?: StreamFetchLike;
+{{/hasSSE}}
+
+ constructor(fetch: FetchLike, options?: ClientOptions) {
+ this.fetch = fetch;
+ this.root = options?.root ?? "";
+ this.mapZodError = options?.mapZodError ?? defaultMapZodError;
+ this.mapUnhandledException = options?.mapUnhandledException ?? defaultMapUnhandledException;
+{{#hasSSE}}
+ this.streamFetch = options?.streamFetch;
+{{/hasSSE}}
+ }
+
+{{#operations}}
+ /** {{{description}}} */
+ async {{operationId}}({{#hasParams}}params{{#allParamsOptional}}?{{/allParamsOptional}}: types.{{operationIdPascal}}Params{{/hasParams}}): Promise<{{#responseType}}{{{responseDomainGeneric}}}{{/responseType}}{{^responseType}}void{{/responseType}}> {
+{{#hasQueryParams}}
+ const query = new URLSearchParams();
+{{#queryParams}}
+{{#hasDifferentName}}
+ if (params{{#allParamsOptional}}?{{/allParamsOptional}}.{{name}} !== undefined) query.set("{{baseName}}", String(params{{#allParamsOptional}}!{{/allParamsOptional}}.{{name}}));
+{{/hasDifferentName}}
+{{^hasDifferentName}}
+ if (params{{#allParamsOptional}}?{{/allParamsOptional}}.{{name}} !== undefined) query.set("{{name}}", String(params{{#allParamsOptional}}!{{/allParamsOptional}}.{{name}}));
+{{/hasDifferentName}}
+{{/queryParams}}
+ const queryString = query.toString();
+ const url = `${this.root}{{{urlTemplate}}}${queryString ? `?${queryString}` : ""}`;
+{{/hasQueryParams}}
+{{^hasQueryParams}}
+ const url = `${this.root}{{{urlTemplate}}}`;
+{{/hasQueryParams}}
+ try {
+{{#hasBodyParam}}
+ const response = await this.fetch<{{#responseDtoGeneric}}{{{responseDtoGeneric}}}{{/responseDtoGeneric}}{{^responseDtoGeneric}}unknown{{/responseDtoGeneric}}>(url, {
+{{#hasFetchMethod}}
+ method: "{{fetchMethod}}",
+{{/hasFetchMethod}}
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify(({{{bodyMapFn}}})(params{{#allParamsOptional}}?{{/allParamsOptional}}.{{bodyParam.name}})),
+ });
+{{/hasBodyParam}}
+{{^hasBodyParam}}
+{{#hasFetchMethod}}
+ const response = await this.fetch<{{#responseDtoGeneric}}{{{responseDtoGeneric}}}{{/responseDtoGeneric}}{{^responseDtoGeneric}}unknown{{/responseDtoGeneric}}>(url, { method: "{{fetchMethod}}" });
+{{/hasFetchMethod}}
+{{^hasFetchMethod}}
+ const response = await this.fetch<{{#responseDtoGeneric}}{{{responseDtoGeneric}}}{{/responseDtoGeneric}}{{^responseDtoGeneric}}unknown{{/responseDtoGeneric}}>(url);
+{{/hasFetchMethod}}
+{{/hasBodyParam}}
+{{#responseType}}
+ const json = await response.json();
+ return ({{{responseDtoMapper}}})(schemas.{{responseSchema}}.parse(json));
+{{/responseType}}
+{{^responseType}}
+ // No response body expected (e.g. 204 No Content); nothing to parse.
+ void response;
+ return;
+{{/responseType}}
+ } catch (err) {
+ if (err instanceof ZodError) {
+ return { errors: this.mapZodError(err) } as unknown as {{#responseType}}{{{responseDomainGeneric}}}{{/responseType}}{{^responseType}}any{{/responseType}};
+ }
+ return { errors: this.mapUnhandledException(err) } as unknown as {{#responseType}}{{{responseDomainGeneric}}}{{/responseType}}{{^responseType}}any{{/responseType}};
+ }
+ }
+
+{{#hasSSE}}
+ /** {{{description}}} (streaming) */
+ async *{{streamOperationId}}({{#hasParams}}params{{#allParamsOptional}}?{{/allParamsOptional}}: types.{{operationIdPascal}}Params{{/hasParams}}): AsyncGenerator {
+{{#hasQueryParams}}
+ const query = new URLSearchParams();
+{{#queryParams}}
+{{#hasDifferentName}}
+ if (params{{#allParamsOptional}}?{{/allParamsOptional}}.{{name}} !== undefined) query.set("{{baseName}}", String(params{{#allParamsOptional}}!{{/allParamsOptional}}.{{name}}));
+{{/hasDifferentName}}
+{{^hasDifferentName}}
+ if (params{{#allParamsOptional}}?{{/allParamsOptional}}.{{name}} !== undefined) query.set("{{name}}", String(params{{#allParamsOptional}}!{{/allParamsOptional}}.{{name}}));
+{{/hasDifferentName}}
+{{/queryParams}}
+ const queryString = query.toString();
+ const url = `${this.root}{{{urlTemplate}}}${queryString ? `?${queryString}` : ""}`;
+{{/hasQueryParams}}
+{{^hasQueryParams}}
+ const url = `${this.root}{{{urlTemplate}}}`;
+{{/hasQueryParams}}
+ const fetchFn = this.streamFetch ?? (this.fetch as unknown as StreamFetchLike);
+ const response = await fetchFn(url, {
+{{#hasFetchMethod}}
+ method: "{{fetchMethod}}",
+{{/hasFetchMethod}}
+{{#hasBodyParam}}
+ headers: { "Content-Type": "application/json", "Accept": "text/event-stream" },
+ body: JSON.stringify(({{{bodyMapFn}}})(params.{{bodyParam.name}})),
+{{/hasBodyParam}}
+{{^hasBodyParam}}
+ headers: { "Accept": "text/event-stream" },
+{{/hasBodyParam}}
+ });
+ const body = (response as any).body as ReadableStream | null;
+ if (!body) throw new Error("Response body not available for SSE streaming");
+ yield* parseSSEStream(body, schemas.{{sseSchema}}, mappers.{{sseDtoMapper}});
+ }
+
+{{/hasSSE}}
+{{/operations}}
+}
+
+{{/services}}
diff --git a/modules/openapi-generator/src/main/resources/typescript/express-zod/index.mustache b/modules/openapi-generator/src/main/resources/typescript/express-zod/index.mustache
new file mode 100644
index 000000000000..f4e733094774
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/typescript/express-zod/index.mustache
@@ -0,0 +1,11 @@
+/**
+ * This code was generated by openapi-generator (typescript, framework 'express-zod').
+ *
+ * Changes to this file may cause incorrect behavior and will be lost if
+ * the code is regenerated.
+ */
+
+export * from "./types";
+export * from "./schemas";
+export * from "./dtos";
+export * from "./http-client";
diff --git a/modules/openapi-generator/src/main/resources/typescript/express-zod/schemas.mustache b/modules/openapi-generator/src/main/resources/typescript/express-zod/schemas.mustache
new file mode 100644
index 000000000000..598183d9ea69
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/typescript/express-zod/schemas.mustache
@@ -0,0 +1,69 @@
+/**
+ * This code was generated by openapi-generator (typescript, framework 'express-zod').
+ *
+ * Changes to this file may cause incorrect behavior and will be lost if
+ * the code is regenerated.
+ */
+
+import { z } from "zod";
+
+{{#models}}
+{{#model}}
+{{#isEnum}}
+export const {{classname}}Schema = z.enum([{{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}}]);
+
+{{/isEnum}}
+{{^isEnum}}
+{{#vendorExtensions.x-is-discriminated-union}}
+export const {{classname}}Schema = z.discriminatedUnion("{{{vendorExtensions.x-discriminator-property}}}", [
+{{#vendorExtensions.x-mapped-models}}
+ {{modelName}}Schema,
+{{/vendorExtensions.x-mapped-models}}
+]);
+
+{{/vendorExtensions.x-is-discriminated-union}}
+{{^vendorExtensions.x-is-discriminated-union}}
+{{#vendorExtensions.x-is-union}}
+export const {{classname}}Schema = z.union([
+{{#vendorExtensions.x-union-members}}
+ {{modelName}}Schema,
+{{/vendorExtensions.x-union-members}}
+]);
+
+{{/vendorExtensions.x-is-union}}
+{{^vendorExtensions.x-is-union}}
+{{#vendorExtensions.x-is-intersection}}
+export const {{classname}}Schema = z.object({
+{{#vars}}
+{{#vendorExtensions.x-is-own-property}}
+ {{name}}: {{{vendorExtensions.x-zod-full}}},
+{{/vendorExtensions.x-is-own-property}}
+{{/vars}}
+}){{#vendorExtensions.x-intersection-parents}}.extend({{modelName}}Schema.shape){{/vendorExtensions.x-intersection-parents}};
+
+{{/vendorExtensions.x-is-intersection}}
+{{^vendorExtensions.x-is-intersection}}
+{{#hasVars}}
+export const {{classname}}Schema = z.object({
+{{#vars}}
+ {{name}}: {{{vendorExtensions.x-zod-full}}},
+{{/vars}}
+});
+
+{{/hasVars}}
+{{^hasVars}}
+export const {{classname}}Schema = z.object({}).catchall(z.unknown());
+
+{{/hasVars}}
+{{/vendorExtensions.x-is-intersection}}
+{{/vendorExtensions.x-is-union}}
+{{/vendorExtensions.x-is-discriminated-union}}
+{{/isEnum}}
+{{/model}}
+{{/models}}
+{{#allOperations}}
+{{#responseType}}
+export const {{operationIdPascal}}ResponseSchema = {{{responseZodExpr}}};
+
+{{/responseType}}
+{{/allOperations}}
diff --git a/modules/openapi-generator/src/main/resources/typescript/express-zod/types.mustache b/modules/openapi-generator/src/main/resources/typescript/express-zod/types.mustache
new file mode 100644
index 000000000000..022c12b90236
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/typescript/express-zod/types.mustache
@@ -0,0 +1,121 @@
+/**
+ * This code was generated by openapi-generator (typescript, framework 'express-zod').
+ *
+ * Changes to this file may cause incorrect behavior and will be lost if
+ * the code is regenerated.
+ */
+
+{{#services}}
+/** Interface for the {{name}} */
+export interface {{name}} {
+{{#operations}}
+ /** {{{description}}} */
+ {{operationId}}({{#hasParams}}params{{#allParamsOptional}}?{{/allParamsOptional}}: {{operationIdPascal}}Params{{/hasParams}}): Promise<{{#responseType}}{{{responseType}}}{{/responseType}}{{^responseType}}void{{/responseType}}>;
+
+{{#hasSSE}}
+ /** {{{description}}} (streaming) */
+ {{streamOperationId}}({{#hasParams}}params{{#allParamsOptional}}?{{/allParamsOptional}}: {{operationIdPascal}}Params{{/hasParams}}): AsyncIterable<{{{sseType}}}>;
+
+{{/hasSSE}}
+{{/operations}}
+}
+
+{{/services}}
+{{#allOperations}}
+{{#hasParams}}
+export type {{operationIdPascal}}Params = {
+{{#pathParams}}
+ /** {{baseName}} */
+ {{name}}: {{{dataType}}};
+{{/pathParams}}
+{{#queryParams}}
+ /** {{baseName}} */
+ {{name}}{{^required}}?{{/required}}: {{{dataType}}};
+{{/queryParams}}
+{{#hasBodyParam}}
+ /** {{bodyParam.name}} */
+ {{bodyParam.name}}{{^bodyParam.required}}?{{/bodyParam.required}}: {{{bodyParam.dataType}}};
+{{/hasBodyParam}}
+};
+
+{{/hasParams}}
+{{/allOperations}}
+{{#models}}
+{{#model}}
+{{#isEnum}}
+export type {{classname}} = {{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}} | {{/-last}}{{/enumVars}}{{/allowableValues}};
+
+{{/isEnum}}
+{{^isEnum}}
+{{#vendorExtensions.x-is-discriminated-union}}
+{{#description}}
+/** {{{.}}} */
+{{/description}}
+export type {{classname}} = {{#vendorExtensions.x-mapped-models}}{{modelName}}{{^-last}} | {{/-last}}{{/vendorExtensions.x-mapped-models}};
+
+{{#vendorExtensions.x-mapped-models}}
+export function is{{modelName}}(obj: {{classname}}): obj is {{modelName}} {
+ return obj.{{{vendorExtensions.x-discriminator-property}}} === "{{mappingName}}";
+}
+
+{{/vendorExtensions.x-mapped-models}}
+{{/vendorExtensions.x-is-discriminated-union}}
+{{^vendorExtensions.x-is-discriminated-union}}
+{{#vendorExtensions.x-is-union}}
+{{#description}}
+/** {{{.}}} */
+{{/description}}
+export type {{classname}} = {{#vendorExtensions.x-union-members}}{{modelName}}{{^-last}} | {{/-last}}{{/vendorExtensions.x-union-members}};
+
+{{/vendorExtensions.x-is-union}}
+{{^vendorExtensions.x-is-union}}
+{{#vendorExtensions.x-is-intersection}}
+{{#description}}
+/** {{{.}}} */
+{{/description}}
+{{#vendorExtensions.x-has-own-properties}}
+export type {{classname}} = {
+{{#vars}}
+{{#vendorExtensions.x-is-own-property}}
+{{#description}}
+ /** {{{.}}} */
+{{/description}}
+{{#vendorExtensions.x-is-literal}}
+ {{name}}: "{{{vendorExtensions.x-literal-value}}}";
+{{/vendorExtensions.x-is-literal}}
+{{^vendorExtensions.x-is-literal}}
+ {{name}}{{^required}}?{{/required}}: {{{dataType}}}{{#isNullable}} | null{{/isNullable}};
+{{/vendorExtensions.x-is-literal}}
+{{/vendorExtensions.x-is-own-property}}
+{{/vars}}
+}{{#vendorExtensions.x-intersection-parents}} & {{modelName}}{{/vendorExtensions.x-intersection-parents}};
+{{/vendorExtensions.x-has-own-properties}}
+{{^vendorExtensions.x-has-own-properties}}
+export type {{classname}} = {{#vendorExtensions.x-intersection-parents}}{{modelName}}{{^-last}} & {{/-last}}{{/vendorExtensions.x-intersection-parents}};
+{{/vendorExtensions.x-has-own-properties}}
+
+{{/vendorExtensions.x-is-intersection}}
+{{^vendorExtensions.x-is-intersection}}
+{{#description}}
+/** {{{.}}} */
+{{/description}}
+export type {{classname}} = {
+{{#vars}}
+{{#description}}
+ /** {{{.}}} */
+{{/description}}
+{{#vendorExtensions.x-is-literal}}
+ {{name}}: "{{{vendorExtensions.x-literal-value}}}";
+{{/vendorExtensions.x-is-literal}}
+{{^vendorExtensions.x-is-literal}}
+ {{name}}{{^required}}?{{/required}}: {{{dataType}}}{{#isNullable}} | null{{/isNullable}};
+{{/vendorExtensions.x-is-literal}}
+{{/vars}}
+};
+
+{{/vendorExtensions.x-is-intersection}}
+{{/vendorExtensions.x-is-union}}
+{{/vendorExtensions.x-is-discriminated-union}}
+{{/isEnum}}
+{{/model}}
+{{/models}}
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/TypeScriptExpressZodServerCodegenOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/TypeScriptExpressZodServerCodegenOptionsProvider.java
new file mode 100644
index 000000000000..e8a6247cb992
--- /dev/null
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/TypeScriptExpressZodServerCodegenOptionsProvider.java
@@ -0,0 +1,26 @@
+package org.openapitools.codegen.options;
+
+import com.google.common.collect.ImmutableMap;
+
+import java.util.Map;
+
+public class TypeScriptExpressZodServerCodegenOptionsProvider implements TypeScriptSharedClientOptionsProvider {
+ public static final String PROJECT_NAME_VALUE = "OpenAPI";
+
+ @Override
+ public String getLanguage() {
+ return "typescript-express-zod-server";
+ }
+
+ @Override
+ public Map createOptions() {
+ return ImmutableMap.builder()
+ .putAll(TypeScriptSharedClientOptionsProvider.super.createOptions())
+ .build();
+ }
+
+ @Override
+ public boolean isServer() {
+ return true;
+ }
+}
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/express/zod/TypeScriptExpressZodClientFrameworkTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/express/zod/TypeScriptExpressZodClientFrameworkTest.java
new file mode 100644
index 000000000000..af07b361015f
--- /dev/null
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/express/zod/TypeScriptExpressZodClientFrameworkTest.java
@@ -0,0 +1,95 @@
+package org.openapitools.codegen.typescript.express.zod;
+
+import org.openapitools.codegen.ClientOptInput;
+import org.openapitools.codegen.DefaultGenerator;
+import org.openapitools.codegen.SupportingFile;
+import org.openapitools.codegen.TestUtils;
+import org.openapitools.codegen.config.CodegenConfigurator;
+import org.openapitools.codegen.languages.TypeScriptClientCodegen;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * Tests for the {@code express-zod} framework of the unified {@code typescript} generator
+ * (the client counterpart of {@code typescript-express-zod-server}).
+ */
+public class TypeScriptExpressZodClientFrameworkTest {
+
+ @Test(description = "express-zod framework replaces the default template set with its supporting files")
+ public void processOptsRegistersExpressZodFiles() {
+ final TypeScriptClientCodegen codegen = new TypeScriptClientCodegen();
+ codegen.additionalProperties().put("framework", "express-zod");
+ codegen.processOpts();
+
+ Set outputs = codegen.supportingFiles().stream()
+ .map(sf -> sf.getFolder().isEmpty()
+ ? sf.getDestinationFilename()
+ : sf.getFolder() + "/" + sf.getDestinationFilename())
+ .collect(Collectors.toSet());
+ Assert.assertEquals(outputs, Set.of(
+ "types.ts", "schemas.ts", "http-client.ts", "index.ts",
+ "dtos/types.ts", "dtos/mappers.ts", "dtos/index.ts"),
+ "unexpected supporting files: " + outputs);
+ Assert.assertTrue(codegen.modelTemplateFiles().isEmpty());
+ Assert.assertTrue(codegen.apiTemplateFiles().isEmpty());
+ Assert.assertTrue(codegen.apiDocTemplateFiles().isEmpty());
+ }
+
+ @Test(description = "express-zod framework generates the express-zod client layout end to end")
+ public void endToEndGeneration() throws Exception {
+ final File output = Files.createTempDirectory("typescriptexpresszodclient_").toFile();
+ output.deleteOnExit();
+
+ final CodegenConfigurator configurator = new CodegenConfigurator()
+ .setGeneratorName("typescript")
+ .addAdditionalProperty("framework", "express-zod")
+ .setInputSpec("src/test/resources/3_0/typescript-express-zod/petstore.yaml")
+ .setOutputDir(output.getAbsolutePath().replace("\\", "/"));
+
+ final ClientOptInput clientOptInput = configurator.toClientOptInput();
+ final DefaultGenerator generator = new DefaultGenerator();
+ final List files = generator.opts(clientOptInput).generate();
+ files.forEach(File::deleteOnExit);
+
+ for (String expected : new String[]{
+ "types.ts", "schemas.ts", "http-client.ts", "index.ts",
+ "dtos/types.ts", "dtos/mappers.ts", "dtos/index.ts"}) {
+ Assert.assertTrue(new File(output, expected).exists(), "missing " + expected);
+ }
+ for (String unexpected : new String[]{"apis", "models", "package.json", "http"}) {
+ Assert.assertFalse(new File(output, unexpected).exists(), "unexpected " + unexpected);
+ }
+
+ // Response schemas resolved via TypeScriptExpressZodSupport (guard regression)
+ TestUtils.assertFileContains(Paths.get(output + "/schemas.ts"), "ResponseSchema");
+ TestUtils.assertFileContains(Paths.get(output + "/http-client.ts"),
+ "generated by openapi-generator (typescript, framework 'express-zod')");
+ }
+
+ @Test(description = "the default fetch-api framework is unaffected by the express-zod hooks")
+ public void defaultFrameworkStillGeneratesFetchApi() throws Exception {
+ final File output = Files.createTempDirectory("typescriptdefaultframework_").toFile();
+ output.deleteOnExit();
+
+ final CodegenConfigurator configurator = new CodegenConfigurator()
+ .setGeneratorName("typescript")
+ .setInputSpec("src/test/resources/3_0/typescript-express-zod/petstore.yaml")
+ .setOutputDir(output.getAbsolutePath().replace("\\", "/"));
+
+ final ClientOptInput clientOptInput = configurator.toClientOptInput();
+ final DefaultGenerator generator = new DefaultGenerator();
+ final List files = generator.opts(clientOptInput).generate();
+ files.forEach(File::deleteOnExit);
+
+ Assert.assertTrue(new File(output, "http/isomorphic-fetch.ts").exists(),
+ "default framework should still emit the fetch-api http lib");
+ Assert.assertTrue(new File(output, "package.json").exists());
+ }
+}
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/express/zod/TypeScriptExpressZodServerCodegenModelTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/express/zod/TypeScriptExpressZodServerCodegenModelTest.java
new file mode 100644
index 000000000000..db3ea8a82a56
--- /dev/null
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/express/zod/TypeScriptExpressZodServerCodegenModelTest.java
@@ -0,0 +1,50 @@
+package org.openapitools.codegen.typescript.express.zod;
+
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.media.IntegerSchema;
+import io.swagger.v3.oas.models.media.Schema;
+import io.swagger.v3.oas.models.media.StringSchema;
+import io.swagger.v3.parser.util.SchemaTypeUtil;
+
+import org.openapitools.codegen.CodegenModel;
+import org.openapitools.codegen.CodegenProperty;
+import org.openapitools.codegen.DefaultCodegen;
+import org.openapitools.codegen.TestUtils;
+import org.openapitools.codegen.languages.TypeScriptExpressZodServerCodegen;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+@SuppressWarnings("static-method")
+public class TypeScriptExpressZodServerCodegenModelTest {
+
+ @Test(description = "convert a simple TypeScript Express Zod model")
+ public void simpleModelTest() {
+ final Schema schema = new Schema()
+ .description("a sample model")
+ .addProperties("id", new IntegerSchema().format(SchemaTypeUtil.INTEGER64_FORMAT))
+ .addProperties("name", new StringSchema())
+ .addRequiredItem("id")
+ .addRequiredItem("name");
+ final DefaultCodegen codegen = new TypeScriptExpressZodServerCodegen();
+ final OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema("Sample", schema);
+ codegen.setOpenAPI(openAPI);
+
+ final CodegenModel cm = codegen.fromModel("Sample", schema);
+
+ Assert.assertEquals(cm.name, "Sample");
+ Assert.assertEquals(cm.classname, "Sample");
+ Assert.assertEquals(cm.description, "a sample model");
+ Assert.assertEquals(cm.vars.size(), 2);
+
+ final CodegenProperty id = cm.vars.get(0);
+ Assert.assertEquals(id.baseName, "id");
+ Assert.assertEquals(id.dataType, "number");
+ Assert.assertTrue(id.required);
+
+ final CodegenProperty name = cm.vars.get(1);
+ Assert.assertEquals(name.baseName, "name");
+ Assert.assertEquals(name.dataType, "string");
+ Assert.assertTrue(name.required);
+ }
+}
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/express/zod/TypeScriptExpressZodServerCodegenOptionsTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/express/zod/TypeScriptExpressZodServerCodegenOptionsTest.java
new file mode 100644
index 000000000000..e4ecd5e98354
--- /dev/null
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/express/zod/TypeScriptExpressZodServerCodegenOptionsTest.java
@@ -0,0 +1,30 @@
+package org.openapitools.codegen.typescript.express.zod;
+
+import org.openapitools.codegen.AbstractOptionsTest;
+import org.openapitools.codegen.CodegenConfig;
+import org.openapitools.codegen.languages.TypeScriptExpressZodServerCodegen;
+import org.openapitools.codegen.options.TypeScriptExpressZodServerCodegenOptionsProvider;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+public class TypeScriptExpressZodServerCodegenOptionsTest extends AbstractOptionsTest {
+ private TypeScriptExpressZodServerCodegen codegen = mock(TypeScriptExpressZodServerCodegen.class, mockSettings);
+
+ public TypeScriptExpressZodServerCodegenOptionsTest() {
+ super(new TypeScriptExpressZodServerCodegenOptionsProvider());
+ }
+
+ @Override
+ protected CodegenConfig getCodegenConfig() {
+ return codegen;
+ }
+
+ @SuppressWarnings("unused")
+ @Override
+ protected void verifyOptions() {
+ // TODO: Complete options using Mockito
+ // verify(codegen).someMethod(arguments)
+ }
+}
+
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/express/zod/TypeScriptExpressZodServerCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/express/zod/TypeScriptExpressZodServerCodegenTest.java
new file mode 100644
index 000000000000..0935577ad6ee
--- /dev/null
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/express/zod/TypeScriptExpressZodServerCodegenTest.java
@@ -0,0 +1,40 @@
+package org.openapitools.codegen.typescript.express.zod;
+
+import org.openapitools.codegen.CodegenType;
+import org.openapitools.codegen.SupportingFile;
+import org.openapitools.codegen.languages.TypeScriptExpressZodServerCodegen;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class TypeScriptExpressZodServerCodegenTest {
+
+ @Test(description = "exposes the expected generator metadata")
+ public void generatorMetadata() {
+ final TypeScriptExpressZodServerCodegen codegen = new TypeScriptExpressZodServerCodegen();
+ Assert.assertEquals(codegen.getName(), "typescript-express-zod-server");
+ Assert.assertEquals(codegen.getTag(), CodegenType.SERVER);
+ }
+
+ @Test(description = "emits everything as supporting files, no per-model/per-api templates")
+ public void processOptsRegistersSupportingFiles() {
+ final TypeScriptExpressZodServerCodegen codegen = new TypeScriptExpressZodServerCodegen();
+ codegen.processOpts();
+
+ Set outputs = codegen.supportingFiles().stream()
+ .map(sf -> sf.getFolder().isEmpty()
+ ? sf.getDestinationFilename()
+ : sf.getFolder() + "/" + sf.getDestinationFilename())
+ .collect(Collectors.toSet());
+ Assert.assertEquals(outputs, Set.of(
+ "types.ts", "schemas.ts", "index.ts",
+ "dtos/types.ts", "dtos/mappers.ts", "dtos/index.ts",
+ "express/handlers.ts", "express/types.ts", "express/router-factory.ts",
+ "express/errors.ts", "express/auth-middleware.ts", "express/index.ts"),
+ "unexpected supporting files: " + outputs);
+ Assert.assertTrue(codegen.modelTemplateFiles().isEmpty());
+ Assert.assertTrue(codegen.apiTemplateFiles().isEmpty());
+ }
+}
diff --git a/modules/openapi-generator/src/test/resources/3_0/typescript-express-zod/petstore.yaml b/modules/openapi-generator/src/test/resources/3_0/typescript-express-zod/petstore.yaml
new file mode 100644
index 000000000000..06c2a8f0a3a9
--- /dev/null
+++ b/modules/openapi-generator/src/test/resources/3_0/typescript-express-zod/petstore.yaml
@@ -0,0 +1,215 @@
+openapi: 3.0.3
+info:
+ title: Bookstore API
+ description: >
+ Minimal spec used by the typescript-express-zod-server / -client samples.
+ It stays within the generators' currently supported surface (each request
+ body and response is a single named model, or a void/no-content response)
+ while still exercising path/query params, nested & nullable $ref properties,
+ enum refs, and a discriminated union.
+ version: 1.0.0
+tags:
+ - name: catalog
+ description: Book catalog operations
+ - name: authors
+ description: Author operations
+paths:
+ /books/{bookId}:
+ get:
+ tags: [catalog]
+ operationId: getBook
+ summary: Get a book by id
+ parameters:
+ - name: bookId
+ in: path
+ required: true
+ schema:
+ type: integer
+ format: int64
+ - name: expand
+ in: query
+ required: false
+ schema:
+ type: boolean
+ responses:
+ '200':
+ description: The requested book
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Book'
+ '404':
+ description: Not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ delete:
+ tags: [catalog]
+ operationId: deleteBook
+ summary: Delete a book
+ parameters:
+ - name: bookId
+ in: path
+ required: true
+ schema:
+ type: integer
+ format: int64
+ responses:
+ '204':
+ description: Deleted
+ /books:
+ post:
+ tags: [catalog]
+ operationId: createBook
+ summary: Create a book
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CreateBookRequest'
+ responses:
+ '201':
+ description: The created book
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Book'
+ /books/{bookId}/latest-event:
+ get:
+ tags: [catalog]
+ operationId: getLatestBookEvent
+ summary: Get the latest event for a book (discriminated union response)
+ parameters:
+ - name: bookId
+ in: path
+ required: true
+ schema:
+ type: integer
+ format: int64
+ responses:
+ '200':
+ description: The latest event
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BookEvent'
+ /authors/{authorId}:
+ get:
+ tags: [authors]
+ operationId: getAuthor
+ summary: Get an author by id
+ parameters:
+ - name: authorId
+ in: path
+ required: true
+ schema:
+ type: integer
+ format: int64
+ responses:
+ '200':
+ description: The requested author
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Author'
+ /authors:
+ post:
+ tags: [authors]
+ operationId: createAuthor
+ summary: Create an author
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Author'
+ responses:
+ '201':
+ description: The created author
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Author'
+components:
+ schemas:
+ Genre:
+ type: string
+ enum: [FICTION, NONFICTION, POETRY]
+ Author:
+ type: object
+ required: [name]
+ properties:
+ id:
+ type: integer
+ format: int64
+ name:
+ type: string
+ Book:
+ type: object
+ required: [title]
+ properties:
+ id:
+ type: integer
+ format: int64
+ title:
+ type: string
+ genre:
+ $ref: '#/components/schemas/Genre'
+ author:
+ nullable: true
+ allOf:
+ - $ref: '#/components/schemas/Author'
+ pageCount:
+ type: integer
+ format: int32
+ nullable: true
+ CreateBookRequest:
+ type: object
+ required: [title]
+ properties:
+ title:
+ type: string
+ genre:
+ $ref: '#/components/schemas/Genre'
+ authorId:
+ type: integer
+ format: int64
+ BookAddedEvent:
+ type: object
+ required: [type, bookId]
+ properties:
+ type:
+ type: string
+ enum: [BOOK_ADDED]
+ bookId:
+ type: integer
+ format: int64
+ BookRemovedEvent:
+ type: object
+ required: [type, bookId]
+ properties:
+ type:
+ type: string
+ enum: [BOOK_REMOVED]
+ bookId:
+ type: integer
+ format: int64
+ BookEvent:
+ oneOf:
+ - $ref: '#/components/schemas/BookAddedEvent'
+ - $ref: '#/components/schemas/BookRemovedEvent'
+ discriminator:
+ propertyName: type
+ mapping:
+ BOOK_ADDED: '#/components/schemas/BookAddedEvent'
+ BOOK_REMOVED: '#/components/schemas/BookRemovedEvent'
+ Error:
+ type: object
+ required: [message]
+ properties:
+ message:
+ type: string
+ code:
+ type: string
diff --git a/samples/client/petstore/typescript-express-zod-client/.gitignore b/samples/client/petstore/typescript-express-zod-client/.gitignore
new file mode 100644
index 000000000000..73b44f4e9e31
--- /dev/null
+++ b/samples/client/petstore/typescript-express-zod-client/.gitignore
@@ -0,0 +1,5 @@
+/node_modules
+/dist
+/coverage
+*.log
+.DS_Store
diff --git a/samples/client/petstore/typescript-express-zod-client/builds/default/.openapi-generator-ignore b/samples/client/petstore/typescript-express-zod-client/builds/default/.openapi-generator-ignore
new file mode 100644
index 000000000000..7484ee590a38
--- /dev/null
+++ b/samples/client/petstore/typescript-express-zod-client/builds/default/.openapi-generator-ignore
@@ -0,0 +1,23 @@
+# OpenAPI Generator Ignore
+# Generated by openapi-generator https://github.com/openapitools/openapi-generator
+
+# Use this file to prevent files from being overwritten by the generator.
+# The patterns follow closely to .gitignore or .dockerignore.
+
+# As an example, the C# client generator defines ApiClient.cs.
+# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
+#ApiClient.cs
+
+# You can match any string of characters against a directory, file or extension with a single asterisk (*):
+#foo/*/qux
+# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
+
+# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
+#foo/**/qux
+# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
+
+# You can also negate patterns with an exclamation (!).
+# For example, you can ignore all files in a docs folder with the file extension .md:
+#docs/*.md
+# Then explicitly reverse the ignore rule for a single file:
+#!docs/README.md
diff --git a/samples/client/petstore/typescript-express-zod-client/builds/default/.openapi-generator/FILES b/samples/client/petstore/typescript-express-zod-client/builds/default/.openapi-generator/FILES
new file mode 100644
index 000000000000..26785f1d5cd0
--- /dev/null
+++ b/samples/client/petstore/typescript-express-zod-client/builds/default/.openapi-generator/FILES
@@ -0,0 +1,7 @@
+dtos/index.ts
+dtos/mappers.ts
+dtos/types.ts
+http-client.ts
+index.ts
+schemas.ts
+types.ts
diff --git a/samples/client/petstore/typescript-express-zod-client/builds/default/.openapi-generator/VERSION b/samples/client/petstore/typescript-express-zod-client/builds/default/.openapi-generator/VERSION
new file mode 100644
index 000000000000..186c33c96ed8
--- /dev/null
+++ b/samples/client/petstore/typescript-express-zod-client/builds/default/.openapi-generator/VERSION
@@ -0,0 +1 @@
+7.24.0-SNAPSHOT
diff --git a/samples/client/petstore/typescript-express-zod-client/builds/default/dtos/index.ts b/samples/client/petstore/typescript-express-zod-client/builds/default/dtos/index.ts
new file mode 100644
index 000000000000..be223c7d1e00
--- /dev/null
+++ b/samples/client/petstore/typescript-express-zod-client/builds/default/dtos/index.ts
@@ -0,0 +1,9 @@
+/**
+ * This code was generated by openapi-generator (typescript, framework 'express-zod').
+ *
+ * Changes to this file may cause incorrect behavior and will be lost if
+ * the code is regenerated.
+ */
+
+export * from "./types";
+export * from "./mappers";
diff --git a/samples/client/petstore/typescript-express-zod-client/builds/default/dtos/mappers.ts b/samples/client/petstore/typescript-express-zod-client/builds/default/dtos/mappers.ts
new file mode 100644
index 000000000000..b85e4523e58e
--- /dev/null
+++ b/samples/client/petstore/typescript-express-zod-client/builds/default/dtos/mappers.ts
@@ -0,0 +1,178 @@
+/**
+ * This code was generated by openapi-generator (typescript, framework 'express-zod').
+ *
+ * Changes to this file may cause incorrect behavior and will be lost if
+ * the code is regenerated.
+ */
+
+import { ZodError } from "zod";
+
+import type * as types from "../types";
+import type * as dtos from "./types";
+
+function compact(obj: T): T {
+ return Object.keys(obj).reduce((acc, key) => {
+ const value = obj[key as keyof T];
+ if (value !== undefined) {
+ acc[key as keyof T] = value;
+ }
+ return acc;
+ }, {} as T);
+}
+
+export function mapFromAuthorDto(
+ dto: dtos.AuthorDto,
+): types.Author {
+ return compact({
+ id: dto.id,
+ name: dto.name,
+ });
+}
+
+export function mapToAuthorDto(
+ obj: types.Author,
+): dtos.AuthorDto {
+ return compact({
+ id: obj.id,
+ name: obj.name,
+ });
+}
+
+export function mapFromBookDto(
+ dto: dtos.BookDto,
+): types.Book {
+ return compact({
+ id: dto.id,
+ title: dto.title,
+ genre: dto.genre,
+ author:
+ dto.author == null
+ ? dto.author
+ : mapFromAuthorDto(dto.author),
+ pageCount: dto.pageCount,
+ });
+}
+
+export function mapToBookDto(
+ obj: types.Book,
+): dtos.BookDto {
+ return compact({
+ id: obj.id,
+ title: obj.title,
+ genre: obj.genre,
+ author:
+ obj.author == null
+ ? obj.author
+ : mapToAuthorDto(obj.author),
+ pageCount: obj.pageCount,
+ });
+}
+
+export function mapFromBookAddedEventDto(
+ dto: dtos.BookAddedEventDto,
+): types.BookAddedEvent {
+ return compact({
+ type: dto.type,
+ bookId: dto.bookId,
+ });
+}
+
+export function mapToBookAddedEventDto(
+ obj: types.BookAddedEvent,
+): dtos.BookAddedEventDto {
+ return compact({
+ type: obj.type,
+ bookId: obj.bookId,
+ });
+}
+
+export function mapFromBookRemovedEventDto(
+ dto: dtos.BookRemovedEventDto,
+): types.BookRemovedEvent {
+ return compact({
+ type: dto.type,
+ bookId: dto.bookId,
+ });
+}
+
+export function mapToBookRemovedEventDto(
+ obj: types.BookRemovedEvent,
+): dtos.BookRemovedEventDto {
+ return compact({
+ type: obj.type,
+ bookId: obj.bookId,
+ });
+}
+
+export function mapFromBookEventDto(dto: dtos.BookEventDto): types.BookEvent {
+ switch (dto.type) {
+ case "BOOK_ADDED":
+ return mapFromBookAddedEventDto(dto);
+ case "BOOK_REMOVED":
+ return mapFromBookRemovedEventDto(dto);
+ default:
+ // On the client this maps a server response: an unknown discriminator
+ // means the server returned a variant not described by the spec. Surface
+ // it through the same ZodError channel the client already uses for
+ // response validation, so mapZodError (and any user override) applies.
+ throw new ZodError([
+ {
+ code: "custom",
+ path: ["type"],
+ message: `Unexpected BookEvent discriminator in server response: ${(dto as { type?: unknown }).type}`,
+ },
+ ]);
+ }
+}
+
+export function mapToBookEventDto(obj: types.BookEvent): dtos.BookEventDto {
+ switch (obj.type) {
+ case "BOOK_ADDED":
+ return mapToBookAddedEventDto(obj);
+ case "BOOK_REMOVED":
+ return mapToBookRemovedEventDto(obj);
+ default:
+ throw new Error(
+ `Unknown BookEvent discriminator: ${(obj as { type?: unknown }).type}`,
+ );
+ }
+}
+
+export function mapFromCreateBookRequestDto(
+ dto: dtos.CreateBookRequestDto,
+): types.CreateBookRequest {
+ return compact({
+ title: dto.title,
+ genre: dto.genre,
+ authorId: dto.authorId,
+ });
+}
+
+export function mapToCreateBookRequestDto(
+ obj: types.CreateBookRequest,
+): dtos.CreateBookRequestDto {
+ return compact({
+ title: obj.title,
+ genre: obj.genre,
+ authorId: obj.authorId,
+ });
+}
+
+export function mapFromModelErrorDto(
+ dto: dtos.ModelErrorDto,
+): types.ModelError {
+ return compact({
+ message: dto.message,
+ code: dto.code,
+ });
+}
+
+export function mapToModelErrorDto(
+ obj: types.ModelError,
+): dtos.ModelErrorDto {
+ return compact({
+ message: obj.message,
+ code: obj.code,
+ });
+}
+
diff --git a/samples/client/petstore/typescript-express-zod-client/builds/default/dtos/types.ts b/samples/client/petstore/typescript-express-zod-client/builds/default/dtos/types.ts
new file mode 100644
index 000000000000..0c75df04cf5f
--- /dev/null
+++ b/samples/client/petstore/typescript-express-zod-client/builds/default/dtos/types.ts
@@ -0,0 +1,52 @@
+/**
+ * This code was generated by openapi-generator (typescript, framework 'express-zod').
+ *
+ * Changes to this file may cause incorrect behavior and will be lost if
+ * the code is regenerated.
+ */
+
+import type * as types from "../types";
+
+/** The over-the-wire representation of the {@link types.Author|Author} type. */
+export type AuthorDto = {
+ id?: number;
+ name: string;
+};
+
+/** The over-the-wire representation of the {@link types.Book|Book} type. */
+export type BookDto = {
+ id?: number;
+ title: string;
+ genre?: types.Genre;
+ author?: AuthorDto | null;
+ pageCount?: number | null;
+};
+
+/** The over-the-wire representation of the {@link types.BookAddedEvent|BookAddedEvent} type. */
+export type BookAddedEventDto = {
+ type: "BOOK_ADDED";
+ bookId: number;
+};
+
+/** The over-the-wire representation of the {@link types.BookRemovedEvent|BookRemovedEvent} type. */
+export type BookRemovedEventDto = {
+ type: "BOOK_REMOVED";
+ bookId: number;
+};
+
+/** The over-the-wire representation of the {@link types.BookEvent|BookEvent} type. */
+export type BookEventDto = BookAddedEventDto | BookRemovedEventDto;
+
+/** The over-the-wire representation of the {@link types.CreateBookRequest|CreateBookRequest} type. */
+export type CreateBookRequestDto = {
+ title: string;
+ genre?: types.Genre;
+ authorId?: number;
+};
+
+/** The over-the-wire representation of the {@link types.ModelError|ModelError} type. */
+export type ModelErrorDto = {
+ message: string;
+ code?: string;
+};
+
diff --git a/samples/client/petstore/typescript-express-zod-client/builds/default/http-client.ts b/samples/client/petstore/typescript-express-zod-client/builds/default/http-client.ts
new file mode 100644
index 000000000000..5fa42c3ad50c
--- /dev/null
+++ b/samples/client/petstore/typescript-express-zod-client/builds/default/http-client.ts
@@ -0,0 +1,178 @@
+/**
+ * This code was generated by openapi-generator (typescript, framework 'express-zod').
+ *
+ * Changes to this file may cause incorrect behavior and will be lost if
+ * the code is regenerated.
+ */
+
+import * as types from "./types";
+import * as dtos from "./dtos/types";
+import * as mappers from "./dtos/mappers";
+import * as schemas from "./schemas";
+import { ZodError } from "zod";
+
+/** Minimal fetch-like interface for making HTTP requests. */
+export interface FetchLike {
+ (resource: string, init?: {
+ method?: string;
+ headers?: Record;
+ body?: string;
+ }): Promise<{ json(): Promise; status: number }>;
+}
+
+/** Options for configuring an HTTP client. */
+export interface ClientOptions {
+ /** Base URL prefix prepended to all request paths (e.g. "https://api.example.com"). */
+ root?: string;
+ /** Custom mapper for Zod validation errors on the response. */
+ mapZodError?: (err: ZodError) => types.ModelError[];
+ /** Custom mapper for unhandled exceptions. */
+ mapUnhandledException?: (err: unknown) => types.ModelError[];
+}
+
+function defaultMapZodError(err: ZodError): types.ModelError[] {
+ return err.issues.map((issue) => ({
+ message: issue.message,
+ code: String(issue.code),
+ }));
+}
+
+function defaultMapUnhandledException(err: unknown): types.ModelError[] {
+ const message = err instanceof Error ? err.message : String(err);
+ return [{ message: message }];
+}
+
+/** HTTP client for the AuthorsService */
+export class HttpAuthorsService implements types.AuthorsService {
+ private fetch: FetchLike;
+ private root: string;
+ private mapZodError: (err: ZodError) => types.ModelError[];
+ private mapUnhandledException: (err: unknown) => types.ModelError[];
+
+ constructor(fetch: FetchLike, options?: ClientOptions) {
+ this.fetch = fetch;
+ this.root = options?.root ?? "";
+ this.mapZodError = options?.mapZodError ?? defaultMapZodError;
+ this.mapUnhandledException = options?.mapUnhandledException ?? defaultMapUnhandledException;
+ }
+
+ /** Create an author */
+ async createAuthor(params: types.CreateAuthorParams): Promise {
+ const url = `${this.root}/authors`;
+ try {
+ const response = await this.fetch(url, {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify((mappers.mapToAuthorDto)(params.author)),
+ });
+ const json = await response.json();
+ return (mappers.mapFromAuthorDto)(schemas.CreateAuthorResponseSchema.parse(json));
+ } catch (err) {
+ if (err instanceof ZodError) {
+ return { errors: this.mapZodError(err) } as unknown as types.Author;
+ }
+ return { errors: this.mapUnhandledException(err) } as unknown as types.Author;
+ }
+ }
+
+ /** Get an author by id */
+ async getAuthor(params: types.GetAuthorParams): Promise {
+ const url = `${this.root}/authors/${encodeURIComponent(String(params.authorId))}`;
+ try {
+ const response = await this.fetch(url);
+ const json = await response.json();
+ return (mappers.mapFromAuthorDto)(schemas.GetAuthorResponseSchema.parse(json));
+ } catch (err) {
+ if (err instanceof ZodError) {
+ return { errors: this.mapZodError(err) } as unknown as types.Author;
+ }
+ return { errors: this.mapUnhandledException(err) } as unknown as types.Author;
+ }
+ }
+
+}
+
+/** HTTP client for the CatalogService */
+export class HttpCatalogService implements types.CatalogService {
+ private fetch: FetchLike;
+ private root: string;
+ private mapZodError: (err: ZodError) => types.ModelError[];
+ private mapUnhandledException: (err: unknown) => types.ModelError[];
+
+ constructor(fetch: FetchLike, options?: ClientOptions) {
+ this.fetch = fetch;
+ this.root = options?.root ?? "";
+ this.mapZodError = options?.mapZodError ?? defaultMapZodError;
+ this.mapUnhandledException = options?.mapUnhandledException ?? defaultMapUnhandledException;
+ }
+
+ /** Create a book */
+ async createBook(params: types.CreateBookParams): Promise {
+ const url = `${this.root}/books`;
+ try {
+ const response = await this.fetch(url, {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify((mappers.mapToCreateBookRequestDto)(params.createBookRequest)),
+ });
+ const json = await response.json();
+ return (mappers.mapFromBookDto)(schemas.CreateBookResponseSchema.parse(json));
+ } catch (err) {
+ if (err instanceof ZodError) {
+ return { errors: this.mapZodError(err) } as unknown as types.Book;
+ }
+ return { errors: this.mapUnhandledException(err) } as unknown as types.Book;
+ }
+ }
+
+ /** Delete a book */
+ async deleteBook(params: types.DeleteBookParams): Promise {
+ const url = `${this.root}/books/${encodeURIComponent(String(params.bookId))}`;
+ try {
+ const response = await this.fetch(url, { method: "DELETE" });
+ // No response body expected (e.g. 204 No Content); nothing to parse.
+ void response;
+ return;
+ } catch (err) {
+ if (err instanceof ZodError) {
+ return { errors: this.mapZodError(err) } as unknown as any;
+ }
+ return { errors: this.mapUnhandledException(err) } as unknown as any;
+ }
+ }
+
+ /** Get a book by id */
+ async getBook(params: types.GetBookParams): Promise {
+ const query = new URLSearchParams();
+ if (params.expand !== undefined) query.set("expand", String(params.expand));
+ const queryString = query.toString();
+ const url = `${this.root}/books/${encodeURIComponent(String(params.bookId))}${queryString ? `?${queryString}` : ""}`;
+ try {
+ const response = await this.fetch(url);
+ const json = await response.json();
+ return (mappers.mapFromBookDto)(schemas.GetBookResponseSchema.parse(json));
+ } catch (err) {
+ if (err instanceof ZodError) {
+ return { errors: this.mapZodError(err) } as unknown as types.Book;
+ }
+ return { errors: this.mapUnhandledException(err) } as unknown as types.Book;
+ }
+ }
+
+ /** Get the latest event for a book (discriminated union response) */
+ async getLatestBookEvent(params: types.GetLatestBookEventParams): Promise {
+ const url = `${this.root}/books/${encodeURIComponent(String(params.bookId))}/latest-event`;
+ try {
+ const response = await this.fetch(url);
+ const json = await response.json();
+ return (mappers.mapFromBookEventDto)(schemas.GetLatestBookEventResponseSchema.parse(json));
+ } catch (err) {
+ if (err instanceof ZodError) {
+ return { errors: this.mapZodError(err) } as unknown as types.BookEvent;
+ }
+ return { errors: this.mapUnhandledException(err) } as unknown as types.BookEvent;
+ }
+ }
+
+}
+
diff --git a/samples/client/petstore/typescript-express-zod-client/builds/default/index.ts b/samples/client/petstore/typescript-express-zod-client/builds/default/index.ts
new file mode 100644
index 000000000000..f4e733094774
--- /dev/null
+++ b/samples/client/petstore/typescript-express-zod-client/builds/default/index.ts
@@ -0,0 +1,11 @@
+/**
+ * This code was generated by openapi-generator (typescript, framework 'express-zod').
+ *
+ * Changes to this file may cause incorrect behavior and will be lost if
+ * the code is regenerated.
+ */
+
+export * from "./types";
+export * from "./schemas";
+export * from "./dtos";
+export * from "./http-client";
diff --git a/samples/client/petstore/typescript-express-zod-client/builds/default/schemas.ts b/samples/client/petstore/typescript-express-zod-client/builds/default/schemas.ts
new file mode 100644
index 000000000000..54043b987553
--- /dev/null
+++ b/samples/client/petstore/typescript-express-zod-client/builds/default/schemas.ts
@@ -0,0 +1,60 @@
+/**
+ * This code was generated by openapi-generator (typescript, framework 'express-zod').
+ *
+ * Changes to this file may cause incorrect behavior and will be lost if
+ * the code is regenerated.
+ */
+
+import { z } from "zod";
+
+export const AuthorSchema = z.object({
+ id: z.coerce.number().int().optional(),
+ name: z.string(),
+});
+
+export const GenreSchema = z.enum(['FICTION', 'NONFICTION', 'POETRY']);
+
+export const BookSchema = z.object({
+ id: z.coerce.number().int().optional(),
+ title: z.string(),
+ genre: GenreSchema.optional(),
+ author: AuthorSchema.nullable().optional(),
+ pageCount: z.coerce.number().int().nullable().optional(),
+});
+
+export const BookAddedEventSchema = z.object({
+ type: z.literal("BOOK_ADDED"),
+ bookId: z.coerce.number().int(),
+});
+
+export const BookRemovedEventSchema = z.object({
+ type: z.literal("BOOK_REMOVED"),
+ bookId: z.coerce.number().int(),
+});
+
+export const BookEventSchema = z.discriminatedUnion("type", [
+ BookAddedEventSchema,
+ BookRemovedEventSchema,
+]);
+
+export const CreateBookRequestSchema = z.object({
+ title: z.string(),
+ genre: GenreSchema.optional(),
+ authorId: z.coerce.number().int().optional(),
+});
+
+export const ModelErrorSchema = z.object({
+ message: z.string(),
+ code: z.string().optional(),
+});
+
+export const CreateAuthorResponseSchema = AuthorSchema;
+
+export const CreateBookResponseSchema = BookSchema;
+
+export const GetAuthorResponseSchema = AuthorSchema;
+
+export const GetBookResponseSchema = BookSchema;
+
+export const GetLatestBookEventResponseSchema = BookEventSchema;
+
diff --git a/samples/client/petstore/typescript-express-zod-client/builds/default/types.ts b/samples/client/petstore/typescript-express-zod-client/builds/default/types.ts
new file mode 100644
index 000000000000..ac3004fbcf9c
--- /dev/null
+++ b/samples/client/petstore/typescript-express-zod-client/builds/default/types.ts
@@ -0,0 +1,111 @@
+/**
+ * This code was generated by openapi-generator (typescript, framework 'express-zod').
+ *
+ * Changes to this file may cause incorrect behavior and will be lost if
+ * the code is regenerated.
+ */
+
+/** Interface for the AuthorsService */
+export interface AuthorsService {
+ /** Create an author */
+ createAuthor(params: CreateAuthorParams): Promise;
+
+ /** Get an author by id */
+ getAuthor(params: GetAuthorParams): Promise;
+
+}
+
+/** Interface for the CatalogService */
+export interface CatalogService {
+ /** Create a book */
+ createBook(params: CreateBookParams): Promise;
+
+ /** Delete a book */
+ deleteBook(params: DeleteBookParams): Promise;
+
+ /** Get a book by id */
+ getBook(params: GetBookParams): Promise;
+
+ /** Get the latest event for a book (discriminated union response) */
+ getLatestBookEvent(params: GetLatestBookEventParams): Promise;
+
+}
+
+export type CreateAuthorParams = {
+ /** author */
+ author: Author;
+};
+
+export type CreateBookParams = {
+ /** createBookRequest */
+ createBookRequest: CreateBookRequest;
+};
+
+export type DeleteBookParams = {
+ /** bookId */
+ bookId: number;
+};
+
+export type GetAuthorParams = {
+ /** authorId */
+ authorId: number;
+};
+
+export type GetBookParams = {
+ /** bookId */
+ bookId: number;
+ /** expand */
+ expand?: boolean;
+};
+
+export type GetLatestBookEventParams = {
+ /** bookId */
+ bookId: number;
+};
+
+export type Author = {
+ id?: number;
+ name: string;
+};
+
+export type Genre = 'FICTION' | 'NONFICTION' | 'POETRY';
+
+export type Book = {
+ id?: number;
+ title: string;
+ genre?: Genre;
+ author?: Author | null;
+ pageCount?: number | null;
+};
+
+export type BookAddedEvent = {
+ type: "BOOK_ADDED";
+ bookId: number;
+};
+
+export type BookRemovedEvent = {
+ type: "BOOK_REMOVED";
+ bookId: number;
+};
+
+export type BookEvent = BookAddedEvent | BookRemovedEvent;
+
+export function isBookAddedEvent(obj: BookEvent): obj is BookAddedEvent {
+ return obj.type === "BOOK_ADDED";
+}
+
+export function isBookRemovedEvent(obj: BookEvent): obj is BookRemovedEvent {
+ return obj.type === "BOOK_REMOVED";
+}
+
+export type CreateBookRequest = {
+ title: string;
+ genre?: Genre;
+ authorId?: number;
+};
+
+export type ModelError = {
+ message: string;
+ code?: string;
+};
+
diff --git a/samples/client/petstore/typescript-express-zod-client/jest.config.js b/samples/client/petstore/typescript-express-zod-client/jest.config.js
new file mode 100644
index 000000000000..ed8fc6ffeabf
--- /dev/null
+++ b/samples/client/petstore/typescript-express-zod-client/jest.config.js
@@ -0,0 +1,6 @@
+/** @type {import('ts-jest').JestConfigWithTsJest} */
+module.exports = {
+ preset: "ts-jest",
+ testEnvironment: "node",
+ testMatch: ["**/test/**/*.e2e-spec.ts"],
+};
diff --git a/samples/client/petstore/typescript-express-zod-client/package-lock.json b/samples/client/petstore/typescript-express-zod-client/package-lock.json
new file mode 100644
index 000000000000..55072d83ba13
--- /dev/null
+++ b/samples/client/petstore/typescript-express-zod-client/package-lock.json
@@ -0,0 +1,3872 @@
+{
+ "name": "typescript-express-zod-client-petstore",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "typescript-express-zod-client-petstore",
+ "version": "1.0.0",
+ "dependencies": {
+ "zod": "^4.0.0"
+ },
+ "devDependencies": {
+ "@types/jest": "^29.5.14",
+ "@types/node": "^22.10.7",
+ "jest": "^29.7.0",
+ "ts-jest": "^29.2.5",
+ "typescript": "^5.7.3"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz",
+ "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.29.7",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz",
+ "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz",
+ "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.29.7",
+ "@babel/generator": "^7.29.7",
+ "@babel/helper-compilation-targets": "^7.29.7",
+ "@babel/helper-module-transforms": "^7.29.7",
+ "@babel/helpers": "^7.29.7",
+ "@babel/parser": "^7.29.7",
+ "@babel/template": "^7.29.7",
+ "@babel/traverse": "^7.29.7",
+ "@babel/types": "^7.29.7",
+ "@jridgewell/remapping": "^2.3.5",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz",
+ "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.29.7",
+ "@babel/types": "^7.29.7",
+ "@jridgewell/gen-mapping": "^0.3.12",
+ "@jridgewell/trace-mapping": "^0.3.28",
+ "jsesc": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz",
+ "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/compat-data": "^7.29.7",
+ "@babel/helper-validator-option": "^7.29.7",
+ "browserslist": "^4.24.0",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-globals": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz",
+ "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz",
+ "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/traverse": "^7.29.7",
+ "@babel/types": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz",
+ "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.29.7",
+ "@babel/helper-validator-identifier": "^7.29.7",
+ "@babel/traverse": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz",
+ "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz",
+ "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz",
+ "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz",
+ "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz",
+ "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.29.7",
+ "@babel/types": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz",
+ "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.29.7"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-async-generators": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
+ "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-bigint": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz",
+ "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-class-properties": {
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
+ "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.12.13"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-class-static-block": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz",
+ "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-import-attributes": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.29.7.tgz",
+ "integrity": "sha512-zGYcYfq/WmZ4V+kBIXQon9dSSc8ircGZqw9ZaNhhGj9nZkeBu1jHLBDQqYYi5WA9uawvA2sIMbry2nCFhf5Djg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-import-meta": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
+ "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-json-strings": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
+ "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-jsx": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.29.7.tgz",
+ "integrity": "sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
+ "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
+ "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-numeric-separator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
+ "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-object-rest-spread": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
+ "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-catch-binding": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
+ "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-chaining": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
+ "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-private-property-in-object": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz",
+ "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-top-level-await": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
+ "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-typescript": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.29.7.tgz",
+ "integrity": "sha512-ngr+82Sh0xMz25TPCZi+nC2iTzjfCdWS2ONXTp/PtSCHCgaCNBpdMqgvJ2ccdLlClVZ7sisIgB914j/JFe+RZA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz",
+ "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.29.7",
+ "@babel/parser": "^7.29.7",
+ "@babel/types": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz",
+ "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.29.7",
+ "@babel/generator": "^7.29.7",
+ "@babel/helper-globals": "^7.29.7",
+ "@babel/parser": "^7.29.7",
+ "@babel/template": "^7.29.7",
+ "@babel/types": "^7.29.7",
+ "debug": "^4.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz",
+ "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.29.7",
+ "@babel/helper-validator-identifier": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@bcoe/v8-coverage": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
+ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@istanbuljs/load-nyc-config": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
+ "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "camelcase": "^5.3.1",
+ "find-up": "^4.1.0",
+ "get-package-type": "^0.1.0",
+ "js-yaml": "^3.13.1",
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/schema": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.6.tgz",
+ "integrity": "sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@jest/console": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz",
+ "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/core": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz",
+ "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/console": "^29.7.0",
+ "@jest/reporters": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.9",
+ "jest-changed-files": "^29.7.0",
+ "jest-config": "^29.7.0",
+ "jest-haste-map": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.7.0",
+ "jest-resolve-dependencies": "^29.7.0",
+ "jest-runner": "^29.7.0",
+ "jest-runtime": "^29.7.0",
+ "jest-snapshot": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "jest-watcher": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@jest/environment": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz",
+ "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-mock": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/expect": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz",
+ "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "expect": "^29.7.0",
+ "jest-snapshot": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/expect-utils": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz",
+ "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "jest-get-type": "^29.6.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/fake-timers": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz",
+ "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@sinonjs/fake-timers": "^10.0.2",
+ "@types/node": "*",
+ "jest-message-util": "^29.7.0",
+ "jest-mock": "^29.7.0",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/globals": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz",
+ "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/expect": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "jest-mock": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/reporters": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz",
+ "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@bcoe/v8-coverage": "^0.2.3",
+ "@jest/console": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "collect-v8-coverage": "^1.0.0",
+ "exit": "^0.1.2",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "istanbul-lib-coverage": "^3.0.0",
+ "istanbul-lib-instrument": "^6.0.0",
+ "istanbul-lib-report": "^3.0.0",
+ "istanbul-lib-source-maps": "^4.0.0",
+ "istanbul-reports": "^3.1.3",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "slash": "^3.0.0",
+ "string-length": "^4.0.1",
+ "strip-ansi": "^6.0.0",
+ "v8-to-istanbul": "^9.0.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@sinclair/typebox": "^0.27.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/source-map": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz",
+ "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "callsites": "^3.0.0",
+ "graceful-fs": "^4.2.9"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/test-result": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz",
+ "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/console": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "collect-v8-coverage": "^1.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/test-sequencer": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz",
+ "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/test-result": "^29.7.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/transform": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz",
+ "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@jest/types": "^29.6.3",
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "babel-plugin-istanbul": "^6.1.1",
+ "chalk": "^4.0.0",
+ "convert-source-map": "^2.0.0",
+ "fast-json-stable-stringify": "^2.1.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "pirates": "^4.0.4",
+ "slash": "^3.0.0",
+ "write-file-atomic": "^4.0.2"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.13",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
+ "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/remapping": {
+ "version": "2.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
+ "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.31",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
+ "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@sinclair/typebox": {
+ "version": "0.27.10",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz",
+ "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@sinonjs/commons": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz",
+ "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "type-detect": "4.0.8"
+ }
+ },
+ "node_modules/@sinonjs/fake-timers": {
+ "version": "10.3.0",
+ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz",
+ "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@sinonjs/commons": "^3.0.0"
+ }
+ },
+ "node_modules/@types/babel__core": {
+ "version": "7.20.5",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
+ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
+ "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
+ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
+ "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.28.2"
+ }
+ },
+ "node_modules/@types/graceful-fs": {
+ "version": "4.1.9",
+ "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz",
+ "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/istanbul-lib-coverage": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
+ "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/istanbul-lib-report": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz",
+ "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/istanbul-lib-coverage": "*"
+ }
+ },
+ "node_modules/@types/istanbul-reports": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz",
+ "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/istanbul-lib-report": "*"
+ }
+ },
+ "node_modules/@types/jest": {
+ "version": "29.5.14",
+ "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz",
+ "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "expect": "^29.0.0",
+ "pretty-format": "^29.0.0"
+ }
+ },
+ "node_modules/@types/node": {
+ "version": "22.20.0",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.0.tgz",
+ "integrity": "sha512-QWlFW2wf3nTjC13/DqRnBpR4ZO36VJH/JVBkA/vcnmbTBNQIlnObqyqZE1tUR7+Ni23Lda8R1BxMfbXRpCUx5g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.21.0"
+ }
+ },
+ "node_modules/@types/stack-utils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
+ "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/yargs": {
+ "version": "17.0.35",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz",
+ "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "node_modules/@types/yargs-parser": {
+ "version": "21.0.3",
+ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz",
+ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/ansi-escapes": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "type-fest": "^0.21.3"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "node_modules/babel-jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz",
+ "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/transform": "^29.7.0",
+ "@types/babel__core": "^7.1.14",
+ "babel-plugin-istanbul": "^6.1.1",
+ "babel-preset-jest": "^29.6.3",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.8.0"
+ }
+ },
+ "node_modules/babel-plugin-istanbul": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz",
+ "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@istanbuljs/load-nyc-config": "^1.0.0",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-instrument": "^5.0.4",
+ "test-exclude": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz",
+ "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/core": "^7.12.3",
+ "@babel/parser": "^7.14.7",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-coverage": "^3.2.0",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/babel-plugin-jest-hoist": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz",
+ "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.3.3",
+ "@babel/types": "^7.3.3",
+ "@types/babel__core": "^7.1.14",
+ "@types/babel__traverse": "^7.0.6"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/babel-preset-current-node-syntax": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz",
+ "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/plugin-syntax-async-generators": "^7.8.4",
+ "@babel/plugin-syntax-bigint": "^7.8.3",
+ "@babel/plugin-syntax-class-properties": "^7.12.13",
+ "@babel/plugin-syntax-class-static-block": "^7.14.5",
+ "@babel/plugin-syntax-import-attributes": "^7.24.7",
+ "@babel/plugin-syntax-import-meta": "^7.10.4",
+ "@babel/plugin-syntax-json-strings": "^7.8.3",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+ "@babel/plugin-syntax-private-property-in-object": "^7.14.5",
+ "@babel/plugin-syntax-top-level-await": "^7.14.5"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0 || ^8.0.0-0"
+ }
+ },
+ "node_modules/babel-preset-jest": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz",
+ "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "babel-plugin-jest-hoist": "^29.6.3",
+ "babel-preset-current-node-syntax": "^1.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/baseline-browser-mapping": {
+ "version": "2.10.42",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.42.tgz",
+ "integrity": "sha512-c/jurFrDLyui7o1J86yLkRu4LMsTYcBohveus7/I2Hzdn9KIP2bdJPTue/lR1KH46enoPbD77GKeSYNdyPoD3Q==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.cjs"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz",
+ "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.28.4",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.4.tgz",
+ "integrity": "sha512-MTc8i/x9jBQd1iMw2CFGS+rwMa07eYjLR0CCTLDACl9xhxy+nIs3KeML/biicXtk9JrZ6dnnTatmc7ErPXIxqw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "baseline-browser-mapping": "^2.10.38",
+ "caniuse-lite": "^1.0.30001799",
+ "electron-to-chromium": "^1.5.376",
+ "node-releases": "^2.0.48",
+ "update-browserslist-db": "^1.2.3"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/bs-logger": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz",
+ "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-json-stable-stringify": "2.x"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/bser": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz",
+ "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "node-int64": "^0.4.0"
+ }
+ },
+ "node_modules/buffer-from": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001800",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001800.tgz",
+ "integrity": "sha512-MMHtuAz9Ys840zAY5F4k6fV5GaivZ9sPk+nz0mY+GYVzRBnYkN0mpqkSR92oWRQ19yQWo4HvBV/FnC16AJX8MA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "CC-BY-4.0"
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/char-regex": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
+ "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cjs-module-lexer": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz",
+ "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/co": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+ "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "iojs": ">= 1.0.0",
+ "node": ">= 0.12.0"
+ }
+ },
+ "node_modules/collect-v8-coverage": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz",
+ "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/create-jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz",
+ "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "chalk": "^4.0.0",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.9",
+ "jest-config": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "prompts": "^2.0.1"
+ },
+ "bin": {
+ "create-jest": "bin/create-jest.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/dedent": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.2.tgz",
+ "integrity": "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "babel-plugin-macros": "^3.1.0"
+ },
+ "peerDependenciesMeta": {
+ "babel-plugin-macros": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deepmerge": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
+ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/detect-newline": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
+ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/diff-sequences": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz",
+ "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.387",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.387.tgz",
+ "integrity": "sha512-TaxwufTFDufvPEoXdhwVrA3UdFWBeWGkYoJ1K8ldF1xe6gKfth6iRNS5lTQ5JPNOHdGQm8PT1QYKUqFLCiUefQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/emittery": {
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz",
+ "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/emittery?sponsor=1"
+ }
+ },
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/error-ex": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz",
+ "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
+ "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/execa": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.0",
+ "human-signals": "^2.1.0",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.1",
+ "onetime": "^5.1.2",
+ "signal-exit": "^3.0.3",
+ "strip-final-newline": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/exit": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
+ "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/expect": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz",
+ "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/expect-utils": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fb-watchman": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz",
+ "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "bser": "2.1.1"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/get-package-type": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
+ "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/get-stream": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/handlebars": {
+ "version": "4.7.9",
+ "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz",
+ "integrity": "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "minimist": "^1.2.5",
+ "neo-async": "^2.6.2",
+ "source-map": "^0.6.1",
+ "wordwrap": "^1.0.0"
+ },
+ "bin": {
+ "handlebars": "bin/handlebars"
+ },
+ "engines": {
+ "node": ">=0.4.7"
+ },
+ "optionalDependencies": {
+ "uglify-js": "^3.1.4"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz",
+ "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/html-escaper": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
+ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/human-signals": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
+ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=10.17.0"
+ }
+ },
+ "node_modules/import-local": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz",
+ "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "pkg-dir": "^4.2.0",
+ "resolve-cwd": "^3.0.0"
+ },
+ "bin": {
+ "import-local-fixture": "fixtures/cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/is-core-module": {
+ "version": "2.16.2",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz",
+ "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-generator-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz",
+ "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/istanbul-lib-coverage": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
+ "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/istanbul-lib-instrument": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz",
+ "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/core": "^7.23.9",
+ "@babel/parser": "^7.23.9",
+ "@istanbuljs/schema": "^0.1.3",
+ "istanbul-lib-coverage": "^3.2.0",
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-instrument/node_modules/semver": {
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-report": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
+ "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "istanbul-lib-coverage": "^3.0.0",
+ "make-dir": "^4.0.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-source-maps": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz",
+ "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "debug": "^4.1.1",
+ "istanbul-lib-coverage": "^3.0.0",
+ "source-map": "^0.6.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-reports": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz",
+ "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "html-escaper": "^2.0.0",
+ "istanbul-lib-report": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz",
+ "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/core": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "import-local": "^3.0.2",
+ "jest-cli": "^29.7.0"
+ },
+ "bin": {
+ "jest": "bin/jest.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-changed-files": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz",
+ "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "execa": "^5.0.0",
+ "jest-util": "^29.7.0",
+ "p-limit": "^3.1.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-circus": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz",
+ "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/expect": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "co": "^4.6.0",
+ "dedent": "^1.0.0",
+ "is-generator-fn": "^2.0.0",
+ "jest-each": "^29.7.0",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-runtime": "^29.7.0",
+ "jest-snapshot": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "p-limit": "^3.1.0",
+ "pretty-format": "^29.7.0",
+ "pure-rand": "^6.0.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-cli": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz",
+ "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/core": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "chalk": "^4.0.0",
+ "create-jest": "^29.7.0",
+ "exit": "^0.1.2",
+ "import-local": "^3.0.2",
+ "jest-config": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "yargs": "^17.3.1"
+ },
+ "bin": {
+ "jest": "bin/jest.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-config": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz",
+ "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@jest/test-sequencer": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "babel-jest": "^29.7.0",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "deepmerge": "^4.2.2",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "jest-circus": "^29.7.0",
+ "jest-environment-node": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.7.0",
+ "jest-runner": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "parse-json": "^5.2.0",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@types/node": "*",
+ "ts-node": ">=9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "ts-node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-diff": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz",
+ "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "diff-sequences": "^29.6.3",
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-docblock": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz",
+ "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "detect-newline": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-each": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz",
+ "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-environment-node": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz",
+ "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-mock": "^29.7.0",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-get-type": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz",
+ "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-haste-map": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz",
+ "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/graceful-fs": "^4.1.3",
+ "@types/node": "*",
+ "anymatch": "^3.0.3",
+ "fb-watchman": "^2.0.0",
+ "graceful-fs": "^4.2.9",
+ "jest-regex-util": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "walker": "^1.0.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "^2.3.2"
+ }
+ },
+ "node_modules/jest-leak-detector": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz",
+ "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-matcher-utils": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz",
+ "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "jest-diff": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-message-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz",
+ "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.12.13",
+ "@jest/types": "^29.6.3",
+ "@types/stack-utils": "^2.0.0",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-mock": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz",
+ "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-pnp-resolver": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz",
+ "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ },
+ "peerDependencies": {
+ "jest-resolve": "*"
+ },
+ "peerDependenciesMeta": {
+ "jest-resolve": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-regex-util": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz",
+ "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-resolve": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz",
+ "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-pnp-resolver": "^1.2.2",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "resolve": "^1.20.0",
+ "resolve.exports": "^2.0.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-resolve-dependencies": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz",
+ "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "jest-regex-util": "^29.6.3",
+ "jest-snapshot": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-runner": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz",
+ "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/console": "^29.7.0",
+ "@jest/environment": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "emittery": "^0.13.1",
+ "graceful-fs": "^4.2.9",
+ "jest-docblock": "^29.7.0",
+ "jest-environment-node": "^29.7.0",
+ "jest-haste-map": "^29.7.0",
+ "jest-leak-detector": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-resolve": "^29.7.0",
+ "jest-runtime": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-watcher": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "p-limit": "^3.1.0",
+ "source-map-support": "0.5.13"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-runtime": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz",
+ "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/globals": "^29.7.0",
+ "@jest/source-map": "^29.6.3",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "cjs-module-lexer": "^1.0.0",
+ "collect-v8-coverage": "^1.0.0",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-mock": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.7.0",
+ "jest-snapshot": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "slash": "^3.0.0",
+ "strip-bom": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-snapshot": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz",
+ "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@babel/generator": "^7.7.2",
+ "@babel/plugin-syntax-jsx": "^7.7.2",
+ "@babel/plugin-syntax-typescript": "^7.7.2",
+ "@babel/types": "^7.3.3",
+ "@jest/expect-utils": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "babel-preset-current-node-syntax": "^1.0.0",
+ "chalk": "^4.0.0",
+ "expect": "^29.7.0",
+ "graceful-fs": "^4.2.9",
+ "jest-diff": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "natural-compare": "^1.4.0",
+ "pretty-format": "^29.7.0",
+ "semver": "^7.5.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-snapshot/node_modules/semver": {
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-validate": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz",
+ "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "camelcase": "^6.2.0",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^29.6.3",
+ "leven": "^3.1.0",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-validate/node_modules/camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/jest-watcher": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz",
+ "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.0.0",
+ "emittery": "^0.13.1",
+ "jest-util": "^29.7.0",
+ "string-length": "^4.0.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-worker": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz",
+ "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "jest-util": "^29.7.0",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-worker/node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/js-yaml": {
+ "version": "3.15.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.15.0.tgz",
+ "integrity": "sha512-ttBQIIQPDeLjpPOohtUdXuXUVoA2uIB6fEH9HyJ7234s5mBJ5wTx20njxplLZQgLaOfpmPQA7X2t5AX6tIPbog==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsesc": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/json-parse-even-better-errors": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/kleur": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
+ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/leven": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
+ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/lines-and-columns": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/lodash.memoize": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
+ "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node_modules/make-dir": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
+ "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "semver": "^7.5.3"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/make-dir/node_modules/semver": {
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/make-error": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
+ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/makeerror": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
+ "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "tmpl": "1.0.5"
+ }
+ },
+ "node_modules/merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "braces": "^3.0.3",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
+ "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/neo-async": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
+ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/node-int64": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
+ "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.50",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.50.tgz",
+ "integrity": "sha512-J6l92tKHX6w8Jy5nO1Vuc01NoIiRGi/d6qBKVxh+IQ8Cr3b6HbVNfKiF8ZpFKufTwpwxMmce2W3iQZ861ZRyTg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mimic-fn": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/p-locate/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse-json": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-even-better-errors": "^2.3.0",
+ "lines-and-columns": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
+ "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pirates": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz",
+ "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/pkg-dir": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "find-up": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/pretty-format/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/prompts": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
+ "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "kleur": "^3.0.3",
+ "sisteransi": "^1.0.5"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/pure-rand": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz",
+ "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/dubzzz"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fast-check"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/react-is": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
+ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "1.22.12",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz",
+ "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "is-core-module": "^2.16.1",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-cwd": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
+ "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/resolve.exports": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz",
+ "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/sisteransi": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
+ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-support": {
+ "version": "0.5.13",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz",
+ "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/stack-utils": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
+ "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "escape-string-regexp": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/string-length": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
+ "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "char-regex": "^1.0.2",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-bom": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
+ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-final-newline": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/test-exclude": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
+ "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "@istanbuljs/schema": "^0.1.2",
+ "glob": "^7.1.4",
+ "minimatch": "^3.0.4"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/tmpl": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
+ "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/ts-jest": {
+ "version": "29.4.11",
+ "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.11.tgz",
+ "integrity": "sha512-IrFl7l9AuB/qrNw5quqvAv/hmKMb8dhWOH4jQOGo0Oq8tCeo1O86/iTFG1FaRimgUkF13l4PcepO8ATFT6Ns4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "bs-logger": "^0.2.6",
+ "fast-json-stable-stringify": "^2.1.0",
+ "handlebars": "^4.7.9",
+ "json5": "^2.2.3",
+ "lodash.memoize": "^4.1.2",
+ "make-error": "^1.3.6",
+ "semver": "^7.8.0",
+ "type-fest": "^4.41.0",
+ "yargs-parser": "^21.1.1"
+ },
+ "bin": {
+ "ts-jest": "cli.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": ">=7.0.0-beta.0 <8",
+ "@jest/transform": "^29.0.0 || ^30.0.0",
+ "@jest/types": "^29.0.0 || ^30.0.0",
+ "babel-jest": "^29.0.0 || ^30.0.0",
+ "jest": "^29.0.0 || ^30.0.0",
+ "jest-util": "^29.0.0 || ^30.0.0",
+ "typescript": ">=4.3 <7"
+ },
+ "peerDependenciesMeta": {
+ "@babel/core": {
+ "optional": true
+ },
+ "@jest/transform": {
+ "optional": true
+ },
+ "@jest/types": {
+ "optional": true
+ },
+ "babel-jest": {
+ "optional": true
+ },
+ "esbuild": {
+ "optional": true
+ },
+ "jest-util": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/ts-jest/node_modules/semver": {
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/ts-jest/node_modules/type-fest": {
+ "version": "4.41.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz",
+ "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==",
+ "dev": true,
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/type-detect": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
+ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "0.21.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+ "dev": true,
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.9.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
+ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/uglify-js": {
+ "version": "3.19.3",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz",
+ "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "optional": true,
+ "bin": {
+ "uglifyjs": "bin/uglifyjs"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
+ "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
+ "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/v8-to-istanbul": {
+ "version": "9.3.0",
+ "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz",
+ "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.12",
+ "@types/istanbul-lib-coverage": "^2.0.1",
+ "convert-source-map": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10.12.0"
+ }
+ },
+ "node_modules/walker": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
+ "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "makeerror": "1.0.12"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/wordwrap": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+ "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/write-file-atomic": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz",
+ "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^3.0.7"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/yargs": {
+ "version": "17.7.3",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz",
+ "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/zod": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz",
+ "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ }
+ }
+}
diff --git a/samples/client/petstore/typescript-express-zod-client/package.json b/samples/client/petstore/typescript-express-zod-client/package.json
new file mode 100644
index 000000000000..7fc1ceb3f70d
--- /dev/null
+++ b/samples/client/petstore/typescript-express-zod-client/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "typescript-express-zod-client-petstore",
+ "version": "1.0.0",
+ "private": true,
+ "description": "Sample project exercising the typescript-express-zod-client generated output",
+ "scripts": {
+ "build": "tsc --noEmit",
+ "test": "tsc --noEmit && jest"
+ },
+ "dependencies": {
+ "zod": "^4.0.0"
+ },
+ "devDependencies": {
+ "@types/jest": "^29.5.14",
+ "@types/node": "^22.10.7",
+ "jest": "^29.7.0",
+ "ts-jest": "^29.2.5",
+ "typescript": "^5.7.3"
+ }
+}
diff --git a/samples/client/petstore/typescript-express-zod-client/test/bookstore.e2e-spec.ts b/samples/client/petstore/typescript-express-zod-client/test/bookstore.e2e-spec.ts
new file mode 100644
index 000000000000..11fb2f4304d6
--- /dev/null
+++ b/samples/client/petstore/typescript-express-zod-client/test/bookstore.e2e-spec.ts
@@ -0,0 +1,72 @@
+import {
+ HttpAuthorsService,
+ HttpCatalogService,
+ type FetchLike,
+} from "../builds/default/http-client";
+
+/**
+ * Build a FetchLike that returns a canned wire payload, so the generated client
+ * runs its real runtime path: response.json() -> Zod schema validation -> DTO
+ * mapping, plus the error path when validation fails.
+ */
+function makeFetch(payload: unknown, status = 200): FetchLike {
+ return function (): Promise<{ json(): Promise; status: number }> {
+ return Promise.resolve({ status, json: async () => payload as T });
+ };
+}
+
+const bookDto = {
+ id: 1,
+ title: "A Wizard of Earthsea",
+ genre: "FICTION",
+ author: { id: 1, name: "Ursula K. Le Guin" },
+ pageCount: 183,
+};
+
+describe("typescript-express-zod-client (bookstore)", () => {
+ it("parses and maps a valid response into a domain object", async () => {
+ const catalog = new HttpCatalogService(makeFetch(bookDto), { root: "http://api.test" });
+ const book = await catalog.getBook({ bookId: 1 });
+ expect(book).toMatchObject({
+ id: 1,
+ title: "A Wizard of Earthsea",
+ genre: "FICTION",
+ author: { name: "Ursula K. Le Guin" },
+ });
+ });
+
+ it("routes a schema-invalid response through the error mapper", async () => {
+ // Missing the required `title` -> Zod validation fails -> { errors }.
+ const catalog = new HttpCatalogService(makeFetch({ id: 1 }), {});
+ const result = (await catalog.getBook({ bookId: 1 })) as unknown as {
+ errors?: unknown[];
+ };
+ expect(Array.isArray(result.errors)).toBe(true);
+ expect(result.errors!.length).toBeGreaterThan(0);
+ });
+
+ it("honors a custom mapZodError override on validation failure", async () => {
+ const catalog = new HttpCatalogService(makeFetch({ id: 1 }), {
+ mapZodError: () => [{ message: "custom-mapped" }],
+ });
+ const result = (await catalog.getBook({ bookId: 1 })) as unknown as {
+ errors?: Array<{ message?: string }>;
+ };
+ expect(result.errors?.[0]?.message).toBe("custom-mapped");
+ });
+
+ it("parses a discriminated-union response", async () => {
+ const catalog = new HttpCatalogService(
+ makeFetch({ type: "BOOK_ADDED", bookId: 5 }),
+ {},
+ );
+ const event = await catalog.getLatestBookEvent({ bookId: 5 });
+ expect(event).toEqual({ type: "BOOK_ADDED", bookId: 5 });
+ });
+
+ it("works across generated service classes (authors)", async () => {
+ const authors = new HttpAuthorsService(makeFetch({ id: 9, name: "Le Guin" }), {});
+ const author = await authors.getAuthor({ authorId: 9 });
+ expect(author).toMatchObject({ id: 9, name: "Le Guin" });
+ });
+});
diff --git a/samples/client/petstore/typescript-express-zod-client/tsconfig.json b/samples/client/petstore/typescript-express-zod-client/tsconfig.json
new file mode 100644
index 000000000000..1918179ce0e1
--- /dev/null
+++ b/samples/client/petstore/typescript-express-zod-client/tsconfig.json
@@ -0,0 +1,20 @@
+{
+ "compilerOptions": {
+ "target": "ES2022",
+ "module": "commonjs",
+ "moduleResolution": "node",
+ "lib": ["ES2022"],
+ "types": ["node", "jest"],
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": false,
+ "esModuleInterop": true,
+ "forceConsistentCasingInFileNames": true,
+ "isolatedModules": true,
+ "skipLibCheck": true,
+ "declaration": false,
+ "outDir": "dist"
+ },
+ "include": ["builds/**/*.ts", "test/**/*.ts"],
+ "exclude": ["node_modules", "dist"]
+}
diff --git a/samples/server/petstore/typescript-express-zod-server/.gitignore b/samples/server/petstore/typescript-express-zod-server/.gitignore
new file mode 100644
index 000000000000..73b44f4e9e31
--- /dev/null
+++ b/samples/server/petstore/typescript-express-zod-server/.gitignore
@@ -0,0 +1,5 @@
+/node_modules
+/dist
+/coverage
+*.log
+.DS_Store
diff --git a/samples/server/petstore/typescript-express-zod-server/builds/default/.openapi-generator-ignore b/samples/server/petstore/typescript-express-zod-server/builds/default/.openapi-generator-ignore
new file mode 100644
index 000000000000..7484ee590a38
--- /dev/null
+++ b/samples/server/petstore/typescript-express-zod-server/builds/default/.openapi-generator-ignore
@@ -0,0 +1,23 @@
+# OpenAPI Generator Ignore
+# Generated by openapi-generator https://github.com/openapitools/openapi-generator
+
+# Use this file to prevent files from being overwritten by the generator.
+# The patterns follow closely to .gitignore or .dockerignore.
+
+# As an example, the C# client generator defines ApiClient.cs.
+# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
+#ApiClient.cs
+
+# You can match any string of characters against a directory, file or extension with a single asterisk (*):
+#foo/*/qux
+# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
+
+# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
+#foo/**/qux
+# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
+
+# You can also negate patterns with an exclamation (!).
+# For example, you can ignore all files in a docs folder with the file extension .md:
+#docs/*.md
+# Then explicitly reverse the ignore rule for a single file:
+#!docs/README.md
diff --git a/samples/server/petstore/typescript-express-zod-server/builds/default/.openapi-generator/FILES b/samples/server/petstore/typescript-express-zod-server/builds/default/.openapi-generator/FILES
new file mode 100644
index 000000000000..0184b27bbaeb
--- /dev/null
+++ b/samples/server/petstore/typescript-express-zod-server/builds/default/.openapi-generator/FILES
@@ -0,0 +1,12 @@
+dtos/index.ts
+dtos/mappers.ts
+dtos/types.ts
+express/auth-middleware.ts
+express/errors.ts
+express/handlers.ts
+express/index.ts
+express/router-factory.ts
+express/types.ts
+index.ts
+schemas.ts
+types.ts
diff --git a/samples/server/petstore/typescript-express-zod-server/builds/default/.openapi-generator/VERSION b/samples/server/petstore/typescript-express-zod-server/builds/default/.openapi-generator/VERSION
new file mode 100644
index 000000000000..186c33c96ed8
--- /dev/null
+++ b/samples/server/petstore/typescript-express-zod-server/builds/default/.openapi-generator/VERSION
@@ -0,0 +1 @@
+7.24.0-SNAPSHOT
diff --git a/samples/server/petstore/typescript-express-zod-server/builds/default/dtos/index.ts b/samples/server/petstore/typescript-express-zod-server/builds/default/dtos/index.ts
new file mode 100644
index 000000000000..cfd0927bbd2b
--- /dev/null
+++ b/samples/server/petstore/typescript-express-zod-server/builds/default/dtos/index.ts
@@ -0,0 +1,2 @@
+export * from "./types";
+export * from "./mappers";
diff --git a/samples/server/petstore/typescript-express-zod-server/builds/default/dtos/mappers.ts b/samples/server/petstore/typescript-express-zod-server/builds/default/dtos/mappers.ts
new file mode 100644
index 000000000000..57cf6f362656
--- /dev/null
+++ b/samples/server/petstore/typescript-express-zod-server/builds/default/dtos/mappers.ts
@@ -0,0 +1,176 @@
+/**
+ * This code was generated by openapi-generator (typescript-express-zod-server).
+ *
+ * Changes to this file may cause incorrect behavior and will be lost if
+ * the code is regenerated.
+ */
+
+import { ZodError } from "zod";
+
+import type * as types from "../types";
+import type * as dtos from "./types";
+
+function compact(obj: T): T {
+ return Object.keys(obj).reduce((acc, key) => {
+ const value = obj[key as keyof T];
+ if (value !== undefined) {
+ acc[key as keyof T] = value;
+ }
+ return acc;
+ }, {} as T);
+}
+
+export function mapFromAuthorDto(
+ dto: dtos.AuthorDto,
+): types.Author {
+ return compact({
+ id: dto.id,
+ name: dto.name,
+ });
+}
+
+export function mapToAuthorDto(
+ obj: types.Author,
+): dtos.AuthorDto {
+ return compact({
+ id: obj.id,
+ name: obj.name,
+ });
+}
+
+export function mapFromBookDto(
+ dto: dtos.BookDto,
+): types.Book {
+ return compact({
+ id: dto.id,
+ title: dto.title,
+ genre: dto.genre,
+ author:
+ dto.author == null
+ ? dto.author
+ : mapFromAuthorDto(dto.author),
+ pageCount: dto.pageCount,
+ });
+}
+
+export function mapToBookDto(
+ obj: types.Book,
+): dtos.BookDto {
+ return compact({
+ id: obj.id,
+ title: obj.title,
+ genre: obj.genre,
+ author:
+ obj.author == null
+ ? obj.author
+ : mapToAuthorDto(obj.author),
+ pageCount: obj.pageCount,
+ });
+}
+
+export function mapFromBookAddedEventDto(
+ dto: dtos.BookAddedEventDto,
+): types.BookAddedEvent {
+ return compact({
+ type: dto.type,
+ bookId: dto.bookId,
+ });
+}
+
+export function mapToBookAddedEventDto(
+ obj: types.BookAddedEvent,
+): dtos.BookAddedEventDto {
+ return compact({
+ type: obj.type,
+ bookId: obj.bookId,
+ });
+}
+
+export function mapFromBookRemovedEventDto(
+ dto: dtos.BookRemovedEventDto,
+): types.BookRemovedEvent {
+ return compact({
+ type: dto.type,
+ bookId: dto.bookId,
+ });
+}
+
+export function mapToBookRemovedEventDto(
+ obj: types.BookRemovedEvent,
+): dtos.BookRemovedEventDto {
+ return compact({
+ type: obj.type,
+ bookId: obj.bookId,
+ });
+}
+
+export function mapFromBookEventDto(dto: dtos.BookEventDto): types.BookEvent {
+ switch (dto.type) {
+ case "BOOK_ADDED":
+ return mapFromBookAddedEventDto(dto);
+ case "BOOK_REMOVED":
+ return mapFromBookRemovedEventDto(dto);
+ default:
+ // Unknown discriminator on inbound (wire -> domain) data is a client
+ // input error: throw a ZodError so the caller maps it to a 4xx response.
+ throw new ZodError([
+ {
+ code: "custom",
+ path: ["type"],
+ message: `Unknown BookEvent discriminator: ${(dto as { type?: unknown }).type}`,
+ },
+ ]);
+ }
+}
+
+export function mapToBookEventDto(obj: types.BookEvent): dtos.BookEventDto {
+ switch (obj.type) {
+ case "BOOK_ADDED":
+ return mapToBookAddedEventDto(obj);
+ case "BOOK_REMOVED":
+ return mapToBookRemovedEventDto(obj);
+ default:
+ throw new Error(
+ `Unknown BookEvent discriminator: ${(obj as { type?: unknown }).type}`,
+ );
+ }
+}
+
+export function mapFromCreateBookRequestDto(
+ dto: dtos.CreateBookRequestDto,
+): types.CreateBookRequest {
+ return compact({
+ title: dto.title,
+ genre: dto.genre,
+ authorId: dto.authorId,
+ });
+}
+
+export function mapToCreateBookRequestDto(
+ obj: types.CreateBookRequest,
+): dtos.CreateBookRequestDto {
+ return compact({
+ title: obj.title,
+ genre: obj.genre,
+ authorId: obj.authorId,
+ });
+}
+
+export function mapFromModelErrorDto(
+ dto: dtos.ModelErrorDto,
+): types.ModelError {
+ return compact({
+ message: dto.message,
+ code: dto.code,
+ });
+}
+
+export function mapToModelErrorDto(
+ obj: types.ModelError,
+): dtos.ModelErrorDto {
+ return compact({
+ message: obj.message,
+ code: obj.code,
+ });
+}
+
diff --git a/samples/server/petstore/typescript-express-zod-server/builds/default/dtos/types.ts b/samples/server/petstore/typescript-express-zod-server/builds/default/dtos/types.ts
new file mode 100644
index 000000000000..287108195e1a
--- /dev/null
+++ b/samples/server/petstore/typescript-express-zod-server/builds/default/dtos/types.ts
@@ -0,0 +1,52 @@
+/**
+ * This code was generated by openapi-generator (typescript-express-zod-server).
+ *
+ * Changes to this file may cause incorrect behavior and will be lost if
+ * the code is regenerated.
+ */
+
+import type * as types from "../types";
+
+/** The over-the-wire representation of the {@link types.Author|Author} type. */
+export type AuthorDto = {
+ id?: number;
+ name: string;
+};
+
+/** The over-the-wire representation of the {@link types.Book|Book} type. */
+export type BookDto = {
+ id?: number;
+ title: string;
+ genre?: types.Genre;
+ author?: AuthorDto | null;
+ pageCount?: number | null;
+};
+
+/** The over-the-wire representation of the {@link types.BookAddedEvent|BookAddedEvent} type. */
+export type BookAddedEventDto = {
+ type: "BOOK_ADDED";
+ bookId: number;
+};
+
+/** The over-the-wire representation of the {@link types.BookRemovedEvent|BookRemovedEvent} type. */
+export type BookRemovedEventDto = {
+ type: "BOOK_REMOVED";
+ bookId: number;
+};
+
+/** The over-the-wire representation of the {@link types.BookEvent|BookEvent} type. */
+export type BookEventDto = BookAddedEventDto | BookRemovedEventDto;
+
+/** The over-the-wire representation of the {@link types.CreateBookRequest|CreateBookRequest} type. */
+export type CreateBookRequestDto = {
+ title: string;
+ genre?: types.Genre;
+ authorId?: number;
+};
+
+/** The over-the-wire representation of the {@link types.ModelError|ModelError} type. */
+export type ModelErrorDto = {
+ message: string;
+ code?: string;
+};
+
diff --git a/samples/server/petstore/typescript-express-zod-server/builds/default/express/auth-middleware.ts b/samples/server/petstore/typescript-express-zod-server/builds/default/express/auth-middleware.ts
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/samples/server/petstore/typescript-express-zod-server/builds/default/express/errors.ts b/samples/server/petstore/typescript-express-zod-server/builds/default/express/errors.ts
new file mode 100644
index 000000000000..b37504ff8a1a
--- /dev/null
+++ b/samples/server/petstore/typescript-express-zod-server/builds/default/express/errors.ts
@@ -0,0 +1,71 @@
+import type { ZodIssue } from "zod";
+
+import type * as types from "../types";
+
+export function methodNotAllowed(): MethodNotAllowedError {
+ return {
+ code: "METHOD_NOT_ALLOWED",
+ status: 405,
+ title: "Method Not Allowed",
+ };
+}
+
+export function isMethodNotAllowed(error: any): error is MethodNotAllowedError {
+ return typeof error === "object" && error !== null && error.code === "METHOD_NOT_ALLOWED";
+}
+
+export type MethodNotAllowedError = {
+ code: "METHOD_NOT_ALLOWED";
+ status: number;
+ title: string;
+};
+
+export function validationErrors(
+ status: 400 | 500,
+ errors: ZodIssue[],
+): ValidationErrorsError {
+ return { code: "VALIDATION_ERRORS", status, errors };
+}
+
+export function isValidationErrors(error: any): error is ValidationErrorsError {
+ return typeof error === "object" && error !== null && error.code === "VALIDATION_ERRORS";
+}
+
+export type ValidationErrorsError = {
+ code: "VALIDATION_ERRORS";
+ status: number;
+ errors: ZodIssue[];
+};
+
+export function handledException(
+ status: number,
+ errors: types.ModelError[],
+): HandledExceptionError {
+ return { code: "HANDLED_EXCEPTION", status, errors };
+}
+
+export function isHandledException(error: any): error is HandledExceptionError {
+ return typeof error === "object" && error !== null && error.code === "HANDLED_EXCEPTION";
+}
+
+export type HandledExceptionError = {
+ code: "HANDLED_EXCEPTION";
+ status: number;
+ errors: types.ModelError[];
+};
+
+export function unhandledException(exception: any): UnhandledExceptionError {
+ return { code: "UNHANDLED_EXCEPTION", status: 500, exception };
+}
+
+export function isUnhandledException(
+ error: any,
+): error is UnhandledExceptionError {
+ return typeof error === "object" && error !== null && error.code === "UNHANDLED_EXCEPTION";
+}
+
+export type UnhandledExceptionError = {
+ code: "UNHANDLED_EXCEPTION";
+ status: number;
+ exception: any;
+};
diff --git a/samples/server/petstore/typescript-express-zod-server/builds/default/express/handlers.ts b/samples/server/petstore/typescript-express-zod-server/builds/default/express/handlers.ts
new file mode 100644
index 000000000000..db3f47cb7e31
--- /dev/null
+++ b/samples/server/petstore/typescript-express-zod-server/builds/default/express/handlers.ts
@@ -0,0 +1,300 @@
+/**
+ * This code was generated by openapi-generator (typescript-express-zod-server).
+ *
+ * Changes to this file may cause incorrect behavior and will be lost if
+ * the code is regenerated.
+ */
+
+import type { Request, Response, NextFunction } from "express";
+import { ZodError } from "zod";
+
+import type * as types from "../types";
+import * as schemas from "../schemas";
+import * as mappers from "../dtos/mappers";
+
+import * as errors from "./errors";
+import type * as expressTypes from "./types";
+
+/** POST /authors */
+export const handleCreateAuthor =
+ (
+ getService: (req: Request, res: Response) => types.AuthorsService,
+ ): expressTypes.CreateAuthorRequestHandler =>
+ async (req, res, next) => {
+ try {
+ // Parse parameters from request
+ const params: types.CreateAuthorParams =
+ schemas.CreateAuthorParamsSchema.parse({
+ author: ((b) => b == null ? b : (mappers.mapFromAuthorDto)(b))(req.body),
+ });
+
+ // Execute service method
+ const service = getService(req, res);
+ const result = await service.createAuthor(params);
+ const status = getHttpStatus(200, result);
+ if (isError(result)) {
+ next(errors.handledException(status, result.errors));
+ } else {
+ return sendResponse(
+ res,
+ next,
+ status,
+ (mappers.mapToAuthorDto)(result),
+ (payload) => schemas.CreateAuthorResponseSchema.parse(payload),
+ );
+ }
+ } catch (err) {
+ if (err instanceof ZodError) {
+ const statusCode = res.headersSent ? 500 : 400;
+ return next(errors.validationErrors(statusCode, err.issues));
+ } else {
+ next(errors.unhandledException(err));
+ }
+ }
+ };
+
+/** POST /books */
+export const handleCreateBook =
+ (
+ getService: (req: Request, res: Response) => types.CatalogService,
+ ): expressTypes.CreateBookRequestHandler =>
+ async (req, res, next) => {
+ try {
+ // Parse parameters from request
+ const params: types.CreateBookParams =
+ schemas.CreateBookParamsSchema.parse({
+ createBookRequest: ((b) => b == null ? b : (mappers.mapFromCreateBookRequestDto)(b))(req.body),
+ });
+
+ // Execute service method
+ const service = getService(req, res);
+ const result = await service.createBook(params);
+ const status = getHttpStatus(200, result);
+ if (isError(result)) {
+ next(errors.handledException(status, result.errors));
+ } else {
+ return sendResponse(
+ res,
+ next,
+ status,
+ (mappers.mapToBookDto)(result),
+ (payload) => schemas.CreateBookResponseSchema.parse(payload),
+ );
+ }
+ } catch (err) {
+ if (err instanceof ZodError) {
+ const statusCode = res.headersSent ? 500 : 400;
+ return next(errors.validationErrors(statusCode, err.issues));
+ } else {
+ next(errors.unhandledException(err));
+ }
+ }
+ };
+
+/** DELETE /books/:bookId */
+export const handleDeleteBook =
+ (
+ getService: (req: Request, res: Response) => types.CatalogService,
+ ): expressTypes.DeleteBookRequestHandler =>
+ async (req, res, next) => {
+ try {
+ // Parse parameters from request
+ const params: types.DeleteBookParams =
+ schemas.DeleteBookParamsSchema.parse({
+ bookId: req.params.bookId,
+ });
+
+ // Execute service method
+ const service = getService(req, res);
+ const result = await service.deleteBook(params);
+ const status = getHttpStatus(200, result);
+ if (isError(result)) {
+ next(errors.handledException(status, result.errors));
+ } else {
+ return sendResponse(
+ res,
+ next,
+ status,
+ result,
+ );
+ }
+ } catch (err) {
+ if (err instanceof ZodError) {
+ const statusCode = res.headersSent ? 500 : 400;
+ return next(errors.validationErrors(statusCode, err.issues));
+ } else {
+ next(errors.unhandledException(err));
+ }
+ }
+ };
+
+/** GET /authors/:authorId */
+export const handleGetAuthor =
+ (
+ getService: (req: Request, res: Response) => types.AuthorsService,
+ ): expressTypes.GetAuthorRequestHandler =>
+ async (req, res, next) => {
+ try {
+ // Parse parameters from request
+ const params: types.GetAuthorParams =
+ schemas.GetAuthorParamsSchema.parse({
+ authorId: req.params.authorId,
+ });
+
+ // Execute service method
+ const service = getService(req, res);
+ const result = await service.getAuthor(params);
+ const status = getHttpStatus(200, result);
+ if (isError(result)) {
+ next(errors.handledException(status, result.errors));
+ } else {
+ return sendResponse(
+ res,
+ next,
+ status,
+ (mappers.mapToAuthorDto)(result),
+ (payload) => schemas.GetAuthorResponseSchema.parse(payload),
+ );
+ }
+ } catch (err) {
+ if (err instanceof ZodError) {
+ const statusCode = res.headersSent ? 500 : 400;
+ return next(errors.validationErrors(statusCode, err.issues));
+ } else {
+ next(errors.unhandledException(err));
+ }
+ }
+ };
+
+/** GET /books/:bookId */
+export const handleGetBook =
+ (
+ getService: (req: Request, res: Response) => types.CatalogService,
+ ): expressTypes.GetBookRequestHandler =>
+ async (req, res, next) => {
+ try {
+ // Parse parameters from request
+ const params: types.GetBookParams =
+ schemas.GetBookParamsSchema.parse({
+ bookId: req.params.bookId,
+ expand: req.query.expand,
+ });
+
+ // Execute service method
+ const service = getService(req, res);
+ const result = await service.getBook(params);
+ const status = getHttpStatus(200, result);
+ if (isError(result)) {
+ next(errors.handledException(status, result.errors));
+ } else {
+ return sendResponse(
+ res,
+ next,
+ status,
+ (mappers.mapToBookDto)(result),
+ (payload) => schemas.GetBookResponseSchema.parse(payload),
+ );
+ }
+ } catch (err) {
+ if (err instanceof ZodError) {
+ const statusCode = res.headersSent ? 500 : 400;
+ return next(errors.validationErrors(statusCode, err.issues));
+ } else {
+ next(errors.unhandledException(err));
+ }
+ }
+ };
+
+/** GET /books/:bookId/latest-event */
+export const handleGetLatestBookEvent =
+ (
+ getService: (req: Request, res: Response) => types.CatalogService,
+ ): expressTypes.GetLatestBookEventRequestHandler =>
+ async (req, res, next) => {
+ try {
+ // Parse parameters from request
+ const params: types.GetLatestBookEventParams =
+ schemas.GetLatestBookEventParamsSchema.parse({
+ bookId: req.params.bookId,
+ });
+
+ // Execute service method
+ const service = getService(req, res);
+ const result = await service.getLatestBookEvent(params);
+ const status = getHttpStatus(200, result);
+ if (isError(result)) {
+ next(errors.handledException(status, result.errors));
+ } else {
+ return sendResponse(
+ res,
+ next,
+ status,
+ (mappers.mapToBookEventDto)(result),
+ (payload) => schemas.GetLatestBookEventResponseSchema.parse(payload),
+ );
+ }
+ } catch (err) {
+ if (err instanceof ZodError) {
+ const statusCode = res.headersSent ? 500 : 400;
+ return next(errors.validationErrors(statusCode, err.issues));
+ } else {
+ next(errors.unhandledException(err));
+ }
+ }
+ };
+
+/**
+ * Send a successful response, optionally validating the wire payload first.
+ *
+ * Validation runs BEFORE the payload is committed, so a schema mismatch never
+ * ships invalid data to the client. A mismatch is a server-side contract
+ * violation: it is surfaced as a structured validation error with a 5xx status,
+ * preserving the Zod issue details.
+ */
+function sendResponse(
+ res: Response,
+ next: NextFunction,
+ status: number,
+ payload: unknown,
+ validate?: (payload: unknown) => void,
+): void {
+ if (validate) {
+ try {
+ validate(payload);
+ } catch (err) {
+ if (err instanceof ZodError) {
+ return next(errors.validationErrors(500, err.issues));
+ }
+ return next(errors.unhandledException(err));
+ }
+ }
+ res.status(status).json(payload);
+}
+
+type ErrorResult = {
+ errors: types.ModelError[];
+ data?: unknown;
+};
+
+function isError(result: unknown): result is ErrorResult {
+ if (typeof result !== "object" || result === null || !("errors" in result)) {
+ return false;
+ }
+ const candidate = result as Record;
+ if (!Array.isArray(candidate.errors) || candidate.errors.length === 0) {
+ return false;
+ }
+ return !("data" in result) ||
+ candidate.data === undefined ||
+ (Array.isArray(candidate.data) && candidate.data.length === 0);
+}
+
+function getHttpStatus(success: number, result: unknown): number {
+ if (!isError(result)) return success;
+ return result.errors.reduce((max, item) => {
+ const status = (item as Record)["status"];
+ if (status === undefined) return success;
+ const value = typeof status === "string" ? Number(status) : typeof status === "number" ? status : NaN;
+ return !Number.isNaN(value) && value > max ? value : max;
+ }, success);
+}
diff --git a/samples/server/petstore/typescript-express-zod-server/builds/default/express/index.ts b/samples/server/petstore/typescript-express-zod-server/builds/default/express/index.ts
new file mode 100644
index 000000000000..cf9925295b58
--- /dev/null
+++ b/samples/server/petstore/typescript-express-zod-server/builds/default/express/index.ts
@@ -0,0 +1,4 @@
+export * from "./errors";
+export * from "./handlers";
+export * from "./router-factory";
+export * from "./types";
diff --git a/samples/server/petstore/typescript-express-zod-server/builds/default/express/router-factory.ts b/samples/server/petstore/typescript-express-zod-server/builds/default/express/router-factory.ts
new file mode 100644
index 000000000000..31b794bc4259
--- /dev/null
+++ b/samples/server/petstore/typescript-express-zod-server/builds/default/express/router-factory.ts
@@ -0,0 +1,199 @@
+/**
+ * This code was generated by openapi-generator (typescript-express-zod-server).
+ *
+ * Changes to this file may cause incorrect behavior and will be lost if
+ * the code is regenerated.
+ */
+
+import { Router, type RequestHandler } from "express";
+
+import * as handlers from "./handlers";
+import * as errors from "./errors";
+import type * as expressTypes from "./types";
+
+export function getRouter({
+ schema,
+ getAuthorsService,
+ getCatalogService,
+ middleware,
+ handlerOverrides,
+ swaggerUiVersion = "3.51.1",
+}: expressTypes.RouterFactoryInput): Router {
+ const router = Router();
+ const methodNotAllowed: (allow: string) => RequestHandler =
+ (allow) => (_req, res, next) => {
+ res.set("Allow", allow);
+ return next(errors.methodNotAllowed());
+ };
+
+ function handlersFor<
+ TName extends Exclude<
+ keyof expressTypes.Middleware,
+ "_onlySwaggerUI" | "_exceptSwaggerUI"
+ >,
+ >(methodName: TName, defaultHandler: RequestHandler): RequestHandler[] {
+ return [
+ ...getMiddleware(middleware, methodName),
+ ...getHandlers(handlerOverrides?.[methodName], defaultHandler),
+ ];
+ }
+
+ router
+ .route("/books/:bookId/latest-event")
+ .get(
+ handlersFor(
+ "getLatestBookEvent",
+ handlers.handleGetLatestBookEvent(getCatalogService),
+ ),
+ )
+ .options((_, res) => {
+ res.set("Allow", "GET, HEAD, OPTIONS").sendStatus(204);
+ })
+ .all(methodNotAllowed("GET, HEAD, OPTIONS"));
+
+ router
+ .route("/authors/:authorId")
+ .get(
+ handlersFor(
+ "getAuthor",
+ handlers.handleGetAuthor(getAuthorsService),
+ ),
+ )
+ .options((_, res) => {
+ res.set("Allow", "GET, HEAD, OPTIONS").sendStatus(204);
+ })
+ .all(methodNotAllowed("GET, HEAD, OPTIONS"));
+
+ router
+ .route("/books/:bookId")
+ .delete(
+ handlersFor(
+ "deleteBook",
+ handlers.handleDeleteBook(getCatalogService),
+ ),
+ )
+ .get(
+ handlersFor(
+ "getBook",
+ handlers.handleGetBook(getCatalogService),
+ ),
+ )
+ .options((_, res) => {
+ res.set("Allow", "DELETE, GET, HEAD, OPTIONS").sendStatus(204);
+ })
+ .all(methodNotAllowed("DELETE, GET, HEAD, OPTIONS"));
+
+ router
+ .route("/authors")
+ .post(
+ handlersFor(
+ "createAuthor",
+ handlers.handleCreateAuthor(getAuthorsService),
+ ),
+ )
+ .options((_, res) => {
+ res.set("Allow", "OPTIONS, POST").sendStatus(204);
+ })
+ .all(methodNotAllowed("OPTIONS, POST"));
+
+ router
+ .route("/books")
+ .post(
+ handlersFor(
+ "createBook",
+ handlers.handleCreateBook(getCatalogService),
+ ),
+ )
+ .options((_, res) => {
+ res.set("Allow", "OPTIONS, POST").sendStatus(204);
+ })
+ .all(methodNotAllowed("OPTIONS, POST"));
+
+ router
+ .route("/")
+ .get(...getMiddleware(middleware, "_onlySwaggerUI"), (_, res) => {
+ const swaggerUiUrl = `https://unpkg.com/swagger-ui-dist@${swaggerUiVersion}/`;
+ res.send(`
+
+
+
+ API Documentation
+
+
+
+
+
+ CONTENT NOT LOADED
+
+
+
+ `);
+ })
+ .options((_, res) => {
+ res.set("Allow", "GET, HEAD, OPTIONS").sendStatus(204);
+ })
+ .all(methodNotAllowed("GET, HEAD, OPTIONS"));
+ return router;
+}
+/**
+ * Gets a list of middleware functions for a given name from the supplied middleware object(s).
+ * If no middleware objects are supplied, an empty array is returned.
+ * Handlers are returned in the order they are defined in the middleware object(s).
+ * @param middleware - The middleware object(s) to extract middleware from
+ * @param name - The name of the service method to get middleware for
+ * @returns An array of {@link RequestHandler|express.RequestHandler} functions
+ */
+function getMiddleware(
+ middleware: expressTypes.Middleware | expressTypes.Middleware[] | undefined,
+ name: keyof expressTypes.Middleware,
+): RequestHandler[] {
+ if (!middleware) return [];
+ const middlewareArray = Array.isArray(middleware) ? middleware : [middleware];
+
+ return middlewareArray.flatMap((m) => {
+ const exceptSwaggerUI =
+ m._exceptSwaggerUI && name !== "_onlySwaggerUI"
+ ? m._exceptSwaggerUI
+ : [];
+
+ const handler = m[name];
+ const base = handler ? handler : [];
+ const baseArray = Array.isArray(base) ? base : [base];
+ const exceptArray = Array.isArray(exceptSwaggerUI)
+ ? exceptSwaggerUI
+ : [exceptSwaggerUI];
+ return [...baseArray, ...exceptArray];
+ });
+}
+
+/**
+ * Gets a list of handlers for a given service method.
+ * If overrides are provided, they are used in place of the default handler.
+ * If no overrides are provided, the default handler is used.
+ * @param overrides - The handler(s) to use in place of the default handler
+ * @param defaultHandler - The default handler to use if no overrides are provided
+ * @returns An array of {@link RequestHandler|express.RequestHandler} functions
+ */
+function getHandlers(
+ overrides: RequestHandler | RequestHandler[] | undefined,
+ defaultHandler: RequestHandler,
+): RequestHandler[] {
+ if (!overrides) return [defaultHandler];
+ return Array.isArray(overrides) ? overrides : [overrides];
+}
diff --git a/samples/server/petstore/typescript-express-zod-server/builds/default/express/types.ts b/samples/server/petstore/typescript-express-zod-server/builds/default/express/types.ts
new file mode 100644
index 000000000000..7e2429771512
--- /dev/null
+++ b/samples/server/petstore/typescript-express-zod-server/builds/default/express/types.ts
@@ -0,0 +1,117 @@
+/**
+ * This code was generated by openapi-generator (typescript-express-zod-server).
+ *
+ * Changes to this file may cause incorrect behavior and will be lost if
+ * the code is regenerated.
+ */
+
+import type { Request, Response, RequestHandler } from "express";
+
+import type * as types from "../types";
+import type * as dtos from "../dtos/types";
+
+export type RouterFactoryInput = {
+ /** OpenAPI schema as a JSON object */
+ schema: any;
+
+ getAuthorsService: (
+ req: Request,
+ res: Response,
+ ) => types.AuthorsService;
+ getCatalogService: (
+ req: Request,
+ res: Response,
+ ) => types.CatalogService;
+
+ middleware?: Middleware | Middleware[];
+ handlerOverrides?: HandlerOverrides;
+ swaggerUiVersion?: string;
+};
+
+export type Middleware = {
+ /** Middleware to be applied to the Swagger UI handler. */
+ _onlySwaggerUI?: RequestHandler | RequestHandler[];
+ /** Middleware to be applied to all handlers _except_ Swagger UI after any other method-specific middleware. */
+ _exceptSwaggerUI?: RequestHandler | RequestHandler[];
+ createAuthor?:
+ | CreateAuthorRequestHandler
+ | CreateAuthorRequestHandler[];
+ createBook?:
+ | CreateBookRequestHandler
+ | CreateBookRequestHandler[];
+ deleteBook?:
+ | DeleteBookRequestHandler
+ | DeleteBookRequestHandler[];
+ getAuthor?:
+ | GetAuthorRequestHandler
+ | GetAuthorRequestHandler[];
+ getBook?:
+ | GetBookRequestHandler
+ | GetBookRequestHandler[];
+ getLatestBookEvent?:
+ | GetLatestBookEventRequestHandler
+ | GetLatestBookEventRequestHandler[];
+};
+
+/**
+ * Per-operation handler replacements. Unlike {@link Middleware}, the
+ * Swagger-UI scopes (`_onlySwaggerUI` / `_exceptSwaggerUI`) are not valid here
+ * because they are ignored when resolving handler overrides.
+ */
+export type HandlerOverrides = Omit<
+ Middleware,
+ "_onlySwaggerUI" | "_exceptSwaggerUI"
+>;
+
+export type CreateAuthorRequestHandler = RequestHandler<
+ {},
+ dtos.AuthorDto,
+ dtos.AuthorDto,
+ {}
+>;
+
+export type CreateBookRequestHandler = RequestHandler<
+ {},
+ dtos.BookDto,
+ dtos.CreateBookRequestDto,
+ {}
+>;
+
+export type DeleteBookRequestHandler = RequestHandler<
+ {
+ bookId: string
+ },
+ any,
+ unknown,
+ {}
+>;
+
+export type GetAuthorRequestHandler = RequestHandler<
+ {
+ authorId: string
+ },
+ dtos.AuthorDto,
+ unknown,
+ {}
+>;
+
+export type GetBookRequestHandler = RequestHandler<
+ {
+ bookId: string
+ },
+ dtos.BookDto,
+ unknown,
+ {
+ expand?: string
+ }
+>;
+
+export type GetLatestBookEventRequestHandler = RequestHandler<
+ {
+ bookId: string
+ },
+ dtos.BookEventDto,
+ unknown,
+ {}
+>;
+
diff --git a/samples/server/petstore/typescript-express-zod-server/builds/default/index.ts b/samples/server/petstore/typescript-express-zod-server/builds/default/index.ts
new file mode 100644
index 000000000000..019e4c35bb62
--- /dev/null
+++ b/samples/server/petstore/typescript-express-zod-server/builds/default/index.ts
@@ -0,0 +1,4 @@
+export * from "./types";
+export * from "./schemas";
+export * from "./dtos";
+export * from "./express";
diff --git a/samples/server/petstore/typescript-express-zod-server/builds/default/schemas.ts b/samples/server/petstore/typescript-express-zod-server/builds/default/schemas.ts
new file mode 100644
index 000000000000..f064b2b98300
--- /dev/null
+++ b/samples/server/petstore/typescript-express-zod-server/builds/default/schemas.ts
@@ -0,0 +1,85 @@
+/**
+ * This code was generated by openapi-generator (typescript-express-zod-server).
+ *
+ * Changes to this file may cause incorrect behavior and will be lost if
+ * the code is regenerated.
+ */
+
+import { z } from "zod";
+
+export const AuthorSchema = z.object({
+ id: z.coerce.number().int().optional(),
+ name: z.string(),
+});
+
+export const GenreSchema = z.enum(['FICTION', 'NONFICTION', 'POETRY']);
+
+export const BookSchema = z.object({
+ id: z.coerce.number().int().optional(),
+ title: z.string(),
+ genre: GenreSchema.optional(),
+ author: AuthorSchema.nullable().optional(),
+ pageCount: z.coerce.number().int().nullable().optional(),
+});
+
+export const BookAddedEventSchema = z.object({
+ type: z.literal("BOOK_ADDED"),
+ bookId: z.coerce.number().int(),
+});
+
+export const BookRemovedEventSchema = z.object({
+ type: z.literal("BOOK_REMOVED"),
+ bookId: z.coerce.number().int(),
+});
+
+export const BookEventSchema = z.discriminatedUnion("type", [
+ BookAddedEventSchema,
+ BookRemovedEventSchema,
+]);
+
+export const CreateBookRequestSchema = z.object({
+ title: z.string(),
+ genre: GenreSchema.optional(),
+ authorId: z.coerce.number().int().optional(),
+});
+
+export const ModelErrorSchema = z.object({
+ message: z.string(),
+ code: z.string().optional(),
+});
+
+export const CreateAuthorParamsSchema = z.object({
+ author: AuthorSchema,
+});
+
+export const CreateBookParamsSchema = z.object({
+ createBookRequest: CreateBookRequestSchema,
+});
+
+export const DeleteBookParamsSchema = z.object({
+ bookId: z.coerce.number().int(),
+});
+
+export const GetAuthorParamsSchema = z.object({
+ authorId: z.coerce.number().int(),
+});
+
+export const GetBookParamsSchema = z.object({
+ bookId: z.coerce.number().int(),
+ expand: z.boolean().optional(),
+});
+
+export const GetLatestBookEventParamsSchema = z.object({
+ bookId: z.coerce.number().int(),
+});
+
+export const CreateAuthorResponseSchema = AuthorSchema;
+
+export const CreateBookResponseSchema = BookSchema;
+
+export const GetAuthorResponseSchema = AuthorSchema;
+
+export const GetBookResponseSchema = BookSchema;
+
+export const GetLatestBookEventResponseSchema = BookEventSchema;
+
diff --git a/samples/server/petstore/typescript-express-zod-server/builds/default/types.ts b/samples/server/petstore/typescript-express-zod-server/builds/default/types.ts
new file mode 100644
index 000000000000..1d4563b21708
--- /dev/null
+++ b/samples/server/petstore/typescript-express-zod-server/builds/default/types.ts
@@ -0,0 +1,111 @@
+/**
+ * This code was generated by openapi-generator (typescript-express-zod-server).
+ *
+ * Changes to this file may cause incorrect behavior and will be lost if
+ * the code is regenerated.
+ */
+
+/** Interface for the AuthorsService */
+export interface AuthorsService {
+ /** Create an author */
+ createAuthor(params: CreateAuthorParams): Promise;
+
+ /** Get an author by id */
+ getAuthor(params: GetAuthorParams): Promise;
+
+}
+
+/** Interface for the CatalogService */
+export interface CatalogService {
+ /** Create a book */
+ createBook(params: CreateBookParams): Promise;
+
+ /** Delete a book */
+ deleteBook(params: DeleteBookParams): Promise;
+
+ /** Get a book by id */
+ getBook(params: GetBookParams): Promise;
+
+ /** Get the latest event for a book (discriminated union response) */
+ getLatestBookEvent(params: GetLatestBookEventParams): Promise;
+
+}
+
+export type CreateAuthorParams = {
+ /** author */
+ author: Author;
+};
+
+export type CreateBookParams = {
+ /** createBookRequest */
+ createBookRequest: CreateBookRequest;
+};
+
+export type DeleteBookParams = {
+ /** bookId */
+ bookId: number;
+};
+
+export type GetAuthorParams = {
+ /** authorId */
+ authorId: number;
+};
+
+export type GetBookParams = {
+ /** bookId */
+ bookId: number;
+ /** expand */
+ expand?: boolean;
+};
+
+export type GetLatestBookEventParams = {
+ /** bookId */
+ bookId: number;
+};
+
+export type Author = {
+ id?: number;
+ name: string;
+};
+
+export type Genre = 'FICTION' | 'NONFICTION' | 'POETRY';
+
+export type Book = {
+ id?: number;
+ title: string;
+ genre?: Genre;
+ author?: Author | null;
+ pageCount?: number | null;
+};
+
+export type BookAddedEvent = {
+ type: "BOOK_ADDED";
+ bookId: number;
+};
+
+export type BookRemovedEvent = {
+ type: "BOOK_REMOVED";
+ bookId: number;
+};
+
+export type BookEvent = BookAddedEvent | BookRemovedEvent;
+
+export function isBookAddedEvent(obj: BookEvent): obj is BookAddedEvent {
+ return obj.type === "BOOK_ADDED";
+}
+
+export function isBookRemovedEvent(obj: BookEvent): obj is BookRemovedEvent {
+ return obj.type === "BOOK_REMOVED";
+}
+
+export type CreateBookRequest = {
+ title: string;
+ genre?: Genre;
+ authorId?: number;
+};
+
+export type ModelError = {
+ message: string;
+ code?: string;
+};
+
diff --git a/samples/server/petstore/typescript-express-zod-server/jest.config.js b/samples/server/petstore/typescript-express-zod-server/jest.config.js
new file mode 100644
index 000000000000..ed8fc6ffeabf
--- /dev/null
+++ b/samples/server/petstore/typescript-express-zod-server/jest.config.js
@@ -0,0 +1,6 @@
+/** @type {import('ts-jest').JestConfigWithTsJest} */
+module.exports = {
+ preset: "ts-jest",
+ testEnvironment: "node",
+ testMatch: ["**/test/**/*.e2e-spec.ts"],
+};
diff --git a/samples/server/petstore/typescript-express-zod-server/package-lock.json b/samples/server/petstore/typescript-express-zod-server/package-lock.json
new file mode 100644
index 000000000000..12ba8d55d303
--- /dev/null
+++ b/samples/server/petstore/typescript-express-zod-server/package-lock.json
@@ -0,0 +1,5010 @@
+{
+ "name": "typescript-express-zod-server-petstore",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "typescript-express-zod-server-petstore",
+ "version": "1.0.0",
+ "dependencies": {
+ "express": "^5.0.0",
+ "zod": "^4.0.0"
+ },
+ "devDependencies": {
+ "@types/express": "^5.0.0",
+ "@types/jest": "^29.5.14",
+ "@types/node": "^22.10.7",
+ "@types/supertest": "^6.0.2",
+ "jest": "^29.7.0",
+ "supertest": "^7.0.0",
+ "ts-jest": "^29.2.5",
+ "typescript": "^5.7.3"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz",
+ "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.29.7",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz",
+ "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz",
+ "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.29.7",
+ "@babel/generator": "^7.29.7",
+ "@babel/helper-compilation-targets": "^7.29.7",
+ "@babel/helper-module-transforms": "^7.29.7",
+ "@babel/helpers": "^7.29.7",
+ "@babel/parser": "^7.29.7",
+ "@babel/template": "^7.29.7",
+ "@babel/traverse": "^7.29.7",
+ "@babel/types": "^7.29.7",
+ "@jridgewell/remapping": "^2.3.5",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz",
+ "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.29.7",
+ "@babel/types": "^7.29.7",
+ "@jridgewell/gen-mapping": "^0.3.12",
+ "@jridgewell/trace-mapping": "^0.3.28",
+ "jsesc": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz",
+ "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/compat-data": "^7.29.7",
+ "@babel/helper-validator-option": "^7.29.7",
+ "browserslist": "^4.24.0",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-globals": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz",
+ "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz",
+ "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/traverse": "^7.29.7",
+ "@babel/types": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz",
+ "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.29.7",
+ "@babel/helper-validator-identifier": "^7.29.7",
+ "@babel/traverse": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz",
+ "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz",
+ "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz",
+ "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz",
+ "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz",
+ "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.29.7",
+ "@babel/types": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz",
+ "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.29.7"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-async-generators": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
+ "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-bigint": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz",
+ "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-class-properties": {
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
+ "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.12.13"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-class-static-block": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz",
+ "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-import-attributes": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.29.7.tgz",
+ "integrity": "sha512-zGYcYfq/WmZ4V+kBIXQon9dSSc8ircGZqw9ZaNhhGj9nZkeBu1jHLBDQqYYi5WA9uawvA2sIMbry2nCFhf5Djg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-import-meta": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
+ "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-json-strings": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
+ "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-jsx": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.29.7.tgz",
+ "integrity": "sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
+ "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
+ "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-numeric-separator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
+ "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-object-rest-spread": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
+ "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-catch-binding": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
+ "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-chaining": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
+ "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-private-property-in-object": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz",
+ "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-top-level-await": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
+ "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-typescript": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.29.7.tgz",
+ "integrity": "sha512-ngr+82Sh0xMz25TPCZi+nC2iTzjfCdWS2ONXTp/PtSCHCgaCNBpdMqgvJ2ccdLlClVZ7sisIgB914j/JFe+RZA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz",
+ "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.29.7",
+ "@babel/parser": "^7.29.7",
+ "@babel/types": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz",
+ "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.29.7",
+ "@babel/generator": "^7.29.7",
+ "@babel/helper-globals": "^7.29.7",
+ "@babel/parser": "^7.29.7",
+ "@babel/template": "^7.29.7",
+ "@babel/types": "^7.29.7",
+ "debug": "^4.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz",
+ "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.29.7",
+ "@babel/helper-validator-identifier": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@bcoe/v8-coverage": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
+ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@istanbuljs/load-nyc-config": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
+ "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "camelcase": "^5.3.1",
+ "find-up": "^4.1.0",
+ "get-package-type": "^0.1.0",
+ "js-yaml": "^3.13.1",
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/schema": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.6.tgz",
+ "integrity": "sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@jest/console": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz",
+ "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/core": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz",
+ "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/console": "^29.7.0",
+ "@jest/reporters": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.9",
+ "jest-changed-files": "^29.7.0",
+ "jest-config": "^29.7.0",
+ "jest-haste-map": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.7.0",
+ "jest-resolve-dependencies": "^29.7.0",
+ "jest-runner": "^29.7.0",
+ "jest-runtime": "^29.7.0",
+ "jest-snapshot": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "jest-watcher": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@jest/environment": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz",
+ "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-mock": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/expect": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz",
+ "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "expect": "^29.7.0",
+ "jest-snapshot": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/expect-utils": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz",
+ "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "jest-get-type": "^29.6.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/fake-timers": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz",
+ "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@sinonjs/fake-timers": "^10.0.2",
+ "@types/node": "*",
+ "jest-message-util": "^29.7.0",
+ "jest-mock": "^29.7.0",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/globals": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz",
+ "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/expect": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "jest-mock": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/reporters": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz",
+ "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@bcoe/v8-coverage": "^0.2.3",
+ "@jest/console": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "collect-v8-coverage": "^1.0.0",
+ "exit": "^0.1.2",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "istanbul-lib-coverage": "^3.0.0",
+ "istanbul-lib-instrument": "^6.0.0",
+ "istanbul-lib-report": "^3.0.0",
+ "istanbul-lib-source-maps": "^4.0.0",
+ "istanbul-reports": "^3.1.3",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "slash": "^3.0.0",
+ "string-length": "^4.0.1",
+ "strip-ansi": "^6.0.0",
+ "v8-to-istanbul": "^9.0.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@sinclair/typebox": "^0.27.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/source-map": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz",
+ "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "callsites": "^3.0.0",
+ "graceful-fs": "^4.2.9"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/test-result": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz",
+ "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/console": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "collect-v8-coverage": "^1.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/test-sequencer": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz",
+ "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/test-result": "^29.7.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/transform": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz",
+ "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@jest/types": "^29.6.3",
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "babel-plugin-istanbul": "^6.1.1",
+ "chalk": "^4.0.0",
+ "convert-source-map": "^2.0.0",
+ "fast-json-stable-stringify": "^2.1.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "pirates": "^4.0.4",
+ "slash": "^3.0.0",
+ "write-file-atomic": "^4.0.2"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.13",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
+ "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/remapping": {
+ "version": "2.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
+ "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.31",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
+ "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@noble/hashes": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
+ "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^14.21.3 || >=16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@paralleldrive/cuid2": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.3.1.tgz",
+ "integrity": "sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@noble/hashes": "^1.1.5"
+ }
+ },
+ "node_modules/@sinclair/typebox": {
+ "version": "0.27.10",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz",
+ "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@sinonjs/commons": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz",
+ "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "type-detect": "4.0.8"
+ }
+ },
+ "node_modules/@sinonjs/fake-timers": {
+ "version": "10.3.0",
+ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz",
+ "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@sinonjs/commons": "^3.0.0"
+ }
+ },
+ "node_modules/@types/babel__core": {
+ "version": "7.20.5",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
+ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
+ "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
+ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
+ "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.28.2"
+ }
+ },
+ "node_modules/@types/body-parser": {
+ "version": "1.19.6",
+ "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz",
+ "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/connect": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/connect": {
+ "version": "3.4.38",
+ "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
+ "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/cookiejar": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.5.tgz",
+ "integrity": "sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/express": {
+ "version": "5.0.6",
+ "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.6.tgz",
+ "integrity": "sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/body-parser": "*",
+ "@types/express-serve-static-core": "^5.0.0",
+ "@types/serve-static": "^2"
+ }
+ },
+ "node_modules/@types/express-serve-static-core": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.1.1.tgz",
+ "integrity": "sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "@types/qs": "*",
+ "@types/range-parser": "*",
+ "@types/send": "*"
+ }
+ },
+ "node_modules/@types/graceful-fs": {
+ "version": "4.1.9",
+ "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz",
+ "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/http-errors": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz",
+ "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/istanbul-lib-coverage": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
+ "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/istanbul-lib-report": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz",
+ "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/istanbul-lib-coverage": "*"
+ }
+ },
+ "node_modules/@types/istanbul-reports": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz",
+ "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/istanbul-lib-report": "*"
+ }
+ },
+ "node_modules/@types/jest": {
+ "version": "29.5.14",
+ "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz",
+ "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "expect": "^29.0.0",
+ "pretty-format": "^29.0.0"
+ }
+ },
+ "node_modules/@types/methods": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/@types/methods/-/methods-1.1.4.tgz",
+ "integrity": "sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/node": {
+ "version": "22.20.0",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.0.tgz",
+ "integrity": "sha512-QWlFW2wf3nTjC13/DqRnBpR4ZO36VJH/JVBkA/vcnmbTBNQIlnObqyqZE1tUR7+Ni23Lda8R1BxMfbXRpCUx5g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.21.0"
+ }
+ },
+ "node_modules/@types/qs": {
+ "version": "6.15.1",
+ "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.1.tgz",
+ "integrity": "sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/range-parser": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz",
+ "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/send": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz",
+ "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/serve-static": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-2.2.0.tgz",
+ "integrity": "sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/http-errors": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/stack-utils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
+ "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/superagent": {
+ "version": "8.1.10",
+ "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.10.tgz",
+ "integrity": "sha512-nbt4IWXABhW0jGmmpRzCFNlbmwCTzZ2gTUsNIr+X+ItdqPms+PAJZbWsNzpS2USqXjcoNLQcO6nXo60zcPQiIg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/cookiejar": "^2.1.5",
+ "@types/methods": "^1.1.4",
+ "@types/node": "*",
+ "form-data": "^4.0.0"
+ }
+ },
+ "node_modules/@types/supertest": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-6.0.3.tgz",
+ "integrity": "sha512-8WzXq62EXFhJ7QsH3Ocb/iKQ/Ty9ZVWnVzoTKc9tyyFRRF3a74Tk2+TLFgaFFw364Ere+npzHKEJ6ga2LzIL7w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/methods": "^1.1.4",
+ "@types/superagent": "^8.1.0"
+ }
+ },
+ "node_modules/@types/yargs": {
+ "version": "17.0.35",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz",
+ "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "node_modules/@types/yargs-parser": {
+ "version": "21.0.3",
+ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz",
+ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/accepts": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
+ "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-types": "^3.0.0",
+ "negotiator": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/ansi-escapes": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "type-fest": "^0.21.3"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "node_modules/asap": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
+ "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/babel-jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz",
+ "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/transform": "^29.7.0",
+ "@types/babel__core": "^7.1.14",
+ "babel-plugin-istanbul": "^6.1.1",
+ "babel-preset-jest": "^29.6.3",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.8.0"
+ }
+ },
+ "node_modules/babel-plugin-istanbul": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz",
+ "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@istanbuljs/load-nyc-config": "^1.0.0",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-instrument": "^5.0.4",
+ "test-exclude": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz",
+ "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/core": "^7.12.3",
+ "@babel/parser": "^7.14.7",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-coverage": "^3.2.0",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/babel-plugin-jest-hoist": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz",
+ "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.3.3",
+ "@babel/types": "^7.3.3",
+ "@types/babel__core": "^7.1.14",
+ "@types/babel__traverse": "^7.0.6"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/babel-preset-current-node-syntax": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz",
+ "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/plugin-syntax-async-generators": "^7.8.4",
+ "@babel/plugin-syntax-bigint": "^7.8.3",
+ "@babel/plugin-syntax-class-properties": "^7.12.13",
+ "@babel/plugin-syntax-class-static-block": "^7.14.5",
+ "@babel/plugin-syntax-import-attributes": "^7.24.7",
+ "@babel/plugin-syntax-import-meta": "^7.10.4",
+ "@babel/plugin-syntax-json-strings": "^7.8.3",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+ "@babel/plugin-syntax-private-property-in-object": "^7.14.5",
+ "@babel/plugin-syntax-top-level-await": "^7.14.5"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0 || ^8.0.0-0"
+ }
+ },
+ "node_modules/babel-preset-jest": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz",
+ "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "babel-plugin-jest-hoist": "^29.6.3",
+ "babel-preset-current-node-syntax": "^1.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/baseline-browser-mapping": {
+ "version": "2.10.42",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.42.tgz",
+ "integrity": "sha512-c/jurFrDLyui7o1J86yLkRu4LMsTYcBohveus7/I2Hzdn9KIP2bdJPTue/lR1KH46enoPbD77GKeSYNdyPoD3Q==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.cjs"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/body-parser": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.3.0.tgz",
+ "integrity": "sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==",
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "^3.1.2",
+ "content-type": "^2.0.0",
+ "debug": "^4.4.3",
+ "http-errors": "^2.0.1",
+ "iconv-lite": "^0.7.2",
+ "on-finished": "^2.4.1",
+ "qs": "^6.15.2",
+ "raw-body": "^3.0.2",
+ "type-is": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/body-parser/node_modules/content-type": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz",
+ "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz",
+ "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.28.4",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.4.tgz",
+ "integrity": "sha512-MTc8i/x9jBQd1iMw2CFGS+rwMa07eYjLR0CCTLDACl9xhxy+nIs3KeML/biicXtk9JrZ6dnnTatmc7ErPXIxqw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "baseline-browser-mapping": "^2.10.38",
+ "caniuse-lite": "^1.0.30001799",
+ "electron-to-chromium": "^1.5.376",
+ "node-releases": "^2.0.48",
+ "update-browserslist-db": "^1.2.3"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/bs-logger": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz",
+ "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-json-stable-stringify": "2.x"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/bser": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz",
+ "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "node-int64": "^0.4.0"
+ }
+ },
+ "node_modules/buffer-from": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/bytes": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/call-bind-apply-helpers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/call-bound": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
+ "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "get-intrinsic": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001800",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001800.tgz",
+ "integrity": "sha512-MMHtuAz9Ys840zAY5F4k6fV5GaivZ9sPk+nz0mY+GYVzRBnYkN0mpqkSR92oWRQ19yQWo4HvBV/FnC16AJX8MA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "CC-BY-4.0"
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/char-regex": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
+ "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cjs-module-lexer": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz",
+ "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/co": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+ "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "iojs": ">= 1.0.0",
+ "node": ">= 0.12.0"
+ }
+ },
+ "node_modules/collect-v8-coverage": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz",
+ "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/component-emitter": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz",
+ "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/content-disposition": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz",
+ "integrity": "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/content-type": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
+ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cookie": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
+ "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie-signature": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
+ "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.6.0"
+ }
+ },
+ "node_modules/cookiejar": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz",
+ "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/create-jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz",
+ "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "chalk": "^4.0.0",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.9",
+ "jest-config": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "prompts": "^2.0.1"
+ },
+ "bin": {
+ "create-jest": "bin/create-jest.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/dedent": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.2.tgz",
+ "integrity": "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "babel-plugin-macros": "^3.1.0"
+ },
+ "peerDependenciesMeta": {
+ "babel-plugin-macros": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deepmerge": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
+ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/depd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/detect-newline": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
+ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/dezalgo": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz",
+ "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "asap": "^2.0.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/diff-sequences": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz",
+ "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/dunder-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
+ "license": "MIT"
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.387",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.387.tgz",
+ "integrity": "sha512-TaxwufTFDufvPEoXdhwVrA3UdFWBeWGkYoJ1K8ldF1xe6gKfth6iRNS5lTQ5JPNOHdGQm8PT1QYKUqFLCiUefQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/emittery": {
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz",
+ "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/emittery?sponsor=1"
+ }
+ },
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/encodeurl": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
+ "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/error-ex": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz",
+ "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "node_modules/es-define-property": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-object-atoms": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz",
+ "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
+ "license": "MIT"
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
+ "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/execa": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.0",
+ "human-signals": "^2.1.0",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.1",
+ "onetime": "^5.1.2",
+ "signal-exit": "^3.0.3",
+ "strip-final-newline": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/exit": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
+ "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/expect": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz",
+ "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/expect-utils": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/express": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz",
+ "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==",
+ "license": "MIT",
+ "dependencies": {
+ "accepts": "^2.0.0",
+ "body-parser": "^2.2.1",
+ "content-disposition": "^1.0.0",
+ "content-type": "^1.0.5",
+ "cookie": "^0.7.1",
+ "cookie-signature": "^1.2.1",
+ "debug": "^4.4.0",
+ "depd": "^2.0.0",
+ "encodeurl": "^2.0.0",
+ "escape-html": "^1.0.3",
+ "etag": "^1.8.1",
+ "finalhandler": "^2.1.0",
+ "fresh": "^2.0.0",
+ "http-errors": "^2.0.0",
+ "merge-descriptors": "^2.0.0",
+ "mime-types": "^3.0.0",
+ "on-finished": "^2.4.1",
+ "once": "^1.4.0",
+ "parseurl": "^1.3.3",
+ "proxy-addr": "^2.0.7",
+ "qs": "^6.14.0",
+ "range-parser": "^1.2.1",
+ "router": "^2.2.0",
+ "send": "^1.1.0",
+ "serve-static": "^2.2.0",
+ "statuses": "^2.0.1",
+ "type-is": "^2.0.1",
+ "vary": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-safe-stringify": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz",
+ "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fb-watchman": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz",
+ "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "bser": "2.1.1"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/finalhandler": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz",
+ "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.4.0",
+ "encodeurl": "^2.0.0",
+ "escape-html": "^1.0.3",
+ "on-finished": "^2.4.1",
+ "parseurl": "^1.3.3",
+ "statuses": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/form-data": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz",
+ "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "es-set-tostringtag": "^2.1.0",
+ "hasown": "^2.0.4",
+ "mime-types": "^2.1.35"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/form-data/node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/form-data/node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/formidable": {
+ "version": "3.5.4",
+ "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.4.tgz",
+ "integrity": "sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@paralleldrive/cuid2": "^2.2.2",
+ "dezalgo": "^1.0.4",
+ "once": "^1.4.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "funding": {
+ "url": "https://ko-fi.com/tunnckoCore/commissions"
+ }
+ },
+ "node_modules/forwarded": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fresh": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz",
+ "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "function-bind": "^1.1.2",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-package-type": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
+ "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/get-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/get-stream": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/handlebars": {
+ "version": "4.7.9",
+ "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz",
+ "integrity": "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "minimist": "^1.2.5",
+ "neo-async": "^2.6.2",
+ "source-map": "^0.6.1",
+ "wordwrap": "^1.0.0"
+ },
+ "bin": {
+ "handlebars": "bin/handlebars"
+ },
+ "engines": {
+ "node": ">=0.4.7"
+ },
+ "optionalDependencies": {
+ "uglify-js": "^3.1.4"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-symbols": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz",
+ "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==",
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/html-escaper": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
+ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/http-errors": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
+ "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
+ "license": "MIT",
+ "dependencies": {
+ "depd": "~2.0.0",
+ "inherits": "~2.0.4",
+ "setprototypeof": "~1.2.0",
+ "statuses": "~2.0.2",
+ "toidentifier": "~1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/human-signals": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
+ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=10.17.0"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.3.tgz",
+ "integrity": "sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==",
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/import-local": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz",
+ "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "pkg-dir": "^4.2.0",
+ "resolve-cwd": "^3.0.0"
+ },
+ "bin": {
+ "import-local-fixture": "fixtures/cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "license": "ISC"
+ },
+ "node_modules/ipaddr.js": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/is-core-module": {
+ "version": "2.16.2",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz",
+ "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-generator-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz",
+ "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-promise": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
+ "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
+ "license": "MIT"
+ },
+ "node_modules/is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/istanbul-lib-coverage": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
+ "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/istanbul-lib-instrument": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz",
+ "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/core": "^7.23.9",
+ "@babel/parser": "^7.23.9",
+ "@istanbuljs/schema": "^0.1.3",
+ "istanbul-lib-coverage": "^3.2.0",
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-instrument/node_modules/semver": {
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-report": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
+ "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "istanbul-lib-coverage": "^3.0.0",
+ "make-dir": "^4.0.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-source-maps": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz",
+ "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "debug": "^4.1.1",
+ "istanbul-lib-coverage": "^3.0.0",
+ "source-map": "^0.6.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-reports": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz",
+ "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "html-escaper": "^2.0.0",
+ "istanbul-lib-report": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz",
+ "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/core": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "import-local": "^3.0.2",
+ "jest-cli": "^29.7.0"
+ },
+ "bin": {
+ "jest": "bin/jest.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-changed-files": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz",
+ "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "execa": "^5.0.0",
+ "jest-util": "^29.7.0",
+ "p-limit": "^3.1.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-circus": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz",
+ "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/expect": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "co": "^4.6.0",
+ "dedent": "^1.0.0",
+ "is-generator-fn": "^2.0.0",
+ "jest-each": "^29.7.0",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-runtime": "^29.7.0",
+ "jest-snapshot": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "p-limit": "^3.1.0",
+ "pretty-format": "^29.7.0",
+ "pure-rand": "^6.0.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-cli": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz",
+ "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/core": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "chalk": "^4.0.0",
+ "create-jest": "^29.7.0",
+ "exit": "^0.1.2",
+ "import-local": "^3.0.2",
+ "jest-config": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "yargs": "^17.3.1"
+ },
+ "bin": {
+ "jest": "bin/jest.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-config": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz",
+ "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@jest/test-sequencer": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "babel-jest": "^29.7.0",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "deepmerge": "^4.2.2",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "jest-circus": "^29.7.0",
+ "jest-environment-node": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.7.0",
+ "jest-runner": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "parse-json": "^5.2.0",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@types/node": "*",
+ "ts-node": ">=9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "ts-node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-diff": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz",
+ "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "diff-sequences": "^29.6.3",
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-docblock": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz",
+ "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "detect-newline": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-each": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz",
+ "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-environment-node": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz",
+ "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-mock": "^29.7.0",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-get-type": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz",
+ "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-haste-map": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz",
+ "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/graceful-fs": "^4.1.3",
+ "@types/node": "*",
+ "anymatch": "^3.0.3",
+ "fb-watchman": "^2.0.0",
+ "graceful-fs": "^4.2.9",
+ "jest-regex-util": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "walker": "^1.0.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "^2.3.2"
+ }
+ },
+ "node_modules/jest-leak-detector": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz",
+ "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-matcher-utils": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz",
+ "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "jest-diff": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-message-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz",
+ "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.12.13",
+ "@jest/types": "^29.6.3",
+ "@types/stack-utils": "^2.0.0",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-mock": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz",
+ "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-pnp-resolver": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz",
+ "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ },
+ "peerDependencies": {
+ "jest-resolve": "*"
+ },
+ "peerDependenciesMeta": {
+ "jest-resolve": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-regex-util": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz",
+ "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-resolve": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz",
+ "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-pnp-resolver": "^1.2.2",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "resolve": "^1.20.0",
+ "resolve.exports": "^2.0.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-resolve-dependencies": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz",
+ "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "jest-regex-util": "^29.6.3",
+ "jest-snapshot": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-runner": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz",
+ "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/console": "^29.7.0",
+ "@jest/environment": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "emittery": "^0.13.1",
+ "graceful-fs": "^4.2.9",
+ "jest-docblock": "^29.7.0",
+ "jest-environment-node": "^29.7.0",
+ "jest-haste-map": "^29.7.0",
+ "jest-leak-detector": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-resolve": "^29.7.0",
+ "jest-runtime": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-watcher": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "p-limit": "^3.1.0",
+ "source-map-support": "0.5.13"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-runtime": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz",
+ "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/globals": "^29.7.0",
+ "@jest/source-map": "^29.6.3",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "cjs-module-lexer": "^1.0.0",
+ "collect-v8-coverage": "^1.0.0",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-mock": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.7.0",
+ "jest-snapshot": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "slash": "^3.0.0",
+ "strip-bom": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-snapshot": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz",
+ "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@babel/generator": "^7.7.2",
+ "@babel/plugin-syntax-jsx": "^7.7.2",
+ "@babel/plugin-syntax-typescript": "^7.7.2",
+ "@babel/types": "^7.3.3",
+ "@jest/expect-utils": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "babel-preset-current-node-syntax": "^1.0.0",
+ "chalk": "^4.0.0",
+ "expect": "^29.7.0",
+ "graceful-fs": "^4.2.9",
+ "jest-diff": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "natural-compare": "^1.4.0",
+ "pretty-format": "^29.7.0",
+ "semver": "^7.5.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-snapshot/node_modules/semver": {
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-validate": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz",
+ "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "camelcase": "^6.2.0",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^29.6.3",
+ "leven": "^3.1.0",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-validate/node_modules/camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/jest-watcher": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz",
+ "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.0.0",
+ "emittery": "^0.13.1",
+ "jest-util": "^29.7.0",
+ "string-length": "^4.0.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-worker": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz",
+ "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "jest-util": "^29.7.0",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-worker/node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/js-yaml": {
+ "version": "3.15.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.15.0.tgz",
+ "integrity": "sha512-ttBQIIQPDeLjpPOohtUdXuXUVoA2uIB6fEH9HyJ7234s5mBJ5wTx20njxplLZQgLaOfpmPQA7X2t5AX6tIPbog==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsesc": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/json-parse-even-better-errors": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/kleur": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
+ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/leven": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
+ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/lines-and-columns": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/lodash.memoize": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
+ "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node_modules/make-dir": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
+ "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "semver": "^7.5.3"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/make-dir/node_modules/semver": {
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/make-error": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
+ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/makeerror": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
+ "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "tmpl": "1.0.5"
+ }
+ },
+ "node_modules/math-intrinsics": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/media-typer": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz",
+ "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/merge-descriptors": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz",
+ "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "braces": "^3.0.3",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/mime": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
+ "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.54.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
+ "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz",
+ "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "^1.54.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
+ "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/negotiator": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz",
+ "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/neo-async": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
+ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/node-int64": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
+ "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.50",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.50.tgz",
+ "integrity": "sha512-J6l92tKHX6w8Jy5nO1Vuc01NoIiRGi/d6qBKVxh+IQ8Cr3b6HbVNfKiF8ZpFKufTwpwxMmce2W3iQZ861ZRyTg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.13.4",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
+ "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/on-finished": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
+ "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
+ "license": "MIT",
+ "dependencies": {
+ "ee-first": "1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "license": "ISC",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mimic-fn": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/p-locate/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse-json": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-even-better-errors": "^2.3.0",
+ "lines-and-columns": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/path-to-regexp": {
+ "version": "8.4.2",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.2.tgz",
+ "integrity": "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
+ "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pirates": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz",
+ "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/pkg-dir": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "find-up": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/pretty-format/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/prompts": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
+ "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "kleur": "^3.0.3",
+ "sisteransi": "^1.0.5"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/proxy-addr": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
+ "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
+ "license": "MIT",
+ "dependencies": {
+ "forwarded": "0.2.0",
+ "ipaddr.js": "1.9.1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/pure-rand": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz",
+ "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/dubzzz"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fast-check"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/qs": {
+ "version": "6.15.3",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.3.tgz",
+ "integrity": "sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "es-define-property": "^1.0.1",
+ "side-channel": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/range-parser": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.3.0.tgz",
+ "integrity": "sha512-hek2mFQpPuI4E1BBKrSto+BU3e3x4xuarsbiwr3+lf7p44juvFMV0XFWQAP3xUyqXA4RrXLIoaSUGbSt056ZMw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/raw-body": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz",
+ "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==",
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "~3.1.2",
+ "http-errors": "~2.0.1",
+ "iconv-lite": "~0.7.0",
+ "unpipe": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/react-is": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
+ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "1.22.12",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz",
+ "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "is-core-module": "^2.16.1",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-cwd": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
+ "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/resolve.exports": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz",
+ "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/router": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz",
+ "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.4.0",
+ "depd": "^2.0.0",
+ "is-promise": "^4.0.0",
+ "parseurl": "^1.3.3",
+ "path-to-regexp": "^8.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "license": "MIT"
+ },
+ "node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/send": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz",
+ "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.4.3",
+ "encodeurl": "^2.0.0",
+ "escape-html": "^1.0.3",
+ "etag": "^1.8.1",
+ "fresh": "^2.0.0",
+ "http-errors": "^2.0.1",
+ "mime-types": "^3.0.2",
+ "ms": "^2.1.3",
+ "on-finished": "^2.4.1",
+ "range-parser": "^1.2.1",
+ "statuses": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/serve-static": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz",
+ "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==",
+ "license": "MIT",
+ "dependencies": {
+ "encodeurl": "^2.0.0",
+ "escape-html": "^1.0.3",
+ "parseurl": "^1.3.3",
+ "send": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/setprototypeof": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
+ "license": "ISC"
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/side-channel": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz",
+ "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.4",
+ "side-channel-list": "^1.0.1",
+ "side-channel-map": "^1.0.1",
+ "side-channel-weakmap": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-list": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz",
+ "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-map": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
+ "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-weakmap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
+ "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3",
+ "side-channel-map": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/sisteransi": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
+ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-support": {
+ "version": "0.5.13",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz",
+ "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/stack-utils": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
+ "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "escape-string-regexp": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/statuses": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
+ "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/string-length": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
+ "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "char-regex": "^1.0.2",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-bom": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
+ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-final-newline": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/superagent": {
+ "version": "10.3.0",
+ "resolved": "https://registry.npmjs.org/superagent/-/superagent-10.3.0.tgz",
+ "integrity": "sha512-B+4Ik7ROgVKrQsXTV0Jwp2u+PXYLSlqtDAhYnkkD+zn3yg8s/zjA2MeGayPoY/KICrbitwneDHrjSotxKL+0XQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "component-emitter": "^1.3.1",
+ "cookiejar": "^2.1.4",
+ "debug": "^4.3.7",
+ "fast-safe-stringify": "^2.1.1",
+ "form-data": "^4.0.5",
+ "formidable": "^3.5.4",
+ "methods": "^1.1.2",
+ "mime": "2.6.0",
+ "qs": "^6.14.1"
+ },
+ "engines": {
+ "node": ">=14.18.0"
+ }
+ },
+ "node_modules/supertest": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.2.2.tgz",
+ "integrity": "sha512-oK8WG9diS3DlhdUkcFn4tkNIiIbBx9lI2ClF8K+b2/m8Eyv47LSawxUzZQSNKUrVb2KsqeTDCcjAAVPYaSLVTA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cookie-signature": "^1.2.2",
+ "methods": "^1.1.2",
+ "superagent": "^10.3.0"
+ },
+ "engines": {
+ "node": ">=14.18.0"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/test-exclude": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
+ "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "@istanbuljs/schema": "^0.1.2",
+ "glob": "^7.1.4",
+ "minimatch": "^3.0.4"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/tmpl": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
+ "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/toidentifier": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/ts-jest": {
+ "version": "29.4.11",
+ "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.11.tgz",
+ "integrity": "sha512-IrFl7l9AuB/qrNw5quqvAv/hmKMb8dhWOH4jQOGo0Oq8tCeo1O86/iTFG1FaRimgUkF13l4PcepO8ATFT6Ns4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "bs-logger": "^0.2.6",
+ "fast-json-stable-stringify": "^2.1.0",
+ "handlebars": "^4.7.9",
+ "json5": "^2.2.3",
+ "lodash.memoize": "^4.1.2",
+ "make-error": "^1.3.6",
+ "semver": "^7.8.0",
+ "type-fest": "^4.41.0",
+ "yargs-parser": "^21.1.1"
+ },
+ "bin": {
+ "ts-jest": "cli.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": ">=7.0.0-beta.0 <8",
+ "@jest/transform": "^29.0.0 || ^30.0.0",
+ "@jest/types": "^29.0.0 || ^30.0.0",
+ "babel-jest": "^29.0.0 || ^30.0.0",
+ "jest": "^29.0.0 || ^30.0.0",
+ "jest-util": "^29.0.0 || ^30.0.0",
+ "typescript": ">=4.3 <7"
+ },
+ "peerDependenciesMeta": {
+ "@babel/core": {
+ "optional": true
+ },
+ "@jest/transform": {
+ "optional": true
+ },
+ "@jest/types": {
+ "optional": true
+ },
+ "babel-jest": {
+ "optional": true
+ },
+ "esbuild": {
+ "optional": true
+ },
+ "jest-util": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/ts-jest/node_modules/semver": {
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/ts-jest/node_modules/type-fest": {
+ "version": "4.41.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz",
+ "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==",
+ "dev": true,
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/type-detect": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
+ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "0.21.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+ "dev": true,
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/type-is": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.1.0.tgz",
+ "integrity": "sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==",
+ "license": "MIT",
+ "dependencies": {
+ "content-type": "^2.0.0",
+ "media-typer": "^1.1.0",
+ "mime-types": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/type-is/node_modules/content-type": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz",
+ "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.9.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
+ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/uglify-js": {
+ "version": "3.19.3",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz",
+ "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "optional": true,
+ "bin": {
+ "uglifyjs": "bin/uglifyjs"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
+ "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
+ "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/v8-to-istanbul": {
+ "version": "9.3.0",
+ "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz",
+ "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.12",
+ "@types/istanbul-lib-coverage": "^2.0.1",
+ "convert-source-map": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10.12.0"
+ }
+ },
+ "node_modules/vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/walker": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
+ "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "makeerror": "1.0.12"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/wordwrap": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+ "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "license": "ISC"
+ },
+ "node_modules/write-file-atomic": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz",
+ "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^3.0.7"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/yargs": {
+ "version": "17.7.3",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz",
+ "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/zod": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz",
+ "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ }
+ }
+}
diff --git a/samples/server/petstore/typescript-express-zod-server/package.json b/samples/server/petstore/typescript-express-zod-server/package.json
new file mode 100644
index 000000000000..6abb72c0b3f7
--- /dev/null
+++ b/samples/server/petstore/typescript-express-zod-server/package.json
@@ -0,0 +1,24 @@
+{
+ "name": "typescript-express-zod-server-petstore",
+ "version": "1.0.0",
+ "private": true,
+ "description": "Sample project exercising the typescript-express-zod-server generated output",
+ "scripts": {
+ "build": "tsc --noEmit",
+ "test": "tsc --noEmit && jest"
+ },
+ "dependencies": {
+ "express": "^5.0.0",
+ "zod": "^4.0.0"
+ },
+ "devDependencies": {
+ "@types/express": "^5.0.0",
+ "@types/jest": "^29.5.14",
+ "@types/node": "^22.10.7",
+ "@types/supertest": "^6.0.2",
+ "jest": "^29.7.0",
+ "supertest": "^7.0.0",
+ "ts-jest": "^29.2.5",
+ "typescript": "^5.7.3"
+ }
+}
diff --git a/samples/server/petstore/typescript-express-zod-server/src/app.ts b/samples/server/petstore/typescript-express-zod-server/src/app.ts
new file mode 100644
index 000000000000..567b9400b4db
--- /dev/null
+++ b/samples/server/petstore/typescript-express-zod-server/src/app.ts
@@ -0,0 +1,24 @@
+/**
+ * Wires the generated router factory into an Express app using the hand-written
+ * service implementations. Exported as a factory so tests can create isolated
+ * app instances.
+ */
+import express from "express";
+
+import { getRouter } from "../builds/default/express";
+import { authorsService, catalogService } from "./services";
+
+export function createApp(): express.Express {
+ const app = express();
+ app.use(express.json());
+
+ const router = getRouter({
+ // Only consumed to serve Swagger UI at "/"; not needed for the API routes.
+ schema: {},
+ getAuthorsService: () => authorsService,
+ getCatalogService: () => catalogService,
+ });
+
+ app.use(router);
+ return app;
+}
diff --git a/samples/server/petstore/typescript-express-zod-server/src/services.ts b/samples/server/petstore/typescript-express-zod-server/src/services.ts
new file mode 100644
index 000000000000..c67a00a48415
--- /dev/null
+++ b/samples/server/petstore/typescript-express-zod-server/src/services.ts
@@ -0,0 +1,51 @@
+/**
+ * Hand-written implementations of the generated service interfaces.
+ *
+ * Each service is a plain object typed as the generated interface, so the
+ * method parameter/return types are contextually checked against the generated
+ * contract (in ../builds/default). The bodies use trivial in-memory data — the
+ * point of the sample is to exercise the generated routing / validation /
+ * DTO-mapping pipeline, not to be a real store.
+ */
+import type {
+ AuthorsService,
+ CatalogService,
+ Author,
+ Book,
+} from "../builds/default/types";
+
+const sampleAuthor: Author = { id: 1, name: "Ursula K. Le Guin" };
+
+const sampleBook: Book = {
+ id: 1,
+ title: "A Wizard of Earthsea",
+ genre: "FICTION",
+ author: sampleAuthor,
+ pageCount: 183,
+};
+
+export const catalogService: CatalogService = {
+ async createBook(params) {
+ return {
+ ...sampleBook,
+ title: params.createBookRequest.title,
+ genre: params.createBookRequest.genre,
+ };
+ },
+ async deleteBook() {},
+ async getBook(params) {
+ return { ...sampleBook, id: params.bookId };
+ },
+ async getLatestBookEvent(params) {
+ return { type: "BOOK_ADDED", bookId: params.bookId };
+ },
+};
+
+export const authorsService: AuthorsService = {
+ async createAuthor(params) {
+ return { ...params.author, id: params.author.id ?? 7 };
+ },
+ async getAuthor(params) {
+ return { ...sampleAuthor, id: params.authorId };
+ },
+};
diff --git a/samples/server/petstore/typescript-express-zod-server/test/bookstore.e2e-spec.ts b/samples/server/petstore/typescript-express-zod-server/test/bookstore.e2e-spec.ts
new file mode 100644
index 000000000000..d989bd7211e5
--- /dev/null
+++ b/samples/server/petstore/typescript-express-zod-server/test/bookstore.e2e-spec.ts
@@ -0,0 +1,51 @@
+import request from "supertest";
+
+import { createApp } from "../src/app";
+
+const app = createApp();
+
+describe("typescript-express-zod-server (bookstore)", () => {
+ it("GET /books/{bookId} returns the book; the path param is coerced to a number", async () => {
+ const res = await request(app).get("/books/42");
+ expect(res.status).toBe(200);
+ expect(res.body).toMatchObject({ id: 42, title: "A Wizard of Earthsea", genre: "FICTION" });
+ // nullable $ref property is mapped through the DTO layer
+ expect(res.body.author).toMatchObject({ name: "Ursula K. Le Guin" });
+ });
+
+ it("POST /books validates the request body and returns the created book", async () => {
+ const res = await request(app)
+ .post("/books")
+ .send({ title: "The Dispossessed", genre: "FICTION", authorId: 1 });
+ expect(res.status).toBe(200);
+ expect(res.body).toMatchObject({ title: "The Dispossessed" });
+ });
+
+ it("DELETE /books/{bookId} succeeds for a void operation", async () => {
+ const res = await request(app).delete("/books/1");
+ expect(res.status).toBe(200);
+ });
+
+ it("GET /books/{bookId}/latest-event returns a discriminated-union member", async () => {
+ const res = await request(app).get("/books/5/latest-event");
+ expect(res.status).toBe(200);
+ expect(res.body).toEqual({ type: "BOOK_ADDED", bookId: 5 });
+ });
+
+ it("GET /authors/{authorId} returns the author", async () => {
+ const res = await request(app).get("/authors/9");
+ expect(res.status).toBe(200);
+ expect(res.body).toMatchObject({ id: 9, name: "Ursula K. Le Guin" });
+ });
+
+ it("rejects a path param that fails schema validation with a 4xx", async () => {
+ const res = await request(app).get("/books/not-a-number");
+ expect(res.status).toBeGreaterThanOrEqual(400);
+ expect(res.status).toBeLessThan(500);
+ });
+
+ it("returns 405 Method Not Allowed for an unsupported method on a known route", async () => {
+ const res = await request(app).patch("/books/1");
+ expect(res.status).toBe(405);
+ });
+});
diff --git a/samples/server/petstore/typescript-express-zod-server/tsconfig.json b/samples/server/petstore/typescript-express-zod-server/tsconfig.json
new file mode 100644
index 000000000000..678feb1055c0
--- /dev/null
+++ b/samples/server/petstore/typescript-express-zod-server/tsconfig.json
@@ -0,0 +1,19 @@
+{
+ "compilerOptions": {
+ "target": "ES2022",
+ "module": "commonjs",
+ "moduleResolution": "node",
+ "lib": ["ES2022"],
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": false,
+ "esModuleInterop": true,
+ "forceConsistentCasingInFileNames": true,
+ "isolatedModules": true,
+ "skipLibCheck": true,
+ "declaration": false,
+ "outDir": "dist"
+ },
+ "include": ["builds/**/*.ts", "src/**/*.ts", "test/**/*.ts"],
+ "exclude": ["node_modules", "dist"]
+}