@nest-yalc-2/omnikernel-module 2.2.1 → 2.2.4

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 (74) hide show
  1. package/package.json +22 -14
  2. package/src/__tests__/omni-collection.entity.spec.ts +49 -49
  3. package/src/__tests__/omni-collection.service.spec.ts +83 -83
  4. package/src/__tests__/omni-document.entity.spec.ts +55 -55
  5. package/src/__tests__/omni-document.service.spec.ts +83 -83
  6. package/src/__tests__/omni-extension-projection-constraints.spec.ts +518 -518
  7. package/src/__tests__/omni-extension-projection.registration.spec.ts +947 -946
  8. package/src/__tests__/omni-extension-projection.service.spec.ts +806 -806
  9. package/src/__tests__/omni-external-ref.entity.spec.ts +36 -36
  10. package/src/__tests__/omni-external-ref.service.spec.ts +252 -252
  11. package/src/__tests__/omni-named.entity.spec.ts +33 -33
  12. package/src/__tests__/omni-record.entity.spec.ts +32 -32
  13. package/src/__tests__/omni-record.service.spec.ts +107 -107
  14. package/src/__tests__/omni-relation-semantics.spec.ts +102 -102
  15. package/src/__tests__/omni-relation.entity.spec.ts +38 -38
  16. package/src/__tests__/omni-scope-substrate.spec.ts +81 -81
  17. package/src/__tests__/omni-scoped.backend.spec.ts +115 -115
  18. package/src/__tests__/omni-scoped.service.spec.ts +354 -354
  19. package/src/__tests__/omnikernel.diagnostics.spec.ts +94 -94
  20. package/src/__tests__/omnikernel.module.spec.ts +38 -40
  21. package/src/__tests__/omnikernel.persistence.spec.ts +154 -154
  22. package/src/__tests__/omnikernel.public-api.spec.ts +238 -238
  23. package/src/__tests__/omnikernel.query.service.spec.ts +155 -155
  24. package/src/base/omni-base.entity.ts +41 -41
  25. package/src/base/omni-external-ref.entity.ts +53 -53
  26. package/src/base/omni-named.entity.ts +16 -16
  27. package/src/base/omni-record.entity.ts +51 -51
  28. package/src/base/omni-relation.entity.ts +72 -72
  29. package/src/index.ts +49 -49
  30. package/src/omni-collection-kind.enum.ts +10 -10
  31. package/src/omni-collection.backend.ts +16 -16
  32. package/src/omni-collection.dto.ts +170 -170
  33. package/src/omni-collection.entity.ts +21 -21
  34. package/src/omni-collection.service.ts +75 -75
  35. package/src/omni-document-kind.enum.ts +12 -12
  36. package/src/omni-document.backend.ts +16 -16
  37. package/src/omni-document.dto.ts +198 -198
  38. package/src/omni-document.entity.ts +30 -30
  39. package/src/omni-document.service.ts +75 -75
  40. package/src/omni-dto.helpers.ts +21 -21
  41. package/src/omni-extension-projection.definition.ts +294 -294
  42. package/src/omni-extension-projection.resource.ts +274 -274
  43. package/src/omni-extension-projection.service.ts +452 -452
  44. package/src/omni-external-ref-binding.validator.ts +53 -53
  45. package/src/omni-external-ref-internal-type.enum.ts +11 -11
  46. package/src/omni-external-ref.backend.ts +25 -25
  47. package/src/omni-external-ref.dto.ts +128 -128
  48. package/src/omni-external-ref.service.ts +255 -255
  49. package/src/omni-migration.ts +365 -365
  50. package/src/omni-named.backend.ts +11 -11
  51. package/src/omni-named.dto.ts +86 -86
  52. package/src/omni-projection.catalog.ts +345 -345
  53. package/src/omni-projection.lifecycle.ts +53 -53
  54. package/src/omni-record-status.enum.ts +11 -11
  55. package/src/omni-record.backend.ts +19 -19
  56. package/src/omni-record.dto.ts +157 -157
  57. package/src/omni-record.service.ts +113 -113
  58. package/src/omni-relation-kind.contract.ts +49 -49
  59. package/src/omni-relation-kind.enum.ts +12 -12
  60. package/src/omni-relation-projection.definition.ts +166 -166
  61. package/src/omni-relation-projection.resource.ts +360 -360
  62. package/src/omni-relation-projection.service.ts +610 -610
  63. package/src/omni-relation-semantics.ts +52 -52
  64. package/src/omni-relation-status.enum.ts +11 -11
  65. package/src/omni-relation.backend.ts +21 -21
  66. package/src/omni-relation.dto.ts +142 -142
  67. package/src/omni-relation.service.ts +159 -159
  68. package/src/omni-scope.ts +161 -161
  69. package/src/omni-scoped.backend.ts +110 -110
  70. package/src/omni-scoped.repository.ts +34 -34
  71. package/src/omni-scoped.service.ts +338 -338
  72. package/src/omnikernel.diagnostics.ts +83 -83
  73. package/src/omnikernel.module.ts +97 -97
  74. package/src/omnikernel.query.service.ts +108 -108
@@ -1,94 +1,94 @@
1
- import { describe, expect, it, jest } from "@jest/globals";
2
-
3
- import { collectOmniKernelQueryPlanEvidence } from '../omnikernel.diagnostics.js';
4
-
5
- const sample = {
6
- scopeId: "scope-alpha",
7
- recordKind: "generic",
8
- recordStatus: "active",
9
- sourceRecordId: "record-1",
10
- relationKind: "references",
11
- relationStatus: "active",
12
- };
13
-
14
- describe("OmniKernel query-plan diagnostics", () => {
15
- it("records sqlite index evidence for the bounded generated read shapes", async () => {
16
- const query = jest
17
- .fn()
18
- .mockResolvedValueOnce([
19
- {
20
- detail:
21
- "SEARCH omni-record USING INDEX omni_record_scope_kind_status_guid_idx",
22
- },
23
- ])
24
- .mockResolvedValueOnce([
25
- {
26
- detail:
27
- "SEARCH omni-relation USING INDEX omni_relation_scope_source_kind_status_created_guid_idx",
28
- },
29
- ]);
30
-
31
- const evidence = await collectOmniKernelQueryPlanEvidence(
32
- { options: { type: "sqlite" }, query } as never,
33
- sample,
34
- );
35
-
36
- expect(evidence).toMatchObject({
37
- dialect: "sqlite",
38
- usesRecordGridIndex: true,
39
- usesRelationSourceIndex: true,
40
- });
41
- expect(query.mock.calls[0][0]).toContain("EXPLAIN QUERY PLAN");
42
- expect(query.mock.calls[1][1]).toEqual([
43
- sample.scopeId,
44
- sample.sourceRecordId,
45
- sample.relationKind,
46
- sample.relationStatus,
47
- ]);
48
- });
49
-
50
- it("records PostgreSQL JSON-plan index evidence", async () => {
51
- const query = jest
52
- .fn()
53
- .mockResolvedValueOnce([
54
- {
55
- "QUERY PLAN": [
56
- {
57
- Plan: { "Index Name": "omni_record_scope_kind_status_guid_idx" },
58
- },
59
- ],
60
- },
61
- ])
62
- .mockResolvedValueOnce([
63
- {
64
- "QUERY PLAN": [
65
- {
66
- Plan: {
67
- "Index Name":
68
- "omni_relation_scope_source_kind_status_created_guid_idx",
69
- },
70
- },
71
- ],
72
- },
73
- ]);
74
-
75
- const evidence = await collectOmniKernelQueryPlanEvidence(
76
- { options: { type: "postgres" }, query } as never,
77
- sample,
78
- );
79
-
80
- expect(evidence.dialect).toBe("postgres");
81
- expect(evidence.usesRecordGridIndex).toBe(true);
82
- expect(evidence.usesRelationSourceIndex).toBe(true);
83
- expect(query.mock.calls[0][0]).toContain("EXPLAIN (FORMAT JSON)");
84
- });
85
-
86
- it("rejects unsupported drivers instead of guessing their query-plan syntax", async () => {
87
- await expect(
88
- collectOmniKernelQueryPlanEvidence(
89
- { options: { type: "mysql" }, query: jest.fn() } as never,
90
- sample,
91
- ),
92
- ).rejects.toThrow("sqlite and postgres only");
93
- });
94
- });
1
+ import { describe, expect, it, jest } from "@jest/globals";
2
+
3
+ import { collectOmniKernelQueryPlanEvidence } from '../omnikernel.diagnostics.js';
4
+
5
+ const sample = {
6
+ scopeId: "scope-alpha",
7
+ recordKind: "generic",
8
+ recordStatus: "active",
9
+ sourceRecordId: "record-1",
10
+ relationKind: "references",
11
+ relationStatus: "active",
12
+ };
13
+
14
+ describe("OmniKernel query-plan diagnostics", () => {
15
+ it("records sqlite index evidence for the bounded generated read shapes", async () => {
16
+ const query = jest
17
+ .fn()
18
+ .mockResolvedValueOnce([
19
+ {
20
+ detail:
21
+ "SEARCH omni-record USING INDEX omni_record_scope_kind_status_guid_idx",
22
+ },
23
+ ])
24
+ .mockResolvedValueOnce([
25
+ {
26
+ detail:
27
+ "SEARCH omni-relation USING INDEX omni_relation_scope_source_kind_status_created_guid_idx",
28
+ },
29
+ ]);
30
+
31
+ const evidence = await collectOmniKernelQueryPlanEvidence(
32
+ { options: { type: "sqlite" }, query } as never,
33
+ sample,
34
+ );
35
+
36
+ expect(evidence).toMatchObject({
37
+ dialect: "sqlite",
38
+ usesRecordGridIndex: true,
39
+ usesRelationSourceIndex: true,
40
+ });
41
+ expect(query.mock.calls[0][0]).toContain("EXPLAIN QUERY PLAN");
42
+ expect(query.mock.calls[1][1]).toEqual([
43
+ sample.scopeId,
44
+ sample.sourceRecordId,
45
+ sample.relationKind,
46
+ sample.relationStatus,
47
+ ]);
48
+ });
49
+
50
+ it("records PostgreSQL JSON-plan index evidence", async () => {
51
+ const query = jest
52
+ .fn()
53
+ .mockResolvedValueOnce([
54
+ {
55
+ "QUERY PLAN": [
56
+ {
57
+ Plan: { "Index Name": "omni_record_scope_kind_status_guid_idx" },
58
+ },
59
+ ],
60
+ },
61
+ ])
62
+ .mockResolvedValueOnce([
63
+ {
64
+ "QUERY PLAN": [
65
+ {
66
+ Plan: {
67
+ "Index Name":
68
+ "omni_relation_scope_source_kind_status_created_guid_idx",
69
+ },
70
+ },
71
+ ],
72
+ },
73
+ ]);
74
+
75
+ const evidence = await collectOmniKernelQueryPlanEvidence(
76
+ { options: { type: "postgres" }, query } as never,
77
+ sample,
78
+ );
79
+
80
+ expect(evidence.dialect).toBe("postgres");
81
+ expect(evidence.usesRecordGridIndex).toBe(true);
82
+ expect(evidence.usesRelationSourceIndex).toBe(true);
83
+ expect(query.mock.calls[0][0]).toContain("EXPLAIN (FORMAT JSON)");
84
+ });
85
+
86
+ it("rejects unsupported drivers instead of guessing their query-plan syntax", async () => {
87
+ await expect(
88
+ collectOmniKernelQueryPlanEvidence(
89
+ { options: { type: "mysql" }, query: jest.fn() } as never,
90
+ sample,
91
+ ),
92
+ ).rejects.toThrow("sqlite and postgres only");
93
+ });
94
+ });
@@ -1,40 +1,38 @@
1
- import { describe, expect, it, jest } from '@jest/globals';
2
- import 'reflect-metadata';
3
- import { OmniKernelQueryService } from '../omnikernel.query.service.js';
4
-
5
- import * as OmniNamedBackend from '../omni-named.backend.js';
6
- import * as OmniRecordBackend from '../omni-record.backend.js';
7
- import * as OmniRelationBackend from '../omni-relation.backend.js';
8
- import * as OmniCollectionBackend from '../omni-collection.backend.js';
9
- import * as OmniDocumentBackend from '../omni-document.backend.js';
10
- import * as OmniExternalRefBackend from '../omni-external-ref.backend.js';
11
-
12
- const omniNamedBackendProvidersFactory = jest.spyOn(OmniNamedBackend as any, 'omniNamedBackendProvidersFactory').mockReturnValue({ providers: ['named-backend'] });
13
- const omniRecordBackendProvidersFactory = jest.spyOn(OmniRecordBackend as any, 'omniRecordBackendProvidersFactory').mockReturnValue({ providers: ['record-backend'] });
14
- const omniRelationBackendProvidersFactory = jest.spyOn(OmniRelationBackend as any, 'omniRelationBackendProvidersFactory').mockReturnValue({ providers: ['relation-backend'] });
15
- const omniCollectionBackendProvidersFactory = jest.spyOn(OmniCollectionBackend as any, 'omniCollectionBackendProvidersFactory').mockReturnValue({ providers: ['collection-backend'] });
16
- const omniDocumentBackendProvidersFactory = jest.spyOn(OmniDocumentBackend as any, 'omniDocumentBackendProvidersFactory').mockReturnValue({ providers: ['document-backend'] });
17
- const omniExternalRefBackendProvidersFactory = jest.spyOn(OmniExternalRefBackend as any, 'omniExternalRefBackendProvidersFactory').mockReturnValue({ providers: ['external-ref-backend'] });
18
-
19
- import { OmniKernelModule } from '../omnikernel.module.js';
20
-
21
- describe('OmniKernelModule', () => {
22
- it('registers only backend substrate providers', () => {
23
- const module = OmniKernelModule.register('test');
24
-
25
- expect(module).toBeDefined();
26
- expect(omniNamedBackendProvidersFactory).toHaveBeenCalledWith('test');
27
- expect(module.providers).toEqual(
28
- expect.arrayContaining([
29
- 'named-backend',
30
- 'record-backend',
31
- 'relation-backend',
32
- 'collection-backend',
33
- 'document-backend',
34
- 'external-ref-backend',
35
- expect.objectContaining({ provide: OmniKernelQueryService }),
36
- ]),
37
- );
38
- expect(module.controllers).toBeUndefined();
39
- });
40
- });
1
+ import { describe, expect, it, jest } from '@jest/globals';
2
+ import 'reflect-metadata';
3
+ import { OmniKernelQueryService } from '../omnikernel.query.service.js';
4
+
5
+
6
+ import * as OmniNamedBackend from '../omni-named.backend.js';
7
+ import * as OmniRecordBackend from '../omni-record.backend.js';
8
+ import * as OmniRelationBackend from '../omni-relation.backend.js';
9
+ import * as OmniCollectionBackend from '../omni-collection.backend.js';
10
+ import * as OmniDocumentBackend from '../omni-document.backend.js';
11
+ import * as OmniExternalRefBackend from '../omni-external-ref.backend.js';
12
+
13
+ const omniNamedBackendProvidersFactory = OmniNamedBackend.omniNamedBackendProvidersFactory as jest.Mock;
14
+ const omniRecordBackendProvidersFactory = OmniRecordBackend.omniRecordBackendProvidersFactory as jest.Mock;
15
+ const omniRelationBackendProvidersFactory = OmniRelationBackend.omniRelationBackendProvidersFactory as jest.Mock;
16
+ const omniCollectionBackendProvidersFactory = OmniCollectionBackend.omniCollectionBackendProvidersFactory as jest.Mock;
17
+ const omniDocumentBackendProvidersFactory = OmniDocumentBackend.omniDocumentBackendProvidersFactory as jest.Mock;
18
+ const omniExternalRefBackendProvidersFactory = OmniExternalRefBackend.omniExternalRefBackendProvidersFactory as jest.Mock;
19
+
20
+ import { OmniKernelModule } from '../omnikernel.module.js';
21
+
22
+ describe('OmniKernelModule', () => {
23
+ it('registers only backend substrate providers', () => {
24
+ const module = OmniKernelModule.register('test');
25
+
26
+ expect(module).toBeDefined();
27
+
28
+ expect(module.providers).toEqual(
29
+ expect.arrayContaining([
30
+ expect.objectContaining({ provide: 'OmniNamedEntityGenericService' }),
31
+ expect.objectContaining({ provide: 'OmniRecordEntityGenericService' }),
32
+ expect.objectContaining({ provide: 'OmniRelationEntityGenericService' }),
33
+ expect.objectContaining({ provide: OmniKernelQueryService }),
34
+ ]),
35
+ );
36
+ expect(module.controllers).toBeUndefined();
37
+ });
38
+ });
@@ -1,154 +1,154 @@
1
- import { afterEach, beforeEach, describe, expect, it } from '@jest/globals';
2
- import { DataSource } from 'typeorm';
3
-
4
- import { OmniNamedEntity } from '../base/omni-named.entity.js';
5
- import { OmniRecordEntity } from '../base/omni-record.entity.js';
6
- import { OmniRelationEntity } from '../base/omni-relation.entity.js';
7
- import { OmniCollectionEntity } from '../omni-collection.entity.js';
8
- import { OmniCollectionKind } from '../omni-collection-kind.enum.js';
9
- import { OmniDocumentEntity } from '../omni-document.entity.js';
10
- import { OmniDocumentKind } from '../omni-document-kind.enum.js';
11
- import { OmniRecordStatus } from '../omni-record-status.enum.js';
12
- import { OmniRelationKind } from '../omni-relation-kind.enum.js';
13
- import { OmniRelationStatus } from '../omni-relation-status.enum.js';
14
-
15
- describe('OmniKernel persistence', () => {
16
- let dataSource: DataSource;
17
-
18
- beforeEach(async () => {
19
- dataSource = new DataSource({
20
- type: 'sqlite',
21
- database: ':memory:',
22
- dropSchema: true,
23
- synchronize: true,
24
- entities: [
25
- OmniNamedEntity,
26
- OmniRecordEntity,
27
- OmniCollectionEntity,
28
- OmniDocumentEntity,
29
- OmniRelationEntity,
30
- ],
31
- });
32
-
33
- await dataSource.initialize();
34
- });
35
-
36
- afterEach(async () => {
37
- if (dataSource.isInitialized) {
38
- await dataSource.destroy();
39
- }
40
- });
41
-
42
- it('stores collections and documents in omni-record and resolves graph links back through the shared record hierarchy', async () => {
43
- const recordRepo = dataSource.getRepository(OmniRecordEntity);
44
- const collectionRepo = dataSource.getRepository(OmniCollectionEntity);
45
- const documentRepo = dataSource.getRepository(OmniDocumentEntity);
46
- const relationRepo = dataSource.getRepository(OmniRelationEntity);
47
-
48
- await recordRepo.insert(
49
- recordRepo.create({
50
- guid: '11111111-1111-1111-1111-111111111111',
51
- title: 'Task record',
52
- kind: 'task',
53
- status: OmniRecordStatus.Draft,
54
- }),
55
- );
56
- await documentRepo.insert(
57
- documentRepo.create({
58
- guid: '22222222-2222-2222-2222-222222222222',
59
- title: 'Document record',
60
- status: OmniRecordStatus.Draft,
61
- documentKind: OmniDocumentKind.Note,
62
- }),
63
- );
64
- await collectionRepo.insert(
65
- collectionRepo.create({
66
- guid: '44444444-4444-4444-4444-444444444444',
67
- title: 'Knowledge base',
68
- status: OmniRecordStatus.Active,
69
- collectionKind: OmniCollectionKind.Folder,
70
- summary: 'Primary document container',
71
- }),
72
- );
73
- await relationRepo.insert(
74
- relationRepo.create({
75
- guid: '33333333-3333-3333-3333-333333333333',
76
- sourceRecordId: '11111111-1111-1111-1111-111111111111',
77
- targetRecordId: '22222222-2222-2222-2222-222222222222',
78
- kind: OmniRelationKind.References,
79
- status: OmniRelationStatus.Active,
80
- }),
81
- );
82
- await relationRepo.insert(
83
- relationRepo.create({
84
- guid: '55555555-5555-5555-5555-555555555555',
85
- sourceRecordId: '44444444-4444-4444-4444-444444444444',
86
- targetRecordId: '22222222-2222-2222-2222-222222222222',
87
- kind: OmniRelationKind.Contains,
88
- status: OmniRelationStatus.Active,
89
- }),
90
- );
91
-
92
- const rows = await dataSource.query(
93
- 'select guid, kind, recordType, collectionKind, documentKind from "omni-record" order by guid',
94
- );
95
-
96
- expect(rows).toEqual(
97
- expect.arrayContaining([
98
- expect.objectContaining({
99
- guid: '11111111-1111-1111-1111-111111111111',
100
- kind: 'task',
101
- }),
102
- expect.objectContaining({
103
- guid: '22222222-2222-2222-2222-222222222222',
104
- kind: OmniDocumentKind.Document,
105
- recordType: OmniDocumentKind.Document,
106
- documentKind: OmniDocumentKind.Note,
107
- }),
108
- expect.objectContaining({
109
- guid: '44444444-4444-4444-4444-444444444444',
110
- kind: OmniCollectionKind.Collection,
111
- recordType: OmniCollectionKind.Collection,
112
- collectionKind: OmniCollectionKind.Folder,
113
- }),
114
- ]),
115
- );
116
-
117
- const relation = await relationRepo.findOneOrFail({
118
- where: { guid: '33333333-3333-3333-3333-333333333333' },
119
- relations: {
120
- sourceRecord: true,
121
- targetRecord: true,
122
- },
123
- });
124
-
125
- expect(relation.sourceRecord.guid).toBe(
126
- '11111111-1111-1111-1111-111111111111',
127
- );
128
- expect(relation.targetRecord).toBeInstanceOf(OmniDocumentEntity);
129
- expect(relation.targetRecord.guid).toBe(
130
- '22222222-2222-2222-2222-222222222222',
131
- );
132
- expect((relation.targetRecord as OmniDocumentEntity).kind).toBe(
133
- OmniDocumentKind.Document,
134
- );
135
-
136
- const membershipRelation = await relationRepo.findOneOrFail({
137
- where: { guid: '55555555-5555-5555-5555-555555555555' },
138
- relations: {
139
- sourceRecord: true,
140
- targetRecord: true,
141
- },
142
- });
143
-
144
- expect(membershipRelation.sourceRecord).toBeInstanceOf(OmniCollectionEntity);
145
- expect(membershipRelation.sourceRecord.guid).toBe(
146
- '44444444-4444-4444-4444-444444444444',
147
- );
148
- expect((membershipRelation.sourceRecord as OmniCollectionEntity).kind).toBe(
149
- OmniCollectionKind.Collection,
150
- );
151
- expect(membershipRelation.targetRecord).toBeInstanceOf(OmniDocumentEntity);
152
- expect(membershipRelation.kind).toBe(OmniRelationKind.Contains);
153
- });
154
- });
1
+ import { afterEach, beforeEach, describe, expect, it } from '@jest/globals';
2
+ import { DataSource } from 'typeorm';
3
+
4
+ import { OmniNamedEntity } from '../base/omni-named.entity.js';
5
+ import { OmniRecordEntity } from '../base/omni-record.entity.js';
6
+ import { OmniRelationEntity } from '../base/omni-relation.entity.js';
7
+ import { OmniCollectionEntity } from '../omni-collection.entity.js';
8
+ import { OmniCollectionKind } from '../omni-collection-kind.enum.js';
9
+ import { OmniDocumentEntity } from '../omni-document.entity.js';
10
+ import { OmniDocumentKind } from '../omni-document-kind.enum.js';
11
+ import { OmniRecordStatus } from '../omni-record-status.enum.js';
12
+ import { OmniRelationKind } from '../omni-relation-kind.enum.js';
13
+ import { OmniRelationStatus } from '../omni-relation-status.enum.js';
14
+
15
+ describe('OmniKernel persistence', () => {
16
+ let dataSource: DataSource;
17
+
18
+ beforeEach(async () => {
19
+ dataSource = new DataSource({
20
+ type: 'sqlite',
21
+ database: ':memory:',
22
+ dropSchema: true,
23
+ synchronize: true,
24
+ entities: [
25
+ OmniNamedEntity,
26
+ OmniRecordEntity,
27
+ OmniCollectionEntity,
28
+ OmniDocumentEntity,
29
+ OmniRelationEntity,
30
+ ],
31
+ });
32
+
33
+ await dataSource.initialize();
34
+ });
35
+
36
+ afterEach(async () => {
37
+ if (dataSource.isInitialized) {
38
+ await dataSource.destroy();
39
+ }
40
+ });
41
+
42
+ it('stores collections and documents in omni-record and resolves graph links back through the shared record hierarchy', async () => {
43
+ const recordRepo = dataSource.getRepository(OmniRecordEntity);
44
+ const collectionRepo = dataSource.getRepository(OmniCollectionEntity);
45
+ const documentRepo = dataSource.getRepository(OmniDocumentEntity);
46
+ const relationRepo = dataSource.getRepository(OmniRelationEntity);
47
+
48
+ await recordRepo.insert(
49
+ recordRepo.create({
50
+ guid: '11111111-1111-1111-1111-111111111111',
51
+ title: 'Task record',
52
+ kind: 'task',
53
+ status: OmniRecordStatus.Draft,
54
+ }),
55
+ );
56
+ await documentRepo.insert(
57
+ documentRepo.create({
58
+ guid: '22222222-2222-2222-2222-222222222222',
59
+ title: 'Document record',
60
+ status: OmniRecordStatus.Draft,
61
+ documentKind: OmniDocumentKind.Note,
62
+ }),
63
+ );
64
+ await collectionRepo.insert(
65
+ collectionRepo.create({
66
+ guid: '44444444-4444-4444-4444-444444444444',
67
+ title: 'Knowledge base',
68
+ status: OmniRecordStatus.Active,
69
+ collectionKind: OmniCollectionKind.Folder,
70
+ summary: 'Primary document container',
71
+ }),
72
+ );
73
+ await relationRepo.insert(
74
+ relationRepo.create({
75
+ guid: '33333333-3333-3333-3333-333333333333',
76
+ sourceRecordId: '11111111-1111-1111-1111-111111111111',
77
+ targetRecordId: '22222222-2222-2222-2222-222222222222',
78
+ kind: OmniRelationKind.References,
79
+ status: OmniRelationStatus.Active,
80
+ }),
81
+ );
82
+ await relationRepo.insert(
83
+ relationRepo.create({
84
+ guid: '55555555-5555-5555-5555-555555555555',
85
+ sourceRecordId: '44444444-4444-4444-4444-444444444444',
86
+ targetRecordId: '22222222-2222-2222-2222-222222222222',
87
+ kind: OmniRelationKind.Contains,
88
+ status: OmniRelationStatus.Active,
89
+ }),
90
+ );
91
+
92
+ const rows = await dataSource.query(
93
+ 'select guid, kind, recordType, collectionKind, documentKind from "omni-record" order by guid',
94
+ );
95
+
96
+ expect(rows).toEqual(
97
+ expect.arrayContaining([
98
+ expect.objectContaining({
99
+ guid: '11111111-1111-1111-1111-111111111111',
100
+ kind: 'task',
101
+ }),
102
+ expect.objectContaining({
103
+ guid: '22222222-2222-2222-2222-222222222222',
104
+ kind: OmniDocumentKind.Document,
105
+ recordType: OmniDocumentKind.Document,
106
+ documentKind: OmniDocumentKind.Note,
107
+ }),
108
+ expect.objectContaining({
109
+ guid: '44444444-4444-4444-4444-444444444444',
110
+ kind: OmniCollectionKind.Collection,
111
+ recordType: OmniCollectionKind.Collection,
112
+ collectionKind: OmniCollectionKind.Folder,
113
+ }),
114
+ ]),
115
+ );
116
+
117
+ const relation = await relationRepo.findOneOrFail({
118
+ where: { guid: '33333333-3333-3333-3333-333333333333' },
119
+ relations: {
120
+ sourceRecord: true,
121
+ targetRecord: true,
122
+ },
123
+ });
124
+
125
+ expect(relation.sourceRecord.guid).toBe(
126
+ '11111111-1111-1111-1111-111111111111',
127
+ );
128
+ expect(relation.targetRecord).toBeInstanceOf(OmniDocumentEntity);
129
+ expect(relation.targetRecord.guid).toBe(
130
+ '22222222-2222-2222-2222-222222222222',
131
+ );
132
+ expect((relation.targetRecord as OmniDocumentEntity).kind).toBe(
133
+ OmniDocumentKind.Document,
134
+ );
135
+
136
+ const membershipRelation = await relationRepo.findOneOrFail({
137
+ where: { guid: '55555555-5555-5555-5555-555555555555' },
138
+ relations: {
139
+ sourceRecord: true,
140
+ targetRecord: true,
141
+ },
142
+ });
143
+
144
+ expect(membershipRelation.sourceRecord).toBeInstanceOf(OmniCollectionEntity);
145
+ expect(membershipRelation.sourceRecord.guid).toBe(
146
+ '44444444-4444-4444-4444-444444444444',
147
+ );
148
+ expect((membershipRelation.sourceRecord as OmniCollectionEntity).kind).toBe(
149
+ OmniCollectionKind.Collection,
150
+ );
151
+ expect(membershipRelation.targetRecord).toBeInstanceOf(OmniDocumentEntity);
152
+ expect(membershipRelation.kind).toBe(OmniRelationKind.Contains);
153
+ });
154
+ });