@_linked/core 2.2.0-next.20260320002642 → 2.2.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 +239 -21
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,43 @@
|
|
|
2
2
|
|
|
3
3
|
## 2.2.0
|
|
4
4
|
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#34](https://github.com/Semantu/linked/pull/34) [`e2ae4a2`](https://github.com/Semantu/linked/commit/e2ae4a28e5be28716e1634ca81d9c379a291cbc6) Thanks [@flyon](https://github.com/flyon)! - ### SHACL property path support
|
|
8
|
+
|
|
9
|
+
Property decorators now accept full SPARQL property path syntax:
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
@literalProperty({path: 'foaf:knows/foaf:name'}) // sequence
|
|
13
|
+
@literalProperty({path: '<http://ex.org/a>|<http://ex.org/b>'}) // alternative
|
|
14
|
+
@literalProperty({path: '^foaf:knows'}) // inverse
|
|
15
|
+
@literalProperty({path: 'foaf:knows*'}) // zeroOrMore
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
New exports from `src/paths/`:
|
|
19
|
+
|
|
20
|
+
- `PathExpr`, `PathRef` — AST types for property paths
|
|
21
|
+
- `parsePropertyPath(input): PathExpr` — parser for SPARQL property path strings
|
|
22
|
+
- `normalizePropertyPath(input): PathExpr` — normalizes any input form to canonical AST
|
|
23
|
+
- `pathExprToSparql(expr): string` — renders PathExpr to SPARQL syntax
|
|
24
|
+
- `serializePathToSHACL(expr): SHACLPathResult` — serializes to SHACL RDF triples
|
|
25
|
+
|
|
26
|
+
`PropertyShape.path` is now typed as `PathExpr` (was opaque). Complex paths flow through the full IR pipeline and emit correct SPARQL property path syntax in generated queries.
|
|
27
|
+
|
|
28
|
+
### Strict prefix resolution in query API
|
|
29
|
+
|
|
30
|
+
`QueryBuilder.for()` and `.forAll()` now throw on unregistered prefixes instead of silently passing through. New export:
|
|
31
|
+
|
|
32
|
+
- `resolveUriOrThrow(str): string` — strict prefix resolution (throws on unknown prefix)
|
|
33
|
+
|
|
34
|
+
### SHACL constraint field fixes
|
|
35
|
+
|
|
36
|
+
- `hasValue` and `in` config fields now correctly handle literal values (`string`, `number`, `boolean`) — previously all values were wrapped as IRI nodes
|
|
37
|
+
- `lessThan` and `lessThanOrEquals` config fields are now wired into `createPropertyShape` and exposed via `getResult()`
|
|
38
|
+
- New `PropertyShapeResult` interface provides typed access to `getResult()` output
|
|
39
|
+
|
|
40
|
+
## 2.1.0
|
|
41
|
+
|
|
5
42
|
### Minor Changes
|
|
6
43
|
|
|
7
44
|
- [#31](https://github.com/Semantu/linked/pull/31) [`eb88865`](https://github.com/Semantu/linked/commit/eb8886564f2c9663805c4308a834ca615f9a1dab) Thanks [@flyon](https://github.com/flyon)! - Properties in `select()` and `update()` now support expressions — you can compute values dynamically instead of just reading or writing raw fields.
|
|
@@ -51,40 +88,221 @@
|
|
|
51
88
|
|
|
52
89
|
See the [README](./README.md#computed-expressions) for the full method reference and more examples.
|
|
53
90
|
|
|
91
|
+
## 2.0.1
|
|
92
|
+
|
|
54
93
|
### Patch Changes
|
|
55
94
|
|
|
56
|
-
- [#
|
|
95
|
+
- [#27](https://github.com/Semantu/linked/pull/27) [`d3c1e91`](https://github.com/Semantu/linked/commit/d3c1e918b2a63240ddbf3cb550ec43fa1e019c35) Thanks [@flyon](https://github.com/flyon)! - Add MINUS support on QueryBuilder with multiple call styles:
|
|
57
96
|
|
|
58
|
-
|
|
97
|
+
- `.minus(Shape)` — exclude by shape type
|
|
98
|
+
- `.minus(p => p.prop.equals(val))` — exclude by condition
|
|
99
|
+
- `.minus(p => p.prop)` — exclude by property existence
|
|
100
|
+
- `.minus(p => [p.prop1, p.nested.prop2])` — exclude by multi-property existence with nested path support
|
|
59
101
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
102
|
+
Add bulk delete operations:
|
|
103
|
+
|
|
104
|
+
- `Shape.deleteAll()` / `DeleteBuilder.from(Shape).all()` — delete all instances with schema-aware blank node cleanup
|
|
105
|
+
- `Shape.deleteWhere(fn)` / `DeleteBuilder.from(Shape).where(fn)` — conditional delete
|
|
106
|
+
|
|
107
|
+
Add conditional update operations:
|
|
108
|
+
|
|
109
|
+
- `.update(data).where(fn)` — update matching instances
|
|
110
|
+
- `.update(data).forAll()` — update all instances
|
|
111
|
+
|
|
112
|
+
API cleanup:
|
|
113
|
+
|
|
114
|
+
- Deprecate `sortBy()` in favor of `orderBy()`
|
|
115
|
+
- Remove `DeleteBuilder.for()` — use `DeleteBuilder.from(shape, ids)` instead
|
|
116
|
+
- Require `data` parameter in `Shape.update(data)`
|
|
117
|
+
|
|
118
|
+
## 2.0.0
|
|
119
|
+
|
|
120
|
+
### Major Changes
|
|
121
|
+
|
|
122
|
+
- [#23](https://github.com/Semantu/linked/pull/23) [`d2d1eca`](https://github.com/Semantu/linked/commit/d2d1eca3517af11f39348dc83ba5e60703ef86d2) Thanks [@flyon](https://github.com/flyon)! - ## Breaking Changes
|
|
123
|
+
|
|
124
|
+
### `Shape.select()` and `Shape.update()` no longer accept an ID as the first argument
|
|
125
|
+
|
|
126
|
+
Use `.for(id)` to target a specific entity instead.
|
|
127
|
+
|
|
128
|
+
**Select:**
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
// Before
|
|
132
|
+
const result = await Person.select({ id: "..." }, (p) => p.name);
|
|
133
|
+
|
|
134
|
+
// After
|
|
135
|
+
const result = await Person.select((p) => p.name).for({ id: "..." });
|
|
65
136
|
```
|
|
66
137
|
|
|
67
|
-
|
|
138
|
+
`.for(id)` unwraps the result type from array to single object, matching the old single-subject overload behavior.
|
|
68
139
|
|
|
69
|
-
|
|
70
|
-
- `parsePropertyPath(input): PathExpr` — parser for SPARQL property path strings
|
|
71
|
-
- `normalizePropertyPath(input): PathExpr` — normalizes any input form to canonical AST
|
|
72
|
-
- `pathExprToSparql(expr): string` — renders PathExpr to SPARQL syntax
|
|
73
|
-
- `serializePathToSHACL(expr): SHACLPathResult` — serializes to SHACL RDF triples
|
|
140
|
+
**Update:**
|
|
74
141
|
|
|
75
|
-
|
|
142
|
+
```typescript
|
|
143
|
+
// Before
|
|
144
|
+
const result = await Person.update({ id: "..." }, { name: "Alice" });
|
|
76
145
|
|
|
77
|
-
|
|
146
|
+
// After
|
|
147
|
+
const result = await Person.update({ name: "Alice" }).for({ id: "..." });
|
|
148
|
+
```
|
|
78
149
|
|
|
79
|
-
`
|
|
150
|
+
`Shape.selectAll(id)` also no longer accepts an id — use `Person.selectAll().for(id)`.
|
|
80
151
|
|
|
81
|
-
|
|
152
|
+
### `ShapeType` renamed to `ShapeConstructor`
|
|
82
153
|
|
|
83
|
-
|
|
154
|
+
The type alias for concrete Shape subclass constructors has been renamed. Update any imports or references:
|
|
84
155
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
156
|
+
```typescript
|
|
157
|
+
// Before
|
|
158
|
+
import type { ShapeType } from "@_linked/core/shapes/Shape";
|
|
159
|
+
|
|
160
|
+
// After
|
|
161
|
+
import type { ShapeConstructor } from "@_linked/core/shapes/Shape";
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### `QueryString`, `QueryNumber`, `QueryBoolean`, `QueryDate` classes removed
|
|
165
|
+
|
|
166
|
+
These have been consolidated into a single generic `QueryPrimitive<T>` class. If you were using `instanceof` checks against these classes, use `instanceof QueryPrimitive` instead and check the value's type.
|
|
167
|
+
|
|
168
|
+
### Internal IR types removed
|
|
169
|
+
|
|
170
|
+
The following types and functions have been removed from `SelectQuery`. These were internal pipeline types — if you were using them for custom store integrations, the replacement is `FieldSetEntry[]` (available from `FieldSet`):
|
|
171
|
+
|
|
172
|
+
- Types: `SelectPath`, `QueryPath`, `CustomQueryObject`, `SubQueryPaths`, `ComponentQueryPath`
|
|
173
|
+
- Functions: `fieldSetToSelectPath()`, `entryToQueryPath()`
|
|
174
|
+
- Methods: `QueryBuilder.getQueryPaths()`, `BoundComponent.getComponentQueryPaths()`
|
|
175
|
+
- `RawSelectInput.select` field renamed to `RawSelectInput.entries` (type changed from `SelectPath` to `FieldSetEntry[]`)
|
|
176
|
+
|
|
177
|
+
### `getPackageShape()` return type is now nullable
|
|
178
|
+
|
|
179
|
+
Returns `ShapeConstructor | undefined` instead of `typeof Shape`. Code that didn't null-check the return value will now get TypeScript errors.
|
|
180
|
+
|
|
181
|
+
## New Features
|
|
182
|
+
|
|
183
|
+
### `.for(id)` and `.forAll(ids)` chaining
|
|
184
|
+
|
|
185
|
+
Consistent API for targeting entities across select and update operations:
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
// Single entity (result is unwrapped, not an array)
|
|
189
|
+
await Person.select((p) => p.name).for({ id: "..." });
|
|
190
|
+
await Person.select((p) => p.name).for("https://...");
|
|
191
|
+
|
|
192
|
+
// Multiple specific entities
|
|
193
|
+
await QueryBuilder.from(Person)
|
|
194
|
+
.select((p) => p.name)
|
|
195
|
+
.forAll([{ id: "..." }, { id: "..." }]);
|
|
196
|
+
|
|
197
|
+
// All instances (default — no .for() needed)
|
|
198
|
+
await Person.select((p) => p.name);
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Dynamic Query Building with `QueryBuilder` and `FieldSet`
|
|
202
|
+
|
|
203
|
+
Build queries programmatically at runtime — for CMS dashboards, API endpoints, configurable reports. See the [Dynamic Query Building](./README.md#dynamic-query-building) section in the README for full documentation and examples.
|
|
204
|
+
|
|
205
|
+
Key capabilities:
|
|
206
|
+
|
|
207
|
+
- `QueryBuilder.from(Person)` or `QueryBuilder.from('https://schema.org/Person')` — fluent, chainable, immutable query construction
|
|
208
|
+
- `FieldSet.for(Person, ['name', 'knows'])` — composable field selections with `.add()`, `.remove()`, `.pick()`, `FieldSet.merge()`
|
|
209
|
+
- `FieldSet.all(Person, {depth: 2})` — select all decorated properties with optional depth
|
|
210
|
+
- JSON serialization: `query.toJSON()` / `QueryBuilder.fromJSON(json)` and `fieldSet.toJSON()` / `FieldSet.fromJSON(json)`
|
|
211
|
+
- All builders are `PromiseLike` — `await` them directly or call `.build()` to inspect the IR
|
|
212
|
+
|
|
213
|
+
### Mutation Builders
|
|
214
|
+
|
|
215
|
+
`CreateBuilder`, `UpdateBuilder`, and `DeleteBuilder` provide the programmatic equivalent of `Person.create()`, `Person.update()`, and `Person.delete()`, accepting Shape classes or shape IRI strings. See the [Mutation Builders](./README.md#mutation-builders) section in the README.
|
|
216
|
+
|
|
217
|
+
### `PropertyPath` exported
|
|
218
|
+
|
|
219
|
+
The `PropertyPath` value object is now a public export — a type-safe representation of a sequence of property traversals through a shape graph.
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
import { PropertyPath, walkPropertyPath } from "@_linked/core";
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### `ShapeConstructor<S>` type
|
|
226
|
+
|
|
227
|
+
New concrete constructor type for Shape subclasses. Eliminates ~30 `as any` casts across the codebase and provides better type safety at runtime boundaries (builder `.from()` methods, Shape static methods).
|
|
228
|
+
|
|
229
|
+
## 1.3.0
|
|
230
|
+
|
|
231
|
+
### Minor Changes
|
|
232
|
+
|
|
233
|
+
- [#20](https://github.com/Semantu/linked/pull/20) [`33e9fb0`](https://github.com/Semantu/linked/commit/33e9fb0205343eca8c84723cbabc3f3342e40be5) Thanks [@flyon](https://github.com/flyon)! - **Breaking:** `QueryParser` has been removed. If you imported `QueryParser` directly, replace with `getQueryDispatch()` from `@_linked/core/queries/queryDispatch`. The Shape DSL (`Shape.select()`, `.create()`, `.update()`, `.delete()`) and `SelectQuery.exec()` are unchanged.
|
|
234
|
+
|
|
235
|
+
**New:** `getQueryDispatch()` and `setQueryDispatch()` are now exported, allowing custom query dispatch implementations (e.g. for testing or alternative storage backends) without subclassing `LinkedStorage`.
|
|
236
|
+
|
|
237
|
+
## 1.2.1
|
|
238
|
+
|
|
239
|
+
### Patch Changes
|
|
240
|
+
|
|
241
|
+
- [#17](https://github.com/Semantu/linked/pull/17) [`0654780`](https://github.com/Semantu/linked/commit/06547807a7bae56e992eba73263f83e092b7788b) Thanks [@flyon](https://github.com/flyon)! - Preserve nested array sub-select branches in canonical IR so `build()` emits complete traversals, projection fields, and `resultMap` entries for nested selections.
|
|
242
|
+
|
|
243
|
+
This fixes cases where nested branches present in `toRawInput().select` were dropped during desugar/lowering (for example nested `friends.select([name, hobby])` branches under another sub-select).
|
|
244
|
+
|
|
245
|
+
Also adds regression coverage for desugar preservation, IR lowering completeness, and updated SPARQL golden output for nested query fixtures.
|
|
246
|
+
|
|
247
|
+
## 1.2.0
|
|
248
|
+
|
|
249
|
+
### Minor Changes
|
|
250
|
+
|
|
251
|
+
- [#9](https://github.com/Semantu/linked/pull/9) [`381067b`](https://github.com/Semantu/linked/commit/381067b0fbc25f4a0446c5f8cc0eec57ddded466) Thanks [@flyon](https://github.com/flyon)! - Replaced internal query representation with a canonical backend-agnostic IR AST. `SelectQuery`, `CreateQuery`, `UpdateQuery`, and `DeleteQuery` are now typed IR objects with `kind` discriminators, compact shape/property ID references, and expression trees — replacing the previous ad-hoc nested arrays. The public Shape DSL is unchanged; what changed is what `IQuadStore` implementations receive. Store result types (`ResultRow`, `SelectResult`, `CreateResult`, `UpdateResult`) are now exported. All factories expose `build()` as the primary method. See `documentation/intermediate-representation.md` for the full IR reference and migration guidance.
|
|
252
|
+
|
|
253
|
+
- [#14](https://github.com/Semantu/linked/pull/14) [`b65e156`](https://github.com/Semantu/linked/commit/b65e15688ac173478e58e1dbb9f26dbaf5fc5a37) Thanks [@flyon](https://github.com/flyon)! - Add SPARQL conversion layer — compiles Linked IR queries into executable SPARQL and maps results back to typed DSL objects.
|
|
254
|
+
|
|
255
|
+
**New exports from `@_linked/core/sparql`:**
|
|
256
|
+
|
|
257
|
+
- **`SparqlStore`** — abstract base class for SPARQL-backed stores. Extend it and implement two methods to connect any SPARQL 1.1 endpoint:
|
|
258
|
+
|
|
259
|
+
```ts
|
|
260
|
+
import { SparqlStore } from "@_linked/core/sparql";
|
|
261
|
+
|
|
262
|
+
class MyStore extends SparqlStore {
|
|
263
|
+
protected async executeSparqlSelect(
|
|
264
|
+
sparql: string
|
|
265
|
+
): Promise<SparqlJsonResults> {
|
|
266
|
+
/* ... */
|
|
267
|
+
}
|
|
268
|
+
protected async executeSparqlUpdate(sparql: string): Promise<void> {
|
|
269
|
+
/* ... */
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
- **IR → SPARQL string** convenience functions (full pipeline in one call):
|
|
275
|
+
|
|
276
|
+
- `selectToSparql(query, options?)` — SelectQuery → SPARQL string
|
|
277
|
+
- `createToSparql(query, options?)` — CreateQuery → SPARQL string
|
|
278
|
+
- `updateToSparql(query, options?)` — UpdateQuery → SPARQL string
|
|
279
|
+
- `deleteToSparql(query, options?)` — DeleteQuery → SPARQL string
|
|
280
|
+
|
|
281
|
+
- **IR → SPARQL algebra** (for stores that want to inspect/optimize the algebra before serialization):
|
|
282
|
+
|
|
283
|
+
- `selectToAlgebra(query, options?)` — returns `SparqlSelectPlan`
|
|
284
|
+
- `createToAlgebra(query, options?)` — returns `SparqlInsertDataPlan`
|
|
285
|
+
- `updateToAlgebra(query, options?)` — returns `SparqlDeleteInsertPlan`
|
|
286
|
+
- `deleteToAlgebra(query, options?)` — returns `SparqlDeleteInsertPlan`
|
|
287
|
+
|
|
288
|
+
- **Algebra → SPARQL string** serialization:
|
|
289
|
+
|
|
290
|
+
- `selectPlanToSparql(plan, options?)`, `insertDataPlanToSparql(plan, options?)`, `deleteInsertPlanToSparql(plan, options?)`, `deleteWherePlanToSparql(plan, options?)`
|
|
291
|
+
- `serializeAlgebraNode(node)`, `serializeExpression(expr)`, `serializeTerm(term)`
|
|
292
|
+
|
|
293
|
+
- **Result mapping** (SPARQL JSON results → typed DSL objects):
|
|
294
|
+
|
|
295
|
+
- `mapSparqlSelectResult(json, query)` — handles flat/nested/aggregated results with XSD type coercion
|
|
296
|
+
- `mapSparqlCreateResult(uri, query)` — echoes created fields with generated URI
|
|
297
|
+
- `mapSparqlUpdateResult(query)` — echoes updated fields
|
|
298
|
+
|
|
299
|
+
- **All algebra types** re-exported: `SparqlTerm`, `SparqlTriple`, `SparqlAlgebraNode`, `SparqlExpression`, `SparqlSelectPlan`, `SparqlInsertDataPlan`, `SparqlDeleteInsertPlan`, `SparqlDeleteWherePlan`, `SparqlPlan`, `SparqlOptions`, etc.
|
|
300
|
+
|
|
301
|
+
**Bug fixes included:**
|
|
302
|
+
|
|
303
|
+
- Fixed `isNodeReference()` in MutationQuery.ts — nested creates with predefined IDs (e.g., `{id: '...', name: 'Bestie'}`) now correctly insert entity data instead of only creating the link.
|
|
304
|
+
|
|
305
|
+
See [SPARQL Algebra Layer docs](./documentation/sparql-algebra.md) for the full type reference, conversion rules, and store implementation guide.
|
|
88
306
|
|
|
89
307
|
## 1.1.0
|
|
90
308
|
|