@_linked/core 1.0.0 → 1.2.0-next.20260302120536
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 +72 -0
- package/README.md +321 -43
- package/lib/cjs/index.js +4 -0
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/interfaces/IQuadStore.d.ts +19 -7
- package/lib/cjs/queries/CreateQuery.d.ts +7 -8
- package/lib/cjs/queries/CreateQuery.js +4 -4
- package/lib/cjs/queries/CreateQuery.js.map +1 -1
- package/lib/cjs/queries/DeleteQuery.d.ts +7 -8
- package/lib/cjs/queries/DeleteQuery.js +4 -4
- package/lib/cjs/queries/DeleteQuery.js.map +1 -1
- package/lib/cjs/queries/IRAliasScope.d.ts +20 -0
- package/lib/cjs/queries/IRAliasScope.js +52 -0
- package/lib/cjs/queries/IRAliasScope.js.map +1 -0
- package/lib/cjs/queries/IRCanonicalize.d.ts +36 -0
- package/lib/cjs/queries/IRCanonicalize.js +121 -0
- package/lib/cjs/queries/IRCanonicalize.js.map +1 -0
- package/lib/cjs/queries/IRDesugar.d.ts +98 -0
- package/lib/cjs/queries/IRDesugar.js +244 -0
- package/lib/cjs/queries/IRDesugar.js.map +1 -0
- package/lib/cjs/queries/IRLower.d.ts +8 -0
- package/lib/cjs/queries/IRLower.js +272 -0
- package/lib/cjs/queries/IRLower.js.map +1 -0
- package/lib/cjs/queries/IRMutation.d.ts +23 -0
- package/lib/cjs/queries/IRMutation.js +77 -0
- package/lib/cjs/queries/IRMutation.js.map +1 -0
- package/lib/cjs/queries/IRPipeline.d.ts +8 -0
- package/lib/cjs/queries/IRPipeline.js +25 -0
- package/lib/cjs/queries/IRPipeline.js.map +1 -0
- package/lib/cjs/queries/IRProjection.d.ts +38 -0
- package/lib/cjs/queries/IRProjection.js +98 -0
- package/lib/cjs/queries/IRProjection.js.map +1 -0
- package/lib/cjs/queries/IntermediateRepresentation.d.ts +210 -0
- package/lib/cjs/queries/IntermediateRepresentation.js +3 -0
- package/lib/cjs/queries/IntermediateRepresentation.js.map +1 -0
- package/lib/cjs/queries/MutationQuery.js +9 -23
- package/lib/cjs/queries/MutationQuery.js.map +1 -1
- package/lib/cjs/queries/QueryFactory.d.ts +0 -2
- package/lib/cjs/queries/QueryFactory.js +0 -3
- package/lib/cjs/queries/QueryFactory.js.map +1 -1
- package/lib/cjs/queries/QueryParser.d.ts +6 -1
- package/lib/cjs/queries/QueryParser.js +14 -22
- package/lib/cjs/queries/QueryParser.js.map +1 -1
- package/lib/cjs/queries/SelectQuery.d.ts +18 -27
- package/lib/cjs/queries/SelectQuery.js +54 -45
- package/lib/cjs/queries/SelectQuery.js.map +1 -1
- package/lib/cjs/queries/UpdateQuery.d.ts +8 -9
- package/lib/cjs/queries/UpdateQuery.js +4 -4
- package/lib/cjs/queries/UpdateQuery.js.map +1 -1
- package/lib/cjs/shapes/SHACL.d.ts +1 -0
- package/lib/cjs/shapes/SHACL.js +82 -2
- package/lib/cjs/shapes/SHACL.js.map +1 -1
- package/lib/cjs/shapes/Shape.d.ts +11 -10
- package/lib/cjs/shapes/Shape.js +11 -5
- package/lib/cjs/shapes/Shape.js.map +1 -1
- package/lib/cjs/sparql/SparqlAlgebra.d.ts +158 -0
- package/lib/cjs/sparql/SparqlAlgebra.js +4 -0
- package/lib/cjs/sparql/SparqlAlgebra.js.map +1 -0
- package/lib/cjs/sparql/SparqlStore.d.ts +52 -0
- package/lib/cjs/sparql/SparqlStore.js +81 -0
- package/lib/cjs/sparql/SparqlStore.js.map +1 -0
- package/lib/cjs/sparql/algebraToString.d.ts +13 -0
- package/lib/cjs/sparql/algebraToString.js +298 -0
- package/lib/cjs/sparql/algebraToString.js.map +1 -0
- package/lib/cjs/sparql/index.d.ts +9 -0
- package/lib/cjs/sparql/index.js +40 -0
- package/lib/cjs/sparql/index.js.map +1 -0
- package/lib/cjs/sparql/irToAlgebra.d.ts +39 -0
- package/lib/cjs/sparql/irToAlgebra.js +927 -0
- package/lib/cjs/sparql/irToAlgebra.js.map +1 -0
- package/lib/cjs/sparql/resultMapping.d.ts +36 -0
- package/lib/cjs/sparql/resultMapping.js +501 -0
- package/lib/cjs/sparql/resultMapping.js.map +1 -0
- package/lib/cjs/sparql/sparqlUtils.d.ts +32 -0
- package/lib/cjs/sparql/sparqlUtils.js +89 -0
- package/lib/cjs/sparql/sparqlUtils.js.map +1 -0
- package/lib/cjs/test-helpers/FusekiStore.d.ts +29 -0
- package/lib/cjs/test-helpers/FusekiStore.js +82 -0
- package/lib/cjs/test-helpers/FusekiStore.js.map +1 -0
- package/lib/cjs/test-helpers/fuseki-test-store.d.ts +43 -0
- package/lib/cjs/test-helpers/fuseki-test-store.js +144 -0
- package/lib/cjs/test-helpers/fuseki-test-store.js.map +1 -0
- package/lib/cjs/test-helpers/query-capture-store.d.ts +5 -0
- package/lib/cjs/test-helpers/query-capture-store.js +59 -0
- package/lib/cjs/test-helpers/query-capture-store.js.map +1 -0
- package/lib/cjs/test-helpers/query-fixtures.d.ts +700 -117
- package/lib/cjs/test-helpers/query-fixtures.js +39 -1
- package/lib/cjs/test-helpers/query-fixtures.js.map +1 -1
- package/lib/cjs/utils/LinkedStorage.d.ts +7 -7
- package/lib/cjs/utils/LinkedStorage.js +4 -3
- package/lib/cjs/utils/LinkedStorage.js.map +1 -1
- package/lib/esm/index.js +4 -0
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/interfaces/IQuadStore.d.ts +19 -7
- package/lib/esm/queries/CreateQuery.d.ts +7 -8
- package/lib/esm/queries/CreateQuery.js +4 -4
- package/lib/esm/queries/CreateQuery.js.map +1 -1
- package/lib/esm/queries/DeleteQuery.d.ts +7 -8
- package/lib/esm/queries/DeleteQuery.js +4 -4
- package/lib/esm/queries/DeleteQuery.js.map +1 -1
- package/lib/esm/queries/IRAliasScope.d.ts +20 -0
- package/lib/esm/queries/IRAliasScope.js +47 -0
- package/lib/esm/queries/IRAliasScope.js.map +1 -0
- package/lib/esm/queries/IRCanonicalize.d.ts +36 -0
- package/lib/esm/queries/IRCanonicalize.js +116 -0
- package/lib/esm/queries/IRCanonicalize.js.map +1 -0
- package/lib/esm/queries/IRDesugar.d.ts +98 -0
- package/lib/esm/queries/IRDesugar.js +240 -0
- package/lib/esm/queries/IRDesugar.js.map +1 -0
- package/lib/esm/queries/IRLower.d.ts +8 -0
- package/lib/esm/queries/IRLower.js +268 -0
- package/lib/esm/queries/IRLower.js.map +1 -0
- package/lib/esm/queries/IRMutation.d.ts +23 -0
- package/lib/esm/queries/IRMutation.js +71 -0
- package/lib/esm/queries/IRMutation.js.map +1 -0
- package/lib/esm/queries/IRPipeline.d.ts +8 -0
- package/lib/esm/queries/IRPipeline.js +21 -0
- package/lib/esm/queries/IRPipeline.js.map +1 -0
- package/lib/esm/queries/IRProjection.d.ts +38 -0
- package/lib/esm/queries/IRProjection.js +92 -0
- package/lib/esm/queries/IRProjection.js.map +1 -0
- package/lib/esm/queries/IntermediateRepresentation.d.ts +210 -0
- package/lib/esm/queries/IntermediateRepresentation.js +2 -0
- package/lib/esm/queries/IntermediateRepresentation.js.map +1 -0
- package/lib/esm/queries/MutationQuery.js +9 -23
- package/lib/esm/queries/MutationQuery.js.map +1 -1
- package/lib/esm/queries/QueryFactory.d.ts +0 -2
- package/lib/esm/queries/QueryFactory.js +0 -3
- package/lib/esm/queries/QueryFactory.js.map +1 -1
- package/lib/esm/queries/QueryParser.d.ts +6 -1
- package/lib/esm/queries/QueryParser.js +14 -23
- package/lib/esm/queries/QueryParser.js.map +1 -1
- package/lib/esm/queries/SelectQuery.d.ts +18 -27
- package/lib/esm/queries/SelectQuery.js +54 -45
- package/lib/esm/queries/SelectQuery.js.map +1 -1
- package/lib/esm/queries/UpdateQuery.d.ts +8 -9
- package/lib/esm/queries/UpdateQuery.js +4 -4
- package/lib/esm/queries/UpdateQuery.js.map +1 -1
- package/lib/esm/shapes/SHACL.d.ts +1 -0
- package/lib/esm/shapes/SHACL.js +82 -2
- package/lib/esm/shapes/SHACL.js.map +1 -1
- package/lib/esm/shapes/Shape.d.ts +11 -10
- package/lib/esm/shapes/Shape.js +11 -5
- package/lib/esm/shapes/Shape.js.map +1 -1
- package/lib/esm/sparql/SparqlAlgebra.d.ts +158 -0
- package/lib/esm/sparql/SparqlAlgebra.js +3 -0
- package/lib/esm/sparql/SparqlAlgebra.js.map +1 -0
- package/lib/esm/sparql/SparqlStore.d.ts +52 -0
- package/lib/esm/sparql/SparqlStore.js +77 -0
- package/lib/esm/sparql/SparqlStore.js.map +1 -0
- package/lib/esm/sparql/algebraToString.d.ts +13 -0
- package/lib/esm/sparql/algebraToString.js +289 -0
- package/lib/esm/sparql/algebraToString.js.map +1 -0
- package/lib/esm/sparql/index.d.ts +9 -0
- package/lib/esm/sparql/index.js +13 -0
- package/lib/esm/sparql/index.js.map +1 -0
- package/lib/esm/sparql/irToAlgebra.d.ts +39 -0
- package/lib/esm/sparql/irToAlgebra.js +917 -0
- package/lib/esm/sparql/irToAlgebra.js.map +1 -0
- package/lib/esm/sparql/resultMapping.d.ts +36 -0
- package/lib/esm/sparql/resultMapping.js +496 -0
- package/lib/esm/sparql/resultMapping.js.map +1 -0
- package/lib/esm/sparql/sparqlUtils.d.ts +32 -0
- package/lib/esm/sparql/sparqlUtils.js +82 -0
- package/lib/esm/sparql/sparqlUtils.js.map +1 -0
- package/lib/esm/test-helpers/FusekiStore.d.ts +29 -0
- package/lib/esm/test-helpers/FusekiStore.js +78 -0
- package/lib/esm/test-helpers/FusekiStore.js.map +1 -0
- package/lib/esm/test-helpers/fuseki-test-store.d.ts +43 -0
- package/lib/esm/test-helpers/fuseki-test-store.js +135 -0
- package/lib/esm/test-helpers/fuseki-test-store.js.map +1 -0
- package/lib/esm/test-helpers/query-capture-store.d.ts +5 -0
- package/lib/esm/test-helpers/query-capture-store.js +55 -0
- package/lib/esm/test-helpers/query-capture-store.js.map +1 -0
- package/lib/esm/test-helpers/query-fixtures.d.ts +700 -117
- package/lib/esm/test-helpers/query-fixtures.js +38 -0
- package/lib/esm/test-helpers/query-fixtures.js.map +1 -1
- package/lib/esm/utils/LinkedStorage.d.ts +7 -7
- package/lib/esm/utils/LinkedStorage.js +4 -3
- package/lib/esm/utils/LinkedStorage.js.map +1 -1
- package/package.json +7 -3
- package/lib/cjs/interfaces/IQueryParser.d.ts +0 -13
- package/lib/cjs/interfaces/IQueryParser.js +0 -10
- package/lib/cjs/interfaces/IQueryParser.js.map +0 -1
- package/lib/esm/interfaces/IQueryParser.d.ts +0 -13
- package/lib/esm/interfaces/IQueryParser.js +0 -7
- package/lib/esm/interfaces/IQueryParser.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,8 +1,80 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#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.
|
|
8
|
+
|
|
9
|
+
- [#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.
|
|
10
|
+
|
|
11
|
+
**New exports from `@_linked/core/sparql`:**
|
|
12
|
+
|
|
13
|
+
- **`SparqlStore`** — abstract base class for SPARQL-backed stores. Extend it and implement two methods to connect any SPARQL 1.1 endpoint:
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { SparqlStore } from "@_linked/core/sparql";
|
|
17
|
+
|
|
18
|
+
class MyStore extends SparqlStore {
|
|
19
|
+
protected async executeSparqlSelect(
|
|
20
|
+
sparql: string
|
|
21
|
+
): Promise<SparqlJsonResults> {
|
|
22
|
+
/* ... */
|
|
23
|
+
}
|
|
24
|
+
protected async executeSparqlUpdate(sparql: string): Promise<void> {
|
|
25
|
+
/* ... */
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
- **IR → SPARQL string** convenience functions (full pipeline in one call):
|
|
31
|
+
|
|
32
|
+
- `selectToSparql(query, options?)` — SelectQuery → SPARQL string
|
|
33
|
+
- `createToSparql(query, options?)` — CreateQuery → SPARQL string
|
|
34
|
+
- `updateToSparql(query, options?)` — UpdateQuery → SPARQL string
|
|
35
|
+
- `deleteToSparql(query, options?)` — DeleteQuery → SPARQL string
|
|
36
|
+
|
|
37
|
+
- **IR → SPARQL algebra** (for stores that want to inspect/optimize the algebra before serialization):
|
|
38
|
+
|
|
39
|
+
- `selectToAlgebra(query, options?)` — returns `SparqlSelectPlan`
|
|
40
|
+
- `createToAlgebra(query, options?)` — returns `SparqlInsertDataPlan`
|
|
41
|
+
- `updateToAlgebra(query, options?)` — returns `SparqlDeleteInsertPlan`
|
|
42
|
+
- `deleteToAlgebra(query, options?)` — returns `SparqlDeleteInsertPlan`
|
|
43
|
+
|
|
44
|
+
- **Algebra → SPARQL string** serialization:
|
|
45
|
+
|
|
46
|
+
- `selectPlanToSparql(plan, options?)`, `insertDataPlanToSparql(plan, options?)`, `deleteInsertPlanToSparql(plan, options?)`, `deleteWherePlanToSparql(plan, options?)`
|
|
47
|
+
- `serializeAlgebraNode(node)`, `serializeExpression(expr)`, `serializeTerm(term)`
|
|
48
|
+
|
|
49
|
+
- **Result mapping** (SPARQL JSON results → typed DSL objects):
|
|
50
|
+
|
|
51
|
+
- `mapSparqlSelectResult(json, query)` — handles flat/nested/aggregated results with XSD type coercion
|
|
52
|
+
- `mapSparqlCreateResult(uri, query)` — echoes created fields with generated URI
|
|
53
|
+
- `mapSparqlUpdateResult(query)` — echoes updated fields
|
|
54
|
+
|
|
55
|
+
- **All algebra types** re-exported: `SparqlTerm`, `SparqlTriple`, `SparqlAlgebraNode`, `SparqlExpression`, `SparqlSelectPlan`, `SparqlInsertDataPlan`, `SparqlDeleteInsertPlan`, `SparqlDeleteWherePlan`, `SparqlPlan`, `SparqlOptions`, etc.
|
|
56
|
+
|
|
57
|
+
**Bug fixes included:**
|
|
58
|
+
|
|
59
|
+
- 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.
|
|
60
|
+
|
|
61
|
+
See [SPARQL Algebra Layer docs](./documentation/sparql-algebra.md) for the full type reference, conversion rules, and store implementation guide.
|
|
62
|
+
|
|
63
|
+
## 1.1.0
|
|
64
|
+
|
|
65
|
+
### Minor Changes
|
|
66
|
+
|
|
67
|
+
- [#4](https://github.com/Semantu/linked/pull/4) [`c35e686`](https://github.com/Semantu/linked/commit/c35e6861600d7aa8683b4b288fc4d1dc74c4aff2) Thanks [@flyon](https://github.com/flyon)! - - Added `Shape.selectAll()` plus nested `selectAll()` support on sub-queries.
|
|
68
|
+
- Added inherited property deduplication via `NodeShape.getUniquePropertyShapes()` so subclass overrides win by label and are selected once.
|
|
69
|
+
- Improved `selectAll()` type inference (including nested queries) and excluded base `Shape` keys from inferred results.
|
|
70
|
+
- Added registration-time override guards: `minCount` cannot be lowered, `maxCount` cannot be increased, and `nodeKind` cannot be widened.
|
|
71
|
+
- Fixed `createPropertyShape` to preserve explicit `minCount: 0` / `maxCount: 0`.
|
|
72
|
+
- Expanded tests and README documentation for `selectAll`, CRUD return types, and multi-value update semantics.
|
|
73
|
+
|
|
3
74
|
## 1.0.0
|
|
4
75
|
|
|
5
76
|
### Major Changes
|
|
77
|
+
|
|
6
78
|
This is a rebranding + extraction release. It moves the core query/shape system into `@_linked/core` and removes RDF models and React-specific code.
|
|
7
79
|
|
|
8
80
|
Key changes:
|
package/README.md
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
# @_linked/core
|
|
2
2
|
Core Linked package for the query DSL, SHACL shape decorators/metadata, and package registration.
|
|
3
3
|
|
|
4
|
-
Linked core gives you a type-safe, schema-parameterized query language and SHACL-driven Shape classes for linked data. It compiles queries into a
|
|
4
|
+
Linked core gives you a type-safe, schema-parameterized query language and SHACL-driven Shape classes for linked data. It compiles queries into a normalized [Intermediate Representation (IR)](./documentation/intermediate-representation.md) that can be executed by any store.
|
|
5
5
|
|
|
6
6
|
## Linked core offers
|
|
7
7
|
|
|
8
8
|
- **Schema-Parameterized Query DSL**: TypeScript-embedded queries driven by your Shape definitions.
|
|
9
|
+
- **Fully Inferred Result Types**: The TypeScript return type of every query is automatically inferred from the selected paths — no manual type annotations needed. Select `p.name` and get `{id: string; name: string}[]`. Select `p.friends.name` and get nested result types. This works for all operations: select, create, update, and delete.
|
|
9
10
|
- **Shape Classes (SHACL)**: TypeScript classes that generate SHACL shape metadata.
|
|
10
11
|
- **Object-Oriented Data Operations**: Query, create, update, and delete data using the same Shape-based API.
|
|
11
12
|
- **Storage Routing**: `LinkedStorage` routes query objects to your configured store(s) that implement `IQuadStore`.
|
|
@@ -17,16 +18,151 @@ Linked core gives you a type-safe, schema-parameterized query language and SHACL
|
|
|
17
18
|
npm install @_linked/core
|
|
18
19
|
```
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
## Repository setup (contributors)
|
|
22
|
+
|
|
23
|
+
After cloning this repository, run:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install
|
|
27
|
+
npm run setup
|
|
23
28
|
```
|
|
24
29
|
|
|
30
|
+
`npm run setup` syncs `docs/agents` into local folders for agent tooling:
|
|
31
|
+
|
|
32
|
+
- `.claude/agents`
|
|
33
|
+
- `.agents/agents`
|
|
34
|
+
|
|
25
35
|
## Related packages
|
|
26
36
|
|
|
27
37
|
- `@_linked/rdf-mem-store`: in-memory RDF store that implements `IQuadStore`.
|
|
28
38
|
- `@_linked/react`: React bindings for Linked queries and shapes.
|
|
29
39
|
|
|
40
|
+
## Documentation
|
|
41
|
+
|
|
42
|
+
- [Intermediate Representation (IR)](./documentation/intermediate-representation.md)
|
|
43
|
+
- [SPARQL Algebra Layer](./documentation/sparql-algebra.md)
|
|
44
|
+
|
|
45
|
+
## How Linked works — from shapes to query results
|
|
46
|
+
|
|
47
|
+
Linked turns TypeScript classes into a type-safe query pipeline. Here is the full flow, traced through a single example:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
Shape class → DSL query → IR (AST) → Target query language → Execute → Map results
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### 1. SHACL shapes from TypeScript classes
|
|
54
|
+
|
|
55
|
+
Shape classes use decorators to generate SHACL metadata. These shapes define the data model, drive the DSL's type safety, and can be synced to a store for runtime data validation.
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
@linkedShape
|
|
59
|
+
export class Person extends Shape {
|
|
60
|
+
static targetClass = schema('Person');
|
|
61
|
+
|
|
62
|
+
@literalProperty({path: schema('name'), maxCount: 1})
|
|
63
|
+
get name(): string { return ''; }
|
|
64
|
+
|
|
65
|
+
@objectProperty({path: schema('knows'), shape: Person})
|
|
66
|
+
get friends(): ShapeSet<Person> { return null; }
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### 2. Type-safe query DSL with inferred result types
|
|
71
|
+
|
|
72
|
+
The DSL uses these shape classes to provide compile-time checked queries. You cannot write a query that references a property not defined on the shape. The result type is **fully inferred** from the selected paths — no manual type annotations needed:
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
// TypeScript infers: Promise<{id: string; name: string}[]>
|
|
76
|
+
const result = await Person.select(p => p.name);
|
|
77
|
+
|
|
78
|
+
// TypeScript infers: Promise<{id: string; friends: {id: string; name: string}[]}[]>
|
|
79
|
+
const nested = await Person.select(p => p.friends.name);
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### 3. SHACL-based Intermediate Representation (IR)
|
|
83
|
+
|
|
84
|
+
The DSL compiles to a backend-agnostic AST — the [Intermediate Representation](./documentation/intermediate-representation.md). This is the contract between the DSL and any store implementation.
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
{
|
|
88
|
+
"kind": "select",
|
|
89
|
+
"root": { "kind": "shape_scan", "shape": ".../Person", "alias": "a0" },
|
|
90
|
+
"projection": [
|
|
91
|
+
{ "alias": "a1", "expression": { "kind": "property_expr", "sourceAlias": "a0", "property": ".../name" } }
|
|
92
|
+
],
|
|
93
|
+
"resultMap": [{ "key": ".../name", "alias": "a1" }]
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
The IR uses full SHACL-derived URIs for shapes and properties. Any store that implements `IQuadStore` receives these IR objects and translates them into its native query language.
|
|
98
|
+
|
|
99
|
+
### 4. IR → SPARQL Algebra
|
|
100
|
+
|
|
101
|
+
For SPARQL-backed stores, the IR is converted into a formal [SPARQL algebra](./documentation/sparql-algebra.md) — a tree of typed nodes aligned with the SPARQL 1.1 specification.
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
SparqlSelectPlan {
|
|
105
|
+
projection: [?a0, ?a0_name]
|
|
106
|
+
algebra: LeftJoin(
|
|
107
|
+
BGP(?a0 rdf:type <Person>),
|
|
108
|
+
BGP(?a0 <name> ?a0_name) ← wrapped in OPTIONAL
|
|
109
|
+
)
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Properties are wrapped in `LeftJoin` (OPTIONAL) so missing values don't eliminate result rows.
|
|
114
|
+
|
|
115
|
+
### 5. SPARQL Algebra → SPARQL string
|
|
116
|
+
|
|
117
|
+
The algebra is a plain data structure — stores can inspect or optimize it before serialization (e.g., rewriting patterns, adding graph clauses, or pruning redundant joins).
|
|
118
|
+
|
|
119
|
+
The algebra tree is then serialized into a SPARQL query string with automatic PREFIX generation:
|
|
120
|
+
|
|
121
|
+
```sparql
|
|
122
|
+
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
|
|
123
|
+
SELECT DISTINCT ?a0 ?a0_name
|
|
124
|
+
WHERE {
|
|
125
|
+
?a0 rdf:type <.../Person> .
|
|
126
|
+
OPTIONAL {
|
|
127
|
+
?a0 <.../name> ?a0_name .
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### 6. Execute and map results
|
|
133
|
+
|
|
134
|
+
The SPARQL endpoint returns JSON results, which are mapped back into typed result objects:
|
|
135
|
+
|
|
136
|
+
```
|
|
137
|
+
Endpoint returns: Mapped to:
|
|
138
|
+
┌──────────┬──────────┐ ┌──────────────────────────────┐
|
|
139
|
+
│ a0 │ a0_name │ │ { id: ".../p1", name: "Semmy" } │
|
|
140
|
+
│ .../p1 │ "Semmy" │ → │ { id: ".../p2", name: "Moa" } │
|
|
141
|
+
│ .../p2 │ "Moa" │ │ ... │
|
|
142
|
+
└──────────┴──────────┘ └──────────────────────────────┘
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Values are automatically coerced: `xsd:boolean` → `boolean`, `xsd:integer` → `number`, `xsd:dateTime` → `Date`. Nested traversals are grouped and deduplicated into nested result objects.
|
|
146
|
+
|
|
147
|
+
### The SparqlStore base class
|
|
148
|
+
|
|
149
|
+
`SparqlStore` handles this entire pipeline. Concrete stores only implement the transport:
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
import { SparqlStore } from '@_linked/core/sparql';
|
|
153
|
+
|
|
154
|
+
class MyStore extends SparqlStore {
|
|
155
|
+
protected async executeSparqlSelect(sparql: string) {
|
|
156
|
+
// Send SPARQL to your endpoint, return JSON results
|
|
157
|
+
}
|
|
158
|
+
protected async executeSparqlUpdate(sparql: string) {
|
|
159
|
+
// Send SPARQL UPDATE to your endpoint
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
See the [SPARQL Algebra Layer docs](./documentation/sparql-algebra.md) for the full type reference, conversion algorithm, and store implementation guide.
|
|
165
|
+
|
|
30
166
|
## Linked Package Setup
|
|
31
167
|
|
|
32
168
|
Linked packages expose shapes, utilities, and ontologies through a small `package.ts` file. This makes module exports discoverable across Linked modules and enables linked decorators.
|
|
@@ -85,41 +221,35 @@ export class Person extends Shape {
|
|
|
85
221
|
## Queries: Create, Select, Update, Delete
|
|
86
222
|
|
|
87
223
|
Queries are expressed with the same Shape classes and compile to a query object that a store executes.
|
|
224
|
+
Use this section as a quick start. Detailed query variations are documented in `Query examples` below.
|
|
225
|
+
|
|
226
|
+
A few quick examples:
|
|
88
227
|
|
|
228
|
+
**1) Select one field for all matching nodes**
|
|
89
229
|
```typescript
|
|
90
|
-
/* Result: Array<{id: string; name: string}> */
|
|
91
230
|
const names = await Person.select((p) => p.name);
|
|
231
|
+
/* names: {id: string; name: string}[] */
|
|
232
|
+
```
|
|
92
233
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
234
|
+
**2) Select all decorated fields of nested related nodes**
|
|
235
|
+
```typescript
|
|
236
|
+
const allFriends = await Person.select((p) => p.knows.selectAll());
|
|
237
|
+
/* allFriends: {
|
|
238
|
+
id?: string;
|
|
239
|
+
knows: {
|
|
240
|
+
id?: string;
|
|
241
|
+
...all decorated Person fields...
|
|
242
|
+
}[]
|
|
243
|
+
}[] */
|
|
244
|
+
```
|
|
103
245
|
|
|
246
|
+
**3) Apply a simple mutation**
|
|
247
|
+
```typescript
|
|
248
|
+
const myNode = {id: 'https://my.app/node1'};
|
|
104
249
|
const updated = await Person.update(myNode, {
|
|
105
250
|
name: 'Alicia',
|
|
106
251
|
});
|
|
107
|
-
|
|
108
|
-
// Overwrite a multi-value property
|
|
109
|
-
const overwriteFriends = await Person.update(myNode, {
|
|
110
|
-
knows: [{id: 'https://my.app/node2'}],
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
// Add/remove items in a multi-value property
|
|
114
|
-
const addRemoveFriends = await Person.update(myNode, {
|
|
115
|
-
knows: {
|
|
116
|
-
add: [{id: 'https://my.app/node3'}],
|
|
117
|
-
remove: [{id: 'https://my.app/node2'}],
|
|
118
|
-
},
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
/* Result: {deleted: Array<{id: string}>, count: number} */
|
|
122
|
-
await Person.delete(myNode);
|
|
252
|
+
/* updated: {id: string} & UpdatePartial<Person> */
|
|
123
253
|
```
|
|
124
254
|
|
|
125
255
|
## Storage configuration
|
|
@@ -172,10 +302,13 @@ Result types are inferred from your Shape definitions and the selected paths. Ex
|
|
|
172
302
|
|
|
173
303
|
#### Basic selection
|
|
174
304
|
```typescript
|
|
175
|
-
/*
|
|
305
|
+
/* names: {id: string; name: string}[] */
|
|
176
306
|
const names = await Person.select((p) => p.name);
|
|
177
307
|
|
|
178
|
-
/*
|
|
308
|
+
/* friends: {
|
|
309
|
+
id: string;
|
|
310
|
+
knows: { id: string }[]
|
|
311
|
+
}[] */
|
|
179
312
|
const friends = await Person.select((p) => p.knows);
|
|
180
313
|
|
|
181
314
|
const dates = await Person.select((p) => [p.birthDate, p.name]);
|
|
@@ -202,6 +335,12 @@ const deep = await Person.select((p) => p.knows.bestFriend.name);
|
|
|
202
335
|
const detailed = await Person.select((p) =>
|
|
203
336
|
p.knows.select((f) => f.name),
|
|
204
337
|
);
|
|
338
|
+
|
|
339
|
+
const allPeople = await Person.selectAll();
|
|
340
|
+
|
|
341
|
+
const detailedAll = await Person.select((p) =>
|
|
342
|
+
p.knows.selectAll(),
|
|
343
|
+
);
|
|
205
344
|
```
|
|
206
345
|
|
|
207
346
|
#### Where + equals
|
|
@@ -261,7 +400,9 @@ const custom = await Person.select((p) => ({
|
|
|
261
400
|
}));
|
|
262
401
|
```
|
|
263
402
|
|
|
264
|
-
#### Query As (type casting)
|
|
403
|
+
#### Query As (type casting to a sub shape)
|
|
404
|
+
If person.pets returns an array of Pets. And Dog extends Pet.
|
|
405
|
+
And you want to select properties of those pets that are dogs:
|
|
265
406
|
```typescript
|
|
266
407
|
const guards = await Person.select((p) => p.pets.as(Dog).guardDogLevel);
|
|
267
408
|
```
|
|
@@ -293,34 +434,171 @@ const preloaded = await Person.select((p) => [
|
|
|
293
434
|
]);
|
|
294
435
|
```
|
|
295
436
|
|
|
296
|
-
#### Create
|
|
437
|
+
#### Create
|
|
438
|
+
|
|
297
439
|
```typescript
|
|
298
440
|
/* Result: {id: string} & UpdatePartial<Person> */
|
|
299
441
|
const created = await Person.create({name: 'Alice'});
|
|
442
|
+
```
|
|
443
|
+
Where UpdatePartial<Shape> reflects the created properties.
|
|
444
|
+
|
|
445
|
+
#### Update
|
|
300
446
|
|
|
447
|
+
Update will patch any property that you send as payload and leave the rest untouched.
|
|
448
|
+
```typescript
|
|
449
|
+
/* Result: {id: string} & UpdatePartial<Person> */
|
|
301
450
|
const updated = await Person.update({id: 'https://my.app/node1'}, {name: 'Alicia'});
|
|
451
|
+
```
|
|
452
|
+
Returns:
|
|
453
|
+
```json
|
|
454
|
+
{
|
|
455
|
+
id:"https://my.app/node1",
|
|
456
|
+
name:"Alicia"
|
|
457
|
+
}
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
**Updating multi-value properties**
|
|
461
|
+
When updating a property that holds multiple values (one that returns an array in the results), you can either overwrite all the values with a new explicit array of values, or delete from/add to the current values.
|
|
302
462
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
463
|
+
To overwrite all values:
|
|
464
|
+
```typescript
|
|
465
|
+
// Overwrite the full set of "knows" values.
|
|
466
|
+
const overwriteFriends = await Person.update({id: 'https://my.app/person1'}, {
|
|
467
|
+
knows: [{id: 'https://my.app/person2'}],
|
|
306
468
|
});
|
|
469
|
+
```
|
|
470
|
+
The result will contain an object with `updatedTo`, to indicate that previous values were overwritten to this new set of values:
|
|
471
|
+
```json
|
|
472
|
+
{
|
|
473
|
+
id: "https://my.app/person1",
|
|
474
|
+
knows: {
|
|
475
|
+
updatedTo: [{id:"https://my.app/person2"}],
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
```
|
|
307
479
|
|
|
308
|
-
|
|
309
|
-
|
|
480
|
+
To make incremental changes to the current set of values you can provide an object with `add` and/or `remove` keys:
|
|
481
|
+
```typescript
|
|
482
|
+
// Add one value and remove one value without replacing the whole set.
|
|
483
|
+
const addRemoveFriends = await Person.update({id: 'https://my.app/person1'}, {
|
|
310
484
|
knows: {
|
|
311
|
-
add: [{id: 'https://my.app/
|
|
312
|
-
remove: [{id: 'https://my.app/
|
|
485
|
+
add: [{id: 'https://my.app/person2'}],
|
|
486
|
+
remove: [{id: 'https://my.app/person3'}],
|
|
313
487
|
},
|
|
314
488
|
});
|
|
489
|
+
```
|
|
490
|
+
This returns an object with the added and removed items
|
|
491
|
+
```json
|
|
492
|
+
{
|
|
493
|
+
id: "https://my.app/person1",
|
|
494
|
+
knows: {
|
|
495
|
+
added?: [{id:"https://my.app/person2"},
|
|
496
|
+
removed?: [{id:"https://my.app/person3"}],
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
```
|
|
500
|
+
|
|
315
501
|
|
|
316
|
-
|
|
502
|
+
#### Delete
|
|
503
|
+
To delete a node entirely:
|
|
504
|
+
|
|
505
|
+
```typescript
|
|
506
|
+
/* Result: {deleted: Array<{id: string}>, count: number} */
|
|
507
|
+
const deleted = await Person.delete({id: 'https://my.app/node1'});
|
|
508
|
+
```
|
|
509
|
+
Returns
|
|
510
|
+
```json
|
|
511
|
+
{
|
|
512
|
+
deleted:[
|
|
513
|
+
{id:"https://my.app/node1"}
|
|
514
|
+
],
|
|
515
|
+
count:1
|
|
516
|
+
}
|
|
317
517
|
```
|
|
318
518
|
|
|
519
|
+
To delete multiple nodes pass an array:
|
|
520
|
+
|
|
521
|
+
```typescript
|
|
522
|
+
/* Result: {deleted: Array<{id: string}>, count: number} */
|
|
523
|
+
const deleted = await Person.delete([{id: 'https://my.app/node1'},{id: 'https://my.app/node2'}]);
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
## Extending shapes
|
|
528
|
+
|
|
529
|
+
Shape classes can extend other shape classes. Subclasses inherit property shapes from their superclasses and may override them.
|
|
530
|
+
This example assumes `Person` from the `Shapes` section above.
|
|
531
|
+
|
|
532
|
+
```typescript
|
|
533
|
+
import {literalProperty} from '@_linked/core/shapes/SHACL';
|
|
534
|
+
import {createNameSpace} from '@_linked/core/utils/NameSpace';
|
|
535
|
+
import {linkedShape} from './package';
|
|
536
|
+
|
|
537
|
+
const schema = createNameSpace('https://schema.org/');
|
|
538
|
+
const EmployeeClass = schema('Employee');
|
|
539
|
+
const name = schema('name');
|
|
540
|
+
const employeeId = schema('employeeId');
|
|
541
|
+
|
|
542
|
+
@linkedShape
|
|
543
|
+
export class Employee extends Person {
|
|
544
|
+
static targetClass = EmployeeClass;
|
|
545
|
+
|
|
546
|
+
// Override inherited "name" with stricter constraints (still maxCount: 1)
|
|
547
|
+
@literalProperty({path: name, required: true, minLength: 2, maxCount: 1})
|
|
548
|
+
declare name: string;
|
|
549
|
+
|
|
550
|
+
@literalProperty({path: employeeId, required: true, maxCount: 1})
|
|
551
|
+
declare employeeId: string;
|
|
552
|
+
}
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
Override behavior:
|
|
556
|
+
|
|
557
|
+
- `NodeShape.getUniquePropertyShapes()` returns one property shape per label, with subclass overrides taking precedence.
|
|
558
|
+
- Overrides must be tighten-only for `minCount`, `maxCount`, and `nodeKind` (widening is rejected at registration time).
|
|
559
|
+
- If an override omits `minCount`, `maxCount`, or `nodeKind`, inherited values are kept.
|
|
560
|
+
- Current scope: compatibility checks for `datatype`, `class`, and `pattern` are not enforced yet.
|
|
561
|
+
|
|
319
562
|
## TODO
|
|
320
563
|
|
|
321
564
|
- Allow `preloadFor` to accept another query (not just a component).
|
|
322
565
|
- Make and expose functions for auto syncing shapes to the graph.
|
|
323
566
|
|
|
567
|
+
## Intermediate Representation (IR)
|
|
568
|
+
|
|
569
|
+
Every Linked query compiles to a plain, JSON-serializable JavaScript object — the **Intermediate Representation**. This IR is the contract between the DSL and any storage backend. A store receives these objects and translates them into its native query language (SPARQL, SQL, etc.).
|
|
570
|
+
|
|
571
|
+
For example, this DSL call:
|
|
572
|
+
|
|
573
|
+
```typescript
|
|
574
|
+
const names = await Person.select((p) => p.name);
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
produces the following IR object, which is passed to your store's `selectQuery()` method:
|
|
578
|
+
|
|
579
|
+
```json
|
|
580
|
+
{
|
|
581
|
+
"kind": "select",
|
|
582
|
+
"root": {"kind": "shape_scan", "shape": "https://schema.org/Person", "alias": "a0"},
|
|
583
|
+
"patterns": [],
|
|
584
|
+
"projection": [
|
|
585
|
+
{
|
|
586
|
+
"alias": "a1",
|
|
587
|
+
"expression": {"kind": "property_expr", "sourceAlias": "a0", "property": "https://schema.org/name"}
|
|
588
|
+
}
|
|
589
|
+
],
|
|
590
|
+
"resultMap": [{"key": "name", "alias": "a1"}],
|
|
591
|
+
"singleResult": false
|
|
592
|
+
}
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
All IR types are available from `@_linked/core/queries/IntermediateRepresentation`. See the full [Intermediate Representation docs](./documentation/intermediate-representation.md) for the complete type reference, examples, and a store implementer guide.
|
|
596
|
+
|
|
597
|
+
**Store packages:**
|
|
598
|
+
|
|
599
|
+
- `SparqlStore` base class — included in `@_linked/core/sparql`, extend it for any SPARQL endpoint
|
|
600
|
+
- `@_linked/rdf-mem-store` — in-memory RDF store
|
|
601
|
+
|
|
324
602
|
## Changelog
|
|
325
603
|
|
|
326
604
|
See [CHANGELOG.md](./CHANGELOG.md).
|
package/lib/cjs/index.js
CHANGED
|
@@ -61,6 +61,7 @@ const DeleteQuery = __importStar(require("./queries/DeleteQuery.js"));
|
|
|
61
61
|
const CreateQuery = __importStar(require("./queries/CreateQuery.js"));
|
|
62
62
|
const QueryParser = __importStar(require("./queries/QueryParser.js"));
|
|
63
63
|
const QueryFactory = __importStar(require("./queries/QueryFactory.js"));
|
|
64
|
+
const IntermediateRepresentation = __importStar(require("./queries/IntermediateRepresentation.js"));
|
|
64
65
|
const NameSpace = __importStar(require("./utils/NameSpace.js"));
|
|
65
66
|
const ShapeClass = __importStar(require("./utils/ShapeClass.js"));
|
|
66
67
|
const cached = __importStar(require("./utils/cached.js"));
|
|
@@ -75,6 +76,7 @@ const shacl = __importStar(require("./ontologies/shacl.js"));
|
|
|
75
76
|
const lincd = __importStar(require("./ontologies/lincd.js"));
|
|
76
77
|
const owl = __importStar(require("./ontologies/owl.js"));
|
|
77
78
|
const npm = __importStar(require("./ontologies/npm.js"));
|
|
79
|
+
const Sparql = __importStar(require("./sparql/index.js"));
|
|
78
80
|
const next_tick_1 = __importDefault(require("next-tick"));
|
|
79
81
|
exports.nextTick = next_tick_1.default;
|
|
80
82
|
function initModularApp() {
|
|
@@ -103,6 +105,7 @@ function initModularApp() {
|
|
|
103
105
|
CreateQuery,
|
|
104
106
|
QueryParser,
|
|
105
107
|
QueryFactory,
|
|
108
|
+
IntermediateRepresentation,
|
|
106
109
|
SHACLShapes,
|
|
107
110
|
rdf,
|
|
108
111
|
rdfs,
|
|
@@ -111,6 +114,7 @@ function initModularApp() {
|
|
|
111
114
|
lincd,
|
|
112
115
|
owl,
|
|
113
116
|
npm,
|
|
117
|
+
Sparql,
|
|
114
118
|
};
|
|
115
119
|
var lincdExport = {};
|
|
116
120
|
for (let fileKey in publicFiles) {
|
package/lib/cjs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0CA,wCAiDC;AA3FD;;;;GAIG;AACH,4DAA8C;AAC9C,kFAAoE;AACpE,gFAAkE;AAClE,wEAA0D;AAC1D,kEAAoD;AACpD,kEAAoD;AACpD,yDAA2C;AAC3C,+DAAiD;AACjD,oEAAsD;AACtD,0DAA4C;AAC5C,oDAAsC;AACtC,sEAAwD;AACxD,sEAAwD;AACxD,0EAA4D;AAC5D,sEAAwD;AACxD,sEAAwD;AACxD,sEAAwD;AACxD,wEAA0D;AAC1D,oGAAsF;AACtF,gEAAkD;AAClD,kEAAoD;AACpD,0DAA4C;AAC5C,uDAAyC;AACzC,6EAA+D;AAC/D,uEAAyD;AACzD,uEAAyD;AACzD,yDAA2C;AAC3C,2DAA6C;AAC7C,yDAA2C;AAC3C,6DAA+C;AAC/C,6DAA+C;AAC/C,yDAA2C;AAC3C,yDAA2C;AAC3C,0DAA4C;AAC5C,0DAAiC;AACzB,mBADD,mBAAQ,CACC;AAEhB,SAAgB,cAAc;IAC5B,IAAI,WAAW,GAAG;QAChB,OAAO;QACP,kBAAkB;QAClB,iBAAiB;QACjB,aAAa;QACb,OAAO;QACP,OAAO;QACP,KAAK;QACL,QAAQ;QACR,MAAM;QACN,SAAS;QACT,MAAM;QACN,GAAG;QACH,UAAU;QACV,IAAI;QACJ,aAAa;QACb,UAAU;QACV,UAAU;QACV,WAAW;QACX,WAAW;QACX,aAAa;QACb,WAAW;QACX,WAAW;QACX,WAAW;QACX,YAAY;QACZ,0BAA0B;QAC1B,WAAW;QACX,GAAG;QACH,IAAI;QACJ,GAAG;QACH,KAAK;QACL,KAAK;QACL,GAAG;QACH,GAAG;QACH,MAAM;KACP,CAAC;IACF,IAAI,WAAW,GAAG,EAAE,CAAC;IACrB,KAAK,IAAI,OAAO,IAAI,WAAW,EAAE,CAAC;QAChC,IAAI,eAAe,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;QAC3C,KAAK,IAAI,SAAS,IAAI,eAAe,EAAE,CAAC;YACtC,WAAW,CAAC,SAAS,CAAC,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;IACD,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QAClC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,WAAW,CAAC,CAAC;IAC9C,CAAC;SAAM,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QACzC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,WAAW,CAAC,CAAC;IAC9C,CAAC;AACH,CAAC"}
|
|
@@ -1,14 +1,26 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import type { SelectQuery } from '../queries/SelectQuery.js';
|
|
2
|
+
import type { CreateQuery } from '../queries/CreateQuery.js';
|
|
3
|
+
import type { UpdateQuery } from '../queries/UpdateQuery.js';
|
|
4
|
+
import type { DeleteQuery, DeleteResponse } from '../queries/DeleteQuery.js';
|
|
5
|
+
import type { SelectResult, CreateResult, UpdateResult } from '../queries/IntermediateRepresentation.js';
|
|
6
|
+
/**
|
|
7
|
+
* Store interface for executing IR queries.
|
|
8
|
+
*
|
|
9
|
+
* Implement this interface to back Linked with a custom storage engine
|
|
10
|
+
* (SPARQL endpoint, SQL database, in-memory store, etc.).
|
|
11
|
+
*
|
|
12
|
+
* Each method receives a canonical IR query object and returns the result.
|
|
13
|
+
* The calling layer (LinkedStorage / QueryParser) threads the precise
|
|
14
|
+
* DSL-level TypeScript result type back to the caller — the store only
|
|
15
|
+
* needs to produce data that matches the structural result types.
|
|
16
|
+
*/
|
|
5
17
|
export interface IQuadStore {
|
|
6
18
|
/**
|
|
7
19
|
* Prepares the store to be used.
|
|
8
20
|
*/
|
|
9
21
|
init?(): Promise<any>;
|
|
10
|
-
selectQuery
|
|
11
|
-
updateQuery
|
|
12
|
-
createQuery
|
|
22
|
+
selectQuery(query: SelectQuery): Promise<SelectResult>;
|
|
23
|
+
updateQuery?(query: UpdateQuery): Promise<UpdateResult>;
|
|
24
|
+
createQuery?(query: CreateQuery): Promise<CreateResult>;
|
|
13
25
|
deleteQuery?(query: DeleteQuery): Promise<DeleteResponse>;
|
|
14
26
|
}
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
import { Shape } from '../shapes/Shape.js';
|
|
2
|
-
import { NodeShape } from '../shapes/SHACL.js';
|
|
3
|
-
import { LinkedQuery } from './SelectQuery.js';
|
|
4
2
|
import { AddId, NodeDescriptionValue, UpdatePartial } from './QueryFactory.js';
|
|
5
3
|
import { MutationQueryFactory } from './MutationQuery.js';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
4
|
+
import { IRCreateMutation } from './IntermediateRepresentation.js';
|
|
5
|
+
/**
|
|
6
|
+
* The canonical CreateQuery type — an IR AST node representing a create mutation.
|
|
7
|
+
* This is the type received by IQuadStore.createQuery().
|
|
8
|
+
*/
|
|
9
|
+
export type CreateQuery = IRCreateMutation;
|
|
11
10
|
export type CreateResponse<U> = AddId<U, true>;
|
|
12
11
|
export declare class CreateQueryFactory<ShapeType extends Shape, U extends UpdatePartial<ShapeType>> extends MutationQueryFactory {
|
|
13
12
|
shapeClass: typeof Shape;
|
|
14
13
|
readonly id: string;
|
|
15
14
|
readonly description: NodeDescriptionValue;
|
|
16
15
|
constructor(shapeClass: typeof Shape, updateObjectOrFn: U);
|
|
17
|
-
|
|
16
|
+
build(): CreateQuery;
|
|
18
17
|
}
|
|
@@ -2,18 +2,18 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.CreateQueryFactory = void 0;
|
|
4
4
|
const MutationQuery_js_1 = require("./MutationQuery.js");
|
|
5
|
+
const IRMutation_js_1 = require("./IRMutation.js");
|
|
5
6
|
class CreateQueryFactory extends MutationQuery_js_1.MutationQueryFactory {
|
|
6
7
|
constructor(shapeClass, updateObjectOrFn) {
|
|
7
8
|
super();
|
|
8
9
|
this.shapeClass = shapeClass;
|
|
9
10
|
this.description = this.convertUpdateObject(updateObjectOrFn, this.shapeClass.shape, true);
|
|
10
11
|
}
|
|
11
|
-
|
|
12
|
-
return {
|
|
13
|
-
type: 'create',
|
|
12
|
+
build() {
|
|
13
|
+
return (0, IRMutation_js_1.buildCanonicalCreateMutationIR)({
|
|
14
14
|
shape: this.shapeClass.shape,
|
|
15
15
|
description: this.description,
|
|
16
|
-
};
|
|
16
|
+
});
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
exports.CreateQueryFactory = CreateQueryFactory;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CreateQuery.js","sourceRoot":"","sources":["../../../src/queries/CreateQuery.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"CreateQuery.js","sourceRoot":"","sources":["../../../src/queries/CreateQuery.ts"],"names":[],"mappings":";;;AAEA,yDAAwD;AAExD,mDAA+D;AAU/D,MAAa,kBAGX,SAAQ,uCAAoB;IAI5B,YACS,UAAwB,EAC/B,gBAAmB;QAEnB,KAAK,EAAE,CAAC;QAHD,eAAU,GAAV,UAAU,CAAc;QAI/B,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,mBAAmB,CACzC,gBAAgB,EAChB,IAAI,CAAC,UAAU,CAAC,KAAK,EACrB,IAAI,CACL,CAAC;IACJ,CAAC;IAED,KAAK;QACH,OAAO,IAAA,8CAA8B,EAAC;YACpC,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK;YAC5B,WAAW,EAAE,IAAI,CAAC,WAAW;SAC9B,CAAC,CAAC;IACL,CAAC;CACF;AAzBD,gDAyBC"}
|