@nteract/sift 0.0.1 → 0.5.4-nightly.38473320686
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +101 -7
- package/docs/embedding-guide.md +216 -0
- package/lib/LICENSE +28 -0
- package/lib/THIRD_PARTY_NOTICES.md +2018 -0
- package/lib/handoff.css +37 -0
- package/lib/handoff.js +26 -0
- package/lib/index.js +6548 -0
- package/lib/style.css +2 -0
- package/lib/types/packages/sift/src/accumulators.d.ts +61 -0
- package/lib/types/packages/sift/src/auto-width.d.ts +13 -0
- package/lib/types/packages/sift/src/column-menu.d.ts +8 -0
- package/lib/types/packages/sift/src/components/column-context-menu.d.ts +32 -0
- package/lib/types/packages/sift/src/components/image-viewer.d.ts +16 -0
- package/lib/types/packages/sift/src/csv.d.ts +19 -0
- package/lib/types/packages/sift/src/events.d.ts +1 -0
- package/lib/types/packages/sift/src/file-data.d.ts +40 -0
- package/lib/types/packages/sift/src/filter-schema.d.ts +100 -0
- package/lib/types/packages/sift/src/handoff.d.ts +11 -0
- package/lib/types/packages/sift/src/index.d.ts +29 -0
- package/lib/types/packages/sift/src/parquet-features.d.ts +15 -0
- package/lib/types/packages/sift/src/predicate.d.ts +199 -0
- package/lib/types/packages/sift/src/react.d.ts +97 -0
- package/lib/types/packages/sift/src/sparkline.d.ts +25 -0
- package/lib/types/packages/sift/src/table-response.d.ts +5 -0
- package/lib/types/packages/sift/src/table.d.ts +175 -0
- package/lib/types/packages/sift/src/wasm-summaries.d.ts +3 -0
- package/lib/types/packages/sift/src/wasm-table-data.d.ts +19 -0
- package/lib/types/src/components/ui/button.d.ts +11 -0
- package/lib/types/src/components/ui/popover.d.ts +7 -0
- package/lib/types/src/lib/utils.d.ts +2 -0
- package/lib/wasm/sift_wasm.d.ts +382 -0
- package/lib/wasm/sift_wasm.js +1398 -0
- package/lib/wasm/sift_wasm_bg.wasm +0 -0
- package/package.json +76 -5
package/README.md
CHANGED
|
@@ -1,13 +1,107 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Sift
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
publish through npm trusted publishing. It contains no code.
|
|
3
|
+
Crossfilter data explorer. [Pretext](https://github.com/chenglou/pretext) × [Arrow](https://arrow.apache.org/).
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
[`@nteract/sift`](https://github.com/nteract) on npm. Try it at [rgbkrk.github.io/sift](https://rgbkrk.github.io/sift/).
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- **Local CSV/TSV, Parquet, and Arrow IPC streams** — bounded file adapters, no notebook or server needed
|
|
12
|
+
- **Stream hosted Arrow IPC or load Parquet URLs** — WASM-native
|
|
13
|
+
- **Crossfilter** — brush histograms to filter, all other summaries update instantly
|
|
14
|
+
- **Column profiling** — null%, distinct count shown inline in headers
|
|
15
|
+
- **Smart summaries** — histograms, category bars, boolean ratios, binary value bars, searchable popovers. Adapts visualization to column type × cardinality.
|
|
16
|
+
- **Column type casting** — right-click to treat text as numbers, dates, booleans — with full undo
|
|
17
|
+
- **Smart column detection** — pandas index columns, HuggingFace ClassLabel features
|
|
18
|
+
- **Virtual scroll** — 100k+ rows at 120fps. Pretext layout at 0.0002ms/cell.
|
|
19
|
+
- **Odometer status bar** — rolling digit animation for row count, visible range, FPS
|
|
20
|
+
- **Multi-instance** — embed multiple tables on one page (notebook demo included)
|
|
21
|
+
- **RxJS streaming** — cancellable dataset loading via `switchMap`
|
|
22
|
+
- **Mobile** — tap any row for a detail sheet with all column values
|
|
23
|
+
- **Dark mode**, keyboard nav, pinned columns, ARIA grid
|
|
24
|
+
- **8 HuggingFace datasets** built into the demo
|
|
25
|
+
|
|
26
|
+
## Quick start
|
|
27
|
+
|
|
28
|
+
From the nteract repository root:
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
pnpm install --frozen-lockfile
|
|
32
|
+
cargo xtask wasm sift --skip-renderer-plugins
|
|
33
|
+
pnpm --dir packages/sift dev
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Use as a library
|
|
37
|
+
|
|
38
|
+
The package ships JavaScript, compiled CSS, TypeScript declarations, and WASM,
|
|
39
|
+
with third-party notices for the bundled code in `lib/THIRD_PARTY_NOTICES.md`.
|
|
40
|
+
React and React DOM are required; no notebook, kernel, or daemon is needed.
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
import { parseCsv, SiftTable } from '@nteract/sift'
|
|
44
|
+
import '@nteract/sift/style.css'
|
|
45
|
+
|
|
46
|
+
const data = parseCsv(csvText) // Complete file; rejects malformed/over-limit data.
|
|
47
|
+
<SiftTable data={data} style={{ height: 600 }} />
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
For binary files, use `loadTableFile(bytes)` through a memoized React loader
|
|
51
|
+
source or pass its result to imperative `createTable` (see the guide).
|
|
52
|
+
The default file adapters impose independent ceilings of 16 MiB,
|
|
53
|
+
100,000 rows, and 256 columns; CSV also has a 1,000,000-cell ceiling, and binary
|
|
54
|
+
files have a conservative 128 MiB decoded-memory admission guard. Meeting the
|
|
55
|
+
byte, row, and column ceilings alone does not guarantee acceptance.
|
|
56
|
+
Virtual scrolling does not provide disk paging.
|
|
57
|
+
|
|
58
|
+
See the [embedding guide](docs/embedding-guide.md) for WASM asset setup, CSV/TSV
|
|
59
|
+
options, memory limits, lifecycle, themes, and host viewer/editor integration.
|
|
60
|
+
|
|
61
|
+
## Engine API
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
engine.setSort('age', 'desc')
|
|
65
|
+
engine.setFilter(colIndex, { kind: 'range', min: 18, max: 65 })
|
|
66
|
+
engine.clearAllFilters()
|
|
67
|
+
|
|
68
|
+
// Inspect the current sort, filters, and counts.
|
|
69
|
+
const state = engine.getState()
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
See [`docs/embedding-guide.md`](docs/embedding-guide.md) for the full API.
|
|
73
|
+
|
|
74
|
+
## WASM compute (`sift-wasm`)
|
|
75
|
+
|
|
76
|
+
Rust crate wrapping arrow-rs. Parquet decoding, sort, histograms, value counts, string search, column casting — all in one WASM binary. Data lives in WASM memory; JS holds handles.
|
|
7
77
|
|
|
8
78
|
```sh
|
|
9
|
-
|
|
79
|
+
cargo xtask wasm sift --skip-renderer-plugins
|
|
10
80
|
```
|
|
11
81
|
|
|
12
|
-
|
|
13
|
-
|
|
82
|
+
## Stack
|
|
83
|
+
|
|
84
|
+
| Layer | What |
|
|
85
|
+
|-------|------|
|
|
86
|
+
| Layout | [@chenglou/pretext](https://github.com/chenglou/pretext) — DOM-free text measurement |
|
|
87
|
+
| Data | [Apache Arrow](https://arrow.apache.org/) — columnar, streamed via RecordBatchReader |
|
|
88
|
+
| Compute | [sift-wasm](../../crates/sift-wasm/) — arrow-rs WASM kernels |
|
|
89
|
+
| Reactivity | [RxJS](https://rxjs.dev/) — streaming pipeline |
|
|
90
|
+
| Charts | SVG histograms + HTML bars |
|
|
91
|
+
|
|
92
|
+
## Development
|
|
93
|
+
|
|
94
|
+
Run from the repository root after the setup above:
|
|
95
|
+
|
|
96
|
+
```sh
|
|
97
|
+
pnpm --dir packages/sift test # Vitest unit tests
|
|
98
|
+
pnpm --dir packages/sift test:e2e # Playwright E2E
|
|
99
|
+
pnpm --dir packages/sift build # production build (demo)
|
|
100
|
+
pnpm --dir packages/sift build:lib # lib/ (JS, CSS, types, WASM)
|
|
101
|
+
pnpm --dir packages/sift test:package # packed consumer outside the workspace
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Demo pages
|
|
105
|
+
|
|
106
|
+
- `/` — main demo with dataset picker
|
|
107
|
+
- `/notebook.html` — multi-table notebook simulation
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# Embedding Sift
|
|
2
|
+
|
|
3
|
+
`@nteract/sift` is a browser table viewer with compiled JavaScript, CSS, TypeScript
|
|
4
|
+
interfaces, and a matching WebAssembly decoder. It does not require a notebook,
|
|
5
|
+
kernel, daemon, Tauri, Electron, or an nteract runtime connection. React and React
|
|
6
|
+
DOM are required even for the imperative API because column controls use React.
|
|
7
|
+
|
|
8
|
+
## Install and assets
|
|
9
|
+
|
|
10
|
+
```sh
|
|
11
|
+
npm install @nteract/sift react react-dom
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
import { SiftTable, setWasmUrl } from '@nteract/sift'
|
|
16
|
+
import '@nteract/sift/style.css'
|
|
17
|
+
// Vite example: emit the packaged binary through the host's asset pipeline.
|
|
18
|
+
import wasmUrl from '@nteract/sift/sift.wasm?url'
|
|
19
|
+
|
|
20
|
+
setWasmUrl(wasmUrl) // Configure once, before the first binary table loads.
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Other bundlers can copy `@nteract/sift/sift.wasm` into their local assets and pass
|
|
24
|
+
its served URL to `setWasmUrl`. Without an override, the shipped wasm-bindgen glue
|
|
25
|
+
resolves `sift_wasm_bg.wasm` relative to itself; preserve that layout when serving
|
|
26
|
+
unbundled modules. Serve the binary with `application/wasm`. Keep the JavaScript
|
|
27
|
+
and WASM from the same package version. No CDN or data upload is required.
|
|
28
|
+
|
|
29
|
+
The host owns file access and its existing sandbox/CSP policy. In an Electron
|
|
30
|
+
app, read selected files through the approved main/preload bridge and pass text
|
|
31
|
+
or bytes to the renderer; Sift does not need Node integration or filesystem
|
|
32
|
+
access. The package's URL API explicitly fetches URLs supplied by the host.
|
|
33
|
+
|
|
34
|
+
## Local CSV and TSV
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
import { parseCsv, SiftTable } from '@nteract/sift'
|
|
38
|
+
|
|
39
|
+
const data = parseCsv(csvText)
|
|
40
|
+
// For TSV: parseCsv(tsvText, { delimiter: '\t' })
|
|
41
|
+
|
|
42
|
+
<SiftTable data={data} style={{ height: 600 }} />
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Parse once when the file snapshot changes, not on every React render. The host
|
|
46
|
+
owns text decoding: for UTF-8 files, use `new TextDecoder('utf-8', { fatal: true })`
|
|
47
|
+
so invalid byte sequences become an actionable error. A leading BOM is accepted.
|
|
48
|
+
There is no encoding or delimiter guessing. Delimiters are comma (default), tab,
|
|
49
|
+
semicolon, and pipe.
|
|
50
|
+
|
|
51
|
+
The first record supplies column names; blank and duplicate names are made
|
|
52
|
+
unique. Quoted delimiters, escaped quotes, and multiline fields are supported.
|
|
53
|
+
Malformed quoting and inconsistent record widths throw an error. Empty unquoted
|
|
54
|
+
fields become null; quoted empty fields stay empty strings. Literal `NA`, `null`,
|
|
55
|
+
and similar strings are preserved. Nulls are excluded from categorical counts
|
|
56
|
+
and never match the empty-string category. Selecting that category matches only
|
|
57
|
+
quoted empty strings; excluding it retains null rows. Category percentages use
|
|
58
|
+
all rows in the current selection as their denominator, including null rows.
|
|
59
|
+
|
|
60
|
+
A final line ending terminates the preceding record. Additional blank records
|
|
61
|
+
are preserved: in a one-column file each is a null row; in a wider file each
|
|
62
|
+
fails the record-width check. Automatically skipping blank records is an open
|
|
63
|
+
format-policy decision because it could silently remove valid null rows.
|
|
64
|
+
|
|
65
|
+
Default inference examines every loaded value in a column. Conservative numbers
|
|
66
|
+
and lowercase `true`/`false` become numeric/boolean columns; dates, leading-zero
|
|
67
|
+
identifiers, and unsafe integers stay text. Original spellings remain available
|
|
68
|
+
for display, but numeric comparisons use JavaScript numbers and can approximate
|
|
69
|
+
exact decimals. Use `{ typing: 'text' }` to keep every non-null field as text.
|
|
70
|
+
|
|
71
|
+
The default limits are 16 MiB of UTF-8 text, 100,000 data rows, 256 columns, and
|
|
72
|
+
1,000,000 cells. Override `maxBytes`, `maxRows`, `maxColumns`, and `maxCells`
|
|
73
|
+
explicitly when the host can support larger files. Over-limit input fails; it is
|
|
74
|
+
never silently truncated. Reject oversized files before reading them as well.
|
|
75
|
+
|
|
76
|
+
## Local Parquet and Arrow
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
import { loadTableFile, createTable } from '@nteract/sift'
|
|
80
|
+
|
|
81
|
+
const data = await loadTableFile(bytes) // Uint8Array; detects Parquet magic.
|
|
82
|
+
const engine = createTable(container, data)
|
|
83
|
+
// When the document closes or changes:
|
|
84
|
+
engine.destroy() // Also disposes the data's WASM store.
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
For React, use a memoized loader returning fresh data for every invocation.
|
|
88
|
+
This also supports React StrictMode's setup/cleanup replay:
|
|
89
|
+
|
|
90
|
+
```tsx
|
|
91
|
+
import { useCallback } from 'react'
|
|
92
|
+
import { loadTableFile, SiftTable } from '@nteract/sift'
|
|
93
|
+
|
|
94
|
+
function ParquetView({ bytes }: { bytes: Uint8Array }) {
|
|
95
|
+
const load = useCallback(() => loadTableFile(bytes), [bytes])
|
|
96
|
+
return <SiftTable source={{ kind: 'loader', load }} style={{ height: 600 }} />
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Keep the bytes snapshot stable until the file changes. Do not capture and return
|
|
101
|
+
one previously loaded disposable table from the callback.
|
|
102
|
+
|
|
103
|
+
`loadTableFile` supports Parquet and uncompressed Arrow IPC streams. The optional
|
|
104
|
+
`format` is `'parquet'` or `'arrow-ipc'`. CSV/TSV should use `parseCsv`. Arrow file
|
|
105
|
+
containers and compressed IPC streams are not supported by this path.
|
|
106
|
+
|
|
107
|
+
Binary input defaults to 16 MiB, 100,000 rows, 256 columns, and a 128 MiB decoded
|
|
108
|
+
memory guardrail (`maxBytes`, `maxRows`, `maxColumns`, `maxDecodedBytes`). Parquet
|
|
109
|
+
checks footer metadata before decoding, summed across all row groups. Boolean and
|
|
110
|
+
fixed-width leaves (integers, floats, dates, times, timestamps, decimals,
|
|
111
|
+
fixed-size binary) are charged their Arrow width per value, plus validity, list
|
|
112
|
+
offsets, and per-batch array overhead, so compact wide tables such as 100,000
|
|
113
|
+
rows across 90 boolean columns fit the default guard. Variable-width leaves
|
|
114
|
+
(strings, binaries, dictionaries) keep a conservative allowance of twice the
|
|
115
|
+
uncompressed page bytes plus 16 bytes per value, so string-heavy files can still
|
|
116
|
+
be rejected below the byte, row, and column caps. The row, column,
|
|
117
|
+
input-byte, and decoded-byte limits are independent ceilings, not a promise that
|
|
118
|
+
every file below the first three will load. Retained Arrow allocations are also
|
|
119
|
+
checked after each decoded batch. That check counts decoder buffer capacity,
|
|
120
|
+
which can reach twice the data of a numeric column with nulls, so a file the
|
|
121
|
+
footer estimate admits can still be rejected. These are admission limits, not a
|
|
122
|
+
process memory sandbox: dictionaries, decoder batches, summaries, copies, and
|
|
123
|
+
temporary allocations add memory. Raising `maxDecodedBytes` relaxes both the
|
|
124
|
+
Parquet estimate and retained-allocation checks; hosts should do so only with an
|
|
125
|
+
appropriate memory budget.
|
|
126
|
+
|
|
127
|
+
This API materializes a complete file. Virtual scrolling bounds rendered DOM,
|
|
128
|
+
not the loaded dataset. Sorting, filtering, and summaries cover all accepted
|
|
129
|
+
rows. There is no disk paging or sampled preview. Larger files need a separate
|
|
130
|
+
bounded-preview or query architecture with explicit operation scope.
|
|
131
|
+
|
|
132
|
+
After filtering, binary numeric ratio bars retain the unfiltered file's two-value
|
|
133
|
+
baseline; nearby counts and null statistics describe the filtered rows.
|
|
134
|
+
|
|
135
|
+
Arrow/Parquet schemas and nulls are retained in WASM. Lists, structs, and map-like
|
|
136
|
+
values may display as text; known image structures have dedicated rendering.
|
|
137
|
+
Nested values do not become editable sub-tables, and a formatted nested column's
|
|
138
|
+
ordering/filtering is not a nested query language. Do not assume all nested types
|
|
139
|
+
have numeric or categorical semantics identical to primitive columns.
|
|
140
|
+
|
|
141
|
+
## Lifecycle and host controls
|
|
142
|
+
|
|
143
|
+
A `TableData` instance returned by `loadTableFile` owns one WASM store. The React
|
|
144
|
+
loader source creates a fresh store for each setup and discards stale completions;
|
|
145
|
+
the mounted engine disposes the store on teardown. Avoid passing preloaded binary
|
|
146
|
+
data directly to the React `data` prop, because effect replay would reuse a freed
|
|
147
|
+
store. For the imperative API, pass each result to one `createTable` instance. If
|
|
148
|
+
an imperative load is stale or never mounted, call `data.dispose?.()`, using an
|
|
149
|
+
activation token to recognize results completed after switching or closing files.
|
|
150
|
+
Reopen/reload creates fresh data. Do not share disposable data between tables.
|
|
151
|
+
|
|
152
|
+
Sift is a read-only exploration surface. Sorting, filtering, and type casts do
|
|
153
|
+
not rewrite the file. Keep editor text and dirty state in the host; a viewer/editor
|
|
154
|
+
toggle should derive its preview from the current text buffer and preserve edits
|
|
155
|
+
on parse errors or mode changes. Save, Save As/export, reveal-in-folder, file
|
|
156
|
+
watching, dirty-file conflict handling, and loading/error messages remain host
|
|
157
|
+
responsibilities. Parquet can use a view-only mode.
|
|
158
|
+
|
|
159
|
+
For already hosted data, `<SiftTable url="/data.arrow" />` and
|
|
160
|
+
`<SiftTable url="/data.parquet" />` remain available. The URL/manifest paths have
|
|
161
|
+
different loading behavior and do not inherit `loadTableFile` admission limits.
|
|
162
|
+
A sampled Arrow manifest must include its `summary.sampled` and included/total
|
|
163
|
+
row metadata; its sorting, filtering, and summaries cover only the supplied rows.
|
|
164
|
+
|
|
165
|
+
## Interaction and appearance
|
|
166
|
+
|
|
167
|
+
```ts
|
|
168
|
+
engine.setSort('age', 'desc')
|
|
169
|
+
engine.setFilter(0, { kind: 'range', min: 18, max: 65 })
|
|
170
|
+
engine.clearAllFilters()
|
|
171
|
+
const state = engine.getState()
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
The container needs a defined height. The table supplies keyboard navigation and
|
|
175
|
+
ARIA grid semantics; give the surrounding file view an accessible title, expose
|
|
176
|
+
loading/errors to assistive technology, and keep keyboard focus predictable when
|
|
177
|
+
switching modes. Test the host's narrow view and keyboard paths.
|
|
178
|
+
|
|
179
|
+
`style.css` is compiled: consumers do not need Tailwind or nteract source files.
|
|
180
|
+
It includes shared base styles and design-token defaults, so load it before host
|
|
181
|
+
theme overrides or use an existing isolated document boundary. Set
|
|
182
|
+
`data-theme="dark"`/`"light"` explicitly on the root; OS theme preference is not
|
|
183
|
+
a separate automatic mode. `data-color-theme="cream"` selects the optional cream
|
|
184
|
+
palette. Override `--sift-bg`, `--sift-panel`, `--sift-ink`, `--sift-muted`,
|
|
185
|
+
`--sift-rule`, and `--sift-accent` to match the host. Popovers render in portals;
|
|
186
|
+
theme tokens should be available at their document root too.
|
|
187
|
+
|
|
188
|
+
## Build and verify a local package
|
|
189
|
+
|
|
190
|
+
From the nteract repository root:
|
|
191
|
+
|
|
192
|
+
```sh
|
|
193
|
+
pnpm install --frozen-lockfile
|
|
194
|
+
cargo xtask wasm sift --skip-renderer-plugins
|
|
195
|
+
pnpm --dir packages/sift test:package
|
|
196
|
+
# Optional: production consumer smoke (install with pnpm exec playwright install chromium).
|
|
197
|
+
pnpm --dir packages/sift exec node scripts/test-package.mjs --browser
|
|
198
|
+
pnpm --dir packages/sift pack --pack-destination /tmp/sift-package
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
`test:package` builds the library, packs it, extracts it outside the workspace,
|
|
202
|
+
checks its public declarations and dependency boundary, and tests the shipped
|
|
203
|
+
WASM glue/binary against synthetic Arrow data. With `--browser`, it builds and
|
|
204
|
+
previews a production consumer in Chromium, testing both explicit and default
|
|
205
|
+
WASM asset URLs. It reuses installed public
|
|
206
|
+
dependencies without registry requests. `prepack` rejects missing built assets,
|
|
207
|
+
checks every current runtime method against the actual WASM and JavaScript
|
|
208
|
+
exports, and instantiates the pair to reject incompatible glue/binary imports.
|
|
209
|
+
The resulting tarball can be installed via its local path; nothing is published.
|
|
210
|
+
|
|
211
|
+
`build:lib` also writes `lib/THIRD_PARTY_NOTICES.md`. It lists the Rust crates
|
|
212
|
+
and C sources that `cargo tree` reports for the WASM build and the npm packages
|
|
213
|
+
the bundle inlines, with their license texts and NOTICE files. Ship it with any
|
|
214
|
+
host app that redistributes Sift. A dependency under a license the generator
|
|
215
|
+
doesn't recognize, without its license text, or with unreviewed native sources
|
|
216
|
+
fails the build until the generator learns it.
|
package/lib/LICENSE
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024, runtimed
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
16
|
+
contributors may be used to endorse or promote products derived from
|
|
17
|
+
this software without specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|