@_linked/core 0.0.1 → 1.0.0-next.20260216062729

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.
Files changed (81) hide show
  1. package/CHANGELOG.md +71 -0
  2. package/LICENSE +1 -1
  3. package/README.md +147 -92
  4. package/lib/cjs/queries/SelectQuery.d.ts +5 -0
  5. package/lib/cjs/queries/SelectQuery.js +14 -0
  6. package/lib/cjs/queries/SelectQuery.js.map +1 -1
  7. package/lib/cjs/shapes/SHACL.d.ts +1 -0
  8. package/lib/cjs/shapes/SHACL.js +82 -2
  9. package/lib/cjs/shapes/SHACL.js.map +1 -1
  10. package/lib/cjs/shapes/Shape.d.ts +13 -1
  11. package/lib/cjs/shapes/Shape.js +6 -0
  12. package/lib/cjs/shapes/Shape.js.map +1 -1
  13. package/lib/cjs/test-helpers/query-fixtures.d.ts +583 -0
  14. package/lib/cjs/test-helpers/query-fixtures.js +39 -1
  15. package/lib/cjs/test-helpers/query-fixtures.js.map +1 -1
  16. package/lib/esm/queries/SelectQuery.d.ts +5 -0
  17. package/lib/esm/queries/SelectQuery.js +14 -0
  18. package/lib/esm/queries/SelectQuery.js.map +1 -1
  19. package/lib/esm/shapes/SHACL.d.ts +1 -0
  20. package/lib/esm/shapes/SHACL.js +82 -2
  21. package/lib/esm/shapes/SHACL.js.map +1 -1
  22. package/lib/esm/shapes/Shape.d.ts +13 -1
  23. package/lib/esm/shapes/Shape.js +6 -0
  24. package/lib/esm/shapes/Shape.js.map +1 -1
  25. package/lib/esm/test-helpers/query-fixtures.d.ts +583 -0
  26. package/lib/esm/test-helpers/query-fixtures.js +38 -0
  27. package/lib/esm/test-helpers/query-fixtures.js.map +1 -1
  28. package/package.json +17 -1
  29. package/.context/notes.md +0 -0
  30. package/.context/todos.md +0 -0
  31. package/AGENTS.md +0 -59
  32. package/docs/001-core-extraction.md +0 -305
  33. package/jest.config.js +0 -25
  34. package/scripts/dual-package.js +0 -25
  35. package/src/collections/CoreMap.ts +0 -127
  36. package/src/collections/CoreSet.ts +0 -171
  37. package/src/collections/ShapeSet.ts +0 -18
  38. package/src/index.ts +0 -88
  39. package/src/interfaces/ICoreIterable.ts +0 -35
  40. package/src/interfaces/IFileStore.ts +0 -28
  41. package/src/interfaces/IQuadStore.ts +0 -16
  42. package/src/interfaces/IQueryParser.ts +0 -51
  43. package/src/ontologies/lincd.ts +0 -25
  44. package/src/ontologies/npm.ts +0 -15
  45. package/src/ontologies/owl.ts +0 -26
  46. package/src/ontologies/rdf.ts +0 -32
  47. package/src/ontologies/rdfs.ts +0 -38
  48. package/src/ontologies/shacl.ts +0 -136
  49. package/src/ontologies/xsd.ts +0 -47
  50. package/src/package.ts +0 -11
  51. package/src/queries/CreateQuery.ts +0 -41
  52. package/src/queries/DeleteQuery.ts +0 -54
  53. package/src/queries/MutationQuery.ts +0 -287
  54. package/src/queries/QueryContext.ts +0 -41
  55. package/src/queries/QueryFactory.ts +0 -275
  56. package/src/queries/QueryParser.ts +0 -79
  57. package/src/queries/SelectQuery.ts +0 -2101
  58. package/src/queries/UpdateQuery.ts +0 -47
  59. package/src/shapes/List.ts +0 -52
  60. package/src/shapes/SHACL.ts +0 -653
  61. package/src/shapes/Shape.ts +0 -282
  62. package/src/test-helpers/query-fixtures.ts +0 -313
  63. package/src/tests/core-utils.test.ts +0 -286
  64. package/src/tests/metadata.test.ts +0 -65
  65. package/src/tests/query.test.ts +0 -599
  66. package/src/tests/query.types.test.ts +0 -606
  67. package/src/tests/store-routing.test.ts +0 -133
  68. package/src/utils/LinkedErrorLogging.ts +0 -25
  69. package/src/utils/LinkedFileStorage.ts +0 -75
  70. package/src/utils/LinkedStorage.ts +0 -120
  71. package/src/utils/NameSpace.ts +0 -5
  72. package/src/utils/NodeReference.ts +0 -16
  73. package/src/utils/Package.ts +0 -681
  74. package/src/utils/Prefix.ts +0 -108
  75. package/src/utils/ShapeClass.ts +0 -335
  76. package/src/utils/Types.ts +0 -19
  77. package/src/utils/URI.ts +0 -40
  78. package/src/utils/cached.ts +0 -53
  79. package/tsconfig-cjs.json +0 -8
  80. package/tsconfig-esm.json +0 -9
  81. package/tsconfig.json +0 -29
@@ -1,286 +0,0 @@
1
- import {describe, expect, test, jest, beforeEach} from '@jest/globals';
2
- import {linkedPackage} from '../utils/Package';
3
- import {Shape} from '../shapes/Shape';
4
- import {literalProperty, objectProperty} from '../shapes/SHACL';
5
- import {CoreSet} from '../collections/CoreSet';
6
- import {
7
- getLeastSpecificShapeClasses,
8
- getMostSpecificSubShapes,
9
- getPropertyShapeByLabel,
10
- getShapeClass,
11
- getSubShapesClasses,
12
- getSuperShapesClasses,
13
- } from '../utils/ShapeClass';
14
- import {LinkedStorage} from '../utils/LinkedStorage';
15
- import {QueryParser} from '../queries/QueryParser';
16
- import {isWhereEvaluationPath} from '../queries/SelectQuery';
17
- import {getQueryContext, setQueryContext} from '../queries/QueryContext';
18
- import {NodeReferenceValue} from '../utils/NodeReference';
19
-
20
- const makeProp = (base: string) => (suffix: string): NodeReferenceValue => ({
21
- id: `${base}${suffix}`,
22
- });
23
-
24
- const shapeProp = makeProp('linked://tmp/shapeclass/');
25
- const contextProp = makeProp('linked://tmp/context/');
26
- const packageProp = makeProp('linked://tmp/package/');
27
-
28
- const {linkedShape: linkedShapeClassTest} = linkedPackage('shapeclass-test');
29
- const {linkedShape: linkedShapeContextTest} = linkedPackage('context-test');
30
- const {
31
- linkedShape: linkedShapePackageTest,
32
- registerPackageExport,
33
- registerPackageModule,
34
- packageExports,
35
- getPackageShape,
36
- } = linkedPackage('package-test');
37
-
38
- @linkedShapeClassTest
39
- class BaseShape extends Shape {
40
- @literalProperty({path: shapeProp('base')})
41
- get base(): string {
42
- return '';
43
- }
44
- }
45
-
46
- @linkedShapeClassTest
47
- class SubShape extends BaseShape {
48
- @literalProperty({path: shapeProp('sub')})
49
- get sub(): string {
50
- return '';
51
- }
52
- }
53
-
54
- @linkedShapeClassTest
55
- class DeepSubShape extends SubShape {
56
- @literalProperty({path: shapeProp('deep')})
57
- get deep(): string {
58
- return '';
59
- }
60
- }
61
-
62
- @linkedShapeClassTest
63
- class SiblingSubShape extends BaseShape {
64
- @literalProperty({path: shapeProp('sibling')})
65
- get sibling(): string {
66
- return '';
67
- }
68
- }
69
-
70
- @linkedShapeContextTest
71
- class ContextPerson extends Shape {
72
- @literalProperty({path: contextProp('name'), maxCount: 1})
73
- get name(): string {
74
- return '';
75
- }
76
-
77
- @objectProperty({path: contextProp('bestFriend'), maxCount: 1, shape: ContextPerson})
78
- get bestFriend(): ContextPerson {
79
- return null;
80
- }
81
- }
82
-
83
- @linkedShapePackageTest
84
- class PackagePerson extends Shape {
85
- @literalProperty({path: packageProp('name'), maxCount: 1})
86
- get name(): string {
87
- return '';
88
- }
89
- }
90
-
91
- const resetLinkedStorage = () => {
92
- LinkedStorage.setDefaultStore(null as any);
93
- LinkedStorage.getShapeToStoreMap().clear();
94
- };
95
-
96
- describe('ShapeClass utilities', () => {
97
- test('getShapeClass resolves a class by node shape id', () => {
98
- expect(getShapeClass(BaseShape.shape.id)).toBe(BaseShape);
99
- });
100
-
101
- test('getSubShapesClasses returns subclasses', () => {
102
- const subs = getSubShapesClasses(BaseShape);
103
- expect(subs).toEqual(
104
- expect.arrayContaining([SubShape, DeepSubShape, SiblingSubShape]),
105
- );
106
- });
107
-
108
- test('getSuperShapesClasses returns superclasses (most specific first)', () => {
109
- const supers = getSuperShapesClasses(DeepSubShape);
110
- expect(supers[0]).toBe(SubShape);
111
- expect(supers).toEqual(expect.arrayContaining([BaseShape, Shape]));
112
- });
113
-
114
- test('getPropertyShapeByLabel walks inheritance chain', () => {
115
- const property = getPropertyShapeByLabel(DeepSubShape, 'base');
116
- expect(property).toBeDefined();
117
- expect(property?.parentNodeShape).toBe(BaseShape.shape);
118
- });
119
-
120
- test('getMostSpecificSubShapes returns only leaves', () => {
121
- const mostSpecific = getMostSpecificSubShapes(BaseShape);
122
- expect(mostSpecific).toEqual(
123
- expect.arrayContaining([DeepSubShape, SiblingSubShape]),
124
- );
125
- expect(mostSpecific).not.toEqual(expect.arrayContaining([SubShape]));
126
- });
127
-
128
- test('getLeastSpecificShapeClasses filters to base shapes', () => {
129
- const shapes = new CoreSet([new SubShape(), new SiblingSubShape(), new BaseShape()]);
130
- const leastSpecific = getLeastSpecificShapeClasses(shapes);
131
- expect(leastSpecific).toEqual(expect.arrayContaining([BaseShape]));
132
- expect(leastSpecific).not.toEqual(
133
- expect.arrayContaining([SubShape, SiblingSubShape]),
134
- );
135
- });
136
- });
137
-
138
- describe('LinkedStorage extra behaviors', () => {
139
- beforeEach(() => resetLinkedStorage());
140
-
141
- test('setDefaultStore calls init when provided', () => {
142
- const init = jest.fn();
143
- LinkedStorage.setDefaultStore({init} as any);
144
- expect(init).toHaveBeenCalled();
145
- });
146
-
147
- test('getStores returns default and shape-specific stores', () => {
148
- const defaultStore = {selectQuery: jest.fn()} as any;
149
- const shapeStore = {selectQuery: jest.fn()} as any;
150
- LinkedStorage.setDefaultStore(defaultStore);
151
- LinkedStorage.setStoreForShapes(shapeStore, BaseShape);
152
- const stores = LinkedStorage.getStores();
153
- expect(stores.has(defaultStore)).toBe(true);
154
- expect(stores.has(shapeStore)).toBe(true);
155
- });
156
-
157
- test('getStoreForShapeClass falls back to superclass mapping', () => {
158
- const baseStore = {selectQuery: jest.fn()} as any;
159
- LinkedStorage.setStoreForShapes(baseStore, BaseShape);
160
- expect(LinkedStorage.getStoreForShapeClass(SubShape)).toBe(baseStore);
161
- });
162
-
163
- test('selectQuery rejects when no store is configured', async () => {
164
- await expect(
165
- LinkedStorage.selectQuery({shape: null} as any),
166
- ).rejects.toThrow('No query store configured');
167
- });
168
- });
169
-
170
- describe('QueryParser delegation', () => {
171
- beforeEach(() => resetLinkedStorage());
172
-
173
- test('selectQuery delegates to LinkedStorage', async () => {
174
- const store = {
175
- selectQuery: jest.fn(async () => [{id: 'r1'}]),
176
- } as any;
177
- LinkedStorage.setDefaultStore(store);
178
-
179
- const queryFactory = ContextPerson.query((p) => p.name);
180
- const result = await QueryParser.selectQuery(queryFactory);
181
-
182
- expect(store.selectQuery).toHaveBeenCalledTimes(1);
183
- expect(store.selectQuery.mock.calls[0][0]?.type).toBe('select');
184
- expect(result).toEqual([{id: 'r1'}]);
185
- });
186
-
187
- test('update/create/delete delegate to LinkedStorage', async () => {
188
- const store = {
189
- updateQuery: jest.fn(async () => ({id: 'u1'})),
190
- createQuery: jest.fn(async () => ({id: 'c1'})),
191
- deleteQuery: jest.fn(async () => ({deleted: [], count: 0})),
192
- } as any;
193
- LinkedStorage.setDefaultStore(store);
194
-
195
- const updateResult = await QueryParser.updateQuery(
196
- 'u1',
197
- {name: 'Ada'} as any,
198
- ContextPerson,
199
- );
200
- const createResult = await QueryParser.createQuery(
201
- {name: 'Tess'} as any,
202
- ContextPerson,
203
- );
204
- const deleteResult = await QueryParser.deleteQuery('d1', ContextPerson);
205
-
206
- expect(store.updateQuery.mock.calls[0][0]?.type).toBe('update');
207
- expect(store.createQuery.mock.calls[0][0]?.type).toBe('create');
208
- expect(store.deleteQuery.mock.calls[0][0]?.type).toBe('delete');
209
- expect(updateResult).toEqual({id: 'u1'});
210
- expect(createResult).toEqual({id: 'c1'});
211
- expect(deleteResult).toEqual({deleted: [], count: 0});
212
- });
213
- });
214
-
215
- describe('QueryContext edge cases', () => {
216
- test('getQueryContext returns null for unknown names', () => {
217
- expect(getQueryContext('missing-context')).toBeNull();
218
- });
219
-
220
- test('setQueryContext warns and ignores invalid values', () => {
221
- const warn = jest.spyOn(console, 'warn').mockImplementation(() => {});
222
- setQueryContext('invalid-context', {foo: 'bar'} as any);
223
- expect(getQueryContext('invalid-context')).toBeNull();
224
- expect(warn).toHaveBeenCalled();
225
- warn.mockRestore();
226
- });
227
-
228
- test('setQueryContext warns when QResult provided without shapeType', () => {
229
- const warn = jest.spyOn(console, 'warn').mockImplementation(() => {});
230
- setQueryContext('missing-shape', {id: 'ctx-1'} as any);
231
- expect(getQueryContext('missing-shape')).toBeNull();
232
- expect(warn).toHaveBeenCalled();
233
- warn.mockRestore();
234
- });
235
-
236
- test('setQueryContext accepts QResult with shapeType and uses latest value', () => {
237
- setQueryContext('ctx', {id: 'ctx-1'} as any, ContextPerson);
238
- setQueryContext('ctx', {id: 'ctx-2'} as any, ContextPerson);
239
- const context = getQueryContext('ctx');
240
- expect(context.id).toBe('ctx-2');
241
-
242
- const query = ContextPerson.query((p) => p.name).where((p) =>
243
- p.bestFriend.equals(context),
244
- );
245
- const queryObject = query.getQueryObject();
246
- const where = queryObject?.where;
247
- expect(where).toBeDefined();
248
- if (!where) {
249
- throw new Error('Expected where clause');
250
- }
251
- const evaluation = isWhereEvaluationPath(where) ? where : where.firstPath;
252
- if (!isWhereEvaluationPath(evaluation)) {
253
- throw new Error('Expected evaluation where clause');
254
- }
255
- expect(evaluation.args[0]).toEqual({
256
- id: 'ctx-2',
257
- shape: {id: ContextPerson.shape.id},
258
- });
259
- });
260
- });
261
-
262
- describe('Package registration helpers', () => {
263
- test('getPackageShape returns a shape class by name', () => {
264
- expect(getPackageShape(PackagePerson.name)).toBe(PackagePerson);
265
- });
266
-
267
- test('registerPackageExport adds items to packageExports', () => {
268
- function Helper() {}
269
- registerPackageExport(Helper);
270
- expect(packageExports.Helper).toBe(Helper);
271
- });
272
-
273
- test('registerPackageModule sets names and registers exports', () => {
274
- const unnamed = {name: '', original: {name: ''}};
275
- const wrapped = {name: '_wrappedComponent', original: {name: ''}};
276
- const moduleRef = {exports: {Unnamed: unnamed, Wrapped: wrapped}};
277
-
278
- registerPackageModule(moduleRef);
279
-
280
- expect(moduleRef.exports.Unnamed.name).toBe('Unnamed');
281
- expect(moduleRef.exports.Wrapped.name).toBe('Wrapped');
282
- expect(moduleRef.exports.Wrapped.original.name).toBe('Wrapped_implementation');
283
- expect(packageExports.Unnamed).toBe(moduleRef.exports.Unnamed);
284
- expect(packageExports.Wrapped).toBe(moduleRef.exports.Wrapped);
285
- });
286
- });
@@ -1,65 +0,0 @@
1
- import {describe, expect, test} from '@jest/globals';
2
- import {linkedPackage} from '../utils/Package';
3
- import {Shape} from '../shapes/Shape';
4
- import {literalProperty, LINCD_DATA_ROOT} from '../shapes/SHACL';
5
- import {URI} from '../utils/URI';
6
- import {lincd} from '../ontologies/lincd';
7
- import {shacl} from '../ontologies/shacl';
8
- import {NodeReferenceValue} from '../utils/NodeReference';
9
-
10
- const packageName = 'meta-test';
11
- const {linkedShape, packageMetadata} = linkedPackage(packageName);
12
-
13
- const tmpPropBase = 'linked://tmp/props/';
14
- const tmpTypeBase = 'linked://tmp/types/';
15
-
16
- const prop = (suffix: string): NodeReferenceValue => ({
17
- id: `${tmpPropBase}${suffix}`,
18
- });
19
- const type = (suffix: string): NodeReferenceValue => ({
20
- id: `${tmpTypeBase}${suffix}`,
21
- });
22
-
23
- @linkedShape
24
- class MetaPerson extends Shape {
25
- static targetClass = type('MetaPerson');
26
-
27
- @literalProperty({path: prop('name'), maxCount: 1})
28
- get name(): string {
29
- return '';
30
- }
31
- }
32
-
33
- describe('Package & Shape Metadata Registration', () => {
34
- test('registers package metadata with legacy id format', () => {
35
- expect(packageMetadata).toEqual({
36
- id: `${LINCD_DATA_ROOT}module/${packageName}`,
37
- packageName,
38
- type: lincd.Module,
39
- });
40
- expect(globalThis['lincd']._packages[packageName]).toBe(packageMetadata);
41
- });
42
-
43
- test('registers node shape metadata with expected id', () => {
44
- const expectedId = `${LINCD_DATA_ROOT}module/${URI.sanitize(
45
- packageName,
46
- )}/shape/${URI.sanitize(MetaPerson.name)}`;
47
-
48
- expect(MetaPerson.shape).toBeDefined();
49
- expect(MetaPerson.shape.id).toBe(expectedId);
50
- expect(MetaPerson.shape.label).toBe(MetaPerson.name);
51
- expect(MetaPerson.shape.targetClass).toEqual(type('MetaPerson'));
52
- });
53
-
54
- test('registers property shape metadata with expected id', () => {
55
- const nodeShapeId = MetaPerson.shape.id;
56
- const propertyShape = MetaPerson.shape.getPropertyShape('name');
57
-
58
- expect(propertyShape).toBeDefined();
59
- expect(propertyShape.label).toBe('name');
60
- expect(propertyShape.id).toBe(`${nodeShapeId}/name`);
61
- expect(propertyShape.path).toEqual(prop('name'));
62
- expect(propertyShape.nodeKind).toEqual(shacl.Literal);
63
- expect(propertyShape.parentNodeShape).toBe(MetaPerson.shape);
64
- });
65
- });