Skip to main content

jpx_core/extensions/
ids.rs

1//! ID generation functions (nanoid, ulid).
2
3use std::collections::HashSet;
4
5use serde_json::Value;
6
7use crate::functions::{Function, number_value};
8use crate::interpreter::SearchResult;
9use crate::registry::register_if_enabled;
10use crate::{Context, Runtime, arg, defn};
11
12// =============================================================================
13// nanoid(size?) -> string
14// =============================================================================
15
16defn!(NanoidFn, vec![], Some(arg!(number)));
17
18impl Function for NanoidFn {
19    fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
20        self.signature.validate(args, ctx)?;
21
22        let id = if args.is_empty() {
23            nanoid::nanoid!()
24        } else {
25            let size = args[0].as_f64().unwrap_or(21.0) as usize;
26            nanoid::nanoid!(size)
27        };
28
29        Ok(Value::String(id))
30    }
31}
32
33// =============================================================================
34// ulid() -> string
35// =============================================================================
36
37defn!(UlidFn, vec![], None);
38
39impl Function for UlidFn {
40    fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
41        self.signature.validate(args, ctx)?;
42        let id = ulid::Ulid::new().to_string();
43        Ok(Value::String(id))
44    }
45}
46
47// =============================================================================
48// ulid_timestamp(ulid) -> number (unix ms)
49// =============================================================================
50
51defn!(UlidTimestampFn, vec![arg!(string)], None);
52
53impl Function for UlidTimestampFn {
54    fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
55        self.signature.validate(args, ctx)?;
56        let ulid_str = args[0].as_str().unwrap();
57
58        match ulid::Ulid::from_string(ulid_str) {
59            Ok(id) => {
60                let ts = id.timestamp_ms();
61                Ok(number_value(ts as f64))
62            }
63            Err(_) => Ok(Value::Null),
64        }
65    }
66}
67
68/// Register ID functions filtered by the enabled set.
69pub fn register_filtered(runtime: &mut Runtime, enabled: &HashSet<&str>) {
70    register_if_enabled(runtime, "nanoid", enabled, Box::new(NanoidFn::new()));
71    register_if_enabled(runtime, "ulid", enabled, Box::new(UlidFn::new()));
72    register_if_enabled(
73        runtime,
74        "ulid_timestamp",
75        enabled,
76        Box::new(UlidTimestampFn::new()),
77    );
78}