mirror of
https://github.com/lune-org/lune.git
synced 2024-12-12 13:00:37 +00:00
Version 0.5.1
This commit is contained in:
parent
c83917206f
commit
7d75d5c52f
9 changed files with 313 additions and 41 deletions
31
CHANGELOG.md
31
CHANGELOG.md
|
@ -8,6 +8,37 @@ All notable changes to this project will be documented in this file.
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## `0.5.1` - February 25th, 2023
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Added `net.encode` and `net.decode` which are equivalent to `net.jsonEncode` and `net.jsonDecode`, but with support for more formats.
|
||||||
|
|
||||||
|
**_WARNING: Unstable API_**
|
||||||
|
|
||||||
|
_This API is unstable and may change or be removed in the next major version of Lune. The purpose of making a new release with these functions is to gather feedback from the community, and potentially replace the JSON-specific encoding and decoding utilities._
|
||||||
|
|
||||||
|
Example usage:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
local toml = net.decode("toml", [[
|
||||||
|
[package]
|
||||||
|
name = "my-cool-toml-package"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[values]
|
||||||
|
epic = true
|
||||||
|
]])
|
||||||
|
|
||||||
|
assert(toml.package.name == "my-cool-toml-package")
|
||||||
|
assert(toml.package.version == "0.1.0")
|
||||||
|
assert(toml.values.epic == true)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fixed indentation of closing curly bracket when printing tables
|
||||||
|
|
||||||
## `0.5.0` - February 23rd, 2023
|
## `0.5.0` - February 23rd, 2023
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
54
Cargo.lock
generated
54
Cargo.lock
generated
|
@ -797,6 +797,7 @@ dependencies = [
|
||||||
"serde_yaml",
|
"serde_yaml",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-tungstenite",
|
"tokio-tungstenite",
|
||||||
|
"toml",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1276,6 +1277,15 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_spanned"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_urlencoded"
|
name = "serde_urlencoded"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
|
@ -1510,6 +1520,41 @@ dependencies = [
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml"
|
||||||
|
version = "0.7.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f7afcae9e3f0fe2c370fd4657108972cbb2fa9db1b9f84849cefd80741b01cb6"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap",
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"toml_edit",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_datetime"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_edit"
|
||||||
|
version = "0.19.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a1eb0622d28f4b9c90adc4ea4b2b46b47663fde9ac5fafcb14a1369d5508825"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap",
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"winnow",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tower-service"
|
name = "tower-service"
|
||||||
version = "0.3.2"
|
version = "0.3.2"
|
||||||
|
@ -1858,6 +1903,15 @@ version = "0.42.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
|
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winnow"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "44c06e7dbfe731192c512aa707249279d720876a868eb08f21ea93eb9de1eca9"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winreg"
|
name = "winreg"
|
||||||
version = "0.10.1"
|
version = "0.10.1"
|
||||||
|
|
29
Cargo.toml
29
Cargo.toml
|
@ -2,6 +2,8 @@
|
||||||
members = ["packages/cli", "packages/lib"]
|
members = ["packages/cli", "packages/lib"]
|
||||||
default-members = ["packages/cli"]
|
default-members = ["packages/cli"]
|
||||||
|
|
||||||
|
# Package config values shared across all packages,
|
||||||
|
# such as version, license, and other metadata
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
@ -12,23 +14,32 @@ readme = "README.md"
|
||||||
keywords = ["cli", "lua", "luau", "scripts"]
|
keywords = ["cli", "lua", "luau", "scripts"]
|
||||||
categories = ["command-line-interface"]
|
categories = ["command-line-interface"]
|
||||||
|
|
||||||
|
# Shared dependencies that are used across 2 or more packages
|
||||||
|
# These are declared here to ensure consistent versioning
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
console = "0.15"
|
console = "0.15"
|
||||||
futures-util = "0.3"
|
futures-util = "0.3"
|
||||||
lazy_static = "1.4"
|
lazy_static = "1.4"
|
||||||
|
|
||||||
|
# Serde dependencies, supporting user-facing formats: json, yaml, toml
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = { version = "1.0", features = ["preserve_order"] }
|
serde_json = { version = "1.0", features = ["preserve_order"] }
|
||||||
serde_yaml = "0.9"
|
serde_yaml = "0.9"
|
||||||
|
toml = { version = "0.7", features = ["preserve_order"] }
|
||||||
|
|
||||||
|
# Tokio runtime & async clients
|
||||||
tokio = { version = "1.24", features = ["full"] }
|
tokio = { version = "1.24", features = ["full"] }
|
||||||
|
reqwest = { version = "0.11", default-features = false, features = [
|
||||||
|
"rustls-tls",
|
||||||
|
] }
|
||||||
|
|
||||||
[workspace.dependencies.reqwest]
|
# Profile for building the release binary, with the following options set:
|
||||||
version = "0.11"
|
# 1. Optimize for size
|
||||||
default-features = false
|
# 2. Automatically strip symbols from the binary
|
||||||
features = ["rustls-tls"]
|
# 3. Enable link-time optimization
|
||||||
|
# 4. Remove extra panic info
|
||||||
[profile.release]
|
[profile.release]
|
||||||
strip = true # Automatically strip symbols from the binary.
|
opt-level = "z"
|
||||||
opt-level = "z" # Optimize for size.
|
strip = true
|
||||||
lto = true # Enable link-time optimization
|
lto = true
|
||||||
panic = "abort" # Remove extra panic info
|
panic = "abort"
|
||||||
|
|
|
@ -162,6 +162,8 @@ declare fs: {
|
||||||
|
|
||||||
type NetMethod = "GET" | "POST" | "PUT" | "DELETE" | "HEAD" | "OPTIONS" | "PATCH"
|
type NetMethod = "GET" | "POST" | "PUT" | "DELETE" | "HEAD" | "OPTIONS" | "PATCH"
|
||||||
|
|
||||||
|
type NetEncodeDecodeFormat = "json" | "yaml" | "toml"
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
@type NetFetchParams
|
@type NetFetchParams
|
||||||
@within Net
|
@within Net
|
||||||
|
@ -364,6 +366,37 @@ declare net: {
|
||||||
@return The decoded lua value
|
@return The decoded lua value
|
||||||
]=]
|
]=]
|
||||||
jsonDecode: (encoded: string) -> any,
|
jsonDecode: (encoded: string) -> any,
|
||||||
|
--[=[
|
||||||
|
@within Net
|
||||||
|
@must_use
|
||||||
|
|
||||||
|
***WARNING:** Unstable API*
|
||||||
|
|
||||||
|
*This API is unstable and may change or be removed in the next major version of Lune.*
|
||||||
|
|
||||||
|
Encodes the given value using the given format.
|
||||||
|
|
||||||
|
@param format The format to use
|
||||||
|
@param value The value to encode
|
||||||
|
@param pretty If the encoded string should be human-readable, including things such as newlines and spaces. Only supported for json and toml formats, and defaults to false
|
||||||
|
@return The encoded string
|
||||||
|
]=]
|
||||||
|
encode: (format: NetEncodeDecodeFormat, value: any, pretty: boolean?) -> string,
|
||||||
|
--[=[
|
||||||
|
@within Net
|
||||||
|
@must_use
|
||||||
|
|
||||||
|
***WARNING:** Unstable API*
|
||||||
|
|
||||||
|
*This API is unstable and may change or be removed in the next major version of Lune.*
|
||||||
|
|
||||||
|
Decodes the given string using the given format into a lua value.
|
||||||
|
|
||||||
|
@param format The format to use
|
||||||
|
@param encoded The JSON string to decode
|
||||||
|
@return The decoded lua value
|
||||||
|
]=]
|
||||||
|
decode: (format: NetEncodeDecodeFormat, encoded: string) -> any,
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProcessSpawnOptionsStdio = "inherit" | "default"
|
type ProcessSpawnOptionsStdio = "inherit" | "default"
|
||||||
|
|
|
@ -21,6 +21,7 @@ lazy_static.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
serde_yaml.workspace = true
|
serde_yaml.workspace = true
|
||||||
|
toml.workspace = true
|
||||||
tokio.workspace = true
|
tokio.workspace = true
|
||||||
reqwest.workspace = true
|
reqwest.workspace = true
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,8 @@ use tokio::{sync::mpsc, task};
|
||||||
|
|
||||||
use crate::lua::{
|
use crate::lua::{
|
||||||
net::{
|
net::{
|
||||||
NetClient, NetClientBuilder, NetLocalExec, NetService, NetWebSocket, RequestConfig,
|
EncodeDecodeConfig, EncodeDecodeFormat, NetClient, NetClientBuilder, NetLocalExec,
|
||||||
ServeConfig,
|
NetService, NetWebSocket, RequestConfig, ServeConfig,
|
||||||
},
|
},
|
||||||
table::TableBuilder,
|
table::TableBuilder,
|
||||||
task::{TaskScheduler, TaskSchedulerAsyncExt},
|
task::{TaskScheduler, TaskSchedulerAsyncExt},
|
||||||
|
@ -25,6 +25,8 @@ pub fn create(lua: &'static Lua) -> LuaResult<LuaTable> {
|
||||||
lua.set_named_registry_value("net.client", client)?;
|
lua.set_named_registry_value("net.client", client)?;
|
||||||
// Create the global table for net
|
// Create the global table for net
|
||||||
TableBuilder::new(lua)?
|
TableBuilder::new(lua)?
|
||||||
|
.with_function("encode", net_encode)?
|
||||||
|
.with_function("decode", net_decode)?
|
||||||
.with_function("jsonEncode", net_json_encode)?
|
.with_function("jsonEncode", net_json_encode)?
|
||||||
.with_function("jsonDecode", net_json_decode)?
|
.with_function("jsonDecode", net_json_decode)?
|
||||||
.with_async_function("request", net_request)?
|
.with_async_function("request", net_request)?
|
||||||
|
@ -42,17 +44,32 @@ fn create_user_agent_header() -> String {
|
||||||
format!("{github_owner}-{github_repo}-cli")
|
format!("{github_owner}-{github_repo}-cli")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn net_json_encode(_: &'static Lua, (val, pretty): (LuaValue, Option<bool>)) -> LuaResult<String> {
|
fn net_encode<'a>(
|
||||||
if let Some(true) = pretty {
|
lua: &'static Lua,
|
||||||
serde_json::to_string_pretty(&val).map_err(LuaError::external)
|
(format, val, pretty): (EncodeDecodeFormat, LuaValue<'a>, Option<bool>),
|
||||||
} else {
|
) -> LuaResult<LuaString<'a>> {
|
||||||
serde_json::to_string(&val).map_err(LuaError::external)
|
let config = EncodeDecodeConfig::from((format, pretty.unwrap_or_default()));
|
||||||
}
|
config.serialize_to_string(lua, val)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn net_json_decode(lua: &'static Lua, json: String) -> LuaResult<LuaValue> {
|
fn net_decode<'a>(
|
||||||
let json: serde_json::Value = serde_json::from_str(&json).map_err(LuaError::external)?;
|
lua: &'static Lua,
|
||||||
lua.to_value(&json)
|
(format, str): (EncodeDecodeFormat, LuaString<'a>),
|
||||||
|
) -> LuaResult<LuaValue<'a>> {
|
||||||
|
let config = EncodeDecodeConfig::from(format);
|
||||||
|
config.deserialize_from_string(lua, str)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn net_json_encode<'a>(
|
||||||
|
lua: &'static Lua,
|
||||||
|
(val, pretty): (LuaValue<'a>, Option<bool>),
|
||||||
|
) -> LuaResult<LuaString<'a>> {
|
||||||
|
EncodeDecodeConfig::from((EncodeDecodeFormat::Json, pretty.unwrap_or_default()))
|
||||||
|
.serialize_to_string(lua, val)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn net_json_decode<'a>(lua: &'static Lua, json: LuaString<'a>) -> LuaResult<LuaValue<'a>> {
|
||||||
|
EncodeDecodeConfig::from(EncodeDecodeFormat::Json).deserialize_from_string(lua, json)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn net_request<'a>(lua: &'static Lua, config: RequestConfig<'a>) -> LuaResult<LuaTable<'a>> {
|
async fn net_request<'a>(lua: &'static Lua, config: RequestConfig<'a>) -> LuaResult<LuaTable<'a>> {
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
mod client;
|
mod client;
|
||||||
mod config;
|
mod config;
|
||||||
mod response;
|
mod response;
|
||||||
|
mod serde;
|
||||||
mod server;
|
mod server;
|
||||||
mod websocket;
|
mod websocket;
|
||||||
|
|
||||||
|
pub use self::serde::{EncodeDecodeConfig, EncodeDecodeFormat};
|
||||||
pub use client::{NetClient, NetClientBuilder};
|
pub use client::{NetClient, NetClientBuilder};
|
||||||
pub use config::{RequestConfig, ServeConfig};
|
pub use config::{RequestConfig, ServeConfig};
|
||||||
pub use response::{NetServeResponse, NetServeResponseKind};
|
pub use response::{NetServeResponse, NetServeResponseKind};
|
||||||
|
|
123
packages/lib/src/lua/net/serde.rs
Normal file
123
packages/lib/src/lua/net/serde.rs
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
use mlua::prelude::*;
|
||||||
|
|
||||||
|
use serde_json::Value as JsonValue;
|
||||||
|
use serde_yaml::Value as YamlValue;
|
||||||
|
use toml::Value as TomlValue;
|
||||||
|
|
||||||
|
// Serde config
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum EncodeDecodeFormat {
|
||||||
|
Json,
|
||||||
|
Yaml,
|
||||||
|
Toml,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'lua> FromLua<'lua> for EncodeDecodeFormat {
|
||||||
|
fn from_lua(value: LuaValue<'lua>, _: &'lua Lua) -> LuaResult<Self> {
|
||||||
|
if let LuaValue::String(s) = &value {
|
||||||
|
match s.to_string_lossy().to_ascii_lowercase().trim() {
|
||||||
|
"json" => Ok(Self::Json),
|
||||||
|
"yaml" => Ok(Self::Yaml),
|
||||||
|
"toml" => Ok(Self::Toml),
|
||||||
|
kind => Err(LuaError::FromLuaConversionError {
|
||||||
|
from: value.type_name(),
|
||||||
|
to: "EncodeDecodeFormat",
|
||||||
|
message: Some(format!(
|
||||||
|
"Invalid format '{kind}', valid formats are: json, yaml, toml"
|
||||||
|
)),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(LuaError::FromLuaConversionError {
|
||||||
|
from: value.type_name(),
|
||||||
|
to: "EncodeDecodeFormat",
|
||||||
|
message: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct EncodeDecodeConfig {
|
||||||
|
pub format: EncodeDecodeFormat,
|
||||||
|
pub pretty: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EncodeDecodeConfig {
|
||||||
|
pub fn serialize_to_string<'lua>(
|
||||||
|
self,
|
||||||
|
lua: &'lua Lua,
|
||||||
|
value: LuaValue<'lua>,
|
||||||
|
) -> LuaResult<LuaString<'lua>> {
|
||||||
|
let bytes = match self.format {
|
||||||
|
EncodeDecodeFormat::Json => {
|
||||||
|
if self.pretty {
|
||||||
|
serde_json::to_vec_pretty(&value).map_err(LuaError::external)?
|
||||||
|
} else {
|
||||||
|
serde_json::to_vec(&value).map_err(LuaError::external)?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EncodeDecodeFormat::Yaml => {
|
||||||
|
let mut writer = Vec::with_capacity(128);
|
||||||
|
serde_yaml::to_writer(&mut writer, &value).map_err(LuaError::external)?;
|
||||||
|
writer
|
||||||
|
}
|
||||||
|
EncodeDecodeFormat::Toml => {
|
||||||
|
let s = if self.pretty {
|
||||||
|
toml::to_string_pretty(&value).map_err(LuaError::external)?
|
||||||
|
} else {
|
||||||
|
toml::to_string(&value).map_err(LuaError::external)?
|
||||||
|
};
|
||||||
|
s.as_bytes().to_vec()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
lua.create_string(&bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deserialize_from_string<'lua>(
|
||||||
|
self,
|
||||||
|
lua: &'lua Lua,
|
||||||
|
string: LuaString<'lua>,
|
||||||
|
) -> LuaResult<LuaValue<'lua>> {
|
||||||
|
let bytes = string.as_bytes();
|
||||||
|
match self.format {
|
||||||
|
EncodeDecodeFormat::Json => {
|
||||||
|
let value: JsonValue = serde_json::from_slice(bytes).map_err(LuaError::external)?;
|
||||||
|
lua.to_value(&value)
|
||||||
|
}
|
||||||
|
EncodeDecodeFormat::Yaml => {
|
||||||
|
let value: YamlValue = serde_yaml::from_slice(bytes).map_err(LuaError::external)?;
|
||||||
|
lua.to_value(&value)
|
||||||
|
}
|
||||||
|
EncodeDecodeFormat::Toml => {
|
||||||
|
if let Ok(s) = string.to_str() {
|
||||||
|
let value: TomlValue = toml::from_str(s).map_err(LuaError::external)?;
|
||||||
|
lua.to_value(&value)
|
||||||
|
} else {
|
||||||
|
Err(LuaError::RuntimeError(
|
||||||
|
"TOML must be valid utf-8".to_string(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<EncodeDecodeFormat> for EncodeDecodeConfig {
|
||||||
|
fn from(format: EncodeDecodeFormat) -> Self {
|
||||||
|
Self {
|
||||||
|
format,
|
||||||
|
pretty: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<(EncodeDecodeFormat, bool)> for EncodeDecodeConfig {
|
||||||
|
fn from(value: (EncodeDecodeFormat, bool)) -> Self {
|
||||||
|
Self {
|
||||||
|
format: value.0,
|
||||||
|
pretty: value.1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -156,7 +156,7 @@ pub fn pretty_format_value(
|
||||||
if is_empty {
|
if is_empty {
|
||||||
write!(buffer, "{}", STYLE_DIM.apply_to(" }"))?;
|
write!(buffer, "{}", STYLE_DIM.apply_to(" }"))?;
|
||||||
} else {
|
} else {
|
||||||
write!(buffer, "\n{}", STYLE_DIM.apply_to("}"))?;
|
write!(buffer, "\n{depth_indent}{}", STYLE_DIM.apply_to("}"))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue