Class: Opdotenv::Loader

Inherits:
Object
  • Object
show all
Defined in:
lib/opdotenv/loader.rb

Constant Summary collapse

NOTES_PURPOSE =
"NOTES"

Class Method Summary collapse

Class Method Details

.build_field_path(path, field_name) ⇒ Object



49
50
51
52
53
# File 'lib/opdotenv/loader.rb', line 49

def self.build_field_path(path, field_name)
  # op CLI requires vault/item/field format
  # Avoid duplication if field name already in path
  path.end_with?("/#{field_name}") ? path : "#{path}/#{field_name}"
end

.field_env_entry(field) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/opdotenv/loader.rb', line 36

def self.field_env_entry(field)
  return nil unless field.is_a?(Hash)

  label = (field["label"] || field["id"])&.strip
  return nil if label.nil? || label.empty?
  return nil if field["purpose"] == NOTES_PURPOSE

  value = field["value"]
  return nil if value.nil? || (value.is_a?(String) && value.strip.empty?)

  {key: label.to_s, value: value.to_s}
end

.load(path, field_name: nil, field_type: :dotenv, env: ENV, client: nil, overwrite: true) ⇒ Object

Unified loading API If field_name is set, fetches a single field and parses it with field_type (default: :dotenv) If field_name is not set, fetches all fields without parsing



8
9
10
11
12
13
14
15
# File 'lib/opdotenv/loader.rb', line 8

def self.load(path, field_name: nil, field_type: :dotenv, env: ENV, client: nil, overwrite: true)
  client ||= ClientFactory.create(env: env)

  data = field_name ? load_field(client, path, field_name, field_type) : load_all_fields(client, path)

  merge_into_env(env, data, overwrite: overwrite)
  data
end

.load_all_fields(client, path) ⇒ Object



23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/opdotenv/loader.rb', line 23

def self.load_all_fields(client, path)
  vault, item = parse_op_path(path)
  raw_json = client.item_get(item, vault: vault)
  item_hash = parse_json_safe(raw_json)

  item_hash["fields"]&.each_with_object({}) do |field, env_data|
    entry = field_env_entry(field)
    next unless entry

    env_data[entry[:key]] = entry[:value]
  end || {}
end

.load_field(client, path, field_name, field_type) ⇒ Object



17
18
19
20
21
# File 'lib/opdotenv/loader.rb', line 17

def self.load_field(client, path, field_name, field_type)
  field_path = build_field_path(path, field_name)
  text = client.read(field_path)
  parse_by_format(text, field_type)
end

.merge_into_env(env, hash, overwrite: true) ⇒ Object



77
78
79
80
81
82
83
# File 'lib/opdotenv/loader.rb', line 77

def self.merge_into_env(env, hash, overwrite: true)
  hash.each do |k, v|
    key = k.to_s
    next if !overwrite && env.key?(key)
    env[key] = v.to_s
  end
end

.parse_by_format(text, format) ⇒ Object



61
62
63
64
65
66
67
68
69
# File 'lib/opdotenv/loader.rb', line 61

def self.parse_by_format(text, format)
  case format
  when :dotenv then Parsers::DotenvParser.parse(text)
  when :json then Parsers::JsonParser.parse(text)
  when :yaml, :yml then Parsers::YamlParser.parse(text)
  else
    raise ArgumentError, "Unsupported format: #{format}. Supported: :dotenv, :json, :yaml"
  end
end

.parse_json_safe(json_string) ⇒ Object



55
56
57
58
59
# File 'lib/opdotenv/loader.rb', line 55

def self.parse_json_safe(json_string)
  JSON.parse(json_string)
rescue JSON::ParserError
  {}
end

.parse_op_path(path) ⇒ Object

Raises:

  • (ArgumentError)


71
72
73
74
75
# File 'lib/opdotenv/loader.rb', line 71

def self.parse_op_path(path)
  m = path.match(/\Aop:\/\/([^\/]*)\/([^\/]*)/)
  raise ArgumentError, "Invalid op path: #{path}" unless m
  [m[1], m[2]]
end