Module: Textus::Schema::Tools
- Defined in:
- lib/textus/schema/tools.rb
Class Method Summary collapse
-
.diff(store, name:) ⇒ Object
textus schema diff NAME → list keys whose frontmatter violates the schema.
- .infer_type(value) ⇒ Object
-
.init(store, name:, from:) ⇒ Object
textus schema init NAME –from=KEY → infer YAML schema from an entry’s frontmatter.
- .load_schema(store, name) ⇒ Object
-
.migrate(store, name:, rename: nil) ⇒ Object
textus schema migrate NAME –rename=OLD:NEW → rewrites frontmatter across affected entries If –rename is omitted, falls back to schema.evolution.migrate_from.
Class Method Details
.diff(store, name:) ⇒ Object
textus schema diff NAME → list keys whose frontmatter violates the schema
24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/textus/schema/tools.rb', line 24 def self.diff(store, name:) schema = load_schema(store, name) drift = [] store.manifest.enumerate.each do |row| env = store.get(row[:key]) begin schema.validate!(env["_meta"]) rescue SchemaViolation => e drift << { "key" => row[:key], "details" => e.details } end end { "protocol" => PROTOCOL, "schema_name" => name, "drift" => drift } end |
.infer_type(value) ⇒ Object
71 72 73 74 75 76 77 78 79 80 |
# File 'lib/textus/schema/tools.rb', line 71 def self.infer_type(value) case value when String then "string" when Numeric then "number" when true, false then "boolean" when Array then "array" when Hash then "object" else "string" end end |
.init(store, name:, from:) ⇒ Object
textus schema init NAME –from=KEY → infer YAML schema from an entry’s frontmatter
8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# File 'lib/textus/schema/tools.rb', line 8 def self.init(store, name:, from:) env = store.get(from) = env["_meta"] schema = { "name" => name, "required" => .keys, "optional" => [], "fields" => .each_with_object({}) { |(k, v), h| h[k] = { "type" => infer_type(v) } }, } FileUtils.mkdir_p(File.join(store.root, "schemas")) target = File.join(store.root, "schemas", "#{name}.yaml") File.write(target, YAML.dump(schema)) { "protocol" => PROTOCOL, "schema_name" => name, "path" => target } end |
.load_schema(store, name) ⇒ Object
82 83 84 85 86 |
# File 'lib/textus/schema/tools.rb', line 82 def self.load_schema(store, name) store.schema_for(name) rescue IoError raise UsageError.new("schema not found: #{name}") end |
.migrate(store, name:, rename: nil) ⇒ Object
textus schema migrate NAME –rename=OLD:NEW → rewrites frontmatter across affected entries If –rename is omitted, falls back to schema.evolution.migrate_from.
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/textus/schema/tools.rb', line 40 def self.migrate(store, name:, rename: nil) renames = if rename old_field, new_field = rename.split(":", 2) raise UsageError.new("--rename=OLD:NEW") unless old_field && new_field && !new_field.empty? { old_field => new_field } else load_schema(store, name).evolution["migrate_from"] || {} end raise UsageError.new("schema migrate needs --rename=OLD:NEW or schema.evolution.migrate_from") if renames.empty? touched = [] store.manifest.enumerate.each do |row| env = store.get(row[:key]) = env["_meta"] changed = false renames.each do |old, new| if .key?(old) [new] = .delete(old) changed = true end end next unless changed store.put(row[:key], meta: , body: env["body"], as: "human") touched << row[:key] end { "protocol" => PROTOCOL, "migrated" => touched, "renames" => renames } end |