@aiquants/contact-map 0.9.0 → 0.11.0
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 +47 -23
- package/dist/client.d.mts +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/client.js +2 -2
- package/dist/client.mjs +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/dist/server.d.mts +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js +4 -4
- package/dist/server.mjs +4 -4
- package/package.json +11 -11
- /package/dist/{wire-hAxBVVH6.d.mts → wire-CVZNwmQx.d.mts} +0 -0
- /package/dist/{wire-hAxBVVH6.d.ts → wire-CVZNwmQx.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -33,8 +33,8 @@ Reusable, host-agnostic business contact map and corporate directory feature pac
|
|
|
33
33
|
- **Server Layer (`@aiquants/contact-map/server`)**:
|
|
34
34
|
- Dependency Injection (DI) port architecture decouples database connections, schemas, authentication, and loggers from host apps.
|
|
35
35
|
- DB接続、スキーマ、認証、ロガーをホストアプリから疎結合化する DI ポート設計。
|
|
36
|
-
- Streaming keyset pagination handler (`createContactMapStreamHandler`)
|
|
37
|
-
-
|
|
36
|
+
- Streaming keyset pagination handler (`createContactMapStreamHandler`) whose resume cursor keeps `contacted_at` to the 100 ns of `datetime2(7)`, so no row at a chunk boundary is skipped or sent twice.
|
|
37
|
+
- 再開カーソルが `contacted_at` を `datetime2(7)` の 100 ns まで保ち、チャンクの境界の行を読み飛ばしも重複もしないストリーミングキーセットパジネーションハンドラー。
|
|
38
38
|
|
|
39
39
|
---
|
|
40
40
|
|
|
@@ -105,12 +105,26 @@ export async function loader({ request }: { request: Request }) {
|
|
|
105
105
|
}
|
|
106
106
|
```
|
|
107
107
|
|
|
108
|
-
`db`, `table`, `ensureConnection` and `authenticate` are required, and `createContactMapStreamHandler` / `createContactMapServer` throw a `TypeError` when `db` or `table` is missing, `
|
|
109
|
-
|
|
108
|
+
`db`, `table`, `ensureConnection` and `authenticate` are required, and `createContactMapStreamHandler` / `createContactMapServer` throw a `TypeError` when `db` or `table` is missing, `table.contacted_at` is missing or is not a Drizzle column, `ensureConnection` or `authenticate` is not a function, or `firstBatchSize` / `nextBatchSize` is given but is not a number.
|
|
109
|
+
They throw a `RangeError` when `table.contacted_at` is not a `datetime2` column (`datetime2` or `datetime2(0)` to `datetime2(7)`; a `datetime`, `datetimeoffset` or `date` column is refused) or `firstBatchSize` or `nextBatchSize` is a number but not an integer from 1 to `Number.MAX_SAFE_INTEGER`.
|
|
110
|
+
Each message names the setting and ends with the value given (`[contact-map] server config authenticate must be the function that returns the request's user (…); got undefined`, `[contact-map] server config table.contacted_at must be a Drizzle datetime2 column; got "datetime"`). A stream open to everyone says so with an `authenticate` that returns a user; leaving the setting out never serves the contacts unauthenticated.
|
|
110
111
|
The handler calls `authenticate(request, { failureRedirect: null })` after checking the resume cursor (a malformed cursor gets 400 without authenticating), answers 401 when no user comes back, and sends a returned `cookie` as `Set-Cookie` on the 401 and on the stream response alike, so a session the call refreshed reaches the browser. The stream is sent with `Cache-Control: no-store, no-transform`.
|
|
111
112
|
|
|
112
|
-
|
|
113
|
-
|
|
113
|
+
The resume cursor (`StreamCursor`: each chunk line's `nextCursor`, sent back as `cursor_contacted_at` / `cursor_person_id`) is written by the server and opaque to clients. Its `contacted_at` is the last row's value in UTC with exactly 7 fractional digits (`YYYY-MM-DDThh:mm:ss.fffffffZ`, the 100 ns of `datetime2(7)`), read from the database as text so that no digit is lost to the driver's millisecond `Date`, or `null` once the stream has reached the rows without one; its `person_id` is the last row's id, any safe integer (a signed key may be negative).
|
|
114
|
+
The chunk query checks both values by the rules below when it writes the cursor, so the next request accepts every cursor the server writes; a chunk whose last row's `person_id` is not a safe integer fails with an error naming the value.
|
|
115
|
+
The handler accepts only that form naming a real instant from year 1 on and a `cursor_person_id` holding a safe integer written in canonical decimal (`0`, or digits without a leading zero after an optional minus sign); anything else (`-0`, `+5`, `05`, `1e3`, …) gets 400 before authenticating.
|
|
116
|
+
The next chunk compares the bare column with the cursor cast to `datetime2(7)`, so an index on (`is_active`, `contacted_at`, `person_id`) can seek. `createContactMapServer().getContactsStreamChunk(cursor)` checks the cursor by the same rules and throws a `TypeError` (a value of the wrong type or shape) or a `RangeError` (any other form) before connecting.
|
|
117
|
+
`ContactMapStreamClient` sends the cursor back unchanged. When a resumed request gets 400 (the cursor was written by a server of another version), it drops the cursor and loads from the beginning again once, keeping the records it has (they are keyed by `person_id`); a 400 to a request without a cursor, or a second 400 in the same load, ends the load at once with `[contact-map] the server rejected the stream request (400); reload the page`.
|
|
118
|
+
A 401 or 403 ends the load at once in phase `auth-required` with the error `Authentication required`, without retrying (`retryNow()` starts again from the last cursor, for example after the user signs in again). Any other failed response is retried with backoff and sets the error to `[contact-map] the stream request failed (status <status>)`.
|
|
119
|
+
|
|
120
|
+
`db`・`table`・`ensureConnection`・`authenticate` は必須で、`db` か `table` が無い、`table.contacted_at` が無いか Drizzle の列でない、`ensureConnection` か `authenticate` が関数でない、または `firstBatchSize` / `nextBatchSize` が数値でなければ `createContactMapStreamHandler` / `createContactMapServer` は `TypeError` を、`table.contacted_at` が `datetime2` の列 (`datetime2` か `datetime2(0)` から `datetime2(7)`。`datetime`・`datetimeoffset`・`date` の列は断る) でないか、`firstBatchSize` か `nextBatchSize` が 1 から `Number.MAX_SAFE_INTEGER` までの整数でない数値なら `RangeError` を投げる。
|
|
121
|
+
どの文言も設定を名指し、与えた値で終わる (`[contact-map] server config authenticate must be the function that returns the request's user (…); got undefined`、`[contact-map] server config table.contacted_at must be a Drizzle datetime2 column; got "datetime"`)。誰にでも開くストリームは user を返す `authenticate` で明示し、設定を書き漏らしても認証なしで連絡先を配ることはない。ハンドラーは再開カーソルを検査してから (不正な形は認証せずに 400) `authenticate(request, { failureRedirect: null })` を呼び、user が無ければ 401 を返し、返された `cookie` は 401 にもストリームの応答にも `Set-Cookie` で載せる (呼び出しが更新したセッションをブラウザへ届ける)。ストリームは `Cache-Control: no-store, no-transform` で送る。
|
|
122
|
+
|
|
123
|
+
再開カーソル (`StreamCursor`。各チャンク行の `nextCursor` で、`cursor_contacted_at` / `cursor_person_id` として送り返す) はサーバーが書き、クライアントにとって形は不透明。`contacted_at` は最後の行の値を UTC で小数部ちょうど 7 桁 (`YYYY-MM-DDThh:mm:ss.fffffffZ`、`datetime2(7)` の 100 ns) で表したもので、ドライバのミリ秒までの `Date` で桁を落とさないようデータベースから文字列で読む。日時の無い行へ進んだ後は `null`。`person_id` は最後の行の ID で、負を含む任意の安全な整数 (符号付きのキーは負にもなる)。
|
|
124
|
+
チャンクの照会はカーソルを書くときに両方の値を下の規則で確かめるので、サーバーが書いたカーソルは次の要求が必ず受け入れる。最後の行の `person_id` が安全な整数でないチャンクは、その値を示すエラーで失敗する。
|
|
125
|
+
ハンドラーは 1 年以降の実在する日時を表すこの形と、安全な整数を正規の 10 進 (`0` か、省略できる負の符号に続く先頭が 0 でない数字) で書いた `cursor_person_id` だけを受け入れ、それ以外 (`-0`・`+5`・`05`・`1e3` など) は認証の前に 400 で断る。次のチャンクは素の列と `datetime2(7)` へ CAST したカーソルを比べるので、(`is_active`, `contacted_at`, `person_id`) の索引でシークできる。`createContactMapServer().getContactsStreamChunk(cursor)` も同じ規則でカーソルを検査し、接続の前に `TypeError` (型や形の誤り) か `RangeError` (それ以外の形) を投げる。
|
|
126
|
+
`ContactMapStreamClient` はカーソルをそのまま送り返す。再開した要求が 400 を受けたら (別の版のサーバーが書いたカーソル)、カーソルを捨てて最初から 1 回だけ読み直し、受信済みのレコードは残す (`person_id` で重ねる)。カーソルの無い要求への 400 と、同じ読み込みでの 2 回目の 400 は、`[contact-map] the server rejected the stream request (400); reload the page` で即座に読み込みを終える。
|
|
127
|
+
401 と 403 は再試行せず、段階 `auth-required`・エラー `Authentication required` で即座に読み込みを終える (`retryNow()` で最終カーソルから読み直す。たとえば再ログインの後)。それ以外の失敗の応答はバックオフで再試行し、エラーを `[contact-map] the stream request failed (status <status>)` にする。
|
|
114
128
|
|
|
115
129
|
### 2. Client Page Setup / クライアント側ページの設定
|
|
116
130
|
|
|
@@ -173,26 +187,36 @@ Worker を作れないか Worker が落ちると、250 ms 後と 500 ms 後の 2
|
|
|
173
187
|
|
|
174
188
|
## Search Normalization / 検索語の正規化
|
|
175
189
|
|
|
176
|
-
The search
|
|
190
|
+
The search box reads its text as keywords. Each whitespace-separated word is a keyword of its own, and the words between two quotation marks (`"`, `"`, `“`, `”`; any of them opens or closes a group, and a group left open runs to the end) are one keyword.
|
|
191
|
+
The page searches every keyword with `@aiquants/fuzzy-search`: `useFuzzySearch`'s `querySetsOf` reads the term with `parseQuerySets`, and `FuzzySearchManager.searchSets` searches one query set per keyword. The AND / OR button next to the search box combines the keywords' answers: AND keeps the contacts every keyword finds (intersection), OR the contacts any keyword finds (union). The button starts at OR, and switching it searches the current term again without rebuilding the index.
|
|
192
|
+
A quoted keyword is matched by fuzzy-search's multi-word matching, whose operator is the settings tab's "Operator for words inside quotes" select (`multiTermOperator`, AND at first): AND requires every word of the group to appear in some search field, OR does not. A keyword of one word matches the same under either operator.
|
|
193
|
+
A "Maximum results" cap of the index or Levenshtein settings (no limit at first) applies to each keyword's answer before the keywords are combined, so with a cap an AND search can miss a contact that one keyword's capped answer left out.
|
|
177
194
|
|
|
178
|
-
|
|
195
|
+
The search page normalizes the typed text with `normalizeSearchInput` (exported from `@aiquants/contact-map`) into the fuzzy search term. The contact fields (name, company, department, title, email, phone numbers) are matched as stored. Every keyword is therefore only brought into a form those fields can hold:
|
|
196
|
+
|
|
197
|
+
- Invisible characters (U+200B, U+FEFF) are removed before the keywords are read, and each keyword's surrounding whitespace (U+3000 and U+00A0 included) is trimmed.
|
|
179
198
|
- Width, kana (hiragana → katakana) and case are unified with select-box's `normalizeText` (`ABC商事` → `abc商事`, `さとう` → `サトウ`). Kana stays as written (`つづき` → `ツヅキ`).
|
|
180
|
-
- The
|
|
181
|
-
- Mixed text, digits and symbols, and words that do not read completely keep their width / kana / case form (`user@example.com`, `営業部 tanaka`, `tanaka1`, `ke-su`, `sony`).
|
|
199
|
+
- The keywords are replaced by their katakana readings only when every keyword is romaji that reads completely. Each must hold only Latin letters and whitespace, and select-box's `romajiToKatakana` must leave no letter untransliterated (`tanaka` → `タナカ`, `yamada taro` → `ヤマダ タロ`, `"yamada taro" suzuki` → `"ヤマダ タロ" スズキ`, `tsuduki` → `ツヅキ`).
|
|
200
|
+
- Mixed text, digits and symbols, and words that do not read completely keep their width / kana / case form, and so does every other keyword of the text (`user@example.com`, `営業部 tanaka`, `tanaka1`, `ke-su`, `sony`, `"yamada taro" sony`).
|
|
201
|
+
- The keywords are written back with fuzzy-search's `formatQuerySets`: single spaces between them, a keyword holding whitespace in ASCII quotation marks (`"ABC 商事"` → `"abc 商事"`), and neither a blank keyword nor a keyword that normalization made equal to an earlier one. `parseQuerySets` therefore reads exactly these keywords from the term. Text without quotation marks becomes its whitespace-separated words, each normalized as above and written once, separated by single spaces.
|
|
182
202
|
|
|
183
|
-
The result highlight and the exact-match ranking are one derivation from the
|
|
184
|
-
`HighlightedText` marks its matches, and `createExactMatchRanker(query, fields)` moves the results with a match in one of the fields to the top, keeping the fuzzy order within each group. A field is therefore highlighted exactly when it ranks its record as an exact match. A kana reading is marked only when
|
|
203
|
+
The result highlight and the exact-match ranking are one derivation from the text as typed. `createSearchQueryPattern(query)` finds the spellings that `getSearchQuerySpellings(query)` lists (select-box's `getNormalizedVariants` of each word of the text's keywords and of its normalized form's keywords, read with fuzzy-search's `parseQuerySets`, so a quotation mark is never part of a spelling), longest first and case-insensitively.
|
|
204
|
+
`HighlightedText` marks its matches, and `createExactMatchRanker(query, fields)` moves the results with a match in one of the fields to the top, keeping the fuzzy order within each group. A field is therefore highlighted exactly when it ranks its record as an exact match. A kana reading is marked only when every keyword reads as romaji.
|
|
185
205
|
|
|
186
206
|
The typed query is used because normalization can drop a spelling it holds. select-box reads a prolonged sound mark that follows no kana as a hyphen, so `ーヒー` (the middle of `コーヒー`) becomes the search term `-ヒー`, while the highlight and the ranking still find `ーヒー`. The search outlet context carries both: `searchQuery` (as typed) and `searchTerm` (`normalizeSearchInput(searchQuery)`). The select-box peer range is ^0.11.0, expanded from `workspace:^` at publish.
|
|
187
207
|
|
|
188
|
-
|
|
208
|
+
検索欄はテキストをキーワードとして読む。空白で区切った語はそれぞれ 1 つのキーワードで、2 つの引用符 (`"`・`"`・`“`・`”`。どれでも組を開き閉じ、開いたままの組は終わりまで続く) の間の語はまとめて 1 つのキーワード。ページはどのキーワードも `@aiquants/fuzzy-search` で検索する: `useFuzzySearch` の `querySetsOf` が `parseQuerySets` で検索語を読み、`FuzzySearchManager.searchSets` がキーワードごとに 1 つの問い合わせのセットを検索する。検索欄の隣の AND / OR ボタンはキーワードの答えをまとめ、AND はどのキーワードも見つけた連絡先 (積集合)、OR はどれかのキーワードが見つけた連絡先 (和集合) を残す。ボタンは OR で始まり、切り替えると索引を建て直さずに今の検索語を検索し直す。
|
|
209
|
+
引用符で囲んだキーワードは fuzzy-search の複数語の照合で照合し、その演算子は設定タブの「引用符の中の語の演算子」セレクト (`multiTermOperator`。最初は AND): AND は組のどの語もいずれかの検索フィールドに現れることを求め、OR は求めない。1 語のキーワードはどちらの演算子でも同じに照合する。
|
|
210
|
+
|
|
211
|
+
検索ページは入力されたテキストを `normalizeSearchInput` (`@aiquants/contact-map` から公開) で正規化し、あいまい検索の検索語にする。連絡先のフィールド (氏名・会社・部署・役職・メール・電話番号) は保存されたままの値で照合する。そのため各キーワードは、それらのフィールドが持ちうる形に揃えるだけ:
|
|
189
212
|
|
|
190
|
-
-
|
|
213
|
+
- キーワードを読む前に不可視文字 (U+200B・U+FEFF) を除き、各キーワードの端の空白 (U+3000・U+00A0 を含む) を除く。
|
|
191
214
|
- select-box の `normalizeText` で全角/半角・かな (ひらがな → カタカナ)・大文字小文字を統一する (`ABC商事` → `abc商事`、`さとう` → `サトウ`)。かなは書いたまま (`つづき` → `ツヅキ`)。
|
|
192
|
-
-
|
|
193
|
-
-
|
|
215
|
+
- どのキーワードも完全に読めるローマ字のときだけ、各キーワードをカタカナの読みに置き換える。どれもラテン文字と空白だけで、select-box の `romajiToKatakana` が音訳しない文字を残さないことが条件 (`tanaka` → `タナカ`、`yamada taro` → `ヤマダ タロ`、`"yamada taro" suzuki` → `"ヤマダ タロ" スズキ`、`tsuduki` → `ツヅキ`)。
|
|
216
|
+
- 混在テキスト・数字や記号・完全には読めない語は全角/半角・かな・大文字小文字の形のままで、そのテキストのほかのキーワードも同じ (`user@example.com`、`営業部 tanaka`、`tanaka1`、`ke-su`、`sony`、`"yamada taro" sony`)。
|
|
217
|
+
- キーワードは fuzzy-search の `formatQuerySets` で書き戻す: キーワードの間は 1 つの空白、空白を持つキーワードは ASCII の引用符で囲み (`"ABC 商事"` → `"abc 商事"`)、空のキーワードと、正規化で先のキーワードと等しくなったキーワードは書かない。そのため `parseQuerySets` は検索語からちょうどこれらのキーワードを読む。引用符の無いテキストは、空白で区切った各語を上のとおり正規化して 1 度ずつ並べ、1 つの空白で区切ったものになる。
|
|
194
218
|
|
|
195
|
-
|
|
219
|
+
検索結果のハイライトと完全一致による並べ替えは、入力されたままのテキストからの 1 つの導出。`createSearchQueryPattern(query)` は `getSearchQuerySpellings(query)` が並べる表記 (テキストのキーワードとその正規化形のキーワードの各語に対する select-box の `getNormalizedVariants`。語は fuzzy-search の `parseQuerySets` で読むため、引用符は表記の一部にならない) を、最長のものから大文字小文字を区別せずに探す。`HighlightedText` はその一致に印を付け、`createExactMatchRanker(query, fields)` はいずれかのフィールドに一致を持つ結果を先頭へ移す (各グループ内ではあいまい検索の順序を保つ)。そのため、フィールドにハイライトが付くのは、そのフィールドがレコードを完全一致として並べさせるときちょうど。かなの読みに印が付くのはどのキーワードもローマ字として読めるときだけ。
|
|
196
220
|
|
|
197
221
|
入力されたままの検索語を使うのは、正規化が検索語の持つ表記を落とすことがあるため。select-box はかなに続かない長音記号をハイフンと読むので、`ーヒー` (`コーヒー` の途中) は検索語 `-ヒー` になるが、ハイライトと並べ替えは `ーヒー` を探し続ける。検索のアウトレットコンテキストは両方を運ぶ: `searchQuery` (入力されたまま) と `searchTerm` (`normalizeSearchInput(searchQuery)`)。select-box のピア範囲は ^0.11.0 (公開時に `workspace:^` から展開)。
|
|
198
222
|
|
|
@@ -242,7 +266,7 @@ export default function ContactMapRoute() {
|
|
|
242
266
|
- An own key outside `CONTACT_MAP_LABEL_KEYS` throws a short `RangeError` that suggests the nearest key (`[contact-map] labels has a key that is not a label key (did you mean "searchTab"? CONTACT_MAP_LABEL_KEYS lists every key); got "serchTab"`).
|
|
243
267
|
- A string key must be a string (else a `TypeError`) with non-whitespace content (else a `RangeError`); a function key (the keys shown with arguments in the table below) must be a function (else a `TypeError`). An explicit `undefined` keeps the catalog value.
|
|
244
268
|
- Every error the package throws starts with `[contact-map]`, with one exception: a cancelled query (`countActiveContactsQuery`, `getContactsStreamChunkQuery`) rejects with the standard `DOMException` named `AbortError`, as `fetch` does, so tell a cancellation by `error.name === "AbortError"`.
|
|
245
|
-
- A setting check (`locale`, `labels`, `streamEndpoint`, `workerUrls`, the server config, row counts, tree names) throws a `TypeError` for a value of the wrong type or shape, a missing required setting included, and a `RangeError` for a value of the right type that is not allowed, a key the setting does not take included.
|
|
269
|
+
- A setting check (`locale`, `labels`, `streamEndpoint`, `workerUrls`, the server config, row counts, the resume cursor given to `getContactsStreamChunkQuery` or `createContactMapServer().getContactsStreamChunk` (both named `getContactsStreamChunkQuery cursor` in the message), tree names) throws a `TypeError` for a value of the wrong type or shape, a missing required setting included, and a `RangeError` for a value of the right type that is not allowed, a key the setting does not take included.
|
|
246
270
|
It names the setting as the surface calls it (`labels`, `ContactMapAppView labels`, `server config firstBatchSize`), and it ends with `; got <value>`: the rejected value, or the rejected key, written the same way everywhere (a quoted string, `undefined`, `null`, `-0`, `10n`, `Symbol(x)`, `[object URL]`).
|
|
247
271
|
- Two views of one browser tab that disagree on `streamEndpoint` or `workerUrls.treeWorker`, and a CommonJS build without `workerUrls.treeWorker`, throw a plain `Error` (no single value is wrong).
|
|
248
272
|
- A unit key (`recordUnit`, `companyUnit`, `resultUnit`, `timesUnit`, `itemsUnit`, `charactersUnit`) receives the number exactly as it is displayed (`"1"`, `"1,001"`, `"1.0"`), so the English singular / plural follows what the reader sees: only a displayed `"1"` is singular (`"1.0 items"`). `timesUnit` / `itemsUnit` / `charactersUnit` / `throughputUnit` are appended to the number without a separator and carry their own leading space.
|
|
@@ -253,7 +277,7 @@ export default function ContactMapRoute() {
|
|
|
253
277
|
- `CONTACT_MAP_LABEL_KEYS` 外の自身のキーは、最も近いキーを示す短い `RangeError` (`[contact-map] labels has a key that is not a label key (did you mean "searchTab"? CONTACT_MAP_LABEL_KEYS lists every key); got "serchTab"`)。
|
|
254
278
|
- 文字列キーは文字列 (でなければ `TypeError`) で空白以外を含むこと (でなければ `RangeError`)、関数キー (下表で引数付きのキー) は関数であること (でなければ `TypeError`) が必須。明示 `undefined` はカタログ値のまま。
|
|
255
279
|
- パッケージが投げる例外は全て `[contact-map]` で始まる。例外は 1 つで、取り消した照会 (`countActiveContactsQuery`・`getContactsStreamChunkQuery`) は `fetch` と同じく名前が `AbortError` の標準の `DOMException` で拒否するので、取消は `error.name === "AbortError"` で見分ける。
|
|
256
|
-
- 設定の検査 (`locale`・`labels`・`streamEndpoint`・`workerUrls
|
|
280
|
+
- 設定の検査 (`locale`・`labels`・`streamEndpoint`・`workerUrls`・サーバーの設定・行数・`getContactsStreamChunkQuery` か `createContactMapServer().getContactsStreamChunk` に渡す再開カーソル (文言ではどちらも `getContactsStreamChunkQuery cursor`)・代替名) は、型や形の誤り (必須の設定が無い場合を含む) を `TypeError`、型は合うが許されない値 (設定が受け取らないキーを含む) を `RangeError` にする。設定は面の呼び名で名指し (`labels`・`ContactMapAppView labels`・`server config firstBatchSize`)、末尾は `; got <値>` で、拒否した値か拒否したキーをどこでも同じ表記で書く (引用符付きの文字列・`undefined`・`null`・`-0`・`10n`・`Symbol(x)`・`[object URL]`)。
|
|
257
281
|
- ブラウザのタブの 2 つのビューが `streamEndpoint` か `workerUrls.treeWorker` で食い違う場合と、`workerUrls.treeWorker` の無い CommonJS のビルドは、どの値 1 つが誤りでもないので素の `Error`。
|
|
258
282
|
- 単位キー (`recordUnit`、`companyUnit`、`resultUnit`、`timesUnit`、`itemsUnit`、`charactersUnit`) は表示どおりの数値文字列 (`"1"`、`"1,001"`、`"1.0"`) を受け取るため、英語の単数 / 複数は読み手が見る値に従う (単数は表示 `"1"` のときだけで `"1.0 items"`)。`timesUnit` / `itemsUnit` / `charactersUnit` / `throughputUnit` は数値の直後に区切りなしで連結されるため、先頭の空白は単位側が持つ。
|
|
259
283
|
- エンジン 7 キーと行種別語 2 キーも、`@aiquants/virtualscroll` と `@aiquants/directory-tree` へ渡す前にここで同じ規則で検査するので、その例外もパッケージの規則に従う。
|
|
@@ -437,10 +461,10 @@ Function keys are shown with their arguments; the cells show sample output (`cou
|
|
|
437
461
|
| `basicCaseSensitive` | `"Case-sensitive"` | `"大文字小文字を区別"` |
|
|
438
462
|
| `basicHighlight` | `"Highlight matches"` | `"ハイライト表示"` |
|
|
439
463
|
| `basicOpenEmailsWithGmail` | `"Open email addresses in Gmail compose"` | `"メールアドレスを Gmail の作成画面で開く"` |
|
|
440
|
-
| `basicMultiTermOperator` | `"
|
|
441
|
-
| `basicOperatorOr` | `"OR (any
|
|
442
|
-
| `basicOperatorAnd` | `"AND (all
|
|
443
|
-
| `basicMultiTermHint` | `
|
|
464
|
+
| `basicMultiTermOperator` | `"Operator for words inside quotes"` | `"引用符の中の語の演算子"` |
|
|
465
|
+
| `basicOperatorOr` | `"OR (any word matches)"` | `"OR (いずれか一致)"` |
|
|
466
|
+
| `basicOperatorAnd` | `"AND (all words match)"` | `"AND (すべて一致)"` |
|
|
467
|
+
| `basicMultiTermHint` | `'How words between quotation marks ("tanaka taro") are combined (default: AND). Words outside quotation marks are separate keywords combined by the AND / OR button'` | `'引用符で囲んだ語 ("田中 太郎") の結合方法 (既定は AND)。引用符の外の語はそれぞれ別のキーワードで、AND / OR ボタンで結合する'` |
|
|
444
468
|
| `basicSortHeading` | `"Sorting"` | `"ソート設定"` |
|
|
445
469
|
| `basicSortBy` | `"Sort by"` | `"ソート基準"` |
|
|
446
470
|
| `basicSortByScore` | `"Score"` | `"スコア"` |
|
package/dist/client.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react from "react";
|
|
2
2
|
import { CSSProperties, ReactNode, RefObject, PointerEvent, MouseEvent } from "react";
|
|
3
3
|
import { UseFuzzySearchOptions } from "@aiquants/fuzzy-search/react";
|
|
4
|
-
import { C as ContactRecord, a as ContactMapStreamPhase, b as ContactMapSearchOutletContext, c as ContactMapOutletContext, d as ContactMapLogger, S as SerializedContactStreamRow } from "./wire-
|
|
4
|
+
import { C as ContactRecord, a as ContactMapStreamPhase, b as ContactMapSearchOutletContext, c as ContactMapOutletContext, d as ContactMapLogger, S as SerializedContactStreamRow } from "./wire-CVZNwmQx.mjs";
|
|
5
5
|
import { DirectoryTreeLabels, DirectoryTreeVirtualScrollOptions } from "@aiquants/directory-tree";
|
|
6
6
|
import * as _aiquants_virtualscroll from "@aiquants/virtualscroll";
|
|
7
7
|
import { VirtualScrollLocale } from "@aiquants/virtualscroll";
|
package/dist/client.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react from "react";
|
|
2
2
|
import { CSSProperties, ReactNode, RefObject, PointerEvent, MouseEvent } from "react";
|
|
3
3
|
import { UseFuzzySearchOptions } from "@aiquants/fuzzy-search/react";
|
|
4
|
-
import { C as ContactRecord, a as ContactMapStreamPhase, b as ContactMapSearchOutletContext, c as ContactMapOutletContext, d as ContactMapLogger, S as SerializedContactStreamRow } from "./wire-
|
|
4
|
+
import { C as ContactRecord, a as ContactMapStreamPhase, b as ContactMapSearchOutletContext, c as ContactMapOutletContext, d as ContactMapLogger, S as SerializedContactStreamRow } from "./wire-CVZNwmQx.js";
|
|
5
5
|
import { DirectoryTreeLabels, DirectoryTreeVirtualScrollOptions } from "@aiquants/directory-tree";
|
|
6
6
|
import * as _aiquants_virtualscroll from "@aiquants/virtualscroll";
|
|
7
7
|
import { VirtualScrollLocale } from "@aiquants/virtualscroll";
|