diff --git a/migrations/postgres/20260502000001_migrate_legacy_scripts.sql b/migrations/postgres/20260502000001_migrate_legacy_scripts.sql new file mode 100644 index 0000000..451cf84 --- /dev/null +++ b/migrations/postgres/20260502000001_migrate_legacy_scripts.sql @@ -0,0 +1,26 @@ +-- Migrate legacy index_hook and script columns into the trigger-keyed +-- scripts table, then drop the old columns. + +-- 1. index_hook -> record.index: +INSERT INTO scripts (id, body, script_type, created_at, updated_at) +SELECT 'record.index:' || id, index_hook, 'lua', NOW(), NOW() + FROM lexicons + WHERE index_hook IS NOT NULL +ON CONFLICT (id) DO NOTHING; + +-- 2. script -> xrpc.query: or xrpc.procedure: +INSERT INTO scripts (id, body, script_type, created_at, updated_at) +SELECT 'xrpc.' || + CASE (lexicon_json::jsonb)->'defs'->'main'->>'type' + WHEN 'query' THEN 'query' + WHEN 'procedure' THEN 'procedure' + END || ':' || id, + script, 'lua', NOW(), NOW() + FROM lexicons + WHERE script IS NOT NULL + AND (lexicon_json::jsonb)->'defs'->'main'->>'type' IN ('query', 'procedure') +ON CONFLICT (id) DO NOTHING; + +-- 3. Drop legacy columns. +ALTER TABLE lexicons DROP COLUMN index_hook; +ALTER TABLE lexicons DROP COLUMN script; diff --git a/migrations/sqlite/20260502000001_migrate_legacy_scripts.sql b/migrations/sqlite/20260502000001_migrate_legacy_scripts.sql new file mode 100644 index 0000000..5baf81b --- /dev/null +++ b/migrations/sqlite/20260502000001_migrate_legacy_scripts.sql @@ -0,0 +1,26 @@ +-- Migrate legacy index_hook and script columns into the trigger-keyed +-- scripts table, then drop the old columns. + +-- 1. index_hook -> record.index: +INSERT INTO scripts (id, body, script_type, created_at, updated_at) +SELECT 'record.index:' || id, index_hook, 'lua', datetime('now'), datetime('now') + FROM lexicons + WHERE index_hook IS NOT NULL +ON CONFLICT (id) DO NOTHING; + +-- 2. script -> xrpc.query: or xrpc.procedure: +INSERT INTO scripts (id, body, script_type, created_at, updated_at) +SELECT 'xrpc.' || + CASE json_extract(lexicon_json, '$.defs.main.type') + WHEN 'query' THEN 'query' + WHEN 'procedure' THEN 'procedure' + END || ':' || id, + script, 'lua', datetime('now'), datetime('now') + FROM lexicons + WHERE script IS NOT NULL + AND json_extract(lexicon_json, '$.defs.main.type') IN ('query', 'procedure') +ON CONFLICT (id) DO NOTHING; + +-- 3. Drop legacy columns. +ALTER TABLE lexicons DROP COLUMN index_hook; +ALTER TABLE lexicons DROP COLUMN script; diff --git a/src/admin/lexicons.rs b/src/admin/lexicons.rs index f238fe0..b4f93c2 100644 --- a/src/admin/lexicons.rs +++ b/src/admin/lexicons.rs @@ -60,39 +60,24 @@ pub(super) async fn upload_lexicon( 1, body.target_collection.clone(), action.clone(), - body.script.clone(), - body.index_hook.clone(), body.token_cost.map(|c| c as u32), ) .map_err(|e| AppError::BadRequest(format!("failed to parse lexicon: {e}")))?; - // Validate script if provided - if let Some(ref script) = body.script { - crate::lua::validate_script(script).map_err(AppError::BadRequest)?; - } - - // Validate index_hook if provided - if let Some(ref script) = body.index_hook { - crate::lua::validate_script(script).map_err(AppError::BadRequest)?; - } - let action_str = action.to_optional_str(); - let has_script = body.script.is_some(); let lexicon_json_str = serde_json::to_string(&body.lexicon_json).unwrap_or_default(); let now = now_rfc3339(); // Upsert into database let sql = adapt_sql( r#" - INSERT INTO lexicons (id, lexicon_json, backfill, target_collection, action, script, index_hook, token_cost, source, created_at) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'manual', ?) + INSERT INTO lexicons (id, lexicon_json, backfill, target_collection, action, token_cost, source, created_at) + VALUES (?, ?, ?, ?, ?, ?, 'manual', ?) ON CONFLICT (id) DO UPDATE SET lexicon_json = EXCLUDED.lexicon_json, backfill = EXCLUDED.backfill, target_collection = EXCLUDED.target_collection, action = EXCLUDED.action, - script = EXCLUDED.script, - index_hook = EXCLUDED.index_hook, token_cost = EXCLUDED.token_cost, source = 'manual', revision = lexicons.revision + 1, @@ -107,8 +92,6 @@ pub(super) async fn upload_lexicon( .bind(if body.backfill { 1_i32 } else { 0_i32 }) .bind(&body.target_collection) .bind(action_str) - .bind(&body.script) - .bind(&body.index_hook) .bind(body.token_cost) .bind(&now) .bind(&now) @@ -124,8 +107,6 @@ pub(super) async fn upload_lexicon( revision, body.target_collection, action, - body.script, - body.index_hook.clone(), body.token_cost.map(|c| c as u32), ) .map_err(|e| AppError::Internal(format!("failed to re-parse lexicon: {e}")))?; @@ -156,8 +137,6 @@ pub(super) async fn upload_lexicon( subject: Some(id.clone()), detail: serde_json::json!({ "revision": revision, - "has_script": has_script, - "has_index_hook": body.index_hook.is_some(), "source": "manual", }), }, @@ -182,7 +161,7 @@ pub(super) async fn list_lexicons( auth.require(Permission::LexiconsRead).await?; let backend = state.db_backend; let sql = adapt_sql( - "SELECT id, revision, lexicon_json, backfill, action, target_collection, script, index_hook, source, authority_did, last_fetched_at, created_at, updated_at, token_cost FROM lexicons ORDER BY id", + "SELECT id, revision, lexicon_json, backfill, action, target_collection, source, authority_did, last_fetched_at, created_at, updated_at, token_cost FROM lexicons ORDER BY id", backend, ); #[allow(clippy::type_complexity)] @@ -193,8 +172,6 @@ pub(super) async fn list_lexicons( i32, Option, Option, - Option, - Option, String, Option, Option, @@ -216,8 +193,6 @@ pub(super) async fn list_lexicons( backfill, action, target_collection, - script, - index_hook, source, authority_did, last_fetched_at, @@ -226,15 +201,8 @@ pub(super) async fn list_lexicons( token_cost, )| { let json: Value = serde_json::from_str(&json_str).unwrap_or_default(); - let parsed = ParsedLexicon::parse( - json, - revision, - None, - ProcedureAction::Upsert, - None, - None, - None, - ); + let parsed = + ParsedLexicon::parse(json, revision, None, ProcedureAction::Upsert, None); let lexicon_type = parsed .as_ref() .map(|p| format!("{:?}", p.lexicon_type).to_lowercase()) @@ -251,8 +219,6 @@ pub(super) async fn list_lexicons( backfill: backfill != 0, action, target_collection, - has_script: script.is_some(), - has_index_hook: index_hook.is_some(), source, authority_did, last_fetched_at, @@ -277,7 +243,7 @@ pub(super) async fn get_lexicon( auth.require(Permission::LexiconsRead).await?; let backend = state.db_backend; let sql = adapt_sql( - "SELECT id, revision, lexicon_json, backfill, action, target_collection, script, index_hook, source, authority_did, last_fetched_at, created_at, updated_at, token_cost FROM lexicons WHERE id = ?", + "SELECT id, revision, lexicon_json, backfill, action, target_collection, source, authority_did, last_fetched_at, created_at, updated_at, token_cost FROM lexicons WHERE id = ?", backend, ); #[allow(clippy::type_complexity)] @@ -288,8 +254,6 @@ pub(super) async fn get_lexicon( i32, Option, Option, - Option, - Option, String, Option, Option, @@ -309,8 +273,6 @@ pub(super) async fn get_lexicon( backfill, action, target_collection, - script, - index_hook, source, authority_did, last_fetched_at, @@ -327,14 +289,10 @@ pub(super) async fn get_lexicon( None, ProcedureAction::Upsert, None, - None, - None, ) .map(|p| format!("{:?}", p.lexicon_type).to_lowercase()) .unwrap_or_else(|_| "unknown".into()); - let has_script = script.is_some(); - Ok(Json(serde_json::json!({ "id": id, "revision": revision, @@ -343,10 +301,6 @@ pub(super) async fn get_lexicon( "backfill": backfill != 0, "action": action, "target_collection": target_collection, - "has_script": has_script, - "script": script, - "has_index_hook": index_hook.is_some(), - "index_hook": index_hook, "source": source, "authority_did": authority_did, "last_fetched_at": last_fetched_at, diff --git a/src/admin/network_lexicons.rs b/src/admin/network_lexicons.rs index a0b7fb8..b68f5fe 100644 --- a/src/admin/network_lexicons.rs +++ b/src/admin/network_lexicons.rs @@ -72,8 +72,6 @@ pub(super) async fn add( body.target_collection.clone(), ProcedureAction::Upsert, None, - None, - None, ) .map_err(|e| AppError::BadRequest(format!("failed to parse lexicon: {e}")))?; @@ -121,8 +119,6 @@ pub(super) async fn add( body.target_collection, ProcedureAction::Upsert, None, - None, - None, ) .map_err(|e| AppError::Internal(format!("failed to re-parse lexicon: {e}")))?; state.lexicons.upsert(parsed).await; diff --git a/src/admin/types.rs b/src/admin/types.rs index 2e903a8..26b15ae 100644 --- a/src/admin/types.rs +++ b/src/admin/types.rs @@ -13,8 +13,6 @@ pub(super) struct LexiconSummary { pub(super) backfill: bool, pub(super) action: Option, pub(super) target_collection: Option, - pub(super) has_script: bool, - pub(super) has_index_hook: bool, pub(super) source: String, pub(super) authority_did: Option, pub(super) last_fetched_at: Option, @@ -33,8 +31,6 @@ pub(super) struct UploadLexiconBody { pub(super) backfill: bool, pub(super) target_collection: Option, pub(super) action: Option, - pub(super) script: Option, - pub(super) index_hook: Option, pub(super) token_cost: Option, } diff --git a/src/lexicon.rs b/src/lexicon.rs index f39823b..05b4491 100644 --- a/src/lexicon.rs +++ b/src/lexicon.rs @@ -79,10 +79,6 @@ pub struct ParsedLexicon { pub target_collection: Option, /// For procedures: the action this procedure performs (create, update, delete, upsert). pub action: ProcedureAction, - /// Optional Lua script that replaces the built-in handler. - pub script: Option, - /// Optional Lua script that runs when a record in this collection is indexed. - pub index_hook: Option, /// Optional per-NSID token cost for rate limiting. pub token_cost: Option, /// Optional space type NSID indicating this lexicon is designed for use within spaces of that type. @@ -96,8 +92,6 @@ impl ParsedLexicon { revision: i32, target_collection: Option, action: ProcedureAction, - script: Option, - index_hook: Option, token_cost: Option, ) -> Result { let id = raw @@ -146,8 +140,6 @@ impl ParsedLexicon { revision, target_collection, action, - script, - index_hook, token_cost, space_type, }) @@ -182,11 +174,9 @@ impl LexiconRegistry { i32, Option, Option, - Option, - Option, Option, )> = sqlx::query_as( - "SELECT id, lexicon_json, revision, target_collection, action, script, index_hook, token_cost FROM lexicons", + "SELECT id, lexicon_json, revision, target_collection, action, token_cost FROM lexicons", ) .fetch_all(db) .await @@ -196,17 +186,7 @@ impl LexiconRegistry { inner.clear(); let mut loaded = 0u32; - for ( - id, - json_str, - revision, - target_collection, - action_str, - script, - index_hook, - token_cost, - ) in rows - { + for (id, json_str, revision, target_collection, action_str, token_cost) in rows { let json: Value = match serde_json::from_str(&json_str) { Ok(v) => v, Err(e) => { @@ -226,8 +206,6 @@ impl LexiconRegistry { revision, target_collection, action, - script, - index_hook, token_cost.map(|c| c as u32), ) { Ok(parsed) => { @@ -292,12 +270,6 @@ impl LexiconRegistry { .collect() } - /// Get the index_hook for a record-type lexicon by its collection NSID. - pub async fn get_index_hook(&self, collection: &str) -> Option { - let inner = self.inner.read().await; - inner.get(collection).and_then(|lex| lex.index_hook.clone()) - } - /// Return the total count of registered lexicons. pub async fn count(&self) -> usize { let inner = self.inner.read().await; @@ -393,8 +365,6 @@ mod tests { None, ProcedureAction::Upsert, None, - None, - None, ) .unwrap(); assert_eq!(parsed.id, "games.gamesgamesgamesgames.game"); @@ -413,8 +383,6 @@ mod tests { Some("games.gamesgamesgamesgames.game".into()), ProcedureAction::Upsert, None, - None, - None, ) .unwrap(); assert_eq!(parsed.lexicon_type, LexiconType::Query); @@ -435,8 +403,6 @@ mod tests { None, ProcedureAction::Upsert, None, - None, - None, ) .unwrap(); assert_eq!(parsed.lexicon_type, LexiconType::Procedure); @@ -452,8 +418,6 @@ mod tests { None, ProcedureAction::Delete, None, - None, - None, ) .unwrap(); assert_eq!(parsed.action, ProcedureAction::Delete); @@ -467,8 +431,6 @@ mod tests { None, ProcedureAction::Upsert, None, - None, - None, ) .unwrap(); assert_eq!(parsed.lexicon_type, LexiconType::Definitions); @@ -477,7 +439,7 @@ mod tests { #[test] fn parse_missing_id_returns_error() { let raw = json!({"lexicon": 1, "defs": {}}); - let result = ParsedLexicon::parse(raw, 1, None, ProcedureAction::Upsert, None, None, None); + let result = ParsedLexicon::parse(raw, 1, None, ProcedureAction::Upsert, None); assert!(result.is_err()); assert!(result.unwrap_err().contains("id")); } @@ -485,16 +447,8 @@ mod tests { #[test] fn parse_preserves_raw_json() { let raw = record_lexicon_json(); - let parsed = ParsedLexicon::parse( - raw.clone(), - 1, - None, - ProcedureAction::Upsert, - None, - None, - None, - ) - .unwrap(); + let parsed = + ParsedLexicon::parse(raw.clone(), 1, None, ProcedureAction::Upsert, None).unwrap(); assert_eq!(parsed.raw, raw); } @@ -506,8 +460,6 @@ mod tests { Some("custom.collection".into()), ProcedureAction::Upsert, None, - None, - None, ) .unwrap(); assert_eq!(parsed.target_collection, Some("custom.collection".into())); @@ -532,8 +484,6 @@ mod tests { None, ProcedureAction::Upsert, None, - None, - None, ) .unwrap(); reg.upsert(parsed).await; @@ -552,8 +502,6 @@ mod tests { None, ProcedureAction::Upsert, None, - None, - None, ) .unwrap(); reg.upsert(v1).await; @@ -564,8 +512,6 @@ mod tests { None, ProcedureAction::Upsert, None, - None, - None, ) .unwrap(); reg.upsert(v2).await; @@ -589,8 +535,6 @@ mod tests { None, ProcedureAction::Upsert, None, - None, - None, ) .unwrap(); reg.upsert(parsed).await; @@ -621,28 +565,17 @@ mod tests { None, ProcedureAction::Upsert, None, - None, - None, - ) - .unwrap(); - let query = ParsedLexicon::parse( - query_lexicon_json(), - 1, - None, - ProcedureAction::Upsert, - None, - None, - None, ) .unwrap(); + let query = + ParsedLexicon::parse(query_lexicon_json(), 1, None, ProcedureAction::Upsert, None) + .unwrap(); let procedure = ParsedLexicon::parse( procedure_lexicon_json(), 1, None, ProcedureAction::Upsert, None, - None, - None, ) .unwrap(); let defs = ParsedLexicon::parse( @@ -651,8 +584,6 @@ mod tests { None, ProcedureAction::Upsert, None, - None, - None, ) .unwrap(); @@ -723,85 +654,6 @@ mod tests { assert_eq!(ProcedureAction::Upsert.to_optional_str(), None); } - // ----------------------------------------------------------------------- - // index_hook - // ----------------------------------------------------------------------- - - #[test] - fn parse_preserves_index_hook() { - let parsed = ParsedLexicon::parse( - record_lexicon_json(), - 1, - None, - ProcedureAction::Upsert, - None, - Some("function handle() end".into()), - None, - ) - .unwrap(); - assert_eq!(parsed.index_hook, Some("function handle() end".into())); - } - - #[test] - fn parse_index_hook_none_by_default() { - let parsed = ParsedLexicon::parse( - record_lexicon_json(), - 1, - None, - ProcedureAction::Upsert, - None, - None, - None, - ) - .unwrap(); - assert!(parsed.index_hook.is_none()); - } - - #[tokio::test] - async fn registry_get_index_hook_returns_script() { - let reg = LexiconRegistry::new(); - let parsed = ParsedLexicon::parse( - record_lexicon_json(), - 1, - None, - ProcedureAction::Upsert, - None, - Some("function handle() log('hook') end".into()), - None, - ) - .unwrap(); - reg.upsert(parsed).await; - - let script = reg.get_index_hook("games.gamesgamesgamesgames.game").await; - assert_eq!(script, Some("function handle() log('hook') end".into())); - } - - #[tokio::test] - async fn registry_get_index_hook_returns_none_when_absent() { - let reg = LexiconRegistry::new(); - let parsed = ParsedLexicon::parse( - record_lexicon_json(), - 1, - None, - ProcedureAction::Upsert, - None, - None, - None, - ) - .unwrap(); - reg.upsert(parsed).await; - - let script = reg.get_index_hook("games.gamesgamesgamesgames.game").await; - assert!(script.is_none()); - } - - #[tokio::test] - async fn registry_get_index_hook_returns_none_for_unknown() { - let reg = LexiconRegistry::new(); - let script = reg.get_index_hook("nonexistent").await; - assert!(script.is_none()); - } - #[test] fn parse_space_type_from_lexicon() { let raw = json!({ @@ -821,8 +673,7 @@ mod tests { } } }); - let parsed = - ParsedLexicon::parse(raw, 1, None, ProcedureAction::Upsert, None, None, None).unwrap(); + let parsed = ParsedLexicon::parse(raw, 1, None, ProcedureAction::Upsert, None).unwrap(); assert_eq!(parsed.space_type.as_deref(), Some("com.example.forum")); } @@ -834,8 +685,6 @@ mod tests { None, ProcedureAction::Upsert, None, - None, - None, ) .unwrap(); assert!(parsed.space_type.is_none()); diff --git a/src/lua/scripts.rs b/src/lua/scripts.rs index b7ebbaf..40e8324 100644 --- a/src/lua/scripts.rs +++ b/src/lua/scripts.rs @@ -415,8 +415,7 @@ pub async fn run_record_event_once( register_default_apis(&lua, &state_arc, &script.id, Some(payload.did))?; // Legacy globals (action, uri, did, collection, rkey, record) for - // back-compat with scripts written against the old `index_hook` - // surface. + // convenience / backwards compatibility. context::set_hook_context( &lua, payload.action, diff --git a/src/lua/xrpc_api.rs b/src/lua/xrpc_api.rs index 11a8f23..a30b366 100644 --- a/src/lua/xrpc_api.rs +++ b/src/lua/xrpc_api.rs @@ -336,7 +336,7 @@ mod tests { .unwrap(); } - fn make_query_lexicon(id: &str, script: Option<&str>) -> ParsedLexicon { + fn make_query_lexicon(id: &str) -> ParsedLexicon { ParsedLexicon { id: id.to_string(), lexicon_type: LexiconType::Query, @@ -349,14 +349,12 @@ mod tests { revision: 1, target_collection: None, action: ProcedureAction::Create, - script: script.map(|s| s.to_string()), - index_hook: None, token_cost: None, space_type: None, } } - fn make_procedure_lexicon(id: &str, script: Option<&str>) -> ParsedLexicon { + fn make_procedure_lexicon(id: &str) -> ParsedLexicon { ParsedLexicon { id: id.to_string(), lexicon_type: LexiconType::Procedure, @@ -369,8 +367,6 @@ mod tests { revision: 1, target_collection: None, action: ProcedureAction::Create, - script: script.map(|s| s.to_string()), - index_hook: None, token_cost: None, space_type: None, } @@ -463,7 +459,7 @@ mod tests { let state = test_state(); // Register a scripted query that returns a static response - let lexicon = make_query_lexicon("test.echo", None); + let lexicon = make_query_lexicon("test.echo"); state.lexicons.upsert(lexicon).await; seed_script( &state, @@ -488,7 +484,7 @@ mod tests { async fn query_local_script_receives_params() { let state = test_state(); - let lexicon = make_query_lexicon("test.greet", None); + let lexicon = make_query_lexicon("test.greet"); state.lexicons.upsert(lexicon).await; seed_script( &state, @@ -517,7 +513,7 @@ mod tests { async fn query_local_script_receives_caller_did() { let state = test_state(); - let lexicon = make_query_lexicon("test.whoami", None); + let lexicon = make_query_lexicon("test.whoami"); state.lexicons.upsert(lexicon).await; seed_script( &state, @@ -562,7 +558,7 @@ mod tests { async fn query_rejects_procedure_lexicon() { let state = test_state(); - let lexicon = make_procedure_lexicon("test.create", None); + let lexicon = make_procedure_lexicon("test.create"); state.lexicons.upsert(lexicon).await; let mut params = HashMap::new(); @@ -576,7 +572,7 @@ mod tests { async fn procedure_rejects_query_lexicon() { let state = test_state(); - let lexicon = make_query_lexicon("test.echo", Some("function handle() end")); + let lexicon = make_query_lexicon("test.echo"); state.lexicons.upsert(lexicon).await; let claims = Claims::internal("did:plc:test".into()); @@ -597,7 +593,7 @@ mod tests { let state = test_state(); // Register a simple query that the outer script will call - let inner_lexicon = make_query_lexicon("test.inner", None); + let inner_lexicon = make_query_lexicon("test.inner"); state.lexicons.upsert(inner_lexicon).await; seed_script( &state, diff --git a/src/main.rs b/src/main.rs index aae42b4..e5da6e1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -138,8 +138,6 @@ async fn main() { target_collection.clone(), ProcedureAction::Upsert, None, - None, - None, ) { Ok(parsed) => { let now = db::now_rfc3339(); diff --git a/src/oauth/client_auth.rs b/src/oauth/client_auth.rs index 9be1f22..2f6e651 100644 --- a/src/oauth/client_auth.rs +++ b/src/oauth/client_auth.rs @@ -375,8 +375,6 @@ mod tests { None, crate::lexicon::ProcedureAction::Upsert, None, - None, - None, ) .unwrap(); reg.upsert(parsed).await; @@ -435,8 +433,6 @@ mod tests { None, crate::lexicon::ProcedureAction::Upsert, None, - None, - None, ) .unwrap(); reg.upsert(parsed).await; @@ -487,8 +483,6 @@ mod tests { None, crate::lexicon::ProcedureAction::Upsert, None, - None, - None, ) .unwrap(); reg.upsert(parsed).await; diff --git a/src/record_handler.rs b/src/record_handler.rs index c35dd27..6837a70 100644 --- a/src/record_handler.rs +++ b/src/record_handler.rs @@ -303,8 +303,6 @@ pub async fn handle_lexicon_schema_event(state: &AppState, did: &str, record: &R target_collection.clone(), ProcedureAction::Upsert, None, - None, - None, ) { Ok(p) => p, Err(e) => { diff --git a/src/xrpc/procedure.rs b/src/xrpc/procedure.rs index a652dd7..b619218 100644 --- a/src/xrpc/procedure.rs +++ b/src/xrpc/procedure.rs @@ -19,8 +19,7 @@ pub(crate) async fn handle_procedure( lexicon: &crate::lexicon::ParsedLexicon, ) -> Result { // Trigger-keyed dispatch: a script bound at `xrpc.procedure:` - // overrides the default PDS-write flow. The legacy `lexicon.script` - // column is no longer read. + // overrides the default PDS-write flow. let trigger = format!("xrpc.procedure:{}", lexicon.id); if let Some(resolved) = crate::lua::resolve(state, &trigger).await { // Delegation guard preserved from origin/dev: scripts that run diff --git a/src/xrpc/query.rs b/src/xrpc/query.rs index 14bd9ad..23bbf6a 100644 --- a/src/xrpc/query.rs +++ b/src/xrpc/query.rs @@ -16,8 +16,7 @@ pub(crate) async fn handle_query( claims: Option<&Claims>, ) -> Result { // Trigger-keyed dispatch: a script bound at `xrpc.query:` - // overrides the default list / get-record flow. The legacy - // `lexicon.script` column is no longer read. + // overrides the default list / get-record flow. let trigger = format!("xrpc.query:{}", lexicon.id); if let Some(resolved) = crate::lua::resolve(state, &trigger).await { return crate::lua::execute_query_script( diff --git a/web/src/app/dashboard/lexicons/[id]/lexicon-detail.tsx b/web/src/app/dashboard/lexicons/[id]/lexicon-detail.tsx index bb20a21..53e27a3 100644 --- a/web/src/app/dashboard/lexicons/[id]/lexicon-detail.tsx +++ b/web/src/app/dashboard/lexicons/[id]/lexicon-detail.tsx @@ -44,11 +44,6 @@ export default function LexiconDetailPage() { const [deleting, setDeleting] = useState(false); const [saving, setSaving] = useState(false); - // Editable text state. The lexicon page used to edit `script` and - // `index_hook` columns inline via lua editors; those columns are - // now managed via the Scripts subsystem (see "Scripts targeting - // this lexicon" panel below). We pass the existing values through - // unchanged on save so legacy data isn't accidentally NULLed. const [jsonText, setJsonText] = useState(""); const [originalJson, setOriginalJson] = useState(""); const [tokenCost, setTokenCost] = useState(""); @@ -89,11 +84,6 @@ export default function LexiconDetailPage() { await uploadLexicon({ lexicon_json: lexiconJson, backfill: lexicon.backfill, - // Preserve any legacy script / index_hook values verbatim — we - // no longer edit them here, but leaving them out of the body - // would NULL the columns on upsert and lose data. - script: lexicon.script ?? undefined, - index_hook: lexicon.index_hook ?? undefined, token_cost: tokenCost ? Number(tokenCost) : null, }); load(); @@ -262,9 +252,7 @@ export default function LexiconDetailPage() { {/* JSON editor only — scripts (record-event handlers, XRPC handlers, label-arrival handlers) are managed via the - "Scripts targeting this lexicon" panel above. The legacy - `script` / `index_hook` columns on the lexicons table are - preserved as-is on save but no longer edited here. */} + "Scripts targeting this lexicon" panel above. */} { - if (scriptManuallyEdited.current) return; - if (localMainType === "procedure") { - setScript(procedureScript(localTargetCollection)); - } else if (localMainType === "query") { - setScript(queryScript(localTargetCollection)); - } - }, [localMainType, localTargetCollection]); - - function handleScriptChange(value: string) { - scriptManuallyEdited.current = true; - setScript(value); - } - - // Reset manual-edit flag when type changes const prevType = useRef(localMainType); useEffect(() => { if (prevType.current !== localMainType) { - scriptManuallyEdited.current = false; prevType.current = localMainType; } }, [localMainType]); @@ -139,7 +115,6 @@ export default function AddLexiconPage() { await uploadLexicon({ lexicon_json: lexiconJson, backfill: localMainType === "record" && backfill, - script: showScript && script ? script : undefined, }); router.push("/dashboard/lexicons"); } catch (e: unknown) { @@ -211,10 +186,6 @@ export default function AddLexiconPage() { className="flex-1 min-h-0" jsonValue={json} onJsonChange={setJson} - luaValue={showScript ? script : undefined} - onLuaChange={showScript ? handleScriptChange : undefined} - luaCompletions={showScript ? luaCompletions : undefined} - collections={showScript ? collections : undefined} /> diff --git a/web/src/app/dashboard/lexicons/page.tsx b/web/src/app/dashboard/lexicons/page.tsx index 6494384..ae2a352 100644 --- a/web/src/app/dashboard/lexicons/page.tsx +++ b/web/src/app/dashboard/lexicons/page.tsx @@ -149,20 +149,6 @@ export default function LexiconsPage() { cell: ({ row }) => row.original.action ?? "--", enableSorting: true, }, - { - id: "has_script", - accessorKey: "has_script", - header: ({ column }) => ( - - ), - cell: ({ row }) => - row.original.has_script ? ( - Lua - ) : ( - "--" - ), - enableSorting: true, - }, { id: "backfill", accessorKey: "backfill", diff --git a/web/src/lib/api.ts b/web/src/lib/api.ts index 3f5fffa..41996e4 100644 --- a/web/src/lib/api.ts +++ b/web/src/lib/api.ts @@ -141,8 +141,6 @@ export function uploadLexicon(body: { backfill?: boolean; target_collection?: string; action?: string; - script?: string; - index_hook?: string; token_cost?: number | null; }) { return apiFetch<{ id: string; revision: number }>("/admin/lexicons", { diff --git a/web/src/types/lexicons.ts b/web/src/types/lexicons.ts index c7e1fb9..f1ceb81 100644 --- a/web/src/types/lexicons.ts +++ b/web/src/types/lexicons.ts @@ -5,8 +5,6 @@ export interface LexiconSummary { backfill: boolean action: string | null target_collection: string | null - has_script: boolean - has_index_hook: boolean source: string authority_did: string | null last_fetched_at: string | null @@ -17,6 +15,4 @@ export interface LexiconSummary { export interface LexiconDetail extends LexiconSummary { lexicon_json: Record - script: string | null - index_hook: string | null }