Merge pull request 'push-xsnmptvkprqt' (#13) from push-xsnmptvkprqt into main
Reviewed-on: #13
This commit is contained in:
141
Cargo.lock
generated
141
Cargo.lock
generated
@@ -7,7 +7,9 @@ name = "PMOMusic"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"pmoapp",
|
||||
"pmoconfig",
|
||||
"pmoserver",
|
||||
"pmoupnp",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
@@ -467,41 +469,6 @@ dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.20.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"darling_macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.20.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.20.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_arbitrary"
|
||||
version = "1.4.2"
|
||||
@@ -1129,12 +1096,6 @@ dependencies = [
|
||||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "1.1.0"
|
||||
@@ -1483,6 +1444,13 @@ version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
|
||||
|
||||
[[package]]
|
||||
name = "pmoapp"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"rust-embed",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pmoconfig"
|
||||
version = "0.1.0"
|
||||
@@ -1511,41 +1479,50 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pmoupnp"
|
||||
name = "pmoserver"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-stream",
|
||||
"axum",
|
||||
"axum-embed",
|
||||
"axum-server",
|
||||
"futures",
|
||||
"futures-util",
|
||||
"pmoconfig",
|
||||
"pmoupnp",
|
||||
"rust-embed",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"utoipa",
|
||||
"utoipa-swagger-ui",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pmoupnp"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"base64",
|
||||
"bevy_reflect",
|
||||
"bevy_reflect_derive",
|
||||
"chrono",
|
||||
"futures",
|
||||
"futures-util",
|
||||
"get_if_addrs",
|
||||
"hex",
|
||||
"log",
|
||||
"once_cell",
|
||||
"parking_lot",
|
||||
"pmoconfig",
|
||||
"pmodidl",
|
||||
"reqwest",
|
||||
"rust-embed",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"url",
|
||||
"utoipa",
|
||||
"utoipa-swagger-ui",
|
||||
"uuid",
|
||||
"validator",
|
||||
"xmltree",
|
||||
]
|
||||
|
||||
@@ -1580,28 +1557,6 @@ dependencies = [
|
||||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr2"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error2"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.101"
|
||||
@@ -2050,12 +2005,6 @@ version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.6.1"
|
||||
@@ -2492,36 +2441,6 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "validator"
|
||||
version = "0.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43fb22e1a008ece370ce08a3e9e4447a910e92621bb49b85d6e48a45397e7cfa"
|
||||
dependencies = [
|
||||
"idna",
|
||||
"once_cell",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"url",
|
||||
"validator_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "validator_derive"
|
||||
version = "0.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7df16e474ef958526d1205f6dda359fdfab79d9aa6d54bafcb92dcd07673dca"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"once_cell",
|
||||
"proc-macro-error2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "valuable"
|
||||
version = "0.1.1"
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
[workspace]
|
||||
resolver = "3"
|
||||
members = ["PMOMusic", "pmoupnp","pmoconfig", "pmoutils", "pmodidl"]
|
||||
members = ["PMOMusic", "pmoupnp","pmoconfig", "pmoutils", "pmodidl", "pmoserver", "pmoapp"]
|
||||
|
||||
6
Makefile
6
Makefile
@@ -2,7 +2,7 @@
|
||||
# Variables de configuration
|
||||
CARGO = cargo
|
||||
NPM = npm
|
||||
WEBAPP_DIR = pmoupnp/webapp
|
||||
WEBAPP_DIR = pmoapp/webapp
|
||||
DIST_DIR = $(WEBAPP_DIR)/dist
|
||||
RUST_TARGET = target/release
|
||||
DOC_DIR = target/doc
|
||||
@@ -29,13 +29,13 @@ build: webapp release
|
||||
@echo "$(GREEN)✓ Build complet terminé$(NC)"
|
||||
|
||||
## release: Compile le binaire Rust en mode release
|
||||
release:
|
||||
release: webapp
|
||||
@echo "$(YELLOW)→ Compilation Rust (release)...$(NC)"
|
||||
$(CARGO) build --release
|
||||
@echo "$(GREEN)✓ Binaire disponible : $(RUST_TARGET)/$(BINARY_NAME)$(NC)"
|
||||
|
||||
## debug: Compile le binaire Rust en mode debug
|
||||
debug:
|
||||
debug: webapp
|
||||
@echo "$(YELLOW)→ Compilation Rust (debug)...$(NC)"
|
||||
$(CARGO) build
|
||||
@echo "$(GREEN)✓ Binaire disponible : target/debug/$(BINARY_NAME)$(NC)"
|
||||
|
||||
@@ -6,6 +6,8 @@ edition = "2024"
|
||||
[dependencies]
|
||||
pmoconfig = { path = "../pmoconfig" }
|
||||
pmoupnp = { path = "../pmoupnp"}
|
||||
pmoserver = { path = "../pmoserver" }
|
||||
pmoapp = { path = "../pmoapp" }
|
||||
|
||||
|
||||
tokio = { version = "1.35", features = ["rt-multi-thread", "macros", "sync", "time","signal"] }
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
use pmoupnp::{mediarenderer::avtransport::{actions::SETAVTRANSPORTURI, AVTTRANSPORT}, server::{
|
||||
logs::{log_dump, log_sse, LogState, SseLayer}, ServerBuilder, Webapp
|
||||
}, UpnpObject}; // ton module pmoupnp::server
|
||||
use pmoupnp::{mediarenderer::avtransport::AVTTRANSPORT, UpnpObject};
|
||||
use pmoserver::{
|
||||
logs::{log_dump, log_sse, LogState, SseLayer},
|
||||
ServerBuilder
|
||||
};
|
||||
use pmoapp::Webapp;
|
||||
use tracing_subscriber::Registry;
|
||||
use tracing_subscriber::prelude::*;
|
||||
use tracing::info;
|
||||
|
||||
7
pmoapp/Cargo.toml
Normal file
7
pmoapp/Cargo.toml
Normal file
@@ -0,0 +1,7 @@
|
||||
[package]
|
||||
name = "pmoapp"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
rust-embed = "8.5.0"
|
||||
51
pmoapp/src/lib.rs
Normal file
51
pmoapp/src/lib.rs
Normal file
@@ -0,0 +1,51 @@
|
||||
//! # pmoapp - Application web UPnP pour PMOMusic
|
||||
//!
|
||||
//! Cette crate fournit l'application web frontend pour le contrôle UPnP,
|
||||
//! intégrée via RustEmbed pour être servie par pmoserver.
|
||||
//!
|
||||
//! ## Fonctionnalités
|
||||
//!
|
||||
//! - 📦 **Frontend intégré** : Application web compilée et embarquée dans le binaire
|
||||
//! - 🎨 **Interface de contrôle** : UI pour gérer les devices UPnP MediaRenderer
|
||||
//! - 🚀 **Zero configuration** : Pas besoin de servir des fichiers statiques séparés
|
||||
//!
|
||||
//! ## Utilisation
|
||||
//!
|
||||
//! ```rust,no_run
|
||||
//! use pmoapp::Webapp;
|
||||
//! use pmoserver::ServerBuilder;
|
||||
//!
|
||||
//! # async fn example() {
|
||||
//! let mut server = ServerBuilder::new("MyApp").build();
|
||||
//! server.add_spa::<Webapp>("/app").await;
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! ## Structure
|
||||
//!
|
||||
//! La webapp est construite avec Vite et Vue.js, et les fichiers statiques
|
||||
//! sont embarqués dans le binaire au moment de la compilation via `RustEmbed`.
|
||||
|
||||
use rust_embed::RustEmbed;
|
||||
|
||||
/// Structure représentant l'application web embarquée.
|
||||
///
|
||||
/// Cette structure utilise `RustEmbed` pour inclure tous les fichiers
|
||||
/// du répertoire `webapp/dist` dans le binaire au moment de la compilation.
|
||||
///
|
||||
/// ## Exemple
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use pmoapp::Webapp;
|
||||
/// use pmoserver::ServerBuilder;
|
||||
///
|
||||
/// # async fn example() {
|
||||
/// let mut server = ServerBuilder::new("MyApp").build();
|
||||
///
|
||||
/// // Ajouter la webapp comme SPA sur le chemin /app
|
||||
/// server.add_spa::<Webapp>("/app").await;
|
||||
/// # }
|
||||
/// ```
|
||||
#[derive(RustEmbed, Clone)]
|
||||
#[folder = "webapp/dist"]
|
||||
pub struct Webapp;
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 496 B After Width: | Height: | Size: 496 B |
@@ -87,11 +87,41 @@ function formatTimestamp(timestamp) {
|
||||
}
|
||||
|
||||
function renderMarkdown(text) {
|
||||
// Convertir markdown en HTML et nettoyer pour la sécurité
|
||||
const rawHtml = marked.parse(text, { async: false })
|
||||
// ÉTAPE 1 : Pré-processing pour détecter et protéger le XML
|
||||
let processedText = text
|
||||
|
||||
// Détecter si le message contient du XML
|
||||
// Pattern : cherche <?xml ou des balises XML racine communes (scpd, root, service, etc.)
|
||||
const hasXml = /<\?xml|<(scpd|root|service|device|actionList|stateVariable)[>\s]/i.test(text)
|
||||
|
||||
if (hasXml) {
|
||||
// Extraire tout ce qui ressemble à du XML (du <?xml ou première balise jusqu'à la fin)
|
||||
const xmlStartMatch = text.match(/<\?xml[\s\S]*$/)
|
||||
|
||||
if (xmlStartMatch) {
|
||||
const xmlContent = xmlStartMatch[0]
|
||||
const beforeXml = text.substring(0, text.indexOf(xmlContent))
|
||||
|
||||
// Créer le texte avec le XML dans un bloc de code
|
||||
processedText = beforeXml + '\n```xml\n' + xmlContent + '\n```\n'
|
||||
} else {
|
||||
// Fallback : chercher une balise racine XML
|
||||
const xmlMatch = text.match(/<([a-zA-Z][a-zA-Z0-9:-]*)[>\s][\s\S]*/)
|
||||
if (xmlMatch) {
|
||||
const xmlContent = xmlMatch[0]
|
||||
const beforeXml = text.substring(0, text.indexOf(xmlContent))
|
||||
processedText = beforeXml + '\n```xml\n' + xmlContent + '\n```\n'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ÉTAPE 2 : Convertir markdown en HTML
|
||||
const rawHtml = marked.parse(processedText, { async: false })
|
||||
|
||||
// ÉTAPE 3 : Nettoyer pour la sécurité
|
||||
return DOMPurify.sanitize(rawHtml, {
|
||||
ALLOWED_TAGS: ['strong', 'em', 'code', 'pre', 'a', 'ul', 'ol', 'li', 'p', 'br'],
|
||||
ALLOWED_ATTR: ['href', 'target']
|
||||
ALLOWED_TAGS: ['strong', 'em', 'code', 'pre', 'a', 'ul', 'ol', 'li', 'p', 'br', 'span'],
|
||||
ALLOWED_ATTR: ['href', 'target', 'class']
|
||||
})
|
||||
}
|
||||
|
||||
@@ -425,16 +455,46 @@ button.active {
|
||||
|
||||
.markdown-content :deep(pre) {
|
||||
background: #2d2d30;
|
||||
padding: 0.5rem;
|
||||
padding: 0.75rem;
|
||||
border-radius: 4px;
|
||||
overflow-x: auto;
|
||||
margin: 0.25rem 0;
|
||||
margin: 0.5rem 0;
|
||||
border: 1px solid #3e3e42;
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.markdown-content :deep(pre code) {
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
color: #d4d4d4;
|
||||
font-size: 0.85em;
|
||||
line-height: 1.5;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Coloration pour les blocs XML */
|
||||
.markdown-content :deep(pre code.language-xml) {
|
||||
color: #ce9178;
|
||||
}
|
||||
|
||||
/* Scrollbar pour les blocs de code longs */
|
||||
.markdown-content :deep(pre)::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
.markdown-content :deep(pre)::-webkit-scrollbar-track {
|
||||
background: #1e1e1e;
|
||||
}
|
||||
|
||||
.markdown-content :deep(pre)::-webkit-scrollbar-thumb {
|
||||
background: #424242;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.markdown-content :deep(pre)::-webkit-scrollbar-thumb:hover {
|
||||
background: #4e4e4e;
|
||||
}
|
||||
|
||||
.markdown-content :deep(strong) {
|
||||
27
pmoserver/Cargo.toml
Normal file
27
pmoserver/Cargo.toml
Normal file
@@ -0,0 +1,27 @@
|
||||
[package]
|
||||
name = "pmoserver"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
pmoconfig = { path = "../pmoconfig" }
|
||||
|
||||
axum = "0.8.4"
|
||||
tokio = { version = "1.35", features = ["rt-multi-thread", "macros", "sync", "time", "signal"] }
|
||||
tokio-stream = "0.1"
|
||||
futures-util = "0.3"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["fmt", "env-filter"] }
|
||||
futures = "0.3"
|
||||
async-stream = "0.3.6"
|
||||
axum-server = "0.7.2"
|
||||
axum-embed = "0.1.0"
|
||||
rust-embed = "8.7.2"
|
||||
utoipa = { version = "5.4.0", features = ["axum_extras"] }
|
||||
utoipa-swagger-ui = { version = "9.0.2", features = ["axum"] }
|
||||
|
||||
[dependencies.pmoupnp]
|
||||
path = "../pmoupnp"
|
||||
default-features = false
|
||||
79
pmoserver/src/lib.rs
Normal file
79
pmoserver/src/lib.rs
Normal file
@@ -0,0 +1,79 @@
|
||||
//! # pmoserver - Serveur web haut niveau basé sur Axum
|
||||
//!
|
||||
//! Cette crate fournit une abstraction simple et ergonomique pour créer des serveurs HTTP
|
||||
//! avec Axum, spécialement conçue pour les applications UPnP et les serveurs multimédia.
|
||||
//!
|
||||
//! ## Fonctionnalités
|
||||
//!
|
||||
//! - 🚀 **API de haut niveau** : Interface simple pour créer des serveurs HTTP avec Axum
|
||||
//! - 🎯 **Support UPnP** : Implémentation du trait `UpnpServer` pour connecter des devices UPnP
|
||||
//! - 📡 **Server-Sent Events (SSE)** : Support intégré pour les logs en temps réel via SSE
|
||||
//! - ⚛️ **Applications SPA** : Support pour servir des applications Single Page (Vue.js, React, etc.)
|
||||
//! - 📁 **Fichiers statiques** : Serve de fichiers statiques avec `RustEmbed`
|
||||
//! - 🔀 **Redirections** : Support pour les redirections HTTP
|
||||
//! - 📚 **Documentation OpenAPI** : Génération automatique de Swagger UI
|
||||
//! - ⚡ **Arrêt gracieux** : Gestion propre de l'arrêt sur Ctrl+C
|
||||
//!
|
||||
//! ## Architecture
|
||||
//!
|
||||
//! La crate est organisée en plusieurs modules :
|
||||
//!
|
||||
//! - [`server`] : Implémentation du serveur principal et du builder
|
||||
//! - [`logs`] : Système de logs SSE pour monitoring en temps réel
|
||||
//! - `upnp_impl` : Implémentation du trait `pmoupnp::UpnpServer` (privé)
|
||||
//!
|
||||
//! ## Exemple d'utilisation
|
||||
//!
|
||||
//! ```rust,no_run
|
||||
//! use pmoserver::{ServerBuilder, logs::{LogState, SseLayer}};
|
||||
//! use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||
//!
|
||||
//! #[tokio::main]
|
||||
//! async fn main() {
|
||||
//! // Configuration des logs avec SSE
|
||||
//! let log_state = LogState::new();
|
||||
//! tracing_subscriber::registry()
|
||||
//! .with(SseLayer::new(log_state.clone()))
|
||||
//! .init();
|
||||
//!
|
||||
//! // Création et démarrage du serveur
|
||||
//! let mut server = ServerBuilder::new("MyServer")
|
||||
//! .http_port(8080)
|
||||
//! .build();
|
||||
//!
|
||||
//! // Ajout d'une route JSON
|
||||
//! server.add_route("/api/status", || async {
|
||||
//! serde_json::json!({"status": "ok"})
|
||||
//! }).await;
|
||||
//!
|
||||
//! // Démarrage
|
||||
//! server.start().await;
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! ## Intégration UPnP
|
||||
//!
|
||||
//! Le serveur implémente automatiquement le trait `pmoupnp::UpnpServer`, permettant
|
||||
//! de connecter des devices UPnP :
|
||||
//!
|
||||
//! ```rust,no_run
|
||||
//! use pmoupnp::{UpnpServer, mediarenderer::device::MEDIA_RENDERER};
|
||||
//! use pmoupnp::devices::DeviceInstance;
|
||||
//! use pmoserver::ServerBuilder;
|
||||
//! use std::sync::Arc;
|
||||
//!
|
||||
//! # async fn example() {
|
||||
//! let mut server = ServerBuilder::new("MediaRenderer").build();
|
||||
//! let device = Arc::new(DeviceInstance::new(&MEDIA_RENDERER));
|
||||
//!
|
||||
//! // Le device enregistre automatiquement ses routes
|
||||
//! device.register_urls(&mut server).await;
|
||||
//! # }
|
||||
//! ```
|
||||
|
||||
pub mod server;
|
||||
pub mod logs;
|
||||
mod upnp_impl;
|
||||
|
||||
pub use server::{Server, ServerBuilder, ServerInfo};
|
||||
pub use logs::{LogState, SseLayer, log_sse, log_dump};
|
||||
@@ -13,8 +13,6 @@
|
||||
//! - 📚 **Documentation API** : OpenAPI/Swagger automatique avec `add_openapi()`
|
||||
//! - ⚡ **Gestion gracieuse** : Arrêt propre sur Ctrl+C
|
||||
|
||||
pub mod logs;
|
||||
|
||||
use axum::handler::Handler;
|
||||
use axum::response::Redirect;
|
||||
use axum::routing::get;
|
||||
@@ -25,8 +23,7 @@ use rust_embed::RustEmbed;
|
||||
use serde::Serialize;
|
||||
use std::{net::SocketAddr, sync::Arc};
|
||||
use tokio::{signal, sync::RwLock, task::JoinHandle};
|
||||
use tracing::{info, warn, debug, error};
|
||||
use utoipa::OpenApi;
|
||||
use tracing::info;
|
||||
use utoipa_swagger_ui::SwaggerUi;
|
||||
|
||||
/// Info serveur sérialisable
|
||||
@@ -50,10 +47,6 @@ pub struct Server {
|
||||
join_handle: Option<JoinHandle<()>>,
|
||||
}
|
||||
|
||||
#[derive(RustEmbed, Clone)]
|
||||
#[folder = "webapp/dist"]
|
||||
pub struct Webapp;
|
||||
|
||||
impl Server {
|
||||
/// Crée une nouvelle instance de serveur
|
||||
///
|
||||
94
pmoserver/src/upnp_impl.rs
Normal file
94
pmoserver/src/upnp_impl.rs
Normal file
@@ -0,0 +1,94 @@
|
||||
//! Implémentation du trait UpnpServer pour le serveur pmoserver
|
||||
//!
|
||||
//! Ce module fournit l'implémentation du trait [`pmoupnp::UpnpServer`] pour
|
||||
//! le [`Server`](crate::server::Server) de pmoserver, permettant aux devices
|
||||
//! et services UPnP d'enregistrer automatiquement leurs endpoints HTTP.
|
||||
//!
|
||||
//! ## Architecture
|
||||
//!
|
||||
//! L'implémentation fait le pont entre :
|
||||
//! - Les pointeurs de fonction du trait `UpnpServer` (agnostiques du framework web)
|
||||
//! - Les handlers Axum (spécifiques à l'implémentation `pmoserver`)
|
||||
//!
|
||||
//! Chaque méthode du trait crée un wrapper qui :
|
||||
//! 1. Convertit les pointeurs de fonction en closures compatibles Axum
|
||||
//! 2. Délègue l'enregistrement aux méthodes internes du `Server`
|
||||
//! 3. Retourne une future qui se résout une fois le handler enregistré
|
||||
//!
|
||||
//! ## Exemple d'utilisation
|
||||
//!
|
||||
//! ```rust,no_run
|
||||
//! use pmoupnp::{UpnpServer, mediarenderer::device::MEDIA_RENDERER};
|
||||
//! use pmoupnp::devices::DeviceInstance;
|
||||
//! use pmoserver::ServerBuilder;
|
||||
//! use std::sync::Arc;
|
||||
//!
|
||||
//! # async fn example() {
|
||||
//! let mut server = ServerBuilder::new("MyRenderer").build();
|
||||
//! let device = Arc::new(DeviceInstance::new(&MEDIA_RENDERER));
|
||||
//!
|
||||
//! // Le trait UpnpServer est automatiquement disponible
|
||||
//! device.register_urls(&mut server).await;
|
||||
//! # }
|
||||
//! ```
|
||||
|
||||
use crate::server::Server;
|
||||
use pmoupnp::{UpnpServer, server::{Response, HeaderMap, Request}};
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use axum::extract::State;
|
||||
|
||||
impl UpnpServer for Server {
|
||||
fn add_handler<F, Fut>(&mut self, path: &str, handler: F) -> Pin<Box<dyn Future<Output = ()> + Send + '_>>
|
||||
where
|
||||
F: Fn() -> Fut + Send + Sync + 'static + Clone,
|
||||
Fut: Future<Output = Response> + Send + 'static,
|
||||
{
|
||||
let path = path.to_string();
|
||||
Box::pin(async move {
|
||||
Self::add_handler(self, &path, handler).await;
|
||||
})
|
||||
}
|
||||
|
||||
fn add_post_handler_with_state<S>(
|
||||
&mut self,
|
||||
path: &str,
|
||||
handler: fn(State<S>, String) -> Pin<Box<dyn Future<Output = Response> + Send>>,
|
||||
state: S,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + '_>>
|
||||
where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
let path = path.to_string();
|
||||
|
||||
// Créer un wrapper qui convertit le fn pointer en handler Axum
|
||||
let wrapper = move |State(s): State<S>, body: String| -> Pin<Box<dyn Future<Output = Response> + Send>> {
|
||||
handler(State(s), body)
|
||||
};
|
||||
|
||||
Box::pin(async move {
|
||||
Self::add_post_handler_with_state(self, &path, wrapper, state).await;
|
||||
})
|
||||
}
|
||||
|
||||
fn add_handler_with_state<S>(
|
||||
&mut self,
|
||||
path: &str,
|
||||
handler: fn(State<S>, HeaderMap, Request) -> Pin<Box<dyn Future<Output = Response> + Send>>,
|
||||
state: S,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + '_>>
|
||||
where
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
let path = path.to_string();
|
||||
|
||||
// Créer un wrapper qui convertit le fn pointer en handler Axum
|
||||
let wrapper = move |State(s): State<S>, headers: HeaderMap, req: Request| -> Pin<Box<dyn Future<Output = Response> + Send>> {
|
||||
handler(State(s), headers, req)
|
||||
};
|
||||
|
||||
Box::pin(async move {
|
||||
Self::add_handler_with_state(self, &path, wrapper, state).await;
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -13,28 +13,14 @@ hex = "0.4.3"
|
||||
base64 = "0.22.1"
|
||||
thiserror = "2.0.16"
|
||||
xmltree = "0.11.0"
|
||||
get_if_addrs = "0.5.3"
|
||||
axum = "0.8.4"
|
||||
tokio = { version = "1.35", features = ["rt-multi-thread", "macros", "sync", "time", "signal"] }
|
||||
tokio-stream = "0.1"
|
||||
futures-util = "0.3"
|
||||
tokio = { version = "1.35", features = ["rt-multi-thread", "macros", "sync"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
chrono = { version = "0.4.42", features = ["serde"] }
|
||||
log = "0.4.28"
|
||||
once_cell = "1.20"
|
||||
parking_lot = "0.12"
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["fmt", "env-filter"] }
|
||||
futures = "0.3"
|
||||
async-stream = "0.3.6"
|
||||
axum-server = "0.7.2"
|
||||
axum-embed = "0.1.0"
|
||||
rust-embed = "8.7.2"
|
||||
anyhow = "1.0"
|
||||
utoipa = { version = "5.4.0", features = ["axum_extras"] }
|
||||
utoipa-swagger-ui = { version = "9.0.2", features = ["axum"] }
|
||||
validator = { version = "0.20.0", features = ["derive"] }
|
||||
bevy_reflect = "0.17.1"
|
||||
bevy_reflect_derive = "0.17.1"
|
||||
reqwest = "0.12.23"
|
||||
|
||||
309
pmoupnp/src/devices/device.rs
Normal file
309
pmoupnp/src/devices/device.rs
Normal file
@@ -0,0 +1,309 @@
|
||||
//! Définition du modèle Device UPnP.
|
||||
|
||||
use std::sync::{Arc, RwLock};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::{
|
||||
UpnpTyped, UpnpObjectType,
|
||||
services::Service,
|
||||
};
|
||||
|
||||
use super::errors::DeviceError;
|
||||
|
||||
/// Modèle d'un device UPnP.
|
||||
///
|
||||
/// Représente la définition d'un device selon la spécification UPnP Device Architecture.
|
||||
/// Un device peut contenir plusieurs services et éventuellement des sous-devices.
|
||||
#[derive(Debug)]
|
||||
pub struct Device {
|
||||
/// Métadonnées de l'objet
|
||||
object: UpnpObjectType,
|
||||
|
||||
/// Type de device UPnP (ex: "MediaRenderer", "MediaServer")
|
||||
device_type: String,
|
||||
|
||||
/// Version du device
|
||||
version: u8,
|
||||
|
||||
/// Nom convivial du device
|
||||
friendly_name: String,
|
||||
|
||||
/// Fabricant
|
||||
manufacturer: String,
|
||||
|
||||
/// URL du fabricant
|
||||
manufacturer_url: Option<String>,
|
||||
|
||||
/// Description du modèle
|
||||
model_description: Option<String>,
|
||||
|
||||
/// Nom du modèle
|
||||
model_name: String,
|
||||
|
||||
/// Numéro du modèle
|
||||
model_number: Option<String>,
|
||||
|
||||
/// URL du modèle
|
||||
model_url: Option<String>,
|
||||
|
||||
/// Numéro de série
|
||||
serial_number: Option<String>,
|
||||
|
||||
/// UDN (Unique Device Name) - sera généré à l'instance
|
||||
udn_prefix: String,
|
||||
|
||||
/// UPC (Universal Product Code)
|
||||
upc: Option<String>,
|
||||
|
||||
/// URL de l'icône
|
||||
icon_url: Option<String>,
|
||||
|
||||
/// URL de présentation
|
||||
presentation_url: Option<String>,
|
||||
|
||||
/// Services du device
|
||||
services: RwLock<HashMap<String, Arc<Service>>>,
|
||||
|
||||
/// Sous-devices (embedded devices)
|
||||
devices: RwLock<HashMap<String, Arc<Device>>>,
|
||||
}
|
||||
|
||||
impl Clone for Device {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
object: self.object.clone(),
|
||||
device_type: self.device_type.clone(),
|
||||
version: self.version,
|
||||
friendly_name: self.friendly_name.clone(),
|
||||
manufacturer: self.manufacturer.clone(),
|
||||
manufacturer_url: self.manufacturer_url.clone(),
|
||||
model_description: self.model_description.clone(),
|
||||
model_name: self.model_name.clone(),
|
||||
model_number: self.model_number.clone(),
|
||||
model_url: self.model_url.clone(),
|
||||
serial_number: self.serial_number.clone(),
|
||||
udn_prefix: self.udn_prefix.clone(),
|
||||
upc: self.upc.clone(),
|
||||
icon_url: self.icon_url.clone(),
|
||||
presentation_url: self.presentation_url.clone(),
|
||||
services: RwLock::new(self.services.read().unwrap().clone()),
|
||||
devices: RwLock::new(self.devices.read().unwrap().clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Device {
|
||||
/// Crée un nouveau modèle de device.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `name` - Nom unique du device
|
||||
/// * `device_type` - Type UPnP du device
|
||||
/// * `friendly_name` - Nom convivial pour l'utilisateur
|
||||
pub fn new(name: String, device_type: String, friendly_name: String) -> Self {
|
||||
Self {
|
||||
object: UpnpObjectType {
|
||||
name: name.clone(),
|
||||
object_type: "Device".to_string(),
|
||||
},
|
||||
device_type,
|
||||
version: 1,
|
||||
friendly_name,
|
||||
manufacturer: "PMOMusic".to_string(),
|
||||
manufacturer_url: None,
|
||||
model_description: None,
|
||||
model_name: name.clone(),
|
||||
model_number: None,
|
||||
model_url: None,
|
||||
serial_number: None,
|
||||
udn_prefix: "pmomusic".to_string(),
|
||||
upc: None,
|
||||
icon_url: None,
|
||||
presentation_url: None,
|
||||
services: RwLock::new(HashMap::new()),
|
||||
devices: RwLock::new(HashMap::new()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Retourne le type de device UPnP.
|
||||
///
|
||||
/// Format: `urn:schemas-upnp-org:device:{type}:{version}`
|
||||
pub fn device_type(&self) -> String {
|
||||
format!("urn:schemas-upnp-org:device:{}:{}", self.device_type, self.version)
|
||||
}
|
||||
|
||||
/// Définit la version du device.
|
||||
pub fn set_version(&mut self, version: u8) -> Result<(), DeviceError> {
|
||||
if version == 0 {
|
||||
return Err(DeviceError::InvalidVersion);
|
||||
}
|
||||
self.version = version;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Retourne la version du device.
|
||||
pub fn version(&self) -> u8 {
|
||||
self.version
|
||||
}
|
||||
|
||||
/// Définit le fabricant.
|
||||
pub fn set_manufacturer(&mut self, manufacturer: String) {
|
||||
self.manufacturer = manufacturer;
|
||||
}
|
||||
|
||||
/// Définit l'URL du fabricant.
|
||||
pub fn set_manufacturer_url(&mut self, url: String) {
|
||||
self.manufacturer_url = Some(url);
|
||||
}
|
||||
|
||||
/// Définit la description du modèle.
|
||||
pub fn set_model_description(&mut self, description: String) {
|
||||
self.model_description = Some(description);
|
||||
}
|
||||
|
||||
/// Définit le nom du modèle.
|
||||
pub fn set_model_name(&mut self, name: String) {
|
||||
self.model_name = name;
|
||||
}
|
||||
|
||||
/// Définit le numéro du modèle.
|
||||
pub fn set_model_number(&mut self, number: String) {
|
||||
self.model_number = Some(number);
|
||||
}
|
||||
|
||||
/// Définit le numéro de série.
|
||||
pub fn set_serial_number(&mut self, serial: String) {
|
||||
self.serial_number = Some(serial);
|
||||
}
|
||||
|
||||
/// Définit le préfixe UDN.
|
||||
pub fn set_udn_prefix(&mut self, prefix: String) {
|
||||
self.udn_prefix = prefix;
|
||||
}
|
||||
|
||||
/// Retourne le préfixe UDN.
|
||||
pub fn udn_prefix(&self) -> &str {
|
||||
&self.udn_prefix
|
||||
}
|
||||
|
||||
/// Définit l'URL de présentation.
|
||||
pub fn set_presentation_url(&mut self, url: String) {
|
||||
self.presentation_url = Some(url);
|
||||
}
|
||||
|
||||
/// Ajoute un service au device.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Retourne une erreur si un service avec le même nom existe déjà.
|
||||
pub fn add_service(&self, service: Arc<Service>) -> Result<(), DeviceError> {
|
||||
let mut services = self.services.write().unwrap();
|
||||
let name = service.get_name().to_string();
|
||||
|
||||
if services.contains_key(&name) {
|
||||
return Err(DeviceError::ServiceAlreadyExists(name));
|
||||
}
|
||||
|
||||
services.insert(name, service);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Retourne tous les services.
|
||||
pub fn services(&self) -> Vec<Arc<Service>> {
|
||||
self.services.read().unwrap().values().cloned().collect()
|
||||
}
|
||||
|
||||
/// Retourne un service par nom.
|
||||
pub fn get_service(&self, name: &str) -> Option<Arc<Service>> {
|
||||
self.services.read().unwrap().get(name).cloned()
|
||||
}
|
||||
|
||||
/// Ajoute un sous-device.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Retourne une erreur si un device avec le même nom existe déjà.
|
||||
pub fn add_device(&self, device: Arc<Device>) -> Result<(), DeviceError> {
|
||||
let mut devices = self.devices.write().unwrap();
|
||||
let name = device.get_name().to_string();
|
||||
|
||||
if devices.contains_key(&name) {
|
||||
return Err(DeviceError::DeviceAlreadyExists(name));
|
||||
}
|
||||
|
||||
devices.insert(name, device);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Retourne tous les sous-devices.
|
||||
pub fn devices(&self) -> Vec<Arc<Device>> {
|
||||
self.devices.read().unwrap().values().cloned().collect()
|
||||
}
|
||||
|
||||
/// Retourne le nom convivial.
|
||||
pub fn friendly_name(&self) -> &str {
|
||||
&self.friendly_name
|
||||
}
|
||||
|
||||
/// Retourne le fabricant.
|
||||
pub fn manufacturer(&self) -> &str {
|
||||
&self.manufacturer
|
||||
}
|
||||
|
||||
/// Retourne le nom du modèle.
|
||||
pub fn model_name(&self) -> &str {
|
||||
&self.model_name
|
||||
}
|
||||
|
||||
/// Retourne la description du modèle.
|
||||
pub fn model_description(&self) -> Option<&str> {
|
||||
self.model_description.as_deref()
|
||||
}
|
||||
|
||||
/// Retourne l'URL de présentation.
|
||||
pub fn presentation_url(&self) -> Option<&str> {
|
||||
self.presentation_url.as_deref()
|
||||
}
|
||||
|
||||
/// Retourne l'URL du fabricant.
|
||||
pub fn manufacturer_url(&self) -> Option<&str> {
|
||||
self.manufacturer_url.as_deref()
|
||||
}
|
||||
|
||||
/// Retourne le numéro du modèle.
|
||||
pub fn model_number(&self) -> Option<&str> {
|
||||
self.model_number.as_deref()
|
||||
}
|
||||
|
||||
/// Retourne l'URL du modèle.
|
||||
pub fn model_url(&self) -> Option<&str> {
|
||||
self.model_url.as_deref()
|
||||
}
|
||||
|
||||
/// Retourne le numéro de série.
|
||||
pub fn serial_number(&self) -> Option<&str> {
|
||||
self.serial_number.as_deref()
|
||||
}
|
||||
|
||||
/// Retourne l'UPC.
|
||||
pub fn upc(&self) -> Option<&str> {
|
||||
self.upc.as_deref()
|
||||
}
|
||||
|
||||
/// Retourne l'URL de l'icône.
|
||||
pub fn icon_url(&self) -> Option<&str> {
|
||||
self.icon_url.as_deref()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Device {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, "Device({}:{})", self.get_name(), self.version)
|
||||
}
|
||||
}
|
||||
|
||||
impl UpnpTyped for Device {
|
||||
fn as_upnp_object_type(&self) -> &UpnpObjectType {
|
||||
&self.object
|
||||
}
|
||||
}
|
||||
330
pmoupnp/src/devices/device_instance.rs
Normal file
330
pmoupnp/src/devices/device_instance.rs
Normal file
@@ -0,0 +1,330 @@
|
||||
//! Implémentation de DeviceInstance.
|
||||
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
sync::{Arc, RwLock},
|
||||
};
|
||||
use axum::{
|
||||
http::StatusCode,
|
||||
response::{IntoResponse, Response},
|
||||
};
|
||||
use tracing::info;
|
||||
use xmltree::{Element, XMLNode, EmitterConfig};
|
||||
|
||||
use crate::{
|
||||
devices::{Device, errors::DeviceError},
|
||||
services::ServiceInstance,
|
||||
UpnpObject, UpnpInstance, UpnpTyped, UpnpTypedInstance, UpnpObjectType,
|
||||
};
|
||||
|
||||
/// Instance d'un device UPnP.
|
||||
///
|
||||
/// Représente une instance concrète d'un device UPnP, avec ses services instanciés
|
||||
/// et son UDN unique.
|
||||
pub struct DeviceInstance {
|
||||
/// Métadonnées de l'objet
|
||||
object: UpnpObjectType,
|
||||
|
||||
/// Référence vers le modèle
|
||||
model: Arc<Device>,
|
||||
|
||||
/// UDN unique pour cette instance
|
||||
udn: String,
|
||||
|
||||
/// URL de base du serveur
|
||||
server_base_url: String,
|
||||
|
||||
/// Instances de services
|
||||
services: RwLock<HashMap<String, Arc<ServiceInstance>>>,
|
||||
|
||||
/// Instances de sous-devices
|
||||
devices: RwLock<HashMap<String, Arc<DeviceInstance>>>,
|
||||
}
|
||||
|
||||
impl Clone for DeviceInstance {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
object: self.object.clone(),
|
||||
model: Arc::clone(&self.model),
|
||||
udn: self.udn.clone(),
|
||||
server_base_url: self.server_base_url.clone(),
|
||||
services: RwLock::new(self.services.read().unwrap().clone()),
|
||||
devices: RwLock::new(self.devices.read().unwrap().clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for DeviceInstance {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("DeviceInstance")
|
||||
.field("object", &self.object)
|
||||
.field("udn", &self.udn)
|
||||
.field("server_base_url", &self.server_base_url)
|
||||
.field("services", &self.services)
|
||||
.field("devices", &self.devices)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl UpnpTyped for DeviceInstance {
|
||||
fn as_upnp_object_type(&self) -> &UpnpObjectType {
|
||||
&self.object
|
||||
}
|
||||
}
|
||||
|
||||
impl UpnpInstance for DeviceInstance {
|
||||
type Model = Device;
|
||||
|
||||
fn new(model: &Device) -> Self {
|
||||
// Obtenir ou créer un UDN persistant via la configuration
|
||||
let device_name = model.get_name();
|
||||
|
||||
let udn = if let Ok(config_udn) = pmoconfig::get_config().get_device_udn("mediarenderer", device_name) {
|
||||
config_udn
|
||||
} else {
|
||||
// Fallback : générer un UDN
|
||||
tracing::warn!("Failed to get/save UDN from config, using generated UUID");
|
||||
format!("uuid:{}_{}", model.udn_prefix(), uuid::Uuid::new_v4())
|
||||
};
|
||||
|
||||
Self {
|
||||
object: UpnpObjectType {
|
||||
name: model.get_name().to_string(),
|
||||
object_type: "DeviceInstance".to_string(),
|
||||
},
|
||||
model: Arc::new(model.clone()),
|
||||
udn,
|
||||
server_base_url: "http://localhost:8080".to_string(),
|
||||
services: RwLock::new(HashMap::new()),
|
||||
devices: RwLock::new(HashMap::new()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl UpnpTypedInstance for DeviceInstance {
|
||||
fn get_model(&self) -> &Self::Model {
|
||||
&self.model
|
||||
}
|
||||
}
|
||||
|
||||
impl UpnpObject for DeviceInstance {
|
||||
fn to_xml_element(&self) -> Element {
|
||||
let mut elem = Element::new("device");
|
||||
|
||||
// deviceType
|
||||
let mut device_type = Element::new("deviceType");
|
||||
device_type.children.push(XMLNode::Text(self.model.device_type()));
|
||||
elem.children.push(XMLNode::Element(device_type));
|
||||
|
||||
// friendlyName
|
||||
let mut friendly_name = Element::new("friendlyName");
|
||||
friendly_name.children.push(XMLNode::Text(self.model.friendly_name().to_string()));
|
||||
elem.children.push(XMLNode::Element(friendly_name));
|
||||
|
||||
// manufacturer
|
||||
let mut manufacturer = Element::new("manufacturer");
|
||||
manufacturer.children.push(XMLNode::Text(self.model.manufacturer().to_string()));
|
||||
elem.children.push(XMLNode::Element(manufacturer));
|
||||
|
||||
// modelName
|
||||
let mut model_name = Element::new("modelName");
|
||||
model_name.children.push(XMLNode::Text(self.model.model_name().to_string()));
|
||||
elem.children.push(XMLNode::Element(model_name));
|
||||
|
||||
// UDN
|
||||
let mut udn = Element::new("UDN");
|
||||
udn.children.push(XMLNode::Text(self.udn.clone()));
|
||||
elem.children.push(XMLNode::Element(udn));
|
||||
|
||||
// serviceList
|
||||
let services = self.services.read().unwrap();
|
||||
if !services.is_empty() {
|
||||
let mut service_list = Element::new("serviceList");
|
||||
for service in services.values() {
|
||||
service_list.children.push(XMLNode::Element(service.to_xml_element()));
|
||||
}
|
||||
elem.children.push(XMLNode::Element(service_list));
|
||||
}
|
||||
|
||||
// deviceList (sous-devices)
|
||||
let devices = self.devices.read().unwrap();
|
||||
if !devices.is_empty() {
|
||||
let mut device_list = Element::new("deviceList");
|
||||
for device in devices.values() {
|
||||
device_list.children.push(XMLNode::Element(device.to_xml_element()));
|
||||
}
|
||||
elem.children.push(XMLNode::Element(device_list));
|
||||
}
|
||||
|
||||
// presentationURL
|
||||
if let Some(url) = self.model.presentation_url() {
|
||||
let mut presentation_url = Element::new("presentationURL");
|
||||
presentation_url.children.push(XMLNode::Text(url.to_string()));
|
||||
elem.children.push(XMLNode::Element(presentation_url));
|
||||
}
|
||||
|
||||
elem
|
||||
}
|
||||
}
|
||||
|
||||
impl DeviceInstance {
|
||||
/// Définit l'URL de base du serveur.
|
||||
pub fn set_server_base_url(&mut self, url: String) {
|
||||
self.server_base_url = url;
|
||||
}
|
||||
|
||||
/// Retourne l'UDN du device.
|
||||
pub fn udn(&self) -> &str {
|
||||
&self.udn
|
||||
}
|
||||
|
||||
/// Retourne l'URL de base du serveur (protocole + host + port).
|
||||
pub fn base_url(&self) -> &str {
|
||||
&self.server_base_url
|
||||
}
|
||||
|
||||
/// Retourne la route du device (chemin relatif).
|
||||
pub fn route(&self) -> String {
|
||||
format!("/device/{}", self.get_name())
|
||||
}
|
||||
|
||||
/// Retourne la route de description du device.
|
||||
pub fn description_route(&self) -> String {
|
||||
format!("{}/desc.xml", self.route())
|
||||
}
|
||||
|
||||
/// Ajoute une instance de service au device.
|
||||
///
|
||||
/// Cette méthode configure automatiquement le service pour qu'il connaisse
|
||||
/// son device parent.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Retourne une erreur si un service avec le même nom existe déjà.
|
||||
pub fn add_service(self: &Arc<Self>, service: Arc<ServiceInstance>) -> Result<(), DeviceError> {
|
||||
let mut services = self.services.write().unwrap();
|
||||
let name = service.get_name().to_string();
|
||||
|
||||
if services.contains_key(&name) {
|
||||
return Err(DeviceError::ServiceAlreadyExists(name));
|
||||
}
|
||||
|
||||
// Configurer le service pour qu'il connaisse son device parent
|
||||
service.set_device(Arc::clone(self));
|
||||
|
||||
services.insert(name, service);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Retourne tous les services.
|
||||
pub fn services(&self) -> Vec<Arc<ServiceInstance>> {
|
||||
self.services.read().unwrap().values().cloned().collect()
|
||||
}
|
||||
|
||||
/// Retourne un service par nom.
|
||||
pub fn get_service(&self, name: &str) -> Option<Arc<ServiceInstance>> {
|
||||
self.services.read().unwrap().get(name).cloned()
|
||||
}
|
||||
|
||||
/// Ajoute une instance de sous-device.
|
||||
pub fn add_device(&self, device: Arc<DeviceInstance>) -> Result<(), DeviceError> {
|
||||
let mut devices = self.devices.write().unwrap();
|
||||
let name = device.get_name().to_string();
|
||||
|
||||
if devices.contains_key(&name) {
|
||||
return Err(DeviceError::DeviceAlreadyExists(name));
|
||||
}
|
||||
|
||||
devices.insert(name, device);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Retourne tous les sous-devices.
|
||||
pub fn devices(&self) -> Vec<Arc<DeviceInstance>> {
|
||||
self.devices.read().unwrap().values().cloned().collect()
|
||||
}
|
||||
|
||||
/// Enregistre toutes les URLs du device et de ses services dans le serveur.
|
||||
pub fn register_urls<'a, S: crate::UpnpServer + ?Sized>(&'a self, server: &'a mut S) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), DeviceError>> + 'a>> {
|
||||
Box::pin(async move {
|
||||
info!(
|
||||
"✅ Device description for {} available at: {}{}",
|
||||
self.get_name(),
|
||||
self.base_url(),
|
||||
self.description_route(),
|
||||
);
|
||||
|
||||
// Handler pour la description du device
|
||||
let instance_desc = self.clone();
|
||||
server.add_handler(&self.description_route(), move || {
|
||||
let instance = instance_desc.clone();
|
||||
async move { instance.description_handler().await }
|
||||
}).await;
|
||||
|
||||
// Enregistrer les services
|
||||
for service in self.services() {
|
||||
service.register_urls(server).await
|
||||
.map_err(|e| DeviceError::UrlRegistrationError(e.to_string()))?;
|
||||
}
|
||||
|
||||
// Enregistrer les sous-devices
|
||||
for device in self.devices() {
|
||||
device.register_urls(server).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
/// Génère l'élément XML de description du device.
|
||||
pub fn description_element(&self) -> Element {
|
||||
let mut root = Element::new("root");
|
||||
root.attributes.insert(
|
||||
"xmlns".to_string(),
|
||||
"urn:schemas-upnp-org:device-1-0".to_string(),
|
||||
);
|
||||
|
||||
// specVersion
|
||||
let mut spec = Element::new("specVersion");
|
||||
let mut major = Element::new("major");
|
||||
major.children.push(XMLNode::Text("1".to_string()));
|
||||
spec.children.push(XMLNode::Element(major));
|
||||
|
||||
let mut minor = Element::new("minor");
|
||||
minor.children.push(XMLNode::Text("0".to_string()));
|
||||
spec.children.push(XMLNode::Element(minor));
|
||||
|
||||
root.children.push(XMLNode::Element(spec));
|
||||
|
||||
// device
|
||||
root.children.push(XMLNode::Element(self.to_xml_element()));
|
||||
|
||||
root
|
||||
}
|
||||
|
||||
/// Handler HTTP pour la description du device.
|
||||
async fn description_handler(&self) -> Response {
|
||||
let elem = self.description_element();
|
||||
|
||||
let config = EmitterConfig::new()
|
||||
.perform_indent(true)
|
||||
.indent_string(" ");
|
||||
|
||||
let mut xml_output = Vec::new();
|
||||
if let Err(e) = elem.write_with_config(&mut xml_output, config) {
|
||||
tracing::error!("Failed to serialize device description XML: {}", e);
|
||||
return StatusCode::INTERNAL_SERVER_ERROR.into_response();
|
||||
}
|
||||
|
||||
let mut xml = String::from_utf8_lossy(&xml_output).to_string();
|
||||
|
||||
// Ajouter l'en-tête XML
|
||||
xml.insert_str(0, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
|
||||
|
||||
(
|
||||
StatusCode::OK,
|
||||
[(axum::http::header::CONTENT_TYPE, "text/xml; charset=\"utf-8\"")],
|
||||
xml,
|
||||
).into_response()
|
||||
}
|
||||
}
|
||||
118
pmoupnp/src/devices/device_methods.rs
Normal file
118
pmoupnp/src/devices/device_methods.rs
Normal file
@@ -0,0 +1,118 @@
|
||||
//! Implémentation des traits UPnP pour Device.
|
||||
|
||||
use xmltree::{Element, XMLNode};
|
||||
|
||||
use crate::{
|
||||
devices::{Device, DeviceInstance},
|
||||
UpnpObject, UpnpModel,
|
||||
};
|
||||
|
||||
impl UpnpObject for Device {
|
||||
fn to_xml_element(&self) -> Element {
|
||||
let mut elem = Element::new("device");
|
||||
|
||||
// deviceType
|
||||
let mut device_type = Element::new("deviceType");
|
||||
device_type.children.push(XMLNode::Text(self.device_type()));
|
||||
elem.children.push(XMLNode::Element(device_type));
|
||||
|
||||
// friendlyName
|
||||
let mut friendly_name = Element::new("friendlyName");
|
||||
friendly_name.children.push(XMLNode::Text(self.friendly_name().to_string()));
|
||||
elem.children.push(XMLNode::Element(friendly_name));
|
||||
|
||||
// manufacturer
|
||||
let mut manufacturer = Element::new("manufacturer");
|
||||
manufacturer.children.push(XMLNode::Text(self.manufacturer().to_string()));
|
||||
elem.children.push(XMLNode::Element(manufacturer));
|
||||
|
||||
// manufacturerURL (optionnel)
|
||||
if let Some(url) = self.manufacturer_url() {
|
||||
let mut manufacturer_url = Element::new("manufacturerURL");
|
||||
manufacturer_url.children.push(XMLNode::Text(url.to_string()));
|
||||
elem.children.push(XMLNode::Element(manufacturer_url));
|
||||
}
|
||||
|
||||
// modelDescription (optionnel)
|
||||
if let Some(desc) = self.model_description() {
|
||||
let mut model_description = Element::new("modelDescription");
|
||||
model_description.children.push(XMLNode::Text(desc.to_string()));
|
||||
elem.children.push(XMLNode::Element(model_description));
|
||||
}
|
||||
|
||||
// modelName
|
||||
let mut model_name = Element::new("modelName");
|
||||
model_name.children.push(XMLNode::Text(self.model_name().to_string()));
|
||||
elem.children.push(XMLNode::Element(model_name));
|
||||
|
||||
// modelNumber (optionnel)
|
||||
if let Some(number) = self.model_number() {
|
||||
let mut model_number = Element::new("modelNumber");
|
||||
model_number.children.push(XMLNode::Text(number.to_string()));
|
||||
elem.children.push(XMLNode::Element(model_number));
|
||||
}
|
||||
|
||||
// modelURL (optionnel)
|
||||
if let Some(url) = self.model_url() {
|
||||
let mut model_url = Element::new("modelURL");
|
||||
model_url.children.push(XMLNode::Text(url.to_string()));
|
||||
elem.children.push(XMLNode::Element(model_url));
|
||||
}
|
||||
|
||||
// serialNumber (optionnel)
|
||||
if let Some(serial) = self.serial_number() {
|
||||
let mut serial_number = Element::new("serialNumber");
|
||||
serial_number.children.push(XMLNode::Text(serial.to_string()));
|
||||
elem.children.push(XMLNode::Element(serial_number));
|
||||
}
|
||||
|
||||
// UPC (optionnel)
|
||||
if let Some(upc) = self.upc() {
|
||||
let mut upc_elem = Element::new("UPC");
|
||||
upc_elem.children.push(XMLNode::Text(upc.to_string()));
|
||||
elem.children.push(XMLNode::Element(upc_elem));
|
||||
}
|
||||
|
||||
// iconList (optionnel)
|
||||
if let Some(icon_url) = self.icon_url() {
|
||||
let mut icon_list = Element::new("iconList");
|
||||
let mut icon = Element::new("icon");
|
||||
|
||||
let mut mimetype = Element::new("mimetype");
|
||||
mimetype.children.push(XMLNode::Text("image/png".to_string()));
|
||||
icon.children.push(XMLNode::Element(mimetype));
|
||||
|
||||
let mut width = Element::new("width");
|
||||
width.children.push(XMLNode::Text("48".to_string()));
|
||||
icon.children.push(XMLNode::Element(width));
|
||||
|
||||
let mut height = Element::new("height");
|
||||
height.children.push(XMLNode::Text("48".to_string()));
|
||||
icon.children.push(XMLNode::Element(height));
|
||||
|
||||
let mut depth = Element::new("depth");
|
||||
depth.children.push(XMLNode::Text("24".to_string()));
|
||||
icon.children.push(XMLNode::Element(depth));
|
||||
|
||||
let mut url = Element::new("url");
|
||||
url.children.push(XMLNode::Text(icon_url.to_string()));
|
||||
icon.children.push(XMLNode::Element(url));
|
||||
|
||||
icon_list.children.push(XMLNode::Element(icon));
|
||||
elem.children.push(XMLNode::Element(icon_list));
|
||||
}
|
||||
|
||||
// presentationURL (optionnel)
|
||||
if let Some(url) = self.presentation_url() {
|
||||
let mut presentation_url = Element::new("presentationURL");
|
||||
presentation_url.children.push(XMLNode::Text(url.to_string()));
|
||||
elem.children.push(XMLNode::Element(presentation_url));
|
||||
}
|
||||
|
||||
elem
|
||||
}
|
||||
}
|
||||
|
||||
impl UpnpModel for Device {
|
||||
type Instance = DeviceInstance;
|
||||
}
|
||||
23
pmoupnp/src/devices/errors.rs
Normal file
23
pmoupnp/src/devices/errors.rs
Normal file
@@ -0,0 +1,23 @@
|
||||
//! Erreurs relatives aux devices UPnP.
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
/// Erreurs liées aux devices UPnP.
|
||||
#[derive(Error, Debug)]
|
||||
pub enum DeviceError {
|
||||
/// Service déjà existant
|
||||
#[error("Service '{0}' already exists in device")]
|
||||
ServiceAlreadyExists(String),
|
||||
|
||||
/// Device déjà existant
|
||||
#[error("Device '{0}' already exists")]
|
||||
DeviceAlreadyExists(String),
|
||||
|
||||
/// Version invalide
|
||||
#[error("Device version must be > 0")]
|
||||
InvalidVersion,
|
||||
|
||||
/// Erreur d'enregistrement d'URL
|
||||
#[error("Failed to register URL: {0}")]
|
||||
UrlRegistrationError(String),
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
//! Module pour les devices UPnP.
|
||||
//!
|
||||
//! Ce module fournit les structures et fonctionnalites pour creer et gerer
|
||||
//! des devices UPnP selon la specification UPnP Device Architecture.
|
||||
//!
|
||||
//! # Architecture
|
||||
//!
|
||||
//! - [`Device`] : Modele d'un device UPnP
|
||||
//! - [`DeviceInstance`] : Instance concrete d'un device
|
||||
//! - [`DeviceError`](errors::DeviceError) : Erreurs liees aux devices
|
||||
//!
|
||||
//! # Exemple
|
||||
//!
|
||||
//! ```ignore
|
||||
//! use pmoupnp::devices::Device;
|
||||
//! use pmoupnp::services::Service;
|
||||
//! use std::sync::Arc;
|
||||
//!
|
||||
//! // Creer un device MediaRenderer
|
||||
//! let mut device = Device::new(
|
||||
//! "MediaRenderer".to_string(),
|
||||
//! "MediaRenderer".to_string(),
|
||||
//! "PMOMusic Renderer".to_string()
|
||||
//! );
|
||||
//!
|
||||
//! // Ajouter des services
|
||||
//! let avtransport = Arc::new(Service::new("AVTransport".to_string()));
|
||||
//! device.add_service(avtransport).unwrap();
|
||||
//!
|
||||
//! // Creer une instance
|
||||
//! let instance = device.create_instance();
|
||||
//! ```
|
||||
|
||||
mod device;
|
||||
mod device_instance;
|
||||
mod device_methods;
|
||||
pub mod errors;
|
||||
|
||||
pub use device::Device;
|
||||
pub use device_instance::DeviceInstance;
|
||||
|
||||
@@ -2,6 +2,7 @@ mod object_trait;
|
||||
mod object_set;
|
||||
|
||||
pub mod actions;
|
||||
pub mod devices;
|
||||
pub mod mediarenderer;
|
||||
pub mod server;
|
||||
pub mod services;
|
||||
@@ -9,6 +10,9 @@ pub mod state_variables;
|
||||
pub mod value_ranges;
|
||||
pub mod variable_types;
|
||||
|
||||
// Re-exports
|
||||
pub use server::UpnpServer;
|
||||
|
||||
|
||||
use std::{collections::HashMap, sync::Arc};
|
||||
|
||||
|
||||
69
pmoupnp/src/mediarenderer/device.rs
Normal file
69
pmoupnp/src/mediarenderer/device.rs
Normal file
@@ -0,0 +1,69 @@
|
||||
//! Définition du device MediaRenderer.
|
||||
|
||||
use once_cell::sync::Lazy;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
devices::Device,
|
||||
mediarenderer::{
|
||||
avtransport::AVTTRANSPORT,
|
||||
renderingcontrol::RENDERINGCONTROL,
|
||||
connectionmanager::CONNECTIONMANAGER,
|
||||
},
|
||||
};
|
||||
|
||||
/// Device MediaRenderer UPnP.
|
||||
///
|
||||
/// MediaRenderer audio-only conforme UPnP AV Architecture 1.0.
|
||||
///
|
||||
/// # Services inclus
|
||||
///
|
||||
/// - **AVTransport:1** : Contrôle de la lecture
|
||||
/// - **RenderingControl:1** : Contrôle du volume et du mute
|
||||
/// - **ConnectionManager:1** : Gestion des connexions
|
||||
///
|
||||
/// # Spécifications
|
||||
///
|
||||
/// - Device Type : `urn:schemas-upnp-org:device:MediaRenderer:1`
|
||||
/// - Version : 1
|
||||
/// - Manufacturer : PMOMusic
|
||||
/// - Model : PMOMusic Audio Renderer
|
||||
///
|
||||
/// # Exemple
|
||||
///
|
||||
/// ```ignore
|
||||
/// use pmoupnp::mediarenderer::MEDIA_RENDERER;
|
||||
/// use pmoupnp::UpnpModel;
|
||||
///
|
||||
/// // Créer une instance du renderer
|
||||
/// let renderer_instance = MEDIA_RENDERER.create_instance();
|
||||
///
|
||||
/// // Accéder aux services
|
||||
/// if let Some(avtransport) = renderer_instance.get_service("AVTransport") {
|
||||
/// // Contrôler la lecture...
|
||||
/// }
|
||||
/// ```
|
||||
pub static MEDIA_RENDERER: Lazy<Arc<Device>> = Lazy::new(|| {
|
||||
let mut device = Device::new(
|
||||
"MediaRenderer".to_string(),
|
||||
"MediaRenderer".to_string(),
|
||||
"PMOMusic Audio Renderer".to_string(),
|
||||
);
|
||||
|
||||
device.set_manufacturer("PMOMusic".to_string());
|
||||
device.set_model_name("PMOMusic Audio Renderer".to_string());
|
||||
device.set_model_description("UPnP AV MediaRenderer for audio streaming".to_string());
|
||||
device.set_udn_prefix("pmomusic".to_string());
|
||||
|
||||
// Ajouter les trois services obligatoires
|
||||
device.add_service(Arc::clone(&AVTTRANSPORT))
|
||||
.expect("Failed to add AVTransport service");
|
||||
|
||||
device.add_service(Arc::clone(&RENDERINGCONTROL))
|
||||
.expect("Failed to add RenderingControl service");
|
||||
|
||||
device.add_service(Arc::clone(&CONNECTIONMANAGER))
|
||||
.expect("Failed to add ConnectionManager service");
|
||||
|
||||
Arc::new(device)
|
||||
});
|
||||
@@ -1,3 +1,35 @@
|
||||
//! Module MediaRenderer UPnP.
|
||||
//!
|
||||
//! Ce module implémente un MediaRenderer UPnP audio-only conforme à la spécification
|
||||
//! UPnP AV Architecture. Un MediaRenderer permet de recevoir et lire du contenu audio
|
||||
//! depuis un serveur UPnP (MediaServer).
|
||||
//!
|
||||
//! # Architecture
|
||||
//!
|
||||
//! Le MediaRenderer est composé de trois services obligatoires :
|
||||
//!
|
||||
//! - **AVTransport** : Contrôle de la lecture (play, pause, stop, seek, etc.)
|
||||
//! - **RenderingControl** : Contrôle du volume et du mute
|
||||
//! - **ConnectionManager** : Gestion des connexions et des protocoles supportés
|
||||
//!
|
||||
//! # Device UPnP
|
||||
//!
|
||||
//! - Type : `urn:schemas-upnp-org:device:MediaRenderer:1`
|
||||
//! - Services : AVTransport:1, RenderingControl:1, ConnectionManager:1
|
||||
//!
|
||||
//! # Utilisation
|
||||
//!
|
||||
//! ```ignore
|
||||
//! use pmoupnp::mediarenderer::MEDIA_RENDERER;
|
||||
//!
|
||||
//! // Le device est déjà configuré avec tous ses services
|
||||
//! let renderer = MEDIA_RENDERER.clone();
|
||||
//! let instance = renderer.create_instance();
|
||||
//! ```
|
||||
|
||||
pub mod avtransport;
|
||||
pub mod connectionmanager;
|
||||
pub mod renderingcontrol;
|
||||
pub mod device;
|
||||
|
||||
pub use device::MEDIA_RENDERER;
|
||||
|
||||
262
pmoupnp/src/server.rs
Normal file
262
pmoupnp/src/server.rs
Normal file
@@ -0,0 +1,262 @@
|
||||
//! Trait pour les serveurs UPnP
|
||||
//!
|
||||
//! Ce module définit le trait [`UpnpServer`] qui permet de connecter
|
||||
//! des devices UPnP à n'importe quelle implémentation de serveur web.
|
||||
//!
|
||||
//! ## Architecture
|
||||
//!
|
||||
//! Le trait `UpnpServer` définit une interface minimale permettant aux devices
|
||||
//! et services UPnP d'enregistrer leurs endpoints HTTP sans dépendre d'une
|
||||
//! implémentation de serveur spécifique.
|
||||
//!
|
||||
//! ## Séparation des responsabilités
|
||||
//!
|
||||
//! - **pmoupnp** : Définit le trait `UpnpServer` et l'utilise via des contraintes génériques
|
||||
//! - **pmoserver** : Fournit une implémentation concrète basée sur Axum
|
||||
//! - **Autres crates** : Peuvent fournir leurs propres implémentations (actix-web, warp, etc.)
|
||||
//!
|
||||
//! ## Exemple d'utilisation
|
||||
//!
|
||||
//! ```rust,no_run
|
||||
//! use pmoupnp::{UpnpServer, devices::{Device, DeviceInstance}};
|
||||
//! use std::sync::Arc;
|
||||
//!
|
||||
//! # async fn example<S: UpnpServer>(mut server: S) {
|
||||
//! // Créer un device
|
||||
//! let device = Device::new(
|
||||
//! "MyDevice".to_string(),
|
||||
//! "MyDeviceType".to_string(),
|
||||
//! "Friendly Name".to_string(),
|
||||
//! );
|
||||
//! let device_instance = Arc::new(DeviceInstance::new(&device));
|
||||
//!
|
||||
//! // Le device enregistre automatiquement ses routes UPnP
|
||||
//! device_instance.register_urls(&mut server).await;
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! ## Implémentation
|
||||
//!
|
||||
//! Pour implémenter ce trait, votre serveur doit fournir trois méthodes
|
||||
//! pour enregistrer des handlers HTTP asynchrones :
|
||||
//!
|
||||
//! ```rust,no_run
|
||||
//! use pmoupnp::UpnpServer;
|
||||
//! use std::future::Future;
|
||||
//! use std::pin::Pin;
|
||||
//!
|
||||
//! struct MyServer {
|
||||
//! // votre implémentation
|
||||
//! }
|
||||
//!
|
||||
//! impl UpnpServer for MyServer {
|
||||
//! fn add_handler<F, Fut>(&mut self, path: &str, handler: F)
|
||||
//! -> Pin<Box<dyn Future<Output = ()> + Send + '_>>
|
||||
//! where
|
||||
//! F: Fn() -> Fut + Send + Sync + 'static + Clone,
|
||||
//! Fut: Future<Output = pmoupnp::server::Response> + Send + 'static,
|
||||
//! {
|
||||
//! // Enregistrer le handler pour GET requests
|
||||
//! # todo!()
|
||||
//! }
|
||||
//!
|
||||
//! fn add_post_handler_with_state<S>(
|
||||
//! &mut self,
|
||||
//! path: &str,
|
||||
//! handler: fn(axum::extract::State<S>, String)
|
||||
//! -> Pin<Box<dyn Future<Output = pmoupnp::server::Response> + Send>>,
|
||||
//! state: S,
|
||||
//! ) -> Pin<Box<dyn Future<Output = ()> + Send + '_>>
|
||||
//! where
|
||||
//! S: Clone + Send + Sync + 'static,
|
||||
//! {
|
||||
//! // Enregistrer le handler pour POST avec body
|
||||
//! # todo!()
|
||||
//! }
|
||||
//!
|
||||
//! fn add_handler_with_state<S>(
|
||||
//! &mut self,
|
||||
//! path: &str,
|
||||
//! handler: fn(axum::extract::State<S>,
|
||||
//! pmoupnp::server::HeaderMap,
|
||||
//! pmoupnp::server::Request)
|
||||
//! -> Pin<Box<dyn Future<Output = pmoupnp::server::Response> + Send>>,
|
||||
//! state: S,
|
||||
//! ) -> Pin<Box<dyn Future<Output = ()> + Send + '_>>
|
||||
//! where
|
||||
//! S: Clone + Send + Sync + 'static,
|
||||
//! {
|
||||
//! // Enregistrer le handler avec accès complet à la requête
|
||||
//! # todo!()
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
|
||||
/// Type alias pour la réponse HTTP (basé sur Axum).
|
||||
///
|
||||
/// Utilisé pour éviter une dépendance directe sur axum dans les signatures de trait,
|
||||
/// tout en restant compatible avec les types Axum.
|
||||
pub type Response = axum::response::Response;
|
||||
|
||||
/// Type alias pour les en-têtes HTTP (basé sur Axum).
|
||||
pub type HeaderMap = axum::http::HeaderMap;
|
||||
|
||||
/// Type alias pour la requête HTTP (basé sur Axum).
|
||||
pub type Request = axum::extract::Request<axum::body::Body>;
|
||||
|
||||
/// Trait pour les serveurs compatibles UPnP.
|
||||
///
|
||||
/// Ce trait définit l'interface minimale qu'un serveur web doit implémenter
|
||||
/// pour supporter l'enregistrement automatique des endpoints UPnP par les
|
||||
/// [`DeviceInstance`](crate::devices::DeviceInstance) et
|
||||
/// [`ServiceInstance`](crate::services::ServiceInstance).
|
||||
///
|
||||
/// ## Contraintes
|
||||
///
|
||||
/// - `Send + Sync` : Le serveur doit être partageable entre threads
|
||||
///
|
||||
/// ## Méthodes
|
||||
///
|
||||
/// Les trois méthodes permettent d'enregistrer différents types de handlers :
|
||||
///
|
||||
/// 1. **`add_handler`** : Handler GET simple sans état
|
||||
/// 2. **`add_post_handler_with_state`** : Handler POST avec état et body texte (pour SOAP)
|
||||
/// 3. **`add_handler_with_state`** : Handler générique avec accès complet (pour SUBSCRIBE/UNSUBSCRIBE)
|
||||
///
|
||||
/// ## Implémentations
|
||||
///
|
||||
/// - **pmoserver::Server** : Implémentation basée sur Axum (fournie par la crate `pmoserver`)
|
||||
pub trait UpnpServer: Send + Sync {
|
||||
/// Ajoute un handler GET pour un chemin donné.
|
||||
///
|
||||
/// Utilisé principalement pour servir les descripteurs XML des devices et services.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `path` - Le chemin HTTP (ex: `/device/MediaRenderer/description.xml`)
|
||||
/// * `handler` - Une closure asynchrone qui génère la réponse
|
||||
///
|
||||
/// # Retour
|
||||
///
|
||||
/// Une future qui se résout quand le handler est enregistré.
|
||||
///
|
||||
/// # Exemple
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use pmoupnp::UpnpServer;
|
||||
/// use axum::response::IntoResponse;
|
||||
///
|
||||
/// # async fn example<S: UpnpServer>(mut server: S) {
|
||||
/// server.add_handler("/description.xml", || async {
|
||||
/// "<?xml version=\"1.0\"?><root></root>".into_response()
|
||||
/// }).await;
|
||||
/// # }
|
||||
/// ```
|
||||
fn add_handler<F, Fut>(&mut self, path: &str, handler: F) -> Pin<Box<dyn Future<Output = ()> + Send + '_>>
|
||||
where
|
||||
F: Fn() -> Fut + Send + Sync + 'static + Clone,
|
||||
Fut: Future<Output = Response> + Send + 'static;
|
||||
|
||||
/// Ajoute un handler POST avec état pour un chemin donné.
|
||||
///
|
||||
/// Utilisé pour les endpoints de contrôle SOAP des services UPnP.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `path` - Le chemin HTTP (ex: `/service/AVTransport/control`)
|
||||
/// * `handler` - Un pointeur de fonction qui traite la requête SOAP
|
||||
/// * `state` - L'état partagé (typiquement une `ServiceInstance`)
|
||||
///
|
||||
/// # Retour
|
||||
///
|
||||
/// Une future qui se résout quand le handler est enregistré.
|
||||
///
|
||||
/// # Exemple
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use pmoupnp::{UpnpServer, server::Response};
|
||||
/// use axum::extract::State;
|
||||
/// use std::pin::Pin;
|
||||
/// use std::future::Future;
|
||||
///
|
||||
/// fn soap_handler(
|
||||
/// State(service): State<String>,
|
||||
/// body: String,
|
||||
/// ) -> Pin<Box<dyn Future<Output = Response> + Send>> {
|
||||
/// Box::pin(async move {
|
||||
/// // Traiter la requête SOAP
|
||||
/// axum::response::Response::default()
|
||||
/// })
|
||||
/// }
|
||||
///
|
||||
/// # async fn example<S: UpnpServer>(mut server: S) {
|
||||
/// server.add_post_handler_with_state(
|
||||
/// "/control",
|
||||
/// soap_handler,
|
||||
/// "ServiceName".to_string(),
|
||||
/// ).await;
|
||||
/// # }
|
||||
/// ```
|
||||
fn add_post_handler_with_state<S>(
|
||||
&mut self,
|
||||
path: &str,
|
||||
handler: fn(axum::extract::State<S>, String) -> Pin<Box<dyn Future<Output = Response> + Send>>,
|
||||
state: S,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + '_>>
|
||||
where
|
||||
S: Clone + Send + Sync + 'static;
|
||||
|
||||
/// Ajoute un handler avec état et accès complet à la requête.
|
||||
///
|
||||
/// Utilisé pour les endpoints d'événements (SUBSCRIBE/UNSUBSCRIBE) qui nécessitent
|
||||
/// un accès aux en-têtes HTTP et à la méthode HTTP.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `path` - Le chemin HTTP (ex: `/service/AVTransport/event`)
|
||||
/// * `handler` - Un pointeur de fonction avec accès complet à la requête
|
||||
/// * `state` - L'état partagé (typiquement une `ServiceInstance`)
|
||||
///
|
||||
/// # Retour
|
||||
///
|
||||
/// Une future qui se résout quand le handler est enregistré.
|
||||
///
|
||||
/// # Exemple
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use pmoupnp::{UpnpServer, server::{Response, HeaderMap, Request}};
|
||||
/// use axum::extract::State;
|
||||
/// use std::pin::Pin;
|
||||
/// use std::future::Future;
|
||||
///
|
||||
/// fn event_handler(
|
||||
/// State(service): State<String>,
|
||||
/// headers: HeaderMap,
|
||||
/// req: Request,
|
||||
/// ) -> Pin<Box<dyn Future<Output = Response> + Send>> {
|
||||
/// Box::pin(async move {
|
||||
/// // Traiter SUBSCRIBE/UNSUBSCRIBE
|
||||
/// axum::response::Response::default()
|
||||
/// })
|
||||
/// }
|
||||
///
|
||||
/// # async fn example<S: UpnpServer>(mut server: S) {
|
||||
/// server.add_handler_with_state(
|
||||
/// "/event",
|
||||
/// event_handler,
|
||||
/// "ServiceName".to_string(),
|
||||
/// ).await;
|
||||
/// # }
|
||||
/// ```
|
||||
fn add_handler_with_state<S>(
|
||||
&mut self,
|
||||
path: &str,
|
||||
handler: fn(axum::extract::State<S>, HeaderMap, Request) -> Pin<Box<dyn Future<Output = Response> + Send>>,
|
||||
state: S,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + '_>>
|
||||
where
|
||||
S: Clone + Send + Sync + 'static;
|
||||
}
|
||||
@@ -400,15 +400,15 @@ impl Service {
|
||||
format!("/service/{}", self.name())
|
||||
}
|
||||
|
||||
pub fn scpd_url(&self) -> String {
|
||||
pub fn scpd_route(&self) -> String {
|
||||
format!("{}/desc.xml", self.service_base_url())
|
||||
}
|
||||
|
||||
pub fn control_url(&self) -> String {
|
||||
pub fn control_route(&self) -> String {
|
||||
format!("{}/control", self.service_base_url())
|
||||
}
|
||||
|
||||
pub fn event_url(&self) -> String {
|
||||
pub fn event_route(&self) -> String {
|
||||
format!("{}/event", self.service_base_url())
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ use std::{
|
||||
collections::HashMap,
|
||||
sync::{Arc, Mutex, RwLock},
|
||||
time::Duration,
|
||||
pin::Pin,
|
||||
future::Future,
|
||||
};
|
||||
use axum::{
|
||||
extract::{Request, State},
|
||||
@@ -19,6 +21,7 @@ use crate::{
|
||||
services::{Service, ServiceError},
|
||||
actions::{ActionInstance, ActionInstanceSet},
|
||||
state_variables::{StateVarInstance, StateVarInstanceSet, UpnpVariable},
|
||||
devices::DeviceInstance,
|
||||
UpnpObject, UpnpInstance, UpnpTyped, UpnpTypedInstance, UpnpObjectType,
|
||||
};
|
||||
|
||||
@@ -74,8 +77,8 @@ pub struct ServiceInstance {
|
||||
/// Identifiant du service
|
||||
identifier: String,
|
||||
|
||||
/// Device parent (optionnel)
|
||||
device: Option<Arc<DeviceStub>>,
|
||||
/// Device parent (optionnel) - utilisé via interior mutability
|
||||
device: Arc<RwLock<Option<Arc<DeviceInstance>>>>,
|
||||
|
||||
/// Variables d'état instanciées
|
||||
statevariables: StateVarInstanceSet,
|
||||
@@ -93,31 +96,6 @@ pub struct ServiceInstance {
|
||||
seqid: Arc<Mutex<HashMap<String, u32>>>,
|
||||
}
|
||||
|
||||
// Stub temporaire pour DeviceInstance
|
||||
// TODO: Remplacer par la vraie implémentation quand le module devices sera créé
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DeviceStub {
|
||||
name: String,
|
||||
udn: String,
|
||||
}
|
||||
|
||||
impl DeviceStub {
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn base_route(&self) -> String {
|
||||
format!("/device/{}", self.name)
|
||||
}
|
||||
|
||||
pub fn udn(&self) -> &str {
|
||||
&self.udn
|
||||
}
|
||||
|
||||
pub fn server_base_url(&self) -> String {
|
||||
"http://localhost:8080".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for ServiceInstance {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
@@ -195,7 +173,7 @@ impl UpnpInstance for ServiceInstance {
|
||||
},
|
||||
model: Arc::new(model.clone()),
|
||||
identifier: model.identifier().to_string(),
|
||||
device: None,
|
||||
device: Arc::new(RwLock::new(None)),
|
||||
statevariables,
|
||||
actions,
|
||||
subscribers: Arc::new(RwLock::new(HashMap::new())),
|
||||
@@ -224,15 +202,15 @@ impl UpnpObject for ServiceInstance {
|
||||
elem.children.push(XMLNode::Element(service_id));
|
||||
|
||||
let mut scpd_url = Element::new("SCPDURL");
|
||||
scpd_url.children.push(XMLNode::Text(self.scpd_url()));
|
||||
scpd_url.children.push(XMLNode::Text(self.scpd_route()));
|
||||
elem.children.push(XMLNode::Element(scpd_url));
|
||||
|
||||
let mut control_url = Element::new("controlURL");
|
||||
control_url.children.push(XMLNode::Text(self.control_url()));
|
||||
control_url.children.push(XMLNode::Text(self.control_route()));
|
||||
elem.children.push(XMLNode::Element(control_url));
|
||||
|
||||
let mut event_sub_url = Element::new("eventSubURL");
|
||||
event_sub_url.children.push(XMLNode::Text(self.event_sub_url()));
|
||||
event_sub_url.children.push(XMLNode::Text(self.event_route()));
|
||||
elem.children.push(XMLNode::Element(event_sub_url));
|
||||
|
||||
elem
|
||||
@@ -269,32 +247,43 @@ impl ServiceInstance {
|
||||
self.actions.get_by_name(name)
|
||||
}
|
||||
|
||||
/// Retourne la route de base du service.
|
||||
pub fn base_route(&self) -> String {
|
||||
match &self.device {
|
||||
Some(device) => format!("{}/service/{}", device.base_route(), self.get_name()),
|
||||
/// Définit le device parent pour ce service.
|
||||
///
|
||||
/// Cette méthode doit être appelée après la création du service instance
|
||||
/// pour établir la relation avec le device parent.
|
||||
pub fn set_device(&self, device: Arc<DeviceInstance>) {
|
||||
let mut dev = self.device.write().unwrap();
|
||||
*dev = Some(device);
|
||||
}
|
||||
|
||||
/// Retourne la route du service (chemin relatif).
|
||||
pub fn route(&self) -> String {
|
||||
let device = self.device.read().unwrap();
|
||||
match device.as_ref() {
|
||||
Some(device) => format!("{}/service/{}", device.route(), self.get_name()),
|
||||
None => format!("/service/{}", self.get_name()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Retourne l'URL de contrôle SOAP.
|
||||
pub fn control_url(&self) -> String {
|
||||
format!("{}/control", self.base_route())
|
||||
/// Retourne la route de contrôle SOAP.
|
||||
pub fn control_route(&self) -> String {
|
||||
format!("{}/control", self.route())
|
||||
}
|
||||
|
||||
/// Retourne l'URL de souscription aux événements.
|
||||
pub fn event_sub_url(&self) -> String {
|
||||
format!("{}/event", self.base_route())
|
||||
/// Retourne la route de souscription aux événements.
|
||||
pub fn event_route(&self) -> String {
|
||||
format!("{}/event", self.route())
|
||||
}
|
||||
|
||||
/// Retourne l'URL de la description SCPD.
|
||||
pub fn scpd_url(&self) -> String {
|
||||
format!("{}/desc.xml", self.base_route())
|
||||
/// Retourne la route de la description SCPD.
|
||||
pub fn scpd_route(&self) -> String {
|
||||
format!("{}/desc.xml", self.route())
|
||||
}
|
||||
|
||||
/// Retourne l'USN (Unique Service Name).
|
||||
pub fn usn(&self) -> String {
|
||||
match &self.device {
|
||||
let device = self.device.read().unwrap();
|
||||
match device.as_ref() {
|
||||
Some(device) => format!("uuid:{}::urn:{}", device.udn(), self.service_type()),
|
||||
None => format!("uuid::urn:{}", self.service_type()),
|
||||
}
|
||||
@@ -310,23 +299,28 @@ impl ServiceInstance {
|
||||
&self.actions
|
||||
}
|
||||
|
||||
/// Enregistre les routes UPnP dans le serveur Axum.
|
||||
/// Enregistre les routes UPnP dans le serveur.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Retourne une erreur si l'enregistrement des routes échoue.
|
||||
pub async fn register_urls(&self, server: &mut crate::server::Server) -> Result<(), ServiceError> {
|
||||
pub async fn register_urls<S: crate::UpnpServer + ?Sized>(&self, server: &mut S) -> Result<(), ServiceError> {
|
||||
let device = self.device.read().unwrap();
|
||||
let device_name = device.as_ref().map(|d| d.get_name().clone()).unwrap_or_else(|| "unknown".to_string());
|
||||
let server_url = device.as_ref().map(|d| d.base_url().to_string()).unwrap_or_default();
|
||||
drop(device);
|
||||
|
||||
info!(
|
||||
"✅ Service description for {}:{} available at : {}{}",
|
||||
self.device.as_ref().map(|d| d.name()).unwrap_or("unknown"),
|
||||
device_name,
|
||||
self.get_name(),
|
||||
self.device.as_ref().map(|d| d.server_base_url()).unwrap_or_default(),
|
||||
self.scpd_url(),
|
||||
server_url,
|
||||
self.scpd_route(),
|
||||
);
|
||||
|
||||
// Handler SCPD
|
||||
let instance_scpd = self.clone();
|
||||
server.add_handler(&self.scpd_url(), move || {
|
||||
server.add_handler(&self.scpd_route(), move || {
|
||||
let instance = instance_scpd.clone();
|
||||
async move { instance.scpd_handler().await }
|
||||
}).await;
|
||||
@@ -334,7 +328,7 @@ impl ServiceInstance {
|
||||
// Handler control
|
||||
let instance_control = self.clone();
|
||||
server.add_post_handler_with_state(
|
||||
&self.control_url(),
|
||||
&self.control_route(),
|
||||
control_handler,
|
||||
instance_control,
|
||||
).await;
|
||||
@@ -342,7 +336,7 @@ impl ServiceInstance {
|
||||
// Handler événements
|
||||
let instance_event = self.clone();
|
||||
server.add_handler_with_state(
|
||||
&self.event_sub_url(),
|
||||
&self.event_route(),
|
||||
event_sub_handler,
|
||||
instance_event,
|
||||
).await;
|
||||
@@ -574,11 +568,12 @@ impl ServiceInstance {
|
||||
}
|
||||
|
||||
/// Handler Axum pour les événements (SUBSCRIBE/UNSUBSCRIBE).
|
||||
async fn event_sub_handler(
|
||||
fn event_sub_handler(
|
||||
State(instance): State<ServiceInstance>,
|
||||
headers: HeaderMap,
|
||||
req: Request<Body>,
|
||||
) -> Response {
|
||||
) -> Pin<Box<dyn Future<Output = Response> + Send>> {
|
||||
Box::pin(async move {
|
||||
info!("📡 Event Subscription request for {}", instance.get_name());
|
||||
|
||||
let method = req.method().as_str();
|
||||
@@ -641,13 +636,15 @@ async fn event_sub_handler(
|
||||
StatusCode::METHOD_NOT_ALLOWED.into_response()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Handler Axum pour le contrôle SOAP.
|
||||
async fn control_handler(
|
||||
fn control_handler(
|
||||
State(instance): State<ServiceInstance>,
|
||||
body: String,
|
||||
) -> Response {
|
||||
_body: String,
|
||||
) -> Pin<Box<dyn Future<Output = Response> + Send>> {
|
||||
Box::pin(async move {
|
||||
info!("📡 Control request for {}", instance.get_name());
|
||||
|
||||
// TODO: Parser le SOAP et appeler l'action correspondante
|
||||
@@ -669,6 +666,7 @@ async fn control_handler(
|
||||
[(axum::http::header::CONTENT_TYPE, "text/xml; charset=\"utf-8\"")],
|
||||
response_xml,
|
||||
).into_response()
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -690,10 +688,10 @@ mod tests {
|
||||
let service = Service::new("AVTransport".to_string());
|
||||
let instance = ServiceInstance::new(&service);
|
||||
|
||||
assert_eq!(instance.base_route(), "/service/AVTransport");
|
||||
assert_eq!(instance.control_url(), "/service/AVTransport/control");
|
||||
assert_eq!(instance.event_sub_url(), "/service/AVTransport/event");
|
||||
assert_eq!(instance.scpd_url(), "/service/AVTransport/desc.xml");
|
||||
assert_eq!(instance.route(), "/service/AVTransport");
|
||||
assert_eq!(instance.control_route(), "/service/AVTransport/control");
|
||||
assert_eq!(instance.event_route(), "/service/AVTransport/event");
|
||||
assert_eq!(instance.scpd_route(), "/service/AVTransport/desc.xml");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -35,17 +35,17 @@ impl UpnpObject for Service {
|
||||
|
||||
// SCPDURL
|
||||
let mut SCPDURL = Element::new("SCPDURL");
|
||||
SCPDURL.children.push(XMLNode::Text(self.scpd_url()));
|
||||
SCPDURL.children.push(XMLNode::Text(self.scpd_route()));
|
||||
elem.children.push(XMLNode::Element(SCPDURL));
|
||||
|
||||
// controlURL
|
||||
let mut controlURL = Element::new("controlURL");
|
||||
controlURL.children.push(XMLNode::Text(self.control_url()));
|
||||
controlURL.children.push(XMLNode::Text(self.control_route()));
|
||||
elem.children.push(XMLNode::Element(controlURL));
|
||||
|
||||
// SCPDURL
|
||||
// eventSubURL
|
||||
let mut eventSubURL = Element::new("eventSubURL");
|
||||
eventSubURL.children.push(XMLNode::Text(self.event_url()));
|
||||
eventSubURL.children.push(XMLNode::Text(self.event_route()));
|
||||
elem.children.push(XMLNode::Element(eventSubURL));
|
||||
|
||||
elem
|
||||
|
||||
1
pmoupnp/webapp/node_modules/.bin/esbuild
generated
vendored
1
pmoupnp/webapp/node_modules/.bin/esbuild
generated
vendored
@@ -1 +0,0 @@
|
||||
../esbuild/bin/esbuild
|
||||
1
pmoupnp/webapp/node_modules/.bin/marked
generated
vendored
1
pmoupnp/webapp/node_modules/.bin/marked
generated
vendored
@@ -1 +0,0 @@
|
||||
../marked/bin/marked.js
|
||||
1
pmoupnp/webapp/node_modules/.bin/nanoid
generated
vendored
1
pmoupnp/webapp/node_modules/.bin/nanoid
generated
vendored
@@ -1 +0,0 @@
|
||||
../nanoid/bin/nanoid.cjs
|
||||
1
pmoupnp/webapp/node_modules/.bin/parser
generated
vendored
1
pmoupnp/webapp/node_modules/.bin/parser
generated
vendored
@@ -1 +0,0 @@
|
||||
../@babel/parser/bin/babel-parser.js
|
||||
1
pmoupnp/webapp/node_modules/.bin/rollup
generated
vendored
1
pmoupnp/webapp/node_modules/.bin/rollup
generated
vendored
@@ -1 +0,0 @@
|
||||
../rollup/dist/bin/rollup
|
||||
1
pmoupnp/webapp/node_modules/.bin/tsc
generated
vendored
1
pmoupnp/webapp/node_modules/.bin/tsc
generated
vendored
@@ -1 +0,0 @@
|
||||
../typescript/bin/tsc
|
||||
1
pmoupnp/webapp/node_modules/.bin/tsserver
generated
vendored
1
pmoupnp/webapp/node_modules/.bin/tsserver
generated
vendored
@@ -1 +0,0 @@
|
||||
../typescript/bin/tsserver
|
||||
1
pmoupnp/webapp/node_modules/.bin/vite
generated
vendored
1
pmoupnp/webapp/node_modules/.bin/vite
generated
vendored
@@ -1 +0,0 @@
|
||||
../vite/bin/vite.js
|
||||
1
pmoupnp/webapp/node_modules/.bin/vue-tsc
generated
vendored
1
pmoupnp/webapp/node_modules/.bin/vue-tsc
generated
vendored
@@ -1 +0,0 @@
|
||||
../vue-tsc/bin/vue-tsc.js
|
||||
1514
pmoupnp/webapp/node_modules/.package-lock.json
generated
vendored
1514
pmoupnp/webapp/node_modules/.package-lock.json
generated
vendored
File diff suppressed because it is too large
Load Diff
1
pmoupnp/webapp/node_modules/.tmp/tsconfig.app.tsbuildinfo
generated
vendored
1
pmoupnp/webapp/node_modules/.tmp/tsconfig.app.tsbuildinfo
generated
vendored
@@ -1 +0,0 @@
|
||||
{"root":["../../src/main.ts","../../src/shims-vue.d.ts","../../src/router/index.ts","../../src/app.vue","../../src/components/helloworld.vue","../../src/components/logview.vue"],"version":"5.8.3"}
|
||||
1
pmoupnp/webapp/node_modules/.tmp/tsconfig.node.tsbuildinfo
generated
vendored
1
pmoupnp/webapp/node_modules/.tmp/tsconfig.node.tsbuildinfo
generated
vendored
@@ -1 +0,0 @@
|
||||
{"root":["../../vite.config.ts"],"version":"5.8.3"}
|
||||
15
pmoupnp/webapp/node_modules/.vite/deps/_metadata.json
generated
vendored
15
pmoupnp/webapp/node_modules/.vite/deps/_metadata.json
generated
vendored
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"hash": "55ffb9fd",
|
||||
"configHash": "38b44685",
|
||||
"lockfileHash": "67a231c1",
|
||||
"browserHash": "0b84b257",
|
||||
"optimized": {
|
||||
"vue": {
|
||||
"src": "../../vue/dist/vue.runtime.esm-bundler.js",
|
||||
"file": "vue.js",
|
||||
"fileHash": "6eecd6fc",
|
||||
"needsInterop": false
|
||||
}
|
||||
},
|
||||
"chunks": {}
|
||||
}
|
||||
3
pmoupnp/webapp/node_modules/.vite/deps/package.json
generated
vendored
3
pmoupnp/webapp/node_modules/.vite/deps/package.json
generated
vendored
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"type": "module"
|
||||
}
|
||||
12704
pmoupnp/webapp/node_modules/.vite/deps/vue.js
generated
vendored
12704
pmoupnp/webapp/node_modules/.vite/deps/vue.js
generated
vendored
File diff suppressed because it is too large
Load Diff
7
pmoupnp/webapp/node_modules/.vite/deps/vue.js.map
generated
vendored
7
pmoupnp/webapp/node_modules/.vite/deps/vue.js.map
generated
vendored
File diff suppressed because one or more lines are too long
137
pmoupnp/webapp/node_modules/.vue-global-types/vue_3.5_0.d.ts
generated
vendored
137
pmoupnp/webapp/node_modules/.vue-global-types/vue_3.5_0.d.ts
generated
vendored
@@ -1,137 +0,0 @@
|
||||
// @ts-nocheck
|
||||
export {};
|
||||
|
||||
; declare global {
|
||||
const __VLS_directiveBindingRestFields: { instance: null, oldValue: null, modifiers: any, dir: any };
|
||||
const __VLS_unref: typeof import('vue').unref;
|
||||
const __VLS_placeholder: any;
|
||||
|
||||
type __VLS_NativeElements = __VLS_SpreadMerge<SVGElementTagNameMap, HTMLElementTagNameMap>;
|
||||
type __VLS_IntrinsicElements = import('vue/jsx-runtime').JSX.IntrinsicElements;
|
||||
type __VLS_Element = import('vue/jsx-runtime').JSX.Element;
|
||||
type __VLS_GlobalComponents = import('vue').GlobalComponents;
|
||||
type __VLS_GlobalDirectives = import('vue').GlobalDirectives;
|
||||
type __VLS_IsAny<T> = 0 extends 1 & T ? true : false;
|
||||
type __VLS_PickNotAny<A, B> = __VLS_IsAny<A> extends true ? B : A;
|
||||
type __VLS_SpreadMerge<A, B> = Omit<A, keyof B> & B;
|
||||
type __VLS_WithComponent<N0 extends string, LocalComponents, Self, N1 extends string, N2 extends string, N3 extends string> =
|
||||
N1 extends keyof LocalComponents ? { [K in N0]: LocalComponents[N1] } :
|
||||
N2 extends keyof LocalComponents ? { [K in N0]: LocalComponents[N2] } :
|
||||
N3 extends keyof LocalComponents ? { [K in N0]: LocalComponents[N3] } :
|
||||
Self extends object ? { [K in N0]: Self } :
|
||||
N1 extends keyof __VLS_GlobalComponents ? { [K in N0]: __VLS_GlobalComponents[N1] } :
|
||||
N2 extends keyof __VLS_GlobalComponents ? { [K in N0]: __VLS_GlobalComponents[N2] } :
|
||||
N3 extends keyof __VLS_GlobalComponents ? { [K in N0]: __VLS_GlobalComponents[N3] } :
|
||||
{};
|
||||
type __VLS_FunctionalComponentCtx<T, K> = __VLS_PickNotAny<'__ctx' extends keyof __VLS_PickNotAny<K, {}>
|
||||
? K extends { __ctx?: infer Ctx } ? NonNullable<Ctx> : never : any
|
||||
, T extends (props: any, ctx: infer Ctx) => any ? Ctx : any
|
||||
>;
|
||||
type __VLS_FunctionalComponentProps<T, K> = '__ctx' extends keyof __VLS_PickNotAny<K, {}>
|
||||
? K extends { __ctx?: { props?: infer P } } ? NonNullable<P> : never
|
||||
: T extends (props: infer P, ...args: any) => any ? P
|
||||
: {};
|
||||
type __VLS_FunctionalComponent<T> = (props: (T extends { $props: infer Props } ? Props : {}) & Record<string, unknown>, ctx?: any) => __VLS_Element & {
|
||||
__ctx?: {
|
||||
attrs?: any;
|
||||
slots?: T extends { $slots: infer Slots } ? Slots : Record<string, any>;
|
||||
emit?: T extends { $emit: infer Emit } ? Emit : {};
|
||||
props?: (T extends { $props: infer Props } ? Props : {}) & Record<string, unknown>;
|
||||
expose?: (exposed: T) => void;
|
||||
};
|
||||
};
|
||||
type __VLS_IsFunction<T, K> = K extends keyof T
|
||||
? __VLS_IsAny<T[K]> extends false
|
||||
? unknown extends T[K]
|
||||
? false
|
||||
: true
|
||||
: false
|
||||
: false;
|
||||
type __VLS_NormalizeComponentEvent<
|
||||
Props,
|
||||
Emits,
|
||||
onEvent extends keyof Props,
|
||||
Event extends keyof Emits,
|
||||
CamelizedEvent extends keyof Emits,
|
||||
> = __VLS_IsFunction<Props, onEvent> extends true
|
||||
? Props
|
||||
: __VLS_IsFunction<Emits, Event> extends true
|
||||
? { [K in onEvent]?: Emits[Event] }
|
||||
: __VLS_IsFunction<Emits, CamelizedEvent> extends true
|
||||
? { [K in onEvent]?: Emits[CamelizedEvent] }
|
||||
: Props;
|
||||
// fix https://github.com/vuejs/language-tools/issues/926
|
||||
type __VLS_UnionToIntersection<U> = (U extends unknown ? (arg: U) => unknown : never) extends ((arg: infer P) => unknown) ? P : never;
|
||||
type __VLS_OverloadUnionInner<T, U = unknown> = U & T extends (...args: infer A) => infer R
|
||||
? U extends T
|
||||
? never
|
||||
: __VLS_OverloadUnionInner<T, Pick<T, keyof T> & U & ((...args: A) => R)> | ((...args: A) => R)
|
||||
: never;
|
||||
type __VLS_OverloadUnion<T> = Exclude<
|
||||
__VLS_OverloadUnionInner<(() => never) & T>,
|
||||
T extends () => never ? never : () => never
|
||||
>;
|
||||
type __VLS_ConstructorOverloads<T> = __VLS_OverloadUnion<T> extends infer F
|
||||
? F extends (event: infer E, ...args: infer A) => any
|
||||
? { [K in E & string]: (...args: A) => void; }
|
||||
: never
|
||||
: never;
|
||||
type __VLS_NormalizeEmits<T> = __VLS_PrettifyGlobal<
|
||||
__VLS_UnionToIntersection<
|
||||
__VLS_ConstructorOverloads<T> & {
|
||||
[K in keyof T]: T[K] extends any[] ? { (...args: T[K]): void } : never
|
||||
}
|
||||
>
|
||||
>;
|
||||
type __VLS_EmitsToProps<T> = __VLS_PrettifyGlobal<{
|
||||
[K in string & keyof T as `on${Capitalize<K>}`]?:
|
||||
(...args: T[K] extends (...args: infer P) => any ? P : T[K] extends null ? any[] : never) => any;
|
||||
}>;
|
||||
type __VLS_ResolveEmits<
|
||||
Comp,
|
||||
Emits,
|
||||
TypeEmits = {},
|
||||
NormalizedEmits = __VLS_NormalizeEmits<Emits> extends infer E ? string extends keyof E ? {} : E : never,
|
||||
> = __VLS_SpreadMerge<NormalizedEmits, TypeEmits>;
|
||||
type __VLS_ResolveDirectives<T> = {
|
||||
[K in keyof T & string as `v${Capitalize<K>}`]: T[K];
|
||||
};
|
||||
type __VLS_PrettifyGlobal<T> = { [K in keyof T as K]: T[K]; } & {};
|
||||
type __VLS_WithDefaultsGlobal<P, D> = {
|
||||
[K in keyof P as K extends keyof D ? K : never]-?: P[K];
|
||||
} & {
|
||||
[K in keyof P as K extends keyof D ? never : K]: P[K];
|
||||
};
|
||||
type __VLS_UseTemplateRef<T> = Readonly<import('vue').ShallowRef<T | null>>;
|
||||
type __VLS_ProxyRefs<T> = import('vue').ShallowUnwrapRef<T>;
|
||||
|
||||
function __VLS_getVForSourceType<T extends number | string | any[] | Iterable<any>>(source: T): [
|
||||
item: T extends number ? number
|
||||
: T extends string ? string
|
||||
: T extends any[] ? T[number]
|
||||
: T extends Iterable<infer T1> ? T1
|
||||
: any,
|
||||
index: number,
|
||||
][];
|
||||
function __VLS_getVForSourceType<T>(source: T): [
|
||||
item: T[keyof T],
|
||||
key: keyof T,
|
||||
index: number,
|
||||
][];
|
||||
function __VLS_getSlotParameters<S, D extends S>(slot: S, decl?: D):
|
||||
D extends (...args: infer P) => any ? P : any[];
|
||||
function __VLS_asFunctionalDirective<T>(dir: T): T extends import('vue').ObjectDirective
|
||||
? NonNullable<T['created' | 'beforeMount' | 'mounted' | 'beforeUpdate' | 'updated' | 'beforeUnmount' | 'unmounted']>
|
||||
: T extends (...args: any) => any
|
||||
? T
|
||||
: (arg1: unknown, arg2: unknown, arg3: unknown, arg4: unknown) => void;
|
||||
function __VLS_asFunctionalComponent<T, K = T extends new (...args: any) => any ? InstanceType<T> : unknown>(t: T, instance?: K):
|
||||
T extends new (...args: any) => any ? __VLS_FunctionalComponent<K>
|
||||
: T extends () => any ? (props: {}, ctx?: any) => ReturnType<T>
|
||||
: T extends (...args: any) => any ? T
|
||||
: __VLS_FunctionalComponent<{}>;
|
||||
function __VLS_functionalComponentArgsRest<T extends (...args: any) => any>(t: T): 2 extends Parameters<T>['length'] ? [any] : [];
|
||||
function __VLS_asFunctionalElement<T>(tag: T, endTag?: T): (attrs: T & Record<string, unknown>) => void;
|
||||
function __VLS_asFunctionalSlot<S>(slot: S): S extends () => infer R ? (props: {}) => R : NonNullable<S>;
|
||||
function __VLS_tryAsConstant<const T>(t: T): T;
|
||||
}
|
||||
137
pmoupnp/webapp/node_modules/.vue-global-types/vue_99_0.d.ts
generated
vendored
137
pmoupnp/webapp/node_modules/.vue-global-types/vue_99_0.d.ts
generated
vendored
@@ -1,137 +0,0 @@
|
||||
// @ts-nocheck
|
||||
export {};
|
||||
|
||||
; declare global {
|
||||
const __VLS_directiveBindingRestFields: { instance: null, oldValue: null, modifiers: any, dir: any };
|
||||
const __VLS_unref: typeof import('vue').unref;
|
||||
const __VLS_placeholder: any;
|
||||
|
||||
type __VLS_NativeElements = __VLS_SpreadMerge<SVGElementTagNameMap, HTMLElementTagNameMap>;
|
||||
type __VLS_IntrinsicElements = import('vue/jsx-runtime').JSX.IntrinsicElements;
|
||||
type __VLS_Element = import('vue/jsx-runtime').JSX.Element;
|
||||
type __VLS_GlobalComponents = import('vue').GlobalComponents;
|
||||
type __VLS_GlobalDirectives = import('vue').GlobalDirectives;
|
||||
type __VLS_IsAny<T> = 0 extends 1 & T ? true : false;
|
||||
type __VLS_PickNotAny<A, B> = __VLS_IsAny<A> extends true ? B : A;
|
||||
type __VLS_SpreadMerge<A, B> = Omit<A, keyof B> & B;
|
||||
type __VLS_WithComponent<N0 extends string, LocalComponents, Self, N1 extends string, N2 extends string, N3 extends string> =
|
||||
N1 extends keyof LocalComponents ? { [K in N0]: LocalComponents[N1] } :
|
||||
N2 extends keyof LocalComponents ? { [K in N0]: LocalComponents[N2] } :
|
||||
N3 extends keyof LocalComponents ? { [K in N0]: LocalComponents[N3] } :
|
||||
Self extends object ? { [K in N0]: Self } :
|
||||
N1 extends keyof __VLS_GlobalComponents ? { [K in N0]: __VLS_GlobalComponents[N1] } :
|
||||
N2 extends keyof __VLS_GlobalComponents ? { [K in N0]: __VLS_GlobalComponents[N2] } :
|
||||
N3 extends keyof __VLS_GlobalComponents ? { [K in N0]: __VLS_GlobalComponents[N3] } :
|
||||
{};
|
||||
type __VLS_FunctionalComponentCtx<T, K> = __VLS_PickNotAny<'__ctx' extends keyof __VLS_PickNotAny<K, {}>
|
||||
? K extends { __ctx?: infer Ctx } ? NonNullable<Ctx> : never : any
|
||||
, T extends (props: any, ctx: infer Ctx) => any ? Ctx : any
|
||||
>;
|
||||
type __VLS_FunctionalComponentProps<T, K> = '__ctx' extends keyof __VLS_PickNotAny<K, {}>
|
||||
? K extends { __ctx?: { props?: infer P } } ? NonNullable<P> : never
|
||||
: T extends (props: infer P, ...args: any) => any ? P
|
||||
: {};
|
||||
type __VLS_FunctionalComponent<T> = (props: (T extends { $props: infer Props } ? Props : {}) & Record<string, unknown>, ctx?: any) => __VLS_Element & {
|
||||
__ctx?: {
|
||||
attrs?: any;
|
||||
slots?: T extends { $slots: infer Slots } ? Slots : Record<string, any>;
|
||||
emit?: T extends { $emit: infer Emit } ? Emit : {};
|
||||
props?: (T extends { $props: infer Props } ? Props : {}) & Record<string, unknown>;
|
||||
expose?: (exposed: T) => void;
|
||||
};
|
||||
};
|
||||
type __VLS_IsFunction<T, K> = K extends keyof T
|
||||
? __VLS_IsAny<T[K]> extends false
|
||||
? unknown extends T[K]
|
||||
? false
|
||||
: true
|
||||
: false
|
||||
: false;
|
||||
type __VLS_NormalizeComponentEvent<
|
||||
Props,
|
||||
Emits,
|
||||
onEvent extends keyof Props,
|
||||
Event extends keyof Emits,
|
||||
CamelizedEvent extends keyof Emits,
|
||||
> = __VLS_IsFunction<Props, onEvent> extends true
|
||||
? Props
|
||||
: __VLS_IsFunction<Emits, Event> extends true
|
||||
? { [K in onEvent]?: Emits[Event] }
|
||||
: __VLS_IsFunction<Emits, CamelizedEvent> extends true
|
||||
? { [K in onEvent]?: Emits[CamelizedEvent] }
|
||||
: Props;
|
||||
// fix https://github.com/vuejs/language-tools/issues/926
|
||||
type __VLS_UnionToIntersection<U> = (U extends unknown ? (arg: U) => unknown : never) extends ((arg: infer P) => unknown) ? P : never;
|
||||
type __VLS_OverloadUnionInner<T, U = unknown> = U & T extends (...args: infer A) => infer R
|
||||
? U extends T
|
||||
? never
|
||||
: __VLS_OverloadUnionInner<T, Pick<T, keyof T> & U & ((...args: A) => R)> | ((...args: A) => R)
|
||||
: never;
|
||||
type __VLS_OverloadUnion<T> = Exclude<
|
||||
__VLS_OverloadUnionInner<(() => never) & T>,
|
||||
T extends () => never ? never : () => never
|
||||
>;
|
||||
type __VLS_ConstructorOverloads<T> = __VLS_OverloadUnion<T> extends infer F
|
||||
? F extends (event: infer E, ...args: infer A) => any
|
||||
? { [K in E & string]: (...args: A) => void; }
|
||||
: never
|
||||
: never;
|
||||
type __VLS_NormalizeEmits<T> = __VLS_PrettifyGlobal<
|
||||
__VLS_UnionToIntersection<
|
||||
__VLS_ConstructorOverloads<T> & {
|
||||
[K in keyof T]: T[K] extends any[] ? { (...args: T[K]): void } : never
|
||||
}
|
||||
>
|
||||
>;
|
||||
type __VLS_EmitsToProps<T> = __VLS_PrettifyGlobal<{
|
||||
[K in string & keyof T as `on${Capitalize<K>}`]?:
|
||||
(...args: T[K] extends (...args: infer P) => any ? P : T[K] extends null ? any[] : never) => any;
|
||||
}>;
|
||||
type __VLS_ResolveEmits<
|
||||
Comp,
|
||||
Emits,
|
||||
TypeEmits = Comp extends { __typeEmits?: infer T } ? unknown extends T ? {} : import('vue').ShortEmitsToObject<T> : {},
|
||||
NormalizedEmits = __VLS_NormalizeEmits<Emits> extends infer E ? string extends keyof E ? {} : E : never,
|
||||
> = __VLS_SpreadMerge<NormalizedEmits, TypeEmits>;
|
||||
type __VLS_ResolveDirectives<T> = {
|
||||
[K in keyof T & string as `v${Capitalize<K>}`]: T[K];
|
||||
};
|
||||
type __VLS_PrettifyGlobal<T> = { [K in keyof T as K]: T[K]; } & {};
|
||||
type __VLS_WithDefaultsGlobal<P, D> = {
|
||||
[K in keyof P as K extends keyof D ? K : never]-?: P[K];
|
||||
} & {
|
||||
[K in keyof P as K extends keyof D ? never : K]: P[K];
|
||||
};
|
||||
type __VLS_UseTemplateRef<T> = Readonly<import('vue').ShallowRef<T | null>>;
|
||||
type __VLS_ProxyRefs<T> = import('vue').ShallowUnwrapRef<T>;
|
||||
|
||||
function __VLS_getVForSourceType<T extends number | string | any[] | Iterable<any>>(source: T): [
|
||||
item: T extends number ? number
|
||||
: T extends string ? string
|
||||
: T extends any[] ? T[number]
|
||||
: T extends Iterable<infer T1> ? T1
|
||||
: any,
|
||||
index: number,
|
||||
][];
|
||||
function __VLS_getVForSourceType<T>(source: T): [
|
||||
item: T[keyof T],
|
||||
key: keyof T,
|
||||
index: number,
|
||||
][];
|
||||
function __VLS_getSlotParameters<S, D extends S>(slot: S, decl?: D):
|
||||
D extends (...args: infer P) => any ? P : any[];
|
||||
function __VLS_asFunctionalDirective<T>(dir: T): T extends import('vue').ObjectDirective
|
||||
? NonNullable<T['created' | 'beforeMount' | 'mounted' | 'beforeUpdate' | 'updated' | 'beforeUnmount' | 'unmounted']>
|
||||
: T extends (...args: any) => any
|
||||
? T
|
||||
: (arg1: unknown, arg2: unknown, arg3: unknown, arg4: unknown) => void;
|
||||
function __VLS_asFunctionalComponent<T, K = T extends new (...args: any) => any ? InstanceType<T> : unknown>(t: T, instance?: K):
|
||||
T extends new (...args: any) => any ? __VLS_FunctionalComponent<K>
|
||||
: T extends () => any ? (props: {}, ctx?: any) => ReturnType<T>
|
||||
: T extends (...args: any) => any ? T
|
||||
: __VLS_FunctionalComponent<{}>;
|
||||
function __VLS_functionalComponentArgsRest<T extends (...args: any) => any>(t: T): 2 extends Parameters<T>['length'] ? [any] : [];
|
||||
function __VLS_asFunctionalElement<T>(tag: T, endTag?: T): (attrs: T & Record<string, unknown>) => void;
|
||||
function __VLS_asFunctionalSlot<S>(slot: S): S extends () => infer R ? (props: {}) => R : NonNullable<S>;
|
||||
function __VLS_tryAsConstant<const T>(t: T): T;
|
||||
}
|
||||
22
pmoupnp/webapp/node_modules/@babel/helper-string-parser/LICENSE
generated
vendored
22
pmoupnp/webapp/node_modules/@babel/helper-string-parser/LICENSE
generated
vendored
@@ -1,22 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2014-present Sebastian McKenzie and other contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
19
pmoupnp/webapp/node_modules/@babel/helper-string-parser/README.md
generated
vendored
19
pmoupnp/webapp/node_modules/@babel/helper-string-parser/README.md
generated
vendored
@@ -1,19 +0,0 @@
|
||||
# @babel/helper-string-parser
|
||||
|
||||
> A utility package to parse strings
|
||||
|
||||
See our website [@babel/helper-string-parser](https://babeljs.io/docs/babel-helper-string-parser) for more information.
|
||||
|
||||
## Install
|
||||
|
||||
Using npm:
|
||||
|
||||
```sh
|
||||
npm install --save @babel/helper-string-parser
|
||||
```
|
||||
|
||||
or using yarn:
|
||||
|
||||
```sh
|
||||
yarn add @babel/helper-string-parser
|
||||
```
|
||||
295
pmoupnp/webapp/node_modules/@babel/helper-string-parser/lib/index.js
generated
vendored
295
pmoupnp/webapp/node_modules/@babel/helper-string-parser/lib/index.js
generated
vendored
@@ -1,295 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.readCodePoint = readCodePoint;
|
||||
exports.readInt = readInt;
|
||||
exports.readStringContents = readStringContents;
|
||||
var _isDigit = function isDigit(code) {
|
||||
return code >= 48 && code <= 57;
|
||||
};
|
||||
const forbiddenNumericSeparatorSiblings = {
|
||||
decBinOct: new Set([46, 66, 69, 79, 95, 98, 101, 111]),
|
||||
hex: new Set([46, 88, 95, 120])
|
||||
};
|
||||
const isAllowedNumericSeparatorSibling = {
|
||||
bin: ch => ch === 48 || ch === 49,
|
||||
oct: ch => ch >= 48 && ch <= 55,
|
||||
dec: ch => ch >= 48 && ch <= 57,
|
||||
hex: ch => ch >= 48 && ch <= 57 || ch >= 65 && ch <= 70 || ch >= 97 && ch <= 102
|
||||
};
|
||||
function readStringContents(type, input, pos, lineStart, curLine, errors) {
|
||||
const initialPos = pos;
|
||||
const initialLineStart = lineStart;
|
||||
const initialCurLine = curLine;
|
||||
let out = "";
|
||||
let firstInvalidLoc = null;
|
||||
let chunkStart = pos;
|
||||
const {
|
||||
length
|
||||
} = input;
|
||||
for (;;) {
|
||||
if (pos >= length) {
|
||||
errors.unterminated(initialPos, initialLineStart, initialCurLine);
|
||||
out += input.slice(chunkStart, pos);
|
||||
break;
|
||||
}
|
||||
const ch = input.charCodeAt(pos);
|
||||
if (isStringEnd(type, ch, input, pos)) {
|
||||
out += input.slice(chunkStart, pos);
|
||||
break;
|
||||
}
|
||||
if (ch === 92) {
|
||||
out += input.slice(chunkStart, pos);
|
||||
const res = readEscapedChar(input, pos, lineStart, curLine, type === "template", errors);
|
||||
if (res.ch === null && !firstInvalidLoc) {
|
||||
firstInvalidLoc = {
|
||||
pos,
|
||||
lineStart,
|
||||
curLine
|
||||
};
|
||||
} else {
|
||||
out += res.ch;
|
||||
}
|
||||
({
|
||||
pos,
|
||||
lineStart,
|
||||
curLine
|
||||
} = res);
|
||||
chunkStart = pos;
|
||||
} else if (ch === 8232 || ch === 8233) {
|
||||
++pos;
|
||||
++curLine;
|
||||
lineStart = pos;
|
||||
} else if (ch === 10 || ch === 13) {
|
||||
if (type === "template") {
|
||||
out += input.slice(chunkStart, pos) + "\n";
|
||||
++pos;
|
||||
if (ch === 13 && input.charCodeAt(pos) === 10) {
|
||||
++pos;
|
||||
}
|
||||
++curLine;
|
||||
chunkStart = lineStart = pos;
|
||||
} else {
|
||||
errors.unterminated(initialPos, initialLineStart, initialCurLine);
|
||||
}
|
||||
} else {
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
return {
|
||||
pos,
|
||||
str: out,
|
||||
firstInvalidLoc,
|
||||
lineStart,
|
||||
curLine,
|
||||
containsInvalid: !!firstInvalidLoc
|
||||
};
|
||||
}
|
||||
function isStringEnd(type, ch, input, pos) {
|
||||
if (type === "template") {
|
||||
return ch === 96 || ch === 36 && input.charCodeAt(pos + 1) === 123;
|
||||
}
|
||||
return ch === (type === "double" ? 34 : 39);
|
||||
}
|
||||
function readEscapedChar(input, pos, lineStart, curLine, inTemplate, errors) {
|
||||
const throwOnInvalid = !inTemplate;
|
||||
pos++;
|
||||
const res = ch => ({
|
||||
pos,
|
||||
ch,
|
||||
lineStart,
|
||||
curLine
|
||||
});
|
||||
const ch = input.charCodeAt(pos++);
|
||||
switch (ch) {
|
||||
case 110:
|
||||
return res("\n");
|
||||
case 114:
|
||||
return res("\r");
|
||||
case 120:
|
||||
{
|
||||
let code;
|
||||
({
|
||||
code,
|
||||
pos
|
||||
} = readHexChar(input, pos, lineStart, curLine, 2, false, throwOnInvalid, errors));
|
||||
return res(code === null ? null : String.fromCharCode(code));
|
||||
}
|
||||
case 117:
|
||||
{
|
||||
let code;
|
||||
({
|
||||
code,
|
||||
pos
|
||||
} = readCodePoint(input, pos, lineStart, curLine, throwOnInvalid, errors));
|
||||
return res(code === null ? null : String.fromCodePoint(code));
|
||||
}
|
||||
case 116:
|
||||
return res("\t");
|
||||
case 98:
|
||||
return res("\b");
|
||||
case 118:
|
||||
return res("\u000b");
|
||||
case 102:
|
||||
return res("\f");
|
||||
case 13:
|
||||
if (input.charCodeAt(pos) === 10) {
|
||||
++pos;
|
||||
}
|
||||
case 10:
|
||||
lineStart = pos;
|
||||
++curLine;
|
||||
case 8232:
|
||||
case 8233:
|
||||
return res("");
|
||||
case 56:
|
||||
case 57:
|
||||
if (inTemplate) {
|
||||
return res(null);
|
||||
} else {
|
||||
errors.strictNumericEscape(pos - 1, lineStart, curLine);
|
||||
}
|
||||
default:
|
||||
if (ch >= 48 && ch <= 55) {
|
||||
const startPos = pos - 1;
|
||||
const match = /^[0-7]+/.exec(input.slice(startPos, pos + 2));
|
||||
let octalStr = match[0];
|
||||
let octal = parseInt(octalStr, 8);
|
||||
if (octal > 255) {
|
||||
octalStr = octalStr.slice(0, -1);
|
||||
octal = parseInt(octalStr, 8);
|
||||
}
|
||||
pos += octalStr.length - 1;
|
||||
const next = input.charCodeAt(pos);
|
||||
if (octalStr !== "0" || next === 56 || next === 57) {
|
||||
if (inTemplate) {
|
||||
return res(null);
|
||||
} else {
|
||||
errors.strictNumericEscape(startPos, lineStart, curLine);
|
||||
}
|
||||
}
|
||||
return res(String.fromCharCode(octal));
|
||||
}
|
||||
return res(String.fromCharCode(ch));
|
||||
}
|
||||
}
|
||||
function readHexChar(input, pos, lineStart, curLine, len, forceLen, throwOnInvalid, errors) {
|
||||
const initialPos = pos;
|
||||
let n;
|
||||
({
|
||||
n,
|
||||
pos
|
||||
} = readInt(input, pos, lineStart, curLine, 16, len, forceLen, false, errors, !throwOnInvalid));
|
||||
if (n === null) {
|
||||
if (throwOnInvalid) {
|
||||
errors.invalidEscapeSequence(initialPos, lineStart, curLine);
|
||||
} else {
|
||||
pos = initialPos - 1;
|
||||
}
|
||||
}
|
||||
return {
|
||||
code: n,
|
||||
pos
|
||||
};
|
||||
}
|
||||
function readInt(input, pos, lineStart, curLine, radix, len, forceLen, allowNumSeparator, errors, bailOnError) {
|
||||
const start = pos;
|
||||
const forbiddenSiblings = radix === 16 ? forbiddenNumericSeparatorSiblings.hex : forbiddenNumericSeparatorSiblings.decBinOct;
|
||||
const isAllowedSibling = radix === 16 ? isAllowedNumericSeparatorSibling.hex : radix === 10 ? isAllowedNumericSeparatorSibling.dec : radix === 8 ? isAllowedNumericSeparatorSibling.oct : isAllowedNumericSeparatorSibling.bin;
|
||||
let invalid = false;
|
||||
let total = 0;
|
||||
for (let i = 0, e = len == null ? Infinity : len; i < e; ++i) {
|
||||
const code = input.charCodeAt(pos);
|
||||
let val;
|
||||
if (code === 95 && allowNumSeparator !== "bail") {
|
||||
const prev = input.charCodeAt(pos - 1);
|
||||
const next = input.charCodeAt(pos + 1);
|
||||
if (!allowNumSeparator) {
|
||||
if (bailOnError) return {
|
||||
n: null,
|
||||
pos
|
||||
};
|
||||
errors.numericSeparatorInEscapeSequence(pos, lineStart, curLine);
|
||||
} else if (Number.isNaN(next) || !isAllowedSibling(next) || forbiddenSiblings.has(prev) || forbiddenSiblings.has(next)) {
|
||||
if (bailOnError) return {
|
||||
n: null,
|
||||
pos
|
||||
};
|
||||
errors.unexpectedNumericSeparator(pos, lineStart, curLine);
|
||||
}
|
||||
++pos;
|
||||
continue;
|
||||
}
|
||||
if (code >= 97) {
|
||||
val = code - 97 + 10;
|
||||
} else if (code >= 65) {
|
||||
val = code - 65 + 10;
|
||||
} else if (_isDigit(code)) {
|
||||
val = code - 48;
|
||||
} else {
|
||||
val = Infinity;
|
||||
}
|
||||
if (val >= radix) {
|
||||
if (val <= 9 && bailOnError) {
|
||||
return {
|
||||
n: null,
|
||||
pos
|
||||
};
|
||||
} else if (val <= 9 && errors.invalidDigit(pos, lineStart, curLine, radix)) {
|
||||
val = 0;
|
||||
} else if (forceLen) {
|
||||
val = 0;
|
||||
invalid = true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
++pos;
|
||||
total = total * radix + val;
|
||||
}
|
||||
if (pos === start || len != null && pos - start !== len || invalid) {
|
||||
return {
|
||||
n: null,
|
||||
pos
|
||||
};
|
||||
}
|
||||
return {
|
||||
n: total,
|
||||
pos
|
||||
};
|
||||
}
|
||||
function readCodePoint(input, pos, lineStart, curLine, throwOnInvalid, errors) {
|
||||
const ch = input.charCodeAt(pos);
|
||||
let code;
|
||||
if (ch === 123) {
|
||||
++pos;
|
||||
({
|
||||
code,
|
||||
pos
|
||||
} = readHexChar(input, pos, lineStart, curLine, input.indexOf("}", pos) - pos, true, throwOnInvalid, errors));
|
||||
++pos;
|
||||
if (code !== null && code > 0x10ffff) {
|
||||
if (throwOnInvalid) {
|
||||
errors.invalidCodePoint(pos, lineStart, curLine);
|
||||
} else {
|
||||
return {
|
||||
code: null,
|
||||
pos
|
||||
};
|
||||
}
|
||||
}
|
||||
} else {
|
||||
({
|
||||
code,
|
||||
pos
|
||||
} = readHexChar(input, pos, lineStart, curLine, 4, false, throwOnInvalid, errors));
|
||||
}
|
||||
return {
|
||||
code,
|
||||
pos
|
||||
};
|
||||
}
|
||||
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
pmoupnp/webapp/node_modules/@babel/helper-string-parser/lib/index.js.map
generated
vendored
1
pmoupnp/webapp/node_modules/@babel/helper-string-parser/lib/index.js.map
generated
vendored
File diff suppressed because one or more lines are too long
31
pmoupnp/webapp/node_modules/@babel/helper-string-parser/package.json
generated
vendored
31
pmoupnp/webapp/node_modules/@babel/helper-string-parser/package.json
generated
vendored
@@ -1,31 +0,0 @@
|
||||
{
|
||||
"name": "@babel/helper-string-parser",
|
||||
"version": "7.27.1",
|
||||
"description": "A utility package to parse strings",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/babel/babel.git",
|
||||
"directory": "packages/babel-helper-string-parser"
|
||||
},
|
||||
"homepage": "https://babel.dev/docs/en/next/babel-helper-string-parser",
|
||||
"license": "MIT",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"main": "./lib/index.js",
|
||||
"devDependencies": {
|
||||
"charcodes": "^0.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
},
|
||||
"author": "The Babel Team (https://babel.dev/team)",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./lib/index.d.ts",
|
||||
"default": "./lib/index.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"type": "commonjs"
|
||||
}
|
||||
22
pmoupnp/webapp/node_modules/@babel/helper-validator-identifier/LICENSE
generated
vendored
22
pmoupnp/webapp/node_modules/@babel/helper-validator-identifier/LICENSE
generated
vendored
@@ -1,22 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2014-present Sebastian McKenzie and other contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
19
pmoupnp/webapp/node_modules/@babel/helper-validator-identifier/README.md
generated
vendored
19
pmoupnp/webapp/node_modules/@babel/helper-validator-identifier/README.md
generated
vendored
@@ -1,19 +0,0 @@
|
||||
# @babel/helper-validator-identifier
|
||||
|
||||
> Validate identifier/keywords name
|
||||
|
||||
See our website [@babel/helper-validator-identifier](https://babeljs.io/docs/babel-helper-validator-identifier) for more information.
|
||||
|
||||
## Install
|
||||
|
||||
Using npm:
|
||||
|
||||
```sh
|
||||
npm install --save @babel/helper-validator-identifier
|
||||
```
|
||||
|
||||
or using yarn:
|
||||
|
||||
```sh
|
||||
yarn add @babel/helper-validator-identifier
|
||||
```
|
||||
70
pmoupnp/webapp/node_modules/@babel/helper-validator-identifier/lib/identifier.js
generated
vendored
70
pmoupnp/webapp/node_modules/@babel/helper-validator-identifier/lib/identifier.js
generated
vendored
@@ -1,70 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.isIdentifierChar = isIdentifierChar;
|
||||
exports.isIdentifierName = isIdentifierName;
|
||||
exports.isIdentifierStart = isIdentifierStart;
|
||||
let nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u0870-\u0887\u0889-\u088e\u08a0-\u08c9\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c5d\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cdd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d04-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u1711\u171f-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4c\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c8a\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5\u1cf6\u1cfa\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31bf\u31f0-\u31ff\u3400-\u4dbf\u4e00-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7cd\ua7d0\ua7d1\ua7d3\ua7d5-\ua7dc\ua7f2-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab69\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc";
|
||||
let nonASCIIidentifierChars = "\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u0897-\u089f\u08ca-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b55-\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3c\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0cf3\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d81-\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ece\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1715\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u180f-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1abf-\u1ace\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf4\u1cf7-\u1cf9\u1dc0-\u1dff\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\u30fb\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua82c\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f\uff65";
|
||||
const nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]");
|
||||
const nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");
|
||||
nonASCIIidentifierStartChars = nonASCIIidentifierChars = null;
|
||||
const astralIdentifierStartCodes = [0, 11, 2, 25, 2, 18, 2, 1, 2, 14, 3, 13, 35, 122, 70, 52, 268, 28, 4, 48, 48, 31, 14, 29, 6, 37, 11, 29, 3, 35, 5, 7, 2, 4, 43, 157, 19, 35, 5, 35, 5, 39, 9, 51, 13, 10, 2, 14, 2, 6, 2, 1, 2, 10, 2, 14, 2, 6, 2, 1, 4, 51, 13, 310, 10, 21, 11, 7, 25, 5, 2, 41, 2, 8, 70, 5, 3, 0, 2, 43, 2, 1, 4, 0, 3, 22, 11, 22, 10, 30, 66, 18, 2, 1, 11, 21, 11, 25, 71, 55, 7, 1, 65, 0, 16, 3, 2, 2, 2, 28, 43, 28, 4, 28, 36, 7, 2, 27, 28, 53, 11, 21, 11, 18, 14, 17, 111, 72, 56, 50, 14, 50, 14, 35, 39, 27, 10, 22, 251, 41, 7, 1, 17, 2, 60, 28, 11, 0, 9, 21, 43, 17, 47, 20, 28, 22, 13, 52, 58, 1, 3, 0, 14, 44, 33, 24, 27, 35, 30, 0, 3, 0, 9, 34, 4, 0, 13, 47, 15, 3, 22, 0, 2, 0, 36, 17, 2, 24, 20, 1, 64, 6, 2, 0, 2, 3, 2, 14, 2, 9, 8, 46, 39, 7, 3, 1, 3, 21, 2, 6, 2, 1, 2, 4, 4, 0, 19, 0, 13, 4, 31, 9, 2, 0, 3, 0, 2, 37, 2, 0, 26, 0, 2, 0, 45, 52, 19, 3, 21, 2, 31, 47, 21, 1, 2, 0, 185, 46, 42, 3, 37, 47, 21, 0, 60, 42, 14, 0, 72, 26, 38, 6, 186, 43, 117, 63, 32, 7, 3, 0, 3, 7, 2, 1, 2, 23, 16, 0, 2, 0, 95, 7, 3, 38, 17, 0, 2, 0, 29, 0, 11, 39, 8, 0, 22, 0, 12, 45, 20, 0, 19, 72, 200, 32, 32, 8, 2, 36, 18, 0, 50, 29, 113, 6, 2, 1, 2, 37, 22, 0, 26, 5, 2, 1, 2, 31, 15, 0, 328, 18, 16, 0, 2, 12, 2, 33, 125, 0, 80, 921, 103, 110, 18, 195, 2637, 96, 16, 1071, 18, 5, 26, 3994, 6, 582, 6842, 29, 1763, 568, 8, 30, 18, 78, 18, 29, 19, 47, 17, 3, 32, 20, 6, 18, 433, 44, 212, 63, 129, 74, 6, 0, 67, 12, 65, 1, 2, 0, 29, 6135, 9, 1237, 42, 9, 8936, 3, 2, 6, 2, 1, 2, 290, 16, 0, 30, 2, 3, 0, 15, 3, 9, 395, 2309, 106, 6, 12, 4, 8, 8, 9, 5991, 84, 2, 70, 2, 1, 3, 0, 3, 1, 3, 3, 2, 11, 2, 0, 2, 6, 2, 64, 2, 3, 3, 7, 2, 6, 2, 27, 2, 3, 2, 4, 2, 0, 4, 6, 2, 339, 3, 24, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 7, 1845, 30, 7, 5, 262, 61, 147, 44, 11, 6, 17, 0, 322, 29, 19, 43, 485, 27, 229, 29, 3, 0, 496, 6, 2, 3, 2, 1, 2, 14, 2, 196, 60, 67, 8, 0, 1205, 3, 2, 26, 2, 1, 2, 0, 3, 0, 2, 9, 2, 3, 2, 0, 2, 0, 7, 0, 5, 0, 2, 0, 2, 0, 2, 2, 2, 1, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 3, 3, 2, 6, 2, 3, 2, 3, 2, 0, 2, 9, 2, 16, 6, 2, 2, 4, 2, 16, 4421, 42719, 33, 4153, 7, 221, 3, 5761, 15, 7472, 16, 621, 2467, 541, 1507, 4938, 6, 4191];
|
||||
const astralIdentifierCodes = [509, 0, 227, 0, 150, 4, 294, 9, 1368, 2, 2, 1, 6, 3, 41, 2, 5, 0, 166, 1, 574, 3, 9, 9, 7, 9, 32, 4, 318, 1, 80, 3, 71, 10, 50, 3, 123, 2, 54, 14, 32, 10, 3, 1, 11, 3, 46, 10, 8, 0, 46, 9, 7, 2, 37, 13, 2, 9, 6, 1, 45, 0, 13, 2, 49, 13, 9, 3, 2, 11, 83, 11, 7, 0, 3, 0, 158, 11, 6, 9, 7, 3, 56, 1, 2, 6, 3, 1, 3, 2, 10, 0, 11, 1, 3, 6, 4, 4, 68, 8, 2, 0, 3, 0, 2, 3, 2, 4, 2, 0, 15, 1, 83, 17, 10, 9, 5, 0, 82, 19, 13, 9, 214, 6, 3, 8, 28, 1, 83, 16, 16, 9, 82, 12, 9, 9, 7, 19, 58, 14, 5, 9, 243, 14, 166, 9, 71, 5, 2, 1, 3, 3, 2, 0, 2, 1, 13, 9, 120, 6, 3, 6, 4, 0, 29, 9, 41, 6, 2, 3, 9, 0, 10, 10, 47, 15, 343, 9, 54, 7, 2, 7, 17, 9, 57, 21, 2, 13, 123, 5, 4, 0, 2, 1, 2, 6, 2, 0, 9, 9, 49, 4, 2, 1, 2, 4, 9, 9, 330, 3, 10, 1, 2, 0, 49, 6, 4, 4, 14, 10, 5350, 0, 7, 14, 11465, 27, 2343, 9, 87, 9, 39, 4, 60, 6, 26, 9, 535, 9, 470, 0, 2, 54, 8, 3, 82, 0, 12, 1, 19628, 1, 4178, 9, 519, 45, 3, 22, 543, 4, 4, 5, 9, 7, 3, 6, 31, 3, 149, 2, 1418, 49, 513, 54, 5, 49, 9, 0, 15, 0, 23, 4, 2, 14, 1361, 6, 2, 16, 3, 6, 2, 1, 2, 4, 101, 0, 161, 6, 10, 9, 357, 0, 62, 13, 499, 13, 245, 1, 2, 9, 726, 6, 110, 6, 6, 9, 4759, 9, 787719, 239];
|
||||
function isInAstralSet(code, set) {
|
||||
let pos = 0x10000;
|
||||
for (let i = 0, length = set.length; i < length; i += 2) {
|
||||
pos += set[i];
|
||||
if (pos > code) return false;
|
||||
pos += set[i + 1];
|
||||
if (pos >= code) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function isIdentifierStart(code) {
|
||||
if (code < 65) return code === 36;
|
||||
if (code <= 90) return true;
|
||||
if (code < 97) return code === 95;
|
||||
if (code <= 122) return true;
|
||||
if (code <= 0xffff) {
|
||||
return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code));
|
||||
}
|
||||
return isInAstralSet(code, astralIdentifierStartCodes);
|
||||
}
|
||||
function isIdentifierChar(code) {
|
||||
if (code < 48) return code === 36;
|
||||
if (code < 58) return true;
|
||||
if (code < 65) return false;
|
||||
if (code <= 90) return true;
|
||||
if (code < 97) return code === 95;
|
||||
if (code <= 122) return true;
|
||||
if (code <= 0xffff) {
|
||||
return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code));
|
||||
}
|
||||
return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes);
|
||||
}
|
||||
function isIdentifierName(name) {
|
||||
let isFirst = true;
|
||||
for (let i = 0; i < name.length; i++) {
|
||||
let cp = name.charCodeAt(i);
|
||||
if ((cp & 0xfc00) === 0xd800 && i + 1 < name.length) {
|
||||
const trail = name.charCodeAt(++i);
|
||||
if ((trail & 0xfc00) === 0xdc00) {
|
||||
cp = 0x10000 + ((cp & 0x3ff) << 10) + (trail & 0x3ff);
|
||||
}
|
||||
}
|
||||
if (isFirst) {
|
||||
isFirst = false;
|
||||
if (!isIdentifierStart(cp)) {
|
||||
return false;
|
||||
}
|
||||
} else if (!isIdentifierChar(cp)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return !isFirst;
|
||||
}
|
||||
|
||||
//# sourceMappingURL=identifier.js.map
|
||||
1
pmoupnp/webapp/node_modules/@babel/helper-validator-identifier/lib/identifier.js.map
generated
vendored
1
pmoupnp/webapp/node_modules/@babel/helper-validator-identifier/lib/identifier.js.map
generated
vendored
File diff suppressed because one or more lines are too long
57
pmoupnp/webapp/node_modules/@babel/helper-validator-identifier/lib/index.js
generated
vendored
57
pmoupnp/webapp/node_modules/@babel/helper-validator-identifier/lib/index.js
generated
vendored
@@ -1,57 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
Object.defineProperty(exports, "isIdentifierChar", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _identifier.isIdentifierChar;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "isIdentifierName", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _identifier.isIdentifierName;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "isIdentifierStart", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _identifier.isIdentifierStart;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "isKeyword", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _keyword.isKeyword;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "isReservedWord", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _keyword.isReservedWord;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "isStrictBindOnlyReservedWord", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _keyword.isStrictBindOnlyReservedWord;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "isStrictBindReservedWord", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _keyword.isStrictBindReservedWord;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "isStrictReservedWord", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _keyword.isStrictReservedWord;
|
||||
}
|
||||
});
|
||||
var _identifier = require("./identifier.js");
|
||||
var _keyword = require("./keyword.js");
|
||||
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
pmoupnp/webapp/node_modules/@babel/helper-validator-identifier/lib/index.js.map
generated
vendored
1
pmoupnp/webapp/node_modules/@babel/helper-validator-identifier/lib/index.js.map
generated
vendored
@@ -1 +0,0 @@
|
||||
{"version":3,"names":["_identifier","require","_keyword"],"sources":["../src/index.ts"],"sourcesContent":["export {\n isIdentifierName,\n isIdentifierChar,\n isIdentifierStart,\n} from \"./identifier.ts\";\nexport {\n isReservedWord,\n isStrictBindOnlyReservedWord,\n isStrictBindReservedWord,\n isStrictReservedWord,\n isKeyword,\n} from \"./keyword.ts\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,WAAA,GAAAC,OAAA;AAKA,IAAAC,QAAA,GAAAD,OAAA","ignoreList":[]}
|
||||
35
pmoupnp/webapp/node_modules/@babel/helper-validator-identifier/lib/keyword.js
generated
vendored
35
pmoupnp/webapp/node_modules/@babel/helper-validator-identifier/lib/keyword.js
generated
vendored
@@ -1,35 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.isKeyword = isKeyword;
|
||||
exports.isReservedWord = isReservedWord;
|
||||
exports.isStrictBindOnlyReservedWord = isStrictBindOnlyReservedWord;
|
||||
exports.isStrictBindReservedWord = isStrictBindReservedWord;
|
||||
exports.isStrictReservedWord = isStrictReservedWord;
|
||||
const reservedWords = {
|
||||
keyword: ["break", "case", "catch", "continue", "debugger", "default", "do", "else", "finally", "for", "function", "if", "return", "switch", "throw", "try", "var", "const", "while", "with", "new", "this", "super", "class", "extends", "export", "import", "null", "true", "false", "in", "instanceof", "typeof", "void", "delete"],
|
||||
strict: ["implements", "interface", "let", "package", "private", "protected", "public", "static", "yield"],
|
||||
strictBind: ["eval", "arguments"]
|
||||
};
|
||||
const keywords = new Set(reservedWords.keyword);
|
||||
const reservedWordsStrictSet = new Set(reservedWords.strict);
|
||||
const reservedWordsStrictBindSet = new Set(reservedWords.strictBind);
|
||||
function isReservedWord(word, inModule) {
|
||||
return inModule && word === "await" || word === "enum";
|
||||
}
|
||||
function isStrictReservedWord(word, inModule) {
|
||||
return isReservedWord(word, inModule) || reservedWordsStrictSet.has(word);
|
||||
}
|
||||
function isStrictBindOnlyReservedWord(word) {
|
||||
return reservedWordsStrictBindSet.has(word);
|
||||
}
|
||||
function isStrictBindReservedWord(word, inModule) {
|
||||
return isStrictReservedWord(word, inModule) || isStrictBindOnlyReservedWord(word);
|
||||
}
|
||||
function isKeyword(word) {
|
||||
return keywords.has(word);
|
||||
}
|
||||
|
||||
//# sourceMappingURL=keyword.js.map
|
||||
1
pmoupnp/webapp/node_modules/@babel/helper-validator-identifier/lib/keyword.js.map
generated
vendored
1
pmoupnp/webapp/node_modules/@babel/helper-validator-identifier/lib/keyword.js.map
generated
vendored
@@ -1 +0,0 @@
|
||||
{"version":3,"names":["reservedWords","keyword","strict","strictBind","keywords","Set","reservedWordsStrictSet","reservedWordsStrictBindSet","isReservedWord","word","inModule","isStrictReservedWord","has","isStrictBindOnlyReservedWord","isStrictBindReservedWord","isKeyword"],"sources":["../src/keyword.ts"],"sourcesContent":["const reservedWords = {\n keyword: [\n \"break\",\n \"case\",\n \"catch\",\n \"continue\",\n \"debugger\",\n \"default\",\n \"do\",\n \"else\",\n \"finally\",\n \"for\",\n \"function\",\n \"if\",\n \"return\",\n \"switch\",\n \"throw\",\n \"try\",\n \"var\",\n \"const\",\n \"while\",\n \"with\",\n \"new\",\n \"this\",\n \"super\",\n \"class\",\n \"extends\",\n \"export\",\n \"import\",\n \"null\",\n \"true\",\n \"false\",\n \"in\",\n \"instanceof\",\n \"typeof\",\n \"void\",\n \"delete\",\n ],\n strict: [\n \"implements\",\n \"interface\",\n \"let\",\n \"package\",\n \"private\",\n \"protected\",\n \"public\",\n \"static\",\n \"yield\",\n ],\n strictBind: [\"eval\", \"arguments\"],\n};\nconst keywords = new Set(reservedWords.keyword);\nconst reservedWordsStrictSet = new Set(reservedWords.strict);\nconst reservedWordsStrictBindSet = new Set(reservedWords.strictBind);\n\n/**\n * Checks if word is a reserved word in non-strict mode\n */\nexport function isReservedWord(word: string, inModule: boolean): boolean {\n return (inModule && word === \"await\") || word === \"enum\";\n}\n\n/**\n * Checks if word is a reserved word in non-binding strict mode\n *\n * Includes non-strict reserved words\n */\nexport function isStrictReservedWord(word: string, inModule: boolean): boolean {\n return isReservedWord(word, inModule) || reservedWordsStrictSet.has(word);\n}\n\n/**\n * Checks if word is a reserved word in binding strict mode, but it is allowed as\n * a normal identifier.\n */\nexport function isStrictBindOnlyReservedWord(word: string): boolean {\n return reservedWordsStrictBindSet.has(word);\n}\n\n/**\n * Checks if word is a reserved word in binding strict mode\n *\n * Includes non-strict reserved words and non-binding strict reserved words\n */\nexport function isStrictBindReservedWord(\n word: string,\n inModule: boolean,\n): boolean {\n return (\n isStrictReservedWord(word, inModule) || isStrictBindOnlyReservedWord(word)\n );\n}\n\nexport function isKeyword(word: string): boolean {\n return keywords.has(word);\n}\n"],"mappings":";;;;;;;;;;AAAA,MAAMA,aAAa,GAAG;EACpBC,OAAO,EAAE,CACP,OAAO,EACP,MAAM,EACN,OAAO,EACP,UAAU,EACV,UAAU,EACV,SAAS,EACT,IAAI,EACJ,MAAM,EACN,SAAS,EACT,KAAK,EACL,UAAU,EACV,IAAI,EACJ,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,KAAK,EACL,KAAK,EACL,OAAO,EACP,OAAO,EACP,MAAM,EACN,KAAK,EACL,MAAM,EACN,OAAO,EACP,OAAO,EACP,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,MAAM,EACN,OAAO,EACP,IAAI,EACJ,YAAY,EACZ,QAAQ,EACR,MAAM,EACN,QAAQ,CACT;EACDC,MAAM,EAAE,CACN,YAAY,EACZ,WAAW,EACX,KAAK,EACL,SAAS,EACT,SAAS,EACT,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,OAAO,CACR;EACDC,UAAU,EAAE,CAAC,MAAM,EAAE,WAAW;AAClC,CAAC;AACD,MAAMC,QAAQ,GAAG,IAAIC,GAAG,CAACL,aAAa,CAACC,OAAO,CAAC;AAC/C,MAAMK,sBAAsB,GAAG,IAAID,GAAG,CAACL,aAAa,CAACE,MAAM,CAAC;AAC5D,MAAMK,0BAA0B,GAAG,IAAIF,GAAG,CAACL,aAAa,CAACG,UAAU,CAAC;AAK7D,SAASK,cAAcA,CAACC,IAAY,EAAEC,QAAiB,EAAW;EACvE,OAAQA,QAAQ,IAAID,IAAI,KAAK,OAAO,IAAKA,IAAI,KAAK,MAAM;AAC1D;AAOO,SAASE,oBAAoBA,CAACF,IAAY,EAAEC,QAAiB,EAAW;EAC7E,OAAOF,cAAc,CAACC,IAAI,EAAEC,QAAQ,CAAC,IAAIJ,sBAAsB,CAACM,GAAG,CAACH,IAAI,CAAC;AAC3E;AAMO,SAASI,4BAA4BA,CAACJ,IAAY,EAAW;EAClE,OAAOF,0BAA0B,CAACK,GAAG,CAACH,IAAI,CAAC;AAC7C;AAOO,SAASK,wBAAwBA,CACtCL,IAAY,EACZC,QAAiB,EACR;EACT,OACEC,oBAAoB,CAACF,IAAI,EAAEC,QAAQ,CAAC,IAAIG,4BAA4B,CAACJ,IAAI,CAAC;AAE9E;AAEO,SAASM,SAASA,CAACN,IAAY,EAAW;EAC/C,OAAOL,QAAQ,CAACQ,GAAG,CAACH,IAAI,CAAC;AAC3B","ignoreList":[]}
|
||||
31
pmoupnp/webapp/node_modules/@babel/helper-validator-identifier/package.json
generated
vendored
31
pmoupnp/webapp/node_modules/@babel/helper-validator-identifier/package.json
generated
vendored
@@ -1,31 +0,0 @@
|
||||
{
|
||||
"name": "@babel/helper-validator-identifier",
|
||||
"version": "7.27.1",
|
||||
"description": "Validate identifier/keywords name",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/babel/babel.git",
|
||||
"directory": "packages/babel-helper-validator-identifier"
|
||||
},
|
||||
"license": "MIT",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"main": "./lib/index.js",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./lib/index.d.ts",
|
||||
"default": "./lib/index.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@unicode/unicode-16.0.0": "^1.0.0",
|
||||
"charcodes": "^0.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
},
|
||||
"author": "The Babel Team (https://babel.dev/team)",
|
||||
"type": "commonjs"
|
||||
}
|
||||
1073
pmoupnp/webapp/node_modules/@babel/parser/CHANGELOG.md
generated
vendored
1073
pmoupnp/webapp/node_modules/@babel/parser/CHANGELOG.md
generated
vendored
File diff suppressed because it is too large
Load Diff
19
pmoupnp/webapp/node_modules/@babel/parser/LICENSE
generated
vendored
19
pmoupnp/webapp/node_modules/@babel/parser/LICENSE
generated
vendored
@@ -1,19 +0,0 @@
|
||||
Copyright (C) 2012-2014 by various contributors (see AUTHORS)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
19
pmoupnp/webapp/node_modules/@babel/parser/README.md
generated
vendored
19
pmoupnp/webapp/node_modules/@babel/parser/README.md
generated
vendored
@@ -1,19 +0,0 @@
|
||||
# @babel/parser
|
||||
|
||||
> A JavaScript parser
|
||||
|
||||
See our website [@babel/parser](https://babeljs.io/docs/babel-parser) for more information or the [issues](https://github.com/babel/babel/issues?utf8=%E2%9C%93&q=is%3Aissue+label%3A%22pkg%3A%20parser%22+is%3Aopen) associated with this package.
|
||||
|
||||
## Install
|
||||
|
||||
Using npm:
|
||||
|
||||
```sh
|
||||
npm install --save-dev @babel/parser
|
||||
```
|
||||
|
||||
or using yarn:
|
||||
|
||||
```sh
|
||||
yarn add @babel/parser --dev
|
||||
```
|
||||
15
pmoupnp/webapp/node_modules/@babel/parser/bin/babel-parser.js
generated
vendored
15
pmoupnp/webapp/node_modules/@babel/parser/bin/babel-parser.js
generated
vendored
@@ -1,15 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
/* eslint-disable no-var, unicorn/prefer-node-protocol */
|
||||
|
||||
var parser = require("..");
|
||||
var fs = require("fs");
|
||||
|
||||
var filename = process.argv[2];
|
||||
if (!filename) {
|
||||
console.error("no filename specified");
|
||||
} else {
|
||||
var file = fs.readFileSync(filename, "utf8");
|
||||
var ast = parser.parse(file);
|
||||
|
||||
console.log(JSON.stringify(ast, null, " "));
|
||||
}
|
||||
14595
pmoupnp/webapp/node_modules/@babel/parser/lib/index.js
generated
vendored
14595
pmoupnp/webapp/node_modules/@babel/parser/lib/index.js
generated
vendored
File diff suppressed because it is too large
Load Diff
50
pmoupnp/webapp/node_modules/@babel/parser/package.json
generated
vendored
50
pmoupnp/webapp/node_modules/@babel/parser/package.json
generated
vendored
@@ -1,50 +0,0 @@
|
||||
{
|
||||
"name": "@babel/parser",
|
||||
"version": "7.28.4",
|
||||
"description": "A JavaScript parser",
|
||||
"author": "The Babel Team (https://babel.dev/team)",
|
||||
"homepage": "https://babel.dev/docs/en/next/babel-parser",
|
||||
"bugs": "https://github.com/babel/babel/issues?utf8=%E2%9C%93&q=is%3Aissue+label%3A%22pkg%3A+parser+%28babylon%29%22+is%3Aopen",
|
||||
"license": "MIT",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"keywords": [
|
||||
"babel",
|
||||
"javascript",
|
||||
"parser",
|
||||
"tc39",
|
||||
"ecmascript",
|
||||
"@babel/parser"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/babel/babel.git",
|
||||
"directory": "packages/babel-parser"
|
||||
},
|
||||
"main": "./lib/index.js",
|
||||
"types": "./typings/babel-parser.d.ts",
|
||||
"files": [
|
||||
"bin",
|
||||
"lib",
|
||||
"typings/babel-parser.d.ts",
|
||||
"index.cjs"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
},
|
||||
"# dependencies": "This package doesn't actually have runtime dependencies. @babel/types is only needed for type definitions.",
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.28.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/code-frame": "^7.27.1",
|
||||
"@babel/helper-check-duplicate-nodes": "^7.27.1",
|
||||
"@babel/helper-fixtures": "^7.28.0",
|
||||
"@babel/helper-string-parser": "^7.27.1",
|
||||
"@babel/helper-validator-identifier": "^7.27.1",
|
||||
"charcodes": "^0.2.0"
|
||||
},
|
||||
"bin": "./bin/babel-parser.js",
|
||||
"type": "commonjs"
|
||||
}
|
||||
239
pmoupnp/webapp/node_modules/@babel/parser/typings/babel-parser.d.ts
generated
vendored
239
pmoupnp/webapp/node_modules/@babel/parser/typings/babel-parser.d.ts
generated
vendored
@@ -1,239 +0,0 @@
|
||||
// This file is auto-generated! Do not modify it directly.
|
||||
// Run `yarn gulp bundle-dts` to re-generate it.
|
||||
/* eslint-disable @typescript-eslint/consistent-type-imports, @typescript-eslint/no-redundant-type-constituents */
|
||||
import { File, Expression } from '@babel/types';
|
||||
|
||||
type BABEL_8_BREAKING = false;
|
||||
type IF_BABEL_7<V> = false extends BABEL_8_BREAKING ? V : never;
|
||||
|
||||
type Plugin$1 =
|
||||
| "asyncDoExpressions"
|
||||
| IF_BABEL_7<"asyncGenerators">
|
||||
| IF_BABEL_7<"bigInt">
|
||||
| IF_BABEL_7<"classPrivateMethods">
|
||||
| IF_BABEL_7<"classPrivateProperties">
|
||||
| IF_BABEL_7<"classProperties">
|
||||
| IF_BABEL_7<"classStaticBlock">
|
||||
| IF_BABEL_7<"decimal">
|
||||
| "decorators-legacy"
|
||||
| "deferredImportEvaluation"
|
||||
| "decoratorAutoAccessors"
|
||||
| "destructuringPrivate"
|
||||
| "deprecatedImportAssert"
|
||||
| "doExpressions"
|
||||
| IF_BABEL_7<"dynamicImport">
|
||||
| IF_BABEL_7<"explicitResourceManagement">
|
||||
| "exportDefaultFrom"
|
||||
| IF_BABEL_7<"exportNamespaceFrom">
|
||||
| "flow"
|
||||
| "flowComments"
|
||||
| "functionBind"
|
||||
| "functionSent"
|
||||
| "importMeta"
|
||||
| "jsx"
|
||||
| IF_BABEL_7<"jsonStrings">
|
||||
| IF_BABEL_7<"logicalAssignment">
|
||||
| IF_BABEL_7<"importAssertions">
|
||||
| IF_BABEL_7<"importReflection">
|
||||
| "moduleBlocks"
|
||||
| IF_BABEL_7<"moduleStringNames">
|
||||
| IF_BABEL_7<"nullishCoalescingOperator">
|
||||
| IF_BABEL_7<"numericSeparator">
|
||||
| IF_BABEL_7<"objectRestSpread">
|
||||
| IF_BABEL_7<"optionalCatchBinding">
|
||||
| IF_BABEL_7<"optionalChaining">
|
||||
| "partialApplication"
|
||||
| "placeholders"
|
||||
| IF_BABEL_7<"privateIn">
|
||||
| IF_BABEL_7<"regexpUnicodeSets">
|
||||
| "sourcePhaseImports"
|
||||
| "throwExpressions"
|
||||
| IF_BABEL_7<"topLevelAwait">
|
||||
| "v8intrinsic"
|
||||
| ParserPluginWithOptions[0];
|
||||
|
||||
type ParserPluginWithOptions =
|
||||
| ["decorators", DecoratorsPluginOptions]
|
||||
| ["discardBinding", { syntaxType: "void" }]
|
||||
| ["estree", { classFeatures?: boolean }]
|
||||
| IF_BABEL_7<["importAttributes", { deprecatedAssertSyntax: boolean }]>
|
||||
| IF_BABEL_7<["moduleAttributes", { version: "may-2020" }]>
|
||||
| ["optionalChainingAssign", { version: "2023-07" }]
|
||||
| ["pipelineOperator", PipelineOperatorPluginOptions]
|
||||
| ["recordAndTuple", RecordAndTuplePluginOptions]
|
||||
| ["flow", FlowPluginOptions]
|
||||
| ["typescript", TypeScriptPluginOptions];
|
||||
|
||||
type PluginConfig = Plugin$1 | ParserPluginWithOptions;
|
||||
|
||||
interface DecoratorsPluginOptions {
|
||||
decoratorsBeforeExport?: boolean;
|
||||
allowCallParenthesized?: boolean;
|
||||
}
|
||||
|
||||
interface PipelineOperatorPluginOptions {
|
||||
proposal: BABEL_8_BREAKING extends false
|
||||
? "minimal" | "fsharp" | "hack" | "smart"
|
||||
: "fsharp" | "hack";
|
||||
topicToken?: "%" | "#" | "@@" | "^^" | "^";
|
||||
}
|
||||
|
||||
interface RecordAndTuplePluginOptions {
|
||||
syntaxType: "bar" | "hash";
|
||||
}
|
||||
|
||||
type FlowPluginOptions = BABEL_8_BREAKING extends true
|
||||
? {
|
||||
all?: boolean;
|
||||
enums?: boolean;
|
||||
}
|
||||
: {
|
||||
all?: boolean;
|
||||
};
|
||||
|
||||
interface TypeScriptPluginOptions {
|
||||
dts?: boolean;
|
||||
disallowAmbiguousJSXLike?: boolean;
|
||||
}
|
||||
|
||||
type Plugin = PluginConfig;
|
||||
|
||||
type SourceType = "script" | "commonjs" | "module" | "unambiguous";
|
||||
interface Options {
|
||||
/**
|
||||
* By default, import and export declarations can only appear at a program's top level.
|
||||
* Setting this option to true allows them anywhere where a statement is allowed.
|
||||
*/
|
||||
allowImportExportEverywhere?: boolean;
|
||||
/**
|
||||
* By default, await use is not allowed outside of an async function.
|
||||
* Set this to true to accept such code.
|
||||
*/
|
||||
allowAwaitOutsideFunction?: boolean;
|
||||
/**
|
||||
* By default, a return statement at the top level raises an error.
|
||||
* Set this to true to accept such code.
|
||||
*/
|
||||
allowReturnOutsideFunction?: boolean;
|
||||
/**
|
||||
* By default, new.target use is not allowed outside of a function or class.
|
||||
* Set this to true to accept such code.
|
||||
*/
|
||||
allowNewTargetOutsideFunction?: boolean;
|
||||
allowSuperOutsideMethod?: boolean;
|
||||
/**
|
||||
* By default, exported identifiers must refer to a declared variable.
|
||||
* Set this to true to allow export statements to reference undeclared variables.
|
||||
*/
|
||||
allowUndeclaredExports?: boolean;
|
||||
/**
|
||||
* By default, yield use is not allowed outside of a generator function.
|
||||
* Set this to true to accept such code.
|
||||
*/
|
||||
allowYieldOutsideFunction?: boolean;
|
||||
/**
|
||||
* By default, Babel parser JavaScript code according to Annex B syntax.
|
||||
* Set this to `false` to disable such behavior.
|
||||
*/
|
||||
annexB?: boolean;
|
||||
/**
|
||||
* By default, Babel attaches comments to adjacent AST nodes.
|
||||
* When this option is set to false, comments are not attached.
|
||||
* It can provide up to 30% performance improvement when the input code has many comments.
|
||||
* @babel/eslint-parser will set it for you.
|
||||
* It is not recommended to use attachComment: false with Babel transform,
|
||||
* as doing so removes all the comments in output code, and renders annotations such as
|
||||
* /* istanbul ignore next *\/ nonfunctional.
|
||||
*/
|
||||
attachComment?: boolean;
|
||||
/**
|
||||
* By default, Babel always throws an error when it finds some invalid code.
|
||||
* When this option is set to true, it will store the parsing error and
|
||||
* try to continue parsing the invalid input file.
|
||||
*/
|
||||
errorRecovery?: boolean;
|
||||
/**
|
||||
* Indicate the mode the code should be parsed in.
|
||||
* Can be one of "script", "commonjs", "module", or "unambiguous". Defaults to "script".
|
||||
* "unambiguous" will make @babel/parser attempt to guess, based on the presence
|
||||
* of ES6 import or export statements.
|
||||
* Files with ES6 imports and exports are considered "module" and are otherwise "script".
|
||||
*
|
||||
* Use "commonjs" to parse code that is intended to be run in a CommonJS environment such as Node.js.
|
||||
*/
|
||||
sourceType?: SourceType;
|
||||
/**
|
||||
* Correlate output AST nodes with their source filename.
|
||||
* Useful when generating code and source maps from the ASTs of multiple input files.
|
||||
*/
|
||||
sourceFilename?: string;
|
||||
/**
|
||||
* By default, all source indexes start from 0.
|
||||
* You can provide a start index to alternatively start with.
|
||||
* Useful for integration with other source tools.
|
||||
*/
|
||||
startIndex?: number;
|
||||
/**
|
||||
* By default, the first line of code parsed is treated as line 1.
|
||||
* You can provide a line number to alternatively start with.
|
||||
* Useful for integration with other source tools.
|
||||
*/
|
||||
startLine?: number;
|
||||
/**
|
||||
* By default, the parsed code is treated as if it starts from line 1, column 0.
|
||||
* You can provide a column number to alternatively start with.
|
||||
* Useful for integration with other source tools.
|
||||
*/
|
||||
startColumn?: number;
|
||||
/**
|
||||
* Array containing the plugins that you want to enable.
|
||||
*/
|
||||
plugins?: Plugin[];
|
||||
/**
|
||||
* Should the parser work in strict mode.
|
||||
* Defaults to true if sourceType === 'module'. Otherwise, false.
|
||||
*/
|
||||
strictMode?: boolean;
|
||||
/**
|
||||
* Adds a ranges property to each node: [node.start, node.end]
|
||||
*/
|
||||
ranges?: boolean;
|
||||
/**
|
||||
* Adds all parsed tokens to a tokens property on the File node.
|
||||
*/
|
||||
tokens?: boolean;
|
||||
/**
|
||||
* By default, the parser adds information about parentheses by setting
|
||||
* `extra.parenthesized` to `true` as needed.
|
||||
* When this option is `true` the parser creates `ParenthesizedExpression`
|
||||
* AST nodes instead of using the `extra` property.
|
||||
*/
|
||||
createParenthesizedExpressions?: boolean;
|
||||
/**
|
||||
* The default is false in Babel 7 and true in Babel 8
|
||||
* Set this to true to parse it as an `ImportExpression` node.
|
||||
* Otherwise `import(foo)` is parsed as `CallExpression(Import, [Identifier(foo)])`.
|
||||
*/
|
||||
createImportExpressions?: boolean;
|
||||
}
|
||||
|
||||
type ParserOptions = Partial<Options>;
|
||||
interface ParseError {
|
||||
code: string;
|
||||
reasonCode: string;
|
||||
}
|
||||
type ParseResult<Result extends File | Expression = File> = Result & {
|
||||
errors: null | ParseError[];
|
||||
};
|
||||
/**
|
||||
* Parse the provided code as an entire ECMAScript program.
|
||||
*/
|
||||
declare function parse(input: string, options?: ParserOptions): ParseResult<File>;
|
||||
declare function parseExpression(input: string, options?: ParserOptions): ParseResult<Expression>;
|
||||
|
||||
declare const tokTypes: {
|
||||
// todo(flow->ts) real token type
|
||||
[name: string]: any;
|
||||
};
|
||||
|
||||
export { DecoratorsPluginOptions, FlowPluginOptions, ParseError, ParseResult, ParserOptions, PluginConfig as ParserPlugin, ParserPluginWithOptions, PipelineOperatorPluginOptions, RecordAndTuplePluginOptions, TypeScriptPluginOptions, parse, parseExpression, tokTypes };
|
||||
22
pmoupnp/webapp/node_modules/@babel/types/LICENSE
generated
vendored
22
pmoupnp/webapp/node_modules/@babel/types/LICENSE
generated
vendored
@@ -1,22 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2014-present Sebastian McKenzie and other contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
19
pmoupnp/webapp/node_modules/@babel/types/README.md
generated
vendored
19
pmoupnp/webapp/node_modules/@babel/types/README.md
generated
vendored
@@ -1,19 +0,0 @@
|
||||
# @babel/types
|
||||
|
||||
> Babel Types is a Lodash-esque utility library for AST nodes
|
||||
|
||||
See our website [@babel/types](https://babeljs.io/docs/babel-types) for more information or the [issues](https://github.com/babel/babel/issues?utf8=%E2%9C%93&q=is%3Aissue+label%3A%22pkg%3A%20types%22+is%3Aopen) associated with this package.
|
||||
|
||||
## Install
|
||||
|
||||
Using npm:
|
||||
|
||||
```sh
|
||||
npm install --save-dev @babel/types
|
||||
```
|
||||
|
||||
or using yarn:
|
||||
|
||||
```sh
|
||||
yarn add @babel/types --dev
|
||||
```
|
||||
16
pmoupnp/webapp/node_modules/@babel/types/lib/asserts/assertNode.js
generated
vendored
16
pmoupnp/webapp/node_modules/@babel/types/lib/asserts/assertNode.js
generated
vendored
@@ -1,16 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = assertNode;
|
||||
var _isNode = require("../validators/isNode.js");
|
||||
function assertNode(node) {
|
||||
if (!(0, _isNode.default)(node)) {
|
||||
var _node$type;
|
||||
const type = (_node$type = node == null ? void 0 : node.type) != null ? _node$type : JSON.stringify(node);
|
||||
throw new TypeError(`Not a valid node of type "${type}"`);
|
||||
}
|
||||
}
|
||||
|
||||
//# sourceMappingURL=assertNode.js.map
|
||||
1
pmoupnp/webapp/node_modules/@babel/types/lib/asserts/assertNode.js.map
generated
vendored
1
pmoupnp/webapp/node_modules/@babel/types/lib/asserts/assertNode.js.map
generated
vendored
@@ -1 +0,0 @@
|
||||
{"version":3,"names":["_isNode","require","assertNode","node","isNode","_node$type","type","JSON","stringify","TypeError"],"sources":["../../src/asserts/assertNode.ts"],"sourcesContent":["import isNode from \"../validators/isNode.ts\";\nimport type * as t from \"../index.ts\";\n\nexport default function assertNode(node?: any): asserts node is t.Node {\n if (!isNode(node)) {\n const type = node?.type ?? JSON.stringify(node);\n throw new TypeError(`Not a valid node of type \"${type}\"`);\n }\n}\n"],"mappings":";;;;;;AAAA,IAAAA,OAAA,GAAAC,OAAA;AAGe,SAASC,UAAUA,CAACC,IAAU,EAA0B;EACrE,IAAI,CAAC,IAAAC,eAAM,EAACD,IAAI,CAAC,EAAE;IAAA,IAAAE,UAAA;IACjB,MAAMC,IAAI,IAAAD,UAAA,GAAGF,IAAI,oBAAJA,IAAI,CAAEG,IAAI,YAAAD,UAAA,GAAIE,IAAI,CAACC,SAAS,CAACL,IAAI,CAAC;IAC/C,MAAM,IAAIM,SAAS,CAAC,6BAA6BH,IAAI,GAAG,CAAC;EAC3D;AACF","ignoreList":[]}
|
||||
1251
pmoupnp/webapp/node_modules/@babel/types/lib/asserts/generated/index.js
generated
vendored
1251
pmoupnp/webapp/node_modules/@babel/types/lib/asserts/generated/index.js
generated
vendored
File diff suppressed because it is too large
Load Diff
1
pmoupnp/webapp/node_modules/@babel/types/lib/asserts/generated/index.js.map
generated
vendored
1
pmoupnp/webapp/node_modules/@babel/types/lib/asserts/generated/index.js.map
generated
vendored
File diff suppressed because one or more lines are too long
3
pmoupnp/webapp/node_modules/@babel/types/lib/ast-types/generated/index.js
generated
vendored
3
pmoupnp/webapp/node_modules/@babel/types/lib/ast-types/generated/index.js
generated
vendored
@@ -1,3 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
pmoupnp/webapp/node_modules/@babel/types/lib/ast-types/generated/index.js.map
generated
vendored
1
pmoupnp/webapp/node_modules/@babel/types/lib/ast-types/generated/index.js.map
generated
vendored
File diff suppressed because one or more lines are too long
18
pmoupnp/webapp/node_modules/@babel/types/lib/builders/flow/createFlowUnionType.js
generated
vendored
18
pmoupnp/webapp/node_modules/@babel/types/lib/builders/flow/createFlowUnionType.js
generated
vendored
@@ -1,18 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = createFlowUnionType;
|
||||
var _index = require("../generated/index.js");
|
||||
var _removeTypeDuplicates = require("../../modifications/flow/removeTypeDuplicates.js");
|
||||
function createFlowUnionType(types) {
|
||||
const flattened = (0, _removeTypeDuplicates.default)(types);
|
||||
if (flattened.length === 1) {
|
||||
return flattened[0];
|
||||
} else {
|
||||
return (0, _index.unionTypeAnnotation)(flattened);
|
||||
}
|
||||
}
|
||||
|
||||
//# sourceMappingURL=createFlowUnionType.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"names":["_index","require","_removeTypeDuplicates","createFlowUnionType","types","flattened","removeTypeDuplicates","length","unionTypeAnnotation"],"sources":["../../../src/builders/flow/createFlowUnionType.ts"],"sourcesContent":["import { unionTypeAnnotation } from \"../generated/index.ts\";\nimport removeTypeDuplicates from \"../../modifications/flow/removeTypeDuplicates.ts\";\nimport type * as t from \"../../index.ts\";\n\n/**\n * Takes an array of `types` and flattens them, removing duplicates and\n * returns a `UnionTypeAnnotation` node containing them.\n */\nexport default function createFlowUnionType<T extends t.FlowType>(\n types: [T] | Array<T>,\n): T | t.UnionTypeAnnotation {\n const flattened = removeTypeDuplicates(types);\n\n if (flattened.length === 1) {\n return flattened[0] as T;\n } else {\n return unionTypeAnnotation(flattened);\n }\n}\n"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AACA,IAAAC,qBAAA,GAAAD,OAAA;AAOe,SAASE,mBAAmBA,CACzCC,KAAqB,EACM;EAC3B,MAAMC,SAAS,GAAG,IAAAC,6BAAoB,EAACF,KAAK,CAAC;EAE7C,IAAIC,SAAS,CAACE,MAAM,KAAK,CAAC,EAAE;IAC1B,OAAOF,SAAS,CAAC,CAAC,CAAC;EACrB,CAAC,MAAM;IACL,OAAO,IAAAG,0BAAmB,EAACH,SAAS,CAAC;EACvC;AACF","ignoreList":[]}
|
||||
@@ -1,31 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
var _index = require("../generated/index.js");
|
||||
var _default = exports.default = createTypeAnnotationBasedOnTypeof;
|
||||
function createTypeAnnotationBasedOnTypeof(type) {
|
||||
switch (type) {
|
||||
case "string":
|
||||
return (0, _index.stringTypeAnnotation)();
|
||||
case "number":
|
||||
return (0, _index.numberTypeAnnotation)();
|
||||
case "undefined":
|
||||
return (0, _index.voidTypeAnnotation)();
|
||||
case "boolean":
|
||||
return (0, _index.booleanTypeAnnotation)();
|
||||
case "function":
|
||||
return (0, _index.genericTypeAnnotation)((0, _index.identifier)("Function"));
|
||||
case "object":
|
||||
return (0, _index.genericTypeAnnotation)((0, _index.identifier)("Object"));
|
||||
case "symbol":
|
||||
return (0, _index.genericTypeAnnotation)((0, _index.identifier)("Symbol"));
|
||||
case "bigint":
|
||||
return (0, _index.anyTypeAnnotation)();
|
||||
}
|
||||
throw new Error("Invalid typeof value: " + type);
|
||||
}
|
||||
|
||||
//# sourceMappingURL=createTypeAnnotationBasedOnTypeof.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"names":["_index","require","_default","exports","default","createTypeAnnotationBasedOnTypeof","type","stringTypeAnnotation","numberTypeAnnotation","voidTypeAnnotation","booleanTypeAnnotation","genericTypeAnnotation","identifier","anyTypeAnnotation","Error"],"sources":["../../../src/builders/flow/createTypeAnnotationBasedOnTypeof.ts"],"sourcesContent":["import {\n anyTypeAnnotation,\n stringTypeAnnotation,\n numberTypeAnnotation,\n voidTypeAnnotation,\n booleanTypeAnnotation,\n genericTypeAnnotation,\n identifier,\n} from \"../generated/index.ts\";\nimport type * as t from \"../../index.ts\";\n\nexport default createTypeAnnotationBasedOnTypeof as {\n (type: \"string\"): t.StringTypeAnnotation;\n (type: \"number\"): t.NumberTypeAnnotation;\n (type: \"undefined\"): t.VoidTypeAnnotation;\n (type: \"boolean\"): t.BooleanTypeAnnotation;\n (type: \"function\"): t.GenericTypeAnnotation;\n (type: \"object\"): t.GenericTypeAnnotation;\n (type: \"symbol\"): t.GenericTypeAnnotation;\n (type: \"bigint\"): t.AnyTypeAnnotation;\n};\n\n/**\n * Create a type annotation based on typeof expression.\n */\nfunction createTypeAnnotationBasedOnTypeof(type: string): t.FlowType {\n switch (type) {\n case \"string\":\n return stringTypeAnnotation();\n case \"number\":\n return numberTypeAnnotation();\n case \"undefined\":\n return voidTypeAnnotation();\n case \"boolean\":\n return booleanTypeAnnotation();\n case \"function\":\n return genericTypeAnnotation(identifier(\"Function\"));\n case \"object\":\n return genericTypeAnnotation(identifier(\"Object\"));\n case \"symbol\":\n return genericTypeAnnotation(identifier(\"Symbol\"));\n case \"bigint\":\n // todo: use BigInt annotation when Flow supports BigInt\n // https://github.com/facebook/flow/issues/6639\n return anyTypeAnnotation();\n }\n throw new Error(\"Invalid typeof value: \" + type);\n}\n"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAQ+B,IAAAC,QAAA,GAAAC,OAAA,CAAAC,OAAA,GAGhBC,iCAAiC;AAchD,SAASA,iCAAiCA,CAACC,IAAY,EAAc;EACnE,QAAQA,IAAI;IACV,KAAK,QAAQ;MACX,OAAO,IAAAC,2BAAoB,EAAC,CAAC;IAC/B,KAAK,QAAQ;MACX,OAAO,IAAAC,2BAAoB,EAAC,CAAC;IAC/B,KAAK,WAAW;MACd,OAAO,IAAAC,yBAAkB,EAAC,CAAC;IAC7B,KAAK,SAAS;MACZ,OAAO,IAAAC,4BAAqB,EAAC,CAAC;IAChC,KAAK,UAAU;MACb,OAAO,IAAAC,4BAAqB,EAAC,IAAAC,iBAAU,EAAC,UAAU,CAAC,CAAC;IACtD,KAAK,QAAQ;MACX,OAAO,IAAAD,4BAAqB,EAAC,IAAAC,iBAAU,EAAC,QAAQ,CAAC,CAAC;IACpD,KAAK,QAAQ;MACX,OAAO,IAAAD,4BAAqB,EAAC,IAAAC,iBAAU,EAAC,QAAQ,CAAC,CAAC;IACpD,KAAK,QAAQ;MAGX,OAAO,IAAAC,wBAAiB,EAAC,CAAC;EAC9B;EACA,MAAM,IAAIC,KAAK,CAAC,wBAAwB,GAAGR,IAAI,CAAC;AAClD","ignoreList":[]}
|
||||
29
pmoupnp/webapp/node_modules/@babel/types/lib/builders/generated/index.js
generated
vendored
29
pmoupnp/webapp/node_modules/@babel/types/lib/builders/generated/index.js
generated
vendored
@@ -1,29 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
var _lowercase = require("./lowercase.js");
|
||||
Object.keys(_lowercase).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _lowercase[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _lowercase[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
var _uppercase = require("./uppercase.js");
|
||||
Object.keys(_uppercase).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _uppercase[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _uppercase[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
pmoupnp/webapp/node_modules/@babel/types/lib/builders/generated/index.js.map
generated
vendored
1
pmoupnp/webapp/node_modules/@babel/types/lib/builders/generated/index.js.map
generated
vendored
File diff suppressed because one or more lines are too long
2896
pmoupnp/webapp/node_modules/@babel/types/lib/builders/generated/lowercase.js
generated
vendored
2896
pmoupnp/webapp/node_modules/@babel/types/lib/builders/generated/lowercase.js
generated
vendored
File diff suppressed because it is too large
Load Diff
1
pmoupnp/webapp/node_modules/@babel/types/lib/builders/generated/lowercase.js.map
generated
vendored
1
pmoupnp/webapp/node_modules/@babel/types/lib/builders/generated/lowercase.js.map
generated
vendored
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user