input = env.getArgument("input");
specialtyService.deleteSpecialty(input.get("specialtyId"));
return new RemoveSpecialtyPayload(List.copyOf(specialtyRepository.findAll()));
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/graphql/UpdateOwnerInput.java
================================================
package org.springframework.samples.petclinic.graphql;
/**
* @author Nils Hartmann (nils@nilshartmann.net)
*/
public class UpdateOwnerInput extends AbstractOwnerInput {
private int ownerId;
public int getOwnerId() {
return ownerId;
}
public void setOwnerId(int ownerId) {
this.ownerId = ownerId;
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/graphql/UpdateOwnerPayload.java
================================================
package org.springframework.samples.petclinic.graphql;
import org.springframework.samples.petclinic.model.Owner;
/**
* @author Nils Hartmann (nils@nilshartmann.net)
*/
public class UpdateOwnerPayload extends AbstractOwnerPayload {
public UpdateOwnerPayload(Owner owner) {
super(owner);
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/graphql/UpdatePetInput.java
================================================
package org.springframework.samples.petclinic.graphql;
/**
* @author Nils Hartmann (nils@nilshartmann.net)
*/
public class UpdatePetInput extends AbstractPetInput {
private int petId;
public int getPetId() {
return petId;
}
public void setPetId(int petId) {
this.petId = petId;
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/graphql/UpdatePetPayload.java
================================================
package org.springframework.samples.petclinic.graphql;
import org.springframework.samples.petclinic.model.Pet;
/**
* @author Nils Hartmann (nils@nilshartmann.net)
*/
public record UpdatePetPayload (Pet pet) {}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/graphql/UpdateSpecialtyInput.java
================================================
package org.springframework.samples.petclinic.graphql;
import jakarta.validation.constraints.NotNull;
public class UpdateSpecialtyInput {
@NotNull
private Integer specialtyId;
@NotNull
private String name;
public void setSpecialtyId(Integer specialtyId) {
this.specialtyId = specialtyId;
}
public void setName(String name) {
this.name = name;
}
public Integer getSpecialtyId() {
return specialtyId;
}
public String getName() {
return name;
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/graphql/UpdateSpecialtyPayload.java
================================================
package org.springframework.samples.petclinic.graphql;
import org.springframework.samples.petclinic.model.Specialty;
/**
* @author Nils Hartmann (nils@nilshartmann.net)
*/
public record UpdateSpecialtyPayload(Specialty specialty) {
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/graphql/VetController.java
================================================
package org.springframework.samples.petclinic.graphql;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Limit;
import org.springframework.data.domain.ScrollPosition;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Window;
import org.springframework.graphql.data.method.annotation.Argument;
import org.springframework.graphql.data.method.annotation.MutationMapping;
import org.springframework.graphql.data.method.annotation.QueryMapping;
import org.springframework.graphql.data.method.annotation.SchemaMapping;
import org.springframework.graphql.data.query.ScrollSubrange;
import org.springframework.samples.petclinic.model.*;
import org.springframework.samples.petclinic.repository.VetRepository;
import org.springframework.samples.petclinic.repository.VisitRepository;
import org.springframework.stereotype.Controller;
import java.util.List;
import java.util.Optional;
import static org.springframework.samples.petclinic.model.OwnerFilter.NO_FILTER;
/**
* GraphQL handler functions for Vet GraphQL type, Query and Mutation
*
* Note that the addVet mutation is secured in the domain layer, so that only
* users with SCOPE_MANAGER are allowed to create new vets
*
* @author Nils Hartmann (nils@nilshartmann.net)
*/
@Controller
public class VetController {
private static final Logger log = LoggerFactory.getLogger(VetController.class);
private final VetService vetService;
private final VetRepository vetRepository;
private final VisitRepository visitRepository;
public VetController(VetService vetService, VetRepository vetRepository, VisitRepository visitRepository) {
this.vetService = vetService;
this.vetRepository = vetRepository;
this.visitRepository = visitRepository;
}
@QueryMapping
public Window vets(ScrollSubrange subrange) {
var position = subrange.position().orElse(ScrollPosition.offset());
var sort = Sort.by("lastName", "firstName");
var limit = subrange.count().isPresent() ? Limit.of(subrange.count().getAsInt()) : Limit.unlimited();
Window vets = this.vetRepository.findBy(position, sort, limit);
return vets;
}
@QueryMapping
public Optional vet(@Argument Integer id) {
return vetRepository.findById(id);
}
@SchemaMapping
public VisitConnection visits(Vet vet) {
List visitList = visitRepository.findByVetId(vet.getId());
return new VisitConnection(visitList);
}
@MutationMapping
public AddVetPayload addVet(@Argument AddVetInput input) {
try {
Vet newVet = vetService.createVet(
input.getFirstName(),
input.getLastName(),
input.getSpecialtyIds());
return new AddVetSuccessPayload(newVet);
} catch (InvalidVetDataException ex) {
return new AddVetErrorPayload(ex.getLocalizedMessage());
}
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/graphql/VisitConnection.java
================================================
package org.springframework.samples.petclinic.graphql;
import org.springframework.samples.petclinic.model.Visit;
import java.util.List;
/**
* @author Nils Hartmann (nils@nilshartmann.net)
*/
public class VisitConnection {
private final List visits;
public VisitConnection(List visits) {
this.visits = visits;
}
public int getTotalCount() {
return visits.size();
}
public List getVisits() {
return visits;
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/graphql/VisitController.java
================================================
package org.springframework.samples.petclinic.graphql;
import org.springframework.graphql.data.method.annotation.Argument;
import org.springframework.graphql.data.method.annotation.MutationMapping;
import org.springframework.graphql.data.method.annotation.SchemaMapping;
import org.springframework.graphql.data.method.annotation.SubscriptionMapping;
import org.springframework.samples.petclinic.model.Vet;
import org.springframework.samples.petclinic.model.Visit;
import org.springframework.samples.petclinic.model.VisitService;
import org.springframework.samples.petclinic.repository.VetRepository;
import org.springframework.stereotype.Controller;
import reactor.core.publisher.Flux;
/**
* GraphQL handler functions for "Vitis" GraphQL type, Query, Mutation and Subscription
*
* @author Nils Hartmann (nils@nilshartmann.net)
*/
@Controller
public class VisitController {
private final VisitService visitService;
private final VisitPublisher visitPublisher;
private final VetRepository vetRepository;
public VisitController(VisitService visitService, VisitPublisher visitPublisher, VetRepository vetRepository) {
this.visitService = visitService;
this.visitPublisher = visitPublisher;
this.vetRepository = vetRepository;
}
@SchemaMapping
public Vet treatingVet(Visit visit) {
if (!visit.hasVetId()) {
return null;
}
return vetRepository.findById(visit.getVetId()).orElseThrow();
}
@MutationMapping
public AddVisitPayload addVisit(@Argument AddVisitInput input) {
Visit visit = visitService.addVisit(
input.getPetId(),
input.getDescription(),
input.getDate(),
input.getVetId()
);
return new AddVisitPayload(visit);
}
@SubscriptionMapping
public Flux onNewVisit() {
return visitPublisher.getPublisher();
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/graphql/VisitPublisher.java
================================================
package org.springframework.samples.petclinic.graphql;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.samples.petclinic.model.Visit;
import org.springframework.samples.petclinic.model.VisitCreatedEvent;
import org.springframework.samples.petclinic.repository.VisitRepository;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.event.TransactionalEventListener;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Sinks;
import reactor.util.concurrent.Queues;
/**
* "Forwards" VisitCreatedEvents that are fired by Spring Boot in our domain layer
* to a reactive publisher that is used by the GraphQL layer to publish events
* for our GraphQL Subscriptions
*
* @author Nils Hartmann (nils@nilshartmann.net)
*/
@Component
public class VisitPublisher {
private static final Logger logger = LoggerFactory.getLogger(VisitPublisher.class);
private final VisitRepository visitRepository;
private final Sinks.Many sink;
public VisitPublisher(VisitRepository visitRepository) {
this.visitRepository = visitRepository;
this.sink = Sinks.many()
.multicast()
.onBackpressureBuffer(Queues.SMALL_BUFFER_SIZE, false);
}
@TransactionalEventListener
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void onNewVisit(VisitCreatedEvent event) {
visitRepository.findById(event.getVisitId())
.ifPresent(visit -> {
this.sink.emitNext(visit, Sinks.EmitFailureHandler.FAIL_FAST);
});
}
public Flux getPublisher() {
return this.sink.asFlux();
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/graphql/runtime/DateCoercing.java
================================================
package org.springframework.samples.petclinic.graphql.runtime;
import graphql.language.StringValue;
import graphql.schema.Coercing;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import static java.lang.String.format;
/**
* Implements own date format (yyyy/MM/dd) for our own "Date" scalar type
*
* @author Nils Hartmann (nils@nilshartmann.net)
*/
public class DateCoercing implements Coercing {
private static DateTimeFormatter createIsoDateFormat() {
return DateTimeFormatter.ofPattern("yyyy/MM/dd");
}
@Override
public String serialize(Object input) {
if (input instanceof LocalDate) {
return createIsoDateFormat().format((LocalDate) input);
}
return null;
}
@Override
public LocalDate parseValue(Object input) {
if (input instanceof LocalDate) {
return (LocalDate) input;
} else if (input instanceof String) {
return fromString((String) input);
}
return null;
}
@Override
public LocalDate parseLiteral(Object input) {
if (input instanceof StringValue) {
String value = ((StringValue) input).getValue();
return fromString(value);
}
throw new UnsupportedOperationException("Unsupported input in DateScalarType: " + input);
}
private static LocalDate fromString(String input) {
try {
LocalDate date = LocalDate.parse(input, createIsoDateFormat());
return date;
} catch (Exception e) {
throw new IllegalArgumentException(format("Could not parse date from String '%s': %s", input, e.getLocalizedMessage()), e);
}
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/graphql/runtime/GraphiQlConfiguration.java
================================================
package org.springframework.samples.petclinic.graphql.runtime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.graphql.GraphQlProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.ClassPathResource;
import org.springframework.graphql.server.webmvc.GraphiQlHandler;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.function.RouterFunction;
import org.springframework.web.servlet.function.RouterFunctions;
import org.springframework.web.servlet.function.ServerResponse;
@Configuration
public class GraphiQlConfiguration implements WebMvcConfigurer {
@Bean
@Order(0)
public RouterFunction graphiQlRouterFunction(@Autowired GraphQlProperties graphQlProperties) {
RouterFunctions.Builder builder = RouterFunctions.route();
ClassPathResource graphiQlPage = new ClassPathResource("/ui/graphiql/index.html");
GraphiQlHandler graphiQLHandler = new GraphiQlHandler(
graphQlProperties.getPath(),
graphQlProperties.getWebsocket().getPath(),
graphiQlPage
);
builder = builder.GET("/", graphiQLHandler::handleRequest);
return builder.build();
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/graphiql/**")
.addResourceLocations("classpath:/ui/graphiql/");
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/graphql/runtime/PetClinicRuntimeWiringConfiguration.java
================================================
package org.springframework.samples.petclinic.graphql.runtime;
import graphql.schema.GraphQLScalarType;
import graphql.schema.idl.RuntimeWiring;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.graphql.execution.RuntimeWiringConfigurer;
import org.springframework.samples.petclinic.model.Vet;
/**
* GraphQL Runtime Wiring Configuration
*
* RunimeWiring connects the schema with behviour. Most of it is done
* aumatically by graphql-java, spring-graphql and Spring Boot starter for spring-graphql
* but here we do our own customizations
*
* @author Nils Hartmann (nils@nilshartmann.net)
*/
@Configuration
public class PetClinicRuntimeWiringConfiguration {
@Bean
RuntimeWiringConfigurer petclinicWiringConfigurer() {
return builder -> {
addDateCoercing(builder);
addPersonTypeResolver(builder);
};
}
private void addPersonTypeResolver(RuntimeWiring.Builder builder) {
builder.type("Person", typeBuilder -> typeBuilder.typeResolver(env -> {
Object javaObject = env.getObject();
if (javaObject instanceof Vet) {
return env.getSchema().getObjectType("Vet");
}
return env.getSchema().getObjectType("Owner");
}));
}
private void addDateCoercing(RuntimeWiring.Builder builder) {
builder.scalar(GraphQLScalarType.newScalar()
.name("Date")
.description("A Type representing a date (without time, only a day)")
.coercing(new DateCoercing())
.build());
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/model/BaseEntity.java
================================================
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.model;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.MappedSuperclass;
import java.io.Serializable;
/**
* Simple JavaBean domain object with an id property. Used as a base class for objects
* needing this property.
*
* @author Ken Krebs
* @author Juergen Hoeller
*/
@MappedSuperclass
public class BaseEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public boolean isNew() {
return this.id == null;
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/model/InvalidVetDataException.java
================================================
package org.springframework.samples.petclinic.model;
public class InvalidVetDataException extends Exception {
public InvalidVetDataException(String msg, Object... args) {
super(String.format(msg, args));
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/model/NamedEntity.java
================================================
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.model;
import jakarta.persistence.Column;
import jakarta.persistence.MappedSuperclass;
/**
* Simple JavaBean domain object adds a name property to BaseEntity. Used as
* a base class for objects needing these properties.
*
* @author Ken Krebs
* @author Juergen Hoeller
*/
@MappedSuperclass
public class NamedEntity extends BaseEntity {
@Column(name = "name")
private String name;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return this.getName();
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/model/OrderField.java
================================================
package org.springframework.samples.petclinic.model;
/**
* @author Xiangbin HAN (hanxb2001@163.com)
*
*/
public enum OrderField {
id,
firstName,
lastName,
address,
city,
telephone
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/model/Owner.java
================================================
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.model;
import org.springframework.beans.support.MutableSortDefinition;
import org.springframework.beans.support.PropertyComparator;
import org.springframework.core.style.ToStringCreator;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotEmpty;
import java.util.*;
/**
* Simple JavaBean domain object representing an owner.
*
* @author Ken Krebs
* @author Juergen Hoeller
* @author Sam Brannen
* @author Michael Isvy
*/
@Entity
@Table(name = "owners")
public class Owner extends Person {
@Column(name = "address")
@NotEmpty
private String address;
@Column(name = "city")
@NotEmpty
private String city;
@Column(name = "telephone")
@NotEmpty
private String telephone;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "owner", fetch = FetchType.EAGER)
private Set pets;
public String getAddress() {
return this.address;
}
public void setAddress(String address) {
this.address = address;
}
public String getCity() {
return this.city;
}
public void setCity(String city) {
this.city = city;
}
public String getTelephone() {
return this.telephone;
}
public void setTelephone(String telephone) {
this.telephone = telephone;
}
protected Set getPetsInternal() {
if (this.pets == null) {
this.pets = new HashSet<>();
}
return this.pets;
}
protected void setPetsInternal(Set pets) {
this.pets = pets;
}
public List getPets() {
List sortedPets = new ArrayList<>(getPetsInternal());
PropertyComparator.sort(sortedPets, new MutableSortDefinition("name", true, true));
return Collections.unmodifiableList(sortedPets);
}
public void addPet(Pet pet) {
getPetsInternal().add(pet);
pet.setOwner(this);
}
/**
* Return the Pet with the given name, or null if none found for this Owner.
* @param name to test
* @return true if pet name is already in use
*/
public Pet getPet(String name) {
return getPet(name, false);
}
/**
* Return the Pet with the given name, or null if none found for this Owner.
* @param name to test
* @return true if pet name is already in use
*/
public Pet getPet(String name, boolean ignoreNew) {
name = name.toLowerCase();
for (Pet pet : getPetsInternal()) {
if (!ignoreNew || !pet.isNew()) {
String compName = pet.getName();
compName = compName.toLowerCase();
if (compName.equals(name)) {
return pet;
}
}
}
return null;
}
@Override
public String toString() {
return new ToStringCreator(this)
.append("id", this.getId()).append("new", this.isNew()).append("lastName", this.getLastName())
.append("firstName", this.getFirstName()).append("address", this.address).append("city", this.city)
.append("telephone", this.telephone).toString();
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/model/OwnerFilter.java
================================================
package org.springframework.samples.petclinic.model;
import org.springframework.data.jpa.domain.Specification;
import jakarta.persistence.Query;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
import java.util.LinkedList;
import java.util.Map;
import java.util.Optional;
/**
* @author Xiangbin HAN (hanxb2001@163.com)
* @author Nils Hartmann
*/
public class OwnerFilter implements Specification {
public static OwnerFilter NO_FILTER = new OwnerFilter() {
public Predicate toPredicate(Root root, CriteriaQuery> query, CriteriaBuilder criteriaBuilder) {
return null;
}
};
private String firstName;
private String lastName;
private String address;
private String city;
private String telephone;
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public void setAddress(String address) {
this.address = address;
}
public void setCity(String city) {
this.city = city;
}
public void setTelephone(String telephone) {
this.telephone = telephone;
}
@Override
public Predicate toPredicate(Root root, CriteriaQuery> query, CriteriaBuilder criteriaBuilder) {
var predicates = new LinkedList();
if (isSet(firstName)) {
predicates.add(criteriaBuilder.like(
criteriaBuilder.lower(
root.get("firstName")), firstName.toLowerCase() + "%"));
}
if (isSet(lastName)) {
predicates.add(criteriaBuilder.like(
criteriaBuilder.lower(
root.get("lastName")), lastName.toLowerCase() + "%"));
}
if (isSet(address)) {
predicates.add(criteriaBuilder.like(
criteriaBuilder.lower(
root.get("address")), address.toLowerCase() + "%"));
}
if (isSet(city)) {
predicates.add(criteriaBuilder.equal(root.get("city"), city));
}
if (isSet(telephone)) {
predicates.add(criteriaBuilder.equal(root.get("telephone"), telephone));
}
if (predicates.isEmpty()) {
return null;
}
return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
}
private boolean isSet(String s) {
return s != null && !s.isBlank();
}
@Override
public String toString() {
return "OwnerFilter{" +
"firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", address='" + address + '\'' +
", city='" + city + '\'' +
", telephone='" + telephone + '\'' +
'}';
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/model/OwnerOrder.java
================================================
package org.springframework.samples.petclinic.model;
import org.springframework.data.domain.Sort;
import java.util.List;
/**
* @author Xiangbin HAN (hanxb2001@163.com)
* @author Nils Hartmann
*/
public record OwnerOrder(OrderField field, Sort.Direction direction) {
public static List defaultOrder() {
return List.of(Sort.Order.asc("id"));
}
public Sort.Order toSortOrder() {
// Sort.Direction direction = order == null ? Sort.DEFAULT_DIRECTION : order == OrderDirection.ASC ? Sort.Direction.ASC : Sort.Direction.DESC;
return new Sort.Order(direction, field.name());
}
public Sort toSort() {
return Sort.by(direction, field.name());
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/model/OwnerService.java
================================================
package org.springframework.samples.petclinic.model;
import org.springframework.samples.petclinic.repository.OwnerRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import jakarta.validation.constraints.NotEmpty;
import java.util.function.Consumer;
@Service
@Validated
public class OwnerService {
private final OwnerRepository ownerRepository;
public OwnerService(OwnerRepository ownerRepository) {
this.ownerRepository = ownerRepository;
}
@Transactional
public Owner addOwner(@NotEmpty String firstName, @NotEmpty String lastName, @NotEmpty String telephone, @NotEmpty String address, @NotEmpty String city) {
final Owner owner = new Owner();
owner.setAddress(address);
owner.setCity(city);
owner.setTelephone(telephone);
owner.setFirstName(firstName);
owner.setLastName(lastName);
ownerRepository.save(owner);
return owner;
}
@Transactional
public Owner updateOwner(@NotEmpty int ownerId, String firstName, String lastName, String telephone, String address, String city) {
Owner owner = ownerRepository.findById(ownerId).orElseThrow();
setIfGiven(address, owner::setAddress);
setIfGiven(firstName, owner::setFirstName);
setIfGiven(lastName, owner::setLastName);
setIfGiven(telephone, owner::setTelephone);
setIfGiven(address, owner::setAddress);
setIfGiven(city, owner::setCity);
ownerRepository.save(owner);
return owner;
}
private void setIfGiven(String value, Consumer s) {
if (value != null) {
s.accept(value);
}
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/model/Person.java
================================================
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.model;
import jakarta.persistence.Column;
import jakarta.persistence.MappedSuperclass;
import jakarta.validation.constraints.NotEmpty;
/**
* Simple JavaBean domain object representing an person.
*
* @author Ken Krebs
*/
@MappedSuperclass
public class Person extends BaseEntity {
@Column(name = "first_name")
@NotEmpty
private String firstName;
@Column(name = "last_name")
@NotEmpty
private String lastName;
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return this.lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/model/Pet.java
================================================
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.springframework.beans.support.MutableSortDefinition;
import org.springframework.beans.support.PropertyComparator;
import org.springframework.format.annotation.DateTimeFormat;
import jakarta.persistence.*;
import java.time.LocalDate;
import java.util.*;
/**
* Simple business object representing a pet.
*
* @author Ken Krebs
* @author Juergen Hoeller
* @author Sam Brannen
*/
@Entity
@Table(name = "pets")
public class Pet extends NamedEntity {
@Column(name = "birth_date")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate birthDate;
@ManyToOne
@JoinColumn(name = "type_id")
private PetType type;
@ManyToOne
@JoinColumn(name = "owner_id")
private Owner owner;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "pet", fetch = FetchType.EAGER)
private Set visits;
public void setBirthDate(LocalDate birthDate) {
this.birthDate = birthDate;
}
public LocalDate getBirthDate() {
return this.birthDate;
}
public PetType getType() {
return this.type;
}
public void setType(PetType type) {
this.type = type;
}
public Owner getOwner() {
return this.owner;
}
public void setOwner(Owner owner) {
this.owner = owner;
}
@JsonIgnore
protected Set getVisitsInternal() {
if (this.visits == null) {
this.visits = new HashSet<>();
}
return this.visits;
}
protected void setVisitsInternal(Set visits) {
this.visits = visits;
}
public List getVisits() {
List sortedVisits = new ArrayList<>(getVisitsInternal());
PropertyComparator.sort(sortedVisits, new MutableSortDefinition("date", false, false));
return Collections.unmodifiableList(sortedVisits);
}
public void addVisit(Visit visit) {
getVisitsInternal().add(visit);
visit.setPet(this);
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/model/PetService.java
================================================
package org.springframework.samples.petclinic.model;
import org.springframework.samples.petclinic.repository.OwnerRepository;
import org.springframework.samples.petclinic.repository.PetRepository;
import org.springframework.samples.petclinic.repository.PetTypeRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import java.time.LocalDate;
import java.util.Optional;
import java.util.function.Consumer;
@Service
@Validated
public class PetService {
private final OwnerRepository ownerRepository;
private final PetRepository petRepository;
private final PetTypeRepository petTypeRepository;
public PetService(OwnerRepository ownerRepository, PetRepository petRepository, PetTypeRepository petTypeRepository) {
this.ownerRepository = ownerRepository;
this.petRepository = petRepository;
this.petTypeRepository = petTypeRepository;
}
@Transactional
public Pet addPet(int ownerId, int petTypeId, @NotEmpty String petName, @NotNull LocalDate petBirthData) {
final Owner owner = ownerRepository.findById(ownerId).orElseThrow();
final PetType type = petTypeRepository.findById(petTypeId).orElseThrow();
Pet pet = new Pet();
pet.setName(petName);
pet.setType(type);
pet.setBirthDate(petBirthData);
pet.setOwner(owner);
petRepository.save(pet);
return pet;
}
@Transactional
public Pet updatePet(int petId, Optional petTypeId, String petName, LocalDate petBirthData) {
final Pet pet = petRepository.findById(petId).orElseThrow();
setIfGiven(petBirthData, pet::setBirthDate);
setIfGiven(petName, pet::setName);
setIfGiven(petTypeId.flatMap(petTypeRepository::findById).orElse(null), pet::setType);
petRepository.save(pet);
return pet;
}
private void setIfGiven(T value, Consumer s) {
if (value != null) {
s.accept(value);
}
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/model/PetType.java
================================================
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.model;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
/**
* @author Juergen Hoeller Can be Cat, Dog, Hamster...
*/
@Entity
@Table(name = "types")
public class PetType extends NamedEntity {
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/model/PetValidator.java
================================================
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.model;
import org.springframework.util.StringUtils;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
/**
* Validator for Pet forms.
*
* We're not using Bean Validation annotations here because it is easier to define such
* validation rule in Java.
*
*
* @author Ken Krebs
* @author Juergen Hoeller
*/
public class PetValidator implements Validator {
private static final String REQUIRED = "required";
@Override
public void validate(Object obj, Errors errors) {
Pet pet = (Pet) obj;
String name = pet.getName();
// name validation
if (!StringUtils.hasLength(name)) {
errors.rejectValue("name", REQUIRED, REQUIRED);
}
// type validation
if (pet.isNew() && pet.getType() == null) {
errors.rejectValue("type", REQUIRED, REQUIRED);
}
// birth date validation
if (pet.getBirthDate() == null) {
errors.rejectValue("birthDate", REQUIRED, REQUIRED);
}
}
/**
* This Validator validates *just* Pet instances
*/
@Override
public boolean supports(Class> clazz) {
return Pet.class.isAssignableFrom(clazz);
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/model/Specialty.java
================================================
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.model;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
import java.io.Serializable;
/**
* Models a {@link Vet Vet's} specialty (for example, dentistry).
*
* @author Juergen Hoeller
*/
@Entity
@Table(name = "specialties")
public class Specialty extends NamedEntity implements Serializable {
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/model/SpecialtyService.java
================================================
package org.springframework.samples.petclinic.model;
import org.springframework.samples.petclinic.repository.SpecialtyRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import jakarta.validation.constraints.NotEmpty;
@Service
@Validated
public class SpecialtyService {
private final SpecialtyRepository specialtyRepository;
public SpecialtyService(SpecialtyRepository specialtyRepository) {
this.specialtyRepository = specialtyRepository;
}
@Transactional
public Specialty addSpecialty(@NotEmpty String name) {
Specialty specialty = new Specialty();
specialty.setName(name);
specialtyRepository.save(specialty);
return specialty;
}
@Transactional
public Specialty updateSpecialty(int specialtyId, @NotEmpty String newName) {
Specialty specialty = specialtyRepository.findById(specialtyId).orElseThrow();
specialty.setName(newName);
specialtyRepository.save(specialty);
return specialty;
}
@Transactional
public void deleteSpecialty(int specialtyId) {
Specialty specialty = specialtyRepository.findById(specialtyId).orElseThrow();
specialtyRepository.delete(specialty);
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/model/Vet.java
================================================
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.model;
import org.springframework.beans.support.MutableSortDefinition;
import org.springframework.beans.support.PropertyComparator;
import jakarta.persistence.*;
import java.util.*;
/**
* Simple JavaBean domain object representing a veterinarian.
*
* @author Ken Krebs
* @author Juergen Hoeller
* @author Sam Brannen
* @author Arjen Poutsma
*/
@Entity
@Table(name = "vets")
public class Vet extends Person {
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "vet_specialties", joinColumns = @JoinColumn(name = "vet_id"),
inverseJoinColumns = @JoinColumn(name = "specialty_id"))
private Set specialties;
protected Set getSpecialtiesInternal() {
if (this.specialties == null) {
this.specialties = new HashSet<>();
}
return this.specialties;
}
protected void setSpecialtiesInternal(Set specialties) {
this.specialties = specialties;
}
public List getSpecialties() {
List sortedSpecs = new ArrayList<>(getSpecialtiesInternal());
PropertyComparator.sort(sortedSpecs, new MutableSortDefinition("name", true, true));
return Collections.unmodifiableList(sortedSpecs);
}
public int getNrOfSpecialties() {
return getSpecialtiesInternal().size();
}
public void addSpecialty(Specialty specialty) {
getSpecialtiesInternal().add(specialty);
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/model/VetService.java
================================================
package org.springframework.samples.petclinic.model;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.samples.petclinic.repository.SpecialtyRepository;
import org.springframework.samples.petclinic.repository.VetRepository;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class VetService {
private static final Logger log = LoggerFactory.getLogger(VetService.class);
private final VetRepository vetRepository;
private final SpecialtyRepository specialtyRepository;
public VetService(VetRepository vetRepository, SpecialtyRepository specialtyRepository) {
this.vetRepository = vetRepository;
this.specialtyRepository = specialtyRepository;
}
@Transactional
@PreAuthorize("hasAuthority('SCOPE_MANAGER')")
public Vet createVet(String firstName, String lastName, List specialtyIds) throws InvalidVetDataException {
Vet vet = new Vet();
vet.setFirstName(firstName);
vet.setLastName(lastName);
for (Integer specialtyId : specialtyIds) {
log.info("Specialty Id '{}'", specialtyId);
Specialty specialty = specialtyRepository.findById(specialtyId)
.orElseThrow( () -> new InvalidVetDataException("Specialty with Id '%s' not found", specialtyId));
log.info("Specialty '{}'", specialty);
vet.addSpecialty(specialty);
}
vetRepository.save(vet);
log.info("VET {}", vet);
return vet;
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/model/Vets.java
================================================
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.model;
import java.util.ArrayList;
import java.util.List;
/**
* Simple domain object representing a list of veterinarians. Mostly here to be used for
* the 'vets' {@link org.springframework.web.servlet.view.xml.MarshallingView}.
*
* @author Arjen Poutsma
*/
public class Vets {
private List vets;
public List getVetList() {
if (vets == null) {
vets = new ArrayList<>();
}
return vets;
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/model/Visit.java
================================================
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.model;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotEmpty;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDate;
/**
* Simple JavaBean domain object representing a visit.
*
* @author Ken Krebs
* @author Dave Syer
*/
@Entity
@Table(name = "visits")
public class Visit extends BaseEntity {
@Column(name = "visit_date")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate date;
@NotEmpty
@Column(name = "description")
private String description;
/**
* Holds value of property pet.
*/
@ManyToOne
@JoinColumn(name = "pet_id")
private Pet pet;
@Column(name = "vet_id")
private Integer vetId;
/**
* Creates a new instance of Visit for the current date
*/
public Visit() {
this.date = LocalDate.now();
}
public LocalDate getDate() {
return this.date;
}
public void setDate(LocalDate date) {
this.date = date;
}
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
public Pet getPet() {
return pet;
}
public void setPet(Pet pet) {
this.pet = pet;
}
public Integer getVetId() {
return vetId;
}
public void setVetId(Integer vetId) {
this.vetId = vetId;
}
public boolean hasVetId() {
return this.vetId != null;
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/model/VisitCreatedEvent.java
================================================
package org.springframework.samples.petclinic.model;
public class VisitCreatedEvent {
private final Integer visitId;
public VisitCreatedEvent(Integer visitId) {
this.visitId = visitId;
}
public Integer getVisitId() {
return visitId;
}
@Override
public String toString() {
return "VisitCreatedEvent{" +
"visitId=" + visitId +
'}';
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/model/VisitService.java
================================================
package org.springframework.samples.petclinic.model;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.samples.petclinic.repository.PetRepository;
import org.springframework.samples.petclinic.repository.VisitRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import java.time.LocalDate;
import java.util.Optional;
@Service
@Validated
public class VisitService {
private final ApplicationEventPublisher applicationEventPublisher;
private final PetRepository petRepository;
private final VisitRepository visitRepository;
public VisitService(ApplicationEventPublisher applicationEventPublisher, PetRepository petRepository, VisitRepository visitRepository) {
this.applicationEventPublisher = applicationEventPublisher;
this.petRepository = petRepository;
this.visitRepository = visitRepository;
}
@Transactional
public Visit addVisit(int petId, @NotEmpty String description, @NotNull LocalDate date, Optional vetId) {
Pet pet = petRepository.findById(petId).orElseThrow();
Visit visit = new Visit();
visit.setDescription(description);
visit.setPet(pet);
visit.setDate(date);
vetId.ifPresent(visit::setVetId);
visitRepository.save(visit);
applicationEventPublisher.publishEvent(new VisitCreatedEvent(visit.getId()));
return visit;
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/model/package-info.java
================================================
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* The classes in this package represent utilities used by the domain.
*/
package org.springframework.samples.petclinic.model;
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/repository/OwnerRepository.java
================================================
/*
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.repository;
import java.util.Collection;
import java.util.Optional;
import org.springframework.data.domain.*;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.Repository;
import org.springframework.lang.Nullable;
import org.springframework.samples.petclinic.model.BaseEntity;
import org.springframework.samples.petclinic.model.Owner;
/**
* Repository class for Owner domain objects
*
* @author Ken Krebs
* @author Juergen Hoeller
* @author Sam Brannen
* @author Michael Isvy
* @author Vitaliy Fedoriv
* @author Nils Hartmann
*/
public interface OwnerRepository extends Repository, JpaSpecificationExecutor {
/**
* Retrieve an Owner from the data store by id.
*
* @param id the id to search for
* @return the Owner if found
*/
Optional findById(Integer id);
/**
* Save an Owner to the data store, either inserting or updating it.
*
* @param owner the Owner to save
* @see BaseEntity#isNew
*/
void save(Owner owner);
/**
* Retrieve Owners from the data store, returning all owners
*
* @return a Collection of Owners (or an empty Collection if none
* found)
*/
Collection findAll();
/**
* Delete an Owner to the data store by Owner.
*
* @param owner the Owner to delete
*
*/
void delete(Owner owner);
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/repository/PetRepository.java
================================================
/*
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.repository;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import org.springframework.dao.DataAccessException;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.Repository;
import org.springframework.samples.petclinic.model.BaseEntity;
import org.springframework.samples.petclinic.model.Pet;
import org.springframework.samples.petclinic.model.PetType;
/**
* Repository class for Pet domain objects
*
* @author Ken Krebs
* @author Juergen Hoeller
* @author Sam Brannen
* @author Michael Isvy
* @author Vitaliy Fedoriv
* @author Nils Hartmann
*/
public interface PetRepository extends Repository {
/**
* Retrieve all PetTypes from the data store.
*
* @return a Collection of PetTypes
*/
@Query("SELECT ptype FROM PetType ptype ORDER BY ptype.name")
List findPetTypes();
/**
* Retrieve a Pet from the data store by id.
*
* @param id the id to search for
* @return the Pet if found
* @throws org.springframework.dao.DataRetrievalFailureException if not found
*/
Optional findById(Integer id);
/**
* Save a Pet to the data store, either inserting or updating it.
*
* @param pet the Pet to save
* @see BaseEntity#isNew
*/
void save(Pet pet);
/**
* Retrieve Pets from the data store, returning all owners
*
* @return a Collection of Pets (or an empty Collection if none
* found)
*/
Collection findAll();
/**
* Delete an Pet to the data store by Pet.
*
* @param pet the Pet to delete
*
*/
void delete(Pet pet);
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/repository/PetTypeRepository.java
================================================
/*
* Copyright 2016-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.repository;
import java.util.Collection;
import java.util.Optional;
import org.springframework.dao.DataAccessException;
import org.springframework.data.repository.Repository;
import org.springframework.samples.petclinic.model.PetType;
/**
* @author Vitaliy Fedoriv
* @author Nils Hartmann
*
*/
public interface PetTypeRepository extends Repository {
Optional findById(Integer id) ;
Collection findAll();
void save(PetType petType);
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/repository/SpecialtyRepository.java
================================================
/*
* Copyright 2016-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.repository;
import java.util.Collection;
import java.util.Optional;
import org.springframework.dao.DataAccessException;
import org.springframework.data.repository.Repository;
import org.springframework.samples.petclinic.model.Specialty;
/**
* @author Vitaliy Fedoriv
* @author Nils Hartmann
*
*/
public interface SpecialtyRepository extends Repository {
Optional findById(Integer id);
Collection findAll();
void save(Specialty specialty);
void delete(Specialty specialty);
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/repository/VetRepository.java
================================================
/*
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.repository;
import java.util.Collection;
import java.util.Optional;
import org.springframework.dao.DataAccessException;
import org.springframework.data.domain.Limit;
import org.springframework.data.domain.ScrollPosition;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Window;
import org.springframework.data.repository.Repository;
import org.springframework.samples.petclinic.model.Vet;
/**
* Repository class for Vet domain objects
*
* @author Ken Krebs
* @author Juergen Hoeller
* @author Sam Brannen
* @author Michael Isvy
* @author Vitaliy Fedoriv
* @author Nils Hartmann
*/
public interface VetRepository extends Repository {
Optional findById(Integer id);
Vet save(Vet vet);
void delete(Vet vet);
Window findBy(ScrollPosition position, Sort sort, Limit limit);
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/repository/VisitRepository.java
================================================
/*
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.repository;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import org.springframework.dao.DataAccessException;
import org.springframework.data.repository.Repository;
import org.springframework.samples.petclinic.model.BaseEntity;
import org.springframework.samples.petclinic.model.Visit;
/**
* Repository class for Visit domain objects
*
* @author Ken Krebs
* @author Juergen Hoeller
* @author Sam Brannen
* @author Michael Isvy
* @author Vitaliy Fedoriv
* @author Nils Hartmann
*/
public interface VisitRepository extends Repository {
/**
* Save a Visit to the data store, either inserting or updating it.
*
* @param visit the Visit to save
* @see BaseEntity#isNew
*/
void save(Visit visit);
List findByPetIdOrderById(Integer petId);
Optional findById(Integer id);
Collection findAll();
void delete(Visit visit);
List findByVetId(Integer id);
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/security/JwtTokenService.java
================================================
package org.springframework.samples.petclinic.security;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.jwt.JwtClaimsSet;
import org.springframework.security.oauth2.jwt.JwtEncoder;
import org.springframework.security.oauth2.jwt.JwtEncoderParameters;
import org.springframework.stereotype.Service;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Collection;
import java.util.stream.Collectors;
/**
* Based con code taken from Dan Vega https://github.com/danvega/jwt-username-password/blob/master/src/main/java/dev/danvega/jwt/service/TokenService.java
*/
@Service
public class JwtTokenService {
private final JwtEncoder encoder;
public JwtTokenService(JwtEncoder encoder) {
this.encoder = encoder;
}
public String generateToken(Authentication authentication) {
return generateToken(authentication.getName(),
authentication.getAuthorities(),
Instant.now().plus(1, ChronoUnit.HOURS)
);
}
public String generateToken(String name, Collection extends GrantedAuthority> authorities, Instant expiresAt) {
String scope = authorities.stream()
.map(GrantedAuthority::getAuthority)
.collect(Collectors.joining(" "));
JwtClaimsSet claims = JwtClaimsSet.builder()
.issuer("self")
.issuedAt(Instant.now())
.expiresAt(expiresAt)
.subject(name)
.claim("scope", scope)
.build();
return this.encoder.encode(JwtEncoderParameters.from(claims)).getTokenValue();
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/security/LoginController.java
================================================
package org.springframework.samples.petclinic.security;
import jakarta.validation.Valid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
/**
* Login via Username/Password via HTTP POST endpoint.
*
* - The /graphql endpoints requires a valid token. This token can be requests by invoking
* HTTP "POST /api/login with" sending username and password.
*
*
* @author Nils Hartmann (nils@nilshartmann.net)
*/
@RestController
public class LoginController {
private static final Logger log = LoggerFactory.getLogger(LoginController.class);
private final JwtTokenService tokenService;
private final AuthenticationManager authenticationManager;
public LoginController(JwtTokenService tokenService, AuthenticationManager authenticationManager) {
this.tokenService = tokenService;
this.authenticationManager = authenticationManager;
}
@PostMapping("/api/login")
public ResponseEntity login(@RequestBody @Valid LoginRequest request) {
log.info("Authorizing '{}'", request.getUsername());
try {
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword())
);
String token = tokenService.generateToken(authentication);
return ResponseEntity.ok(new LoginResponse(token));
} catch (Exception ex) {
log.error("could not authenticate: " + ex, ex);
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
}
@GetMapping("/ping")
public String ping() {
return "pong";
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/security/LoginRequest.java
================================================
package org.springframework.samples.petclinic.security;
public class LoginRequest {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/security/LoginResponse.java
================================================
package org.springframework.samples.petclinic.security;
public class LoginResponse {
private final String token;
public LoginResponse(String token) {
this.token = token;
}
public String getToken() {
return token;
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/security/NeverExpiringTokenGenerator.java
================================================
package org.springframework.samples.petclinic.security;
import jakarta.annotation.PostConstruct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.samples.petclinic.auth.UserRepository;
import org.springframework.stereotype.Component;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
/**
* Generates a non-expiring token for testing.
*
* 👮 👮 👮 YOU SHOULD NEVER DO THIS IN PRODUCTION 👮 👮 👮
*
* @author Nils Hartmann (nils@nilshartmann.net)
*/
@Component
class NeverExpiringTokenGenerator {
private static final Logger log = LoggerFactory.getLogger(NeverExpiringTokenGenerator.class);
private final UserRepository userRepository;
private final JwtTokenService tokenService;
NeverExpiringTokenGenerator(UserRepository userRepository, JwtTokenService tokenService) {
this.userRepository = userRepository;
this.tokenService = tokenService;
}
/**
* Creates a token that will never expire and will be stable accross re-starts
* as longs as the RSAKey does not change (keys from publicKey and privateKey application properties)
*
* This token can be used for easier testing using command line tools etc.
* 👮 👮 👮 YOU SHOULD NEVER DO THIS IN 'REAL' PRODUCTION APPS 👮 👮 👮
*/
@PostConstruct
void createNonExpiringTokens() {
var somewhen = Instant.now().plus(10 * 365, ChronoUnit.DAYS);
var susi = userRepository.findByUsername("susi").orElseThrow();
var neverExpiringManagerToken = tokenService.generateToken(susi.getUsername(), susi.getRoles(), somewhen);
var joe = userRepository.findByUsername("joe").orElseThrow();
var neverExpiringUserToken = tokenService.generateToken(joe.getUsername(), joe.getRoles(), somewhen);
log.info("""
===============================================================
🚨 🚨 🚨 NEVER EXPIRING JWT TOKENS 🚨 🚨 🚨
===============================================================
SCOPE_MANAGER
login: '{}'
{"Authorization": "Bearer {}"}
SCOPE_USER
login: '{}'
{"Authorization": "Bearer {}"}
===============================================================
""",
susi.getUsername(),
neverExpiringManagerToken,
joe.getUsername(),
neverExpiringUserToken);
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/security/RSAKeyProvider.java
================================================
package org.springframework.samples.petclinic.security;
import com.nimbusds.jose.jwk.RSAKey;
import jakarta.annotation.PostConstruct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.UUID;
/**
* @author Nils Hartmann (nils@nilshartmann.net)
*
* Based on Code from Dan Vega: https://github.com/danvega/jwt-username-password/blob/master/src/main/java/dev/danvega/jwt/security/Jwks.java
*
* GENERATE KEYS WITH OPENSSL:
*
* Private Key: openssl genpkey -out private_key.pem -algorithm RSA -pkeyopt rsa_keygen_bits:4096
* Public Key : openssl rsa -pubout -outform pem -in private_key.pem -out public_key.pem
*/
@Component
public class RSAKeyProvider {
private static final Logger log = LoggerFactory.getLogger(RSAKeyProvider.class);
private final Resource publicKeyResource;
private final Resource privateKeyResource;
private RSAKey rsaKey;
public RSAKeyProvider(@Value("${publicKey}") Resource publicKeyResource, @Value("${privateKey}") Resource privateKeyResource) {
this.publicKeyResource = publicKeyResource;
this.privateKeyResource = privateKeyResource;
}
public RSAKey getRsaKey() {
return rsaKey;
}
@PostConstruct
private void generateRsaKey() throws Exception {
var publicKeyString = publicKeyResource.getInputStream().readAllBytes();
var privateKeyString = privateKeyResource.getInputStream().readAllBytes();
log.info("Creating RSA KEY......");
KeyFactory kf = KeyFactory.getInstance("RSA");
RSAPublicKey publicKey = getPublicKey();
RSAPrivateKey privateKey = getPrivateKey();
this.rsaKey = new RSAKey.Builder(publicKey)
.privateKey(privateKey)
.keyID(UUID.randomUUID().toString())
.build();
}
private RSAPublicKey getPublicKey() throws Exception {
log.debug("Public key {}", publicKeyResource.getURI());
byte[] keyBytes = publicKeyResource.getInputStream().readAllBytes();
String publicKeyPem = new String(keyBytes)
.replace("-----BEGIN PUBLIC KEY-----", "")
.replace("-----END PUBLIC KEY-----", "")
.replaceAll("\\s+", "");
byte[] decoded = Base64.getDecoder().decode(publicKeyPem.trim());
X509EncodedKeySpec spec = new X509EncodedKeySpec(decoded);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return (RSAPublicKey) keyFactory.generatePublic(spec);
}
private RSAPrivateKey getPrivateKey() throws Exception {
log.debug("Private key {}", privateKeyResource.getURI());
byte[] keyBytes = privateKeyResource.getInputStream().readAllBytes();
String privateKeyPEM = new String(keyBytes)
.replace("-----BEGIN PRIVATE KEY-----", "")
.replace("-----END PRIVATE KEY-----", "")
.replaceAll("\\s+", "");
byte[] decoded = Base64.getDecoder().decode(privateKeyPEM);
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(decoded);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return (RSAPrivateKey) keyFactory.generatePrivate(spec);
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/security/SecurityConfig.java
================================================
package org.springframework.samples.petclinic.security;
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.source.JWKSource;
import com.nimbusds.jose.proc.SecurityContext;
import jakarta.servlet.DispatcherType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpHeaders;
import org.springframework.samples.petclinic.auth.UserRepository;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.CsrfConfigurer;
import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.JwtEncoder;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
import org.springframework.security.oauth2.jwt.NimbusJwtEncoder;
import org.springframework.security.oauth2.server.resource.web.BearerTokenResolver;
import org.springframework.security.oauth2.server.resource.web.DefaultBearerTokenResolver;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import java.util.Arrays;
/**
* Configures security for PetClinic. Ensures that all requests to /graphql are secured.
*
* @author Nils Hartmann (nils@nilshartmann.net)
*/
@Configuration
@EnableMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig {
private static final Logger log = LoggerFactory.getLogger(SecurityConfig.class);
private final RSAKey rsaKey;
public SecurityConfig(RSAKeyProvider RSAKeyProvider) {
this.rsaKey = RSAKeyProvider.getRsaKey();
}
@Bean
public AuthenticationManager authManager(UserDetailsService userDetailsService) {
var authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService);
return new ProviderManager(authProvider);
}
@Bean
public UserDetailsService userDetailsService(UserRepository userRepository) {
return username -> userRepository
.findByUsername(username)
.orElseThrow(
() -> new UsernameNotFoundException(
username
)
);
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf(AbstractHttpConfigurer::disable);
http.sessionManagement(c -> c.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
http.authorizeHttpRequests(authorizeHttpRequests ->
authorizeHttpRequests
.dispatcherTypeMatchers(DispatcherType.ERROR).permitAll()
// allow login
.requestMatchers("/api/login/**").permitAll()
// // allow access to graphiql
.requestMatchers("/").permitAll()
.requestMatchers("/favicon.ico").permitAll()
.requestMatchers("/index.html").permitAll()
.requestMatchers("/graphiql/**").permitAll()
// ...while all other endpoints (INCLUDING /graphql !) should be authenticated
// fine granular, Role-based, access checks are done in the resolver
.anyRequest().authenticated()
);
http.oauth2ResourceServer(c -> c.jwt(Customizer.withDefaults()));
return http.build();
}
@Bean
BearerTokenResolver bearerTokenResolver() {
DefaultBearerTokenResolver bearerTokenResolver = new DefaultBearerTokenResolver();
bearerTokenResolver.setAllowUriQueryParameter(true);
return bearerTokenResolver;
}
@Bean
public JWKSource jwkSource(RSAKeyProvider RSAKeyProvider) {
JWKSet jwkSet = new JWKSet(rsaKey);
return (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
}
@Bean
JwtEncoder jwtEncoder(JWKSource jwks) {
return new NimbusJwtEncoder(jwks);
}
@Bean
JwtDecoder jwtDecoder() throws JOSEException {
return NimbusJwtDecoder.withPublicKey(rsaKey.toRSAPublicKey()).build();
}
}
================================================
FILE: backend/src/main/java/org/springframework/samples/petclinic/util/EntityUtils.java
================================================
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.util;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Collection;
import java.util.Date;
import org.springframework.orm.ObjectRetrievalFailureException;
import org.springframework.samples.petclinic.model.BaseEntity;
/**
* Utility methods for handling entities. Separate from the BaseEntity class mainly because of dependency on the
* ORM-associated ObjectRetrievalFailureException.
*
* @author Juergen Hoeller
* @author Sam Brannen
* @see BaseEntity
* @since 29.10.2003
*/
public abstract class EntityUtils {
/**
* Look up the entity of the given class with the given id in the given collection.
*
* @param entities the collection to search
* @param entityClass the entity class to look up
* @param entityId the entity id to look up
* @return the found entity
* @throws ObjectRetrievalFailureException if the entity was not found
*/
public static T getById(Collection entities, Class entityClass, int entityId)
throws ObjectRetrievalFailureException {
for (T entity : entities) {
if (entity.getId() == entityId && entityClass.isInstance(entity)) {
return entity;
}
}
throw new ObjectRetrievalFailureException(entityClass, entityId);
}
public static LocalDate asDateTime(Date date) {
return LocalDate.ofInstant(new Date(date.getTime()).toInstant(), ZoneId.systemDefault());
}
}
================================================
FILE: backend/src/main/resources/application.properties
================================================
# DataSource configuration omitted,
# as Spring Boot 3.1+ uses configuration from
# docker-compose/TestContainer automatically
spring.jpa.hibernate.ddl-auto=validate
logging.level.org.springframework.security=TRACE
logging.level.org.springframework.graphql=TRACE
logging.level.graphql=INFO
#----------------------------------------------------------------
# Server Configuration
#----------------------------------------------------------------
server.port=9977
#----------------------------------------------------------------
# Logging
#----------------------------------------------------------------
logging.level.org.springframework=INFO
#----------------------------------------------------------------
# Spring Security
#----------------------------------------------------------------
spring.security.filter.dispatcher-types=request,error
# Note that in real life:
# your would NEVER CHECK IN KEYS TO GIT (esp. no private keys)
# This is only to make the demo easier:
# - no need to generate the keys yourself
# - ability to provide stable, long living tokens for easier (live) demos
# NEVER check in your keys
publicKey=classpath:keys/public_key.pem
privateKey=classpath:keys/private_key.pem
#----------------------------------------------------------------
# spring-graphql config
#----------------------------------------------------------------
# Note that we DO NOT use the embedded GraphiQL UI from
# spring-graphql yet, because we use our own version
# that contains a login form
# Maybe we can switch to cookie-based authentication
# later
spring.graphql.graphiql.enabled=true
# !!! For CORS configuration see SecurityConfig class !!!
# GraphQL endpoints for Web and WebSocket requests
# Note that this endpoints are accessible only with a
# valid JWT token.
# You can find a valid token after login with GraphiQL
# or in the server log file after starting the server
# (search for "Never Expiring JWT Token")
spring.graphql.path=/graphql
spring.graphql.websocket.path=/graphqlws
================================================
FILE: backend/src/main/resources/db/migration/V100_1__create_schema.sql
================================================
DROP TABLE IF EXISTS visits CASCADE;
DROP TABLE IF EXISTS specialties CASCADE;
DROP TABLE IF EXISTS vet_specialties CASCADE;
DROP TABLE IF EXISTS vets CASCADE;
DROP TABLE IF EXISTS pets CASCADE;
DROP TABLE IF EXISTS types CASCADE;
DROP TABLE IF EXISTS owners CASCADE;
DROP TABLE IF EXISTS roles CASCADE;
DROP TABLE IF EXISTS users CASCADE;
CREATE TABLE users
(
username VARCHAR(20) NOT NULL,
password VARCHAR(20) NOT NULL,
enabled BOOLEAN DEFAULT TRUE NOT NULL,
fullname VARCHAR(256) NOT NULL,
PRIMARY KEY (username)
);
CREATE TABLE roles
(
id integer generated by default as identity,
username VARCHAR(20) NOT NULL REFERENCES users (username),
role VARCHAR(20) NOT NULL,
primary key (id)
);
CREATE INDEX fk_username_idx ON roles (username);
CREATE TABLE vets
(
id integer generated by default as identity,
first_name VARCHAR(30),
last_name VARCHAR(30),
primary key (id)
);
CREATE INDEX vets_last_name ON vets (last_name);
CREATE TABLE specialties
(
id integer generated by default as identity,
name VARCHAR(80),
primary key (id)
);
CREATE INDEX specialties_name ON specialties (name);
CREATE TABLE vet_specialties
(
vet_id INTEGER NOT NULL,
specialty_id INTEGER NOT NULL
);
alter table vet_specialties
add constraint vet_specialties_to_vet_fk
foreign key (vet_id)
references vets;
alter table vet_specialties
add constraint vet_specialties_to_specialties_fk
foreign key (specialty_id)
references specialties;
CREATE TABLE types
(
id integer generated by default as identity,
name VARCHAR(80),
primary key (id)
);
CREATE INDEX types_name ON types (name);
CREATE TABLE owners
(
id integer generated by default as identity,
first_name VARCHAR(30),
last_name VARCHAR(30),
address VARCHAR(255),
city VARCHAR(255),
telephone VARCHAR(128),
primary key (id)
);
CREATE INDEX owners_last_name ON owners (lower(last_name));
CREATE TABLE pets
(
id integer generated by default as identity,
name VARCHAR(30),
birth_date DATE,
type_id INTEGER NOT NULL REFERENCES types (id),
owner_id INTEGER NOT NULL REFERENCES owners (id),
primary key (id)
);
CREATE INDEX pets_name ON pets (name);
CREATE TABLE visits
(
id integer generated by default as identity,
pet_id INTEGER NOT NULL REFERENCES pets (id),
vet_id INTEGER REFERENCES vets (id),
visit_date DATE,
description VARCHAR(255),
primary key (id)
);
CREATE INDEX visits_pet_id ON visits (pet_id);
================================================
FILE: backend/src/main/resources/db/migration/V100_2__fill_db.sql
================================================
INSERT INTO users (USERNAME, PASSWORD, ENABLED, FULLNAME) VALUES ('joe', '{noop}joe', true, 'Joe Hill');
INSERT INTO users (USERNAME, PASSWORD, ENABLED, FULLNAME) VALUES ('susi', '{noop}susi', true, 'Susi Smith');
INSERT INTO roles (ID, USERNAME, ROLE) VALUES (0, 'susi', 'MANAGER');
INSERT INTO roles (ID, USERNAME, ROLE) VALUES (1, 'joe', 'USER');
INSERT INTO vets VALUES (1, 'James', 'Carter');
INSERT INTO vets VALUES (2, 'Helen', 'Leary');
INSERT INTO vets VALUES (3, 'Linda', 'Douglas');
INSERT INTO vets VALUES (4, 'Rafael', 'Ortega');
INSERT INTO vets VALUES (5, 'Henry', 'Stevens');
INSERT INTO vets VALUES (6, 'Sharon', 'Jenkins');
INSERT INTO vets VALUES (7, 'John', 'Smith');
INSERT INTO vets VALUES (8, 'Sophie', 'Dubois');
INSERT INTO vets VALUES (9, 'Akira', 'Tanaka');
INSERT INTO vets VALUES (10, 'Elena', 'Petrova');
INSERT INTO specialties VALUES (1, 'radiology');
INSERT INTO specialties VALUES (2, 'surgery');
INSERT INTO specialties VALUES (3, 'dentistry');
INSERT INTO vet_specialties VALUES (2, 1);
INSERT INTO vet_specialties VALUES (3, 2);
INSERT INTO vet_specialties VALUES (3, 3);
INSERT INTO vet_specialties VALUES (4, 2);
INSERT INTO vet_specialties VALUES (5, 1);
INSERT INTO types VALUES (1, 'Cat');
INSERT INTO types VALUES (2, 'Dog');
INSERT INTO types VALUES (3, 'Lizard');
INSERT INTO types VALUES (4, 'Snake');
INSERT INTO types VALUES (5, 'Bird');
INSERT INTO types VALUES (6, 'Hamster');
INSERT INTO owners VALUES (1, 'George', 'Franklin', '110 W. Liberty St.', 'Madison', '6085551023');
INSERT INTO owners VALUES (2, 'Betty', 'Davis', '638 Cardinal Ave.', 'Sun Prairie', '6085551749');
INSERT INTO owners VALUES (3, 'Eduardo', 'Rodriquez', '2693 Commerce St.', 'McFarland', '6085558763');
INSERT INTO owners VALUES (4, 'Harold', 'Davis', '563 Friendly St.', 'Windsor', '6085553198');
INSERT INTO owners VALUES (5, 'Peter', 'McTavish', '2387 S. Fair Way', 'Madison', '6085552765');
INSERT INTO owners VALUES (6, 'Jean', 'Coleman', '105 N. Lake St.', 'Monona', '6085552654');
INSERT INTO owners VALUES (7, 'Jeff', 'Black', '1450 Oak Blvd.', 'Monona', '6085555387');
INSERT INTO owners VALUES (8, 'Maria', 'Escobito', '345 Maple St.', 'Madison', '6085557683');
INSERT INTO owners VALUES (9, 'David', 'Schroeder', '2749 Blackhawk Trail', 'Madison', '6085559435');
INSERT INTO owners VALUES (10, 'Carlos', 'Estaban', '2335 Independence La.', 'Waunakee', '6085555487');
INSERT INTO owners VALUES (11, 'John', 'Smith', '123 Main Street', 'New York', '+1 (555) 123-4567');
INSERT INTO owners VALUES (12, 'Sophie', 'Dubois', '456 Rue de la Paix', 'Paris', '+33 6 12 34 56 78');
INSERT INTO owners VALUES (13, 'Akira', 'Tanaka', '789 Sakura Avenue', 'Tokyo', '+81 90 1234 5678');
INSERT INTO owners VALUES (14, 'Carlos', 'Rodriguez', '202 Avenida de Mayo', 'Buenos Aires', '+54 9 11 2345-6789');
INSERT INTO owners VALUES (15, 'Anita', 'Müller', '303 Hauptstraße', 'Berlin', '+49 30 12345678');
INSERT INTO owners VALUES (16, 'Ravi', 'Patel', '404 MG Road', 'Mumbai', '+91 98765 43210');
INSERT INTO owners VALUES (17, 'Maria', 'da Silva', '505 Rua Augusta', 'São Paulo', '+55 11 98765-4321');
INSERT INTO owners VALUES (18, 'Hans', 'Johansson', '606 Drottninggatan', 'Stockholm', '+46 70 123 45 67');
INSERT INTO owners VALUES (19, 'Xi', 'Chen', '707 Nanjing Road', 'Shanghai', '+86 136 1234 5678');
INSERT INTO owners VALUES (20, 'Alice', 'Johnson', '808 Park Avenue', 'Los Angeles', '+1 (555) 234-5678');
INSERT INTO owners VALUES (21, 'François', 'Dupont', '909 Champs-Élysées', 'Paris', '+33 6 23 45 67 89');
INSERT INTO owners VALUES (22, 'Yuki', 'Kato', '101 Ueno Park', 'Tokyo', '+81 90 2345 6789');
INSERT INTO owners VALUES (23, 'Isabella', 'Gomez', '303 Tango Street', 'Buenos Aires', '+54 9 11 3456-7890');
INSERT INTO owners VALUES (24, 'Lukas', 'Schmidt', '404 Brandenburger Tor', 'Berlin', '+49 30 23456789');
INSERT INTO owners VALUES (25, 'Aarav', 'Sharma', '505 Bollywood Lane', 'Mumbai', '+91 98765 54321');
INSERT INTO owners VALUES (26, 'Camila', 'Santos', '606 Copacabana Beach', 'Rio de Janeiro', '+55 21 98765-4321');
INSERT INTO owners VALUES (27, 'Elsa', 'Larsson', '707 Abba Street', 'Stockholm', '+46 70 234 56 78');
INSERT INTO owners VALUES (28, 'Lei', 'Wang', '808 Forbidden City', 'Beijing', '+86 136 2345 6789');
INSERT INTO owners VALUES (29, 'Olivia', 'Miller', '909 Ocean Drive', 'Miami', '+1 (555) 345-6789');
INSERT INTO owners VALUES (30, 'Antoine', 'Dufresne', '101 Montmartre Avenue', 'Paris', '+33 6 34 56 78 90');
INSERT INTO owners VALUES (31, 'Takashi', 'Yamamoto', '202 Ginza Street', 'Tokyo', '+81 90 3456 7890');
INSERT INTO owners VALUES (32, 'Sofia', 'Ivanova', '303 Nevsky Prospect', 'St. Petersburg', '+7 495 345-67-89');
INSERT INTO owners VALUES (33, 'Diego', 'Lopez', '404 Tango Avenue', 'Buenos Aires', '+54 9 11 4567-8901');
INSERT INTO owners VALUES (34, 'Lena', 'Müller', '505 Oktoberfest Platz', 'Munich', '+49 30 34567890');
INSERT INTO owners VALUES (35, 'Amit', 'Kumar', '606 Bollywood Boulevard', 'Mumbai', '+91 98765 65432');
INSERT INTO owners VALUES (36, 'Giovanna', 'Silva', '707 Samba Street', 'Rio de Janeiro', '+55 21 98765-5432');
INSERT INTO owners VALUES (37, 'Emil', 'Eriksson', '808 Viking Road', 'Gothenburg', '+46 70 345 67 89');
INSERT INTO owners VALUES (38, 'Wei', 'Zhang', '909 Great Wall Street', 'Beijing', '+86 136 3456 7890');
INSERT INTO owners VALUES (39, 'Emma', 'Williams', '101 Broadway', 'New York', '+1 (555) 456-7890');
INSERT INTO owners VALUES (40, 'Lucien', 'Martin', '202 Louvre Lane', 'Paris', '+33 6 45 67 89 01');
INSERT INTO owners VALUES (41, 'Aiko', 'Takahashi', '303 Mt. Fuji View', 'Tokyo', '+81 90 4567 8901');
INSERT INTO owners VALUES (42, 'Mateo', 'Garcia', '505 Tango Terrace', 'Buenos Aires', '+54 9 11 5678-9012');
INSERT INTO owners VALUES (43, 'Lotte', 'Schneider', '606 Black Forest Street', 'Freiburg', '+49 30 45678901');
INSERT INTO owners VALUES (44, 'Arjun', 'Singh', '707 Bollywood Drive', 'Mumbai', '+91 98765 76543');
INSERT INTO owners VALUES (45, 'Juliana', 'Rodrigues', '808 Ipanema Beach', 'Rio de Janeiro', '+55 21 98765-6543');
INSERT INTO owners VALUES (46, 'Oskar', 'Lindgren', '909 Fika Lane', 'Stockholm', '+46 70 456 78 90');
INSERT INTO owners VALUES (47, 'Jing', 'Li', '101 Forbidden Palace Avenue', 'Beijing', '+86 136 4567 8901');
INSERT INTO owners VALUES (48, 'Liam', 'Anderson', '202 Golden Gate Street', 'San Francisco', '+1 (555) 567-8901');
INSERT INTO owners VALUES (49, 'Isabelle', 'Leclerc', '303 Seine River View', 'Paris', '+33 6 56 78 90 12');
INSERT INTO owners VALUES (50, 'Yoshiro', 'Suzuki', '404 Asakusa Street', 'Tokyo', '+81 90 5678 9012');
INSERT INTO owners VALUES (51, 'Polina', 'Petrovich', '505 Hermitage Plaza', 'St. Petersburg', '+7 495 567-89-01');
INSERT INTO owners VALUES (52, 'Mariana', 'Fernandez', '606 Tango Square', 'Buenos Aires', '+54 9 11 6789-0123');
INSERT INTO owners VALUES (53, 'Matteo', 'Weber', '707 Alpine Avenue', 'Munich', '+49 30 56789012');
INSERT INTO owners VALUES (54, 'Anaya', 'Singh', '808 Gateway Street', 'Mumbai', '+91 98765 87654');
INSERT INTO owners VALUES (55, 'Luca', 'Carvalho', '909 Carnival Road', 'Rio de Janeiro', '+55 21 98765-7654');
INSERT INTO owners VALUES (56, 'Hugo', 'Nordström', '101 Ice Hotel Lane', 'Kiruna', '+46 70 567 89 01');
INSERT INTO owners VALUES (57, 'Mei', 'Liu', '202 Great Wall Lane', 'Beijing', '+86 136 5678 9012');
INSERT INTO pets VALUES (1, 'Leo', '2010-09-07', 1, 1);
INSERT INTO pets VALUES (2, 'Basil', '2012-08-06', 6, 2);
INSERT INTO pets VALUES (3, 'Rosy', '2011-04-17', 2, 3);
INSERT INTO pets VALUES (4, 'Jewel', '2010-03-07', 2, 3);
INSERT INTO pets VALUES (5, 'Iggy', '2010-11-30', 3, 4);
INSERT INTO pets VALUES (6, 'George', '2010-01-20', 4, 5);
INSERT INTO pets VALUES (7, 'Samantha', '2012-09-04', 1, 6);
INSERT INTO pets VALUES (8, 'Max', '2012-09-04', 1, 6);
INSERT INTO pets VALUES (9, 'Lucky', '2011-08-06', 5, 7);
INSERT INTO pets VALUES (10, 'Mulligan', '2007-02-24', 2, 8);
INSERT INTO pets VALUES (11, 'Freddy', '2010-03-09', 5, 9);
INSERT INTO pets VALUES (12, 'Lucky', '2010-06-24', 2, 10);
INSERT INTO pets VALUES (13, 'Sly', '2012-06-08', 1, 10);
INSERT INTO pets VALUES (14, 'Bella', '1992-06-20', 1, 11);
INSERT INTO pets VALUES (15, 'Luna', '2002-10-29', 2, 12);
INSERT INTO pets VALUES (16, 'Charlie', '2017-08-13', 3, 13);
INSERT INTO pets VALUES (17, 'Lucy', '2016-09-29', 4, 14);
INSERT INTO pets VALUES (18, 'Cooper', '1984-02-27', 5, 15);
INSERT INTO pets VALUES (19, 'Max', '1975-01-25', 6, 16);
INSERT INTO pets VALUES (20, 'Bailey', '2007-10-03', 1, 17);
INSERT INTO pets VALUES (21, 'Daisy', '1993-01-16', 2, 18);
INSERT INTO pets VALUES (22, 'Sadie', '2020-08-05', 3, 19);
INSERT INTO pets VALUES (23, 'Lola', '2017-08-03', 4, 20);
INSERT INTO pets VALUES (24, 'Buddy', '2015-06-21', 5, 21);
INSERT INTO pets VALUES (25, 'Molly', '2001-03-10', 6, 22);
INSERT INTO pets VALUES (26, 'Stella', '2008-03-27', 1, 23);
INSERT INTO pets VALUES (27, 'Tucker', '2009-11-22', 2, 24);
INSERT INTO pets VALUES (28, 'Bear', '1973-01-02', 3, 25);
INSERT INTO pets VALUES (29, 'Zoey', '2015-10-04', 4, 26);
INSERT INTO pets VALUES (30, 'Duke', '1993-06-25', 5, 27);
INSERT INTO pets VALUES (31, 'Harley', '1991-09-28', 6, 28);
INSERT INTO pets VALUES (32, 'Maggie', '2001-09-25', 1, 29);
INSERT INTO pets VALUES (33, 'Jax', '1980-08-18', 2, 30);
INSERT INTO pets VALUES (34, 'Bentley', '1993-02-01', 3, 31);
INSERT INTO pets VALUES (35, 'Milo', '1990-07-21', 4, 32);
INSERT INTO pets VALUES (36, 'Oliver', '1992-11-21', 5, 33);
INSERT INTO pets VALUES (37, 'Riley', '2013-03-09', 6, 34);
INSERT INTO pets VALUES (38, 'Rocky', '1978-07-27', 1, 35);
INSERT INTO pets VALUES (39, 'Penny', '1998-02-05', 2, 36);
INSERT INTO pets VALUES (40, 'Sophie', '1995-03-15', 3, 37);
INSERT INTO pets VALUES (41, 'Chloe', '2003-07-11', 4, 38);
INSERT INTO pets VALUES (42, 'Jack', '2006-03-22', 5, 39);
INSERT INTO pets VALUES (43, 'Lily', '2002-01-30', 6, 40);
INSERT INTO pets VALUES (44, 'Nala', '1983-02-13', 1, 41);
INSERT INTO pets VALUES (45, 'Piper', '2017-09-04', 2, 42);
INSERT INTO pets VALUES (46, 'Zeus', '1974-03-01', 3, 43);
INSERT INTO pets VALUES (47, 'Ellie', '2000-04-21', 4, 44);
INSERT INTO pets VALUES (48, 'Winston', '2007-02-06', 5, 45);
INSERT INTO pets VALUES (49, 'Toby', '2008-12-11', 6, 46);
INSERT INTO pets VALUES (50, 'Loki', '2011-01-22', 1, 47);
INSERT INTO pets VALUES (51, 'Murphy', '1992-06-12', 2, 48);
INSERT INTO pets VALUES (52, 'Roxy', '1985-01-15', 3, 49);
INSERT INTO pets VALUES (53, 'Coco', '1977-06-20', 4, 50);
INSERT INTO pets VALUES (54, 'Rosie', '2004-09-30', 5, 51);
INSERT INTO pets VALUES (55, 'Teddy', '2017-03-11', 6, 52);
INSERT INTO pets VALUES (56, 'Ruby', '2001-02-14', 1, 53);
INSERT INTO pets VALUES (57, 'Gracie', '1993-02-20', 2, 54);
INSERT INTO pets VALUES (58, 'Leo', '1987-02-03', 3, 55);
INSERT INTO pets VALUES (59, 'Finn', '2005-03-07', 4, 56);
INSERT INTO pets VALUES (60, 'Scout', '1975-10-19', 5, 57);
INSERT INTO pets VALUES (61, 'Dexter', '1983-04-25', 6, 11);
INSERT INTO pets VALUES (62, 'Ollie', '1997-10-20', 1, 12);
INSERT INTO pets VALUES (63, 'Koda', '1993-01-24', 2, 13);
INSERT INTO pets VALUES (64, 'Diesel', '1993-04-19', 3, 14);
INSERT INTO pets VALUES (65, 'Moose', '2012-10-14', 4, 15);
INSERT INTO pets VALUES (66, 'Mia', '2016-11-24', 5, 16);
INSERT INTO pets VALUES (67, 'Marley', '1978-02-18', 6, 17);
INSERT INTO pets VALUES (68, 'Gus', '2001-06-30', 1, 18);
INSERT INTO pets VALUES (69, 'Hank', '2015-10-14', 2, 19);
INSERT INTO pets VALUES (70, 'Willow', '2006-09-02', 3, 20);
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (1, 7, 4, '2013-01-01', 'rabies shot');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (2, 8, NULL, '2013-01-02', 'rabies shot');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (3, 8, 4, '2013-01-03', 'neutered');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (4, 7, NULL, '2013-01-04', 'spayed');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (5, 14, 7, '2022-01-15', 'Vaccination Checkup');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (6, 15, 8, '2022-03-27', 'Teeth Cleaning');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (7, 16, 9, '2022-05-10', 'Orthopedic X-rays');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (8, 17, 10, '2022-07-18', 'Blood Tests');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (9, 18, 7, '2022-09-05', 'Abdominal Ultrasound');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (10, 19, 8, '2022-11-11', 'Heartworm Test');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (11, 20, 9, '2023-01-02', 'Dental Checkup');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (12, 21, 10, '2023-03-14', 'Eye Examination');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (13, 22, 7, '2023-05-26', 'Fecal Analysis');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (14, 23, 8, '2023-08-01', 'Skin Biopsy');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (15, 24, 9, '2023-10-09', 'Spaying/Neutering');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (16, 25, 10, '2023-12-20', 'Microchipping');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (17, 26, 7, '2024-02-01', 'Allergy Testing');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (18, 27, 8, '2024-04-12', 'Joint Aspiration');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (19, 28, 9, '2024-06-25', 'Ear Examination');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (20, 29, 10, '2024-08-08', 'Blood Pressure Measurement');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (21, 30, 7, '2024-10-19', 'Cancer Screening');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (22, 31, 8, '2024-12-03', 'Glaucoma Testing');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (23, 32, 9, '2022-02-18', 'Flea and Tick Prevention');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (24, 33, 10, '2022-04-30', 'Deworming');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (25, 34, 7, '2022-06-15', 'CT Scan');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (26, 35, 8, '2022-08-23', 'MRI');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (27, 36, 9, '2022-10-05', 'EKG');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (28, 37, 10, '2022-12-11', 'Nutritional Counseling');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (29, 38, 7, '2023-02-22', 'Joint Aspiration');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (30, 39, 8, '2023-04-06', 'Cancer Screening');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (31, 40, 9, '2023-06-18', 'Glaucoma Testing');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (32, 41, 10, '2023-08-30', 'Blood Clotting Profile');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (33, 42, 7, '2023-11-06', 'Orthopedic Examination');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (34, 43, 8, '2024-01-19', 'Fecal Analysis');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (35, 44, 9, '2024-03-02', 'Heartworm Test');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (36, 45, 10, '2024-05-15', 'Skin Biopsy');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (37, 46, 7, '2024-07-27', 'Spaying/Neutering');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (38, 47, 8, '2024-10-02', 'Orthopedic Examination');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (39, 48, 9, '2024-12-14', 'Dental Checkup');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (40, 49, 10, '2022-01-27', 'Ear Examination');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (41, 50, 7, '2022-04-09', 'Blood Pressure Measurement');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (42, 51, 8, '2022-06-22', 'Allergy Testing');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (43, 52, 9, '2022-08-05', 'CT Scan');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (44, 53, 10, '2022-10-17', 'MRI');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (45, 54, 7, '2022-12-28', 'EKG');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (46, 55, 8, '2023-03-10', 'Nutritional Counseling');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (47, 56, 9, '2023-05-23', 'Joint Aspiration');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (48, 57, 10, '2023-08-01', 'Cancer Screening');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (49, 58, 7, '2023-10-13', 'Glaucoma Testing');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (50, 59, 8, '2023-12-24', 'Blood Clotting Profile');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (51, 60, 9, '2024-02-03', 'Orthopedic Examination');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (52, 61, 10, '2024-04-16', 'Fecal Analysis');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (53, 62, 7, '2024-06-29', 'Heartworm Test');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (54, 63, 8, '2024-09-11', 'Skin Biopsy');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (55, 64, 9, '2024-11-23', 'Spaying/Neutering');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (56, 65, 10, '2022-02-21', 'Microchipping');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (57, 66, 7, '2022-05-06', 'Allergy Testing');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (58, 67, 8, '2022-07-18', 'Joint Aspiration');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (59, 68, 9, '2022-09-29', 'Ear Examination');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (60, 69, 10, '2022-12-11', 'Blood Pressure Measurement');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (61, 70, 7, '2023-02-01', 'CT Scan');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (62, 14, 8, '2023-04-15', 'MRI');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (63, 15, 9, '2023-06-27', 'EKG');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (64, 16, 10, '2023-09-10', 'Nutritional Counseling');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (65, 17, 7, '2023-11-22', 'Joint Aspiration');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (66, 18, 8, '2024-02-06', 'Cancer Screening');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (67, 19, 9, '2024-05-19', 'Glaucoma Testing');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (68, 20, 10, '2024-07-31', 'Blood Clotting Profile');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (69, 21, 7, '2024-10-11', 'Orthopedic Examination');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (70, 22, 8, '2022-02-27', 'Dental Checkup');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (71, 23, 9, '2022-05-11', 'Fecal Analysis');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (72, 24, 10, '2022-07-24', 'Heartworm Test');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (73, 25, 7, '2022-10-05', 'Skin Biopsy');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (74, 26, 8, '2022-12-16', 'Spaying/Neutering');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (75, 27, 9, '2023-02-26', 'Ear Examination');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (76, 28, 10, '2023-05-09', 'Blood Pressure Measurement');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (77, 29, 7, '2023-07-22', 'Allergy Testing');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (78, 30, 8, '2023-10-03', 'CT Scan');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (79, 31, 9, '2023-12-15', 'MRI');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (80, 32, 10, '2024-02-26', 'EKG');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (81, 33, 7, '2024-05-09', 'Nutritional Counseling');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (82, 34, 8, '2024-07-22', 'Joint Aspiration');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (83, 35, 9, '2024-10-03', 'Cancer Screening');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (84, 36, 10, '2024-12-15', 'Glaucoma Testing');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (85, 37, 7, '2022-04-02', 'Blood Clotting Profile');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (86, 38, 8, '2022-06-15', 'Orthopedic Examination');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (87, 39, 9, '2022-08-28', 'Dental Checkup');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (88, 40, 10, '2022-11-09', 'Fecal Analysis');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (89, 41, 7, '2023-01-21', 'Heartworm Test');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (90, 42, 8, '2023-04-05', 'Skin Biopsy');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (91, 43, 9, '2023-06-17', 'Spaying/Neutering');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (92, 44, 10, '2023-08-30', 'Ear Examination');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (93, 45, 7, '2023-11-11', 'Blood Pressure Measurement');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (94, 46, 8, '2024-02-03', 'Allergy Testing');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (95, 47, 9, '2024-04-18', 'CT Scan');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (96, 48, 10, '2024-07-01', 'MRI');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (97, 49, 7, '2024-09-14', 'EKG');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (98, 50, 8, '2024-11-26', 'Nutritional Counseling');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (99, 51, 9, '2022-01-30', 'Joint Aspiration');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (100, 52, 10, '2022-04-14', 'Cancer Screening');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (101, 53, 7, '2022-06-26', 'Glaucoma Testing');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (102, 54, 8, '2022-09-08', 'Blood Clotting Profile');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (103, 55, 9, '2022-11-21', 'Orthopedic Examination');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (104, 56, 10, '2023-02-02', 'Dental Checkup');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (105, 57, 7, '2023-04-16', 'Fecal Analysis');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (106, 58, 8, '2023-06-29', 'Heartworm Test');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (107, 59, 9, '2023-09-10', 'Skin Biopsy');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (108, 60, 10, '2023-11-23', 'Spaying/Neutering');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (109, 61, 7, '2024-02-05', 'Ear Examination');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (110, 62, 8, '2024-04-18', 'Blood Pressure Measurement');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (111, 63, 9, '2024-06-29', 'Allergy Testing');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (112, 64, 10, '2024-09-11', 'CT Scan');
INSERT INTO visits (id, pet_id, vet_id, visit_date, description) VALUES (113, 65, 7, '2024-11-23', 'MRI');
ALTER SEQUENCE roles_id_seq RESTART WITH 200;
ALTER SEQUENCE vets_id_seq RESTART WITH 200;
ALTER SEQUENCE specialties_id_seq RESTART WITH 200;
ALTER SEQUENCE types_id_seq RESTART WITH 200;
ALTER SEQUENCE owners_id_seq RESTART WITH 200;
ALTER SEQUENCE pets_id_seq RESTART WITH 200;
ALTER SEQUENCE visits_id_seq RESTART WITH 200;
================================================
FILE: backend/src/main/resources/graphql/petclinic.graphqls
================================================
# This file was generated. Do not edit manually.
schema {
query: Query
mutation: Mutation
subscription: Subscription
}
"Interface that describes a Person, i.e. a Vet or an Owner"
interface Person {
firstName: String!
id: Int!
lastName: String!
}
union AddVetPayload = AddVetErrorPayload | AddVetSuccessPayload
type AddOwnerPayload {
owner: Owner!
}
type AddPetPayload {
pet: Pet!
}
"Return Value of the addSpecialty Mutation"
type AddSpecialtyPayload {
"The new Specialty including the assigned Id"
specialty: Specialty!
}
type AddVetErrorPayload {
error: String!
}
type AddVetSuccessPayload {
vet: Vet
}
type AddVisitPayload {
visit: Visit!
}
"""
For motivation of how the Mutation look see:
https://dev-blog.apollodata.com/designing-graphql-mutations-e09de826ed97
"""
type Mutation {
" Add a new Owner"
addOwner(input: AddOwnerInput!): AddOwnerPayload!
" Add a new Pet"
addPet(input: AddPetInput!): AddPetPayload!
" Add a Specialty"
addSpecialty(input: AddSpecialtyInput!): AddSpecialtyPayload!
" Add a new Veterinary (only allowed for users having Role ROLE_MANAGER)"
addVet(input: AddVetInput!): AddVetPayload!
" Add a Visit"
addVisit(input: AddVisitInput!): AddVisitPayload!
removeSpecialty(input: RemoveSpecialtyInput!): RemoveSpecialtyPayload!
" Change an existing owner"
updateOwner(input: UpdateOwnerInput!): UpdateOwnerPayload!
updatePet(input: UpdatePetInput!): UpdatePetPayload!
" Update (rename) a Specialty"
updateSpecialty(input: UpdateSpecialtyInput!): UpdateSpecialtyPayload!
}
" An Owner is someone who owns a Pet"
type Owner implements Person {
address: String!
city: String!
firstName: String!
id: Int!
lastName: String!
" A list of Pets this Owner owns"
pets: [Pet!]!
telephone: String!
}
"""
A pet that might or might not have been seen in this petclinic for
one or more visits
"""
type Pet {
birthDate: Date!
id: Int!
name: String!
owner: Owner!
type: PetType!
" All visits to our PetClinic of this Pet"
visits: VisitConnection!
}
" The type (species) of a Pet"
type PetType {
id: Int!
name: String!
}
type OwnerConnection {
edges: [OwnerEdge]!
pageInfo: PageInfo!
}
type OwnerEdge {
node: Owner!
cursor: String!
}
type VetConnection {
edges: [VetEdge]!
pageInfo: PageInfo!
}
type VetEdge {
node: Vet!
cursor: String!
}
type PageInfo {
hasPreviousPage: Boolean!
hasNextPage: Boolean!
startCursor: String
endCursor: String
}
" The Query type provides all entry points to the PetClinic GraphQL schema"
type Query {
me: User!
" Return the Owner with the specified id"
owner(id: Int!): Owner!
# Note: OwnerConnection and all required types (Edge and PageInfo) could be
# added by Spring for GraphQL at runtime to the schema.
# Disadvantage is, that tooling has problems (Code Generator, IntelliJ plug-in)
# so I deceided to hand code the types instead.
# Nevertheless there is no need forJava classes for the Connection and dependent types,
# because Spring for GraphQL does the mapping for us.
#
# Note: first, after, last and before are automatically processed by Spring for GraphQL
# and are passed with a ScrollSubrange object to the QueryMapping function
#
#
"""
Find a list of owners according to the specified position, filter and order
Note that you either have to specify first _or_ last
"""
owners(first:Int, after:String, last:Int, before:String,
"Use a filter to narrow your search results"
filter: OwnerFilter,
order: [OwnerOrder!]): OwnerConnection!
# owners(filter: OwnerFilter, orders: [OwnerOrder!], page: Int, size: Int): OwnerSearchResult!
" Return the Pet with the specified id"
pet(id: Int!): Pet
" Return a List of all pets that have been registered in the PetClinic"
pets: [Pet!]!
" Return all known PetTypes"
pettypes: [PetType!]!
" Returns 'pong', can be used to verify GraphQL API is working"
ping: String!
specialties: [Specialty!]!
" Return the specified Vet or null if undefined"
vet(id: Int!): Vet
" Return all known veterinaries"
vets(first:Int, after:String, last:Int, before:String): VetConnection!
}
type RemoveSpecialtyPayload {
specialties: [Specialty!]!
}
" Specialty of a Vetenarian"
type Specialty {
id: Int!
name: String!
}
type Subscription {
onNewVisit: Visit!
}
type UpdateOwnerPayload {
owner: Owner!
}
type UpdatePetPayload {
pet: Pet!
}
" Return value of the UpdateSpecialty Mutation"
type UpdateSpecialtyPayload {
" The updated Specialty"
specialty: Specialty!
}
type User {
fullname: String!
username: String!
}
" A Vetenerian"
type Vet implements Person {
" The Vetenarian's first name"
firstName: String!
id: Int!
" The Vetenarian's last name"
lastName: String!
" What is this Vet specialized in?"
specialties: [Specialty!]!
" All of this Vet's visits"
visits: VisitConnection!
}
" A Visit of a Pet in our PetClinic"
type Visit {
" When did this Visit happen?"
date: Date!
" What did the Vet do during the Visit?"
description: String!
id: Int!
pet: Pet!
" Optional: which veterinary has done this treatment?"
treatingVet: Vet
}
type VisitConnection {
" total number of visits this VisitConnection represents"
totalCount: Int!
" the actual visits (might be an empty list)"
visits: [Visit!]!
}
" The input for types of query orders"
enum OrderField {
address
city
firstName
id
lastName
telephone
}
" The input for types of query orders"
enum OrderDirection {
ASC
DESC
}
"A Type representing a date (without time, only a day)"
scalar Date
input AddOwnerInput {
address: String!
city: String!
firstName: String!
lastName: String!
telephone: String!
}
" The Input for AddPet mutation"
input AddPetInput {
birthDate: Date!
name: String!
ownerId: Int!
typeId: Int!
}
" The input value for the addSpecialty Mutation"
input AddSpecialtyInput {
name: String!
}
input AddVetInput {
firstName: String!
lastName: String!
specialtyIds: [Int!]!
}
input AddVisitInput {
date: Date!
description: String!
petId: Int!
" Optional: specifiy the vet that should lead this visit"
vetId: Int
}
" The input for owners query by a filter"
input OwnerFilter {
address: String
city: String
firstName: String
lastName: String
telephone: String
}
" The input for owners query by order"
input OwnerOrder {
field: OrderField!
direction: OrderDirection = ASC
}
input RemoveSpecialtyInput {
specialtyId: Int!
}
input UpdateOwnerInput {
address: String
city: String
firstName: String
lastName: String
ownerId: Int!
telephone: String
}
input UpdatePetInput {
birthDate: Date
name: String
petId: Int!
typeId: Int
}
"""
The input value for the updateSpecialty Mutation
Takes the id of the specialty that should be updated and it's new Name
"""
input UpdateSpecialtyInput {
" The new name of the Specialty"
name: String!
" The id of the specialty that should be updated"
specialtyId: Int!
}
================================================
FILE: backend/src/main/resources/keys/private_key.pem
================================================
-----BEGIN PRIVATE KEY-----
MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQCml29+AGtlMg4w
Ml4egtS3lmYpNn8ClK4gEdTPT5UkEqKTCwxPdQi+AwwU0NWbmumdr0rJc9ky+TRX
wl73BOesDDkhOOPVZR67thKcoYADNdqCkf9j0PYUA32hkrrEUYosEZSwmzcmR5LR
GlHbPCRl1rDCih69YfGhOJPdApILymW5olCZB+L3eEncJeCZIcCqxERW9JTGEnJZ
ZroY0iZphJXvLjGs6l9tXaJvERcrT7ZntKQslieuoHrg9zgI20GKtYs3v1wv/Ljc
1LoM75qQn6KFz61Ea5vrOuzG3QiemqvqZevNlhJmKtWy319RkXdXgFPTpzxDSVUh
vzctcfkoXtRQD2u6E5n53OsOJKnoEzodle4ymDXDcn06yWOgU7an3jxiOqA+Hva2
hb4U3gX2OAsB2567zwwo22lx3RS9FosuUCyV35D3AJHjy6XX9qkudqV5Ly/gJg0f
03uQvBzLPQu+JRCYfVY0yGxxM35XmTSgTEKg5W7QSDrzr0UDobPp0Er2ywFQ3z5l
bk8Z4Qw5nXJ7CUmZaZXz+cyPwJyHebGqBwXF+PBdcAD11ohkUS5/6om7J+icmjvu
f/dQdOy4MTHsE81dmh9/D5/o64zXjLam+OtWRkoRFrbscWoclbYzZ0Pb0J3lcvUt
14lQNDBtcOb8D6nGy6egD/YQde9cAwIDAQABAoICAE6pGLL1PcCVpw9o6PodKpXZ
RTnWiphMXf+0i7iryi8zQWKPB+wIxez6gVze0s3bks2q9HQ06GziMK3zkGWxAjdB
ukQOmb2sNpvJt/YPZ+OcLSYUC/Q0uczvbQW6w8do/QYb8wqE78B6cT+c3uPW/RS9
D8976lHgCnjmvyLPUOiSVAAYPVhU2f2h5bY2iFumDVRUwjQQ3qK8GRRPpjWMHSkb
urQqKriMHi0E1mr9NeR0ihtjt1V6PRh+nCbXdLTx2nvFhwv2pm/eM+fJ5mOvS1tY
lSP70MOK0B99PkoUGjrRq7VNFM+JOfzV4vvH7zkTp7dAV9SLla/r02/Q2xvxQgTj
wwLenhjEPgyRp2R9y9XNYuxOEBgi9PBFeSyGe7hv+oImFCIZP5A0FNLPqJZ6Yjr3
yt4uS9RFCf9De+1khwl6RfRBv88vZDmS5SDiRpkJTTrRgm9wche85KCSR6hS8Qdl
Ny5KvOVIM6S0B9qT5vr+3HkY9SmAe++kT58bIQAyvBMwzIkz0x6zFPGM5fYTTveX
UvtmxIiTVs0KJqQyil19p2lcoOxpBLXZ82M73U3Xm3x69QCZGTuguw/sEtw1CJrc
VjJHPMMqK65wIwJgwuv8UF+uQ+J5yGAllgq985APWuOFwDDsnSmmTjAZTiVFxT8m
CkAzR0HMeHZ5Li9JPE25AoIBAQDWJvFI4KiyzfrtKdnzabAvOoNuhSKn407nLB15
fisPBua8CLIf3cFM+2JO/vzY35uj0yjTqLpqkyJag4GuaUmayUXV02M3GCjH8rsl
mX+P8y7yBy1doNGV+CFGEnmN3VpRmXM2LiSCbwX5/8JAqHlWK1wTmJdFtLWAiIUA
ViwAui2DaphbSKE3pC0mAFTRBcYda32i+cBxxpJRhWyjOhENT0fBo2lnFrUjKDzy
klwlXXG0UUXRK8ViEPLMz/5mkXTowdy62Z4HjT2btfldmDnaguaZ/RpZHxrTpjm7
Qu4CW9r2gDQqPBDz+O67GZOYQ+9Lff3vJmLi1LeA3wR0Zkz3AoIBAQDHJUDp/gGV
KBTP56vBu0l1yHErwBLEgk+pMb6IvH37Y/d/SNLDoC9fr3GpK/ZEfyJMoJB6UKMN
HEK5n3BdW4cx3rnY0HdvnkPK2mj1I9IecCRgETi1pGYnnF2bYZtkAmsmzpALV1z/
YzNGvRsf/eBD4mjmLK9poL1FbqZ8K6kput8hLH6hhUqic5KY56AdQuBIxNfgZs0y
a1pFKjAeNyvLeNYBoMuwjsHQ7Vx3HtPFuFG9D+8SRhqzUYl8N1NyYCDJPm07MdtU
AX6D8VPMFvETOuyIoPoi1ZZ9Hyw0gAf1iMPMgMn7wZF9wQkA1ipBtqmmbbKonvI2
DlccTN+veSJVAoIBAEQTMwZIrDfStJ5pfGgdQ61vu1IJrl+SKYXhBymUytlHB1fk
p8LrekQfcTvNYNEMG+yy9jp6W2//f58oSLQJsiUrMDDtto9P9b7B0W39Yoh+9IBp
ealWsukqbGFbBBrtr4Va8z3Y4zA3XL4A6F4ncBLNS8LK8eNts3i9bRITUn+Ur10k
KHR0HROT8+otlsivPjAh+FkzbVJ9ngueD0+/6KXDevr6GEp19HTNmLo/fl0+XCPG
5hu8/0zSOGyU/bjbKj/HSIR5IvwhkOELss5m0pU8oVN4GsUT1zJKl/WILCLB0lQj
ovF+EKGNk04Urk9r4Qitb2hzWmHi3sZvnnnl/zcCggEAE/R4r7nDINYWV8roHA6P
St0d8ftaJhTEtLiGVh9FJHac60U50V5wwM7Mvd3o3G482p7QO2FvJTYqvXzrfn9Y
abfeuYoSHb4nHuGJ2N6RBHnKO1Iec50Ym2mAu7wpHPldEVNrfadwayrejX0PhcIj
wcmjJ0VdAmGX9agjyJd7aPIPv7w8qCS6GNMp4mZ7VdNItCH9W8ARWbcGIZ4bmjt/
CPF/yEP7hSKY6z2NoWYWZF6W2jIJi7Q4orVN6IOGuhRF1MSLn33cc2t+6Ou6sN2v
pHSoFPzEc88hOEJyZIRbx8+/hvN0yeRYlthL9aiALXuHPmUJnPnoXWBMfEp7s5KY
zQKCAQEAuBqP0rJ4bdaCdnR9adJDe7ifjiq1EVo40rMfwm4HP91JoCqQJqZIiRnU
zc8GTLvXyYH12TOyNfLXfA5pl310Obk3ytJSCh6UDiQRFEzMstR5J0CAiUo5DZzR
0PDSzVl2JHM+kIYoc27t/f7z44m+E5k9Gp74PHkn1zf32VTsAuReF0I1wRIkJe86
T0Q4H7UyPIAfM/pvw01rVoIbQrFG/54bj0s2kQu4IOeKqo39MCmwc8taUvU/LuvL
NEAE2WsJyrVom6jJeee7fke+QrVgoM16vZG98ObTptqUkLeeGocpclJFJqbFSVL0
KyiIFYXpGT1XeTyWb9yDdzUUc0gXsQ==
-----END PRIVATE KEY-----
================================================
FILE: backend/src/main/resources/keys/public_key.pem
================================================
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAppdvfgBrZTIOMDJeHoLU
t5ZmKTZ/ApSuIBHUz0+VJBKikwsMT3UIvgMMFNDVm5rpna9KyXPZMvk0V8Je9wTn
rAw5ITjj1WUeu7YSnKGAAzXagpH/Y9D2FAN9oZK6xFGKLBGUsJs3JkeS0RpR2zwk
ZdawwooevWHxoTiT3QKSC8pluaJQmQfi93hJ3CXgmSHAqsREVvSUxhJyWWa6GNIm
aYSV7y4xrOpfbV2ibxEXK0+2Z7SkLJYnrqB64Pc4CNtBirWLN79cL/y43NS6DO+a
kJ+ihc+tRGub6zrsxt0Inpqr6mXrzZYSZirVst9fUZF3V4BT06c8Q0lVIb83LXH5
KF7UUA9ruhOZ+dzrDiSp6BM6HZXuMpg1w3J9OsljoFO2p948YjqgPh72toW+FN4F
9jgLAdueu88MKNtpcd0UvRaLLlAsld+Q9wCR48ul1/apLnaleS8v4CYNH9N7kLwc
yz0LviUQmH1WNMhscTN+V5k0oExCoOVu0Eg6869FA6Gz6dBK9ssBUN8+ZW5PGeEM
OZ1yewlJmWmV8/nMj8Cch3mxqgcFxfjwXXAA9daIZFEuf+qJuyfonJo77n/3UHTs
uDEx7BPNXZoffw+f6OuM14y2pvjrVkZKERa27HFqHJW2M2dD29Cd5XL1LdeJUDQw
bXDm/A+pxsunoA/2EHXvXAMCAwEAAQ==
-----END PUBLIC KEY-----
================================================
FILE: backend/src/main/resources/readme-graphiql.md
================================================
# Custom GraphiQL build
Inside `graphiql` is a custom graphiql build that is built from `petclinic-graphiql` and then copied
into `graphiql/`.
In a real project you maybe would not add the built version to source control but to add it to `classes/...` during
the build process.
Here I added the built graphiql code to Git because I don't want to force every to setup the JavaScript-based build for the
GraphiQL frontend. If you don't care about the JavaScript-parts of this example project (frontend/graphiql) you can just
run the backend and use(the customized) GraphiQL anyway.
================================================
FILE: backend/src/main/resources/testdata/owners.csv
================================================
FirstName,LastName,Street,City,PhoneNumber
John,Smith,123 Main Street,New York,+1 (555) 123-4567
Sophie,Dubois,456 Rue de la Paix,Paris,+33 6 12 34 56 78
Akira,Tanaka,789 Sakura Avenue,Tokyo,+81 90 1234 5678
Carlos,Rodriguez,202 Avenida de Mayo,Buenos Aires,+54 9 11 2345-6789
Anita,Müller,303 Hauptstraße,Berlin,+49 30 12345678
Ravi,Patel,404 MG Road,Mumbai,+91 98765 43210
Maria,da Silva,505 Rua Augusta,São Paulo,+55 11 98765-4321
Hans,Johansson,606 Drottninggatan,Stockholm,+46 70 123 45 67
Xi,Chen,707 Nanjing Road,Shanghai,+86 136 1234 5678
Alice,Johnson,808 Park Avenue,Los Angeles,+1 (555) 234-5678
François,Dupont,909 Champs-Élysées,Paris,+33 6 23 45 67 89
Yuki,Kato,101 Ueno Park,Tokyo,+81 90 2345 6789
Isabella,Gomez,303 Tango Street,Buenos Aires,+54 9 11 3456-7890
Lukas,Schmidt,404 Brandenburger Tor,Berlin,+49 30 23456789
Aarav,Sharma,505 Bollywood Lane,Mumbai,+91 98765 54321
Camila,Santos,606 Copacabana Beach,Rio de Janeiro,+55 21 98765-4321
Elsa,Larsson,707 Abba Street,Stockholm,+46 70 234 56 78
Lei,Wang,808 Forbidden City,Beijing,+86 136 2345 6789
Olivia,Miller,909 Ocean Drive,Miami,+1 (555) 345-6789
Antoine,Dufresne,101 Montmartre Avenue,Paris,+33 6 34 56 78 90
Takashi,Yamamoto,202 Ginza Street,Tokyo,+81 90 3456 7890
Sofia,Ivanova,303 Nevsky Prospect,St. Petersburg,+7 495 345-67-89
Diego,Lopez,404 Tango Avenue,Buenos Aires,+54 9 11 4567-8901
Lena,Müller,505 Oktoberfest Platz,Munich,+49 30 34567890
Amit,Kumar,606 Bollywood Boulevard,Mumbai,+91 98765 65432
Giovanna,Silva,707 Samba Street,Rio de Janeiro,+55 21 98765-5432
Emil,Eriksson,808 Viking Road,Gothenburg,+46 70 345 67 89
Wei,Zhang,909 Great Wall Street,Beijing,+86 136 3456 7890
Emma,Williams,101 Broadway,New York,+1 (555) 456-7890
Lucien,Martin,202 Louvre Lane,Paris,+33 6 45 67 89 01
Aiko,Takahashi,303 Mt. Fuji View,Tokyo,+81 90 4567 8901
Mateo,Garcia,505 Tango Terrace,Buenos Aires,+54 9 11 5678-9012
Lotte,Schneider,606 Black Forest Street,Freiburg,+49 30 45678901
Arjun,Singh,707 Bollywood Drive,Mumbai,+91 98765 76543
Juliana,Rodrigues,808 Ipanema Beach,Rio de Janeiro,+55 21 98765-6543
Oskar,Lindgren,909 Fika Lane,Stockholm,+46 70 456 78 90
Jing,Li,101 Forbidden Palace Avenue,Beijing,+86 136 4567 8901
Liam,Anderson,202 Golden Gate Street,San Francisco,+1 (555) 567-8901
Isabelle,Leclerc,303 Seine River View,Paris,+33 6 56 78 90 12
Yoshiro,Suzuki,404 Asakusa Street,Tokyo,+81 90 5678 9012
Polina,Petrovich,505 Hermitage Plaza,St. Petersburg,+7 495 567-89-01
Mariana,Fernandez,606 Tango Square,Buenos Aires,+54 9 11 6789-0123
Matteo,Weber,707 Alpine Avenue,Munich,+49 30 56789012
Anaya,Singh,808 Gateway Street,Mumbai,+91 98765 87654
Luca,Carvalho,909 Carnival Road,Rio de Janeiro,+55 21 98765-7654
Hugo,Nordström,101 Ice Hotel Lane,Kiruna,+46 70 567 89 01
Mei,Liu,202 Great Wall Lane,Beijing,+86 136 5678 9012
================================================
FILE: backend/src/main/resources/testdata/pets.csv
================================================
birthdate,name
1992-06-20,Bella
2002-10-29,Luna
2017-08-13,Charlie
2016-09-29,Lucy
1984-02-27,Cooper
1975-01-25,Max
2007-10-03,Bailey
1993-01-16,Daisy
2020-08-05,Sadie
2017-08-03,Lola
2015-06-21,Buddy
2001-03-10,Molly
2008-03-27,Stella
2009-11-22,Tucker
1973-01-02,Bear
2015-10-04,Zoey
1993-06-25,Duke
1991-09-28,Harley
2001-09-25,Maggie
1980-08-18,Jax
1993-02-01,Bentley
1990-07-21,Milo
1992-11-21,Oliver
2013-03-09,Riley
1978-07-27,Rocky
1998-02-05,Penny
1995-03-15,Sophie
2003-07-11,Chloe
2006-03-22,Jack
2002-01-30,Lily
1983-02-13,Nala
2017-09-04,Piper
1974-03-01,Zeus
2000-04-21,Ellie
2007-02-06,Winston
2008-12-11,Toby
2011-01-22,Loki
1992-06-12,Murphy
1985-01-15,Roxy
1977-06-20,Coco
2004-09-30,Rosie
2017-03-11,Teddy
2001-02-14,Ruby
1993-02-20,Gracie
1987-02-03,Leo
2005-03-07,Finn
1975-10-19,Scout
1983-04-25,Dexter
1997-10-20,Ollie
1993-01-24,Koda
1993-04-19,Diesel
2012-10-14,Moose
2016-11-24,Mia
1978-02-18,Marley
2001-06-30,Gus
2015-10-14,Hank
2006-09-02,Willow
================================================
FILE: backend/src/main/resources/testdata/visits.csv
================================================
Date,Treatment
2022-01-15,Vaccination Checkup
2022-03-27,Teeth Cleaning
2022-05-10,Orthopedic X-rays
2022-07-18,Blood Tests
2022-09-05,Abdominal Ultrasound
2022-11-11,Heartworm Test
2023-01-02,Dental Checkup
2023-03-14,Eye Examination
2023-05-26,Fecal Analysis
2023-08-01,Skin Biopsy
2023-10-09,Spaying/Neutering
2023-12-20,Microchipping
2024-02-01,Allergy Testing
2024-04-12,Joint Aspiration
2024-06-25,Ear Examination
2024-08-08,Blood Pressure Measurement
2024-10-19,Cancer Screening
2024-12-03,Glaucoma Testing
2022-02-18,Flea and Tick Prevention
2022-04-30,Deworming
2022-06-15,CT Scan
2022-08-23,MRI
2022-10-05,EKG
2022-12-11,Nutritional Counseling
2023-02-22,Joint Aspiration
2023-04-06,Cancer Screening
2023-06-18,Glaucoma Testing
2023-08-30,Blood Clotting Profile
2023-11-06,Orthopedic Examination
2024-01-19,Fecal Analysis
2024-03-02,Heartworm Test
2024-05-15,Skin Biopsy
2024-07-27,Spaying/Neutering
2024-10-02,Orthopedic Examination
2024-12-14,Dental Checkup
2022-01-27,Ear Examination
2022-04-09,Blood Pressure Measurement
2022-06-22,Allergy Testing
2022-08-05,CT Scan
2022-10-17,MRI
2022-12-28,EKG
2023-03-10,Nutritional Counseling
2023-05-23,Joint Aspiration
2023-08-01,Cancer Screening
2023-10-13,Glaucoma Testing
2023-12-24,Blood Clotting Profile
2024-02-03,Orthopedic Examination
2024-04-16,Fecal Analysis
2024-06-29,Heartworm Test
2024-09-11,Skin Biopsy
2024-11-23,Spaying/Neutering
2022-02-21,Microchipping
2022-05-06,Allergy Testing
2022-07-18,Joint Aspiration
2022-09-29,Ear Examination
2022-12-11,Blood Pressure Measurement
2023-02-01,CT Scan
2023-04-15,MRI
2023-06-27,EKG
2023-09-10,Nutritional Counseling
2023-11-22,Joint Aspiration
2024-02-06,Cancer Screening
2024-05-19,Glaucoma Testing
2024-07-31,Blood Clotting Profile
2024-10-11,Orthopedic Examination
2022-02-27,Dental Checkup
2022-05-11,Fecal Analysis
2022-07-24,Heartworm Test
2022-10-05,Skin Biopsy
2022-12-16,Spaying/Neutering
2023-02-26,Ear Examination
2023-05-09,Blood Pressure Measurement
2023-07-22,Allergy Testing
2023-10-03,CT Scan
2023-12-15,MRI
2024-02-26,EKG
2024-05-09,Nutritional Counseling
2024-07-22,Joint Aspiration
2024-10-03,Cancer Screening
2024-12-15,Glaucoma Testing
2022-04-02,Blood Clotting Profile
2022-06-15,Orthopedic Examination
2022-08-28,Dental Checkup
2022-11-09,Fecal Analysis
2023-01-21,Heartworm Test
2023-04-05,Skin Biopsy
2023-06-17,Spaying/Neutering
2023-08-30,Ear Examination
2023-11-11,Blood Pressure Measurement
2024-02-03,Allergy Testing
2024-04-18,CT Scan
2024-07-01,MRI
2024-09-14,EKG
2024-11-26,Nutritional Counseling
2022-01-30,Joint Aspiration
2022-04-14,Cancer Screening
2022-06-26,Glaucoma Testing
2022-09-08,Blood Clotting Profile
2022-11-21,Orthopedic Examination
2023-02-02,Dental Checkup
2023-04-16,Fecal Analysis
2023-06-29,Heartworm Test
2023-09-10,Skin Biopsy
2023-11-23,Spaying/Neutering
2024-02-05,Ear Examination
2024-04-18,Blood Pressure Measurement
2024-06-29,Allergy Testing
2024-09-11,CT Scan
2024-11-23,MRI
================================================
FILE: backend/src/main/resources/ui/graphiql/assets/Range-52ddcb6a.js
================================================
class h{constructor(t,r){this.containsPosition=e=>this.start.line===e.line?this.start.character<=e.character:this.end.line===e.line?this.end.character>=e.character:this.start.line<=e.line&&this.end.line>=e.line,this.start=t,this.end=r}setStart(t,r){this.start=new s(t,r)}setEnd(t,r){this.end=new s(t,r)}}class s{constructor(t,r){this.lessThanOrEqualTo=e=>this.linej(t,"name",{value:n,configurable:!0});function V(t,n){const e={schema:t,type:null,parentType:null,inputType:null,directiveDef:null,fieldDef:null,argDef:null,argDefs:null,objectFieldDefs:null};return b(n,a=>{var u,p;switch(a.kind){case"Query":case"ShortQuery":e.type=t.getQueryType();break;case"Mutation":e.type=t.getMutationType();break;case"Subscription":e.type=t.getSubscriptionType();break;case"InlineFragment":case"FragmentDefinition":a.type&&(e.type=t.getType(a.type));break;case"Field":case"AliasedField":e.fieldDef=e.type&&a.name?c(t,e.parentType,a.name):null,e.type=(u=e.fieldDef)===null||u===void 0?void 0:u.type;break;case"SelectionSet":e.parentType=e.type?l(e.type):null;break;case"Directive":e.directiveDef=a.name?t.getDirective(a.name):null;break;case"Arguments":const s=a.prevState?a.prevState.kind==="Field"?e.fieldDef:a.prevState.kind==="Directive"?e.directiveDef:a.prevState.kind==="AliasedField"?a.prevState.name&&c(t,e.parentType,a.prevState.name):null:null;e.argDefs=s?s.args:null;break;case"Argument":if(e.argDef=null,e.argDefs){for(let i=0;ii.value===a.name):null;break;case"ListValue":const d=e.inputType?F(e.inputType):null;e.inputType=d instanceof h?d.ofType:null;break;case"ObjectValue":const m=e.inputType?l(e.inputType):null;e.objectFieldDefs=m instanceof k?m.getFields():null;break;case"ObjectField":const o=a.name&&e.objectFieldDefs?e.objectFieldDefs[a.name]:null;e.inputType=o==null?void 0:o.type;break;case"NamedType":e.type=a.name?t.getType(a.name):null;break}}),e}r(V,"getTypeInfo");function c(t,n,e){if(e===g.name&&t.getQueryType()===n)return g;if(e===D.name&&t.getQueryType()===n)return D;if(e===T.name&&Q(n))return T;if(n&&n.getFields)return n.getFields()[e]}r(c,"getFieldDef");function v(t,n){for(let e=0;eS(k,"name",{value:T,configurable:!0});function A(k,T){for(var r=0;rs[e]})}}}return Object.freeze(Object.defineProperty(k,Symbol.toStringTag,{value:"Module"}))}b(A,"_mergeNamespaces");var w={exports:{}};(function(k,T){(function(r){r(I())})(function(r){function s(e){return function(i,o){var t=o.line,u=i.getLine(t);function c(a){for(var l,p=o.ch,v=0;;){var h=p<=0?-1:u.lastIndexOf(a[0],p-1);if(h==-1){if(v==1)break;v=1,p=u.length;continue}if(v==1&&he.lastLine())return null;var g=e.getTokenAt(r.Pos(n,1));if(/\S/.test(g.string)||(g=e.getTokenAt(r.Pos(n,g.end+1))),g.type!="keyword"||g.string!="import")return null;for(var y=n,a=Math.min(e.lastLine(),n+10);y<=a;++y){var l=e.getLine(y),p=l.indexOf(";");if(p!=-1)return{startCh:g.end,end:r.Pos(y,p)}}}b(o,"hasImport");var t=i.line,u=o(t),c;if(!u||o(t-1)||(c=o(t-2))&&c.end.line==t-1)return null;for(var d=u.end;;){var f=o(d.line+1);if(f==null)break;d=f.end}return{from:e.clipPos(r.Pos(t,u.startCh+1)),to:d}}),r.registerHelper("fold","include",function(e,i){function o(f){if(fe.lastLine())return null;var n=e.getTokenAt(r.Pos(f,1));if(/\S/.test(n.string)||(n=e.getTokenAt(r.Pos(f,n.end+1))),n.type=="meta"&&n.string.slice(0,8)=="#include")return n.start+8}b(o,"hasInclude");var t=i.line,u=o(t);if(u==null||o(t-1)!=null)return null;for(var c=t;;){var d=o(c+1);if(d==null)break;++c}return{from:r.Pos(t,u+1),to:e.clipPos(r.Pos(c))}})})})();var H=w.exports;const M=L(H),D=A({__proto__:null,default:M},[H]);export{D as b};
================================================
FILE: backend/src/main/resources/ui/graphiql/assets/closebrackets.es-e969742b.js
================================================
import{c as N,h as q}from"./codemirror.es2-5884f31a.js";var F=Object.defineProperty,f=(P,k)=>F(P,"name",{value:k,configurable:!0});function z(P,k){for(var t=0;tv[o]})}}}return Object.freeze(Object.defineProperty(P,Symbol.toStringTag,{value:"Module"}))}f(z,"_mergeNamespaces");var J={exports:{}};(function(P,k){(function(t){t(N())})(function(t){var v={pairs:`()[]{}''""`,closeBefore:`)]}'":;>`,triples:"",explode:"[]{}"},o=t.Pos;t.defineOption("autoCloseBrackets",!1,function(e,n,r){r&&r!=t.Init&&(e.removeKeyMap(B),e.state.closeBrackets=null),n&&(T(h(n,"pairs")),e.state.closeBrackets=n,e.addKeyMap(B))});function h(e,n){return n=="pairs"&&typeof e=="string"?e:typeof e=="object"&&e[n]!=null?e[n]:v[n]}f(h,"getOption");var B={Backspace:E,Enter:M};function T(e){for(var n=0;n=0;i--){var c=a[i].head;e.replaceRange("",o(c.line,c.ch-1),o(c.line,c.ch+1),"+delete")}}f(E,"handleBackspace");function M(e){var n=A(e),r=n&&h(n,"explode");if(!r||e.getOption("disableInput"))return t.Pass;for(var a=e.listSelections(),i=0;i0?{line:c.head.line,ch:c.head.ch+n}:{line:c.head.line-1};r.push({anchor:u,head:u})}e.setSelections(r,i)}f(S,"moveSel");function R(e){var n=t.cmpPos(e.anchor,e.head)>0;return{anchor:new o(e.anchor.line,e.anchor.ch+(n?-1:1)),head:new o(e.head.line,e.head.ch+(n?1:-1))}}f(R,"contractSelection");function I(e,n){var r=A(e);if(!r||e.getOption("disableInput"))return t.Pass;var a=h(r,"pairs"),i=a.indexOf(n);if(i==-1)return t.Pass;for(var l=h(r,"closeBefore"),c=h(r,"triples"),u=a.charAt(i+1)==n,b=e.listSelections(),C=i%2==0,y,_=0;_=0&&e.getRange(s,o(s.line,s.ch+3))==n+n+n?d="skipThree":d="skip";else if(u&&s.ch>1&&c.indexOf(n)>=0&&e.getRange(o(s.line,s.ch-2),s)==n+n){if(s.ch>2&&/\bstring/.test(e.getTokenTypeAt(o(s.line,s.ch-2))))return t.Pass;d="addFour"}else if(u){var W=s.ch==0?" ":e.getRange(o(s.line,s.ch-1),s);if(!t.isWordChar(m)&&W!=n&&!t.isWordChar(W))d="both";else return t.Pass}else if(C&&(m.length===0||/\s/.test(m)||l.indexOf(m)>-1))d="both";else return t.Pass;if(!y)y=d;else if(y!=d)return t.Pass}var O=i%2?a.charAt(i-1):n,j=i%2?n:a.charAt(i+1);e.operation(function(){if(y=="skip")S(e,1);else if(y=="skipThree")S(e,3);else if(y=="surround"){for(var p=e.getSelections(),g=0;gu(e,"name",{value:n,configurable:!0});function c(e,n){for(var o=0;or[t]})}}}return Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}l(c,"_mergeNamespaces");var i=f();const p=s(i),b=c({__proto__:null,default:p},[i]);export{p as C,b as c};
================================================
FILE: backend/src/main/resources/ui/graphiql/assets/codemirror.es2-5884f31a.js
================================================
var su=Object.defineProperty,u=(Et,Nl)=>su(Et,"name",{value:Nl,configurable:!0}),uu=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function cu(Et){return Et&&Et.__esModule&&Object.prototype.hasOwnProperty.call(Et,"default")?Et.default:Et}u(cu,"getDefaultExportFromCjs");var Gs={exports:{}},Ks;function hu(){return Ks||(Ks=1,function(Et,Nl){(function(it,tr){Et.exports=tr()})(uu,function(){var it=navigator.userAgent,tr=navigator.platform,It=/gecko\/\d/i.test(it),Ol=/MSIE \d/.test(it),Dl=/Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(it),er=/Edge\/(\d+)/.exec(it),A=Ol||Dl||er,I=A&&(Ol?document.documentMode||6:+(er||Dl)[1]),ot=!er&&/WebKit\//.test(it),Vs=ot&&/Qt\/\d+\.\d+/.test(it),nr=!er&&/Chrome\//.test(it),kt=/Opera\//.test(it),rr=/Apple Computer/.test(navigator.vendor),js=/Mac OS X 1\d\D([8-9]|\d\d)\D/.test(it),Xs=/PhantomJS/.test(it),hn=rr&&(/Mobile\/\w+/.test(it)||navigator.maxTouchPoints>2),ir=/Android/.test(it),dn=hn||ir||/webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(it),xt=hn||/Mac/.test(tr),_s=/\bCrOS\b/.test(it),qs=/win/i.test(tr),he=kt&&it.match(/Version\/(\d*\.\d*)/);he&&(he=Number(he[1])),he&&he>=15&&(kt=!1,ot=!0);var Al=xt&&(Vs||kt&&(he==null||he<12.11)),gi=It||A&&I>=9;function de(t){return new RegExp("(^|\\s)"+t+"(?:$|\\s)\\s*")}u(de,"classTest");var fe=u(function(t,e){var r=t.className,n=de(e).exec(r);if(n){var i=r.slice(n.index+n[0].length);t.className=r.slice(0,n.index)+(i?n[1]+i:"")}},"rmClass");function Rt(t){for(var e=t.childNodes.length;e>0;--e)t.removeChild(t.firstChild);return t}u(Rt,"removeChildren");function gt(t,e){return Rt(t).appendChild(e)}u(gt,"removeChildrenAndAdd");function k(t,e,r,n){var i=document.createElement(t);if(r&&(i.className=r),n&&(i.style.cssText=n),typeof e=="string")i.appendChild(document.createTextNode(e));else if(e)for(var o=0;o=e)return l+(e-o);l+=a-o,l+=r-l%r,o=a+1}}u(yt,"countColumn");var Qt=u(function(){this.id=null,this.f=null,this.time=0,this.handler=lr(this.onTimeout,this)},"Delayed");Qt.prototype.onTimeout=function(t){t.id=0,t.time<=+new Date?t.f():setTimeout(t.handler,t.time-+new Date)},Qt.prototype.set=function(t,e){this.f=e;var r=+new Date+t;(!this.id||r=e)return n+Math.min(l,e-i);if(i+=o-n,i+=r-i%r,n=o+1,i>=e)return n}}u(sr,"findColumn");var ur=[""];function cr(t){for(;ur.length<=t;)ur.push(W(ur)+" ");return ur[t]}u(cr,"spaceStr");function W(t){return t[t.length-1]}u(W,"lst");function gn(t,e){for(var r=[],n=0;n""&&(t.toUpperCase()!=t.toLowerCase()||Ys.test(t))}u(hr,"isWordCharBasic");function mn(t,e){return e?e.source.indexOf("\\w")>-1&&hr(t)?!0:e.test(t):hr(t)}u(mn,"isWordChar");function bi(t){for(var e in t)if(t.hasOwnProperty(e)&&t[e])return!1;return!0}u(bi,"isEmpty");var Zs=/[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;function dr(t){return t.charCodeAt(0)>=768&&Zs.test(t)}u(dr,"isExtendingChar");function wi(t,e,r){for(;(r<0?e>0:er?-1:1;;){if(e==r)return e;var i=(e+r)/2,o=n<0?Math.ceil(i):Math.floor(i);if(o==e)return t(o)?e:r;t(o)?r=o:e=o+n}}u(Pe,"findFirst");function Fl(t,e,r,n){if(!t)return n(e,r,"ltr",0);for(var i=!1,o=0;oe||e==r&&l.to==e)&&(n(Math.max(l.from,e),Math.min(l.to,r),l.level==1?"rtl":"ltr",o),i=!0)}i||n(e,r,"ltr")}u(Fl,"iterateBidiSections");var vn=null;function Ee(t,e,r){var n;vn=null;for(var i=0;ie)return i;o.to==e&&(o.from!=o.to&&r=="before"?n=i:vn=i),o.from==e&&(o.from!=o.to&&r!="before"?n=i:vn=i)}return n??vn}u(Ee,"getBidiPartAt");var $s=function(){var t="bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN",e="nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111";function r(c){return c<=247?t.charAt(c):1424<=c&&c<=1524?"R":1536<=c&&c<=1785?e.charAt(c-1536):1774<=c&&c<=2220?"r":8192<=c&&c<=8203?"w":c==8204?"b":"L"}u(r,"charType");var n=/[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/,i=/[stwN]/,o=/[LRr]/,l=/[Lb1n]/,a=/[1n]/;function s(c,h,d){this.level=c,this.from=h,this.to=d}return u(s,"BidiSpan"),function(c,h){var d=h=="ltr"?"L":"R";if(c.length==0||h=="ltr"&&!n.test(c))return!1;for(var p=c.length,f=[],g=0;g-1&&(n[e]=i.slice(0,o).concat(i.slice(o+1)))}}}u(mt,"off");function U(t,e){var r=fr(t,e);if(r.length)for(var n=Array.prototype.slice.call(arguments,2),i=0;i0}u(bt,"hasHandler");function me(t){t.prototype.on=function(e,r){M(this,e,r)},t.prototype.off=function(e,r){mt(this,e,r)}}u(me,"eventMixin");function lt(t){t.preventDefault?t.preventDefault():t.returnValue=!1}u(lt,"e_preventDefault");function Ci(t){t.stopPropagation?t.stopPropagation():t.cancelBubble=!0}u(Ci,"e_stopPropagation");function pr(t){return t.defaultPrevented!=null?t.defaultPrevented:t.returnValue==!1}u(pr,"e_defaultPrevented");function Ie(t){lt(t),Ci(t)}u(Ie,"e_stop");function gr(t){return t.target||t.srcElement}u(gr,"e_target");function Si(t){var e=t.which;return e==null&&(t.button&1?e=1:t.button&2?e=3:t.button&4&&(e=2)),xt&&t.ctrlKey&&e==1&&(e=3),e}u(Si,"e_button");var Qs=function(){if(A&&I<9)return!1;var t=k("div");return"draggable"in t||"dragDrop"in t}(),Li;function El(t){if(Li==null){var e=k("span","");gt(t,k("span",[e,document.createTextNode("x")])),t.firstChild.offsetHeight!=0&&(Li=e.offsetWidth<=1&&e.offsetHeight>2&&!(A&&I<8))}var r=Li?k("span",""):k("span"," ",null,"display: inline-block; width: 1px; margin-right: -1px");return r.setAttribute("cm-text",""),r}u(El,"zeroWidthElement");var ki;function Il(t){if(ki!=null)return ki;var e=gt(t,document.createTextNode("AخA")),r=ge(e,0,1).getBoundingClientRect(),n=ge(e,1,2).getBoundingClientRect();return Rt(t),!r||r.left==r.right?!1:ki=n.right-r.right<3}u(Il,"hasBadBidiRects");var Ti=`
b`.split(/\n/).length!=3?function(t){for(var e=0,r=[],n=t.length;e<=n;){var i=t.indexOf(`
`,e);i==-1&&(i=t.length);var o=t.slice(e,t.charAt(i-1)=="\r"?i-1:i),l=o.indexOf("\r");l!=-1?(r.push(o.slice(0,l)),e+=l+1):(r.push(o),e=i+1)}return r}:function(t){return t.split(/\r\n?|\n/)},Js=window.getSelection?function(t){try{return t.selectionStart!=t.selectionEnd}catch{return!1}}:function(t){var e;try{e=t.ownerDocument.selection.createRange()}catch{}return!e||e.parentElement()!=t?!1:e.compareEndPoints("StartToEnd",e)!=0},tu=function(){var t=k("div");return"oncopy"in t?!0:(t.setAttribute("oncopy","return;"),typeof t.oncopy=="function")}(),Mi=null;function Rl(t){if(Mi!=null)return Mi;var e=gt(t,k("span","x")),r=e.getBoundingClientRect(),n=ge(e,0,1).getBoundingClientRect();return Mi=Math.abs(r.left-n.left)>1}u(Rl,"hasBadZoomedRects");var Ni={},Re={};function zl(t,e){arguments.length>2&&(e.dependencies=Array.prototype.slice.call(arguments,2)),Ni[t]=e}u(zl,"defineMode");function Bl(t,e){Re[t]=e}u(Bl,"defineMIME");function yn(t){if(typeof t=="string"&&Re.hasOwnProperty(t))t=Re[t];else if(t&&typeof t.name=="string"&&Re.hasOwnProperty(t.name)){var e=Re[t.name];typeof e=="string"&&(e={name:e}),t=yi(e,t),t.name=e.name}else{if(typeof t=="string"&&/^[\w\-]+\/[\w\-]+\+xml$/.test(t))return yn("application/xml");if(typeof t=="string"&&/^[\w\-]+\/[\w\-]+\+json$/.test(t))return yn("application/json")}return typeof t=="string"?{name:t}:t||{name:"null"}}u(yn,"resolveMode");function mr(t,e){e=yn(e);var r=Ni[e.name];if(!r)return mr(t,"text/plain");var n=r(t,e);if(ze.hasOwnProperty(e.name)){var i=ze[e.name];for(var o in i)i.hasOwnProperty(o)&&(n.hasOwnProperty(o)&&(n["_"+o]=n[o]),n[o]=i[o])}if(n.name=e.name,e.helperType&&(n.helperType=e.helperType),e.modeProps)for(var l in e.modeProps)n[l]=e.modeProps[l];return n}u(mr,"getMode");var ze={};function Ul(t,e){var r=ze.hasOwnProperty(t)?ze[t]:ze[t]={};$t(e,r)}u(Ul,"extendMode");function Jt(t,e){if(e===!0)return e;if(t.copyState)return t.copyState(e);var r={};for(var n in e){var i=e[n];i instanceof Array&&(i=i.concat([])),r[n]=i}return r}u(Jt,"copyState");function vr(t,e){for(var r;t.innerMode&&(r=t.innerMode(e),!(!r||r.mode==t));)e=r.state,t=r.mode;return r||{mode:t,state:e}}u(vr,"innerMode");function Oi(t,e,r){return t.startState?t.startState(e,r):!0}u(Oi,"startState");var K=u(function(t,e,r){this.pos=this.start=0,this.string=t,this.tabSize=e||8,this.lastColumnPos=this.lastColumnValue=0,this.lineStart=0,this.lineOracle=r},"StringStream");K.prototype.eol=function(){return this.pos>=this.string.length},K.prototype.sol=function(){return this.pos==this.lineStart},K.prototype.peek=function(){return this.string.charAt(this.pos)||void 0},K.prototype.next=function(){if(this.pose},K.prototype.eatSpace=function(){for(var t=this.pos;/[\s\u00a0]/.test(this.string.charAt(this.pos));)++this.pos;return this.pos>t},K.prototype.skipToEnd=function(){this.pos=this.string.length},K.prototype.skipTo=function(t){var e=this.string.indexOf(t,this.pos);if(e>-1)return this.pos=e,!0},K.prototype.backUp=function(t){this.pos-=t},K.prototype.column=function(){return this.lastColumnPos0?null:(o&&e!==!1&&(this.pos+=o[0].length),o)}},K.prototype.current=function(){return this.string.slice(this.start,this.pos)},K.prototype.hideFirstChars=function(t,e){this.lineStart+=t;try{return e()}finally{this.lineStart-=t}},K.prototype.lookAhead=function(t){var e=this.lineOracle;return e&&e.lookAhead(t)},K.prototype.baseToken=function(){var t=this.lineOracle;return t&&t.baseToken(this.pos)};function S(t,e){if(e-=t.first,e<0||e>=t.size)throw new Error("There is no line "+(e+t.first)+" in the document.");for(var r=t;!r.lines;)for(var n=0;;++n){var i=r.children[n],o=i.chunkSize();if(e=t.first&&er?v(r,S(t,r).text.length):Gl(e,S(t,e.line).text.length)}u(O,"clipPos");function Gl(t,e){var r=t.ch;return r==null||r>e?v(t.line,e):r<0?v(t.line,0):t}u(Gl,"clipToLen");function Ai(t,e){for(var r=[],n=0;nthis.maxLookAhead&&(this.maxLookAhead=t),e},Wt.prototype.baseToken=function(t){if(!this.baseTokens)return null;for(;this.baseTokens[this.baseTokenPos]<=t;)this.baseTokenPos+=2;var e=this.baseTokens[this.baseTokenPos+1];return{type:e&&e.replace(/( |^)overlay .*/,""),size:this.baseTokens[this.baseTokenPos]-t}},Wt.prototype.nextLine=function(){this.line++,this.maxLookAhead>0&&this.maxLookAhead--},Wt.fromSaved=function(t,e,r){return e instanceof Cr?new Wt(t,Jt(t.mode,e.state),r,e.lookAhead):new Wt(t,Jt(t.mode,e),r)},Wt.prototype.save=function(t){var e=t!==!1?Jt(this.doc.mode,this.state):this.state;return this.maxLookAhead>0?new Cr(e,this.maxLookAhead):e};function Wi(t,e,r,n){var i=[t.state.modeGen],o={};Ii(t,e.text,t.doc.mode,r,function(c,h){return i.push(c,h)},o,n);for(var l=r.state,a=u(function(c){r.baseTokens=i;var h=t.state.overlays[c],d=1,p=0;r.state=!0,Ii(t,e.text,h.mode,r,function(f,g){for(var m=d;pf&&i.splice(d,1,f,i[d+1],y),d+=2,p=Math.min(f,y)}if(g)if(h.opaque)i.splice(m,d-m,f,"overlay "+g),d=m+2;else for(;mt.options.maxHighlightLength&&Jt(t.doc.mode,n.state),o=Wi(t,e,n);i&&(n.state=i),e.stateAfter=n.save(!i),e.styles=o.styles,o.classes?e.styleClasses=o.classes:e.styleClasses&&(e.styleClasses=null),r===t.doc.highlightFrontier&&(t.doc.modeFrontier=Math.max(t.doc.modeFrontier,++t.doc.highlightFrontier))}return e.styles}u(Hi,"getLineStyles");function Ue(t,e,r){var n=t.doc,i=t.display;if(!n.mode.startState)return new Wt(n,!0,e);var o=Vl(t,e,r),l=o>n.first&&S(n,o-1).stateAfter,a=l?Wt.fromSaved(n,l,o):new Wt(n,Oi(n.mode),o);return n.iter(o,e,function(s){Sr(t,s.text,a);var c=a.line;s.stateAfter=c==e-1||c%5==0||c>=i.viewFrom&&ce.start)return o}throw new Error("Mode "+t.name+" failed to advance stream.")}u(Lr,"readToken");var Kl=u(function(t,e,r){this.start=t.start,this.end=t.pos,this.string=t.current(),this.type=e||null,this.state=r},"Token");function Pi(t,e,r,n){var i=t.doc,o=i.mode,l;e=O(i,e);var a=S(i,e.line),s=Ue(t,e.line,r),c=new K(a.text,t.options.tabSize,s),h;for(n&&(h=[]);(n||c.post.options.maxHighlightLength?(a=!1,l&&Sr(t,e,n,h.pos),h.pos=e.length,d=null):d=Ei(Lr(r,h,n.state,p),o),p){var f=p[0].name;f&&(d="m-"+(d?f+" "+d:f))}if(!a||c!=d){for(;sl;--a){if(a<=o.first)return o.first;var s=S(o,a-1),c=s.stateAfter;if(c&&(!r||a+(c instanceof Cr?c.lookAhead:0)<=o.modeFrontier))return a;var h=yt(s.text,null,t.options.tabSize);(i==null||n>h)&&(i=a-1,n=h)}return i}u(Vl,"findStartLine");function jl(t,e){if(t.modeFrontier=Math.min(t.modeFrontier,e),!(t.highlightFrontierr;n--){var i=S(t,n).stateAfter;if(i&&(!(i instanceof Cr)||n+i.lookAhead=e:o.to>e);(n||(n=[])).push(new xn(l,o.from,s?null:o.to))}}return n}u($l,"markedSpansBefore");function Ql(t,e,r){var n;if(t)for(var i=0;i=e:o.to>e);if(a||o.from==e&&l.type=="bookmark"&&(!r||o.marker.insertLeft)){var s=o.from==null||(l.inclusiveLeft?o.from<=e:o.from0&&a)for(var C=0;C0)){var h=[s,1],d=N(c.from,a.from),p=N(c.to,a.to);(d<0||!l.inclusiveLeft&&!d)&&h.push({from:c.from,to:a.from}),(p>0||!l.inclusiveRight&&!p)&&h.push({from:a.to,to:c.to}),i.splice.apply(i,h),s+=h.length-3}}return i}u(Jl,"removeReadOnlyRanges");function zi(t){var e=t.markedSpans;if(e){for(var r=0;re)&&(!n||Tr(n,o.marker)<0)&&(n=o.marker)}return n}u(ta,"collapsedSpanAround");function Ki(t,e,r,n,i){var o=S(t,e),l=Bt&&o.markedSpans;if(l)for(var a=0;a=0&&d<=0||h<=0&&d>=0)&&(h<=0&&(s.marker.inclusiveRight&&i.inclusiveLeft?N(c.to,r)>=0:N(c.to,r)>0)||h>=0&&(s.marker.inclusiveRight&&i.inclusiveLeft?N(c.from,n)<=0:N(c.from,n)<0)))return!0}}}u(Ki,"conflictingCollapsedRange");function Ct(t){for(var e;e=Gi(t);)t=e.find(-1,!0).line;return t}u(Ct,"visualLine");function ea(t){for(var e;e=Ln(t);)t=e.find(1,!0).line;return t}u(ea,"visualLineEnd");function na(t){for(var e,r;e=Ln(t);)t=e.find(1,!0).line,(r||(r=[])).push(t);return r}u(na,"visualLineContinued");function Mr(t,e){var r=S(t,e),n=Ct(r);return r==n?e:F(n)}u(Mr,"visualLineNo");function Vi(t,e){if(e>t.lastLine())return e;var r=S(t,e),n;if(!Ut(t,r))return e;for(;n=Ln(r);)r=n.find(1,!0).line;return F(r)+1}u(Vi,"visualLineEndNo");function Ut(t,e){var r=Bt&&e.markedSpans;if(r){for(var n=void 0,i=0;ie.maxLineLength&&(e.maxLineLength=i,e.maxLine=n)})}u(Or,"findMaxLine");var Ke=u(function(t,e,r){this.text=t,Bi(this,e),this.height=r?r(this):1},"Line");Ke.prototype.lineNo=function(){return F(this)},me(Ke);function ra(t,e,r,n){t.text=e,t.stateAfter&&(t.stateAfter=null),t.styles&&(t.styles=null),t.order!=null&&(t.order=null),zi(t),Bi(t,r);var i=n?n(t):1;i!=t.height&&Tt(t,i)}u(ra,"updateLine");function ia(t){t.parent=null,zi(t)}u(ia,"cleanUpLine");var eu={},nu={};function ji(t,e){if(!t||/^\s*$/.test(t))return null;var r=e.addModeClass?nu:eu;return r[t]||(r[t]=t.replace(/\S+/g,"cm-$&"))}u(ji,"interpretTokenStyle");function Xi(t,e){var r=pe("span",null,null,ot?"padding-right: .1px":null),n={pre:pe("pre",[r],"CodeMirror-line"),content:r,col:0,pos:0,cm:t,trailingSpace:!1,splitSpaces:t.getOption("lineWrapping")};e.measure={};for(var i=0;i<=(e.rest?e.rest.length:0);i++){var o=i?e.rest[i-1]:e.line,l=void 0;n.pos=0,n.addToken=la,Il(t.display.measure)&&(l=At(o,t.doc.direction))&&(n.addToken=sa(n.addToken,l)),n.map=[];var a=e!=t.display.externalMeasured&&F(o);ua(o,n,Hi(t,o,a)),o.styleClasses&&(o.styleClasses.bgClass&&(n.bgClass=or(o.styleClasses.bgClass,n.bgClass||"")),o.styleClasses.textClass&&(n.textClass=or(o.styleClasses.textClass,n.textClass||""))),n.map.length==0&&n.map.push(0,0,n.content.appendChild(El(t.display.measure))),i==0?(e.measure.map=n.map,e.measure.cache={}):((e.measure.maps||(e.measure.maps=[])).push(n.map),(e.measure.caches||(e.measure.caches=[])).push({}))}if(ot){var s=n.content.lastChild;(/\bcm-tab\b/.test(s.className)||s.querySelector&&s.querySelector(".cm-tab"))&&(n.content.className="cm-tab-wrap-hack")}return U(t,"renderLine",t,e.line,n.pre),n.pre.className&&(n.textClass=or(n.pre.className,n.textClass||"")),n}u(Xi,"buildLineContent");function oa(t){var e=k("span","•","cm-invalidchar");return e.title="\\u"+t.charCodeAt(0).toString(16),e.setAttribute("aria-label",e.title),e}u(oa,"defaultSpecialCharPlaceholder");function la(t,e,r,n,i,o,l){if(e){var a=t.splitSpaces?aa(e,t.trailingSpace):e,s=t.cm.state.specialChars,c=!1,h;if(!s.test(e))t.col+=e.length,h=document.createTextNode(a),t.map.push(t.pos,t.pos+e.length,h),A&&I<9&&(c=!0),t.pos+=e.length;else{h=document.createDocumentFragment();for(var d=0;;){s.lastIndex=d;var p=s.exec(e),f=p?p.index-d:e.length-d;if(f){var g=document.createTextNode(a.slice(d,d+f));A&&I<9?h.appendChild(k("span",[g])):h.appendChild(g),t.map.push(t.pos,t.pos+f,g),t.col+=f,t.pos+=f}if(!p)break;d+=f+1;var m=void 0;if(p[0]==" "){var y=t.cm.options.tabSize,b=y-t.col%y;m=h.appendChild(k("span",cr(b),"cm-tab")),m.setAttribute("role","presentation"),m.setAttribute("cm-text"," "),t.col+=b}else p[0]=="\r"||p[0]==`
`?(m=h.appendChild(k("span",p[0]=="\r"?"␍":"","cm-invalidchar")),m.setAttribute("cm-text",p[0]),t.col+=1):(m=t.cm.options.specialCharPlaceholder(p[0]),m.setAttribute("cm-text",p[0]),A&&I<9?h.appendChild(k("span",[m])):h.appendChild(m),t.col+=1);t.map.push(t.pos,t.pos+1,m),t.pos++}}if(t.trailingSpace=a.charCodeAt(e.length-1)==32,r||n||i||c||o||l){var x=r||"";n&&(x+=n),i&&(x+=i);var w=k("span",[h],x,o);if(l)for(var C in l)l.hasOwnProperty(C)&&C!="style"&&C!="class"&&w.setAttribute(C,l[C]);return t.content.appendChild(w)}t.content.appendChild(h)}}u(la,"buildToken");function aa(t,e){if(t.length>1&&!/ /.test(t))return t;for(var r=e,n="",i=0;ic&&d.from<=c));p++);if(d.to>=h)return t(r,n,i,o,l,a,s);t(r,n.slice(0,d.to-c),i,o,null,a,s),o=null,n=n.slice(d.to-c),c=d.to}}}u(sa,"buildTokenBadBidi");function _i(t,e,r,n){var i=!n&&r.widgetNode;i&&t.map.push(t.pos,t.pos+e,i),!n&&t.cm.display.input.needsContentAttribute&&(i||(i=t.content.appendChild(document.createElement("span"))),i.setAttribute("cm-marker",r.id)),i&&(t.cm.display.input.setUneditable(i),t.content.appendChild(i)),t.pos+=e,t.trailingSpace=!1}u(_i,"buildCollapsedSpan");function ua(t,e,r){var n=t.markedSpans,i=t.text,o=0;if(!n){for(var l=1;ls||D.collapsed&&L.to==s&&L.from==s)){if(L.to!=null&&L.to!=s&&f>L.to&&(f=L.to,m=""),D.className&&(g+=" "+D.className),D.css&&(p=(p?p+";":"")+D.css),D.startStyle&&L.from==s&&(y+=" "+D.startStyle),D.endStyle&&L.to==f&&(C||(C=[])).push(D.endStyle,L.to),D.title&&((x||(x={})).title=D.title),D.attributes)for(var E in D.attributes)(x||(x={}))[E]=D.attributes[E];D.collapsed&&(!b||Tr(b.marker,D)<0)&&(b=L)}else L.from>s&&f>L.from&&(f=L.from)}if(C)for(var $=0;$=a)break;for(var ht=Math.min(a,f);;){if(h){var dt=s+h.length;if(!b){var V=dt>ht?h.slice(0,ht-s):h;e.addToken(e,V,d?d+g:g,y,s+V.length==f?m:"",p,x)}if(dt>=ht){h=h.slice(ht-s),s=ht;break}s=dt,y=""}h=i.slice(o,o=r[c++]),d=ji(r[c++],e.cm.options)}}}u(ua,"insertLineContent");function qi(t,e,r){this.line=e,this.rest=na(e),this.size=this.rest?F(W(this.rest))-r+1:1,this.node=this.text=null,this.hidden=Ut(t,e)}u(qi,"LineView");function Tn(t,e,r){for(var n=[],i,o=e;o2&&o.push((s.bottom+c.top)/2-r.top)}}o.push(r.bottom-r.top)}}u(ba,"ensureLineHeights");function eo(t,e,r){if(t.line==e)return{map:t.measure.map,cache:t.measure.cache};if(t.rest){for(var n=0;nr)return{map:t.measure.maps[i],cache:t.measure.caches[i],before:!0}}}u(eo,"mapFromLineView");function wa(t,e){e=Ct(e);var r=F(e),n=t.display.externalMeasured=new qi(t.doc,e,r);n.lineN=r;var i=n.built=Xi(t,n);return n.text=i.pre,gt(t.display.lineMeasure,i.pre),n}u(wa,"updateExternalMeasurement");function no(t,e,r,n){return Nt(t,ve(t,e),r,n)}u(no,"measureChar");function Hr(t,e){if(e>=t.display.viewFrom&&e=r.lineN&&ee)&&(o=s-a,i=o-1,e>=s&&(l="right")),i!=null){if(n=t[c+2],a==s&&r==(n.insertLeft?"left":"right")&&(l=r),r=="left"&&i==0)for(;c&&t[c-2]==t[c-3]&&t[c-1].insertLeft;)n=t[(c-=3)+2],l="left";if(r=="right"&&i==s-a)for(;c=0&&(r=t[i]).left==r.right;i--);return r}u(Ca,"getUsefulRect");function Sa(t,e,r,n){var i=ro(e.map,r,n),o=i.node,l=i.start,a=i.end,s=i.collapse,c;if(o.nodeType==3){for(var h=0;h<4;h++){for(;l&&dr(e.line.text.charAt(i.coverStart+l));)--l;for(;i.coverStart+a0&&(s=n="right");var d;t.options.lineWrapping&&(d=o.getClientRects()).length>1?c=d[n=="right"?d.length-1:0]:c=o.getBoundingClientRect()}if(A&&I<9&&!l&&(!c||!c.left&&!c.right)){var p=o.parentNode.getClientRects()[0];p?c={left:p.left,right:p.left+we(t.display),top:p.top,bottom:p.bottom}:c=xa}for(var f=c.top-e.rect.top,g=c.bottom-e.rect.top,m=(f+g)/2,y=e.view.measure.heights,b=0;b=n.text.length?(s=n.text.length,c="before"):s<=0&&(s=0,c="after"),!a)return l(c=="before"?s-1:s,c=="before");function h(g,m,y){var b=a[m],x=b.level==1;return l(y?g-1:g,x!=y)}u(h,"getBidi");var d=Ee(a,s,c),p=vn,f=h(s,d,c=="before");return p!=null&&(f.other=h(s,p,c!="before")),f}u(St,"cursorCoords");function uo(t,e){var r=0;e=O(t.doc,e),t.options.lineWrapping||(r=we(t.display)*e.ch);var n=S(t.doc,e.line),i=Ht(n)+Nn(t.display);return{left:r,right:r,top:i,bottom:i+n.height}}u(uo,"estimateCoords");function Pr(t,e,r,n,i){var o=v(t,e,r);return o.xRel=i,n&&(o.outside=n),o}u(Pr,"PosWithInfo");function Er(t,e,r){var n=t.doc;if(r+=t.display.viewOffset,r<0)return Pr(n.first,0,null,-1,-1);var i=ee(n,r),o=n.first+n.size-1;if(i>o)return Pr(n.first+n.size-1,S(n,o).text.length,null,1,1);e<0&&(e=0);for(var l=S(n,i);;){var a=ka(t,l,i,e,r),s=ta(l,a.ch+(a.xRel>0||a.outside>0?1:0));if(!s)return a;var c=s.find(1);if(c.line==i)return c;l=S(n,i=c.line)}}u(Er,"coordsChar");function co(t,e,r,n){n-=Fr(e);var i=e.text.length,o=Pe(function(l){return Nt(t,r,l-1).bottom<=n},i,0);return i=Pe(function(l){return Nt(t,r,l).top>n},o,i),{begin:o,end:i}}u(co,"wrappedLineExtent");function ho(t,e,r,n){r||(r=ve(t,e));var i=On(t,e,Nt(t,r,n),"line").top;return co(t,e,r,i)}u(ho,"wrappedLineExtentChar");function Ir(t,e,r,n){return t.bottom<=r?!1:t.top>r?!0:(n?t.left:t.right)>e}u(Ir,"boxIsAfter");function ka(t,e,r,n,i){i-=Ht(e);var o=ve(t,e),l=Fr(e),a=0,s=e.text.length,c=!0,h=At(e,t.doc.direction);if(h){var d=(t.options.lineWrapping?Ma:Ta)(t,e,r,o,h,n,i);c=d.level!=1,a=c?d.from:d.to-1,s=c?d.to:d.from-1}var p=null,f=null,g=Pe(function(T){var L=Nt(t,o,T);return L.top+=l,L.bottom+=l,Ir(L,n,i,!1)?(L.top<=i&&L.left<=n&&(p=T,f=L),!0):!1},a,s),m,y,b=!1;if(f){var x=n-f.left=C.bottom?1:0}return g=wi(e.text,g,1),Pr(r,g,y,b,n-m)}u(ka,"coordsCharInner");function Ta(t,e,r,n,i,o,l){var a=Pe(function(d){var p=i[d],f=p.level!=1;return Ir(St(t,v(r,f?p.to:p.from,f?"before":"after"),"line",e,n),o,l,!0)},0,i.length-1),s=i[a];if(a>0){var c=s.level!=1,h=St(t,v(r,c?s.from:s.to,c?"after":"before"),"line",e,n);Ir(h,o,l,!0)&&h.top>l&&(s=i[a-1])}return s}u(Ta,"coordsBidiPart");function Ma(t,e,r,n,i,o,l){var a=co(t,e,n,l),s=a.begin,c=a.end;/\s/.test(e.text.charAt(c-1))&&c--;for(var h=null,d=null,p=0;p=c||f.to<=s)){var g=f.level!=1,m=Nt(t,n,g?Math.min(c,f.to)-1:Math.max(s,f.from)).right,y=my)&&(h=f,d=y)}}return h||(h=i[i.length-1]),h.fromc&&(h={from:h.from,to:c,level:h.level}),h}u(Ma,"coordsBidiPartWrapped");var ye;function be(t){if(t.cachedTextHeight!=null)return t.cachedTextHeight;if(ye==null){ye=k("pre",null,"CodeMirror-line-like");for(var e=0;e<49;++e)ye.appendChild(document.createTextNode("x")),ye.appendChild(k("br"));ye.appendChild(document.createTextNode("x"))}gt(t.measure,ye);var r=ye.offsetHeight/50;return r>3&&(t.cachedTextHeight=r),Rt(t.measure),r||1}u(be,"textHeight");function we(t){if(t.cachedCharWidth!=null)return t.cachedCharWidth;var e=k("span","xxxxxxxxxx"),r=k("pre",[e],"CodeMirror-line-like");gt(t.measure,r);var n=e.getBoundingClientRect(),i=(n.right-n.left)/10;return i>2&&(t.cachedCharWidth=i),i||10}u(we,"charWidth");function Rr(t){for(var e=t.display,r={},n={},i=e.gutters.clientLeft,o=e.gutters.firstChild,l=0;o;o=o.nextSibling,++l){var a=t.display.gutterSpecs[l].className;r[a]=o.offsetLeft+o.clientLeft+i,n[a]=o.clientWidth}return{fixedPos:zr(e),gutterTotalWidth:e.gutters.offsetWidth,gutterLeft:r,gutterWidth:n,wrapperWidth:e.wrapper.clientWidth}}u(Rr,"getDimensions");function zr(t){return t.scroller.getBoundingClientRect().left-t.sizer.getBoundingClientRect().left}u(zr,"compensateForHScroll");function fo(t){var e=be(t.display),r=t.options.lineWrapping,n=r&&Math.max(5,t.display.scroller.clientWidth/we(t.display)-3);return function(i){if(Ut(t.doc,i))return 0;var o=0;if(i.widgets)for(var l=0;l0&&(c=S(t.doc,s.line).text).length==s.ch){var h=yt(c,c.length,t.options.tabSize)-c.length;s=v(s.line,Math.max(0,Math.round((o-to(t.display).left)/we(t.display))-h))}return s}u(re,"posFromMouse");function ie(t,e){if(e>=t.display.viewTo||(e-=t.display.viewFrom,e<0))return null;for(var r=t.display.view,n=0;ne)&&(i.updateLineNumbers=e),t.curOp.viewChanged=!0,e>=i.viewTo)Bt&&Mr(t.doc,e)i.viewFrom?Kt(t):(i.viewFrom+=n,i.viewTo+=n);else if(e<=i.viewFrom&&r>=i.viewTo)Kt(t);else if(e<=i.viewFrom){var o=An(t,r,r+n,1);o?(i.view=i.view.slice(o.index),i.viewFrom=o.lineN,i.viewTo+=n):Kt(t)}else if(r>=i.viewTo){var l=An(t,e,e,-1);l?(i.view=i.view.slice(0,l.index),i.viewTo=l.lineN):Kt(t)}else{var a=An(t,e,e,-1),s=An(t,r,r+n,1);a&&s?(i.view=i.view.slice(0,a.index).concat(Tn(t,a.lineN,s.lineN)).concat(i.view.slice(s.index)),i.viewTo+=n):Kt(t)}var c=i.externalMeasured;c&&(r=i.lineN&&e=n.viewTo)){var o=n.view[ie(t,e)];if(o.node!=null){var l=o.changes||(o.changes=[]);J(l,r)==-1&&l.push(r)}}}u(Gt,"regLineChange");function Kt(t){t.display.viewFrom=t.display.viewTo=t.doc.first,t.display.view=[],t.display.viewOffset=0}u(Kt,"resetView");function An(t,e,r,n){var i=ie(t,e),o,l=t.display.view;if(!Bt||r==t.doc.first+t.doc.size)return{index:i,lineN:r};for(var a=t.display.viewFrom,s=0;s0){if(i==l.length-1)return null;o=a+l[i].size-e,i++}else o=a-e;e+=o,r+=o}for(;Mr(t.doc,r)!=r;){if(i==(n<0?0:l.length-1))return null;r+=n*l[i-(n<0?1:0)].size,i+=n}return{index:i,lineN:r}}u(An,"viewCuttingPoint");function Na(t,e,r){var n=t.display,i=n.view;i.length==0||e>=n.viewTo||r<=n.viewFrom?(n.view=Tn(t,e,r),n.viewFrom=e):(n.viewFrom>e?n.view=Tn(t,e,n.viewFrom).concat(n.view):n.viewFromr&&(n.view=n.view.slice(0,ie(t,r)))),n.viewTo=r}u(Na,"adjustView");function po(t){for(var e=t.display.view,r=0,n=0;n=t.display.viewTo||s.to().line0?l:t.defaultCharWidth())+"px"}if(n.other){var a=r.appendChild(k("div"," ","CodeMirror-cursor CodeMirror-secondarycursor"));a.style.display="",a.style.left=n.other.left+"px",a.style.top=n.other.top+"px",a.style.height=(n.other.bottom-n.other.top)*.85+"px"}}u(Ur,"drawSelectionCursor");function Wn(t,e){return t.top-e.top||t.left-e.left}u(Wn,"cmpCoords");function Oa(t,e,r){var n=t.display,i=t.doc,o=document.createDocumentFragment(),l=to(t.display),a=l.left,s=Math.max(n.sizerWidth,ne(t)-n.sizer.offsetLeft)-l.right,c=i.direction=="ltr";function h(w,C,T,L){C<0&&(C=0),C=Math.round(C),L=Math.round(L),o.appendChild(k("div",null,"CodeMirror-selected","position: absolute; left: "+w+`px;
top: `+C+"px; width: "+(T??s-w)+`px;
height: `+(L-C)+"px"))}u(h,"add");function d(w,C,T){var L=S(i,w),D=L.text.length,E,$;function z(V,ft){return Dn(t,v(w,V),"div",L,ft)}u(z,"coords");function ht(V,ft,et){var Z=ho(t,L,null,V),j=ft=="ltr"==(et=="after")?"left":"right",B=et=="after"?Z.begin:Z.end-(/\s/.test(L.text.charAt(Z.end-1))?2:1);return z(B,j)[j]}u(ht,"wrapX");var dt=At(L,i.direction);return Fl(dt,C||0,T??D,function(V,ft,et,Z){var j=et=="ltr",B=z(V,j?"left":"right"),pt=z(ft-1,j?"right":"left"),un=C==null&&V==0,ce=T==null&&ft==D,rt=Z==0,Pt=!dt||Z==dt.length-1;if(pt.top-B.top<=3){var Q=(c?un:ce)&&rt,Tl=(c?ce:un)&&Pt,Yt=Q?a:(j?B:pt).left,He=Tl?s:(j?pt:B).right;h(Yt,B.top,He-Yt,B.bottom)}else{var Fe,st,cn,Ml;j?(Fe=c&&un&&rt?a:B.left,st=c?s:ht(V,et,"before"),cn=c?a:ht(ft,et,"after"),Ml=c&&ce&&Pt?s:pt.right):(Fe=c?ht(V,et,"before"):a,st=!c&&un&&rt?s:B.right,cn=!c&&ce&&Pt?a:pt.left,Ml=c?ht(ft,et,"after"):s),h(Fe,B.top,st-Fe,B.bottom),B.bottom0?e.blinker=setInterval(function(){t.hasFocus()||xe(t),e.cursorDiv.style.visibility=(r=!r)?"":"hidden"},t.options.cursorBlinkRate):t.options.cursorBlinkRate<0&&(e.cursorDiv.style.visibility="hidden")}}u(Gr,"restartBlink");function mo(t){t.hasFocus()||(t.display.input.focus(),t.state.focused||Vr(t))}u(mo,"ensureFocus");function Kr(t){t.state.delayingBlurEvent=!0,setTimeout(function(){t.state.delayingBlurEvent&&(t.state.delayingBlurEvent=!1,t.state.focused&&xe(t))},100)}u(Kr,"delayBlurEvent");function Vr(t,e){t.state.delayingBlurEvent&&!t.state.draggingText&&(t.state.delayingBlurEvent=!1),t.options.readOnly!="nocursor"&&(t.state.focused||(U(t,"focus",t,e),t.state.focused=!0,Zt(t.display.wrapper,"CodeMirror-focused"),!t.curOp&&t.display.selForContextMenu!=t.doc.sel&&(t.display.input.reset(),ot&&setTimeout(function(){return t.display.input.reset(!0)},20)),t.display.input.receivedFocus()),Gr(t))}u(Vr,"onFocus");function xe(t,e){t.state.delayingBlurEvent||(t.state.focused&&(U(t,"blur",t,e),t.state.focused=!1,fe(t.display.wrapper,"CodeMirror-focused")),clearInterval(t.display.blinker),setTimeout(function(){t.state.focused||(t.display.shift=!1)},150))}u(xe,"onBlur");function Hn(t){for(var e=t.display,r=e.lineDiv.offsetTop,n=Math.max(0,e.scroller.getBoundingClientRect().top),i=e.lineDiv.getBoundingClientRect().top,o=0,l=0;l.005||f<-.005)&&(it.display.sizerWidth){var m=Math.ceil(h/we(t.display));m>t.display.maxLineLength&&(t.display.maxLineLength=m,t.display.maxLine=a.line,t.display.maxLineChanged=!0)}}}Math.abs(o)>2&&(e.scroller.scrollTop+=o)}u(Hn,"updateHeightsInViewport");function vo(t){if(t.widgets)for(var e=0;e=l&&(o=ee(e,Ht(S(e,s))-t.wrapper.clientHeight),l=s)}return{from:o,to:Math.max(l,o+1)}}u(Fn,"visibleLines");function Da(t,e){if(!X(t,"scrollCursorIntoView")){var r=t.display,n=r.sizer.getBoundingClientRect(),i=null;if(e.top+n.top<0?i=!0:e.bottom+n.top>(window.innerHeight||document.documentElement.clientHeight)&&(i=!1),i!=null&&!Xs){var o=k("div","",null,`position: absolute;
top: `+(e.top-r.viewOffset-Nn(t.display))+`px;
height: `+(e.bottom-e.top+Mt(t)+r.barHeight)+`px;
left: `+e.left+"px; width: "+Math.max(2,e.right-e.left)+"px;");t.display.lineSpace.appendChild(o),o.scrollIntoView(i),t.display.lineSpace.removeChild(o)}}}u(Da,"maybeScrollWindow");function Aa(t,e,r,n){n==null&&(n=0);var i;!t.options.lineWrapping&&e==r&&(r=e.sticky=="before"?v(e.line,e.ch+1,"before"):e,e=e.ch?v(e.line,e.sticky=="before"?e.ch-1:e.ch,"after"):e);for(var o=0;o<5;o++){var l=!1,a=St(t,e),s=!r||r==e?a:St(t,r);i={left:Math.min(a.left,s.left),top:Math.min(a.top,s.top)-n,right:Math.max(a.left,s.left),bottom:Math.max(a.bottom,s.bottom)+n};var c=jr(t,i),h=t.doc.scrollTop,d=t.doc.scrollLeft;if(c.scrollTop!=null&&(Ze(t,c.scrollTop),Math.abs(t.doc.scrollTop-h)>1&&(l=!0)),c.scrollLeft!=null&&(oe(t,c.scrollLeft),Math.abs(t.doc.scrollLeft-d)>1&&(l=!0)),!l)break}return i}u(Aa,"scrollPosIntoView");function Wa(t,e){var r=jr(t,e);r.scrollTop!=null&&Ze(t,r.scrollTop),r.scrollLeft!=null&&oe(t,r.scrollLeft)}u(Wa,"scrollIntoView");function jr(t,e){var r=t.display,n=be(t.display);e.top<0&&(e.top=0);var i=t.curOp&&t.curOp.scrollTop!=null?t.curOp.scrollTop:r.scroller.scrollTop,o=Wr(t),l={};e.bottom-e.top>o&&(e.bottom=e.top+o);var a=t.doc.height+Ar(r),s=e.topa-n;if(e.topi+o){var h=Math.min(e.top,(c?a:e.bottom)-o);h!=i&&(l.scrollTop=h)}var d=t.options.fixedGutter?0:r.gutters.offsetWidth,p=t.curOp&&t.curOp.scrollLeft!=null?t.curOp.scrollLeft:r.scroller.scrollLeft-d,f=ne(t)-r.gutters.offsetWidth,g=e.right-e.left>f;return g&&(e.right=e.left+f),e.left<10?l.scrollLeft=0:e.leftf+p-3&&(l.scrollLeft=e.right+(g?0:10)-f),l}u(jr,"calculateScrollPos");function Xr(t,e){e!=null&&(Pn(t),t.curOp.scrollTop=(t.curOp.scrollTop==null?t.doc.scrollTop:t.curOp.scrollTop)+e)}u(Xr,"addToScrollTop");function Ce(t){Pn(t);var e=t.getCursor();t.curOp.scrollToPos={from:e,to:e,margin:t.options.cursorScrollMargin}}u(Ce,"ensureCursorVisible");function Ye(t,e,r){(e!=null||r!=null)&&Pn(t),e!=null&&(t.curOp.scrollLeft=e),r!=null&&(t.curOp.scrollTop=r)}u(Ye,"scrollToCoords");function Ha(t,e){Pn(t),t.curOp.scrollToPos=e}u(Ha,"scrollToRange");function Pn(t){var e=t.curOp.scrollToPos;if(e){t.curOp.scrollToPos=null;var r=uo(t,e.from),n=uo(t,e.to);yo(t,r,n,e.margin)}}u(Pn,"resolveScrollToPos");function yo(t,e,r,n){var i=jr(t,{left:Math.min(e.left,r.left),top:Math.min(e.top,r.top)-n,right:Math.max(e.right,r.right),bottom:Math.max(e.bottom,r.bottom)+n});Ye(t,i.scrollLeft,i.scrollTop)}u(yo,"scrollToCoordsRange");function Ze(t,e){Math.abs(t.doc.scrollTop-e)<2||(It||Yr(t,{top:e}),bo(t,e,!0),It&&Yr(t),Qe(t,100))}u(Ze,"updateScrollTop");function bo(t,e,r){e=Math.max(0,Math.min(t.display.scroller.scrollHeight-t.display.scroller.clientHeight,e)),!(t.display.scroller.scrollTop==e&&!r)&&(t.doc.scrollTop=e,t.display.scrollbars.setScrollTop(e),t.display.scroller.scrollTop!=e&&(t.display.scroller.scrollTop=e))}u(bo,"setScrollTop");function oe(t,e,r,n){e=Math.max(0,Math.min(e,t.display.scroller.scrollWidth-t.display.scroller.clientWidth)),!((r?e==t.doc.scrollLeft:Math.abs(t.doc.scrollLeft-e)<2)&&!n)&&(t.doc.scrollLeft=e,So(t),t.display.scroller.scrollLeft!=e&&(t.display.scroller.scrollLeft=e),t.display.scrollbars.setScrollLeft(e))}u(oe,"setScrollLeft");function $e(t){var e=t.display,r=e.gutters.offsetWidth,n=Math.round(t.doc.height+Ar(t.display));return{clientHeight:e.scroller.clientHeight,viewHeight:e.wrapper.clientHeight,scrollWidth:e.scroller.scrollWidth,clientWidth:e.scroller.clientWidth,viewWidth:e.wrapper.clientWidth,barLeft:t.options.fixedGutter?r:0,docHeight:n,scrollHeight:n+Mt(t)+e.barHeight,nativeBarWidth:e.nativeBarWidth,gutterWidth:r}}u($e,"measureForScrollbars");var Se=u(function(t,e,r){this.cm=r;var n=this.vert=k("div",[k("div",null,null,"min-width: 1px")],"CodeMirror-vscrollbar"),i=this.horiz=k("div",[k("div",null,null,"height: 100%; min-height: 1px")],"CodeMirror-hscrollbar");n.tabIndex=i.tabIndex=-1,t(n),t(i),M(n,"scroll",function(){n.clientHeight&&e(n.scrollTop,"vertical")}),M(i,"scroll",function(){i.clientWidth&&e(i.scrollLeft,"horizontal")}),this.checkedZeroWidth=!1,A&&I<8&&(this.horiz.style.minHeight=this.vert.style.minWidth="18px")},"NativeScrollbars");Se.prototype.update=function(t){var e=t.scrollWidth>t.clientWidth+1,r=t.scrollHeight>t.clientHeight+1,n=t.nativeBarWidth;if(r){this.vert.style.display="block",this.vert.style.bottom=e?n+"px":"0";var i=t.viewHeight-(e?n:0);this.vert.firstChild.style.height=Math.max(0,t.scrollHeight-t.clientHeight+i)+"px"}else this.vert.scrollTop=0,this.vert.style.display="",this.vert.firstChild.style.height="0";if(e){this.horiz.style.display="block",this.horiz.style.right=r?n+"px":"0",this.horiz.style.left=t.barLeft+"px";var o=t.viewWidth-t.barLeft-(r?n:0);this.horiz.firstChild.style.width=Math.max(0,t.scrollWidth-t.clientWidth+o)+"px"}else this.horiz.style.display="",this.horiz.firstChild.style.width="0";return!this.checkedZeroWidth&&t.clientHeight>0&&(n==0&&this.zeroWidthHack(),this.checkedZeroWidth=!0),{right:r?n:0,bottom:e?n:0}},Se.prototype.setScrollLeft=function(t){this.horiz.scrollLeft!=t&&(this.horiz.scrollLeft=t),this.disableHoriz&&this.enableZeroWidthBar(this.horiz,this.disableHoriz,"horiz")},Se.prototype.setScrollTop=function(t){this.vert.scrollTop!=t&&(this.vert.scrollTop=t),this.disableVert&&this.enableZeroWidthBar(this.vert,this.disableVert,"vert")},Se.prototype.zeroWidthHack=function(){var t=xt&&!js?"12px":"18px";this.horiz.style.height=this.vert.style.width=t,this.horiz.style.pointerEvents=this.vert.style.pointerEvents="none",this.disableHoriz=new Qt,this.disableVert=new Qt},Se.prototype.enableZeroWidthBar=function(t,e,r){t.style.pointerEvents="auto";function n(){var i=t.getBoundingClientRect(),o=r=="vert"?document.elementFromPoint(i.right-1,(i.top+i.bottom)/2):document.elementFromPoint((i.right+i.left)/2,i.bottom-1);o!=t?t.style.pointerEvents="none":e.set(1e3,n)}u(n,"maybeDisable"),e.set(1e3,n)},Se.prototype.clear=function(){var t=this.horiz.parentNode;t.removeChild(this.horiz),t.removeChild(this.vert)};var En=u(function(){},"NullScrollbars");En.prototype.update=function(){return{bottom:0,right:0}},En.prototype.setScrollLeft=function(){},En.prototype.setScrollTop=function(){},En.prototype.clear=function(){};function Le(t,e){e||(e=$e(t));var r=t.display.barWidth,n=t.display.barHeight;wo(t,e);for(var i=0;i<4&&r!=t.display.barWidth||n!=t.display.barHeight;i++)r!=t.display.barWidth&&t.options.lineWrapping&&Hn(t),wo(t,$e(t)),r=t.display.barWidth,n=t.display.barHeight}u(Le,"updateScrollbars");function wo(t,e){var r=t.display,n=r.scrollbars.update(e);r.sizer.style.paddingRight=(r.barWidth=n.right)+"px",r.sizer.style.paddingBottom=(r.barHeight=n.bottom)+"px",r.heightForcer.style.borderBottom=n.bottom+"px solid transparent",n.right&&n.bottom?(r.scrollbarFiller.style.display="block",r.scrollbarFiller.style.height=n.bottom+"px",r.scrollbarFiller.style.width=n.right+"px"):r.scrollbarFiller.style.display="",n.bottom&&t.options.coverGutterNextToScrollbar&&t.options.fixedGutter?(r.gutterFiller.style.display="block",r.gutterFiller.style.height=n.bottom+"px",r.gutterFiller.style.width=e.gutterWidth+"px"):r.gutterFiller.style.display=""}u(wo,"updateScrollbarsInner");var Fa={native:Se,null:En};function xo(t){t.display.scrollbars&&(t.display.scrollbars.clear(),t.display.scrollbars.addClass&&fe(t.display.wrapper,t.display.scrollbars.addClass)),t.display.scrollbars=new Fa[t.options.scrollbarStyle](function(e){t.display.wrapper.insertBefore(e,t.display.scrollbarFiller),M(e,"mousedown",function(){t.state.focused&&setTimeout(function(){return t.display.input.focus()},0)}),e.setAttribute("cm-not-content","true")},function(e,r){r=="horizontal"?oe(t,e):Ze(t,e)},t),t.display.scrollbars.addClass&&Zt(t.display.wrapper,t.display.scrollbars.addClass)}u(xo,"initScrollbars");var ru=0;function le(t){t.curOp={cm:t,viewChanged:!1,startHeight:t.doc.height,forceUpdate:!1,updateInput:0,typing:!1,changeObjs:null,cursorActivityHandlers:null,cursorActivityCalled:0,selectionChanged:!1,updateMaxLine:!1,scrollLeft:null,scrollTop:null,scrollToPos:null,focus:!1,id:++ru,markArrays:null},ca(t.curOp)}u(le,"startOperation");function ae(t){var e=t.curOp;e&&da(e,function(r){for(var n=0;n=r.viewTo)||r.maxLineChanged&&e.options.lineWrapping,t.update=t.mustUpdate&&new _r(e,t.mustUpdate&&{top:t.scrollTop,ensure:t.scrollToPos},t.forceUpdate)}u(Ea,"endOperation_R1");function Ia(t){t.updatedDisplay=t.mustUpdate&&qr(t.cm,t.update)}u(Ia,"endOperation_W1");function Ra(t){var e=t.cm,r=e.display;t.updatedDisplay&&Hn(e),t.barMeasure=$e(e),r.maxLineChanged&&!e.options.lineWrapping&&(t.adjustWidthTo=no(e,r.maxLine,r.maxLine.text.length).left+3,e.display.sizerWidth=t.adjustWidthTo,t.barMeasure.scrollWidth=Math.max(r.scroller.clientWidth,r.sizer.offsetLeft+t.adjustWidthTo+Mt(e)+e.display.barWidth),t.maxScrollLeft=Math.max(0,r.sizer.offsetLeft+t.adjustWidthTo-ne(e))),(t.updatedDisplay||t.selectionChanged)&&(t.preparedSelection=r.input.prepareSelection())}u(Ra,"endOperation_R2");function za(t){var e=t.cm;t.adjustWidthTo!=null&&(e.display.sizer.style.minWidth=t.adjustWidthTo+"px",t.maxScrollLeft=t.display.viewTo)){var r=+new Date+t.options.workTime,n=Ue(t,e.highlightFrontier),i=[];e.iter(n.line,Math.min(e.first+e.size,t.display.viewTo+500),function(o){if(n.line>=t.display.viewFrom){var l=o.styles,a=o.text.length>t.options.maxHighlightLength?Jt(e.mode,n.state):null,s=Wi(t,o,n,!0);a&&(n.state=a),o.styles=s.styles;var c=o.styleClasses,h=s.classes;h?o.styleClasses=h:c&&(o.styleClasses=null);for(var d=!l||l.length!=o.styles.length||c!=h&&(!c||!h||c.bgClass!=h.bgClass||c.textClass!=h.textClass),p=0;!d&&pr)return Qe(t,t.options.workDelay),!0}),e.highlightFrontier=n.line,e.modeFrontier=Math.max(e.modeFrontier,n.line),i.length&&ut(t,function(){for(var o=0;o=r.viewFrom&&e.visible.to<=r.viewTo&&(r.updateLineNumbers==null||r.updateLineNumbers>=r.viewTo)&&r.renderedView==r.view&&po(t)==0)return!1;Lo(t)&&(Kt(t),e.dims=Rr(t));var i=n.first+n.size,o=Math.max(e.visible.from-t.options.viewportMargin,n.first),l=Math.min(i,e.visible.to+t.options.viewportMargin);r.viewFroml&&r.viewTo-l<20&&(l=Math.min(i,r.viewTo)),Bt&&(o=Mr(t.doc,o),l=Vi(t.doc,l));var a=o!=r.viewFrom||l!=r.viewTo||r.lastWrapHeight!=e.wrapperHeight||r.lastWrapWidth!=e.wrapperWidth;Na(t,o,l),r.viewOffset=Ht(S(t.doc,r.viewFrom)),t.display.mover.style.top=r.viewOffset+"px";var s=po(t);if(!a&&s==0&&!e.force&&r.renderedView==r.view&&(r.updateLineNumbers==null||r.updateLineNumbers>=r.viewTo))return!1;var c=Ka(t);return s>4&&(r.lineDiv.style.display="none"),ja(t,r.updateLineNumbers,e.dims),s>4&&(r.lineDiv.style.display=""),r.renderedView=r.view,Va(c),Rt(r.cursorDiv),Rt(r.selectionDiv),r.gutters.style.height=r.sizer.style.minHeight=0,a&&(r.lastWrapHeight=e.wrapperHeight,r.lastWrapWidth=e.wrapperWidth,Qe(t,400)),r.updateLineNumbers=null,!0}u(qr,"updateDisplayIfNeeded");function Co(t,e){for(var r=e.viewport,n=!0;;n=!1){if(!n||!t.options.lineWrapping||e.oldDisplayWidth==ne(t)){if(r&&r.top!=null&&(r={top:Math.min(t.doc.height+Ar(t.display)-Wr(t),r.top)}),e.visible=Fn(t.display,t.doc,r),e.visible.from>=t.display.viewFrom&&e.visible.to<=t.display.viewTo)break}else n&&(e.visible=Fn(t.display,t.doc,r));if(!qr(t,e))break;Hn(t);var i=$e(t);qe(t),Le(t,i),$r(t,i),e.force=!1}e.signal(t,"update",t),(t.display.viewFrom!=t.display.reportedViewFrom||t.display.viewTo!=t.display.reportedViewTo)&&(e.signal(t,"viewportChange",t,t.display.viewFrom,t.display.viewTo),t.display.reportedViewFrom=t.display.viewFrom,t.display.reportedViewTo=t.display.viewTo)}u(Co,"postUpdateDisplay");function Yr(t,e){var r=new _r(t,e);if(qr(t,r)){Hn(t),Co(t,r);var n=$e(t);qe(t),Le(t,n),$r(t,n),r.finish()}}u(Yr,"updateDisplaySimple");function ja(t,e,r){var n=t.display,i=t.options.lineNumbers,o=n.lineDiv,l=o.firstChild;function a(g){var m=g.nextSibling;return ot&&xt&&t.display.currentWheelTarget==g?g.style.display="none":g.parentNode.removeChild(g),m}u(a,"rm");for(var s=n.view,c=n.viewFrom,h=0;h-1&&(f=!1),Yi(t,d,c,r)),f&&(Rt(d.lineNumber),d.lineNumber.appendChild(document.createTextNode(br(t.options,c)))),l=d.node.nextSibling}c+=d.size}for(;l;)l=a(l)}u(ja,"patchDisplay");function Zr(t){var e=t.gutters.offsetWidth;t.sizer.style.marginLeft=e+"px",_(t,"gutterChanged",t)}u(Zr,"updateGutterSpace");function $r(t,e){t.display.sizer.style.minHeight=e.docHeight+"px",t.display.heightForcer.style.top=e.docHeight+"px",t.display.gutters.style.height=e.docHeight+t.display.barHeight+Mt(t)+"px"}u($r,"setDocumentHeight");function So(t){var e=t.display,r=e.view;if(!(!e.alignWidgets&&(!e.gutters.firstChild||!t.options.fixedGutter))){for(var n=zr(e)-e.scroller.scrollLeft+t.doc.scrollLeft,i=e.gutters.offsetWidth,o=n+"px",l=0;la.clientWidth,c=a.scrollHeight>a.clientHeight;if(n&&s||i&&c){if(i&&xt&&ot){t:for(var h=e.target,d=l.view;h!=a;h=h.parentNode)for(var p=0;p=0&&N(t,n.to())<=0)return r}return-1};var H=u(function(t,e){this.anchor=t,this.head=e},"Range");H.prototype.from=function(){return wn(this.anchor,this.head)},H.prototype.to=function(){return bn(this.anchor,this.head)},H.prototype.empty=function(){return this.head.line==this.anchor.line&&this.head.ch==this.anchor.ch};function Lt(t,e,r){var n=t&&t.options.selectionsMayTouch,i=e[r];e.sort(function(p,f){return N(p.from(),f.from())}),r=J(e,i);for(var o=1;o0:s>=0){var c=wn(a.from(),l.from()),h=bn(a.to(),l.to()),d=a.empty()?l.from()==l.head:a.from()==a.head;o<=r&&--r,e.splice(--o,2,new H(d?h:c,d?c:h))}}return new wt(e,r)}u(Lt,"normalizeSelection");function jt(t,e){return new wt([new H(t,e||t)],0)}u(jt,"simpleSelection");function Xt(t){return t.text?v(t.from.line+t.text.length-1,W(t.text).length+(t.text.length==1?t.from.ch:0)):t.to}u(Xt,"changeEnd");function No(t,e){if(N(t,e.from)<0)return t;if(N(t,e.to)<=0)return Xt(e);var r=t.line+e.text.length-(e.to.line-e.from.line)-1,n=t.ch;return t.line==e.to.line&&(n+=Xt(e).ch-e.to.ch),v(r,n)}u(No,"adjustForChange");function ti(t,e){for(var r=[],n=0;n1&&t.remove(a.line+1,g-1),t.insert(a.line+1,b)}_(t,"change",t,e)}u(ni,"updateDoc");function _t(t,e,r){function n(i,o,l){if(i.linked)for(var a=0;a1&&!t.done[t.done.length-2].ranges)return t.done.pop(),W(t.done)}u(Za,"lastChangeEvent");function Fo(t,e,r,n){var i=t.history;i.undone.length=0;var o=+new Date,l,a;if((i.lastOp==n||i.lastOrigin==e.origin&&e.origin&&(e.origin.charAt(0)=="+"&&i.lastModTime>o-(t.cm?t.cm.options.historyEventDelay:500)||e.origin.charAt(0)=="*"))&&(l=Za(i,i.lastOp==n)))a=W(l.changes),N(e.from,e.to)==0&&N(e.from,a.to)==0?a.to=Xt(e):l.changes.push(ri(t,e));else{var s=W(i.done);for((!s||!s.ranges)&&Rn(t.sel,i.done),l={changes:[ri(t,e)],generation:i.generation},i.done.push(l);i.done.length>i.undoDepth;)i.done.shift(),i.done[0].ranges||i.done.shift()}i.done.push(r),i.generation=++i.maxGeneration,i.lastModTime=i.lastSelTime=o,i.lastOp=i.lastSelOp=n,i.lastOrigin=i.lastSelOrigin=e.origin,a||U(t,"historyAdded")}u(Fo,"addChangeToHistory");function $a(t,e,r,n){var i=e.charAt(0);return i=="*"||i=="+"&&r.ranges.length==n.ranges.length&&r.somethingSelected()==n.somethingSelected()&&new Date-t.history.lastSelTime<=(t.cm?t.cm.options.historyEventDelay:500)}u($a,"selectionEventCanBeMerged");function Qa(t,e,r,n){var i=t.history,o=n&&n.origin;r==i.lastSelOp||o&&i.lastSelOrigin==o&&(i.lastModTime==i.lastSelTime&&i.lastOrigin==o||$a(t,o,W(i.done),e))?i.done[i.done.length-1]=e:Rn(e,i.done),i.lastSelTime=+new Date,i.lastSelOrigin=o,i.lastSelOp=r,n&&n.clearRedo!==!1&&Ho(i.undone)}u(Qa,"addSelectionToHistory");function Rn(t,e){var r=W(e);r&&r.ranges&&r.equals(t)||e.push(t)}u(Rn,"pushSelectionToHistory");function Po(t,e,r,n){var i=e["spans_"+t.id],o=0;t.iter(Math.max(t.first,r),Math.min(t.first+t.size,n),function(l){l.markedSpans&&((i||(i=e["spans_"+t.id]={}))[o]=l.markedSpans),++o})}u(Po,"attachLocalSpans");function Ja(t){if(!t)return null;for(var e,r=0;r-1&&(W(a)[d]=c[d],delete c[d])}}return n}u(ke,"copyHistoryArray");function ii(t,e,r,n){if(n){var i=t.anchor;if(r){var o=N(e,i)<0;o!=N(r,i)<0?(i=e,e=r):o!=N(e,r)<0&&(e=r)}return new H(i,e)}else return new H(r||e,e)}u(ii,"extendRange");function zn(t,e,r,n,i){i==null&&(i=t.cm&&(t.cm.display.shift||t.extend)),tt(t,new wt([ii(t.sel.primary(),e,r,i)],0),n)}u(zn,"extendSelection");function Io(t,e,r){for(var n=[],i=t.cm&&(t.cm.display.shift||t.extend),o=0;o=e.ch:a.to>e.ch))){if(i&&(U(s,"beforeCursorEnter"),s.explicitlyCleared))if(o.markedSpans){--l;continue}else break;if(!s.atomic)continue;if(r){var d=s.find(n<0?1:-1),p=void 0;if((n<0?h:c)&&(d=Ko(t,d,-n,d&&d.line==e.line?o:null)),d&&d.line==e.line&&(p=N(d,r))&&(n<0?p<0:p>0))return Te(t,d,e,n,i)}var f=s.find(n<0?-1:1);return(n<0?c:h)&&(f=Ko(t,f,n,f.line==e.line?o:null)),f?Te(t,f,e,n,i):null}}return e}u(Te,"skipAtomicInner");function Un(t,e,r,n,i){var o=n||1,l=Te(t,e,r,o,i)||!i&&Te(t,e,r,o,!0)||Te(t,e,r,-o,i)||!i&&Te(t,e,r,-o,!0);return l||(t.cantEdit=!0,v(t.first,0))}u(Un,"skipAtomic");function Ko(t,e,r,n){return r<0&&e.ch==0?e.line>t.first?O(t,v(e.line-1)):null:r>0&&e.ch==(n||S(t,e.line)).text.length?e.line=0;--i)Xo(t,{from:n[i].from,to:n[i].to,text:i?[""]:e.text,origin:e.origin});else Xo(t,e)}}u(Me,"makeChange");function Xo(t,e){if(!(e.text.length==1&&e.text[0]==""&&N(e.from,e.to)==0)){var r=ti(t,e);Fo(t,e,r,t.cm?t.cm.curOp.id:NaN),en(t,e,r,kr(t,e));var n=[];_t(t,function(i,o){!o&&J(n,i.history)==-1&&(Zo(i.history,e),n.push(i.history)),en(i,e,null,kr(i,e))})}}u(Xo,"makeChangeInner");function Gn(t,e,r){var n=t.cm&&t.cm.state.suppressEdits;if(!(n&&!r)){for(var i=t.history,o,l=t.sel,a=e=="undo"?i.done:i.undone,s=e=="undo"?i.undone:i.done,c=0;c=0;--f){var g=p(f);if(g)return g.v}}}}u(Gn,"makeChangeFromHistory");function _o(t,e){if(e!=0&&(t.first+=e,t.sel=new wt(gn(t.sel.ranges,function(i){return new H(v(i.anchor.line+e,i.anchor.ch),v(i.head.line+e,i.head.ch))}),t.sel.primIndex),t.cm)){at(t.cm,t.first,t.first-e,e);for(var r=t.cm.display,n=r.viewFrom;nt.lastLine())){if(e.from.lineo&&(e={from:e.from,to:v(o,S(t,o).text.length),text:[e.text[0]],origin:e.origin}),e.removed=te(t,e.from,e.to),r||(r=ti(t,e)),t.cm?ns(t.cm,e,n):ni(t,e,n),Bn(t,r,Dt),t.cantEdit&&Un(t,v(t.firstLine(),0))&&(t.cantEdit=!1)}}u(en,"makeChangeSingleDoc");function ns(t,e,r){var n=t.doc,i=t.display,o=e.from,l=e.to,a=!1,s=o.line;t.options.lineWrapping||(s=F(Ct(S(n,o.line))),n.iter(s,l.line+1,function(f){if(f==i.maxLine)return a=!0,!0})),n.sel.contains(e.from,e.to)>-1&&xi(t),ni(n,e,r,fo(t)),t.options.lineWrapping||(n.iter(s,o.line+e.text.length,function(f){var g=kn(f);g>i.maxLineLength&&(i.maxLine=f,i.maxLineLength=g,i.maxLineChanged=!0,a=!1)}),a&&(t.curOp.updateMaxLine=!0)),jl(n,o.line),Qe(t,400);var c=e.text.length-(l.line-o.line)-1;e.full?at(t):o.line==l.line&&e.text.length==1&&!Do(t.doc,e)?Gt(t,o.line,"text"):at(t,o.line,l.line+1,c);var h=bt(t,"changes"),d=bt(t,"change");if(d||h){var p={from:o,to:l,text:e.text,removed:e.removed,origin:e.origin};d&&_(t,"change",t,p),h&&(t.curOp.changeObjs||(t.curOp.changeObjs=[])).push(p)}t.display.selForContextMenu=null}u(ns,"makeChangeSingleDocInEditor");function Ne(t,e,r,n,i){var o;n||(n=r),N(n,r)<0&&(o=[n,r],r=o[0],n=o[1]),typeof e=="string"&&(e=t.splitLines(e)),Me(t,{from:r,to:n,text:e,origin:i})}u(Ne,"replaceRange");function qo(t,e,r,n){r1||!(this.children[0]instanceof rn))){var a=[];this.collapse(a),this.children=[new rn(a)],this.children[0].parent=this}},collapse:function(t){for(var e=0;e50){for(var l=i.lines.length%25+25,a=l;a10);t.parent.maybeSpill()}},iterN:function(t,e,r){for(var n=0;nt.display.maxLineLength&&(t.display.maxLine=c,t.display.maxLineLength=h,t.display.maxLineChanged=!0)}n!=null&&t&&this.collapsed&&at(t,n,i+1),this.lines.length=0,this.explicitlyCleared=!0,this.atomic&&this.doc.cantEdit&&(this.doc.cantEdit=!1,t&&Uo(t.doc)),t&&_(t,"markerCleared",t,this,n,i),e&&ae(t),this.parent&&this.parent.clear()}},se.prototype.find=function(t,e){t==null&&this.type=="bookmark"&&(t=1);for(var r,n,i=0;i0||l==0&&o.clearWhenEmpty!==!1)return o;if(o.replacedWith&&(o.collapsed=!0,o.widgetNode=pe("span",[o.replacedWith],"CodeMirror-widget"),n.handleMouseEvents||o.widgetNode.setAttribute("cm-ignore-events","true"),n.insertLeft&&(o.widgetNode.insertLeft=!0)),o.collapsed){if(Ki(t,e.line,e,r,o)||e.line!=r.line&&Ki(t,r.line,e,r,o))throw new Error("Inserting collapsed marker partially overlapping an existing one");ql()}o.addToHistory&&Fo(t,{from:e,to:r,origin:"markText"},t.sel,NaN);var a=e.line,s=t.cm,c;if(t.iter(a,r.line+1,function(d){s&&o.collapsed&&!s.options.lineWrapping&&Ct(d)==s.display.maxLine&&(c=!0),o.collapsed&&a!=e.line&&Tt(d,0),Zl(d,new xn(o,a==e.line?e.ch:null,a==r.line?r.ch:null),t.cm&&t.cm.curOp),++a}),o.collapsed&&t.iter(e.line,r.line+1,function(d){Ut(t,d)&&Tt(d,0)}),o.clearOnEnter&&M(o,"beforeCursorEnter",function(){return o.clear()}),o.readOnly&&(_l(),(t.history.done.length||t.history.undone.length)&&t.clearHistory()),o.collapsed&&(o.id=++is,o.atomic=!0),s){if(c&&(s.curOp.updateMaxLine=!0),o.collapsed)at(s,e.line,r.line+1);else if(o.className||o.startStyle||o.endStyle||o.css||o.attributes||o.title)for(var h=e.line;h<=r.line;h++)Gt(s,h,"text");o.atomic&&Uo(s.doc),_(s,"markerAdded",s,o)}return o}u(Oe,"markText");var Vn=u(function(t,e){this.markers=t,this.primary=e;for(var r=0;r=0;s--)Me(this,n[s]);a?zo(this,a):this.cm&&Ce(this.cm)}),undo:Y(function(){Gn(this,"undo")}),redo:Y(function(){Gn(this,"redo")}),undoSelection:Y(function(){Gn(this,"undo",!0)}),redoSelection:Y(function(){Gn(this,"redo",!0)}),setExtending:function(t){this.extend=t},getExtending:function(){return this.extend},historySize:function(){for(var t=this.history,e=0,r=0,n=0;n=t.ch)&&e.push(i.marker.parent||i.marker)}return e},findMarks:function(t,e,r){t=O(this,t),e=O(this,e);var n=[],i=t.line;return this.iter(t.line,e.line+1,function(o){var l=o.markedSpans;if(l)for(var a=0;a=s.to||s.from==null&&i!=t.line||s.from!=null&&i==e.line&&s.from>=e.ch)&&(!r||r(s.marker))&&n.push(s.marker.parent||s.marker)}++i}),n},getAllMarks:function(){var t=[];return this.iter(function(e){var r=e.markedSpans;if(r)for(var n=0;nt)return e=t,!0;t-=o,++r}),O(this,v(r,e))},indexFromPos:function(t){t=O(this,t);var e=t.ch;if(t.linee&&(e=t.from),t.to!=null&&t.to-1){e.state.draggingText(t),setTimeout(function(){return e.display.input.focus()},20);return}try{var h=t.dataTransfer.getData("Text");if(h){var d;if(e.state.draggingText&&!e.state.draggingText.copy&&(d=e.listSelections()),Bn(e.doc,jt(r,r)),d)for(var p=0;p=0;a--)Ne(t.doc,"",n[a].from,n[a].to,"+delete");Ce(t)})}u(Ae,"deleteNearSelection");function ai(t,e,r){var n=wi(t.text,e+r,r);return n<0||n>t.text.length?null:n}u(ai,"moveCharLogically");function si(t,e,r){var n=ai(t,e.ch,r);return n==null?null:new v(e.line,n,r<0?"after":"before")}u(si,"moveLogically");function ui(t,e,r,n,i){if(t){e.doc.direction=="rtl"&&(i=-i);var o=At(r,e.doc.direction);if(o){var l=i<0?W(o):o[0],a=i<0==(l.level==1),s=a?"after":"before",c;if(l.level>0||e.doc.direction=="rtl"){var h=ve(e,r);c=i<0?r.text.length-1:0;var d=Nt(e,h,c).top;c=Pe(function(p){return Nt(e,h,p).top==d},i<0==(l.level==1)?l.from:l.to-1,c),s=="before"&&(c=ai(r,c,1))}else c=i<0?l.to:l.from;return new v(n,c,s)}}return new v(n,i<0?r.text.length:0,i<0?"before":"after")}u(ui,"endOfLine");function ys(t,e,r,n){var i=At(e,t.doc.direction);if(!i)return si(e,r,n);r.ch>=e.text.length?(r.ch=e.text.length,r.sticky="before"):r.ch<=0&&(r.ch=0,r.sticky="after");var o=Ee(i,r.ch,r.sticky),l=i[o];if(t.doc.direction=="ltr"&&l.level%2==0&&(n>0?l.to>r.ch:l.from=l.from&&p>=h.begin)){var f=d?"before":"after";return new v(r.line,p,f)}}var g=u(function(b,x,w){for(var C=u(function(E,$){return $?new v(r.line,a(E,1),"before"):new v(r.line,E,"after")},"getRes");b>=0&&b0==(T.level!=1),D=L?w.begin:a(w.end,-1);if(T.from<=D&&D0?h.end:a(h.begin,-1);return y!=null&&!(n>0&&y==e.text.length)&&(m=g(n>0?0:i.length-1,n,c(y)),m)?m:null}u(ys,"moveVisually");var qn={selectAll:Vo,singleSelection:function(t){return t.setSelection(t.getCursor("anchor"),t.getCursor("head"),Dt)},killLine:function(t){return Ae(t,function(e){if(e.empty()){var r=S(t.doc,e.head.line).text.length;return e.head.ch==r&&e.head.line0)i=new v(i.line,i.ch+1),t.replaceRange(o.charAt(i.ch-1)+o.charAt(i.ch-2),v(i.line,i.ch-2),i,"+transpose");else if(i.line>t.doc.first){var l=S(t.doc,i.line-1).text;l&&(i=new v(i.line,1),t.replaceRange(o.charAt(0)+t.doc.lineSeparator()+l.charAt(l.length-1),v(i.line-1,l.length-1),i,"+transpose"))}}r.push(new H(i,i))}t.setSelections(r)})},newlineAndIndent:function(t){return ut(t,function(){for(var e=t.listSelections(),r=e.length-1;r>=0;r--)t.replaceRange(t.doc.lineSeparator(),e[r].anchor,e[r].head,"+input");e=t.listSelections();for(var n=0;nt&&N(e,this.pos)==0&&r==this.button};var Zn,$n;function Ss(t,e){var r=+new Date;return $n&&$n.compare(r,t,e)?(Zn=$n=null,"triple"):Zn&&Zn.compare(r,t,e)?($n=new dl(r,t,e),Zn=null,"double"):(Zn=new dl(r,t,e),$n=null,"single")}u(Ss,"clickRepeat");function fl(t){var e=this,r=e.display;if(!(X(e,t)||r.activeTouch&&r.input.supportsTouch())){if(r.input.ensurePolled(),r.shift=t.shiftKey,Ft(r,t)){ot||(r.scroller.draggable=!1,setTimeout(function(){return r.scroller.draggable=!0},100));return}if(!ci(e,t)){var n=re(e,t),i=Si(t),o=n?Ss(n,i):"single";window.focus(),i==1&&e.state.selectingText&&e.state.selectingText(t),!(n&&Ls(e,i,n,o,t))&&(i==1?n?Ts(e,n,o,t):gr(t)==r.scroller&<(t):i==2?(n&&zn(e.doc,n),setTimeout(function(){return r.input.focus()},20)):i==3&&(gi?e.display.input.onContextMenu(t):Kr(e)))}}}u(fl,"onMouseDown");function Ls(t,e,r,n,i){var o="Click";return n=="double"?o="Double"+o:n=="triple"&&(o="Triple"+o),o=(e==1?"Left":e==2?"Middle":"Right")+o,ln(t,nl(o,i),i,function(l){if(typeof l=="string"&&(l=qn[l]),!l)return!1;var a=!1;try{t.isReadOnly()&&(t.state.suppressEdits=!0),a=l(t,r)!=ar}finally{t.state.suppressEdits=!1}return a})}u(Ls,"handleMappedButton");function ks(t,e,r){var n=t.getOption("configureMouse"),i=n?n(t,e,r):{};if(i.unit==null){var o=_s?r.shiftKey&&r.metaKey:r.altKey;i.unit=o?"rectangle":e=="single"?"char":e=="double"?"word":"line"}return(i.extend==null||t.doc.extend)&&(i.extend=t.doc.extend||r.shiftKey),i.addNew==null&&(i.addNew=xt?r.metaKey:r.ctrlKey),i.moveOnDrag==null&&(i.moveOnDrag=!(xt?r.altKey:r.ctrlKey)),i}u(ks,"configureMouse");function Ts(t,e,r,n){A?setTimeout(lr(mo,t),0):t.curOp.focus=vt();var i=ks(t,r,n),o=t.doc.sel,l;t.options.dragDrop&&Qs&&!t.isReadOnly()&&r=="single"&&(l=o.contains(e))>-1&&(N((l=o.ranges[l]).from(),e)<0||e.xRel>0)&&(N(l.to(),e)>0||e.xRel<0)?Ms(t,n,e,i):Ns(t,n,e,i)}u(Ts,"leftButtonDown");function Ms(t,e,r,n){var i=t.display,o=!1,l=q(t,function(c){ot&&(i.scroller.draggable=!1),t.state.draggingText=!1,t.state.delayingBlurEvent&&(t.hasFocus()?t.state.delayingBlurEvent=!1:Kr(t)),mt(i.wrapper.ownerDocument,"mouseup",l),mt(i.wrapper.ownerDocument,"mousemove",a),mt(i.scroller,"dragstart",s),mt(i.scroller,"drop",l),o||(lt(c),n.addNew||zn(t.doc,r,null,null,n.extend),ot&&!rr||A&&I==9?setTimeout(function(){i.wrapper.ownerDocument.body.focus({preventScroll:!0}),i.input.focus()},20):i.input.focus())}),a=u(function(c){o=o||Math.abs(e.clientX-c.clientX)+Math.abs(e.clientY-c.clientY)>=10},"mouseMove"),s=u(function(){return o=!0},"dragStart");ot&&(i.scroller.draggable=!0),t.state.draggingText=l,l.copy=!n.moveOnDrag,M(i.wrapper.ownerDocument,"mouseup",l),M(i.wrapper.ownerDocument,"mousemove",a),M(i.scroller,"dragstart",s),M(i.scroller,"drop",l),t.state.delayingBlurEvent=!0,setTimeout(function(){return i.input.focus()},20),i.scroller.dragDrop&&i.scroller.dragDrop()}u(Ms,"leftButtonStartDrag");function pl(t,e,r){if(r=="char")return new H(e,e);if(r=="word")return t.findWordAt(e);if(r=="line")return new H(v(e.line,0),O(t.doc,v(e.line+1,0)));var n=r(t,e);return new H(n.from,n.to)}u(pl,"rangeForUnit");function Ns(t,e,r,n){A&&Kr(t);var i=t.display,o=t.doc;lt(e);var l,a,s=o.sel,c=s.ranges;if(n.addNew&&!n.extend?(a=o.sel.contains(r),a>-1?l=c[a]:l=new H(r,r)):(l=o.sel.primary(),a=o.sel.primIndex),n.unit=="rectangle")n.addNew||(l=new H(r,r)),r=re(t,e,!0,!0),a=-1;else{var h=pl(t,r,n.unit);n.extend?l=ii(l,h.anchor,h.head,n.extend):l=h}n.addNew?a==-1?(a=c.length,tt(o,Lt(t,c.concat([l]),a),{scroll:!1,origin:"*mouse"})):c.length>1&&c[a].empty()&&n.unit=="char"&&!n.extend?(tt(o,Lt(t,c.slice(0,a).concat(c.slice(a+1)),0),{scroll:!1,origin:"*mouse"}),s=o.sel):oi(o,a,l,mi):(a=0,tt(o,new wt([l],0),mi),s=o.sel);var d=r;function p(w){if(N(d,w)!=0)if(d=w,n.unit=="rectangle"){for(var C=[],T=t.options.tabSize,L=yt(S(o,r.line).text,r.ch,T),D=yt(S(o,w.line).text,w.ch,T),E=Math.min(L,D),$=Math.max(L,D),z=Math.min(r.line,w.line),ht=Math.min(t.lastLine(),Math.max(r.line,w.line));z<=ht;z++){var dt=S(o,z).text,V=sr(dt,E,T);E==$?C.push(new H(v(z,V),v(z,V))):dt.length>V&&C.push(new H(v(z,V),v(z,sr(dt,$,T))))}C.length||C.push(new H(r,r)),tt(o,Lt(t,s.ranges.slice(0,a).concat(C),a),{origin:"*mouse",scroll:!1}),t.scrollIntoView(w)}else{var ft=l,et=pl(t,w,n.unit),Z=ft.anchor,j;N(et.anchor,Z)>0?(j=et.head,Z=wn(ft.from(),et.anchor)):(j=et.anchor,Z=bn(ft.to(),et.head));var B=s.ranges.slice(0);B[a]=Os(t,new H(O(o,Z),j)),tt(o,Lt(t,B,a),mi)}}u(p,"extendTo");var f=i.wrapper.getBoundingClientRect(),g=0;function m(w){var C=++g,T=re(t,w,!0,n.unit=="rectangle");if(T)if(N(T,d)!=0){t.curOp.focus=vt(),p(T);var L=Fn(i,o);(T.line>=L.to||T.linef.bottom?20:0;D&&setTimeout(q(t,function(){g==C&&(i.scroller.scrollTop+=D,m(w))}),50)}}u(m,"extend");function y(w){t.state.selectingText=!1,g=1/0,w&&(lt(w),i.input.focus()),mt(i.wrapper.ownerDocument,"mousemove",b),mt(i.wrapper.ownerDocument,"mouseup",x),o.history.lastSelOrigin=null}u(y,"done");var b=q(t,function(w){w.buttons===0||!Si(w)?y(w):m(w)}),x=q(t,y);t.state.selectingText=x,M(i.wrapper.ownerDocument,"mousemove",b),M(i.wrapper.ownerDocument,"mouseup",x)}u(Ns,"leftButtonSelect");function Os(t,e){var r=e.anchor,n=e.head,i=S(t.doc,r.line);if(N(r,n)==0&&r.sticky==n.sticky)return e;var o=At(i);if(!o)return e;var l=Ee(o,r.ch,r.sticky),a=o[l];if(a.from!=r.ch&&a.to!=r.ch)return e;var s=l+(a.from==r.ch==(a.level!=1)?0:1);if(s==0||s==o.length)return e;var c;if(n.line!=r.line)c=(n.line-r.line)*(t.doc.direction=="ltr"?1:-1)>0;else{var h=Ee(o,n.ch,n.sticky),d=h-l||(n.ch-r.ch)*(a.level==1?-1:1);h==s-1||h==s?c=d<0:c=d>0}var p=o[s+(c?-1:0)],f=c==(p.level==1),g=f?p.from:p.to,m=f?"after":"before";return r.ch==g&&r.sticky==m?e:new H(new v(r.line,g,m),n)}u(Os,"bidiSimplify");function gl(t,e,r,n){var i,o;if(e.touches)i=e.touches[0].clientX,o=e.touches[0].clientY;else try{i=e.clientX,o=e.clientY}catch{return!1}if(i>=Math.floor(t.display.gutters.getBoundingClientRect().right))return!1;n&<(e);var l=t.display,a=l.lineDiv.getBoundingClientRect();if(o>a.bottom||!bt(t,r))return pr(e);o-=a.top-l.viewOffset;for(var s=0;s=i){var h=ee(t.doc,o),d=t.display.gutterSpecs[s];return U(t,r,t,h,d.className,e),pr(e)}}}u(gl,"gutterEvent");function ci(t,e){return gl(t,e,"gutterClick",!0)}u(ci,"clickInGutter");function ml(t,e){Ft(t.display,e)||Ds(t,e)||X(t,e,"contextmenu")||gi||t.display.input.onContextMenu(e)}u(ml,"onContextMenu");function Ds(t,e){return bt(t,"gutterContextMenu")?gl(t,e,"gutterContextMenu",!1):!1}u(Ds,"contextMenuInGutter");function vl(t){t.display.wrapper.className=t.display.wrapper.className.replace(/\s*cm-s-\S+/g,"")+t.options.theme.replace(/(^|\s)\s*/g," cm-s-"),_e(t)}u(vl,"themeChanged");var an={toString:function(){return"CodeMirror.Init"}},As={},hi={};function Ws(t){var e=t.optionHandlers;function r(n,i,o,l){t.defaults[n]=i,o&&(e[n]=l?function(a,s,c){c!=an&&o(a,s,c)}:o)}u(r,"option"),t.defineOption=r,t.Init=an,r("value","",function(n,i){return n.setValue(i)},!0),r("mode",null,function(n,i){n.doc.modeOption=i,ei(n)},!0),r("indentUnit",2,ei,!0),r("indentWithTabs",!1),r("smartIndent",!0),r("tabSize",4,function(n){tn(n),_e(n),at(n)},!0),r("lineSeparator",null,function(n,i){if(n.doc.lineSep=i,!!i){var o=[],l=n.doc.first;n.doc.iter(function(s){for(var c=0;;){var h=s.text.indexOf(i,c);if(h==-1)break;c=h+i.length,o.push(v(l,h))}l++});for(var a=o.length-1;a>=0;a--)Ne(n.doc,i,o[a],v(o[a].line,o[a].ch+i.length))}}),r("specialChars",/[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b\u200e\u200f\u2028\u2029\ufeff\ufff9-\ufffc]/g,function(n,i,o){n.state.specialChars=new RegExp(i.source+(i.test(" ")?"":"| "),"g"),o!=an&&n.refresh()}),r("specialCharPlaceholder",oa,function(n){return n.refresh()},!0),r("electricChars",!0),r("inputStyle",dn?"contenteditable":"textarea",function(){throw new Error("inputStyle can not (yet) be changed in a running editor")},!0),r("spellcheck",!1,function(n,i){return n.getInputField().spellcheck=i},!0),r("autocorrect",!1,function(n,i){return n.getInputField().autocorrect=i},!0),r("autocapitalize",!1,function(n,i){return n.getInputField().autocapitalize=i},!0),r("rtlMoveVisually",!qs),r("wholeLineUpdateBefore",!0),r("theme","default",function(n){vl(n),Je(n)},!0),r("keyMap","default",function(n,i,o){var l=_n(i),a=o!=an&&_n(o);a&&a.detach&&a.detach(n,l),l.attach&&l.attach(n,a||null)}),r("extraKeys",null),r("configureMouse",null),r("lineWrapping",!1,Fs,!0),r("gutters",[],function(n,i){n.display.gutterSpecs=Qr(i,n.options.lineNumbers),Je(n)},!0),r("fixedGutter",!0,function(n,i){n.display.gutters.style.left=i?zr(n.display)+"px":"0",n.refresh()},!0),r("coverGutterNextToScrollbar",!1,function(n){return Le(n)},!0),r("scrollbarStyle","native",function(n){xo(n),Le(n),n.display.scrollbars.setScrollTop(n.doc.scrollTop),n.display.scrollbars.setScrollLeft(n.doc.scrollLeft)},!0),r("lineNumbers",!1,function(n,i){n.display.gutterSpecs=Qr(n.options.gutters,i),Je(n)},!0),r("firstLineNumber",1,Je,!0),r("lineNumberFormatter",function(n){return n},Je,!0),r("showCursorWhenSelecting",!1,qe,!0),r("resetSelectionOnContextMenu",!0),r("lineWiseCopyCut",!0),r("pasteLinesPerSelection",!0),r("selectionsMayTouch",!1),r("readOnly",!1,function(n,i){i=="nocursor"&&(xe(n),n.display.input.blur()),n.display.input.readOnlyChanged(i)}),r("screenReaderLabel",null,function(n,i){i=i===""?null:i,n.display.input.screenReaderLabelChanged(i)}),r("disableInput",!1,function(n,i){i||n.display.input.reset()},!0),r("dragDrop",!0,Hs),r("allowDropFileTypes",null),r("cursorBlinkRate",530),r("cursorScrollMargin",0),r("cursorHeight",1,qe,!0),r("singleCursorHeightPerLine",!0,qe,!0),r("workTime",100),r("workDelay",100),r("flattenSpans",!0,tn,!0),r("addModeClass",!1,tn,!0),r("pollInterval",100),r("undoDepth",200,function(n,i){return n.doc.history.undoDepth=i}),r("historyEventDelay",1250),r("viewportMargin",10,function(n){return n.refresh()},!0),r("maxHighlightLength",1e4,tn,!0),r("moveInputWithCursor",!0,function(n,i){i||n.display.input.resetPosition()}),r("tabindex",null,function(n,i){return n.display.input.getField().tabIndex=i||""}),r("autofocus",null),r("direction","ltr",function(n,i){return n.doc.setDirection(i)},!0),r("phrases",null)}u(Ws,"defineOptions");function Hs(t,e,r){var n=r&&r!=an;if(!e!=!n){var i=t.display.dragFunctions,o=e?M:mt;o(t.display.scroller,"dragstart",i.start),o(t.display.scroller,"dragenter",i.enter),o(t.display.scroller,"dragover",i.over),o(t.display.scroller,"dragleave",i.leave),o(t.display.scroller,"drop",i.drop)}}u(Hs,"dragDropChanged");function Fs(t){t.options.lineWrapping?(Zt(t.display.wrapper,"CodeMirror-wrap"),t.display.sizer.style.minWidth="",t.display.sizerWidth=null):(fe(t.display.wrapper,"CodeMirror-wrap"),Or(t)),Br(t),at(t),_e(t),setTimeout(function(){return Le(t)},100)}u(Fs,"wrappingChanged");function R(t,e){var r=this;if(!(this instanceof R))return new R(t,e);this.options=e=e?$t(e):{},$t(As,e,!1);var n=e.value;typeof n=="string"?n=new ct(n,e.mode,null,e.lineSeparator,e.direction):e.mode&&(n.modeOption=e.mode),this.doc=n;var i=new R.inputStyles[e.inputStyle](this),o=this.display=new Xa(t,n,i,e);o.wrapper.CodeMirror=this,vl(this),e.lineWrapping&&(this.display.wrapper.className+=" CodeMirror-wrap"),xo(this),this.state={keyMaps:[],overlays:[],modeGen:0,overwrite:!1,delayingBlurEvent:!1,focused:!1,suppressEdits:!1,pasteIncoming:-1,cutIncoming:-1,selectingText:!1,draggingText:!1,highlight:new Qt,keySeq:null,specialChars:null},e.autofocus&&!dn&&o.input.focus(),A&&I<11&&setTimeout(function(){return r.display.input.reset(!0)},20),Ps(this),fs(),le(this),this.curOp.forceUpdate=!0,Ao(this,n),e.autofocus&&!dn||this.hasFocus()?setTimeout(function(){r.hasFocus()&&!r.state.focused&&Vr(r)},20):xe(this);for(var l in hi)hi.hasOwnProperty(l)&&hi[l](this,e[l],an);Lo(this),e.finishInit&&e.finishInit(this);for(var a=0;a20*20}u(l,"farAway"),M(e.scroller,"touchstart",function(s){if(!X(t,s)&&!o(s)&&!ci(t,s)){e.input.ensurePolled(),clearTimeout(r);var c=+new Date;e.activeTouch={start:c,moved:!1,prev:c-n.end<=300?n:null},s.touches.length==1&&(e.activeTouch.left=s.touches[0].pageX,e.activeTouch.top=s.touches[0].pageY)}}),M(e.scroller,"touchmove",function(){e.activeTouch&&(e.activeTouch.moved=!0)}),M(e.scroller,"touchend",function(s){var c=e.activeTouch;if(c&&!Ft(e,s)&&c.left!=null&&!c.moved&&new Date-c.start<300){var h=t.coordsChar(e.activeTouch,"page"),d;!c.prev||l(c,c.prev)?d=new H(h,h):!c.prev.prev||l(c,c.prev.prev)?d=t.findWordAt(h):d=new H(v(h.line,0),O(t.doc,v(h.line+1,0))),t.setSelection(d.anchor,d.head),t.focus(),lt(s)}i()}),M(e.scroller,"touchcancel",i),M(e.scroller,"scroll",function(){e.scroller.clientHeight&&(Ze(t,e.scroller.scrollTop),oe(t,e.scroller.scrollLeft,!0),U(t,"scroll",t))}),M(e.scroller,"mousewheel",function(s){return Mo(t,s)}),M(e.scroller,"DOMMouseScroll",function(s){return Mo(t,s)}),M(e.wrapper,"scroll",function(){return e.wrapper.scrollTop=e.wrapper.scrollLeft=0}),e.dragFunctions={enter:function(s){X(t,s)||Ie(s)},over:function(s){X(t,s)||(hs(t,s),Ie(s))},start:function(s){return cs(t,s)},drop:q(t,us),leave:function(s){X(t,s)||Jo(t)}};var a=e.input.getField();M(a,"keyup",function(s){return cl.call(t,s)}),M(a,"keydown",q(t,ul)),M(a,"keypress",q(t,hl)),M(a,"focus",function(s){return Vr(t,s)}),M(a,"blur",function(s){return xe(t,s)})}u(Ps,"registerEventHandlers");var yl=[];R.defineInitHook=function(t){return yl.push(t)};function sn(t,e,r,n){var i=t.doc,o;r==null&&(r="add"),r=="smart"&&(i.mode.indent?o=Ue(t,e).state:r="prev");var l=t.options.tabSize,a=S(i,e),s=yt(a.text,null,l);a.stateAfter&&(a.stateAfter=null);var c=a.text.match(/^\s*/)[0],h;if(!n&&!/\S/.test(a.text))h=0,r="not";else if(r=="smart"&&(h=i.mode.indent(o,a.text.slice(c.length),a.text),h==ar||h>150)){if(!n)return;r="prev"}r=="prev"?e>i.first?h=yt(S(i,e-1).text,null,l):h=0:r=="add"?h=s+t.options.indentUnit:r=="subtract"?h=s-t.options.indentUnit:typeof r=="number"&&(h=s+r),h=Math.max(0,h);var d="",p=0;if(t.options.indentWithTabs)for(var f=Math.floor(h/l);f;--f)p+=l,d+=" ";if(pl,s=Ti(e),c=null;if(a&&n.ranges.length>1)if(Ot&&Ot.text.join(`
`)==e){if(n.ranges.length%Ot.text.length==0){c=[];for(var h=0;h=0;p--){var f=n.ranges[p],g=f.from(),m=f.to();f.empty()&&(r&&r>0?g=v(g.line,g.ch-r):t.state.overwrite&&!a?m=v(m.line,Math.min(S(o,m.line).text.length,m.ch+W(s).length)):a&&Ot&&Ot.lineWise&&Ot.text.join(`
`)==s.join(`
`)&&(g=m=v(g.line,0)));var y={from:g,to:m,text:c?c[p%c.length]:s,origin:i||(a?"paste":t.state.cutIncoming>l?"cut":"+input")};Me(t.doc,y),_(t,"inputRead",t,y)}e&&!a&&wl(t,e),Ce(t),t.curOp.updateInput<2&&(t.curOp.updateInput=d),t.curOp.typing=!0,t.state.pasteIncoming=t.state.cutIncoming=-1}u(di,"applyTextInput");function bl(t,e){var r=t.clipboardData&&t.clipboardData.getData("Text");if(r)return t.preventDefault(),!e.isReadOnly()&&!e.options.disableInput&&ut(e,function(){return di(e,r,0,null,"paste")}),!0}u(bl,"handlePaste");function wl(t,e){if(!(!t.options.electricChars||!t.options.smartIndent))for(var r=t.doc.sel,n=r.ranges.length-1;n>=0;n--){var i=r.ranges[n];if(!(i.head.ch>100||n&&r.ranges[n-1].head.line==i.head.line)){var o=t.getModeAt(i.head),l=!1;if(o.electricChars){for(var a=0;a-1){l=sn(t,i.head.line,"smart");break}}else o.electricInput&&o.electricInput.test(S(t.doc,i.head.line).text.slice(0,i.head.ch))&&(l=sn(t,i.head.line,"smart"));l&&_(t,"electricInput",t,i.head.line)}}}u(wl,"triggerElectric");function xl(t){for(var e=[],r=[],n=0;no&&(sn(this,a.head.line,n,!0),o=a.head.line,l==this.doc.sel.primIndex&&Ce(this));else{var s=a.from(),c=a.to(),h=Math.max(o,s.line);o=Math.min(this.lastLine(),c.line-(c.ch?0:1))+1;for(var d=h;d0&&oi(this.doc,l,new H(s,p[l].to()),Dt)}}}),getTokenAt:function(n,i){return Pi(this,n,i)},getLineTokens:function(n,i){return Pi(this,v(n),i,!0)},getTokenTypeAt:function(n){n=O(this.doc,n);var i=Hi(this,S(this.doc,n.line)),o=0,l=(i.length-1)/2,a=n.ch,s;if(a==0)s=i[2];else for(;;){var c=o+l>>1;if((c?i[c*2-1]:0)>=a)l=c;else if(i[c*2+1]s&&(n=s,l=!0),a=S(this.doc,n)}else a=n;return On(this,a,{top:0,left:0},i||"page",o||l).top+(l?this.doc.height-Ht(a):0)},defaultTextHeight:function(){return be(this.display)},defaultCharWidth:function(){return we(this.display)},getViewport:function(){return{from:this.display.viewFrom,to:this.display.viewTo}},addWidget:function(n,i,o,l,a){var s=this.display;n=St(this,O(this.doc,n));var c=n.bottom,h=n.left;if(i.style.position="absolute",i.setAttribute("cm-ignore-events","true"),this.display.input.setUneditable(i),s.sizer.appendChild(i),l=="over")c=n.top;else if(l=="above"||l=="near"){var d=Math.max(s.wrapper.clientHeight,this.doc.height),p=Math.max(s.sizer.clientWidth,s.lineSpace.clientWidth);(l=="above"||n.bottom+i.offsetHeight>d)&&n.top>i.offsetHeight?c=n.top-i.offsetHeight:n.bottom+i.offsetHeight<=d&&(c=n.bottom),h+i.offsetWidth>p&&(h=p-i.offsetWidth)}i.style.top=c+"px",i.style.left=i.style.right="",a=="right"?(h=s.sizer.clientWidth-i.offsetWidth,i.style.right="0px"):(a=="left"?h=0:a=="middle"&&(h=(s.sizer.clientWidth-i.offsetWidth)/2),i.style.left=h+"px"),o&&Wa(this,{left:h,top:c,right:h+i.offsetWidth,bottom:c+i.offsetHeight})},triggerOnKeyDown:nt(ul),triggerOnKeyPress:nt(hl),triggerOnKeyUp:cl,triggerOnMouseDown:nt(fl),execCommand:function(n){if(qn.hasOwnProperty(n))return qn[n].call(null,this)},triggerElectric:nt(function(n){wl(this,n)}),findPosH:function(n,i,o,l){var a=1;i<0&&(a=-1,i=-i);for(var s=O(this.doc,n),c=0;c0&&h(o.charAt(l-1));)--l;for(;a.5||this.options.lineWrapping)&&Br(this),U(this,"refresh",this)}),swapDoc:nt(function(n){var i=this.doc;return i.cm=null,this.state.selectingText&&this.state.selectingText(),Ao(this,n),_e(this),this.display.input.reset(),Ye(this,n.scrollLeft,n.scrollTop),this.curOp.forceScroll=!0,_(this,"swapDoc",this,i),i}),phrase:function(n){var i=this.options.phrases;return i&&Object.prototype.hasOwnProperty.call(i,n)?i[n]:n},getInputField:function(){return this.display.input.getField()},getWrapperElement:function(){return this.display.wrapper},getScrollerElement:function(){return this.display.scroller},getGutterElement:function(){return this.display.gutters}},me(t),t.registerHelper=function(n,i,o){r.hasOwnProperty(n)||(r[n]=t[n]={_global:[]}),r[n][i]=o},t.registerGlobalHelper=function(n,i,o,l){t.registerHelper(n,i,l),r[n]._global.push({pred:o,val:l})}}u(Es,"addEditorMethods");function fi(t,e,r,n,i){var o=e,l=r,a=S(t,e.line),s=i&&t.direction=="rtl"?-r:r;function c(){var x=e.line+s;return x=t.first+t.size?!1:(e=new v(x,e.ch,e.sticky),a=S(t,x))}u(c,"findNextLine");function h(x){var w;if(n=="codepoint"){var C=a.text.charCodeAt(e.ch+(r>0?0:-1));if(isNaN(C))w=null;else{var T=r>0?C>=55296&&C<56320:C>=56320&&C<57343;w=new v(e.line,Math.max(0,Math.min(a.text.length,e.ch+r*(T?2:1))),-r)}}else i?w=ys(t.cm,a,e,r):w=si(a,e,r);if(w==null)if(!x&&c())e=ui(i,t.cm,a,e.line,s);else return!1;else e=w;return!0}if(u(h,"moveOnce"),n=="char"||n=="codepoint")h();else if(n=="column")h(!0);else if(n=="word"||n=="group")for(var d=null,p=n=="group",f=t.cm&&t.cm.getHelper(e,"wordChars"),g=!0;!(r<0&&!h(!g));g=!1){var m=a.text.charAt(e.ch)||`
`,y=mn(m,f)?"w":p&&m==`
`?"n":!p||/\s/.test(m)?null:"p";if(p&&!g&&!y&&(y="s"),d&&d!=y){r<0&&(r=1,h(),e.sticky="after");break}if(y&&(d=y),r>0&&!h(!g))break}var b=Un(t,e,o,l,!0);return wr(o,b)&&(b.hitSide=!0),b}u(fi,"findPosH");function Ll(t,e,r,n){var i=t.doc,o=e.left,l;if(n=="page"){var a=Math.min(t.display.wrapper.clientHeight,window.innerHeight||document.documentElement.clientHeight),s=Math.max(a-.5*be(t.display),3);l=(r>0?e.bottom:e.top)+r*s}else n=="line"&&(l=r>0?e.bottom+3:e.top-3);for(var c;c=Er(t,o,l),!!c.outside;){if(r<0?l<=0:l>=i.height){c.hitSide=!0;break}l+=r*5}return c}u(Ll,"findPosV");var P=u(function(t){this.cm=t,this.lastAnchorNode=this.lastAnchorOffset=this.lastFocusNode=this.lastFocusOffset=null,this.polling=new Qt,this.composing=null,this.gracePeriod=!1,this.readDOMTimeout=null},"ContentEditableInput");P.prototype.init=function(t){var e=this,r=this,n=r.cm,i=r.div=t.lineDiv;i.contentEditable=!0,Cl(i,n.options.spellcheck,n.options.autocorrect,n.options.autocapitalize);function o(a){for(var s=a.target;s;s=s.parentNode){if(s==i)return!0;if(/\bCodeMirror-(?:line)?widget\b/.test(s.className))break}return!1}u(o,"belongsToInput"),M(i,"paste",function(a){!o(a)||X(n,a)||bl(a,n)||I<=11&&setTimeout(q(n,function(){return e.updateFromDOM()}),20)}),M(i,"compositionstart",function(a){e.composing={data:a.data,done:!1}}),M(i,"compositionupdate",function(a){e.composing||(e.composing={data:a.data,done:!1})}),M(i,"compositionend",function(a){e.composing&&(a.data!=e.composing.data&&e.readFromDOMSoon(),e.composing.done=!0)}),M(i,"touchstart",function(){return r.forceCompositionEnd()}),M(i,"input",function(){e.composing||e.readFromDOMSoon()});function l(a){if(!(!o(a)||X(n,a))){if(n.somethingSelected())Qn({lineWise:!1,text:n.getSelections()}),a.type=="cut"&&n.replaceSelection("",null,"cut");else if(n.options.lineWiseCopyCut){var s=xl(n);Qn({lineWise:!0,text:s.text}),a.type=="cut"&&n.operation(function(){n.setSelections(s.ranges,0,Dt),n.replaceSelection("",null,"cut")})}else return;if(a.clipboardData){a.clipboardData.clearData();var c=Ot.text.join(`
`);if(a.clipboardData.setData("Text",c),a.clipboardData.getData("Text")==c){a.preventDefault();return}}var h=Sl(),d=h.firstChild;n.display.lineSpace.insertBefore(h,n.display.lineSpace.firstChild),d.value=Ot.text.join(`
`);var p=vt();fn(d),setTimeout(function(){n.display.lineSpace.removeChild(h),p.focus(),p==i&&r.showPrimarySelection()},50)}}u(l,"onCopyCut"),M(i,"copy",l),M(i,"cut",l)},P.prototype.screenReaderLabelChanged=function(t){t?this.div.setAttribute("aria-label",t):this.div.removeAttribute("aria-label")},P.prototype.prepareSelection=function(){var t=go(this.cm,!1);return t.focus=vt()==this.div,t},P.prototype.showSelection=function(t,e){!t||!this.cm.display.view.length||((t.focus||e)&&this.showPrimarySelection(),this.showMultipleSelections(t))},P.prototype.getSelection=function(){return this.cm.display.wrapper.ownerDocument.getSelection()},P.prototype.showPrimarySelection=function(){var t=this.getSelection(),e=this.cm,r=e.doc.sel.primary(),n=r.from(),i=r.to();if(e.display.viewTo==e.display.viewFrom||n.line>=e.display.viewTo||i.line=e.display.viewFrom&&kl(e,n)||{node:a[0].measure.map[2],offset:0},c=i.linet.firstLine()&&(n=v(n.line-1,S(t.doc,n.line-1).length)),i.ch==S(t.doc,i.line).text.length&&i.linee.viewTo-1)return!1;var o,l,a;n.line==e.viewFrom||(o=ie(t,n.line))==0?(l=F(e.view[0].line),a=e.view[0].node):(l=F(e.view[o].line),a=e.view[o-1].node.nextSibling);var s=ie(t,i.line),c,h;if(s==e.view.length-1?(c=e.viewTo-1,h=e.lineDiv.lastChild):(c=F(e.view[s+1].line)-1,h=e.view[s+1].node.previousSibling),!a)return!1;for(var d=t.doc.splitLines(Rs(t,a,h,l,c)),p=te(t.doc,v(l,0),v(c,S(t.doc,c).text.length));d.length>1&&p.length>1;)if(W(d)==W(p))d.pop(),p.pop(),c--;else if(d[0]==p[0])d.shift(),p.shift(),l++;else break;for(var f=0,g=0,m=d[0],y=p[0],b=Math.min(m.length,y.length);fn.ch&&x.charCodeAt(x.length-g-1)==w.charCodeAt(w.length-g-1);)f--,g++;d[d.length-1]=x.slice(0,x.length-g).replace(/^\u200b+/,""),d[0]=d[0].slice(f).replace(/\u200b+$/,"");var T=v(l,f),L=v(c,p.length?W(p).length-g:0);if(d.length>1||d[0]||N(T,L))return Ne(t.doc,d,T,L,"+input"),!0},P.prototype.ensurePolled=function(){this.forceCompositionEnd()},P.prototype.reset=function(){this.forceCompositionEnd()},P.prototype.forceCompositionEnd=function(){this.composing&&(clearTimeout(this.readDOMTimeout),this.composing=null,this.updateFromDOM(),this.div.blur(),this.div.focus())},P.prototype.readFromDOMSoon=function(){var t=this;this.readDOMTimeout==null&&(this.readDOMTimeout=setTimeout(function(){if(t.readDOMTimeout=null,t.composing)if(t.composing.done)t.composing=null;else return;t.updateFromDOM()},80))},P.prototype.updateFromDOM=function(){var t=this;(this.cm.isReadOnly()||!this.pollContent())&&ut(this.cm,function(){return at(t.cm)})},P.prototype.setUneditable=function(t){t.contentEditable="false"},P.prototype.onKeyPress=function(t){t.charCode==0||this.composing||(t.preventDefault(),this.cm.isReadOnly()||q(this.cm,di)(this.cm,String.fromCharCode(t.charCode==null?t.keyCode:t.charCode),0))},P.prototype.readOnlyChanged=function(t){this.div.contentEditable=String(t!="nocursor")},P.prototype.onContextMenu=function(){},P.prototype.resetPosition=function(){},P.prototype.needsContentAttribute=!0;function kl(t,e){var r=Hr(t,e.line);if(!r||r.hidden)return null;var n=S(t.doc,e.line),i=eo(r,n,e.line),o=At(n,t.doc.direction),l="left";if(o){var a=Ee(o,e.ch);l=a%2?"right":"left"}var s=ro(i.map,e.ch,l);return s.offset=s.collapse=="right"?s.end:s.start,s}u(kl,"posToDOM");function Is(t){for(var e=t;e;e=e.parentNode)if(/CodeMirror-gutter-wrapper/.test(e.className))return!0;return!1}u(Is,"isInGutter");function We(t,e){return e&&(t.bad=!0),t}u(We,"badPos");function Rs(t,e,r,n,i){var o="",l=!1,a=t.doc.lineSeparator(),s=!1;function c(f){return function(g){return g.id==f}}u(c,"recognizeMarker");function h(){l&&(o+=a,s&&(o+=a),l=s=!1)}u(h,"close");function d(f){f&&(h(),o+=f)}u(d,"addText");function p(f){if(f.nodeType==1){var g=f.getAttribute("cm-text");if(g){d(g);return}var m=f.getAttribute("cm-marker"),y;if(m){var b=t.findMarks(v(n,0),v(i+1,0),c(+m));b.length&&(y=b[0].find(0))&&d(te(t.doc,y.from,y.to).join(a));return}if(f.getAttribute("contenteditable")=="false")return;var x=/^(pre|div|p|li|table|br)$/i.test(f.nodeName);if(!/^br$/i.test(f.nodeName)&&f.textContent.length==0)return;x&&h();for(var w=0;w=9&&e.hasSelection&&(e.hasSelection=null),r.poll()}),M(i,"paste",function(l){X(n,l)||bl(l,n)||(n.state.pasteIncoming=+new Date,r.fastPoll())});function o(l){if(!X(n,l)){if(n.somethingSelected())Qn({lineWise:!1,text:n.getSelections()});else if(n.options.lineWiseCopyCut){var a=xl(n);Qn({lineWise:!0,text:a.text}),l.type=="cut"?n.setSelections(a.ranges,null,Dt):(r.prevInput="",i.value=a.text.join(`
`),fn(i))}else return;l.type=="cut"&&(n.state.cutIncoming=+new Date)}}u(o,"prepareCopyCut"),M(i,"cut",o),M(i,"copy",o),M(t.scroller,"paste",function(l){if(!(Ft(t,l)||X(n,l))){if(!i.dispatchEvent){n.state.pasteIncoming=+new Date,r.focus();return}var a=new Event("paste");a.clipboardData=l.clipboardData,i.dispatchEvent(a)}}),M(t.lineSpace,"selectstart",function(l){Ft(t,l)||lt(l)}),M(i,"compositionstart",function(){var l=n.getCursor("from");r.composing&&r.composing.range.clear(),r.composing={start:l,range:n.markText(l,n.getCursor("to"),{className:"CodeMirror-composing"})}}),M(i,"compositionend",function(){r.composing&&(r.poll(),r.composing.range.clear(),r.composing=null)})},G.prototype.createField=function(t){this.wrapper=Sl(),this.textarea=this.wrapper.firstChild},G.prototype.screenReaderLabelChanged=function(t){t?this.textarea.setAttribute("aria-label",t):this.textarea.removeAttribute("aria-label")},G.prototype.prepareSelection=function(){var t=this.cm,e=t.display,r=t.doc,n=go(t);if(t.options.moveInputWithCursor){var i=St(t,r.sel.primary().head,"div"),o=e.wrapper.getBoundingClientRect(),l=e.lineDiv.getBoundingClientRect();n.teTop=Math.max(0,Math.min(e.wrapper.clientHeight-10,i.top+l.top-o.top)),n.teLeft=Math.max(0,Math.min(e.wrapper.clientWidth-10,i.left+l.left-o.left))}return n},G.prototype.showSelection=function(t){var e=this.cm,r=e.display;gt(r.cursorDiv,t.cursors),gt(r.selectionDiv,t.selection),t.teTop!=null&&(this.wrapper.style.top=t.teTop+"px",this.wrapper.style.left=t.teLeft+"px")},G.prototype.reset=function(t){if(!(this.contextMenuPending||this.composing)){var e=this.cm;if(e.somethingSelected()){this.prevInput="";var r=e.getSelection();this.textarea.value=r,e.state.focused&&fn(this.textarea),A&&I>=9&&(this.hasSelection=r)}else t||(this.prevInput=this.textarea.value="",A&&I>=9&&(this.hasSelection=null))}},G.prototype.getField=function(){return this.textarea},G.prototype.supportsTouch=function(){return!1},G.prototype.focus=function(){if(this.cm.options.readOnly!="nocursor"&&(!dn||vt()!=this.textarea))try{this.textarea.focus()}catch{}},G.prototype.blur=function(){this.textarea.blur()},G.prototype.resetPosition=function(){this.wrapper.style.top=this.wrapper.style.left=0},G.prototype.receivedFocus=function(){this.slowPoll()},G.prototype.slowPoll=function(){var t=this;this.pollingFast||this.polling.set(this.cm.options.pollInterval,function(){t.poll(),t.cm.state.focused&&t.slowPoll()})},G.prototype.fastPoll=function(){var t=!1,e=this;e.pollingFast=!0;function r(){var n=e.poll();!n&&!t?(t=!0,e.polling.set(60,r)):(e.pollingFast=!1,e.slowPoll())}u(r,"p"),e.polling.set(20,r)},G.prototype.poll=function(){var t=this,e=this.cm,r=this.textarea,n=this.prevInput;if(this.contextMenuPending||!e.state.focused||Js(r)&&!n&&!this.composing||e.isReadOnly()||e.options.disableInput||e.state.keySeq)return!1;var i=r.value;if(i==n&&!e.somethingSelected())return!1;if(A&&I>=9&&this.hasSelection===i||xt&&/[\uf700-\uf7ff]/.test(i))return e.display.input.reset(),!1;if(e.doc.sel==e.display.selForContextMenu){var o=i.charCodeAt(0);if(o==8203&&!n&&(n=""),o==8666)return this.reset(),this.cm.execCommand("undo")}for(var l=0,a=Math.min(n.length,i.length);l1e3||i.indexOf(`
`)>-1?r.value=t.prevInput="":t.prevInput=i,t.composing&&(t.composing.range.clear(),t.composing.range=e.markText(t.composing.start,e.getCursor("to"),{className:"CodeMirror-composing"}))}),!0},G.prototype.ensurePolled=function(){this.pollingFast&&this.poll()&&(this.pollingFast=!1)},G.prototype.onKeyPress=function(){A&&I>=9&&(this.hasSelection=null),this.fastPoll()},G.prototype.onContextMenu=function(t){var e=this,r=e.cm,n=r.display,i=e.textarea;e.contextMenuPending&&e.contextMenuPending();var o=re(r,t),l=n.scroller.scrollTop;if(!o||kt)return;var a=r.options.resetSelectionOnContextMenu;a&&r.doc.sel.contains(o)==-1&&q(r,tt)(r.doc,jt(o),Dt);var s=i.style.cssText,c=e.wrapper.style.cssText,h=e.wrapper.offsetParent.getBoundingClientRect();e.wrapper.style.cssText="position: static",i.style.cssText=`position: absolute; width: 30px; height: 30px;
top: `+(t.clientY-h.top-5)+"px; left: "+(t.clientX-h.left-5)+`px;
z-index: 1000; background: `+(A?"rgba(255, 255, 255, .05)":"transparent")+`;
outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);`;var d;ot&&(d=window.scrollY),n.input.focus(),ot&&window.scrollTo(null,d),n.input.reset(),r.somethingSelected()||(i.value=e.prevInput=" "),e.contextMenuPending=f,n.selForContextMenu=r.doc.sel,clearTimeout(n.detectingSelectAll);function p(){if(i.selectionStart!=null){var m=r.somethingSelected(),y=""+(m?i.value:"");i.value="⇚",i.value=y,e.prevInput=m?"":"",i.selectionStart=1,i.selectionEnd=y.length,n.selForContextMenu=r.doc.sel}}u(p,"prepareSelectAllHack");function f(){if(e.contextMenuPending==f&&(e.contextMenuPending=!1,e.wrapper.style.cssText=c,i.style.cssText=s,A&&I<9&&n.scrollbars.setScrollTop(n.scroller.scrollTop=l),i.selectionStart!=null)){(!A||A&&I<9)&&p();var m=0,y=u(function(){n.selForContextMenu==r.doc.sel&&i.selectionStart==0&&i.selectionEnd>0&&e.prevInput==""?q(r,Vo)(r):m++<10?n.detectingSelectAll=setTimeout(y,500):(n.selForContextMenu=null,n.input.reset())},"poll");n.detectingSelectAll=setTimeout(y,200)}}if(u(f,"rehide"),A&&I>=9&&p(),gi){Ie(t);var g=u(function(){mt(window,"mouseup",g),setTimeout(f,20)},"mouseup");M(window,"mouseup",g)}else setTimeout(f,50)},G.prototype.readOnlyChanged=function(t){t||this.reset(),this.textarea.disabled=t=="nocursor",this.textarea.readOnly=!!t},G.prototype.setUneditable=function(){},G.prototype.needsContentAttribute=!1;function Bs(t,e){if(e=e?$t(e):{},e.value=t.value,!e.tabindex&&t.tabIndex&&(e.tabindex=t.tabIndex),!e.placeholder&&t.placeholder&&(e.placeholder=t.placeholder),e.autofocus==null){var r=vt();e.autofocus=r==t||t.getAttribute("autofocus")!=null&&r==document.body}function n(){t.value=a.getValue()}u(n,"save");var i;if(t.form&&(M(t.form,"submit",n),!e.leaveSubmitMethodAlone)){var o=t.form;i=o.submit;try{var l=o.submit=function(){n(),o.submit=i,o.submit(),o.submit=l}}catch{}}e.finishInit=function(s){s.save=n,s.getTextArea=function(){return t},s.toTextArea=function(){s.toTextArea=isNaN,n(),t.parentNode.removeChild(s.getWrapperElement()),t.style.display="",t.form&&(mt(t.form,"submit",n),!e.leaveSubmitMethodAlone&&typeof t.form.submit=="function"&&(t.form.submit=i))}},t.style.display="none";var a=R(function(s){return t.parentNode.insertBefore(s,t.nextSibling)},e);return a}u(Bs,"fromTextArea");function Us(t){t.off=mt,t.on=M,t.wheelEventPixels=_a,t.Doc=ct,t.splitLines=Ti,t.countColumn=yt,t.findColumn=sr,t.isWordChar=hr,t.Pass=ar,t.signal=U,t.Line=Ke,t.changeEnd=Xt,t.scrollbarModel=Fa,t.Pos=v,t.cmpPos=N,t.modes=Ni,t.mimeModes=Re,t.resolveMode=yn,t.getMode=mr,t.modeExtensions=ze,t.extendMode=Ul,t.copyState=Jt,t.startState=Oi,t.innerMode=vr,t.commands=qn,t.keyMap=qt,t.keyName=rl,t.isModifierKey=el,t.lookupKey=De,t.normalizeKeyMap=vs,t.StringStream=K,t.SharedTextMarker=Vn,t.TextMarker=se,t.LineWidget=Kn,t.e_preventDefault=lt,t.e_stopPropagation=Ci,t.e_stop=Ie,t.addClass=Zt,t.contains=zt,t.rmClass=fe,t.keyNames=ue}u(Us,"addLegacyProps"),Ws(R),Es(R);var au="iter insert remove copy getEditor constructor".split(" ");for(var pi in ct.prototype)ct.prototype.hasOwnProperty(pi)&&J(au,pi)<0&&(R.prototype[pi]=function(t){return function(){return t.apply(this.doc,arguments)}}(ct.prototype[pi]));return me(ct),R.inputStyles={textarea:G,contenteditable:P},R.defineMode=function(t){!R.defaults.mode&&t!="null"&&(R.defaults.mode=t),zl.apply(this,arguments)},R.defineMIME=Bl,R.defineMode("null",function(){return{token:function(t){return t.skipToEnd()}}}),R.defineMIME("text/plain","null"),R.defineExtension=function(t,e){R.prototype[t]=e},R.defineDocExtension=function(t,e){ct.prototype[t]=e},R.fromTextArea=Bs,Us(R),R.version="5.65.3",R})}(Gs)),Gs.exports}u(hu,"requireCodemirror");export{hu as c,cu as h};
================================================
FILE: backend/src/main/resources/ui/graphiql/assets/comment.es-39699bae.js
================================================
import{c as K,h as Q}from"./codemirror.es2-5884f31a.js";var X=Object.defineProperty,I=(S,A)=>X(S,"name",{value:A,configurable:!0});function q(S,A){for(var f=0;fp[s]})}}}return Object.freeze(Object.defineProperty(S,Symbol.toStringTag,{value:"Module"}))}I(q,"_mergeNamespaces");var $={exports:{}};(function(S,A){(function(f){f(K())})(function(f){var p={},s=/[^\s\u00a0]/,r=f.Pos,J=f.cmpPos;function N(t){var i=t.search(s);return i==-1?0:i}I(N,"firstNonWS"),f.commands.toggleComment=function(t){t.toggleComment()},f.defineExtension("toggleComment",function(t){t||(t=p);for(var i=this,n=1/0,e=this.listSelections(),g=null,m=e.length-1;m>=0;m--){var o=e[m].from(),l=e[m].to();o.line>=n||(l.line>=n&&(l=r(n,0)),n=o.line,g==null?i.uncomment(o,l,t)?g="un":(i.lineComment(o,l,t),g="line"):g=="un"?i.uncomment(o,l,t):i.lineComment(o,l,t))}});function z(t,i,n){return/\bstring\b/.test(t.getTokenTypeAt(r(i.line,0)))&&!/^[\'\"\`]/.test(n)}I(z,"probablyInsideString");function j(t,i){var n=t.getMode();return n.useInnerComments===!1||!n.innerMode?n:t.getModeAt(i)}I(j,"getMode"),f.defineExtension("lineComment",function(t,i,n){n||(n=p);var e=this,g=j(e,t),m=e.getLine(t.line);if(!(m==null||z(e,t,m))){var o=n.lineComment||g.lineComment;if(!o){(n.blockCommentStart||g.blockCommentStart)&&(n.fullLines=!0,e.blockComment(t,i,n));return}var l=Math.min(i.ch!=0||i.line==t.line?i.line+1:i.line,e.lastLine()+1),b=n.padding==null?" ":n.padding,c=n.commentBlankLines||t.line==i.line;e.operation(function(){if(n.indent){for(var d=null,a=t.line;ah.length)&&(d=h)}for(var a=t.line;al||e.operation(function(){if(n.fullLines!=!1){var c=s.test(e.getLine(l));e.replaceRange(b+o,r(l)),e.replaceRange(m+b,r(t.line,0));var d=n.blockCommentLead||g.blockCommentLead;if(d!=null)for(var a=t.line+1;a<=l;++a)(a!=l||c)&&e.replaceRange(d+b,r(a,0))}else{var u=J(e.getCursor("to"),i)==0,h=!e.somethingSelected();e.replaceRange(o,i),u&&e.setSelection(h?i:e.getCursor("from"),i),e.replaceRange(m,t)}})}}),f.defineExtension("uncomment",function(t,i,n){n||(n=p);var e=this,g=j(e,t),m=Math.min(i.ch!=0||i.line==t.line?i.line:i.line-1,e.lastLine()),o=Math.min(t.line,m),l=n.lineComment||g.lineComment,b=[],c=n.padding==null?" ":n.padding,d;e:{if(!l)break e;for(var a=o;a<=m;++a){var u=e.getLine(a),h=u.indexOf(l);if(h>-1&&!/comment/.test(e.getTokenTypeAt(r(a,h+1)))&&(h=-1),h==-1&&s.test(u)||h>-1&&s.test(u.slice(0,h)))break e;b.push(u)}if(e.operation(function(){for(var C=o;C<=m;++C){var y=b[C-o],O=y.indexOf(l),k=O+l.length;O<0||(y.slice(k,k+c.length)==c&&(k+=c.length),d=!0,e.replaceRange("",r(C,O),r(C,k)))}}),d)return!0}var v=n.blockCommentStart||g.blockCommentStart,L=n.blockCommentEnd||g.blockCommentEnd;if(!v||!L)return!1;var w=n.blockCommentLead||g.blockCommentLead,E=e.getLine(o),P=E.indexOf(v);if(P==-1)return!1;var M=m==o?E:e.getLine(m),R=M.indexOf(L,m==o?P+v.length:0),B=r(o,P+1),D=r(m,R+1);if(R==-1||!/comment/.test(e.getTokenTypeAt(B))||!/comment/.test(e.getTokenTypeAt(D))||e.getRange(B,D,`
`).indexOf(L)>-1)return!1;var x=E.lastIndexOf(v,t.ch),T=x==-1?-1:E.slice(0,t.ch).indexOf(L,x+v.length);if(x!=-1&&T!=-1&&T+L.length!=t.ch)return!1;T=M.indexOf(L,i.ch);var W=M.slice(i.ch).lastIndexOf(v,T-i.ch);return x=T==-1||W==-1?-1:i.ch+W,T!=-1&&x!=-1&&x!=i.ch?!1:(e.operation(function(){e.replaceRange("",r(m,R-(c&&M.slice(R-c.length,R)==c?c.length:0)),r(m,R+L.length));var C=P+v.length;if(c&&E.slice(C,C+c.length)==c&&(C+=c.length),e.replaceRange("",r(o,P),r(o,C)),w)for(var y=o+1;y<=m;++y){var O=e.getLine(y),k=O.indexOf(w);if(!(k==-1||s.test(O.slice(0,k)))){var _=k+w.length;c&&O.slice(_,_+c.length)==c&&(_+=c.length),e.replaceRange("",r(y,k),r(y,_))}}}),!0)})})})();var F=$.exports;const G=Q(F),U=q({__proto__:null,default:G},[F]);export{U as c};
================================================
FILE: backend/src/main/resources/ui/graphiql/assets/dialog.es-b2776d29.js
================================================
import{c as b,h as O}from"./codemirror.es2-5884f31a.js";var T=Object.defineProperty,g=(p,m)=>T(p,"name",{value:m,configurable:!0});function C(p,m){for(var o=0;oc[s]})}}}return Object.freeze(Object.defineProperty(p,Symbol.toStringTag,{value:"Module"}))}g(C,"_mergeNamespaces");var k={exports:{}};(function(p,m){(function(o){o(b())})(function(o){function c(u,l,e){var r=u.getWrapperElement(),a;return a=r.appendChild(document.createElement("div")),e?a.className="CodeMirror-dialog CodeMirror-dialog-bottom":a.className="CodeMirror-dialog CodeMirror-dialog-top",typeof l=="string"?a.innerHTML=l:a.appendChild(l),o.addClass(r,"dialog-opened"),a}g(c,"dialogDiv");function s(u,l){u.state.currentNotificationClose&&u.state.currentNotificationClose(),u.state.currentNotificationClose=l}g(s,"closeNotification"),o.defineExtension("openDialog",function(u,l,e){e||(e={}),s(this,null);var r=c(this,u,e.bottom),a=!1,f=this;function i(t){if(typeof t=="string")n.value=t;else{if(a)return;a=!0,o.rmClass(r.parentNode,"dialog-opened"),r.parentNode.removeChild(r),f.focus(),e.onClose&&e.onClose(r)}}g(i,"close");var n=r.getElementsByTagName("input")[0],d;return n?(n.focus(),e.value&&(n.value=e.value,e.selectValueOnOpen!==!1&&n.select()),e.onInput&&o.on(n,"input",function(t){e.onInput(t,n.value,i)}),e.onKeyUp&&o.on(n,"keyup",function(t){e.onKeyUp(t,n.value,i)}),o.on(n,"keydown",function(t){e&&e.onKeyDown&&e.onKeyDown(t,n.value,i)||((t.keyCode==27||e.closeOnEnter!==!1&&t.keyCode==13)&&(n.blur(),o.e_stop(t),i()),t.keyCode==13&&l(n.value,t))}),e.closeOnBlur!==!1&&o.on(r,"focusout",function(t){t.relatedTarget!==null&&i()})):(d=r.getElementsByTagName("button")[0])&&(o.on(d,"click",function(){i(),f.focus()}),e.closeOnBlur!==!1&&o.on(d,"blur",i),d.focus()),i}),o.defineExtension("openConfirm",function(u,l,e){s(this,null);var r=c(this,u,e&&e.bottom),a=r.getElementsByTagName("button"),f=!1,i=this,n=1;function d(){f||(f=!0,o.rmClass(r.parentNode,"dialog-opened"),r.parentNode.removeChild(r),i.focus())}g(d,"close"),a[0].focus();for(var t=0;tj(C,"name",{value:y,configurable:!0});function U(C,y){for(var a=0;ac[g]})}}}return Object.freeze(Object.defineProperty(C,Symbol.toStringTag,{value:"Module"}))}d(U,"_mergeNamespaces");var L={exports:{}},V={exports:{}},E;function S(){return E||(E=1,function(C,y){(function(a){a(P())})(function(a){function c(e,t,i,f){if(i&&i.call){var s=i;i=null}else var s=m(e,i,"rangeFinder");typeof t=="number"&&(t=a.Pos(t,0));var O=m(e,i,"minFoldSize");function w(l){var r=s(e,t);if(!r||r.to.line-r.from.linee.firstLine();)t=a.Pos(t.line-1,0),u=w(!1);if(!(!u||u.cleared||f==="unfold")){var o=g(e,i,u);a.on(o,"mousedown",function(l){n.clear(),a.e_preventDefault(l)});var n=e.markText(u.from,u.to,{replacedWith:o,clearOnEnter:m(e,i,"clearOnEnter"),__isFold:!0});n.on("clear",function(l,r){a.signal(e,"unfold",e,l,r)}),a.signal(e,"fold",e,u.from,u.to)}}d(c,"doFold");function g(e,t,i){var f=m(e,t,"widget");if(typeof f=="function"&&(f=f(i.from,i.to)),typeof f=="string"){var s=document.createTextNode(f);f=document.createElement("span"),f.appendChild(s),f.className="CodeMirror-foldmarker"}else f&&(f=f.cloneNode(!0));return f}d(g,"makeWidget"),a.newFoldFunction=function(e,t){return function(i,f){c(i,f,{rangeFinder:e,widget:t})}},a.defineExtension("foldCode",function(e,t,i){c(this,e,t,i)}),a.defineExtension("isFolded",function(e){for(var t=this.findMarksAt(e),i=0;i=v){if(b&&h&&b.test(h.className))return;_=e(r.indicatorOpen)}}!_&&!h||o.setGutterMarker(M,r.gutter,_)})}d(t,"updateFoldInfo");function i(o){return new RegExp("(^|\\s)"+o+"(?:$|\\s)\\s*")}d(i,"classTest");function f(o){var n=o.getViewport(),l=o.state.foldGutter;l&&(o.operation(function(){t(o,n.from,n.to)}),l.from=n.from,l.to=n.to)}d(f,"updateInViewport");function s(o,n,l){var r=o.state.foldGutter;if(r){var p=r.options;if(l==p.gutter){var v=m(o,n);v?v.clear():o.foldCode(c(n,0),p)}}}d(s,"onGutterClick");function O(o){var n=o.state.foldGutter;if(n){var l=n.options;n.from=n.to=0,clearTimeout(n.changeUpdate),n.changeUpdate=setTimeout(function(){f(o)},l.foldOnChangeTimeSpan||600)}}d(O,"onChange");function w(o){var n=o.state.foldGutter;if(n){var l=n.options;clearTimeout(n.changeUpdate),n.changeUpdate=setTimeout(function(){var r=o.getViewport();n.from==n.to||r.from-n.to>20||n.from-r.to>20?f(o):o.operation(function(){r.fromn.to&&(t(o,n.to,r.to),n.to=r.to)})},l.updateViewportTimeSpan||400)}}d(w,"onViewportChange");function u(o,n){var l=o.state.foldGutter;if(l){var r=n.line;r>=l.from&&ra(t,"name",{value:n,configurable:!0});function f(t,n){const r=[];let e=t;for(;e!=null&&e.kind;)r.push(e),e=e.prevState;for(let o=r.length-1;o>=0;o--)n(r[o])}l(f,"forEachState");export{f as s};
================================================
FILE: backend/src/main/resources/ui/graphiql/assets/hint.es-1418191b.js
================================================
import{C as n}from"./codemirror.es-52e8b92d.js";import"./show-hint.es-b981493e.js";import{g as c}from"./index-27dc12ba.js";import{P as g}from"./Range-52ddcb6a.js";import"./codemirror.es2-5884f31a.js";n.registerHelper("hint","graphql",(i,a)=>{const{schema:s,externalFragments:p}=a;if(!s)return;const r=i.getCursor(),t=i.getTokenAt(r),l=t.type!==null&&/"|\w/.test(t.string[0])?t.start:t.end,m=new g(r.line,l),e={list:c(s,i.getValue(),m,t,p).map(o=>({text:o.label,type:o.type,description:o.documentation,isDeprecated:o.isDeprecated,deprecationReason:o.deprecationReason})),from:{line:r.line,ch:l},to:{line:r.line,ch:t.end}};return e!=null&&e.list&&e.list.length>0&&(e.from=n.Pos(e.from.line,e.from.ch),e.to=n.Pos(e.to.line,e.to.ch),n.signal(i,"hasCompletion",i,e,t)),e});
================================================
FILE: backend/src/main/resources/ui/graphiql/assets/hint.es2-598d3bfe.js
================================================
import{C as f}from"./codemirror.es-52e8b92d.js";import{s as L}from"./forEachState.es-b2033c2b.js";import"./codemirror.es2-5884f31a.js";import{l as h,X as b,Y as T,a3 as d,F as j,W as D}from"./index-27dc12ba.js";var N=Object.defineProperty,p=(i,n)=>N(i,"name",{value:n,configurable:!0});function u(i,n,t){const r=x(t,m(n.string));if(!r)return;const e=n.type!==null&&/"|\w/.test(n.string[0])?n.start:n.end;return{list:r,from:{line:i.line,ch:e},to:{line:i.line,ch:n.end}}}p(u,"hintList");function x(i,n){if(!n)return y(i,r=>!r.isDeprecated);const t=i.map(r=>({proximity:V(m(r.text),n),entry:r}));return y(y(t,r=>r.proximity<=2),r=>!r.entry.isDeprecated).sort((r,e)=>(r.entry.isDeprecated?1:0)-(e.entry.isDeprecated?1:0)||r.proximity-e.proximity||r.entry.text.length-e.entry.text.length).map(r=>r.entry)}p(x,"filterAndSortList");function y(i,n){const t=i.filter(n);return t.length===0?i:t}p(y,"filterNonEmpty");function m(i){return i.toLowerCase().replaceAll(/\W/g,"")}p(m,"normalizeText");function V(i,n){let t=v(n,i);return i.length>n.length&&(t-=i.length-n.length-1,t+=i.indexOf(n)===0?0:.5),t}p(V,"getProximity");function v(i,n){let t,r;const e=[],a=i.length,s=n.length;for(t=0;t<=a;t++)e[t]=[t];for(r=1;r<=s;r++)e[0][r]=r;for(t=1;t<=a;t++)for(r=1;r<=s;r++){const c=i[t-1]===n[r-1]?0:1;e[t][r]=Math.min(e[t-1][r]+1,e[t][r-1]+1,e[t-1][r-1]+c),t>1&&r>1&&i[t-1]===n[r-2]&&i[t-2]===n[r-1]&&(e[t][r]=Math.min(e[t][r],e[t-2][r-2]+c))}return e[a][s]}p(v,"lexicalDistance");f.registerHelper("hint","graphql-variables",(i,n)=>{const t=i.getCursor(),r=i.getTokenAt(t),e=O(t,r,n);return e!=null&&e.list&&e.list.length>0&&(e.from=f.Pos(e.from.line,e.from.ch),e.to=f.Pos(e.to.line,e.to.ch),f.signal(i,"hasCompletion",i,e,r)),e});function O(i,n,t){const r=n.state.kind==="Invalid"?n.state.prevState:n.state,{kind:e,step:a}=r;if(e==="Document"&&a===0)return u(i,n,[{text:"{"}]);const{variableToType:s}=t;if(!s)return;const c=k(s,n.state);if(e==="Document"||e==="Variable"&&a===0){const o=Object.keys(s);return u(i,n,o.map(l=>({text:`"${l}": `,type:s[l]})))}if((e==="ObjectValue"||e==="ObjectField"&&a===0)&&c.fields){const o=Object.keys(c.fields).map(l=>c.fields[l]);return u(i,n,o.map(l=>({text:`"${l.name}": `,type:l.type,description:l.description})))}if(e==="StringValue"||e==="NumberValue"||e==="BooleanValue"||e==="NullValue"||e==="ListValue"&&a===1||e==="ObjectField"&&a===2||e==="Variable"&&a===2){const o=c.type?h(c.type):void 0;if(o instanceof b)return u(i,n,[{text:"{"}]);if(o instanceof T){const l=o.getValues();return u(i,n,l.map(g=>({text:`"${g.name}"`,type:o,description:g.description})))}if(o===d)return u(i,n,[{text:"true",type:d,description:"Not false."},{text:"false",type:d,description:"Not true."}])}}p(O,"getVariablesHint");function k(i,n){const t={type:null,fields:null};return L(n,r=>{switch(r.kind){case"Variable":{t.type=i[r.name];break}case"ListValue":{const e=t.type?j(t.type):void 0;t.type=e instanceof D?e.ofType:null;break}case"ObjectValue":{const e=t.type?h(t.type):void 0;t.fields=e instanceof b?e.getFields():null;break}case"ObjectField":{const e=r.name&&t.fields?t.fields[r.name]:null;t.type=e==null?void 0:e.type;break}}}),t}p(k,"getTypeInfo");
================================================
FILE: backend/src/main/resources/ui/graphiql/assets/index-27dc12ba.js
================================================
function G2(e,t){for(var n=0;nr[o]})}}}return Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const o of document.querySelectorAll('link[rel="modulepreload"]'))r(o);new MutationObserver(o=>{for(const i of o)if(i.type==="childList")for(const s of i.addedNodes)s.tagName==="LINK"&&s.rel==="modulepreload"&&r(s)}).observe(document,{childList:!0,subtree:!0});function n(o){const i={};return o.integrity&&(i.integrity=o.integrity),o.referrerPolicy&&(i.referrerPolicy=o.referrerPolicy),o.crossOrigin==="use-credentials"?i.credentials="include":o.crossOrigin==="anonymous"?i.credentials="omit":i.credentials="same-origin",i}function r(o){if(o.ep)return;o.ep=!0;const i=n(o);fetch(o.href,i)}})();function Wi(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}function W2(e){if(e.__esModule)return e;var t=e.default;if(typeof t=="function"){var n=function r(){return this instanceof r?Reflect.construct(t,arguments,this.constructor):t.apply(this,arguments)};n.prototype=t.prototype}else n={};return Object.defineProperty(n,"__esModule",{value:!0}),Object.keys(e).forEach(function(r){var o=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(n,r,o.get?o:{enumerable:!0,get:function(){return e[r]}})}),n}var _b={exports:{}},Su={},Sb={exports:{}},ue={};/**
* @license React
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/var Oa=Symbol.for("react.element"),Q2=Symbol.for("react.portal"),Y2=Symbol.for("react.fragment"),Z2=Symbol.for("react.strict_mode"),X2=Symbol.for("react.profiler"),J2=Symbol.for("react.provider"),K2=Symbol.for("react.context"),ek=Symbol.for("react.forward_ref"),tk=Symbol.for("react.suspense"),nk=Symbol.for("react.memo"),rk=Symbol.for("react.lazy"),x0=Symbol.iterator;function ok(e){return e===null||typeof e!="object"?null:(e=x0&&e[x0]||e["@@iterator"],typeof e=="function"?e:null)}var Cb={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},Tb=Object.assign,kb={};function Qi(e,t,n){this.props=e,this.context=t,this.refs=kb,this.updater=n||Cb}Qi.prototype.isReactComponent={};Qi.prototype.setState=function(e,t){if(typeof e!="object"&&typeof e!="function"&&e!=null)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,e,t,"setState")};Qi.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,"forceUpdate")};function Nb(){}Nb.prototype=Qi.prototype;function Kh(e,t,n){this.props=e,this.context=t,this.refs=kb,this.updater=n||Cb}var em=Kh.prototype=new Nb;em.constructor=Kh;Tb(em,Qi.prototype);em.isPureReactComponent=!0;var w0=Array.isArray,Ab=Object.prototype.hasOwnProperty,tm={current:null},Db={key:!0,ref:!0,__self:!0,__source:!0};function Ib(e,t,n){var r,o={},i=null,s=null;if(t!=null)for(r in t.ref!==void 0&&(s=t.ref),t.key!==void 0&&(i=""+t.key),t)Ab.call(t,r)&&!Db.hasOwnProperty(r)&&(o[r]=t[r]);var a=arguments.length-2;if(a===1)o.children=n;else if(1>>1,ee=D[Z];if(0>>1;Zo(z,U))Yo(be,z)?(D[Z]=be,D[Y]=U,Z=Y):(D[Z]=z,D[j]=U,Z=j);else if(Yo(be,U))D[Z]=be,D[Y]=U,Z=Y;else break e}}return P}function o(D,P){var U=D.sortIndex-P.sortIndex;return U!==0?U:D.id-P.id}if(typeof performance=="object"&&typeof performance.now=="function"){var i=performance;e.unstable_now=function(){return i.now()}}else{var s=Date,a=s.now();e.unstable_now=function(){return s.now()-a}}var l=[],c=[],u=1,d=null,p=3,f=!1,m=!1,v=!1,b=typeof setTimeout=="function"?setTimeout:null,y=typeof clearTimeout=="function"?clearTimeout:null,g=typeof setImmediate<"u"?setImmediate:null;typeof navigator<"u"&&navigator.scheduling!==void 0&&navigator.scheduling.isInputPending!==void 0&&navigator.scheduling.isInputPending.bind(navigator.scheduling);function E(D){for(var P=n(c);P!==null;){if(P.callback===null)r(c);else if(P.startTime<=D)r(c),P.sortIndex=P.expirationTime,t(l,P);else break;P=n(c)}}function x(D){if(v=!1,E(D),!m)if(n(l)!==null)m=!0,R(w);else{var P=n(c);P!==null&&I(x,P.startTime-D)}}function w(D,P){m=!1,v&&(v=!1,y(A),A=-1),f=!0;var U=p;try{for(E(P),d=n(l);d!==null&&(!(d.expirationTime>P)||D&&!q());){var Z=d.callback;if(typeof Z=="function"){d.callback=null,p=d.priorityLevel;var ee=Z(d.expirationTime<=P);P=e.unstable_now(),typeof ee=="function"?d.callback=ee:d===n(l)&&r(l),E(P)}else r(l);d=n(l)}if(d!==null)var te=!0;else{var j=n(c);j!==null&&I(x,j.startTime-P),te=!1}return te}finally{d=null,p=U,f=!1}}var C=!1,T=null,A=-1,S=5,k=-1;function q(){return!(e.unstable_now()-kD||125Z?(D.sortIndex=U,t(c,D),n(l)===null&&D===n(c)&&(v?(y(A),A=-1):v=!0,I(x,U-Z))):(D.sortIndex=ee,t(l,D),m||f||(m=!0,R(w))),D},e.unstable_shouldYield=q,e.unstable_wrapCallback=function(D){var P=p;return function(){var U=p;p=P;try{return D.apply(this,arguments)}finally{p=U}}}})(Pb);Ob.exports=Pb;var mk=Ob.exports;/**
* @license React
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/var $b=h,qt=mk;function W(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),Yd=Object.prototype.hasOwnProperty,vk=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,S0={},C0={};function gk(e){return Yd.call(C0,e)?!0:Yd.call(S0,e)?!1:vk.test(e)?C0[e]=!0:(S0[e]=!0,!1)}function yk(e,t,n,r){if(n!==null&&n.type===0)return!1;switch(typeof t){case"function":case"symbol":return!0;case"boolean":return r?!1:n!==null?!n.acceptsBooleans:(e=e.toLowerCase().slice(0,5),e!=="data-"&&e!=="aria-");default:return!1}}function Ek(e,t,n,r){if(t===null||typeof t>"u"||yk(e,t,n,r))return!0;if(r)return!1;if(n!==null)switch(n.type){case 3:return!t;case 4:return t===!1;case 5:return isNaN(t);case 6:return isNaN(t)||1>t}return!1}function St(e,t,n,r,o,i,s){this.acceptsBooleans=t===2||t===3||t===4,this.attributeName=r,this.attributeNamespace=o,this.mustUseProperty=n,this.propertyName=e,this.type=t,this.sanitizeURL=i,this.removeEmptyString=s}var st={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach(function(e){st[e]=new St(e,0,!1,e,null,!1,!1)});[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach(function(e){var t=e[0];st[t]=new St(t,1,!1,e[1],null,!1,!1)});["contentEditable","draggable","spellCheck","value"].forEach(function(e){st[e]=new St(e,2,!1,e.toLowerCase(),null,!1,!1)});["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach(function(e){st[e]=new St(e,2,!1,e,null,!1,!1)});"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach(function(e){st[e]=new St(e,3,!1,e.toLowerCase(),null,!1,!1)});["checked","multiple","muted","selected"].forEach(function(e){st[e]=new St(e,3,!0,e,null,!1,!1)});["capture","download"].forEach(function(e){st[e]=new St(e,4,!1,e,null,!1,!1)});["cols","rows","size","span"].forEach(function(e){st[e]=new St(e,6,!1,e,null,!1,!1)});["rowSpan","start"].forEach(function(e){st[e]=new St(e,5,!1,e.toLowerCase(),null,!1,!1)});var rm=/[\-:]([a-z])/g;function om(e){return e[1].toUpperCase()}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach(function(e){var t=e.replace(rm,om);st[t]=new St(t,1,!1,e,null,!1,!1)});"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach(function(e){var t=e.replace(rm,om);st[t]=new St(t,1,!1,e,"http://www.w3.org/1999/xlink",!1,!1)});["xml:base","xml:lang","xml:space"].forEach(function(e){var t=e.replace(rm,om);st[t]=new St(t,1,!1,e,"http://www.w3.org/XML/1998/namespace",!1,!1)});["tabIndex","crossOrigin"].forEach(function(e){st[e]=new St(e,1,!1,e.toLowerCase(),null,!1,!1)});st.xlinkHref=new St("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1);["src","href","action","formAction"].forEach(function(e){st[e]=new St(e,1,!1,e.toLowerCase(),null,!0,!0)});function im(e,t,n,r){var o=st.hasOwnProperty(t)?st[t]:null;(o!==null?o.type!==0:r||!(2a||o[s]!==i[a]){var l=`
`+o[s].replace(" at new "," at ");return e.displayName&&l.includes("