@lde/search 0.23.0 → 0.23.1

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 CHANGED
@@ -6,7 +6,7 @@
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, nestedReferenceType, nestedFieldName, referenceFields, referenceTypeNamed, inlineFramingDepth, fieldNamed, datasetField, ID_FIELD, AND_KEY, OR_KEY, labelFieldOf, labelFieldNameOf, labelSourceNameOf, DEFAULT_LABEL_FIELD, isRangeFacet, isAbsoluteIri, isoToUnixSeconds, unixSecondsToIso, } from './schema.js';
9
+ export { assertTypeInSchema, physicalFields, irAlias, displayFieldName, displayFieldPattern, displayLangOf, searchableFields, facetableFields, filterableFields, sortableFields, outputFields, isInternalField, isInlineReference, nestedReferenceType, nestedFieldName, referenceFields, referenceTypeNamed, rootTypeNamed, inlineFramingDepth, fieldNamed, datasetField, ID_FIELD, AND_KEY, OR_KEY, labelFieldOf, labelFieldNameOf, labelSourceNameOf, documentKeyOf, DEFAULT_LABEL_FIELD, isRangeFacet, isAbsoluteIri, isoToUnixSeconds, unixSecondsToIso, } from './schema.js';
10
10
  export type { PhysicalFields } from './schema.js';
11
11
  export { physicalNameTokens } from './physical-name.js';
12
12
  export { joinGraph, MAX_JOIN_DEPTH } from './join-graph.js';
@@ -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,mBAAmB,EACnB,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,UAAU,EACV,YAAY,EACZ,QAAQ,EACR,OAAO,EACP,MAAM,EACN,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,aAAa,EACb,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,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAC5D,YAAY,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,QAAQ,EACR,eAAe,EACf,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,mBAAmB,EACnB,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,aAAa,EACb,kBAAkB,EAClB,UAAU,EACV,YAAY,EACZ,QAAQ,EACR,OAAO,EACP,MAAM,EACN,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,mBAAmB,EACnB,YAAY,EACZ,aAAa,EACb,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,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAC5D,YAAY,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,QAAQ,EACR,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,7 +6,7 @@
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, nestedReferenceType, nestedFieldName, referenceFields, referenceTypeNamed, inlineFramingDepth, fieldNamed, datasetField, ID_FIELD, AND_KEY, OR_KEY, labelFieldOf, labelFieldNameOf, labelSourceNameOf, DEFAULT_LABEL_FIELD, isRangeFacet, isAbsoluteIri, isoToUnixSeconds, unixSecondsToIso, } from './schema.js';
9
+ export { assertTypeInSchema, physicalFields, irAlias, displayFieldName, displayFieldPattern, displayLangOf, searchableFields, facetableFields, filterableFields, sortableFields, outputFields, isInternalField, isInlineReference, nestedReferenceType, nestedFieldName, referenceFields, referenceTypeNamed, rootTypeNamed, inlineFramingDepth, fieldNamed, datasetField, ID_FIELD, AND_KEY, OR_KEY, labelFieldOf, labelFieldNameOf, labelSourceNameOf, documentKeyOf, DEFAULT_LABEL_FIELD, isRangeFacet, isAbsoluteIri, isoToUnixSeconds, unixSecondsToIso, } from './schema.js';
10
10
  export { physicalNameTokens } from './physical-name.js';
11
11
  export { joinGraph, MAX_JOIN_DEPTH } from './join-graph.js';
12
12
  export { filterOperatorFor, filterOperator, filterOn, isUnsatisfiable, validateQuery, assertValidQuery, pageForOffset, } from './query.js';
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { projectRoots } from './project.js';
2
2
  export type { ProjectedNode, ProjectionContext, SearchDocument, } from './project.js';
3
3
  export { defineSearchType, searchSchema, validateSearchType, assertValidSearchType, ID_FIELD, AND_KEY, OR_KEY, isoToUnixSeconds, unixSecondsToIso, } from './schema.js';
4
- export type { FieldKind, SearchField, SearchFieldBase, TextField, KeywordField, ReferenceField, ReferenceStrategy, NumericField, BooleanField, SearchType, SearchTypeBase, RootType, ReferenceType, RootTypeOf, SearchTypeIssue, SearchSchema, FacetRange, ProjectionValue, } from './schema.js';
4
+ export type { FieldKind, SearchField, SearchFieldBase, TextField, KeywordField, ReferenceField, ReferenceStrategy, NumericField, BooleanField, SearchType, SearchTypeBase, RootType, ReferenceType, RootTypeOf, SearchTypeIssue, KeyField, SearchSchema, FacetRange, ProjectionValue, } from './schema.js';
5
5
  export { joinGraph, MAX_JOIN_DEPTH } from './join-graph.js';
6
6
  export type { JoinGraph } from './join-graph.js';
7
7
  export { filterOn } from './query.js';
@@ -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,EACV,aAAa,EACb,iBAAiB,EACjB,cAAc,GACf,MAAM,cAAc,CAAC;AAKtB,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,kBAAkB,EAClB,qBAAqB,EACrB,QAAQ,EACR,OAAO,EACP,MAAM,EAMN,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,SAAS,EACT,WAAW,EACX,eAAe,EACf,SAAS,EACT,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,cAAc,EACd,QAAQ,EACR,aAAa,EACb,UAAU,EACV,eAAe,EACf,YAAY,EACZ,UAAU,EACV,eAAe,GAChB,MAAM,aAAa,CAAC;AAKrB,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAC5D,YAAY,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAOjD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EACV,WAAW,EACX,mBAAmB,EACnB,MAAM,EACN,SAAS,EACT,aAAa,EACb,IAAI,GACL,MAAM,YAAY,CAAC;AAIpB,YAAY,EACV,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,cAAc,EACd,WAAW,EACX,cAAc,EACd,SAAS,EACT,cAAc,EACd,WAAW,EACX,QAAQ,EACR,aAAa,EACb,aAAa,EACb,cAAc,GACf,MAAM,aAAa,CAAC;AAErB,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,YAAY,EACV,aAAa,EACb,iBAAiB,EACjB,cAAc,GACf,MAAM,cAAc,CAAC;AAKtB,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,kBAAkB,EAClB,qBAAqB,EACrB,QAAQ,EACR,OAAO,EACP,MAAM,EAMN,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,SAAS,EACT,WAAW,EACX,eAAe,EACf,SAAS,EACT,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,cAAc,EACd,QAAQ,EACR,aAAa,EACb,UAAU,EACV,eAAe,EACf,QAAQ,EACR,YAAY,EACZ,UAAU,EACV,eAAe,GAChB,MAAM,aAAa,CAAC;AAKrB,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAC5D,YAAY,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAOjD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EACV,WAAW,EACX,mBAAmB,EACnB,MAAM,EACN,SAAS,EACT,aAAa,EACb,IAAI,GACL,MAAM,YAAY,CAAC;AAIpB,YAAY,EACV,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,cAAc,EACd,WAAW,EACX,cAAc,EACd,SAAS,EACT,cAAc,EACd,WAAW,EACX,QAAQ,EACR,aAAa,EACb,aAAa,EACb,cAAc,GACf,MAAM,aAAa,CAAC;AAErB,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAGL,KAAK,UAAU,EAChB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAYL,KAAK,eAAe,EAEpB,KAAK,QAAQ,EAEb,KAAK,YAAY,EACjB,KAAK,UAAU,EAEhB,MAAM,aAAa,CAAC;AAErB;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEpD,+DAA+D;AAC/D,MAAM,MAAM,cAAc,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG,aAAa,CAAC;AAE5D;;;;;;;;;;GAUG;AACH,MAAM,WAAW,iBAAkB,SAAQ,OAAO,CAChD,QAAQ,CAAC,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,CAC1C;IACC,4CAA4C;IAC5C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAKD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,UAAU,EAChB,UAAU,EAAE,UAAU,EACtB,MAAM,CAAC,EAAE,YAAY,EACrB,OAAO,GAAE,iBAAyC,GACjD,cAAc,CAgBhB;AA2ED;;;;;;;;;;;;GAYG;AACH,wBAAuB,YAAY,CACjC,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,EACrB,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,MAAM,EAAE,YAAY,EACpB,UAAU,EAAE,QAAQ,EACpB,OAAO,GAAE,iBAAyC,GACjD,aAAa,CAAC,cAAc,CAAC,CAW/B"}
1
+ {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAGL,KAAK,UAAU,EAChB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAgBL,KAAK,eAAe,EAEpB,KAAK,QAAQ,EAEb,KAAK,YAAY,EACjB,KAAK,UAAU,EAEhB,MAAM,aAAa,CAAC;AAErB;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEpD,+DAA+D;AAC/D,MAAM,MAAM,cAAc,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG,aAAa,CAAC;AAE5D;;;;;;;;;;GAUG;AACH,MAAM,WAAW,iBAAkB,SAAQ,OAAO,CAChD,QAAQ,CAAC,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,CAC1C;IACC,4CAA4C;IAC5C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAKD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,UAAU,EAChB,UAAU,EAAE,UAAU,EACtB,MAAM,CAAC,EAAE,YAAY,EACrB,OAAO,GAAE,iBAAyC,GACjD,cAAc,CAgBhB;AAmHD;;;;;;;;;;;;GAYG;AACH,wBAAuB,YAAY,CACjC,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,EACrB,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,MAAM,EAAE,YAAY,EACpB,UAAU,EAAE,QAAQ,EACpB,OAAO,GAAE,iBAAyC,GACjD,aAAa,CAAC,cAAc,CAAC,CAc/B"}
package/dist/project.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { fold } from '@lde/text-normalization';
2
2
  import { buildSubjectIndex, frameSubjects, } from './frame-by-type.js';
3
- import { assertTypeInSchema, displayFieldName, inlineFramingDepth, irAlias, isAbsoluteIri, isInternalField, isInlineReference, isoToUnixSeconds, physicalFields, referenceTypeNamed, } from './schema.js';
3
+ import { assertTypeInSchema, displayFieldName, documentKeyOf, fieldNamed, inlineFramingDepth, irAlias, isAbsoluteIri, isInternalField, isInlineReference, isoToUnixSeconds, labelSourceNameOf, physicalFields, referenceTypeNamed, rootTypeNamed, } from './schema.js';
4
4
  /** The context a projection runs with when its caller supplied none. */
5
5
  const NO_PROJECTION_CONTEXT = {};
6
6
  /**
@@ -68,7 +68,7 @@ function pruneInternalFields(document, searchType, schema) {
68
68
  * once the whole nested structure is projected, so a derive at any depth can
69
69
  * still read an internal field before it is removed. */
70
70
  function projectFields(node, searchType, schema, context) {
71
- const id = documentKey(node);
71
+ const id = documentIdOf(node, searchType);
72
72
  const document = id === undefined ? {} : { id };
73
73
  for (const field of searchType.fields) {
74
74
  applyField(document, node, field, searchType, schema, context);
@@ -88,6 +88,33 @@ function documentKey(node) {
88
88
  const id = node['@id'];
89
89
  return typeof id === 'string' && isAbsoluteIri(id) ? id : undefined;
90
90
  }
91
+ /**
92
+ * The `id` a node is projected under: its own IRI, unless its type declares a
93
+ * {@link RootType.key} – then the key its key field carries
94
+ * ({@link documentKeyOf}). The candidates are read off the frame like any other
95
+ * field value, under the key field’s own {@link irAlias IR Alias}, because the
96
+ * key field *is* an ordinary declared field: the extraction already emits it,
97
+ * and a reader transform that repairs reference values has already run on it.
98
+ *
99
+ * The key is assigned before any `derive` runs, so a derive sees the key and
100
+ * never the node IRI; a deployment that wants the node IRI declares a plain
101
+ * `idOnly` reference over the same path.
102
+ */
103
+ function documentIdOf(node, searchType) {
104
+ const nodeIri = documentKey(node);
105
+ if (nodeIri === undefined || searchType.key === undefined) {
106
+ return nodeIri;
107
+ }
108
+ return documentKeyOf(searchType, nodeIri, keyCandidatesOf(node, searchType, searchType.key.field));
109
+ }
110
+ /** The raw values a node carries under a type’s key field – untransformed, as
111
+ * {@link documentKeyOf} expects them. Empty for a node the key field matched
112
+ * nothing on. The field itself is guaranteed declared by `searchSchema`, which
113
+ * is what validates a `key` at all. */
114
+ function keyCandidatesOf(node, searchType, name) {
115
+ const keyField = fieldNamed(searchType, name);
116
+ return irisOf(node, irAlias(searchType, keyField));
117
+ }
91
118
  /**
92
119
  * Project a single type over a known set of `roots` – the per-type, roots-given
93
120
  * projection. The roots are supplied by the caller (the pipeline selector)
@@ -106,8 +133,11 @@ export async function* projectRoots(quads, roots, schema, searchType, context =
106
133
  const index = buildSubjectIndex(quads);
107
134
  // Distinct roots only. A selector may return an IRI more than once – a
108
135
  // non-`DISTINCT` `SELECT` over a one-to-many join yields the same subject per
109
- // matched row – and a repeated root would otherwise frame and emit a
110
- // duplicate document under the same `id`.
136
+ // matched row – and framing a root twice would do the same work twice for one
137
+ // node. Distinct roots may still legitimately share an `id`, where the type
138
+ // declares a `key` two of them carry: that is what a document key means, and
139
+ // it is the writer’s upsert – not the projection – that folds them into one
140
+ // document.
111
141
  const depth = inlineFramingDepth(schema, searchType);
112
142
  for await (const node of frameSubjects(index, [...new Set(roots)], depth)) {
113
143
  yield projectDocument(node, searchType, schema, context);
@@ -179,7 +209,7 @@ function applyField(document, node, field, searchType, schema, context) {
179
209
  case 'keyword':
180
210
  return applyFacet(document, literalsOf(node, alias), field);
181
211
  case 'reference':
182
- return applyFacet(document, irisOf(node, alias), field);
212
+ return applyFacet(document, referenceValues(node, alias, field, schema), field);
183
213
  case 'integer':
184
214
  return setNumber(document, field.name, toInteger(firstLiteralOf(node, alias)));
185
215
  case 'number':
@@ -198,6 +228,53 @@ function applyField(document, node, field, searchType, schema, context) {
198
228
  }
199
229
  }
200
230
  }
231
+ /**
232
+ * The values a non-inline reference stores: the referents’ IRIs, **or their
233
+ * document keys** when the type the reference names declares a
234
+ * {@link RootType.key}. A `lookup`’s `target` and an `idOnly`’s `labelSource`
235
+ * both mean *this field holds ids of documents in that collection* (ADR 20) –
236
+ * the fact a label lookup and a join rely on – so storing the node IRI where
237
+ * the target keys on something else would break an invariant the schema already
238
+ * has. Rewriting a reference is LDE keeping it, not a new rule.
239
+ *
240
+ * That is also why the boundary is *naming the target*: a reference that names
241
+ * none ({@link labelSourceNameOf} → `undefined`) never claimed to hold a
242
+ * collection’s ids, and a `derive`d one produces its own values rather than
243
+ * reading a referent, so neither is re-keyed.
244
+ *
245
+ * The referent’s candidates are in the frame because framing already embeds a
246
+ * referenced node’s own triples at one hop, and the extraction adds the key
247
+ * field to that hop. A projection run without a `schema` cannot resolve the
248
+ * target, so it leaves the values as they are – exactly as it leaves an inline
249
+ * reference unprojected.
250
+ *
251
+ * The referring field’s own {@link ReferenceField.transform} still runs after
252
+ * this, in {@link applyFacet}: a `transform` transforms what the field stores,
253
+ * and for a keyed target that is the key. A `transform` written to repair the
254
+ * referent’s node IRIs therefore sees a key instead, which is why the two are
255
+ * worth declaring together only deliberately.
256
+ */
257
+ function referenceValues(node, alias, field, schema) {
258
+ const targetName = labelSourceNameOf(field);
259
+ if (schema === undefined || targetName === undefined) {
260
+ return irisOf(node, alias);
261
+ }
262
+ // Guaranteed declared: `searchSchema` validates that every named target
263
+ // resolves, and the projection only ever runs against a type of its schema.
264
+ const target = rootTypeNamed(schema, targetName);
265
+ if (target.key === undefined) {
266
+ return irisOf(node, alias);
267
+ }
268
+ const keyFieldName = target.key.field;
269
+ return valuesOf(node, alias)
270
+ .map((value) => {
271
+ const iri = iriString(value);
272
+ return iri === undefined
273
+ ? undefined
274
+ : documentKeyOf(target, iri, isObject(value) ? keyCandidatesOf(value, target, keyFieldName) : []);
275
+ })
276
+ .filter((value) => value !== undefined);
277
+ }
201
278
  /**
202
279
  * Project a text field. **Display** (when `output`) preserves *every* language
203
280
  * present – one label per language (accents preserved, untagged under `und`),
package/dist/schema.d.ts CHANGED
@@ -321,6 +321,56 @@ export interface SearchTypeBase {
321
321
  readonly labelField?: string;
322
322
  readonly fields: readonly SearchField[];
323
323
  }
324
+ /**
325
+ * Which declared field of a {@link RootType} holds its **document key**, when
326
+ * that key is not the node’s own IRI. It has the shape of
327
+ * {@link SearchTypeBase.labelField} – *which field is the label* – and says
328
+ * *which field holds the key*: a statement about the search document, never
329
+ * about the world, so the words a deployment reaches for (identity, alignment,
330
+ * canonical, authority) stay in the deployment’s own schema comments.
331
+ *
332
+ * Two things that already hold of keys then hold here too, without a new rule:
333
+ * several nodes sharing a key are **one document** (the writer upserts by `id`,
334
+ * so a deployment that wants particular content on the merged document attaches
335
+ * a transform, and one that does not gets last-writer-wins), and a reference
336
+ * into a keyed type stores the **target’s key** – a `lookup`/`labelSource`
337
+ * already means *this field holds ids of documents in that collection*
338
+ * (ADR 20), which storing the node IRI would break.
339
+ *
340
+ * See [ADR 22](../../docs/decisions/0022-key-a-root-type-on-a-declared-field.md).
341
+ */
342
+ export interface KeyField {
343
+ /**
344
+ * The `name` of a declared field of this type whose values are the key
345
+ * candidates: a path-bearing, `array` {@link ReferenceField} that is not
346
+ * `inline` ({@link searchSchema} validates all four). Being an ordinary field
347
+ * is the point – its extraction branch already exists, a reader transform
348
+ * that repairs reference values covers it the day it is declared, and its own
349
+ * {@link ReferenceField.transform} is where IRI normalisation lives, so two
350
+ * spellings of one IRI become one candidate before anything chooses among
351
+ * them.
352
+ *
353
+ * A transform that **replaces** a root’s quads must re-emit this field, the
354
+ * existing rule that *a field the document needs must be in the stream*
355
+ * applied to one more field; a transform that only adds never meets it.
356
+ */
357
+ readonly field: string;
358
+ /**
359
+ * Choose the key among the candidates – the key field’s values after its
360
+ * `transform`, IRI-filtered, deduplicated and sorted, so the default is
361
+ * deterministic whatever order the CONSTRUCT returned them in. Return one of
362
+ * them, or `undefined` to keep the node’s own IRI; anything else throws at
363
+ * projection. Not consulted for a node whose key field is empty.
364
+ *
365
+ * Must be **pure**: the same function keys the document and every reference
366
+ * to it, so a `pick` that consulted the network or the clock could key the
367
+ * two differently and leave a reference dangling. LDE never inspects an
368
+ * IRI’s shape – it asks.
369
+ *
370
+ * @default the first candidate
371
+ */
372
+ readonly pick?: (candidates: readonly string[]) => string | undefined;
373
+ }
324
374
  /**
325
375
  * A **Root Type**: a {@link SearchType} that is indexed. It declares a `class`,
326
376
  * roots are selected for it, a Writer owns a collection for it, and the
@@ -333,6 +383,9 @@ export interface RootType extends SearchTypeBase {
333
383
  * key a {@link SearchSchema} maps this type under. Its presence is what makes
334
384
  * a type a Root Type – and so what gives it a collection. */
335
385
  readonly class: string;
386
+ /** Which declared field holds this type’s document key, when it is not the
387
+ * node’s own IRI ({@link KeyField}, {@link documentKeyOf}). */
388
+ readonly key?: KeyField;
336
389
  }
337
390
  /**
338
391
  * A **Reference Type**: a {@link SearchType} reached only through an
@@ -350,6 +403,10 @@ export interface ReferenceType extends SearchTypeBase {
350
403
  * {@link SearchField} discriminates by `kind`: an indexed Reference Type
351
404
  * fails to compile, not at run time. */
352
405
  readonly class?: never;
406
+ /** A Reference Type has no document key to declare: it is nested inside its
407
+ * referrer rather than keyed in a collection of its own. `never` for the
408
+ * same reason `class` is. */
409
+ readonly key?: never;
353
410
  }
354
411
  /**
355
412
  * One type’s complete search declaration: its logical API `name`, the queryable
@@ -420,6 +477,19 @@ export declare function searchSchema<const Types extends readonly SearchType[]>(
420
477
  * resolves an inline reference’s referent shape through it.
421
478
  */
422
479
  export declare function referenceTypeNamed(schema: SearchSchema, name: string): ReferenceType | undefined;
480
+ /**
481
+ * The {@link RootType} a declaration names – a `lookup`’s `target`, an
482
+ * `idOnly`’s {@link ReferenceField.labelSource} ({@link labelSourceNameOf}), a
483
+ * join edge – or `undefined` when the schema declares no Root Type by that
484
+ * name. The one reading of *which type does this point at*, so the projection
485
+ * (which re-keys a reference through its target’s {@link KeyField}), the
486
+ * label-source validation and an adapter’s lookup cannot resolve a target
487
+ * differently.
488
+ *
489
+ * Complements {@link referenceTypeNamed}: the two name indexes are disjoint,
490
+ * because {@link searchSchema} rejects a name declared twice.
491
+ */
492
+ export declare function rootTypeNamed(schema: SearchSchema, name: string): RootType | undefined;
423
493
  /** Whether a field is an inline reference – a {@link ReferenceField} whose
424
494
  * `ref` carries its referent’s projected fields ({@link ReferenceType}). */
425
495
  export declare function isInlineReference(field: SearchField): field is ReferenceField & {
@@ -495,7 +565,7 @@ export declare function labelSourceNameOf(field: ReferenceField): string | undef
495
565
  */
496
566
  export interface SearchTypeIssue {
497
567
  readonly field: string;
498
- readonly reason: 'duplicate-field-name' | 'invalid-field-name' | 'unknown-kind' | 'invalid-locale' | 'missing-ref' | 'missing-ref-type-name' | 'ref-not-allowed' | 'text-requires-locales' | 'locales-not-allowed' | 'facet-ranges-not-allowed' | 'searchable-not-allowed' | 'transform-not-allowed' | 'derive-with-path' | 'from-not-allowed' | 'from-with-path' | 'from-with-derive' | 'from-with-inline-ref' | 'unknown-projection-value' | 'duplicate-projection-value' | 'text-not-filterable' | 'text-not-facetable' | 'joinable-not-allowed' | 'joinable-without-label-source' | 'joinable-with-inline-ref' | 'reserved-field-name';
568
+ readonly reason: 'duplicate-field-name' | 'invalid-field-name' | 'unknown-kind' | 'invalid-locale' | 'missing-ref' | 'missing-ref-type-name' | 'ref-not-allowed' | 'text-requires-locales' | 'locales-not-allowed' | 'facet-ranges-not-allowed' | 'searchable-not-allowed' | 'transform-not-allowed' | 'derive-with-path' | 'from-not-allowed' | 'from-with-path' | 'from-with-derive' | 'from-with-inline-ref' | 'unknown-projection-value' | 'duplicate-projection-value' | 'text-not-filterable' | 'text-not-facetable' | 'joinable-not-allowed' | 'joinable-without-label-source' | 'joinable-with-inline-ref' | 'reserved-field-name' | 'key-field-unknown' | 'key-field-not-reference' | 'key-field-without-path' | 'key-field-not-array' | 'key-field-inline' | 'key-pick-not-a-function' | 'key-not-allowed';
499
569
  }
500
570
  /**
501
571
  * The reserved logical name of a document’s IRI – the one field every indexed
@@ -565,7 +635,10 @@ export declare const OR_KEY = "or";
565
635
  * field has exactly one), is not an `inline` reference (a projection value is
566
636
  * a bare IRI, with no referent to carry fields from), and no two fields
567
637
  * declare the same projection value – which would leave a consumer reading
568
- * the dataset off a declaration no rule picks between.
638
+ * the dataset off a declaration no rule picks between;
639
+ * - a {@link RootType.key} names a declared, `path`-bearing, `array`,
640
+ * non-`inline` `reference` field of this type, and its `pick` is a function
641
+ * ({@link keyIssues}); a {@link ReferenceType} declares no key at all.
569
642
  *
570
643
  * Pure and total: returns every issue rather than throwing;
571
644
  * {@link assertValidSearchType} is the throwing entry point.
@@ -688,6 +761,38 @@ export declare function referenceFields(searchType: SearchType): readonly Refere
688
761
  export declare function datasetField(searchType: SearchType): (KeywordField | ReferenceField) | undefined;
689
762
  /** Look up a field by its logical name. */
690
763
  export declare function fieldNamed(searchType: SearchType, name: string): SearchField | undefined;
764
+ /**
765
+ * The **document key** of one node of `searchType`: what the projection writes
766
+ * as the document’s `id`, and what a reference into this type stores.
767
+ *
768
+ * The whole rule, in one place, so the projection and any transform that needs
769
+ * to know a node’s key read the same answer:
770
+ *
771
+ * 1. a type declaring no {@link RootType.key} keys on `nodeIri` – the node’s own
772
+ * IRI, as every type does today;
773
+ * 2. otherwise the key field’s `rawValues` become **candidates**: its
774
+ * {@link ReferenceField.transform} (where IRI normalisation lives, so two
775
+ * spellings of one IRI become one candidate), then the
776
+ * {@link isAbsoluteIri} filter, then dedupe and sort – so the default is
777
+ * deterministic whatever order the CONSTRUCT returned them in;
778
+ * 3. no candidate keys on `nodeIri`, without consulting {@link KeyField.pick};
779
+ * 4. otherwise {@link KeyField.pick} chooses (defaulting to the first
780
+ * candidate), and `undefined` keeps `nodeIri`.
781
+ *
782
+ * So a key is always either the node’s own IRI or an IRI the graph offered for
783
+ * that node – never one invented in between. A `pick` returning anything else
784
+ * throws, naming the node and the candidates: it is a bug in a pure function
785
+ * that keys both the document and every reference to it, and letting it through
786
+ * would key those two differently.
787
+ *
788
+ * @param nodeIri the node’s own IRI – the key it falls back to
789
+ * @param rawValues the key field’s values **as a reference field reads them** –
790
+ * a node’s `@id` or a bare-string value, before the field’s `transform`. A
791
+ * caller that reads them itself (a transform working on quads) must apply the
792
+ * same rule and skip a literal-valued object, or it will compute a key for a
793
+ * value the projection never saw and key the two differently.
794
+ */
795
+ export declare function documentKeyOf(searchType: RootType, nodeIri: string, rawValues: readonly string[]): string;
691
796
  /**
692
797
  * The **IR Alias** predicate for a field: `urn:lde:‹SearchType.name›/‹field.name›`.
693
798
  * The extraction CONSTRUCT emits a field’s value under this minted predicate, and
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
package/dist/schema.js CHANGED
@@ -36,6 +36,17 @@ export function defineSearchType(searchType) {
36
36
  * through {@link referenceTypeNamed}.
37
37
  */
38
38
  const referenceTypesBySchema = new WeakMap();
39
+ /**
40
+ * The Root Type name index each {@link SearchSchema} carries alongside its
41
+ * class-keyed map. A schema is keyed by `class` because that is what a selector
42
+ * and a Writer address it by, while every declaration that points at another
43
+ * type – a `lookup`’s `target`, an `idOnly`’s `labelSource`, a join edge –
44
+ * names it. Kept beside the map rather than rebuilt per consumer, so the
45
+ * projection, the label-source validation and an adapter’s lookup resolve a
46
+ * target the same way ({@link rootTypeNamed}) instead of each maintaining a
47
+ * by-name map of its own.
48
+ */
49
+ const rootTypesBySchema = new WeakMap();
39
50
  /** Whether a declared type is a {@link RootType} (declares a `class`) rather
40
51
  * than a {@link ReferenceType}. */
41
52
  function isRootType(searchType) {
@@ -80,12 +91,16 @@ export function searchSchema(...types) {
80
91
  .map((searchType) => [searchType.name, searchType]));
81
92
  assertResolvableInlineReferences(types, referenceTypes);
82
93
  assertServiceableNestedFields(referenceTypes);
83
- assertResolvableLabelSources(types);
84
- // The one blessed cast: only this validated constructor mints the brand.
85
- const schema = new Map(types
86
- .filter(isRootType)
87
- .map((searchType) => [searchType.class, searchType]));
94
+ // The one blessed cast: only this validated constructor mints the brand. Built
95
+ // BEFORE the schema-wide assertions that resolve a type by name, so they can
96
+ // use `rootTypeNamed` – the same reading the projection and an adapter's
97
+ // lookup use – rather than a by-name map of their own. The schema stays local
98
+ // until every assertion has passed, so an invalid one is never observable.
99
+ const rootTypes = types.filter(isRootType);
100
+ const schema = new Map(rootTypes.map((searchType) => [searchType.class, searchType]));
88
101
  referenceTypesBySchema.set(schema, referenceTypes);
102
+ rootTypesBySchema.set(schema, new Map(rootTypes.map((searchType) => [searchType.name, searchType])));
103
+ assertResolvableLabelSources(types, schema);
89
104
  // Build the join graph eagerly and discard it: it is cached per schema, and
90
105
  // building it is what enforces the schema-wide join rules (one joinable
91
106
  // reference per target, every target an indexed Root Type, no cycles). A
@@ -103,6 +118,21 @@ export function searchSchema(...types) {
103
118
  export function referenceTypeNamed(schema, name) {
104
119
  return referenceTypesBySchema.get(schema)?.get(name);
105
120
  }
121
+ /**
122
+ * The {@link RootType} a declaration names – a `lookup`’s `target`, an
123
+ * `idOnly`’s {@link ReferenceField.labelSource} ({@link labelSourceNameOf}), a
124
+ * join edge – or `undefined` when the schema declares no Root Type by that
125
+ * name. The one reading of *which type does this point at*, so the projection
126
+ * (which re-keys a reference through its target’s {@link KeyField}), the
127
+ * label-source validation and an adapter’s lookup cannot resolve a target
128
+ * differently.
129
+ *
130
+ * Complements {@link referenceTypeNamed}: the two name indexes are disjoint,
131
+ * because {@link searchSchema} rejects a name declared twice.
132
+ */
133
+ export function rootTypeNamed(schema, name) {
134
+ return rootTypesBySchema.get(schema)?.get(name);
135
+ }
106
136
  /** Whether a field is an inline reference – a {@link ReferenceField} whose
107
137
  * `ref` carries its referent’s projected fields ({@link ReferenceType}). */
108
138
  export function isInlineReference(field) {
@@ -311,13 +341,13 @@ export function labelSourceNameOf(field) {
311
341
  * can actually serve labels ({@link labelFieldOf}). Checked schema-wide,
312
342
  * because a single declaration cannot see its siblings.
313
343
  *
314
- * That leaves only a {@link RootType}, without naming one: a label field is
315
- * `searchable`, and {@link assertServiceableNestedFields} already rejects a
316
- * `searchable` field on a Reference Type – so a Reference Type can never serve
317
- * labels, and a resolved label always has a collection to come from.
344
+ * Resolved through {@link rootTypeNamed}, which is exactly the set that can
345
+ * serve labels: a label field is `searchable`, and
346
+ * {@link assertServiceableNestedFields} – which runs first – already rejects a
347
+ * `searchable` field on a Reference Type, so a resolved label always has a
348
+ * collection to come from.
318
349
  */
319
- function assertResolvableLabelSources(types) {
320
- const byName = new Map(types.map((searchType) => [searchType.name, searchType]));
350
+ function assertResolvableLabelSources(types, schema) {
321
351
  for (const searchType of types) {
322
352
  for (const field of searchType.fields) {
323
353
  const labelSource = field
@@ -339,9 +369,15 @@ function assertResolvableLabelSources(types) {
339
369
  if (sourceName === undefined) {
340
370
  continue;
341
371
  }
342
- const source = byName.get(sourceName);
372
+ const source = rootTypeNamed(schema, sourceName);
343
373
  if (source === undefined) {
344
- throw new Error(`Reference “${searchType.name}.${field.name}” names unknown label source “${sourceName}”; declare a SearchType with that name.`);
374
+ // A name that IS declared, just not as a Root Type, is the confusing
375
+ // case: telling the author to declare a type they already declared
376
+ // would send them looking in the wrong place. Only a Root Type has a
377
+ // collection to resolve against, so name that instead.
378
+ throw new Error(referenceTypeNamed(schema, sourceName) === undefined
379
+ ? `Reference “${searchType.name}.${field.name}” names unknown label source “${sourceName}”; declare a SearchType with that name.`
380
+ : `Reference “${searchType.name}.${field.name}” names label source “${sourceName}”, which is a Reference Type; a label source must be a Root Type, since a resolved label is read from that type’s own collection.`);
345
381
  }
346
382
  if (labelFieldOf(source) === undefined) {
347
383
  throw new Error(`Reference “${searchType.name}.${field.name}” uses label source “${sourceName}”, which must declare an output, searchable text field “${labelFieldNameOf(source)}”.`);
@@ -449,7 +485,10 @@ const LOCALE_PATTERN = /^[A-Za-z0-9]+(-[A-Za-z0-9]+)*$/;
449
485
  * field has exactly one), is not an `inline` reference (a projection value is
450
486
  * a bare IRI, with no referent to carry fields from), and no two fields
451
487
  * declare the same projection value – which would leave a consumer reading
452
- * the dataset off a declaration no rule picks between.
488
+ * the dataset off a declaration no rule picks between;
489
+ * - a {@link RootType.key} names a declared, `path`-bearing, `array`,
490
+ * non-`inline` `reference` field of this type, and its `pick` is a function
491
+ * ({@link keyIssues}); a {@link ReferenceType} declares no key at all.
453
492
  *
454
493
  * Pure and total: returns every issue rather than throwing;
455
494
  * {@link assertValidSearchType} is the throwing entry point.
@@ -596,6 +635,58 @@ export function validateSearchType(searchType) {
596
635
  }
597
636
  }
598
637
  }
638
+ issues.push(...keyIssues(searchType));
639
+ return issues;
640
+ }
641
+ /**
642
+ * The issues a type’s {@link RootType.key} declaration carries, each filed
643
+ * under the field name the declaration names – so a message reads like every
644
+ * other one, naming the field the rule is about rather than a member.
645
+ *
646
+ * The key field must be an ordinary declared field the extraction already
647
+ * reads and the projection already applies a `transform` to: a `reference`
648
+ * (candidates are IRIs), with a `path` (a key read from the graph, not one
649
+ * derived from a document that is keyed already), `array` (a node may offer
650
+ * several candidates, and a single-valued field would drop all but the first
651
+ * before `pick` ever saw them), and not `inline` (which carries the referent’s
652
+ * fields rather than its IRI, so it offers no candidate at all).
653
+ */
654
+ function keyIssues(searchType) {
655
+ const key = searchType.key;
656
+ if (key === undefined) {
657
+ return [];
658
+ }
659
+ const issue = (reason) => ({
660
+ field: key.field,
661
+ reason,
662
+ });
663
+ // A Reference Type is nested inside its referrer, never keyed in a collection
664
+ // of its own – so a key on one states a rule nothing could apply.
665
+ if (searchType.class === undefined) {
666
+ return [issue('key-not-allowed')];
667
+ }
668
+ const issues = [];
669
+ if (key.pick !== undefined && typeof key.pick !== 'function') {
670
+ issues.push(issue('key-pick-not-a-function'));
671
+ }
672
+ const field = fieldNamed(searchType, key.field);
673
+ if (field === undefined) {
674
+ issues.push(issue('key-field-unknown'));
675
+ return issues;
676
+ }
677
+ if (field.kind !== 'reference') {
678
+ issues.push(issue('key-field-not-reference'));
679
+ return issues;
680
+ }
681
+ if (field.path === undefined) {
682
+ issues.push(issue('key-field-without-path'));
683
+ }
684
+ if (field.array !== true) {
685
+ issues.push(issue('key-field-not-array'));
686
+ }
687
+ if (field.ref?.strategy === 'inline') {
688
+ issues.push(issue('key-field-inline'));
689
+ }
599
690
  return issues;
600
691
  }
601
692
  /**
@@ -750,6 +841,66 @@ export function datasetField(searchType) {
750
841
  export function fieldNamed(searchType, name) {
751
842
  return searchType.fields.find((field) => field.name === name);
752
843
  }
844
+ /**
845
+ * The **document key** of one node of `searchType`: what the projection writes
846
+ * as the document’s `id`, and what a reference into this type stores.
847
+ *
848
+ * The whole rule, in one place, so the projection and any transform that needs
849
+ * to know a node’s key read the same answer:
850
+ *
851
+ * 1. a type declaring no {@link RootType.key} keys on `nodeIri` – the node’s own
852
+ * IRI, as every type does today;
853
+ * 2. otherwise the key field’s `rawValues` become **candidates**: its
854
+ * {@link ReferenceField.transform} (where IRI normalisation lives, so two
855
+ * spellings of one IRI become one candidate), then the
856
+ * {@link isAbsoluteIri} filter, then dedupe and sort – so the default is
857
+ * deterministic whatever order the CONSTRUCT returned them in;
858
+ * 3. no candidate keys on `nodeIri`, without consulting {@link KeyField.pick};
859
+ * 4. otherwise {@link KeyField.pick} chooses (defaulting to the first
860
+ * candidate), and `undefined` keeps `nodeIri`.
861
+ *
862
+ * So a key is always either the node’s own IRI or an IRI the graph offered for
863
+ * that node – never one invented in between. A `pick` returning anything else
864
+ * throws, naming the node and the candidates: it is a bug in a pure function
865
+ * that keys both the document and every reference to it, and letting it through
866
+ * would key those two differently.
867
+ *
868
+ * @param nodeIri the node’s own IRI – the key it falls back to
869
+ * @param rawValues the key field’s values **as a reference field reads them** –
870
+ * a node’s `@id` or a bare-string value, before the field’s `transform`. A
871
+ * caller that reads them itself (a transform working on quads) must apply the
872
+ * same rule and skip a literal-valued object, or it will compute a key for a
873
+ * value the projection never saw and key the two differently.
874
+ */
875
+ export function documentKeyOf(searchType, nodeIri, rawValues) {
876
+ const key = searchType.key;
877
+ if (key === undefined) {
878
+ return nodeIri;
879
+ }
880
+ // Guaranteed a declared reference field by `searchSchema`, which is what
881
+ // validates a `key` at all.
882
+ const { transform } = fieldNamed(searchType, key.field);
883
+ const candidates = [
884
+ ...new Set((transform === undefined ? rawValues : rawValues.map(transform)).filter(isAbsoluteIri)),
885
+ ].sort();
886
+ if (candidates.length === 0) {
887
+ return nodeIri;
888
+ }
889
+ const picked = (key.pick ?? firstCandidate)(candidates);
890
+ if (picked === undefined) {
891
+ return nodeIri;
892
+ }
893
+ if (!candidates.includes(picked)) {
894
+ throw new Error(`The “pick” of “${searchType.name}.key” returned “${picked}” for <${nodeIri}>, which is not among its candidates (${candidates
895
+ .map((candidate) => `<${candidate}>`)
896
+ .join(', ')}); a key must be one of them, or “undefined” to keep the node’s own IRI.`);
897
+ }
898
+ return picked;
899
+ }
900
+ /** The {@link KeyField.pick} a type that declares none falls back to. */
901
+ function firstCandidate(candidates) {
902
+ return candidates[0];
903
+ }
753
904
  /**
754
905
  * The **IR Alias** predicate for a field: `urn:lde:‹SearchType.name›/‹field.name›`.
755
906
  * The extraction CONSTRUCT emits a field’s value under this minted predicate, and
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lde/search",
3
- "version": "0.23.0",
3
+ "version": "0.23.1",
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",