Module: Synthra::Export::TypeMapping

Defined in:
lib/synthra/export/type_mapping.rb

Overview

Shared type mapping for all export formats

This module provides consistent type mapping across all exporters, reducing code duplication and ensuring consistency.

rubocop:disable Metrics/ModuleLength -- this is a set of large lookup tables, not logic.

Constant Summary collapse

JSON_SCHEMA_TYPES =

Map Synthra types to JSON Schema types

{
  # Identifiers
  "uuid" => { "type" => "string", "format" => "uuid" },
  "ulid" => { "type" => "string", "pattern" => "^[0-9A-Z]{26}$" },
  "id_sequence" => { "type" => "integer" },
  "snowflake_id" => { "type" => "string" },
  "numeric_string_id" => { "type" => "string", "pattern" => "^[0-9]+$" },

  # Strings
  "text" => { "type" => "string" },
  "name" => { "type" => "string" },
  "first_name" => { "type" => "string" },
  "last_name" => { "type" => "string" },
  "full_name" => { "type" => "string" },
  "username" => { "type" => "string" },
  "email" => { "type" => "string", "format" => "email" },
  "phone" => { "type" => "string" },
  "url" => { "type" => "string", "format" => "uri" },
  "domain" => { "type" => "string", "format" => "hostname" },
  "ip" => { "type" => "string", "format" => "ipv4" },
  "ipv6" => { "type" => "string", "format" => "ipv6" },
  "address" => { "type" => "string" },
  "city" => { "type" => "string" },
  "state" => { "type" => "string" },
  "country" => { "type" => "string" },
  "country_code" => { "type" => "string" },
  "postal_code" => { "type" => "string" },
  "password" => { "type" => "string" },
  "color" => { "type" => "string" },
  "hex_color" => { "type" => "string", "pattern" => "^#[0-9a-fA-F]{6}$" },
  "user_agent" => { "type" => "string" },

  # Numbers (integers)
  "number" => { "type" => "integer" },
  "integer" => { "type" => "integer" },
  "age" => { "type" => "integer", "minimum" => 0, "maximum" => 150 },
  "airport_elevation" => { "type" => "integer" },
  "discount" => { "type" => "integer" },
  "formula" => { "type" => "integer" },
  "row_number" => { "type" => "integer" },
  "sequence" => { "type" => "integer" },

  # Numbers (floats)
  "float" => { "type" => "number" },
  "money" => { "type" => "number" },
  "latitude" => { "type" => "number", "minimum" => -90, "maximum" => 90 },
  "longitude" => { "type" => "number", "minimum" => -180, "maximum" => 180 },
  "airport_latitude" => { "type" => "number", "minimum" => -90, "maximum" => 90 },
  "airport_longitude" => { "type" => "number", "minimum" => -180, "maximum" => 180 },
  "product_price" => { "type" => "number" },
  "tax_rate" => { "type" => "number" },
  "transaction_amount" => { "type" => "number" },

  # Boolean
  "boolean" => { "type" => "boolean" },

  # Date
  "date" => { "type" => "string", "format" => "date" },
  "date_between" => { "type" => "string", "format" => "date" },
  "past_date" => { "type" => "string", "format" => "date" },
  "future_date" => { "type" => "string", "format" => "date" },
  "mobile_device_release_date" => { "type" => "string", "format" => "date" },
  "now" => { "type" => "string", "format" => "date" },

  # Date/Time
  "timestamp" => { "type" => "string", "format" => "date-time" },
  "datetime" => { "type" => "string", "format" => "date-time" },
  "time" => { "type" => "string", "format" => "time" },

  # Structural
  "object" => { "type" => "object" },
  "map_by_field" => { "type" => "object" },
  "array" => { "type" => "array" },
  "empty_array" => { "type" => "array", "maxItems" => 0 },
  "json_array" => { "type" => "array" },
  "indices_pair" => { "type" => "array", "items" => { "type" => "integer" }, "minItems" => 2, "maxItems" => 2 }
}.freeze
TYPESCRIPT_TYPES =

Map Synthra types to TypeScript types

{
  # Identifiers
  "uuid" => "string",
  "ulid" => "string",
  "id_sequence" => "number",
  "snowflake_id" => "string",
  "numeric_string_id" => "string",

  # Strings
  "text" => "string",
  "name" => "string",
  "first_name" => "string",
  "last_name" => "string",
  "full_name" => "string",
  "username" => "string",
  "email" => "string",
  "phone" => "string",
  "url" => "string",
  "domain" => "string",
  "ip" => "string",
  "ipv6" => "string",
  "address" => "string",
  "city" => "string",
  "state" => "string",
  "country" => "string",
  "country_code" => "string",
  "postal_code" => "string",
  "password" => "string",
  "color" => "string",
  "hex_color" => "string",
  "user_agent" => "string",
  "mac_address" => "string",

  # Numbers (integers + floats both map to TS number)
  "number" => "number",
  "integer" => "number",
  "age" => "number",
  "airport_elevation" => "number",
  "discount" => "number",
  "formula" => "number",
  "row_number" => "number",
  "sequence" => "number",
  "float" => "number",
  "money" => "number",
  "latitude" => "number",
  "longitude" => "number",
  "airport_latitude" => "number",
  "airport_longitude" => "number",
  "product_price" => "number",
  "tax_rate" => "number",
  "transaction_amount" => "number",

  # Boolean
  "boolean" => "boolean",

  # Date/Time (string in JSON)
  "date" => "string",
  "date_between" => "string",
  "past_date" => "string",
  "future_date" => "string",
  "mobile_device_release_date" => "string",
  "now" => "string",
  "timestamp" => "string",
  "datetime" => "string",
  "time" => "string",

  # Structural
  "object" => "Record<string, unknown>",
  "map_by_field" => "Record<string, unknown>",
  "array" => "unknown[]",
  "empty_array" => "never[]",
  "json_array" => "unknown[]",
  "indices_pair" => "[number, number]"
}.freeze
PYTHON_TYPES =

Map Synthra types to Python types

{
  # Identifiers
  "uuid" => "UUID",
  "ulid" => "str",
  "id_sequence" => "int",
  "snowflake_id" => "str",
  "numeric_string_id" => "str",

  # Strings
  "text" => "str",
  "name" => "str",
  "first_name" => "str",
  "last_name" => "str",
  "full_name" => "str",
  "username" => "str",
  "email" => "EmailStr",
  "phone" => "str",
  "url" => "HttpUrl",
  "domain" => "str",
  "ip" => "IPv4Address",
  "ipv6" => "IPv6Address",
  "address" => "str",
  "city" => "str",
  "state" => "str",
  "country" => "str",
  "country_code" => "str",
  "postal_code" => "str",
  "password" => "str",
  "color" => "str",
  "hex_color" => "str",
  "user_agent" => "str",
  "mac_address" => "str",

  # Numbers (integers)
  "number" => "int",
  "integer" => "int",
  "age" => "int",
  "airport_elevation" => "int",
  "discount" => "int",
  "formula" => "int",
  "row_number" => "int",
  "sequence" => "int",

  # Numbers (floats)
  "float" => "float",
  "money" => "Decimal",
  "latitude" => "float",
  "longitude" => "float",
  "airport_latitude" => "float",
  "airport_longitude" => "float",
  "product_price" => "float",
  "tax_rate" => "float",
  "transaction_amount" => "float",

  # Boolean
  "boolean" => "bool",

  # Date
  "date" => "date",
  "date_between" => "date",
  "past_date" => "date",
  "future_date" => "date",
  "mobile_device_release_date" => "date",
  "now" => "date",

  # Date/Time
  "timestamp" => "datetime",
  "datetime" => "datetime",
  "time" => "time",

  # Structural
  "object" => "Dict[str, Any]",
  "map_by_field" => "Dict[str, Any]",
  "array" => "List[Any]",
  "empty_array" => "List[Any]",
  "json_array" => "List[Any]",
  "indices_pair" => "Tuple[int, int]"
}.freeze
SQL_TYPES =

Map Synthra types to SQL types

{
  postgresql: {
    "uuid" => "UUID",
    "ulid" => "VARCHAR(26)",
    "id_sequence" => "SERIAL",
    "snowflake_id" => "BIGINT",
    "numeric_string_id" => "VARCHAR(20)",
    "text" => "TEXT",
    "name" => "VARCHAR(255)",
    "first_name" => "VARCHAR(100)",
    "last_name" => "VARCHAR(100)",
    "full_name" => "VARCHAR(255)",
    "username" => "VARCHAR(100)",
    "email" => "VARCHAR(255)",
    "phone" => "VARCHAR(20)",
    "url" => "TEXT",
    "domain" => "VARCHAR(255)",
    "ip" => "INET",
    "ipv6" => "INET",
    "address" => "TEXT",
    "city" => "VARCHAR(100)",
    "state" => "VARCHAR(100)",
    "country" => "VARCHAR(100)",
    "country_code" => "CHAR(2)",
    "postal_code" => "VARCHAR(20)",
    "password" => "VARCHAR(255)",
    "color" => "VARCHAR(50)",
    "hex_color" => "CHAR(7)",
    "number" => "INTEGER",
    "integer" => "INTEGER",
    "age" => "INTEGER",
    "airport_elevation" => "INTEGER",
    "discount" => "INTEGER",
    "formula" => "INTEGER",
    "row_number" => "INTEGER",
    "sequence" => "INTEGER",
    "float" => "REAL",
    "money" => "DECIMAL(10, 2)",
    "latitude" => "DECIMAL(10, 8)",
    "longitude" => "DECIMAL(11, 8)",
    "airport_latitude" => "DECIMAL(10, 8)",
    "airport_longitude" => "DECIMAL(11, 8)",
    "product_price" => "DECIMAL(10, 2)",
    "tax_rate" => "DECIMAL(10, 4)",
    "transaction_amount" => "DECIMAL(15, 2)",
    "boolean" => "BOOLEAN",
    "date" => "DATE",
    "date_between" => "DATE",
    "past_date" => "DATE",
    "future_date" => "DATE",
    "mobile_device_release_date" => "DATE",
    "now" => "DATE",
    "timestamp" => "TIMESTAMP",
    "datetime" => "TIMESTAMP",
    "time" => "TIME",
    "object" => "JSONB",
    "map_by_field" => "JSONB",
    "array" => "JSONB",
    "empty_array" => "JSONB",
    "json_array" => "JSONB",
    "indices_pair" => "INTEGER[]"
  },
  mysql: {
    "uuid" => "CHAR(36)",
    "ulid" => "CHAR(26)",
    "id_sequence" => "INT AUTO_INCREMENT",
    "snowflake_id" => "BIGINT",
    "numeric_string_id" => "VARCHAR(20)",
    "text" => "TEXT",
    "name" => "VARCHAR(255)",
    "email" => "VARCHAR(255)",
    "number" => "INT",
    "integer" => "INT",
    "float" => "FLOAT",
    "money" => "DECIMAL(10, 2)",
    "boolean" => "TINYINT(1)",
    "date" => "DATE",
    "timestamp" => "DATETIME",
    "datetime" => "DATETIME"
  },
  sqlite: {
    "uuid" => "TEXT",
    "ulid" => "TEXT",
    "id_sequence" => "INTEGER PRIMARY KEY AUTOINCREMENT",
    "text" => "TEXT",
    "name" => "TEXT",
    "email" => "TEXT",
    "number" => "INTEGER",
    "integer" => "INTEGER",
    "float" => "REAL",
    "money" => "REAL",
    "boolean" => "INTEGER",
    "date" => "TEXT",
    "timestamp" => "TEXT"
  }
}.freeze

Instance Method Summary collapse

Instance Method Details

#json_schema_type(type_name) ⇒ Hash

Get JSON Schema type for a Synthra type

Parameters:

  • type_name (String)

    the type name

Returns:

  • (Hash)

    JSON Schema type definition



350
351
352
# File 'lib/synthra/export/type_mapping.rb', line 350

def json_schema_type(type_name)
  JSON_SCHEMA_TYPES[type_name] || { "type" => "string" }
end

#python_type(type_name) ⇒ String

Get Python type for a Synthra type

Parameters:

  • type_name (String)

    the type name

Returns:

  • (String)

    Python type



370
371
372
373
374
# File 'lib/synthra/export/type_mapping.rb', line 370

def python_type(type_name)
  # Default to the language's string type: the overwhelming majority of
  # Synthra types generate strings, so an unmapped type is a string.
  PYTHON_TYPES[type_name] || "str"
end

#sql_type(type_name, dialect: :postgresql) ⇒ String

Get SQL type for a Synthra type

Parameters:

  • type_name (String)

    the type name

  • dialect (Symbol) (defaults to: :postgresql)

    SQL dialect (:postgresql, :mysql, :sqlite)

Returns:

  • (String)

    SQL type



382
383
384
385
# File 'lib/synthra/export/type_mapping.rb', line 382

def sql_type(type_name, dialect: :postgresql)
  dialect_types = SQL_TYPES[dialect] || SQL_TYPES[:postgresql]
  dialect_types[type_name] || "VARCHAR(255)"
end

#typescript_type(type_name) ⇒ String

Get TypeScript type for a Synthra type

Parameters:

  • type_name (String)

    the type name

Returns:

  • (String)

    TypeScript type



359
360
361
362
363
# File 'lib/synthra/export/type_mapping.rb', line 359

def typescript_type(type_name)
  # Default to the language's string type: the overwhelming majority of
  # Synthra types generate strings, so an unmapped type is a string.
  TYPESCRIPT_TYPES[type_name] || "string"
end