Module: Everywhere::Config::NativeDesktop

Included in:
Everywhere::Config
Defined in:
lib/everywhere/config/native_desktop.rb

Constant Summary collapse

RUST_FN_NAME =

Everything here is interpolated into generated Rust and TOML, so names are validated hard — same reasoning as MAVEN_COORDINATE above. A command name becomes a path segment in a generate_handler! list; a crate name and its features become bare TOML keys and quoted strings.

/\A[a-z_][a-z0-9_]*\z/
CRATE_NAME =
/\A[a-zA-Z0-9_][a-zA-Z0-9_-]*\z/
CRATE_VERSION =

Cargo's requirement syntax, loosely: ^1.2, ~1.2, >=1.0, 1.*, 1.2.3-beta.1. Deliberately no spaces and no commas — a multi-requirement string would need quoting rules we don't want to own, and cargo reports anything subtler at build time.

/\A[\^~<>=]{0,2}\d+(\.\d+){0,2}(\.\*)?(-[0-9A-Za-z.-]+)?\z/
CRATE_FEATURE =
/\A[A-Za-z0-9_][A-Za-z0-9_+-]*\z/
CRATE_GIT_URL =

Where a git dependency may point. Same rule the SPM packages use — named through NativeMobile because a sibling section module's constants aren't in scope here the way they were when both lived in Config.

NativeMobile::PACKAGE_URL

Instance Method Summary collapse

Instance Method Details

#native_desktopObject

The desktop half of "supernative": Rust the app repo carries in native/desktop/ that every build compiles into the Tauri shell.

The shape differs from ios/android because desktop differs: the whole UI is a webview, so there are no native screens or splash views to register. What an app actually wants down here is the machine — a serial port, a USB device, an FFI library, a Tauri plugin — reached from the page.

native:
desktop:
  commands: [scan_ports]        # fns reachable from the page
  setup: true                   # run native/desktop/setup.rs at boot
  crates:
    serialport: "4.3"
    reqwest: { version: "0.12", features: [json] }

A command is a plain function, NOT a #[tauri::command] — Tauri's typed commands only arrive through invoke, and invoke is unavailable to our pages (they're served over http; see extension_host.rs in the shell). The signature is uniform:

pub fn scan_ports(app: &tauri::AppHandle, payload: serde_json::Value)
  -> Result<serde_json::Value, String>

Declaring anything here has a real cost the mobile sections don't have: the shell stops being one prebuilt crate shared by every app and gets stamped and compiled per app (see Builders::Desktop). Apps that declare nothing keep the fast path.



36
37
38
39
# File 'lib/everywhere/config/native_desktop.rb', line 36

def native_desktop
  section = @data.dig("native", "desktop")
  section.is_a?(Hash) ? section : {}
end

#native_desktop?Boolean

Returns:

  • (Boolean)


58
59
# File 'lib/everywhere/config/native_desktop.rb', line 58

def native_desktop? = !(native_desktop_commands.empty? && native_desktop_crates.empty?) ||
native_desktop_setup?

#native_desktop_commandsObject



41
# File 'lib/everywhere/config/native_desktop.rb', line 41

def native_desktop_commands = Array(native_desktop["commands"]).map { |name| name.to_s.strip }

#native_desktop_crate_errorsObject



104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/everywhere/config/native_desktop.rb', line 104

def native_desktop_crate_errors
  raw = native_desktop["crates"]
  return [] if raw.nil?
  return ["native.desktop.crates must be a mapping of crate name to version"] unless raw.is_a?(Hash)

  raw.flat_map do |name, spec|
    at = "native.desktop.crates.#{name}"
    errors = []
    unless name.to_s.strip.match?(CRATE_NAME)
      errors << "#{at}: #{name.to_s.inspect} is not a crate name (letters, digits, _, -)"
    end
    errors + crate_spec_errors(at, spec)
  end
end

#native_desktop_cratesObject

Cargo dependencies, normalized to { "name" => Everywhere::Config::NativeDesktop......table } so the generator has one shape to write. The short form (a bare version string) becomes { "version" => "4.3" }.



48
49
50
51
52
53
54
55
56
# File 'lib/everywhere/config/native_desktop.rb', line 48

def native_desktop_crates
  entries = native_desktop["crates"]
  return {} unless entries.is_a?(Hash)

  entries.to_h do |name, spec|
    table = spec.is_a?(Hash) ? spec : { "version" => spec.to_s }
    [name.to_s.strip, table]
  end
end

#native_desktop_errorsObject



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/everywhere/config/native_desktop.rb', line 78

def native_desktop_errors
  raw = @data.dig("native", "desktop")
  return [] if raw.nil?
  return ["native.desktop must be a mapping"] unless raw.is_a?(Hash)

  errors = []
  commands = raw["commands"]
  if !commands.nil? && !commands.is_a?(Array)
    errors << "native.desktop.commands must be a list of function names"
  else
    errors += native_desktop_commands.reject { |name| name.match?(RUST_FN_NAME) }.map do |name|
      "native.desktop.commands: #{name.inspect} is not a Rust function name — " \
        "snake_case (letters, digits, _), matching the fn in native/desktop/"
    end
    duplicates = native_desktop_commands.tally.select { |_name, count| count > 1 }.keys
    errors += duplicates.map do |name|
      "native.desktop.commands: #{name.inspect} is listed twice"
    end
  end

  setup = raw["setup"]
  errors << "native.desktop.setup must be true or false" unless setup.nil? || boolean_or_nil(setup) == setup

  errors + native_desktop_crate_errors
end

#native_desktop_setup?Boolean

Returns:

  • (Boolean)


43
# File 'lib/everywhere/config/native_desktop.rb', line 43

def native_desktop_setup? = native_desktop["setup"] == true