@_linked/core 0.0.1 → 1.0.0-next.20260211072341

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 (57) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/LICENSE +1 -1
  3. package/README.md +1 -53
  4. package/package.json +17 -1
  5. package/.context/notes.md +0 -0
  6. package/.context/todos.md +0 -0
  7. package/AGENTS.md +0 -59
  8. package/docs/001-core-extraction.md +0 -305
  9. package/jest.config.js +0 -25
  10. package/scripts/dual-package.js +0 -25
  11. package/src/collections/CoreMap.ts +0 -127
  12. package/src/collections/CoreSet.ts +0 -171
  13. package/src/collections/ShapeSet.ts +0 -18
  14. package/src/index.ts +0 -88
  15. package/src/interfaces/ICoreIterable.ts +0 -35
  16. package/src/interfaces/IFileStore.ts +0 -28
  17. package/src/interfaces/IQuadStore.ts +0 -16
  18. package/src/interfaces/IQueryParser.ts +0 -51
  19. package/src/ontologies/lincd.ts +0 -25
  20. package/src/ontologies/npm.ts +0 -15
  21. package/src/ontologies/owl.ts +0 -26
  22. package/src/ontologies/rdf.ts +0 -32
  23. package/src/ontologies/rdfs.ts +0 -38
  24. package/src/ontologies/shacl.ts +0 -136
  25. package/src/ontologies/xsd.ts +0 -47
  26. package/src/package.ts +0 -11
  27. package/src/queries/CreateQuery.ts +0 -41
  28. package/src/queries/DeleteQuery.ts +0 -54
  29. package/src/queries/MutationQuery.ts +0 -287
  30. package/src/queries/QueryContext.ts +0 -41
  31. package/src/queries/QueryFactory.ts +0 -275
  32. package/src/queries/QueryParser.ts +0 -79
  33. package/src/queries/SelectQuery.ts +0 -2101
  34. package/src/queries/UpdateQuery.ts +0 -47
  35. package/src/shapes/List.ts +0 -52
  36. package/src/shapes/SHACL.ts +0 -653
  37. package/src/shapes/Shape.ts +0 -282
  38. package/src/test-helpers/query-fixtures.ts +0 -313
  39. package/src/tests/core-utils.test.ts +0 -286
  40. package/src/tests/metadata.test.ts +0 -65
  41. package/src/tests/query.test.ts +0 -599
  42. package/src/tests/query.types.test.ts +0 -606
  43. package/src/tests/store-routing.test.ts +0 -133
  44. package/src/utils/LinkedErrorLogging.ts +0 -25
  45. package/src/utils/LinkedFileStorage.ts +0 -75
  46. package/src/utils/LinkedStorage.ts +0 -120
  47. package/src/utils/NameSpace.ts +0 -5
  48. package/src/utils/NodeReference.ts +0 -16
  49. package/src/utils/Package.ts +0 -681
  50. package/src/utils/Prefix.ts +0 -108
  51. package/src/utils/ShapeClass.ts +0 -335
  52. package/src/utils/Types.ts +0 -19
  53. package/src/utils/URI.ts +0 -40
  54. package/src/utils/cached.ts +0 -53
  55. package/tsconfig-cjs.json +0 -8
  56. package/tsconfig-esm.json +0 -9
  57. 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
- });