@abeedoo/radish-schemas 1.8.0 → 1.10.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/index.js CHANGED
@@ -31,7 +31,7 @@ export {
31
31
  * @property {string} minCliVersion - Minimum radish-cli version compatible with this package
32
32
  */
33
33
  export const VERSIONING = {
34
- packageVersion: '1.8.0',
34
+ packageVersion: '1.10.0',
35
35
  currentSpecVersion: 1,
36
36
  supportedSpecVersions: [1],
37
37
  minCliVersion: '0.1.0'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abeedoo/radish-schemas",
3
- "version": "1.8.0",
3
+ "version": "1.10.0",
4
4
  "description": "Shared JSON schemas, validators, and prompts for Radish CLI ecosystem",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -163,7 +163,12 @@ The following entities are already provided by the system. DO NOT recreate them
163
163
  "engine": "typesense",
164
164
  "indexName": "products",
165
165
  "fields": {
166
- "searchable": ["name", "description", "brand"],
166
+ "searchable": [
167
+ { "field": "name", "stem": true },
168
+ { "field": "description", "stem": true },
169
+ "sku",
170
+ "brand"
171
+ ],
167
172
  "filterable": ["brand", "price", "categories"],
168
173
  "sortable": ["price", "name", "createdAt"],
169
174
  "facetable": ["brand", "categories"]
@@ -182,6 +187,22 @@ The following entities are already provided by the system. DO NOT recreate them
182
187
  - **indexName**: Custom index name (defaults to entity plural)
183
188
  - **sync**: `inline` (immediate) or `background` (via jobs)
184
189
  - **vector**: Enable vector/embedding search with `sourceFields` to generate embeddings from
190
+ - **searchable**: Each entry is either a plain field name or `{ "field": "name", "stem": true }`. Stemming reduces terms to their word stems at index time (`computers` → `computer`), so a plural query matches singular text as an exact match rather than relying on typo correction. Set `stem: true` only on prose fields (name, description, summary, body). Never stem identifiers (`sku`, `slug`, `code`), brand or category values, anything listed under `filterable`/`facetable`, or non-string fields — stemming a facet value breaks the filter that reads it.
191
+ - **configureBy**: `"rows"` marks an entity whose *records* are vocabulary for other entities' search indexes — each row (or group of rows) becomes a candidate field in the consuming entity's search configuration. Use it for entities that define terminology rather than content: `Attribute`, `Term`, `Tag`, `Taxonomy`. The system discovers code/label fields and grouping refs from the entity's own field definitions, so no extra configuration is needed. A vocabulary entity that is not itself searchable needs only `"search": { "configureBy": "rows" }`; combine with `"enabled": true` when the entity should also have its own index:
192
+ ```json
193
+ "Term": {
194
+ "plural": "terms",
195
+ "search": {
196
+ "enabled": true,
197
+ "configureBy": "rows",
198
+ "fields": {
199
+ "searchable": [{ "field": "name", "stem": true }, "slug"],
200
+ "filterable": ["taxonomyId"]
201
+ }
202
+ },
203
+ "fields": { ... }
204
+ }
205
+ ```
185
206
 
186
207
  13. **Expiration / TTL** (optional): For entities whose records should be purged automatically (sessions, tokens, logs, temporary uploads), use the entity-level `ttl` shorthand:
187
208
  ```json
@@ -90,8 +90,7 @@
90
90
  },
91
91
  "search": {
92
92
  "type": "object",
93
- "description": "Search index configuration for this entity. Generates search adapters and typed search index classes.",
94
- "required": ["enabled"],
93
+ "description": "Search index configuration for this entity. Generates search adapters and typed search index classes. An entity with configureBy: 'rows' declares its records as vocabulary for other entities' indexes.",
95
94
  "additionalProperties": false,
96
95
  "properties": {
97
96
  "enabled": {
@@ -114,8 +113,27 @@
114
113
  "properties": {
115
114
  "searchable": {
116
115
  "type": "array",
117
- "items": { "type": "string" },
118
- "description": "Fields included in full-text search queries"
116
+ "items": {
117
+ "oneOf": [
118
+ { "type": "string" },
119
+ {
120
+ "type": "object",
121
+ "required": ["field"],
122
+ "additionalProperties": false,
123
+ "properties": {
124
+ "field": {
125
+ "type": "string",
126
+ "description": "Field name"
127
+ },
128
+ "stem": {
129
+ "type": "boolean",
130
+ "description": "Reduce terms to their word stems at index time so plural queries match singular text. Prose fields only — never identifiers, facets, or non-string fields, since stemming a facet value breaks the filter that reads it."
131
+ }
132
+ }
133
+ }
134
+ ]
135
+ },
136
+ "description": "Fields included in full-text search queries. Either a field name, or an object with per-field options such as stemming."
119
137
  },
120
138
  "filterable": {
121
139
  "type": "array",
@@ -154,6 +172,11 @@
154
172
  "description": "Fields to generate embeddings from"
155
173
  }
156
174
  }
175
+ },
176
+ "configureBy": {
177
+ "type": "string",
178
+ "enum": ["rows"],
179
+ "description": "How this entity participates in search configuration. 'rows' means this entity's records are vocabulary for other entities' indexes — each row (or group of rows) becomes a candidate field in the consumer's search config UI. The system discovers code/label fields and grouping refs from the entity's own field definitions. Combinable with enabled: true for entities that are both searchable and vocabulary sources (e.g. Term)."
157
180
  }
158
181
  }
159
182
  },