@e-llm-studio/audit-log

中文文档
2.1.0发布于 2026/09/21MITTypeScriptESM + CJS近 30 天下载 2387
原始使用文档
文档目录39 节
  1. Table of contents
  2. 1. What you get
  3. 2. Installation
  4. Peer dependencies
  5. 3. Setup (styles + router)
  6. 4. Quick start
  7. 5. <AuditLog /> — full prop reference
  8. 6. The LogRow shape
  9. 7. Behavior details
  10. URL state
  11. Sidebar draft state
  12. Infinite scroll
  13. Restore flow
  14. Expandable row detail
  15. 8. <AuditLog /> examples
  16. 8.1 Minimal — API-driven, all defaults
  17. 8.2 With sidebar dropdowns + restore
  18. 8.3 External data mode (you control fetching)
  19. 8.4 Hide the sidebar, keep just toolbar + table
  20. 8.5 Limit the sort options + impact range
  21. 8.6 Expandable row detail
  22. 8.7 Add a custom column + tweak chip colors
  23. 8.8 Customize the restore toast
  24. 8.9 Localized labels
  25. 8.10 Analytics — tap into every interaction
  26. 9. API contracts
  27. 9.1 getData — audit-log fetch
  28. 9.2 distinctValuesApi
  29. 9.3 restoreApi
  30. 10. Using the individual components
  31. 10.1 LogTable — the data table
  32. 10.2 LogFilters — the toolbar
  33. 10.3 LogFiltersSidebar — the filter panel
  34. 10.4 DateRangeSelector — range date picker
  35. 10.5 ImpactRangeSelector — min/max slider
  36. 10.6 CustomMultiSelect — searchable multi-select
  37. 10.7 ActionTakenBody — chip + truncated text cell
  38. 11. Exports reference
  39. 12. Gotchas

@e-llm-studio/audit-log

A flexible, composable React library for rendering audit / change-log surfaces with search, sorting, advanced filtering, infinite scroll, expandable row detail, and version restore.

It ships one drop-in component — <AuditLog /> — that wires everything together from a few API endpoints, plus every sub-component is exported individually so you can compose your own UI.

Package: @e-llm-studio/audit-log Part of: the e-LLM Studio component library


Table of contents

  1. What you get
  2. Installation
  3. Setup (styles + router)
  4. Quick start
  5. <AuditLog /> — full prop reference
  6. The LogRow shape
  7. Behavior details
  8. <AuditLog /> examples
  9. API contracts
  10. Using the individual components
  11. Exports reference
  12. Gotchas

1. What you get

<AuditLog /> renders a complete audit-log surface:

  • A toolbar — keyword search (debounced), a date-range picker, a sort menu (Latest / Oldest / Impact % High↔Low) and a Filter button.
  • A right-side sidebar — multi-select "Modified By", "Change Title", a date-range filter, and an "Impact percentage" range slider. Uses a draft model (changes apply only on Apply Filter).
  • A virtualized data table — infinite scroll, per-row Restore this version action, optional expandable row detail, and an inline restore toast.
  • An internal data layer — calls your cursor-paginated audit API, auto-populates sidebar dropdowns, and handles restore. Or you fully control data externally.

URL state for search, date range, sort, analyst filter, change-title filter, and impact range is handled automatically via react-router-dom's useSearchParams, so links are shareable and the back button works.

Every sub-piece — table, toolbar, sidebar, date picker, multi-select, impact slider — is also exported on its own for fully custom layouts (see §10).


2. Installation

npm install @e-llm-studio/audit-log

Peer dependencies

Your host app must provide these (they are not bundled):

{
  "react":            "^18.3.1",
  "react-dom":        "^18.3.1",
  "react-router-dom": "^7.6.2",
  "lucide-react":     "^0.476.0",
  "primeicons":       "^7.0.0",
  "primereact":       "^10.9.7"
}
npm install react react-dom react-router-dom lucide-react primeicons primereact

3. Setup (styles + router)

1. Import the stylesheet once (e.g. in your app entry point):

import "@e-llm-studio/audit-log/dist/styles.css";

2. Render inside a router. Filter state lives in the URL, so the component must be mounted inside a <BrowserRouter> (or any router exposing useSearchParams):

import { BrowserRouter } from "react-router-dom";

<BrowserRouter>
  {/* ...your routes, including the page that renders <AuditLog /> */}
</BrowserRouter>

4. Quick start

import { AuditLog } from "@e-llm-studio/audit-log";
import { useParams } from "react-router-dom";

export function AuditLogPage() {
  const { id: externalResourceId } = useParams();

  const API = import.meta.env.VITE_BASE_API_URL;

  return (
    <AuditLog
      configId="6a0ab685346f096a6934b358"
      getData={{ baseUrl: API, endpoint: "/claims-management-mode/audits/" }}
      distinctValuesApi={{ baseUrl: API, endpoint: "/audit-log/distinct-values" }}
      restoreApi={{ baseUrl: API, endpoint: "/audit-log/restore", method: "POST" }}
      query={{
        externalResourceId: [externalResourceId!],
        paginationLimit: 20,
      }}
      table={{ tableProps: { scrollHeight: "60vh" } }}
    />
  );
}

That's a fully functional audit-log page: data fetching, filtering, sorting, infinite scroll, sidebar dropdowns, and restore.


5. <AuditLog /> — full prop reference

PropTypeRequiredDescription
configIdstring✅Tenant / configuration identifier sent to every audit API call.
accessTokenstring✅Sent as Authorization: Bearer <accessToken> on the getData and distinctValuesApi requests.
getData{ baseUrl: string; endpoint: string }optional¹Audit-logs API for internal fetching (POST). Required unless you use external data.
distinctValuesApi{ baseUrl: string; endpoint?: string }optionalIf provided, the sidebar's "Modified By" and "Change Title" dropdowns are auto-populated. endpoint defaults to /audit-log/distinct-values.
restoreApi{ baseUrl: string; endpoint: string; method?: "POST" | "PUT" }optionalEnables the Restore this version button. Without it, restore only logs a warning.
query{ externalResourceId?: string[]; paginationLimit?: number }optionalThe resource(s) to scope the log to, and the page size (pageSize) for pagination.
filtersPartial<LogFiltersProps>optionalPass-through overrides for the toolbar. See §10.2.
sidebarPartial<LogFiltersSidebarProps>optionalPass-through overrides for the filter sidebar. See §10.3.
tablePartial<LogTableProps>optionalPass-through overrides for the data table. See §10.1.
config{ showFilters?: boolean; showSidebar?: boolean }optionalToggle whole sub-sections off. Both default to true.
dataLogRow[]optionalExternal data mode. Skips the internal fetcher and renders these rows.
loadingbooleanoptionalInitial-load flag (external mode).
loadingMorebooleanoptional"Loading more" flag (external mode).
hasMorebooleanoptionalWhether more rows exist (external mode).
onLoadMore() => voidoptionalInfinite-scroll callback (external mode).
refetchKeystring | numberoptionalChange this value to force an internal refetch (e.g. after a mutation elsewhere).

¹ If both data and getData are passed, external data wins — internal fetching is disabled.


6. The LogRow shape

type LogRow = {
  id?: string;            // table key; auto-derived from change_log_id
  historyId?: string;     // used as the key for restore
  modifiedBy?: string;
  actionType?: string;    // shown as the chip label in "Change Summary"
  actionText?: string;    // long text (truncated at 95 chars w/ "See More")
  actionDate?: string;    // ISO date string
  updatedByICE?: boolean; // when true, "Modified By" shows "ICE"
  isLive?: boolean;       // when true, shows a red "Live" pill instead of Restore
  [key: string]: any;
};

When the internal fetcher is used, the raw API response is normalized into this shape automatically (see §9.1). In external mode you must provide rows matching this shape.


7. Behavior details

URL state

The component stores filter state in the URL via react-router-dom:

URL paramMeaning
keywordSearch input (debounced 350 ms)
createdAtStart / createdAtEndDate range (ISO strings)
orderBylatest (default), oldest, impactHighToLow, or impactLowToHigh
userEmailsComma-separated list (Modified By)
changeTitlesComma-separated list (Change Title)
impactMin / impactMaxImpact-percentage range (set on Apply)
cursorCleared on every filter change

Sidebar draft state

The sidebar uses a draft model — selections are local until the user clicks Apply Filter, which writes them to the URL. Reset Filter clears both the draft and the applied URL state.

Infinite scroll

The internal fetcher is cursor-based. When the user scrolls within 100 px of the bottom (or when content isn't tall enough to scroll), fetchMore() fires. Skeletons render during the initial load and at the bottom during "load more".

Restore flow

  1. User clicks Restore this version on a row → button shows "Restoring…".
  2. POST/PUT {baseUrl}{endpoint} is called with { change_log_id }.
  3. On success, the internal data refetch()s and a success toast shows (customizable via table.restoreToast).
  4. Rows with isLive === true display a red Live pill instead of the restore button.

Expandable row detail

Pass table.rowDetail.render to render your own content inline beneath a clicked row (AI summaries, diffs, request/response payloads, etc.). Accordion by default; pass multiple: true to allow several open at once. See §10.1.


8. <AuditLog /> examples

8.1 Minimal — API-driven, all defaults

<AuditLog
  configId={CONFIG_ID}
  getData={{ baseUrl: API, endpoint: "/audits" }}
  query={{ externalResourceId: [resourceId] }}
/>

8.2 With sidebar dropdowns + restore

<AuditLog
  configId={CONFIG_ID}
  getData={{ baseUrl: API, endpoint: "/audits" }}
  distinctValuesApi={{ baseUrl: API }}                  // endpoint defaults
  restoreApi={{ baseUrl: API, endpoint: "/restore" }}
  query={{ externalResourceId: [resourceId], paginationLimit: 25 }}
/>

8.3 External data mode (you control fetching)

const { rows, isLoading, hasMore, loadMore } = useMyAuditQuery(resourceId);

<AuditLog
  configId={CONFIG_ID}
  data={rows}
  loading={isLoading}
  hasMore={hasMore}
  onLoadMore={loadMore}
  restoreApi={{ baseUrl: API, endpoint: "/restore" }}
/>

8.4 Hide the sidebar, keep just toolbar + table

<AuditLog
  configId={CONFIG_ID}
  getData={{ baseUrl: API, endpoint: "/audits" }}
  query={{ externalResourceId: [resourceId] }}
  config={{ showSidebar: false }}
  filters={{ config: { showFilterButton: false } }}
/>

8.5 Limit the sort options + impact range

<AuditLog
  configId={CONFIG_ID}
  getData={{ baseUrl: API, endpoint: "/audits" }}
  query={{ externalResourceId: [resourceId] }}
  filters={{
    config: {
      sortOptions: { latest: true, oldest: true, impactHighToLow: false, impactLowToHigh: false },
    },
  }}
  sidebar={{
    impactRangeLimits: { min: 0, max: 50 },         // clamp the slider
    config: { showImpactPercentage: true },
  }}
/>

8.6 Expandable row detail

<AuditLog
  configId={CONFIG_ID}
  getData={{ baseUrl: API, endpoint: "/audits" }}
  query={{ externalResourceId: [resourceId] }}
  table={{
    rowDetail: {
      expandOnRowClick: true,   // default
      multiple: false,          // accordion (default)
      render: (row, { close }) => (
        <div style={{ padding: 16 }}>
          <h4>Change detail — {row.actionType}</h4>
          <pre>{row.actionText}</pre>
          <button onClick={close}>Close</button>
        </div>
      ),
    },
  }}
/>

8.7 Add a custom column + tweak chip colors

import { ShieldCheck } from "lucide-react";

<AuditLog
  configId={CONFIG_ID}
  getData={{ baseUrl: API, endpoint: "/audits" }}
  query={{ externalResourceId: [resourceId] }}
  table={{
    hiddenColumns: ["logId"],
    extraColumns: [
      {
        key: "severity",
        header: "Severity",
        body: (row) => <span>{row.severity ?? "—"}</span>,
        style: { width: "120px" },
      },
    ],
    chipConfig: {
      getTone: (row) => (row.modifiedBy === "ICE" ? "orange" : "purple"),
      getIcon: () => <ShieldCheck size={12} />,
    },
    tableProps: { scrollHeight: "70vh" },
    emptyState: {
      title: "No changes yet",
      description: "Edit the record to see audit entries here.",
    },
  }}
/>

8.8 Customize the restore toast

<AuditLog
  configId={CONFIG_ID}
  getData={{ baseUrl: API, endpoint: "/audits" }}
  restoreApi={{ baseUrl: API, endpoint: "/restore" }}
  query={{ externalResourceId: [resourceId] }}
  table={{
    restoreToast: {
      enabled: true,            // set false to suppress and handle toasts yourself
      position: "top-right",
      life: 4000,
      success: { summary: "Restored", detail: (id) => `Reverted to ${id}` },
      error:   { summary: "Oops", detail: () => "Restore failed, try again." },
    },
  }}
/>

8.9 Localized labels

<AuditLog
  configId={CONFIG_ID}
  getData={{ baseUrl: API, endpoint: "/audits" }}
  query={{ externalResourceId: [resourceId] }}
  sidebar={{
    labels: {
      title: "Filtrer par",
      multiSelectLabel: "Modifié par",
      dateLabel: "Sélectionner une date",
      changeTitleLabel: "Titre du changement",
      impactPercentageTitle: "Pourcentage d'impact",
    },
  }}
/>

8.10 Analytics — tap into every interaction

<AuditLog
  configId={CONFIG_ID}
  getData={{ baseUrl: API, endpoint: "/audits" }}
  query={{ externalResourceId: [resourceId] }}
  filters={{
    onChange: {
      onSearch: (v) => analytics.track("audit_search", { v }),
      onSort:   (v) => analytics.track("audit_sort",   { v }),
    },
  }}
  sidebar={{
    onApply: () => analytics.track("audit_filter_apply"),
    onReset: () => analytics.track("audit_filter_reset"),
  }}
/>

9. API contracts

9.1 getData — audit-log fetch

Request — POST {baseUrl}{endpoint}:

{
  "configId": "string",
  "filters": {
    "externalResourceId":    ["string"],
    "userEmails":            ["string?"],
    "changeTitle":           ["string?"],
    "content":               "string?",
    "modifiedDateStart":     "ISO date?",
    "modifiedDateEnd":       "ISO date?",
    "orderBy":               "latestFirst",  // | oldestFirst | impactPercentageHighToLow | impactPercentageLowToHigh
    "impactPercentageStart": 0,              // only sent once the impact filter is applied
    "impactPercentageEnd":   100
  },
  "pageSize": 20,
  "cursor": "opaque-cursor-from-previous-page?"
}

Response — the library normalizes items into LogRows:

{
  "data": {
    "items": [
      {
        "change_log_id":        "string",  // → id + historyId
        "external_resource_id": "string",
        "modifiedbyname":       "string",  // → modifiedBy
        "modifiedbyemail":      "string",
        "changeTitle":          "string",  // → actionType
        "change":               "string",  // → actionText
        "created_at":           "ISO date" // → actionDate
      }
    ],
    "nextCursor": "string?",
    "hasNext":    true
  }
}

9.2 distinctValuesApi

Request — GET {baseUrl}{endpoint}/{configId}?external_resource_id=... (one query param per id). endpoint defaults to /audit-log/distinct-values.

Response:

{
  "success": true,
  "data": {
    "change_made_title":   ["string"],                  // → Change Title options
    "change_made_by_user": { "User Name": "user@x" },    // → Modified By options (label: name, value: email)
    "truncated": false
  }
}

9.3 restoreApi

Request — POST (or PUT) {baseUrl}{endpoint}:

{ "change_log_id": "string" }

A non-2xx response throws Failed to restore audit version.


10. Using the individual components

Every building block is exported so you can compose a bespoke layout instead of using <AuditLog />. Import the stylesheet once (§3) regardless of which components you use.

import {
  LogTable,
  LogFilters,
  LogFiltersSidebar,
  DateRangeSelector,
  ImpactRangeSelector,
  CustomMultiSelect,
  ActionTakenBody,
} from "@e-llm-studio/audit-log";

10.1 LogTable — the data table

Renders rows, infinite-scroll skeletons, the empty state, the chip + restore cells, and optional expandable detail. You own the data and pagination.

PropTypeDescription
rowsLogRow[]Rows to render.
loading / loadingMorebooleanInitial-load / load-more flags.
hasMorebooleanWhether more rows exist.
onLoadMore() => voidCalled on scroll-to-bottom.
emptyState{ title?; description? }Empty-state copy.
hiddenColumnsstring[]Hide built-ins by key: logId, modifiedBy, changeSummary, changeDateTime, actions.
extraColumns{ key; header; body; style? }[]Append columns, or replace a built-in by reusing its key.
chipConfig{ getTone?; getIcon?; getStyle? }Per-row chip customization. getTone returns a suffix used as audit-chip--{tone}.
tablePropsRecord<string, any>Forwarded verbatim to the PrimeReact <DataTable> (scrollHeight, className, …).
onRowClick(row, helpers) => voidFires on row click. helpers: { isExpanded, expand, collapse, toggle }. Ignores clicks on buttons/links/inputs.
rowDetail{ render; expandOnRowClick?; multiple?; className?; style? }Consumer-rendered inline detail under a clicked row. render(row, { close }).
restoringIdstring | nullMarks the row currently restoring.
onRestore(historyId) => void | PromiseCalled when the restore button is clicked.
restoreToast{ enabled?; position?; life?; success?; error? }Inline PrimeReact toast config.
import { LogTable } from "@e-llm-studio/audit-log";

function MyTable({ rows, hasMore, loadMore, loading }) {
  return (
    <LogTable
      rows={rows}
      loading={loading}
      hasMore={hasMore}
      onLoadMore={loadMore}
      chipConfig={{ getTone: (r) => (r.updatedByICE ? "orange" : "purple") }}
      onRestore={async (id) => myRestoreApi(id)}
      rowDetail={{
        render: (row, { close }) => (
          <div style={{ padding: 12 }}>
            {row.actionText}
            <button onClick={close}>Close</button>
          </div>
        ),
      }}
      tableProps={{ scrollHeight: "65vh" }}
    />
  );
}

10.2 LogFilters — the toolbar

Controlled search / date / sort toolbar. value and onChange are required.

PropTypeDescription
value{ search?; dateRange?; sort? }Current toolbar state.
onChange{ onSearch?; onDate?; onSort? }Change handlers.
config{ showSearch?; showDate?; showSort?; showFilterButton?; sortOptions? }Toggle pieces. sortOptions toggles each of latest/oldest/impactHighToLow/impactLowToHigh.
onOpenFilter() => voidFired when the Filter button is clicked.
import { LogFilters, SortOrder, DateRange } from "@e-llm-studio/audit-log";
import { useState } from "react";

function Toolbar() {
  const [search, setSearch] = useState("");
  const [dateRange, setDateRange] = useState<DateRange>({ start: null, end: null });
  const [sort, setSort] = useState<SortOrder>("latest");

  return (
    <LogFilters
      value={{ search, dateRange, sort }}
      onChange={{ onSearch: setSearch, onDate: setDateRange, onSort: setSort }}
      config={{ showFilterButton: true }}
      onOpenFilter={() => console.log("open sidebar")}
    />
  );
}

10.3 LogFiltersSidebar — the filter panel

A right-side PrimeReact Sidebar with multi-selects, a date range, and an impact slider. Fully controlled.

PropTypeDescription
visible / onHideboolean / () => voidOpen state.
options / selectedValues / onChange—"Modified By" multi-select.
changeTitleOptions / selectedChangeTitles / onChangeTitleChange—"Change Title" multi-select.
dateRange / onDateRangeChange—Date-range filter.
impactRange / impactRangeLimits / onImpactRangeChangeImpactRangeImpact-percentage slider ({ min, max }).
onApply / onReset() => voidFooter actions.
config{ showAnalystFilter?; showDateFilter?; showChangeTitleFilter?; showImpactPercentage? }Toggle blocks.
labelsobjectLocalize every label/hint/title.
import { LogFiltersSidebar } from "@e-llm-studio/audit-log";

<LogFiltersSidebar
  visible={open}
  onHide={() => setOpen(false)}
  options={[{ label: "Renee Ramirez", value: "[email protected]" }]}
  selectedValues={analysts}
  onChange={setAnalysts}
  dateRange={dateRange}
  onDateRangeChange={setDateRange}
  impactRange={impact}
  impactRangeLimits={{ min: 0, max: 100 }}
  onImpactRangeChange={setImpact}
  onApply={applyFilters}
  onReset={resetFilters}
/>

10.4 DateRangeSelector — range date picker

Self-contained day/month/year range picker with draft + Apply/Reset. Note: the committed end is stored as exclusive (one day after the visually selected end).

import { DateRangeSelector, DateRange } from "@e-llm-studio/audit-log";
import { useState } from "react";

const [range, setRange] = useState<DateRange>({ start: null, end: null });

<DateRangeSelector
  value={range}
  onChange={setRange}
  maxDate={new Date()}
  endIcon            // render the calendar icon on the right (sidebar style)
/>

10.5 ImpactRangeSelector — min/max slider

A PrimeReact range slider with numeric Min/Max inputs.

import { ImpactRangeSelector, ImpactRange } from "@e-llm-studio/audit-log";
import { useState } from "react";

const [impact, setImpact] = useState<ImpactRange>({ min: 0, max: 100 });

<ImpactRangeSelector value={impact} onChange={setImpact} min={0} max={100} />

10.6 CustomMultiSelect — searchable multi-select

A lightweight checkbox dropdown with search and "All".

import { CustomMultiSelect, SelectOption } from "@e-llm-studio/audit-log";
import { useState } from "react";

const options: SelectOption[] = [
  { label: "Renee Ramirez", value: "[email protected]" },
  { label: "ICE", value: "[email protected]" },
];
const [selected, setSelected] = useState<string[]>([]);

<CustomMultiSelect
  options={options}
  value={selected}
  onChange={setSelected}
  placeholder="Select analysts"
/>

10.7 ActionTakenBody — chip + truncated text cell

The chip-plus-"See More" cell renderer used inside the table. Useful as a custom column body.

import { ActionTakenBody } from "@e-llm-studio/audit-log";
import { FileText } from "lucide-react";

<ActionTakenBody
  title="Field updated"
  desciption={row.actionText}      // note: prop spelling is `desciption`
  tone="purple"
  icon={<FileText size={12} />}
/>

11. Exports reference

// Components
import {
  AuditLog,            // the all-in-one component
  LogTable,
  LogFilters,
  LogFiltersSidebar,
  ActionTakenBody,
  DateRangeSelector,
  ImpactRangeSelector,
  CustomMultiSelect,
} from "@e-llm-studio/audit-log";

// Types
import type {
  LogRow,
  RowClickHelpers,
  RowDetailHelpers,
  LogTableProps,
  LogFiltersProps,
  SortOrder,
  LogFiltersSidebarProps,
  LogFiltersSidebarOption,
  DateRange,
  ImpactRange,
  SelectOption,
} from "@e-llm-studio/audit-log";

// Styles (import once)
import "@e-llm-studio/audit-log/dist/styles.css";

12. Gotchas

  • <AuditLog /> must be rendered inside a router — filter state lives in the URL.
  • Don't forget to import the stylesheet (dist/styles.css) or the UI will be unstyled.
  • If query.externalResourceId is empty/undefined, the internal fetcher will not fire.
  • distinctValuesApi is fetched lazily — only when the sidebar is visible (config.showSidebar !== false).
  • restoreApi is opt-in; without it, the restore button only console.warns.
  • In external data mode, you are responsible for refetching after a restore — the internal refetch() is skipped. Use refetchKey (internal mode) to force a refresh from a parent.
  • paginationLimit is sent as pageSize; the backend decides the page size if omitted.
  • The impact filter is only sent to the API once applied (committed to impactMin/impactMax in the URL).
  • ActionTakenBody's description prop is spelled desciption (kept for backward compatibility).

版本与发布记录

@e-llm-studio/audit-log 共发布 16 个版本,首次发布于 2026/04/28;过去 12 个月发布了 16 个版本。

版本发布日期距今
2.1.0latest2026/09/211 个月前
2.0.122026/09/022 个月前
2.0.112026/08/063 个月前
2.0.102026/08/053 个月前
2.0.92026/07/173 个月前
2.0.72026/07/153 个月前

其他发布通道:beta → 2.0.3-beta.0。

关于 @e-llm-studio/audit-log 的常见问题

如何安装 @e-llm-studio/audit-log?

在项目目录运行 npm install @e-llm-studio/audit-log,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:axios(^1.7.9)、react(^18.3.1)、react-dom(^18.3.1)、primeicons(^7.0.0)、primereact(>=10.8.5 <11.0.0)、lucide-react(>=0.474.0)、react-router-dom(>=7.5.2)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@e-llm-studio/audit-log 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@e-llm-studio/audit-log 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@e-llm-studio/audit-log 可以商用吗?

@e-llm-studio/audit-log 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@e-llm-studio/audit-log 的下载量有多少?

根据 npm 官方下载统计,@e-llm-studio/audit-log 在 2026/10/13 – 2026/11/11 这 30 天内被下载 2,387 次,日均约 80 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@e-llm-studio/audit-log 还在维护吗?

最新版本 2.1.0 发布于 2026/09/21(1 个月前);至今共发布 16 个版本,其中过去 12 个月发布了 16 个;首次发布于 2026/04/28。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。