"use client";
'use strict';

var chunkI2NZGVBG_js = require('./chunk-I2NZGVBG.js');
var react = require('react');
var outline = require('@heroicons/react/24/outline');
var jsxRuntime = require('react/jsx-runtime');

var DIALECT_CATEGORIES = [
  {
    id: "relational",
    labelKey: "categoryRelational",
    icon: outline.CircleStackIcon,
    gradient: "from-blue-500 to-indigo-600",
    dialects: [
      { value: "postgres", label: "PostgreSQL", defaultPort: 5432, formType: "standard" },
      { value: "mysql", label: "MySQL", defaultPort: 3306, formType: "standard" },
      { value: "mariadb", label: "MariaDB", defaultPort: 3306, formType: "standard" },
      { value: "mssql", label: "SQL Server", defaultPort: 1433, formType: "standard" },
      { value: "oracle", label: "Oracle", defaultPort: 1521, formType: "standard" },
      { value: "db2", label: "IBM Db2", defaultPort: 5e4, formType: "standard" },
      { value: "cockroachdb", label: "CockroachDB", defaultPort: 26257, formType: "standard" },
      { value: "timescaledb", label: "TimescaleDB", defaultPort: 5432, formType: "standard" },
      { value: "sqlite", label: "SQLite", formType: "connection-string" },
      { value: "duckdb", label: "DuckDB", formType: "connection-string" }
    ]
  },
  {
    id: "nosql",
    labelKey: "categoryNoSql",
    icon: outline.ServerStackIcon,
    gradient: "from-emerald-500 to-teal-600",
    dialects: [
      { value: "mongodb", label: "MongoDB", defaultPort: 27017, formType: "connection-string" },
      { value: "cassandra", label: "Cassandra", defaultPort: 9042, formType: "standard" },
      { value: "scylladb", label: "ScyllaDB", defaultPort: 9042, formType: "standard" },
      { value: "dynamodb", label: "DynamoDB", formType: "cloud-key" },
      { value: "cosmosdb", label: "CosmosDB", formType: "connection-string" },
      { value: "arangodb", label: "ArangoDB", defaultPort: 8529, formType: "standard" }
    ]
  },
  {
    id: "warehouse",
    labelKey: "categoryWarehouse",
    icon: outline.CloudIcon,
    gradient: "from-purple-500 to-violet-600",
    dialects: [
      { value: "bigquery", label: "BigQuery", formType: "cloud-bigquery" },
      { value: "snowflake", label: "Snowflake", formType: "cloud-snowflake" },
      { value: "clickhouse", label: "ClickHouse", defaultPort: 8123, formType: "standard" }
    ]
  },
  {
    id: "timeseries",
    labelKey: "categoryTimeSeries",
    icon: outline.ClockIcon,
    gradient: "from-sky-500 to-cyan-600",
    dialects: [
      { value: "influxdb", label: "InfluxDB", formType: "cloud-key" },
      { value: "timestream", label: "Timestream", formType: "cloud-key" }
    ]
  },
  {
    id: "graph",
    labelKey: "categoryGraph",
    icon: outline.ShareIcon,
    gradient: "from-pink-500 to-rose-600",
    dialects: [
      { value: "neo4j", label: "Neo4j", defaultPort: 7687, formType: "standard" },
      { value: "neptune", label: "Neptune", formType: "connection-string" }
    ]
  },
  {
    id: "keyvalue",
    labelKey: "categoryKeyValue",
    icon: outline.KeyIcon,
    gradient: "from-red-500 to-orange-600",
    dialects: [
      { value: "redis", label: "Redis", defaultPort: 6379, formType: "standard" }
    ]
  },
  {
    id: "search",
    labelKey: "categorySearch",
    icon: outline.MagnifyingGlassIcon,
    gradient: "from-amber-500 to-yellow-600",
    dialects: [
      { value: "elasticsearch", label: "Elasticsearch", defaultPort: 9200, formType: "standard" },
      { value: "opensearch", label: "OpenSearch", defaultPort: 9200, formType: "standard" },
      { value: "pinecone", label: "Pinecone", formType: "vector-key" },
      { value: "qdrant", label: "Qdrant", defaultPort: 6333, formType: "standard" },
      { value: "weaviate", label: "Weaviate", defaultPort: 8080, formType: "standard" },
      { value: "milvus", label: "Milvus", defaultPort: 19530, formType: "standard" },
      { value: "chromadb", label: "ChromaDB", defaultPort: 8e3, formType: "standard" }
    ]
  }
];
function findDialect(value) {
  for (const category of DIALECT_CATEGORIES) {
    const found = category.dialects.find((d) => d.value === value);
    if (found) return found;
  }
  return void 0;
}
function findCategory(dialectValue) {
  return DIALECT_CATEGORIES.find((c) => c.dialects.some((d) => d.value === dialectValue));
}
function DialectPicker({
  labels,
  onSelect
}) {
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
    /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500 dark:text-gray-400", children: labels.stepSelectType }),
    DIALECT_CATEGORIES.map((category) => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
      /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-2 flex items-center gap-2", children: [
        /* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex h-7 w-7 items-center justify-center rounded-lg bg-gradient-to-br ${category.gradient}`, children: /* @__PURE__ */ jsxRuntime.jsx(category.icon, { className: "h-4 w-4 text-white" }) }),
        /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold text-gray-700 dark:text-gray-200", children: labels[category.labelKey] ?? category.id })
      ] }),
      /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-2 sm:grid-cols-3", children: category.dialects.map((dialect) => /* @__PURE__ */ jsxRuntime.jsxs(
        "button",
        {
          type: "button",
          onClick: () => onSelect(dialect.value),
          className: "group flex items-center gap-2 rounded-xl border border-gray-200/60 bg-white/60 px-3 py-2.5 text-left text-sm font-medium text-gray-700 transition-all hover:border-amber-400/60 hover:bg-amber-50/50 hover:text-amber-700 active:scale-[0.97] dark:border-white/10 dark:bg-white/5 dark:text-gray-300 dark:hover:border-amber-400/40 dark:hover:bg-amber-500/10 dark:hover:text-amber-300",
          children: [
            /* @__PURE__ */ jsxRuntime.jsx(outline.CircleStackIcon, { className: "h-4 w-4 shrink-0 text-gray-400 transition-colors group-hover:text-amber-500 dark:text-gray-500" }),
            dialect.label
          ]
        },
        dialect.value
      )) })
    ] }, category.id))
  ] });
}
function ConnectionForm({
  dialect,
  labels,
  onBack,
  onSubmit
}) {
  const [testStatus, setTestStatus] = react.useState("idle");
  const category = findCategory(dialect.value);
  function handleSubmit(event) {
    event.preventDefault();
    const formData = new FormData(event.currentTarget);
    const data = {
      name: String(formData.get("name") ?? "").trim(),
      dialect: dialect.value
    };
    for (const key of ["host", "database", "username", "password", "schema", "connectionString", "projectId", "dataset", "keyFile", "account", "warehouse", "region", "bucket", "token", "apiKey", "environment", "index", "url"]) {
      const val = String(formData.get(key) ?? "").trim();
      if (val) data[key] = val;
    }
    const port = String(formData.get("port") ?? "").trim();
    if (port) data.port = Number(port);
    data.ssl = formData.get("ssl") === "on";
    data.readOnly = formData.get("readOnly") === "on";
    const maxPoolSize = String(formData.get("maxPoolSize") ?? "").trim();
    if (maxPoolSize) {
      const parsed = Number(maxPoolSize);
      if (Number.isFinite(parsed) && parsed > 0) data.maxPoolSize = parsed;
    }
    const timeoutMs = String(formData.get("timeoutMs") ?? "").trim();
    if (timeoutMs) {
      const parsed = Number(timeoutMs);
      if (Number.isFinite(parsed) && parsed > 0) data.timeoutMs = parsed;
    }
    const allowedTables = splitList(String(formData.get("allowedTables") ?? ""));
    if (allowedTables.length > 0) data.allowedTables = allowedTables;
    const blockedColumns = splitList(String(formData.get("blockedColumns") ?? ""));
    if (blockedColumns.length > 0) data.blockedColumns = blockedColumns;
    onSubmit(data);
  }
  function handleTestConnection() {
    setTestStatus("testing");
    setTimeout(() => {
      setTestStatus("success");
      setTimeout(() => setTestStatus("idle"), 3e3);
    }, 1500);
  }
  function renderFields() {
    switch (dialect.formType) {
      case "standard":
        return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
          /* @__PURE__ */ jsxRuntime.jsx(chunkI2NZGVBG_js.FormInput, { name: "host", label: labels.fieldHost, placeholder: labels.fieldHostPlaceholder, required: true }),
          /* @__PURE__ */ jsxRuntime.jsx(chunkI2NZGVBG_js.FormInput, { name: "port", label: labels.fieldPort, type: "number", defaultValue: dialect.defaultPort }),
          /* @__PURE__ */ jsxRuntime.jsx(chunkI2NZGVBG_js.FormInput, { name: "database", label: labels.fieldDatabase, placeholder: labels.fieldDatabasePlaceholder, required: true }),
          /* @__PURE__ */ jsxRuntime.jsx(chunkI2NZGVBG_js.FormInput, { name: "username", label: labels.fieldUsername, placeholder: labels.fieldUsernamePlaceholder }),
          /* @__PURE__ */ jsxRuntime.jsx(chunkI2NZGVBG_js.FormInput, { name: "password", label: labels.fieldPassword, type: "password", placeholder: labels.fieldPasswordPlaceholder }),
          /* @__PURE__ */ jsxRuntime.jsx(chunkI2NZGVBG_js.FormInput, { name: "schema", label: labels.fieldSchema, placeholder: labels.fieldSchemaPlaceholder })
        ] });
      case "connection-string":
        return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-full", children: /* @__PURE__ */ jsxRuntime.jsx(chunkI2NZGVBG_js.FormInput, { name: "connectionString", label: labels.fieldConnectionString, placeholder: labels.fieldConnectionStringPlaceholder, required: true }) });
      case "cloud-bigquery":
        return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
          /* @__PURE__ */ jsxRuntime.jsx(chunkI2NZGVBG_js.FormInput, { name: "projectId", label: labels.fieldProjectId, placeholder: labels.fieldProjectIdPlaceholder, required: true }),
          /* @__PURE__ */ jsxRuntime.jsx(chunkI2NZGVBG_js.FormInput, { name: "dataset", label: labels.fieldDataset, placeholder: labels.fieldDatasetPlaceholder, required: true }),
          /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-full", children: /* @__PURE__ */ jsxRuntime.jsx(chunkI2NZGVBG_js.FormInput, { name: "keyFile", label: labels.fieldKeyFile, placeholder: labels.fieldKeyFilePlaceholder }) })
        ] });
      case "cloud-snowflake":
        return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
          /* @__PURE__ */ jsxRuntime.jsx(chunkI2NZGVBG_js.FormInput, { name: "account", label: labels.fieldAccount, placeholder: labels.fieldAccountPlaceholder, required: true }),
          /* @__PURE__ */ jsxRuntime.jsx(chunkI2NZGVBG_js.FormInput, { name: "warehouse", label: labels.fieldWarehouse, placeholder: labels.fieldWarehousePlaceholder, required: true }),
          /* @__PURE__ */ jsxRuntime.jsx(chunkI2NZGVBG_js.FormInput, { name: "database", label: labels.fieldDatabase, placeholder: labels.fieldDatabasePlaceholder, required: true }),
          /* @__PURE__ */ jsxRuntime.jsx(chunkI2NZGVBG_js.FormInput, { name: "username", label: labels.fieldUsername, placeholder: labels.fieldUsernamePlaceholder, required: true }),
          /* @__PURE__ */ jsxRuntime.jsx(chunkI2NZGVBG_js.FormInput, { name: "password", label: labels.fieldPassword, type: "password", placeholder: labels.fieldPasswordPlaceholder }),
          /* @__PURE__ */ jsxRuntime.jsx(chunkI2NZGVBG_js.FormInput, { name: "schema", label: labels.fieldSchema, placeholder: labels.fieldSchemaPlaceholder })
        ] });
      case "cloud-key":
        return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
          /* @__PURE__ */ jsxRuntime.jsx(chunkI2NZGVBG_js.FormInput, { name: "region", label: labels.fieldRegion, placeholder: labels.fieldRegionPlaceholder, required: true }),
          /* @__PURE__ */ jsxRuntime.jsx(chunkI2NZGVBG_js.FormInput, { name: "token", label: labels.fieldToken, type: "password", placeholder: labels.fieldTokenPlaceholder, required: true }),
          /* @__PURE__ */ jsxRuntime.jsx(chunkI2NZGVBG_js.FormInput, { name: "bucket", label: labels.fieldBucket, placeholder: labels.fieldBucketPlaceholder })
        ] });
      case "vector-key":
        return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
          /* @__PURE__ */ jsxRuntime.jsx(chunkI2NZGVBG_js.FormInput, { name: "apiKey", label: labels.fieldApiKey, type: "password", placeholder: labels.fieldApiKeyPlaceholder, required: true }),
          /* @__PURE__ */ jsxRuntime.jsx(chunkI2NZGVBG_js.FormInput, { name: "environment", label: labels.fieldEnvironment, placeholder: labels.fieldEnvironmentPlaceholder, required: true }),
          /* @__PURE__ */ jsxRuntime.jsx(chunkI2NZGVBG_js.FormInput, { name: "index", label: labels.fieldIndex, placeholder: labels.fieldIndexPlaceholder })
        ] });
    }
  }
  return /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit, className: "space-y-6", children: [
    /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
      /* @__PURE__ */ jsxRuntime.jsx(
        "button",
        {
          type: "button",
          onClick: onBack,
          className: "flex h-8 w-8 items-center justify-center rounded-lg text-gray-400 transition-colors hover:bg-gray-100 hover:text-gray-600 dark:hover:bg-white/10 dark:hover:text-gray-300",
          children: /* @__PURE__ */ jsxRuntime.jsx(outline.ArrowLeftIcon, { className: "h-4 w-4" })
        }
      ),
      /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
        /* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex h-8 w-8 items-center justify-center rounded-lg bg-gradient-to-br ${category?.gradient ?? "from-gray-400 to-gray-500"}`, children: category ? /* @__PURE__ */ jsxRuntime.jsx(category.icon, { className: "h-4 w-4 text-white" }) : /* @__PURE__ */ jsxRuntime.jsx(outline.CircleStackIcon, { className: "h-4 w-4 text-white" }) }),
        /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
          /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold text-gray-900 dark:text-white", children: dialect.label }),
          /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2 text-xs text-gray-400", children: labels[category?.labelKey ?? ""] ?? "" })
        ] })
      ] })
    ] }),
    /* @__PURE__ */ jsxRuntime.jsx(chunkI2NZGVBG_js.FormInput, { name: "name", label: labels.fieldName, placeholder: labels.fieldNamePlaceholder, required: true }),
    /* @__PURE__ */ jsxRuntime.jsx(chunkI2NZGVBG_js.FormGrid, { children: renderFields() }),
    /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-6 pt-2", children: [
      /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2 text-sm text-gray-700 dark:text-gray-300", children: [
        /* @__PURE__ */ jsxRuntime.jsx(
          "input",
          {
            type: "checkbox",
            name: "ssl",
            defaultChecked: true,
            className: "h-4 w-4 rounded border-gray-300 text-amber-600 focus:ring-amber-500 dark:border-gray-600 dark:bg-gray-800"
          }
        ),
        labels.fieldSsl
      ] }),
      /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2 text-sm text-gray-700 dark:text-gray-300", children: [
        /* @__PURE__ */ jsxRuntime.jsx(
          "input",
          {
            type: "checkbox",
            name: "readOnly",
            defaultChecked: true,
            className: "h-4 w-4 rounded border-gray-300 text-amber-600 focus:ring-amber-500 dark:border-gray-600 dark:bg-gray-800"
          }
        ),
        labels.fieldReadOnly
      ] })
    ] }),
    /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-400 dark:text-gray-500", children: labels.fieldReadOnlyHelp }),
    /* @__PURE__ */ jsxRuntime.jsxs("details", { className: "rounded-xl border border-gray-200/60 bg-white/40 p-3 dark:border-white/10 dark:bg-white/5", children: [
      /* @__PURE__ */ jsxRuntime.jsx("summary", { className: "cursor-pointer text-sm font-medium text-gray-700 dark:text-gray-300", children: labels.advancedToggle ?? "Governance & performance" }),
      /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 space-y-3", children: [
        /* @__PURE__ */ jsxRuntime.jsxs(chunkI2NZGVBG_js.FormGrid, { children: [
          /* @__PURE__ */ jsxRuntime.jsx(
            chunkI2NZGVBG_js.FormInput,
            {
              name: "maxPoolSize",
              label: labels.fieldMaxPoolSize ?? "Max pool size",
              type: "number",
              min: 1,
              max: 100,
              placeholder: "5"
            }
          ),
          /* @__PURE__ */ jsxRuntime.jsx(
            chunkI2NZGVBG_js.FormInput,
            {
              name: "timeoutMs",
              label: labels.fieldTimeoutMs ?? "Timeout (ms)",
              type: "number",
              min: 100,
              placeholder: "5000"
            }
          )
        ] }),
        /* @__PURE__ */ jsxRuntime.jsx(
          chunkI2NZGVBG_js.FormInput,
          {
            name: "allowedTables",
            label: labels.fieldAllowedTables ?? "Allowed tables (comma-separated)",
            placeholder: "stations, current_prices, competitor_prices"
          }
        ),
        /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-400 dark:text-gray-500", children: labels.fieldAllowedTablesHelp ?? "Leave blank to allow every table the credential can see. Otherwise only the listed tables are queryable from workflows." }),
        /* @__PURE__ */ jsxRuntime.jsx(
          chunkI2NZGVBG_js.FormInput,
          {
            name: "blockedColumns",
            label: labels.fieldBlockedColumns ?? "Blocked columns (comma-separated)",
            placeholder: "customers.ssn, employees.salary"
          }
        ),
        /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-400 dark:text-gray-500", children: labels.fieldBlockedColumnsHelp ?? "Columns the driver must never surface, even if referenced by a workflow. Use table.column notation for specificity." })
      ] })
    ] }),
    /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 border-t border-gray-200/60 pt-5 dark:border-white/10", children: [
      /* @__PURE__ */ jsxRuntime.jsx(
        chunkI2NZGVBG_js.Button,
        {
          type: "button",
          size: "sm",
          color: "zinc",
          onClick: handleTestConnection,
          disabled: testStatus === "testing",
          children: testStatus === "testing" ? labels.testing : labels.testConnection
        }
      ),
      testStatus === "success" && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1 text-xs font-medium text-emerald-600 dark:text-emerald-400", children: [
        /* @__PURE__ */ jsxRuntime.jsx(outline.CheckCircleIcon, { className: "h-4 w-4" }),
        labels.connectionSuccess
      ] }),
      testStatus === "failed" && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1 text-xs font-medium text-red-600 dark:text-red-400", children: [
        /* @__PURE__ */ jsxRuntime.jsx(outline.XCircleIcon, { className: "h-4 w-4" }),
        labels.connectionFailed
      ] }),
      /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1" }),
      /* @__PURE__ */ jsxRuntime.jsx(chunkI2NZGVBG_js.Button, { type: "submit", size: "sm", color: "amber", children: labels.save })
    ] })
  ] });
}
function DatasourceFormModal({ open, onClose, labels, onSave }) {
  const [selectedDialect, setSelectedDialect] = react.useState(null);
  const dialect = selectedDialect ? findDialect(selectedDialect) : null;
  function handleClose() {
    setSelectedDialect(null);
    onClose();
  }
  function handleSave(data) {
    onSave(data);
    handleClose();
  }
  return /* @__PURE__ */ jsxRuntime.jsx(
    chunkI2NZGVBG_js.GlassModal,
    {
      open,
      onClose: handleClose,
      title: labels.createTitle,
      subtitle: dialect ? labels.stepConfigure : labels.stepSelectType,
      icon: /* @__PURE__ */ jsxRuntime.jsx(outline.CircleStackIcon, { className: "h-5 w-5" }),
      gradient: "from-amber-500 to-orange-600",
      maxWidth: "3xl",
      children: dialect ? /* @__PURE__ */ jsxRuntime.jsx(
        ConnectionForm,
        {
          dialect,
          labels,
          onBack: () => setSelectedDialect(null),
          onSubmit: handleSave
        }
      ) : /* @__PURE__ */ jsxRuntime.jsx(DialectPicker, { labels, onSelect: setSelectedDialect })
    }
  );
}
function DatasourceModal({ open, onClose, labels, onSave }) {
  const [selectedDialect, setSelectedDialect] = react.useState(null);
  const dialect = selectedDialect ? findDialect(selectedDialect) : null;
  function handleClose() {
    setSelectedDialect(null);
    onClose();
  }
  function handleSave(data) {
    onSave(data);
    handleClose();
  }
  return /* @__PURE__ */ jsxRuntime.jsx(
    chunkI2NZGVBG_js.GlassModal,
    {
      open,
      onClose: handleClose,
      title: labels.createTitle,
      subtitle: dialect ? labels.stepConfigure : labels.stepSelectType,
      icon: /* @__PURE__ */ jsxRuntime.jsx(outline.CircleStackIcon, { className: "h-5 w-5" }),
      gradient: "from-amber-500 to-orange-600",
      maxWidth: "3xl",
      children: dialect ? /* @__PURE__ */ jsxRuntime.jsx(
        ConnectionForm,
        {
          dialect,
          labels,
          onBack: () => setSelectedDialect(null),
          onSubmit: handleSave
        }
      ) : /* @__PURE__ */ jsxRuntime.jsx(DialectPicker, { labels, onSelect: setSelectedDialect })
    }
  );
}
function splitList(raw) {
  return raw.split(",").map((entry) => entry.trim()).filter((entry) => entry.length > 0);
}

exports.DIALECT_CATEGORIES = DIALECT_CATEGORIES;
exports.DatasourceFormModal = DatasourceFormModal;
exports.DatasourceModal = DatasourceModal;
exports.findCategory = findCategory;
exports.findDialect = findDialect;
//# sourceMappingURL=chunk-TIJJHW2Z.js.map
//# sourceMappingURL=chunk-TIJJHW2Z.js.map