mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-04-21 08:11:24 +02:00
Improve plugin source modeling and runtime dedup (#414)
This commit is contained in:
4
crates/yaak-models/bindings/gen_models.ts
generated
4
crates/yaak-models/bindings/gen_models.ts
generated
@@ -67,7 +67,9 @@ export type ParentAuthentication = { authentication: Record<string, any>, authen
|
||||
|
||||
export type ParentHeaders = { headers: Array<HttpRequestHeader>, };
|
||||
|
||||
export type Plugin = { model: "plugin", id: string, createdAt: string, updatedAt: string, checkedAt: string | null, directory: string, enabled: boolean, url: string | null, };
|
||||
export type Plugin = { model: "plugin", id: string, createdAt: string, updatedAt: string, checkedAt: string | null, directory: string, enabled: boolean, url: string | null, source: PluginSource, };
|
||||
|
||||
export type PluginSource = "bundled" | "filesystem" | "registry";
|
||||
|
||||
export type PluginKeyValue = { model: "plugin_key_value", createdAt: string, updatedAt: string, pluginName: string, key: string, value: string, };
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
ALTER TABLE plugins
|
||||
ADD COLUMN source TEXT DEFAULT 'filesystem' NOT NULL;
|
||||
|
||||
-- Existing registry installs have a URL; classify them first.
|
||||
UPDATE plugins
|
||||
SET source = 'registry'
|
||||
WHERE url IS NOT NULL;
|
||||
|
||||
-- Best-effort bundled backfill for legacy rows.
|
||||
UPDATE plugins
|
||||
SET source = 'bundled'
|
||||
WHERE source = 'filesystem'
|
||||
AND (
|
||||
-- Normalize separators so this also works for Windows paths.
|
||||
replace(directory, '\', '/') LIKE '%/vendored/plugins/%'
|
||||
OR replace(directory, '\', '/') LIKE '%/vendored-plugins/%'
|
||||
);
|
||||
|
||||
-- Keep one row per exact directory before adding uniqueness.
|
||||
-- Tie-break by recency.
|
||||
WITH ranked AS (SELECT id,
|
||||
ROW_NUMBER() OVER (
|
||||
PARTITION BY directory
|
||||
ORDER BY updated_at DESC,
|
||||
created_at DESC
|
||||
) AS row_num
|
||||
FROM plugins)
|
||||
DELETE
|
||||
FROM plugins
|
||||
WHERE id IN (SELECT id FROM ranked WHERE row_num > 1);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_plugins_directory_unique
|
||||
ON plugins (directory);
|
||||
@@ -2074,6 +2074,46 @@ pub struct Plugin {
|
||||
pub directory: String,
|
||||
pub enabled: bool,
|
||||
pub url: Option<String>,
|
||||
pub source: PluginSource,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[ts(export, export_to = "gen_models.ts")]
|
||||
pub enum PluginSource {
|
||||
Bundled,
|
||||
Filesystem,
|
||||
Registry,
|
||||
}
|
||||
|
||||
impl FromStr for PluginSource {
|
||||
type Err = crate::error::Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self> {
|
||||
match s {
|
||||
"bundled" => Ok(Self::Bundled),
|
||||
"filesystem" => Ok(Self::Filesystem),
|
||||
"registry" => Ok(Self::Registry),
|
||||
_ => Ok(Self::default()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for PluginSource {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let str = match self {
|
||||
PluginSource::Bundled => "bundled".to_string(),
|
||||
PluginSource::Filesystem => "filesystem".to_string(),
|
||||
PluginSource::Registry => "registry".to_string(),
|
||||
};
|
||||
write!(f, "{}", str)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for PluginSource {
|
||||
fn default() -> Self {
|
||||
Self::Filesystem
|
||||
}
|
||||
}
|
||||
|
||||
impl UpsertModelInfo for Plugin {
|
||||
@@ -2109,6 +2149,7 @@ impl UpsertModelInfo for Plugin {
|
||||
(Directory, self.directory.into()),
|
||||
(Url, self.url.into()),
|
||||
(Enabled, self.enabled.into()),
|
||||
(Source, self.source.to_string().into()),
|
||||
])
|
||||
}
|
||||
|
||||
@@ -2119,6 +2160,7 @@ impl UpsertModelInfo for Plugin {
|
||||
PluginIden::Directory,
|
||||
PluginIden::Url,
|
||||
PluginIden::Enabled,
|
||||
PluginIden::Source,
|
||||
]
|
||||
}
|
||||
|
||||
@@ -2135,6 +2177,7 @@ impl UpsertModelInfo for Plugin {
|
||||
url: row.get("url")?,
|
||||
directory: row.get("directory")?,
|
||||
enabled: row.get("enabled")?,
|
||||
source: PluginSource::from_str(row.get::<_, String>("source")?.as_str()).unwrap(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,10 @@ impl<'a> DbContext<'a> {
|
||||
}
|
||||
|
||||
pub fn upsert_plugin(&self, plugin: &Plugin, source: &UpdateSource) -> Result<Plugin> {
|
||||
self.upsert(plugin, source)
|
||||
let mut plugin_to_upsert = plugin.clone();
|
||||
if let Some(existing) = self.get_plugin_by_directory(&plugin.directory) {
|
||||
plugin_to_upsert.id = existing.id;
|
||||
}
|
||||
self.upsert(&plugin_to_upsert, source)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user