@lde/search 0.12.3 → 0.13.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/dist/adapter.d.ts +2 -2
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/query.d.ts +23 -5
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +37 -4
- package/dist/schema.d.ts +15 -2
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +20 -1
- package/dist/testing.d.ts +3 -2
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +20 -3
- package/package.json +1 -1
package/dist/adapter.d.ts
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
* deployment author declaring a schema and running searches needs none of
|
|
7
7
|
* this; the main entry point carries that (small) authoring surface.
|
|
8
8
|
*/
|
|
9
|
-
export { assertTypeInSchema, physicalFields, irAlias, displayFieldName, displayFieldPattern, displayLangOf, searchableFields, facetableFields, filterableFields, sortableFields, outputFields, isInternalField, isInlineReference, referenceFields, referenceTypeNamed, inlineFramingDepth, fieldNamed, labelFieldOf, isRangeFacet, isoToUnixSeconds, unixSecondsToIso, } from './schema.js';
|
|
9
|
+
export { assertTypeInSchema, physicalFields, irAlias, displayFieldName, displayFieldPattern, displayLangOf, searchableFields, facetableFields, filterableFields, sortableFields, outputFields, isInternalField, isInlineReference, referenceFields, referenceTypeNamed, inlineFramingDepth, fieldNamed, ID_FIELD, labelFieldOf, isRangeFacet, isoToUnixSeconds, unixSecondsToIso, } from './schema.js';
|
|
10
10
|
export type { PhysicalFields } from './schema.js';
|
|
11
11
|
export { physicalNameTokens } from './physical-name.js';
|
|
12
|
-
export { filterOperatorFor, filterOperator, validateQuery, assertValidQuery, pageForOffset, } from './query.js';
|
|
12
|
+
export { filterOperatorFor, filterOperator, isUnsatisfiable, validateQuery, assertValidQuery, pageForOffset, } from './query.js';
|
|
13
13
|
export type { FilterOperator, QueryIssue } from './query.js';
|
|
14
14
|
//# sourceMappingURL=adapter.d.ts.map
|
package/dist/adapter.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,OAAO,EACP,gBAAgB,EAChB,mBAAmB,EACnB,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,YAAY,EACZ,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,aAAa,GACd,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,OAAO,EACP,gBAAgB,EAChB,mBAAmB,EACnB,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,YAAY,EACZ,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,UAAU,EACV,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,aAAa,GACd,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/adapter.js
CHANGED
|
@@ -6,6 +6,6 @@
|
|
|
6
6
|
* deployment author declaring a schema and running searches needs none of
|
|
7
7
|
* this; the main entry point carries that (small) authoring surface.
|
|
8
8
|
*/
|
|
9
|
-
export { assertTypeInSchema, physicalFields, irAlias, displayFieldName, displayFieldPattern, displayLangOf, searchableFields, facetableFields, filterableFields, sortableFields, outputFields, isInternalField, isInlineReference, referenceFields, referenceTypeNamed, inlineFramingDepth, fieldNamed, labelFieldOf, isRangeFacet, isoToUnixSeconds, unixSecondsToIso, } from './schema.js';
|
|
9
|
+
export { assertTypeInSchema, physicalFields, irAlias, displayFieldName, displayFieldPattern, displayLangOf, searchableFields, facetableFields, filterableFields, sortableFields, outputFields, isInternalField, isInlineReference, referenceFields, referenceTypeNamed, inlineFramingDepth, fieldNamed, ID_FIELD, labelFieldOf, isRangeFacet, isoToUnixSeconds, unixSecondsToIso, } from './schema.js';
|
|
10
10
|
export { physicalNameTokens } from './physical-name.js';
|
|
11
|
-
export { filterOperatorFor, filterOperator, validateQuery, assertValidQuery, pageForOffset, } from './query.js';
|
|
11
|
+
export { filterOperatorFor, filterOperator, isUnsatisfiable, validateQuery, assertValidQuery, pageForOffset, } from './query.js';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { projectRoots } from './project.js';
|
|
2
2
|
export type { SearchDocument } from './project.js';
|
|
3
|
-
export { defineSearchType, searchSchema, validateSearchType, assertValidSearchType, } from './schema.js';
|
|
3
|
+
export { defineSearchType, searchSchema, validateSearchType, assertValidSearchType, ID_FIELD, } from './schema.js';
|
|
4
4
|
export type { FieldKind, SearchField, SearchFieldBase, TextField, KeywordField, ReferenceField, NumericField, BooleanField, SearchType, SearchTypeBase, RootType, ReferenceType, RootTypeOf, SearchTypeIssue, SearchSchema, FacetRange, } from './schema.js';
|
|
5
5
|
export type { SearchQuery, Filter, Sort } from './query.js';
|
|
6
6
|
export type { SearchEngine, SearchResult, SearchHit, ResultDocument, SearchValue, LocalizedValue, Reference, FacetBucket, FacetMap, FacetsOutcome, FacetFieldsOf, OutputFieldsOf, } from './engine.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAKnD,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,kBAAkB,EAClB,qBAAqB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAKnD,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,kBAAkB,EAClB,qBAAqB,EACrB,QAAQ,GACT,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,SAAS,EACT,WAAW,EACX,eAAe,EACf,SAAS,EACT,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,cAAc,EACd,QAAQ,EACR,aAAa,EACb,UAAU,EACV,eAAe,EACf,YAAY,EACZ,UAAU,GACX,MAAM,aAAa,CAAC;AAIrB,YAAY,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAI5D,YAAY,EACV,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,cAAc,EACd,WAAW,EACX,cAAc,EACd,SAAS,EACT,WAAW,EACX,QAAQ,EACR,aAAa,EACb,aAAa,EACb,cAAc,GACf,MAAM,aAAa,CAAC;AAErB,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -10,4 +10,4 @@ export { projectRoots } from './project.js';
|
|
|
10
10
|
// Unified field model: one declaration drives projection, engine collection
|
|
11
11
|
// schema, query semantics and the GraphQL surface – a discriminated union by
|
|
12
12
|
// `kind`, validated again at runtime when the schema is built.
|
|
13
|
-
export { defineSearchType, searchSchema, validateSearchType, assertValidSearchType, } from './schema.js';
|
|
13
|
+
export { defineSearchType, searchSchema, validateSearchType, assertValidSearchType, ID_FIELD, } from './schema.js';
|
package/dist/query.d.ts
CHANGED
|
@@ -24,7 +24,7 @@ export interface SearchQuery {
|
|
|
24
24
|
* One `where` clause. The operator is fixed by the target field’s {@link FieldKind}
|
|
25
25
|
* ({@link filterOperatorFor}): keyword/reference use `in` (OR within the field),
|
|
26
26
|
* the numeric/date kinds use an inclusive `range`, boolean uses `is`. Bounds are
|
|
27
|
-
* inclusive only
|
|
27
|
+
* inclusive only – no `gt`/`gte`/`lt`/`lte`.
|
|
28
28
|
*/
|
|
29
29
|
export type Filter = {
|
|
30
30
|
readonly field: string;
|
|
@@ -49,11 +49,28 @@ export type { FilterOperator } from './schema.js';
|
|
|
49
49
|
import type { FilterOperator } from './schema.js';
|
|
50
50
|
/** The operator a {@link Filter} value carries, from its discriminating key. */
|
|
51
51
|
export declare function filterOperator(filter: Filter): FilterOperator;
|
|
52
|
+
/**
|
|
53
|
+
* Whether the query asks for nothing, so no engine can answer it with a hit.
|
|
54
|
+
* True for an empty `in` on {@link ID_FIELD} – and only there, deliberately:
|
|
55
|
+
*
|
|
56
|
+
* An **identity** filter enumerates the documents wanted, so the empty set
|
|
57
|
+
* wants none. A **value** filter constrains a dimension, so an empty set
|
|
58
|
+
* constrains nothing – which is why every other vacuous clause is a no-op the
|
|
59
|
+
* compilers skip (a facet UI with nothing selected sends exactly that). The
|
|
60
|
+
* readings differ because the fields differ in kind, and only for `id` would
|
|
61
|
+
* “no constraint” hand back the whole collection to a caller who asked for
|
|
62
|
+
* specific things – the likely shape being a client mapping a possibly-empty
|
|
63
|
+
* reference array (`id: { in: doc.publisher }`) into a batch lookup.
|
|
64
|
+
*
|
|
65
|
+
* An adapter MUST answer an unsatisfiable query with an empty result rather
|
|
66
|
+
* than dispatching it.
|
|
67
|
+
*/
|
|
68
|
+
export declare function isUnsatisfiable(query: SearchQuery): boolean;
|
|
52
69
|
/**
|
|
53
70
|
* One structural problem {@link validateQuery} found: the query references a
|
|
54
71
|
* field the search type does not declare, or uses it in a role it does not
|
|
55
72
|
* opt into. Vacuous-but-valid clauses (an empty `in` list, a `range` with no
|
|
56
|
-
* bound) are NOT issues
|
|
73
|
+
* bound) are NOT issues – a compiler skips those as no-ops.
|
|
57
74
|
*/
|
|
58
75
|
export interface QueryIssue {
|
|
59
76
|
readonly part: 'where' | 'facets' | 'orderBy';
|
|
@@ -63,14 +80,15 @@ export interface QueryIssue {
|
|
|
63
80
|
/**
|
|
64
81
|
* Structurally validate a query against its search type: every `where` clause
|
|
65
82
|
* targets a declared, `filterable` field with the operator its kind accepts
|
|
66
|
-
* ({@link filterOperatorFor})
|
|
83
|
+
* ({@link filterOperatorFor}) – or the undeclared, always-filterable
|
|
84
|
+
* {@link ID_FIELD}, which takes `in`; every requested facet is a declared, `facetable`
|
|
67
85
|
* field; every sort is `relevance` or a declared field. Sorting deliberately
|
|
68
86
|
* checks declaration only, not the `sortable` flag: that flag means *publicly
|
|
69
87
|
* selectable*, and a deployment policy may sort on a private tie-break field.
|
|
70
88
|
*
|
|
71
89
|
* This is the port’s always-on guard: every {@link SearchEngine} adapter MUST
|
|
72
90
|
* reject a query with issues ({@link assertValidQuery}) instead of passing
|
|
73
|
-
* garbage to its engine, so validation holds for every caller
|
|
91
|
+
* garbage to its engine, so validation holds for every caller – including
|
|
74
92
|
* `queryDefaults` policies and surfaces weaker than GraphQL.
|
|
75
93
|
*/
|
|
76
94
|
export declare function validateQuery(query: SearchQuery, searchType: SearchType): readonly QueryIssue[];
|
|
@@ -78,7 +96,7 @@ export declare function validateQuery(query: SearchQuery, searchType: SearchType
|
|
|
78
96
|
* naming every issue. The always-on entry point for engine adapters. */
|
|
79
97
|
export declare function assertValidQuery(query: SearchQuery, searchType: SearchType): void;
|
|
80
98
|
/**
|
|
81
|
-
* The 1-based page an `offset` falls on
|
|
99
|
+
* The 1-based page an `offset` falls on – the numbered-pagination presentation
|
|
82
100
|
* of the IR, shared by the surfaces and the adapters. `limit: 0` (a facet-only
|
|
83
101
|
* query) fetches no hits and has no meaningful page, so it pins to 1 rather
|
|
84
102
|
* than dividing by zero.
|
package/dist/query.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,UAAU,EAChB,MAAM,aAAa,CAAC;AAErB;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,wEAAwE;IACxE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,yBAAyB;IACzB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,2EAA2E;IAC3E,QAAQ,CAAC,OAAO,EAAE,SAAS,IAAI,EAAE,CAAC;IAClC,2BAA2B;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,uDAAuD;IACvD,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,+EAA+E;IAC/E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;;GAKG;AACH,MAAM,MAAM,MAAM,GACd;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GAC1D;IACE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE;QACd,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QAC/B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;KAChC,CAAC;CACH,GACD;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAA;CAAE,CAAC;AAErD,+BAA+B;AAC/B,MAAM,WAAW,IAAI;IACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,KAAK,GAAG,MAAM,CAAC;CACpC;AAKD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,gFAAgF;AAChF,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAE7D;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAK3D;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAC;IAC9C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EACb,eAAe,GAAG,gBAAgB,GAAG,mBAAmB,GAAG,eAAe,CAAC;CAC9E;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,WAAW,EAClB,UAAU,EAAE,UAAU,GACrB,SAAS,UAAU,EAAE,CA0DvB;AAED;yEACyE;AACzE,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,WAAW,EAClB,UAAU,EAAE,UAAU,GACrB,IAAI,CAUN;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAEnE"}
|
package/dist/query.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { fieldNamed, filterOperatorFor } from './schema.js';
|
|
1
|
+
import { fieldNamed, filterOperatorFor, ID_FIELD, } from './schema.js';
|
|
2
2
|
// The kind→operator table lives with the field model in schema.ts (one source
|
|
3
3
|
// for the query IR, the surfaces, the adapters AND declaration validation);
|
|
4
4
|
// re-exported here so the query-IR module stays the natural import site.
|
|
@@ -7,22 +7,55 @@ export { filterOperatorFor } from './schema.js';
|
|
|
7
7
|
export function filterOperator(filter) {
|
|
8
8
|
return 'in' in filter ? 'in' : 'range' in filter ? 'range' : 'is';
|
|
9
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* Whether the query asks for nothing, so no engine can answer it with a hit.
|
|
12
|
+
* True for an empty `in` on {@link ID_FIELD} – and only there, deliberately:
|
|
13
|
+
*
|
|
14
|
+
* An **identity** filter enumerates the documents wanted, so the empty set
|
|
15
|
+
* wants none. A **value** filter constrains a dimension, so an empty set
|
|
16
|
+
* constrains nothing – which is why every other vacuous clause is a no-op the
|
|
17
|
+
* compilers skip (a facet UI with nothing selected sends exactly that). The
|
|
18
|
+
* readings differ because the fields differ in kind, and only for `id` would
|
|
19
|
+
* “no constraint” hand back the whole collection to a caller who asked for
|
|
20
|
+
* specific things – the likely shape being a client mapping a possibly-empty
|
|
21
|
+
* reference array (`id: { in: doc.publisher }`) into a batch lookup.
|
|
22
|
+
*
|
|
23
|
+
* An adapter MUST answer an unsatisfiable query with an empty result rather
|
|
24
|
+
* than dispatching it.
|
|
25
|
+
*/
|
|
26
|
+
export function isUnsatisfiable(query) {
|
|
27
|
+
return query.where.some((filter) => filter.field === ID_FIELD && 'in' in filter && filter.in.length === 0);
|
|
28
|
+
}
|
|
10
29
|
/**
|
|
11
30
|
* Structurally validate a query against its search type: every `where` clause
|
|
12
31
|
* targets a declared, `filterable` field with the operator its kind accepts
|
|
13
|
-
* ({@link filterOperatorFor})
|
|
32
|
+
* ({@link filterOperatorFor}) – or the undeclared, always-filterable
|
|
33
|
+
* {@link ID_FIELD}, which takes `in`; every requested facet is a declared, `facetable`
|
|
14
34
|
* field; every sort is `relevance` or a declared field. Sorting deliberately
|
|
15
35
|
* checks declaration only, not the `sortable` flag: that flag means *publicly
|
|
16
36
|
* selectable*, and a deployment policy may sort on a private tie-break field.
|
|
17
37
|
*
|
|
18
38
|
* This is the port’s always-on guard: every {@link SearchEngine} adapter MUST
|
|
19
39
|
* reject a query with issues ({@link assertValidQuery}) instead of passing
|
|
20
|
-
* garbage to its engine, so validation holds for every caller
|
|
40
|
+
* garbage to its engine, so validation holds for every caller – including
|
|
21
41
|
* `queryDefaults` policies and surfaces weaker than GraphQL.
|
|
22
42
|
*/
|
|
23
43
|
export function validateQuery(query, searchType) {
|
|
24
44
|
const issues = [];
|
|
25
45
|
for (const filter of query.where) {
|
|
46
|
+
// `id` is filterable on every type without being declared by any: it is the
|
|
47
|
+
// document’s IRI, so the lookup exists wherever documents do. Membership
|
|
48
|
+
// only – an IRI has no range and no truth value.
|
|
49
|
+
if (filter.field === ID_FIELD) {
|
|
50
|
+
if (filterOperator(filter) !== 'in') {
|
|
51
|
+
issues.push({
|
|
52
|
+
part: 'where',
|
|
53
|
+
field: filter.field,
|
|
54
|
+
reason: 'operator-mismatch',
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
26
59
|
const field = fieldNamed(searchType, filter.field);
|
|
27
60
|
if (field === undefined) {
|
|
28
61
|
issues.push({
|
|
@@ -79,7 +112,7 @@ export function assertValidQuery(query, searchType) {
|
|
|
79
112
|
}
|
|
80
113
|
}
|
|
81
114
|
/**
|
|
82
|
-
* The 1-based page an `offset` falls on
|
|
115
|
+
* The 1-based page an `offset` falls on – the numbered-pagination presentation
|
|
83
116
|
* of the IR, shared by the surfaces and the adapters. `limit: 0` (a facet-only
|
|
84
117
|
* query) fetches no hits and has no meaningful page, so it pins to 1 rather
|
|
85
118
|
* than dividing by zero.
|
package/dist/schema.d.ts
CHANGED
|
@@ -341,8 +341,21 @@ export declare function labelFieldOf(searchType: SearchType): TextField | undefi
|
|
|
341
341
|
*/
|
|
342
342
|
export interface SearchTypeIssue {
|
|
343
343
|
readonly field: string;
|
|
344
|
-
readonly reason: 'duplicate-field-name' | 'invalid-field-name' | 'unknown-kind' | 'invalid-locale' | 'missing-ref' | 'ref-not-allowed' | 'text-requires-locales' | 'locales-not-allowed' | 'facet-ranges-not-allowed' | 'searchable-not-allowed' | 'transform-not-allowed' | 'derive-with-path' | 'text-not-filterable' | 'text-not-facetable';
|
|
344
|
+
readonly reason: 'duplicate-field-name' | 'invalid-field-name' | 'unknown-kind' | 'invalid-locale' | 'missing-ref' | 'ref-not-allowed' | 'text-requires-locales' | 'locales-not-allowed' | 'facet-ranges-not-allowed' | 'searchable-not-allowed' | 'transform-not-allowed' | 'derive-with-path' | 'text-not-filterable' | 'text-not-facetable' | 'reserved-field-name';
|
|
345
345
|
}
|
|
346
|
+
/**
|
|
347
|
+
* The reserved logical name of a document’s IRI – the one field every indexed
|
|
348
|
+
* thing carries, and the only one no {@link SearchType} declares. It is the
|
|
349
|
+
* hit’s identity ({@link SearchHit.id}), not a value in its
|
|
350
|
+
* {@link ResultDocument}, so it is surfaced and filtered by name alone.
|
|
351
|
+
*
|
|
352
|
+
* `id` answers *what the thing is*; a domain field like `schema:identifier`
|
|
353
|
+
* answers *what a source system calls it* (a catalogue or record number). Those
|
|
354
|
+
* are different questions, so a declaration may still carry an `identifier`
|
|
355
|
+
* field of its own – but never an `id` one, which
|
|
356
|
+
* {@link validateSearchType} rejects as `reserved-field-name`.
|
|
357
|
+
*/
|
|
358
|
+
export declare const ID_FIELD = "id";
|
|
346
359
|
/**
|
|
347
360
|
* Structurally validate one {@link SearchType} declaration – the
|
|
348
361
|
* declaration-time counterpart of `validateQuery`. Rules:
|
|
@@ -350,7 +363,7 @@ export interface SearchTypeIssue {
|
|
|
350
363
|
* - field names are unique (a duplicate would silently shadow in every
|
|
351
364
|
* consumer, each picking a different winner) and a metacharacter-free
|
|
352
365
|
* identifier (the name is interpolated into physical field names and the
|
|
353
|
-
* display RE2 pattern);
|
|
366
|
+
* display RE2 pattern), and is not the reserved {@link ID_FIELD};
|
|
354
367
|
* - a `text` field’s declared locales are BCP-47-shaped (no `_`, which is the
|
|
355
368
|
* reserved name↔locale separator);
|
|
356
369
|
* - a `reference` field that is `output` declares `ref` (the API surfaces
|
package/dist/schema.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD;;;;;;GAMG;AACH,MAAM,MAAM,SAAS,GACnB,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,WAAW,CAAC;AAE/E;oEACoE;AACpE,MAAM,MAAM,cAAc,GAAG,IAAI,GAAG,OAAO,GAAG,IAAI,CAAC;AAcnD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,GAAG,cAAc,GAAG,SAAS,CAE7E;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,MAAM,WAAW,GACrB,SAAS,GAAG,YAAY,GAAG,cAAc,GAAG,YAAY,GAAG,YAAY,CAAC;AAE1E,qEAAqE;AACrE,MAAM,WAAW,eAAe;IAC9B;wCACoC;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;+EAC2E;IAC3E,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,oBAAoB;IACpB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB;;yCAEqC;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,gEAAgE;IAChE,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,yBAAyB;IACzB,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAC9B,iCAAiC;IACjC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B,qFAAqF;IACrF,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,cAAc,KAAK,OAAO,CAAC;CACzD;AAED;kEACkE;AAClE,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,UAAU,CAAC,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CACnD;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,SAAU,SAAQ,eAAe,EAAE,UAAU;IAC5D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,UAAU,CAAC,EAAE,KAAK,CAAC;IAC5B,QAAQ,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC;IAC3B,QAAQ,CAAC,WAAW,CAAC,EAAE,KAAK,CAAC;CAC9B;AAED;gCACgC;AAChC,MAAM,WAAW,YAAa,SAAQ,eAAe,EAAE,UAAU;IAC/D,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,wEAAwE;IACxE,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAC/C,QAAQ,CAAC,WAAW,CAAC,EAAE,KAAK,CAAC;CAC9B;AAED,gFAAgF;AAChF,MAAM,WAAW,cAAe,SAAQ,eAAe,EAAE,UAAU;IACjE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,uCAAuC;IACvC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAC/C,QAAQ,CAAC,WAAW,CAAC,EAAE,KAAK,CAAC;IAC7B;;;;;;;OAOG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B;;0DAEsD;IACtD,QAAQ,CAAC,GAAG,CAAC,EAAE;QACb;;;;;;;;;kFAS0E;QAC1E,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B;;;;;+EAKuE;QACvE,QAAQ,CAAC,QAAQ,EAAE,WAAW,GAAG,QAAQ,GAAG,QAAQ,CAAC;KACtD,CAAC;CACH;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;CAC9C;AAED;;;;;GAKG;AACH,MAAM,WAAW,YAAa,SAAQ,eAAe,EAAE,cAAc;IACnE,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC7C,QAAQ,CAAC,UAAU,CAAC,EAAE,KAAK,CAAC;CAC7B;AAED,0DAA0D;AAC1D,MAAM,WAAW,YAAa,SAAQ,eAAe;IACnD,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,UAAU,CAAC,EAAE,KAAK,CAAC;IAC5B,QAAQ,CAAC,WAAW,CAAC,EAAE,KAAK,CAAC;CAC9B;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,+DAA+D;AAC/D,MAAM,WAAW,cAAc;IAC7B;;;;+CAI2C;IAC3C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,CAAC;CACzC;AAED;;;;;;GAMG;AACH,MAAM,WAAW,QAAS,SAAQ,cAAc;IAC9C;;kEAE8D;IAC9D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,aAAc,SAAQ,cAAc;IACnD;;;6CAGyC;IACzC,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;CACxB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,aAAa,CAAC;AAElD;;kEAEkE;AAClE,MAAM,MAAM,UAAU,CAAC,KAAK,SAAS,SAAS,UAAU,EAAE,IAAI,OAAO,CACnE,KAAK,CAAC,MAAM,CAAC,EACb;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAC3B,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,CAAC,IAAI,SAAS,UAAU,EAC5D,UAAU,EAAE,IAAI,GACf,IAAI,CAEN;AAED;;;;;;;;;;;GAWG;AACH;;;uCAGuC;AACvC,MAAM,CAAC,OAAO,CAAC,MAAM,iBAAiB,EAAE,OAAO,MAAM,CAAC;AAEtD,MAAM,WAAW,YAAY,CAC3B,KAAK,SAAS,SAAS,UAAU,EAAE,GAAG,SAAS,UAAU,EAAE,CAC3D,SAAQ,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;IAC9C,QAAQ,CAAC,CAAC,iBAAiB,CAAC,EAAE,IAAI,CAAC;CACpC;AAoBD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAAC,KAAK,CAAC,KAAK,SAAS,SAAS,UAAU,EAAE,EACpE,GAAG,KAAK,EAAE,KAAK,GACd,YAAY,CAAC,KAAK,CAAC,CAmCrB;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE,MAAM,GACX,aAAa,GAAG,SAAS,CAE3B;AAED;6EAC6E;AAC7E,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,WAAW,GACjB,KAAK,IAAI,cAAc,GAAG;IAC3B,QAAQ,CAAC,GAAG,EAAE;QAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;KAAE,CAAC;CAC1E,CAEA;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,YAAY,EACpB,UAAU,EAAE,UAAU,GACrB,MAAM,CAER;AA2ED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,UAAU,GAAG,SAAS,GAAG,SAAS,CAQ1E;AAsCD;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EACX,sBAAsB,GACtB,oBAAoB,GACpB,cAAc,GACd,gBAAgB,GAChB,aAAa,GACb,iBAAiB,GACjB,uBAAuB,GACvB,qBAAqB,GACrB,0BAA0B,GAC1B,wBAAwB,GACxB,uBAAuB,GACvB,kBAAkB,GAClB,qBAAqB,GACrB,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
|
package/dist/schema.js
CHANGED
|
@@ -210,6 +210,19 @@ function assertResolvableLabelSources(types) {
|
|
|
210
210
|
}
|
|
211
211
|
}
|
|
212
212
|
}
|
|
213
|
+
/**
|
|
214
|
+
* The reserved logical name of a document’s IRI – the one field every indexed
|
|
215
|
+
* thing carries, and the only one no {@link SearchType} declares. It is the
|
|
216
|
+
* hit’s identity ({@link SearchHit.id}), not a value in its
|
|
217
|
+
* {@link ResultDocument}, so it is surfaced and filtered by name alone.
|
|
218
|
+
*
|
|
219
|
+
* `id` answers *what the thing is*; a domain field like `schema:identifier`
|
|
220
|
+
* answers *what a source system calls it* (a catalogue or record number). Those
|
|
221
|
+
* are different questions, so a declaration may still carry an `identifier`
|
|
222
|
+
* field of its own – but never an `id` one, which
|
|
223
|
+
* {@link validateSearchType} rejects as `reserved-field-name`.
|
|
224
|
+
*/
|
|
225
|
+
export const ID_FIELD = 'id';
|
|
213
226
|
/** Kinds that can feed full-text search (project a folded search field). */
|
|
214
227
|
const SEARCHABLE_KINDS = ['text', 'keyword', 'reference'];
|
|
215
228
|
/** Kinds whose projection applies the {@link KeywordField.transform}. */
|
|
@@ -237,7 +250,7 @@ const LOCALE_PATTERN = /^[A-Za-z0-9]+(-[A-Za-z0-9]+)*$/;
|
|
|
237
250
|
* - field names are unique (a duplicate would silently shadow in every
|
|
238
251
|
* consumer, each picking a different winner) and a metacharacter-free
|
|
239
252
|
* identifier (the name is interpolated into physical field names and the
|
|
240
|
-
* display RE2 pattern);
|
|
253
|
+
* display RE2 pattern), and is not the reserved {@link ID_FIELD};
|
|
241
254
|
* - a `text` field’s declared locales are BCP-47-shaped (no `_`, which is the
|
|
242
255
|
* reserved name↔locale separator);
|
|
243
256
|
* - a `reference` field that is `output` declares `ref` (the API surfaces
|
|
@@ -277,6 +290,12 @@ export function validateSearchType(searchType) {
|
|
|
277
290
|
if (!FIELD_NAME_PATTERN.test(field.name)) {
|
|
278
291
|
issue('invalid-field-name');
|
|
279
292
|
}
|
|
293
|
+
// `id` is the document’s IRI, surfaced and filtered for every type; a
|
|
294
|
+
// declared field of that name would shadow it in the API output and in
|
|
295
|
+
// `where`, silently answering a different question.
|
|
296
|
+
if (field.name === ID_FIELD) {
|
|
297
|
+
issue('reserved-field-name');
|
|
298
|
+
}
|
|
280
299
|
// Every kind-dependent rule below would silently pass for a kind outside
|
|
281
300
|
// the union, so a typo’d kind in a plain-JS declaration must fail here.
|
|
282
301
|
if (!Object.hasOwn(OPERATOR_BY_KIND, field.kind)) {
|
package/dist/testing.d.ts
CHANGED
|
@@ -5,8 +5,9 @@ import type { SearchEngine } from './engine.js';
|
|
|
5
5
|
* live instance of itself, so the port rules hold by test rather than by
|
|
6
6
|
* prose. Covers schema binding (a type outside the bound schema is rejected),
|
|
7
7
|
* the always-on query validation (a structurally invalid query is rejected
|
|
8
|
-
* before it reaches the engine)
|
|
9
|
-
* `searchFacets` batch – for every type in the
|
|
8
|
+
* before it reaches the engine), the undeclared `id` lookup, and the result
|
|
9
|
+
* shape of a browse query and a `searchFacets` batch – for every type in the
|
|
10
|
+
* schema.
|
|
10
11
|
*
|
|
11
12
|
* ```ts
|
|
12
13
|
* describeSearchEngineContract('TypesenseSearchEngine', () => engine);
|
package/dist/testing.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAchD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,YAAY,GACzB,IAAI,CAuKN"}
|
package/dist/testing.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
2
|
import { filterOperatorFor, } from './query.js';
|
|
3
|
-
import { facetableFields, filterableFields } from './schema.js';
|
|
3
|
+
import { facetableFields, filterableFields, ID_FIELD, } from './schema.js';
|
|
4
4
|
/**
|
|
5
5
|
* The executable {@link SearchEngine} port contract (import from
|
|
6
6
|
* `@lde/search/testing`): a vitest suite every engine adapter runs against a
|
|
7
7
|
* live instance of itself, so the port rules hold by test rather than by
|
|
8
8
|
* prose. Covers schema binding (a type outside the bound schema is rejected),
|
|
9
9
|
* the always-on query validation (a structurally invalid query is rejected
|
|
10
|
-
* before it reaches the engine)
|
|
11
|
-
* `searchFacets` batch – for every type in the
|
|
10
|
+
* before it reaches the engine), the undeclared `id` lookup, and the result
|
|
11
|
+
* shape of a browse query and a `searchFacets` batch – for every type in the
|
|
12
|
+
* schema.
|
|
12
13
|
*
|
|
13
14
|
* ```ts
|
|
14
15
|
* describeSearchEngineContract('TypesenseSearchEngine', () => engine);
|
|
@@ -52,6 +53,22 @@ export function describeSearchEngineContract(name, engine) {
|
|
|
52
53
|
await expect(engine().search(searchType, query)).rejects.toThrow(/unknown-field/);
|
|
53
54
|
}
|
|
54
55
|
});
|
|
56
|
+
it('applies an `id` lookup rather than ignoring the clause', async () => {
|
|
57
|
+
// `id` is filterable on every type without being declared by any, so an
|
|
58
|
+
// adapter that resolves `where` fields through its declaration alone
|
|
59
|
+
// takes the unknown-field path and drops the clause – returning EVERY
|
|
60
|
+
// document where the caller asked for one. Pinned here because that
|
|
61
|
+
// failure is silent: no error, just the wrong result set.
|
|
62
|
+
for (const searchType of types()) {
|
|
63
|
+
const query = {
|
|
64
|
+
...browse(searchType),
|
|
65
|
+
where: [{ field: ID_FIELD, in: ['urn:test:no-such-document'] }],
|
|
66
|
+
};
|
|
67
|
+
const result = await engine().search(searchType, query);
|
|
68
|
+
expect(result.total).toBe(0);
|
|
69
|
+
expect(result.hits).toEqual([]);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
55
72
|
it('rejects a facet request for an unknown field', async () => {
|
|
56
73
|
for (const searchType of types()) {
|
|
57
74
|
const query = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lde/search",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Engine- and domain-agnostic core for RDF-backed search: a unified declarative field model (SearchField/SearchType/SearchSchema), a neutral query IR, the SearchEngine port with logical result types, and a streaming CONSTRUCT-to-document projection. Bakes in no engine, protocol, or domain.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"url": "git+https://github.com/ldelements/lde.git",
|