@objectstack/plugin-pinyin-search 17.2.0 → 17.4.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/CHANGELOG.md +206 -0
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +13 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,211 @@
|
|
|
1
1
|
# @objectstack/plugin-pinyin-search
|
|
2
2
|
|
|
3
|
+
## 17.4.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- be92d46: These fourteen packages now declare `repository.directory`, so their npm pages carry a working "source" deep link to their own directory in the monorepo.
|
|
8
|
+
|
|
9
|
+
npm renders that field by concatenating it onto `repository.url`. None of these fourteen manifests carried a `repository` block at all, so every one of their npm pages offered no route from the package back to its code — not a broken link, no link. That is what this publishes: the block those pages read, naming each package's own directory.
|
|
10
|
+
|
|
11
|
+
Nothing else about these packages changes. No export, no runtime behaviour, no dependency and no file in the tarball other than the manifest's own `repository` key. The version bump exists because the fix is only real once it is published: the field lives in the manifest npm serves, so a corrected manifest sitting in the repository leaves the package page exactly as wrong as it was.
|
|
12
|
+
|
|
13
|
+
The rule behind it is now mechanical rather than remembered — `check:manifest-repository-directory` makes a publishable (non-private) workspace manifest declare the field naming its own directory, so a package added or moved after this cannot quietly go back to having no source link.
|
|
14
|
+
- Updated dependencies [2ed6be6]
|
|
15
|
+
- Updated dependencies [7079694]
|
|
16
|
+
- Updated dependencies [7783738]
|
|
17
|
+
- Updated dependencies [a56baa2]
|
|
18
|
+
- Updated dependencies [4b3955e]
|
|
19
|
+
- Updated dependencies [b0529e1]
|
|
20
|
+
- Updated dependencies [66dc6ab]
|
|
21
|
+
- Updated dependencies [6f94458]
|
|
22
|
+
- Updated dependencies [6e67b86]
|
|
23
|
+
- Updated dependencies [ddfbf04]
|
|
24
|
+
- Updated dependencies [65846bc]
|
|
25
|
+
- Updated dependencies [316a20f]
|
|
26
|
+
- Updated dependencies [2025b1f]
|
|
27
|
+
- Updated dependencies [33388f9]
|
|
28
|
+
- Updated dependencies [fa125f3]
|
|
29
|
+
- Updated dependencies [7778115]
|
|
30
|
+
- Updated dependencies [088f761]
|
|
31
|
+
- Updated dependencies [e9fcd6b]
|
|
32
|
+
- Updated dependencies [f9a3c32]
|
|
33
|
+
- Updated dependencies [51ae731]
|
|
34
|
+
- Updated dependencies [25a3d91]
|
|
35
|
+
- Updated dependencies [c78c918]
|
|
36
|
+
- Updated dependencies [cf9bda4]
|
|
37
|
+
- Updated dependencies [3bd9b34]
|
|
38
|
+
- Updated dependencies [d0ee598]
|
|
39
|
+
- Updated dependencies [e9fcd6b]
|
|
40
|
+
- Updated dependencies [1b6fe3f]
|
|
41
|
+
- Updated dependencies [48b0fcf]
|
|
42
|
+
- Updated dependencies [26144c2]
|
|
43
|
+
- Updated dependencies [2a3decc]
|
|
44
|
+
- Updated dependencies [cc00df2]
|
|
45
|
+
- Updated dependencies [11f848e]
|
|
46
|
+
- Updated dependencies [4771bd9]
|
|
47
|
+
- Updated dependencies [e6279dc]
|
|
48
|
+
- Updated dependencies [d4f9b2a]
|
|
49
|
+
- Updated dependencies [a727043]
|
|
50
|
+
- Updated dependencies [c5d6803]
|
|
51
|
+
- Updated dependencies [ec0a6e7]
|
|
52
|
+
- Updated dependencies [b398ad2]
|
|
53
|
+
- Updated dependencies [eddd612]
|
|
54
|
+
- Updated dependencies [3d3f60e]
|
|
55
|
+
- Updated dependencies [f89812e]
|
|
56
|
+
- Updated dependencies [6d7d740]
|
|
57
|
+
- Updated dependencies [f7ffbd6]
|
|
58
|
+
- Updated dependencies [d61d6e3]
|
|
59
|
+
- @objectstack/core@17.4.0
|
|
60
|
+
- @objectstack/objectql@17.4.0
|
|
61
|
+
- @objectstack/types@17.4.0
|
|
62
|
+
|
|
63
|
+
## 17.3.0
|
|
64
|
+
|
|
65
|
+
### Patch Changes
|
|
66
|
+
|
|
67
|
+
- ad54eb3: feat(tooling): onboard all 14 `packages/plugins/**` packages into `check:test-typecheck` (#14062)
|
|
68
|
+
|
|
69
|
+
Every plugin package now has a `tsconfig.test.json` compiled by the shared
|
|
70
|
+
`check:test-typecheck` gate, and its `typecheck` script names it. Before this,
|
|
71
|
+
the shrink-only `test-typecheck-debt.json` ratchet said **nothing** about a
|
|
72
|
+
third of the repo's runtime surface: 14 packages, 1 `tsconfig.test.json`
|
|
73
|
+
(`plugin-security`, wired directly to `tsc` rather than to the instrument), and
|
|
74
|
+
0 `check:test-typecheck` scripts.
|
|
75
|
+
|
|
76
|
+
Onboarded as a family by the director ruling of 2026-09-01 on #14062
|
|
77
|
+
(maintainer verbatim: 「同意」), which also carries the #5286 maintainer
|
|
78
|
+
authority the starting ledgers need. The smaller branch triage recommended —
|
|
79
|
+
declare the instrument's scope and re-site the two compile-time pins — was
|
|
80
|
+
recorded as considered and not taken: an instrument silent over a third of the
|
|
81
|
+
runtime surface is a hole readers generalise across, and that costs more than
|
|
82
|
+
fourteen tsconfigs.
|
|
83
|
+
|
|
84
|
+
**Measured, not assumed** (at `e80889095`, workspace closure built first). Four
|
|
85
|
+
packages carry residue and therefore a starting ledger — plugin-approvals 324
|
|
86
|
+
over 8 files, plugin-auth 94 over 10, plugin-sharing 3 over 2,
|
|
87
|
+
knowledge-ragflow 3 over 1. The other ten measure **zero** and deliberately get
|
|
88
|
+
no ledger file at all: the gate reads a missing ledger as `{ entries: {} }`, so
|
|
89
|
+
any error there is red immediately with no entry to be added to — strictly
|
|
90
|
+
stronger than a ledger holding nothing, and the call `plugin-security` had
|
|
91
|
+
already recorded for itself.
|
|
92
|
+
|
|
93
|
+
⛔ **This does not repair 345 type errors.** Per ruling item 3 it makes the
|
|
94
|
+
ratchet able to *see* them; paydown follows the ratchet's own shrink-only
|
|
95
|
+
discipline on its own cards. No test file is edited here.
|
|
96
|
+
|
|
97
|
+
Two corrections to the finding's own prose, both measured: the exclusion is
|
|
98
|
+
narrower than "no plugin package compiles its tests" — 9 of the 14 already
|
|
99
|
+
compiled their tests inside the `typecheck`-invoked build config, at zero
|
|
100
|
+
errors — and `exec-context-annotation.pin.ts` is a `.pin.ts`, which
|
|
101
|
+
`**/*.test.ts` never excluded, so its directives were already live. The pin
|
|
102
|
+
this change genuinely makes real is
|
|
103
|
+
`plugin-approvals/src/manager-org-screen-parity.contract.test.ts`, which no tsc
|
|
104
|
+
program had ever read.
|
|
105
|
+
- Updated dependencies [bd8795e]
|
|
106
|
+
- Updated dependencies [efb3513]
|
|
107
|
+
- Updated dependencies [1dcb995]
|
|
108
|
+
- Updated dependencies [655b106]
|
|
109
|
+
- Updated dependencies [101ad2c]
|
|
110
|
+
- Updated dependencies [c5a9a43]
|
|
111
|
+
- Updated dependencies [e27583e]
|
|
112
|
+
- Updated dependencies [4bd6faa]
|
|
113
|
+
- Updated dependencies [86cbe37]
|
|
114
|
+
- Updated dependencies [6a180e4]
|
|
115
|
+
- Updated dependencies [983edf1]
|
|
116
|
+
- Updated dependencies [f6fa22c]
|
|
117
|
+
- Updated dependencies [bbbac0f]
|
|
118
|
+
- Updated dependencies [dc7c226]
|
|
119
|
+
- Updated dependencies [d8024f0]
|
|
120
|
+
- Updated dependencies [8120808]
|
|
121
|
+
- Updated dependencies [0010797]
|
|
122
|
+
- Updated dependencies [c393b56]
|
|
123
|
+
- Updated dependencies [0db5520]
|
|
124
|
+
- Updated dependencies [fa5d137]
|
|
125
|
+
- Updated dependencies [3b4c56c]
|
|
126
|
+
- Updated dependencies [a81aa9d]
|
|
127
|
+
- Updated dependencies [56c093c]
|
|
128
|
+
- Updated dependencies [ba64877]
|
|
129
|
+
- Updated dependencies [30d96ab]
|
|
130
|
+
- Updated dependencies [f658793]
|
|
131
|
+
- Updated dependencies [b1b7d60]
|
|
132
|
+
- Updated dependencies [0fd4899]
|
|
133
|
+
- Updated dependencies [9a71af3]
|
|
134
|
+
- Updated dependencies [c3c72a4]
|
|
135
|
+
- Updated dependencies [7bd6447]
|
|
136
|
+
- Updated dependencies [86df0c9]
|
|
137
|
+
- Updated dependencies [5a22dd7]
|
|
138
|
+
- Updated dependencies [0a8ebf3]
|
|
139
|
+
- Updated dependencies [34ce8e7]
|
|
140
|
+
- Updated dependencies [8542bd4]
|
|
141
|
+
- Updated dependencies [2af5eac]
|
|
142
|
+
- Updated dependencies [c34f693]
|
|
143
|
+
- Updated dependencies [00ff228]
|
|
144
|
+
- Updated dependencies [33681ea]
|
|
145
|
+
- Updated dependencies [bfe13c8]
|
|
146
|
+
- Updated dependencies [0fb3044]
|
|
147
|
+
- Updated dependencies [4635f3e]
|
|
148
|
+
- Updated dependencies [fd289be]
|
|
149
|
+
- Updated dependencies [ee3595c]
|
|
150
|
+
- Updated dependencies [b2eab95]
|
|
151
|
+
- Updated dependencies [6aea1f5]
|
|
152
|
+
- Updated dependencies [d395692]
|
|
153
|
+
- Updated dependencies [2d5cee3]
|
|
154
|
+
- Updated dependencies [af56546]
|
|
155
|
+
- Updated dependencies [bd0c5cc]
|
|
156
|
+
- Updated dependencies [a17da05]
|
|
157
|
+
- Updated dependencies [a8c00e2]
|
|
158
|
+
- Updated dependencies [a8fac3a]
|
|
159
|
+
- Updated dependencies [22e5236]
|
|
160
|
+
- Updated dependencies [e5ce2ed]
|
|
161
|
+
- Updated dependencies [aaa4e65]
|
|
162
|
+
- Updated dependencies [b8562ff]
|
|
163
|
+
- Updated dependencies [3a86a65]
|
|
164
|
+
- Updated dependencies [4cda78c]
|
|
165
|
+
- Updated dependencies [7085f90]
|
|
166
|
+
- Updated dependencies [dee4dd4]
|
|
167
|
+
- Updated dependencies [c351a84]
|
|
168
|
+
- Updated dependencies [9086761]
|
|
169
|
+
- Updated dependencies [c5b9ccc]
|
|
170
|
+
- Updated dependencies [7131f12]
|
|
171
|
+
- Updated dependencies [159e05e]
|
|
172
|
+
- Updated dependencies [2cf5a96]
|
|
173
|
+
- Updated dependencies [8ce628a]
|
|
174
|
+
- Updated dependencies [33184fd]
|
|
175
|
+
- Updated dependencies [7c41693]
|
|
176
|
+
- Updated dependencies [b72db01]
|
|
177
|
+
- Updated dependencies [9688f58]
|
|
178
|
+
- Updated dependencies [556ebc1]
|
|
179
|
+
- Updated dependencies [b003cf2]
|
|
180
|
+
- Updated dependencies [356bd71]
|
|
181
|
+
- Updated dependencies [878aa2e]
|
|
182
|
+
- Updated dependencies [3f64fe6]
|
|
183
|
+
- Updated dependencies [fe72aa5]
|
|
184
|
+
- Updated dependencies [bc5156f]
|
|
185
|
+
- Updated dependencies [5700d83]
|
|
186
|
+
- Updated dependencies [df657d9]
|
|
187
|
+
- Updated dependencies [9c7d9d4]
|
|
188
|
+
- Updated dependencies [21196cf]
|
|
189
|
+
- Updated dependencies [a548550]
|
|
190
|
+
- Updated dependencies [49f0dcf]
|
|
191
|
+
- Updated dependencies [90ff957]
|
|
192
|
+
- Updated dependencies [db8c288]
|
|
193
|
+
- Updated dependencies [0e5fe7f]
|
|
194
|
+
- Updated dependencies [add4360]
|
|
195
|
+
- Updated dependencies [a11c1a5]
|
|
196
|
+
- Updated dependencies [f7b25c5]
|
|
197
|
+
- Updated dependencies [e49d988]
|
|
198
|
+
- Updated dependencies [87ad30c]
|
|
199
|
+
- Updated dependencies [9d7f725]
|
|
200
|
+
- Updated dependencies [3c1bbd2]
|
|
201
|
+
- Updated dependencies [9735662]
|
|
202
|
+
- Updated dependencies [4d5b4f8]
|
|
203
|
+
- Updated dependencies [5d16379]
|
|
204
|
+
- Updated dependencies [aa0688a]
|
|
205
|
+
- @objectstack/objectql@17.3.0
|
|
206
|
+
- @objectstack/core@17.3.0
|
|
207
|
+
- @objectstack/types@17.3.0
|
|
208
|
+
|
|
3
209
|
## 17.2.0
|
|
4
210
|
|
|
5
211
|
### Patch Changes
|
package/dist/index.d.mts
CHANGED
|
@@ -30,7 +30,7 @@ interface PinyinSearchPluginOptions {
|
|
|
30
30
|
declare class PinyinSearchPlugin implements Plugin {
|
|
31
31
|
name: string;
|
|
32
32
|
version: string;
|
|
33
|
-
type:
|
|
33
|
+
type: "standard";
|
|
34
34
|
dependencies: string[];
|
|
35
35
|
private readonly options;
|
|
36
36
|
constructor(options?: PinyinSearchPluginOptions);
|
package/dist/index.d.ts
CHANGED
|
@@ -30,7 +30,7 @@ interface PinyinSearchPluginOptions {
|
|
|
30
30
|
declare class PinyinSearchPlugin implements Plugin {
|
|
31
31
|
name: string;
|
|
32
32
|
version: string;
|
|
33
|
-
type:
|
|
33
|
+
type: "standard";
|
|
34
34
|
dependencies: string[];
|
|
35
35
|
private readonly options;
|
|
36
36
|
constructor(options?: PinyinSearchPluginOptions);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/pinyin-search-plugin.ts","../src/companion-projection.ts","../src/pinyin.ts"],"sourcesContent":["// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\nexport { PinyinSearchPlugin } from './pinyin-search-plugin.js';\nexport type { PinyinSearchPluginOptions } from './pinyin-search-plugin.js';\nexport {\n bindSearchCompanionHooks,\n backfillSearchCompanion,\n rebuildSearchCompanion,\n PINYIN_SEARCH_HOOK_PACKAGE,\n} from './companion-projection.js';\nexport type {\n CompanionBackfillOptions,\n CompanionBackfillResult,\n} from './companion-projection.js';\nexport { computeSearchCompanionValue } from './pinyin.js';\n","// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * PinyinSearchPlugin (#2486) — pinyin recall for `$search`.\n *\n * Pure hook plugin: the `__search` companion column is declared at object\n * compile time by the SchemaRegistry (gated on the SAME\n * `OS_SEARCH_PINYIN_ENABLED` decision point), the engine ORs it into the\n * `$search` filter, and this plugin fills the value:\n *\n * - before-save hooks: recompute full pinyin + initials of the\n * display/name field when it changes;\n * - boot backfill (`kernel:bootstrapped`): fill rows that predate the\n * switch or arrived via hook-bypassing writes;\n * - `rebuildSearchCompanion` (exported): explicit reconcile/rebuild entry.\n *\n * When the flag is off the plugin is inert: no hooks, no backfill, and\n * `pinyin-pro` is never imported.\n */\n\n// `IObjectQLEngine` via the core barrel, which re-exports it from\n// `@objectstack/spec/contracts`: this package does not depend on spec directly,\n// and the slot's contract is not a reason to add a dependency.\nimport type { IObjectQLEngine, Plugin, PluginContext } from '@objectstack/core';\nimport { resolveSearchPinyinEnabled } from '@objectstack/types';\nimport {\n bindSearchCompanionHooks,\n backfillSearchCompanion,\n} from './companion-projection.js';\n\nexport interface PinyinSearchPluginOptions {\n /**\n * Force-enable/disable regardless of `OS_SEARCH_PINYIN_ENABLED` (tests /\n * embedders). Default: `resolveSearchPinyinEnabled()`.\n */\n enabled?: boolean;\n /** Skip the boot backfill (default: run it once per boot). */\n backfill?: boolean;\n}\n\nexport class PinyinSearchPlugin implements Plugin {\n name = 'com.objectstack.plugin.pinyin-search';\n version = '1.0.0';\n type = 'standard';\n dependencies = ['com.objectstack.engine.objectql'];\n\n private readonly options: PinyinSearchPluginOptions;\n\n constructor(options: PinyinSearchPluginOptions = {}) {\n this.options = options;\n }\n\n private get enabled(): boolean {\n return this.options.enabled ?? resolveSearchPinyinEnabled();\n }\n\n async init(_ctx: PluginContext): Promise<void> {\n // Nothing to register: the companion column is provisioned by the\n // SchemaRegistry's compile-time seam, not injected at runtime.\n }\n\n async start(ctx: PluginContext): Promise<void> {\n if (!this.enabled) {\n ctx.logger.debug?.('PinyinSearchPlugin: OS_SEARCH_PINYIN_ENABLED is off — inert');\n return;\n }\n\n ctx.hook('kernel:ready', async () => {\n const engine = this.resolveEngine(ctx);\n if (!engine) {\n ctx.logger.warn('PinyinSearchPlugin: no ObjectQL engine — companion hooks NOT bound');\n return;\n }\n try {\n bindSearchCompanionHooks(engine, ctx.logger as any);\n } catch (err: any) {\n ctx.logger.warn('PinyinSearchPlugin: companion hooks not bound', { error: err?.message });\n }\n });\n\n // Backfill AFTER boot settles (`kernel:bootstrapped` fires once every\n // `kernel:ready` hook — including seed loading — has completed), so\n // seeded rows written before/around hook binding are reconciled too.\n if (this.options.backfill !== false) {\n ctx.hook('kernel:bootstrapped', async () => {\n const engine = this.resolveEngine(ctx);\n if (!engine) return;\n try {\n await backfillSearchCompanion(engine, ctx.logger as any);\n } catch (err: any) {\n ctx.logger.warn('PinyinSearchPlugin: companion backfill failed', { error: err?.message });\n }\n });\n }\n }\n\n /**\n * [#4251 B5] The engine SEEN WHOLE — `bindSearchCompanionHooks` binds\n * `registerHook`, which lives on `IObjectQLEngine`, not on the data plane.\n * The ledger records `objectql` as \"the SAME instance as `data`, seen whole\",\n * so the alias fallback resolves the same object under the same contract.\n */\n private resolveEngine(ctx: PluginContext): IObjectQLEngine | null {\n try {\n return ctx.getService<IObjectQLEngine>('objectql');\n } catch {\n try {\n return ctx.getService<IObjectQLEngine>('data');\n } catch {\n return null;\n }\n }\n }\n}\n","// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * `__search` companion-column projection (#2486).\n *\n * The column itself is DECLARED at object compile time by the SchemaRegistry\n * (`provisionSearchCompanion`, gated on `OS_SEARCH_PINYIN_ENABLED`); this\n * module only FILLS the value — the `plugin-sharing` primary-BU projection\n * pattern (column on the object, plugin maintains it via hooks).\n *\n * Write path: global `beforeInsert`/`beforeUpdate` hooks stamp\n * `data.__search` whenever a companion source field (the object's\n * display/name field) is present in the write — i.e. only when the source\n * actually changed, avoiding write amplification. Writes that bypass hooks\n * (bulk import, direct migration) leave the companion empty; the boot\n * backfill and the `rebuildSearchCompanion` reconcile entry cover that.\n */\n\nimport {\n SEARCH_COMPANION_FIELD,\n resolveSearchCompanionSources,\n containsCJK,\n} from '@objectstack/objectql';\nimport { keysetWalk } from '@objectstack/types';\nimport { computeSearchCompanionValue } from './pinyin.js';\n\nconst SYSTEM_CTX = { isSystem: true, positions: [], permissions: [] } as const;\n\nexport const PINYIN_SEARCH_HOOK_PACKAGE = 'plugin-pinyin-search:companion';\n\ninterface MinimalEngine {\n registerHook(\n event: string,\n handler: (ctx: any) => any | Promise<any>,\n options?: { object?: string | string[]; priority?: number; packageId?: string },\n ): void;\n unregisterHooksByPackage(packageId: string): number;\n find(object: string, query?: any, options?: any): Promise<any[]>;\n update(object: string, data: any, options?: any): Promise<any>;\n registry?: {\n getObject(name: string): any;\n getAllObjects?(packageId?: string): any[];\n };\n}\n\ninterface MinimalLogger {\n info?: (msg: any, ...rest: any[]) => void;\n warn?: (msg: any, ...rest: any[]) => void;\n debug?: (msg: any, ...rest: any[]) => void;\n}\n\n/**\n * Stamp `data.__search` on a before-save hook context when a companion source\n * field is part of the write. Recomputes from the NEW value; a non-CJK new\n * value clears the companion (null) so stale pinyin never recalls a renamed\n * record. Never throws — a normalization failure must not fail the write.\n */\nasync function stampCompanion(engine: MinimalEngine, ctx: any, logger?: MinimalLogger): Promise<void> {\n const object = ctx?.object;\n if (!object) return;\n const schema = engine.registry?.getObject?.(object);\n if (!schema?.fields?.[SEARCH_COMPANION_FIELD]) return;\n\n const data = ctx?.input?.data;\n if (!data || typeof data !== 'object' || Array.isArray(data)) return;\n\n const sources = resolveSearchCompanionSources(schema);\n if (sources.length === 0) return;\n const touched = sources.filter((s) => Object.prototype.hasOwnProperty.call(data, s));\n if (touched.length === 0) return; // source unchanged → no recompute (no write amplification)\n\n try {\n data[SEARCH_COMPANION_FIELD] = await computeSearchCompanionValue(sources.map((s) => data[s]));\n } catch (err: any) {\n logger?.warn?.('[pinyin-search] companion normalization failed — write proceeds without it', {\n object,\n error: err?.message,\n });\n }\n}\n\n/**\n * Bind the global before-save hooks that keep `__search` in step. Idempotent\n * (unbinds the package first). Hooks are global (no object filter) with a\n * cheap early-out: objects without a provisioned companion column return\n * immediately. They run for system-context writes too — the projection must\n * stay correct regardless of who writes (seeds, imports, admin UI).\n */\nexport function bindSearchCompanionHooks(engine: MinimalEngine, logger?: MinimalLogger): void {\n if (typeof engine.registerHook !== 'function') return;\n if (typeof engine.unregisterHooksByPackage === 'function') {\n engine.unregisterHooksByPackage(PINYIN_SEARCH_HOOK_PACKAGE);\n }\n const opts = { packageId: PINYIN_SEARCH_HOOK_PACKAGE, priority: 150 };\n const handler = (ctx: any) => stampCompanion(engine, ctx, logger);\n engine.registerHook('beforeInsert', handler, opts);\n engine.registerHook('beforeUpdate', handler, opts);\n logger?.info?.('[pinyin-search] companion hooks bound (beforeInsert/beforeUpdate, all objects)');\n}\n\nexport interface CompanionBackfillOptions {\n /** Rows fetched per page during the scan. Default 1000. */\n batchSize?: number;\n /** Restrict to one object (reconcile entry); default: every provisioned object. */\n object?: string;\n /**\n * Recompute EVERY row's companion, not just missing ones — the periodic\n * reconcile/rebuild mode. Default false (backfill: only rows whose\n * companion is empty but whose source has CJK content).\n */\n force?: boolean;\n}\n\nexport interface CompanionBackfillResult {\n objects: number;\n scanned: number;\n updated: number;\n}\n\n/**\n * Backfill / reconcile the companion column.\n *\n * Denormalized-on-write columns go stale when writes bypass hooks (bulk\n * import, direct migration) and are empty for rows that predate the switch\n * being enabled. This scans every object that carries the companion column\n * (paged, system context) and fills the gaps; with `force: true` it\n * recomputes unconditionally (the periodic reconcile / rebuild entry).\n * Idempotent; per-row failures are skipped so one bad row never aborts the\n * pass.\n */\nexport async function backfillSearchCompanion(\n engine: MinimalEngine,\n logger?: MinimalLogger,\n options?: CompanionBackfillOptions,\n): Promise<CompanionBackfillResult> {\n const batchSize = Math.max(1, options?.batchSize ?? 1000);\n const all = options?.object\n ? [engine.registry?.getObject?.(options.object)].filter(Boolean)\n : engine.registry?.getAllObjects?.() ?? [];\n\n const result: CompanionBackfillResult = { objects: 0, scanned: 0, updated: 0 };\n\n for (const schema of all) {\n if (!schema?.name || !schema?.fields?.[SEARCH_COMPANION_FIELD]) continue;\n const sources = resolveSearchCompanionSources(schema);\n if (sources.length === 0) continue;\n result.objects++;\n\n // Seek by `id` (#4363). This walk UPDATES the rows it reads, and an offset\n // counts into a set those writes are changing, so rows slide past the\n // cursor and never get their companion blob — a backfill that reports a\n // clean pass while leaving records unsearchable.\n const walk = keysetWalk<any>(\n (q) => engine.find(schema.name, {\n ...q,\n fields: ['id', ...sources, SEARCH_COMPANION_FIELD],\n context: SYSTEM_CTX,\n }),\n { pageSize: batchSize },\n );\n\n try {\n for await (const rows of walk.pages()) {\n result.scanned += rows.length;\n\n for (const row of rows) {\n if (row?.id == null) continue;\n const hasBlob = typeof row[SEARCH_COMPANION_FIELD] === 'string' && row[SEARCH_COMPANION_FIELD] !== '';\n const hasCjkSource = sources.some((s) => containsCJK(row[s]));\n // Backfill mode: touch only rows missing a blob they should have.\n // Force mode: recompute everything (also clears stale blobs).\n if (!options?.force && (hasBlob || !hasCjkSource)) continue;\n try {\n const value = await computeSearchCompanionValue(sources.map((s) => row[s]));\n if (!options?.force && value == null) continue;\n if (value === row[SEARCH_COMPANION_FIELD]) continue;\n await engine.update(\n schema.name,\n { id: row.id, [SEARCH_COMPANION_FIELD]: value },\n { context: SYSTEM_CTX },\n );\n result.updated++;\n } catch (err: any) {\n logger?.warn?.('[pinyin-search] backfill row skipped', {\n object: schema.name,\n id: row.id,\n error: err?.message,\n });\n }\n }\n }\n } catch (err: any) {\n logger?.warn?.('[pinyin-search] backfill scan failed', { object: schema.name, error: err?.message });\n continue;\n }\n }\n\n if (result.updated > 0) {\n logger?.info?.('[pinyin-search] companion backfill complete', result);\n }\n return result;\n}\n\n/**\n * Periodic reconcile / rebuild entry: recompute the companion for every row\n * (optionally one object). Alias for `backfillSearchCompanion` with\n * `force: true` — exposed under its own name so operators/jobs have an\n * explicit \"rebuild the pinyin index\" handle.\n */\nexport function rebuildSearchCompanion(\n engine: MinimalEngine,\n logger?: MinimalLogger,\n options?: Omit<CompanionBackfillOptions, 'force'>,\n): Promise<CompanionBackfillResult> {\n return backfillSearchCompanion(engine, logger, { ...options, force: true });\n}\n","// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Pinyin normalization for the `__search` companion column (#2486).\n *\n * One normalized blob per record — full pinyin AND initials in the same\n * column — so a single `$contains` recalls every latin input shape:\n *\n * \"张伟\" → \"zhangwei zw\"\n * `zhang` / `wei` / `zhangwei` → substring of the full form\n * `zw` → substring of the initials form\n *\n * `pinyin-pro` is loaded lazily on first use: non-Chinese deployments (flag\n * off → hooks never bound) never import it and pay zero cost.\n *\n * Polyphones: pinyin-pro's default heuristics are accepted (issue #2486\n * \"待定\" — surname polyphone dictionaries are a P2 follow-up).\n */\n\nimport { containsCJK } from '@objectstack/objectql';\n\ntype PinyinFn = (text: string, options?: Record<string, unknown>) => string | string[];\n\nlet _pinyin: Promise<PinyinFn> | null = null;\n\n/** Lazy-load `pinyin-pro` (cached module-wide). */\nfunction loadPinyin(): Promise<PinyinFn> {\n _pinyin ??= import('pinyin-pro').then((m: any) => (m.pinyin ?? m.default?.pinyin) as PinyinFn);\n return _pinyin;\n}\n\n/** Lowercase and strip everything that is not a latin letter or digit. */\nfunction squash(syllables: string | string[]): string {\n const joined = Array.isArray(syllables) ? syllables.join('') : String(syllables ?? '');\n return joined.toLowerCase().replace(/[^a-z0-9]+/g, '');\n}\n\n/**\n * Compute the companion value for the given source-field values.\n *\n * Returns the normalized blob (`\"<full-pinyin> <initials>\"`, deduplicated)\n * when at least one value contains CJK characters, else `null` — a `null`\n * companion means \"nothing pinyin-searchable here\" and clears any stale blob\n * when a name is edited away from CJK. Non-CJK values need no companion:\n * their source column already matches latin input directly.\n */\nexport async function computeSearchCompanionValue(values: ReadonlyArray<unknown>): Promise<string | null> {\n const cjkValues = values.filter((v): v is string => containsCJK(v));\n if (cjkValues.length === 0) return null;\n\n const pinyin = await loadPinyin();\n const parts: string[] = [];\n for (const value of cjkValues) {\n // `nonZh: 'consecutive'` keeps latin/digit runs intact inside mixed\n // values (\"张伟2号\" → \"zhangwei2hao\"), so mixed names stay one token.\n const full = squash(pinyin(value, { toneType: 'none', type: 'array', nonZh: 'consecutive' }));\n const initials = squash(pinyin(value, { pattern: 'first', toneType: 'none', type: 'array', nonZh: 'consecutive' }));\n if (full) parts.push(full);\n if (initials && initials !== full) parts.push(initials);\n }\n if (parts.length === 0) return null;\n return [...new Set(parts)].join(' ');\n}\n"],"mappings":"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","names":["import_types","import_objectql"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/pinyin-search-plugin.ts","../src/companion-projection.ts","../src/pinyin.ts"],"mappings":"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","names":["import_types","import_objectql"]}
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/pinyin-search-plugin.ts","../src/companion-projection.ts","../src/pinyin.ts"],"sourcesContent":["// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * PinyinSearchPlugin (#2486) — pinyin recall for `$search`.\n *\n * Pure hook plugin: the `__search` companion column is declared at object\n * compile time by the SchemaRegistry (gated on the SAME\n * `OS_SEARCH_PINYIN_ENABLED` decision point), the engine ORs it into the\n * `$search` filter, and this plugin fills the value:\n *\n * - before-save hooks: recompute full pinyin + initials of the\n * display/name field when it changes;\n * - boot backfill (`kernel:bootstrapped`): fill rows that predate the\n * switch or arrived via hook-bypassing writes;\n * - `rebuildSearchCompanion` (exported): explicit reconcile/rebuild entry.\n *\n * When the flag is off the plugin is inert: no hooks, no backfill, and\n * `pinyin-pro` is never imported.\n */\n\n// `IObjectQLEngine` via the core barrel, which re-exports it from\n// `@objectstack/spec/contracts`: this package does not depend on spec directly,\n// and the slot's contract is not a reason to add a dependency.\nimport type { IObjectQLEngine, Plugin, PluginContext } from '@objectstack/core';\nimport { resolveSearchPinyinEnabled } from '@objectstack/types';\nimport {\n bindSearchCompanionHooks,\n backfillSearchCompanion,\n} from './companion-projection.js';\n\nexport interface PinyinSearchPluginOptions {\n /**\n * Force-enable/disable regardless of `OS_SEARCH_PINYIN_ENABLED` (tests /\n * embedders). Default: `resolveSearchPinyinEnabled()`.\n */\n enabled?: boolean;\n /** Skip the boot backfill (default: run it once per boot). */\n backfill?: boolean;\n}\n\nexport class PinyinSearchPlugin implements Plugin {\n name = 'com.objectstack.plugin.pinyin-search';\n version = '1.0.0';\n type = 'standard';\n dependencies = ['com.objectstack.engine.objectql'];\n\n private readonly options: PinyinSearchPluginOptions;\n\n constructor(options: PinyinSearchPluginOptions = {}) {\n this.options = options;\n }\n\n private get enabled(): boolean {\n return this.options.enabled ?? resolveSearchPinyinEnabled();\n }\n\n async init(_ctx: PluginContext): Promise<void> {\n // Nothing to register: the companion column is provisioned by the\n // SchemaRegistry's compile-time seam, not injected at runtime.\n }\n\n async start(ctx: PluginContext): Promise<void> {\n if (!this.enabled) {\n ctx.logger.debug?.('PinyinSearchPlugin: OS_SEARCH_PINYIN_ENABLED is off — inert');\n return;\n }\n\n ctx.hook('kernel:ready', async () => {\n const engine = this.resolveEngine(ctx);\n if (!engine) {\n ctx.logger.warn('PinyinSearchPlugin: no ObjectQL engine — companion hooks NOT bound');\n return;\n }\n try {\n bindSearchCompanionHooks(engine, ctx.logger as any);\n } catch (err: any) {\n ctx.logger.warn('PinyinSearchPlugin: companion hooks not bound', { error: err?.message });\n }\n });\n\n // Backfill AFTER boot settles (`kernel:bootstrapped` fires once every\n // `kernel:ready` hook — including seed loading — has completed), so\n // seeded rows written before/around hook binding are reconciled too.\n if (this.options.backfill !== false) {\n ctx.hook('kernel:bootstrapped', async () => {\n const engine = this.resolveEngine(ctx);\n if (!engine) return;\n try {\n await backfillSearchCompanion(engine, ctx.logger as any);\n } catch (err: any) {\n ctx.logger.warn('PinyinSearchPlugin: companion backfill failed', { error: err?.message });\n }\n });\n }\n }\n\n /**\n * [#4251 B5] The engine SEEN WHOLE — `bindSearchCompanionHooks` binds\n * `registerHook`, which lives on `IObjectQLEngine`, not on the data plane.\n * The ledger records `objectql` as \"the SAME instance as `data`, seen whole\",\n * so the alias fallback resolves the same object under the same contract.\n */\n private resolveEngine(ctx: PluginContext): IObjectQLEngine | null {\n try {\n return ctx.getService<IObjectQLEngine>('objectql');\n } catch {\n try {\n return ctx.getService<IObjectQLEngine>('data');\n } catch {\n return null;\n }\n }\n }\n}\n","// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * `__search` companion-column projection (#2486).\n *\n * The column itself is DECLARED at object compile time by the SchemaRegistry\n * (`provisionSearchCompanion`, gated on `OS_SEARCH_PINYIN_ENABLED`); this\n * module only FILLS the value — the `plugin-sharing` primary-BU projection\n * pattern (column on the object, plugin maintains it via hooks).\n *\n * Write path: global `beforeInsert`/`beforeUpdate` hooks stamp\n * `data.__search` whenever a companion source field (the object's\n * display/name field) is present in the write — i.e. only when the source\n * actually changed, avoiding write amplification. Writes that bypass hooks\n * (bulk import, direct migration) leave the companion empty; the boot\n * backfill and the `rebuildSearchCompanion` reconcile entry cover that.\n */\n\nimport {\n SEARCH_COMPANION_FIELD,\n resolveSearchCompanionSources,\n containsCJK,\n} from '@objectstack/objectql';\nimport { keysetWalk } from '@objectstack/types';\nimport { computeSearchCompanionValue } from './pinyin.js';\n\nconst SYSTEM_CTX = { isSystem: true, positions: [], permissions: [] } as const;\n\nexport const PINYIN_SEARCH_HOOK_PACKAGE = 'plugin-pinyin-search:companion';\n\ninterface MinimalEngine {\n registerHook(\n event: string,\n handler: (ctx: any) => any | Promise<any>,\n options?: { object?: string | string[]; priority?: number; packageId?: string },\n ): void;\n unregisterHooksByPackage(packageId: string): number;\n find(object: string, query?: any, options?: any): Promise<any[]>;\n update(object: string, data: any, options?: any): Promise<any>;\n registry?: {\n getObject(name: string): any;\n getAllObjects?(packageId?: string): any[];\n };\n}\n\ninterface MinimalLogger {\n info?: (msg: any, ...rest: any[]) => void;\n warn?: (msg: any, ...rest: any[]) => void;\n debug?: (msg: any, ...rest: any[]) => void;\n}\n\n/**\n * Stamp `data.__search` on a before-save hook context when a companion source\n * field is part of the write. Recomputes from the NEW value; a non-CJK new\n * value clears the companion (null) so stale pinyin never recalls a renamed\n * record. Never throws — a normalization failure must not fail the write.\n */\nasync function stampCompanion(engine: MinimalEngine, ctx: any, logger?: MinimalLogger): Promise<void> {\n const object = ctx?.object;\n if (!object) return;\n const schema = engine.registry?.getObject?.(object);\n if (!schema?.fields?.[SEARCH_COMPANION_FIELD]) return;\n\n const data = ctx?.input?.data;\n if (!data || typeof data !== 'object' || Array.isArray(data)) return;\n\n const sources = resolveSearchCompanionSources(schema);\n if (sources.length === 0) return;\n const touched = sources.filter((s) => Object.prototype.hasOwnProperty.call(data, s));\n if (touched.length === 0) return; // source unchanged → no recompute (no write amplification)\n\n try {\n data[SEARCH_COMPANION_FIELD] = await computeSearchCompanionValue(sources.map((s) => data[s]));\n } catch (err: any) {\n logger?.warn?.('[pinyin-search] companion normalization failed — write proceeds without it', {\n object,\n error: err?.message,\n });\n }\n}\n\n/**\n * Bind the global before-save hooks that keep `__search` in step. Idempotent\n * (unbinds the package first). Hooks are global (no object filter) with a\n * cheap early-out: objects without a provisioned companion column return\n * immediately. They run for system-context writes too — the projection must\n * stay correct regardless of who writes (seeds, imports, admin UI).\n */\nexport function bindSearchCompanionHooks(engine: MinimalEngine, logger?: MinimalLogger): void {\n if (typeof engine.registerHook !== 'function') return;\n if (typeof engine.unregisterHooksByPackage === 'function') {\n engine.unregisterHooksByPackage(PINYIN_SEARCH_HOOK_PACKAGE);\n }\n const opts = { packageId: PINYIN_SEARCH_HOOK_PACKAGE, priority: 150 };\n const handler = (ctx: any) => stampCompanion(engine, ctx, logger);\n engine.registerHook('beforeInsert', handler, opts);\n engine.registerHook('beforeUpdate', handler, opts);\n logger?.info?.('[pinyin-search] companion hooks bound (beforeInsert/beforeUpdate, all objects)');\n}\n\nexport interface CompanionBackfillOptions {\n /** Rows fetched per page during the scan. Default 1000. */\n batchSize?: number;\n /** Restrict to one object (reconcile entry); default: every provisioned object. */\n object?: string;\n /**\n * Recompute EVERY row's companion, not just missing ones — the periodic\n * reconcile/rebuild mode. Default false (backfill: only rows whose\n * companion is empty but whose source has CJK content).\n */\n force?: boolean;\n}\n\nexport interface CompanionBackfillResult {\n objects: number;\n scanned: number;\n updated: number;\n}\n\n/**\n * Backfill / reconcile the companion column.\n *\n * Denormalized-on-write columns go stale when writes bypass hooks (bulk\n * import, direct migration) and are empty for rows that predate the switch\n * being enabled. This scans every object that carries the companion column\n * (paged, system context) and fills the gaps; with `force: true` it\n * recomputes unconditionally (the periodic reconcile / rebuild entry).\n * Idempotent; per-row failures are skipped so one bad row never aborts the\n * pass.\n */\nexport async function backfillSearchCompanion(\n engine: MinimalEngine,\n logger?: MinimalLogger,\n options?: CompanionBackfillOptions,\n): Promise<CompanionBackfillResult> {\n const batchSize = Math.max(1, options?.batchSize ?? 1000);\n const all = options?.object\n ? [engine.registry?.getObject?.(options.object)].filter(Boolean)\n : engine.registry?.getAllObjects?.() ?? [];\n\n const result: CompanionBackfillResult = { objects: 0, scanned: 0, updated: 0 };\n\n for (const schema of all) {\n if (!schema?.name || !schema?.fields?.[SEARCH_COMPANION_FIELD]) continue;\n const sources = resolveSearchCompanionSources(schema);\n if (sources.length === 0) continue;\n result.objects++;\n\n // Seek by `id` (#4363). This walk UPDATES the rows it reads, and an offset\n // counts into a set those writes are changing, so rows slide past the\n // cursor and never get their companion blob — a backfill that reports a\n // clean pass while leaving records unsearchable.\n const walk = keysetWalk<any>(\n (q) => engine.find(schema.name, {\n ...q,\n fields: ['id', ...sources, SEARCH_COMPANION_FIELD],\n context: SYSTEM_CTX,\n }),\n { pageSize: batchSize },\n );\n\n try {\n for await (const rows of walk.pages()) {\n result.scanned += rows.length;\n\n for (const row of rows) {\n if (row?.id == null) continue;\n const hasBlob = typeof row[SEARCH_COMPANION_FIELD] === 'string' && row[SEARCH_COMPANION_FIELD] !== '';\n const hasCjkSource = sources.some((s) => containsCJK(row[s]));\n // Backfill mode: touch only rows missing a blob they should have.\n // Force mode: recompute everything (also clears stale blobs).\n if (!options?.force && (hasBlob || !hasCjkSource)) continue;\n try {\n const value = await computeSearchCompanionValue(sources.map((s) => row[s]));\n if (!options?.force && value == null) continue;\n if (value === row[SEARCH_COMPANION_FIELD]) continue;\n await engine.update(\n schema.name,\n { id: row.id, [SEARCH_COMPANION_FIELD]: value },\n { context: SYSTEM_CTX },\n );\n result.updated++;\n } catch (err: any) {\n logger?.warn?.('[pinyin-search] backfill row skipped', {\n object: schema.name,\n id: row.id,\n error: err?.message,\n });\n }\n }\n }\n } catch (err: any) {\n logger?.warn?.('[pinyin-search] backfill scan failed', { object: schema.name, error: err?.message });\n continue;\n }\n }\n\n if (result.updated > 0) {\n logger?.info?.('[pinyin-search] companion backfill complete', result);\n }\n return result;\n}\n\n/**\n * Periodic reconcile / rebuild entry: recompute the companion for every row\n * (optionally one object). Alias for `backfillSearchCompanion` with\n * `force: true` — exposed under its own name so operators/jobs have an\n * explicit \"rebuild the pinyin index\" handle.\n */\nexport function rebuildSearchCompanion(\n engine: MinimalEngine,\n logger?: MinimalLogger,\n options?: Omit<CompanionBackfillOptions, 'force'>,\n): Promise<CompanionBackfillResult> {\n return backfillSearchCompanion(engine, logger, { ...options, force: true });\n}\n","// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Pinyin normalization for the `__search` companion column (#2486).\n *\n * One normalized blob per record — full pinyin AND initials in the same\n * column — so a single `$contains` recalls every latin input shape:\n *\n * \"张伟\" → \"zhangwei zw\"\n * `zhang` / `wei` / `zhangwei` → substring of the full form\n * `zw` → substring of the initials form\n *\n * `pinyin-pro` is loaded lazily on first use: non-Chinese deployments (flag\n * off → hooks never bound) never import it and pay zero cost.\n *\n * Polyphones: pinyin-pro's default heuristics are accepted (issue #2486\n * \"待定\" — surname polyphone dictionaries are a P2 follow-up).\n */\n\nimport { containsCJK } from '@objectstack/objectql';\n\ntype PinyinFn = (text: string, options?: Record<string, unknown>) => string | string[];\n\nlet _pinyin: Promise<PinyinFn> | null = null;\n\n/** Lazy-load `pinyin-pro` (cached module-wide). */\nfunction loadPinyin(): Promise<PinyinFn> {\n _pinyin ??= import('pinyin-pro').then((m: any) => (m.pinyin ?? m.default?.pinyin) as PinyinFn);\n return _pinyin;\n}\n\n/** Lowercase and strip everything that is not a latin letter or digit. */\nfunction squash(syllables: string | string[]): string {\n const joined = Array.isArray(syllables) ? syllables.join('') : String(syllables ?? '');\n return joined.toLowerCase().replace(/[^a-z0-9]+/g, '');\n}\n\n/**\n * Compute the companion value for the given source-field values.\n *\n * Returns the normalized blob (`\"<full-pinyin> <initials>\"`, deduplicated)\n * when at least one value contains CJK characters, else `null` — a `null`\n * companion means \"nothing pinyin-searchable here\" and clears any stale blob\n * when a name is edited away from CJK. Non-CJK values need no companion:\n * their source column already matches latin input directly.\n */\nexport async function computeSearchCompanionValue(values: ReadonlyArray<unknown>): Promise<string | null> {\n const cjkValues = values.filter((v): v is string => containsCJK(v));\n if (cjkValues.length === 0) return null;\n\n const pinyin = await loadPinyin();\n const parts: string[] = [];\n for (const value of cjkValues) {\n // `nonZh: 'consecutive'` keeps latin/digit runs intact inside mixed\n // values (\"张伟2号\" → \"zhangwei2hao\"), so mixed names stay one token.\n const full = squash(pinyin(value, { toneType: 'none', type: 'array', nonZh: 'consecutive' }));\n const initials = squash(pinyin(value, { pattern: 'first', toneType: 'none', type: 'array', nonZh: 'consecutive' }));\n if (full) parts.push(full);\n if (initials && initials !== full) parts.push(initials);\n }\n if (parts.length === 0) return null;\n return [...new Set(parts)].join(' ');\n}\n"],"mappings":"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","names":["containsCJK","containsCJK"]}
|
|
1
|
+
{"version":3,"sources":["../src/pinyin-search-plugin.ts","../src/companion-projection.ts","../src/pinyin.ts"],"mappings":"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","names":["containsCJK","containsCJK"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@objectstack/plugin-pinyin-search",
|
|
3
|
-
"version": "17.
|
|
3
|
+
"version": "17.4.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "Pinyin search recall for ObjectStack — populates the hidden `__search` companion column (full pinyin + initials of the display/name field) so `$search` hits CJK names typed as pinyin. Locale-gated via OS_SEARCH_PINYIN_ENABLED (#2486).",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -14,12 +14,13 @@
|
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"pinyin-pro": "^3.29.1",
|
|
17
|
-
"@objectstack/
|
|
18
|
-
"@objectstack/
|
|
19
|
-
"@objectstack/
|
|
17
|
+
"@objectstack/core": "17.4.0",
|
|
18
|
+
"@objectstack/objectql": "17.4.0",
|
|
19
|
+
"@objectstack/types": "17.4.0"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"@types/node": "^26.2.0",
|
|
23
|
+
"tsx": "^4.23.12",
|
|
23
24
|
"typescript": "^6.0.3",
|
|
24
25
|
"vitest": "^4.1.10"
|
|
25
26
|
},
|
|
@@ -30,14 +31,20 @@
|
|
|
30
31
|
"pinyin",
|
|
31
32
|
"i18n"
|
|
32
33
|
],
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "https://github.com/objectstack-ai/objectstack.git",
|
|
37
|
+
"directory": "packages/plugins/plugin-pinyin-search"
|
|
38
|
+
},
|
|
33
39
|
"files": [
|
|
34
40
|
"dist",
|
|
35
41
|
"README.md",
|
|
36
42
|
"CHANGELOG.md"
|
|
37
43
|
],
|
|
38
44
|
"scripts": {
|
|
39
|
-
"build": "tsup --config ../../../tsup.config.ts",
|
|
45
|
+
"build": "tsup --config ../../../tsup.config.ts && node ../../../scripts/check-dts-emitted.mjs",
|
|
40
46
|
"test": "vitest run --passWithNoTests",
|
|
41
|
-
"typecheck": "tsc --noEmit"
|
|
47
|
+
"typecheck": "tsc --noEmit && pnpm check:test-typecheck",
|
|
48
|
+
"check:test-typecheck": "tsx ../../../scripts/check-test-typecheck.mts --self-test && tsx ../../../scripts/check-test-typecheck.mts --package packages/plugins/plugin-pinyin-search --project tsconfig.test.json"
|
|
42
49
|
}
|
|
43
50
|
}
|