jinaga-server 1.1.3 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -0
- package/dist/authentication/authentication-device.d.ts +3 -2
- package/dist/authentication/authentication-device.js +6 -0
- package/dist/authentication/authentication-device.js.map +1 -1
- package/dist/authentication/authentication-impl.d.ts +3 -2
- package/dist/authentication/authentication-impl.js +6 -0
- package/dist/authentication/authentication-impl.js.map +1 -1
- package/dist/authentication/authentication-noop.d.ts +20 -0
- package/dist/authentication/authentication-noop.js +52 -0
- package/dist/authentication/authentication-noop.js.map +1 -0
- package/dist/authentication/authentication-session.d.ts +3 -2
- package/dist/authentication/authentication-session.js +6 -0
- package/dist/authentication/authentication-session.js.map +1 -1
- package/dist/authentication.d.ts +3 -2
- package/dist/authentication.js +6 -0
- package/dist/authentication.js.map +1 -1
- package/dist/authorization/authorization-keystore.d.ts +3 -4
- package/dist/authorization/authorization-keystore.js +9 -4
- package/dist/authorization/authorization-keystore.js.map +1 -1
- package/dist/debug.d.ts +1 -0
- package/dist/debug.js +30 -0
- package/dist/debug.js.map +1 -0
- package/dist/http/router.js.map +1 -1
- package/dist/jinaga-server.js +15 -7
- package/dist/jinaga-server.js.map +1 -1
- package/dist/memory/memory-keystore.js +0 -6
- package/dist/memory/memory-keystore.js.map +1 -1
- package/dist/postgres/connection.js +1 -0
- package/dist/postgres/connection.js.map +1 -1
- package/dist/postgres/maps.d.ts +7 -6
- package/dist/postgres/maps.js +9 -1
- package/dist/postgres/maps.js.map +1 -1
- package/dist/postgres/postgres-keystore.js +0 -6
- package/dist/postgres/postgres-keystore.js.map +1 -1
- package/dist/postgres/postgres-store.d.ts +1 -2
- package/dist/postgres/postgres-store.js +29 -24
- package/dist/postgres/postgres-store.js.map +1 -1
- package/dist/postgres/specification-result-sql.d.ts +4 -5
- package/dist/postgres/specification-result-sql.js +139 -112
- package/dist/postgres/specification-result-sql.js.map +1 -1
- package/dist/postgres/specification-sql.js.map +1 -1
- package/dist/postgres/sql.d.ts +1 -1
- package/dist/postgres/sql.js +15 -7
- package/dist/postgres/sql.js.map +1 -1
- package/dist/util/maps.d.ts +0 -0
- package/dist/util/maps.js +2 -0
- package/dist/util/maps.js.map +1 -0
- package/docs/sql/SQL Generator (projection).png +0 -0
- package/docs/sql/SQLFromSpecification.md +396 -0
- package/docs/sql/example.sql +49 -0
- package/docs/sql/first-path.gv +9 -0
- package/docs/sql/first-path.png +0 -0
- package/docs/sql/model.gv +20 -0
- package/docs/sql/model.png +0 -0
- package/integration-test/jinaga-test/Dockerfile +2 -2
- package/integration-test/jinaga-test/jinaga.test.js +3 -3
- package/integration-test/jinaga-test/package-lock.json +745 -3484
- package/integration-test/jinaga-test/package.json +2 -0
- package/integration-test/run.sh +3 -3
- package/package.json +5 -6
- package/replicator/index.ts +31 -0
- package/replicator/package-lock.json +855 -0
- package/replicator/package.json +27 -0
- package/replicator/tsconfig.json +15 -0
- package/src/authentication/authentication-device.ts +11 -1
- package/src/authentication/authentication-impl.ts +9 -2
- package/src/authentication/authentication-noop.ts +65 -0
- package/src/authentication/authentication-session.ts +11 -1
- package/src/authentication.ts +12 -2
- package/src/authorization/authorization-keystore.ts +12 -7
- package/src/debug.ts +30 -0
- package/src/http/router.ts +2 -2
- package/src/jinaga-server.ts +18 -8
- package/src/memory/memory-keystore.ts +0 -6
- package/src/postgres/connection.ts +2 -1
- package/src/postgres/maps.ts +8 -0
- package/src/postgres/postgres-keystore.ts +2 -8
- package/src/postgres/postgres-store.ts +37 -30
- package/src/postgres/specification-result-sql.ts +200 -145
- package/src/postgres/specification-sql.ts +1 -1
- package/src/postgres/sql.ts +23 -12
- package/src/util/maps.ts +0 -0
- package/test/postgres/postgresReadSpec.ts +292 -0
- package/test/postgres/postgresSpec.ts +31 -31
- package/test/postgres/postgresSpecificationSpec.ts +1 -1
- package/tsconfig.json +1 -0
- package/tsconfig.test.json +26 -0
- package/docs/specification.txt +0 -41
- package/interactive/index.js +0 -56
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
Direction,
|
|
4
4
|
ExistentialCondition,
|
|
5
5
|
FactEnvelope,
|
|
6
|
+
FactFeed,
|
|
6
7
|
FactPath,
|
|
7
8
|
FactRecord,
|
|
8
9
|
FactReference,
|
|
@@ -20,9 +21,8 @@ import {
|
|
|
20
21
|
Specification,
|
|
21
22
|
Step,
|
|
22
23
|
Storage,
|
|
23
|
-
TopologicalSorter
|
|
24
|
+
TopologicalSorter
|
|
24
25
|
} from "jinaga";
|
|
25
|
-
import { FactFeed } from "jinaga/dist/storage";
|
|
26
26
|
import { PoolClient } from "pg";
|
|
27
27
|
|
|
28
28
|
import { distinct, flatten } from "../util/fn";
|
|
@@ -37,6 +37,7 @@ import {
|
|
|
37
37
|
emptyFactTypeMap,
|
|
38
38
|
emptyPublicKeyMap,
|
|
39
39
|
emptyRoleMap,
|
|
40
|
+
ensureGetFactTypeId,
|
|
40
41
|
FactMap,
|
|
41
42
|
FactTypeMap,
|
|
42
43
|
getFactId,
|
|
@@ -48,7 +49,7 @@ import {
|
|
|
48
49
|
mergeFactTypes,
|
|
49
50
|
mergeRoleMaps,
|
|
50
51
|
PublicKeyMap,
|
|
51
|
-
RoleMap
|
|
52
|
+
RoleMap
|
|
52
53
|
} from "./maps";
|
|
53
54
|
import { ResultSetTree, resultSqlFromSpecification, SqlQueryTree } from "./specification-result-sql";
|
|
54
55
|
import { sqlFromFeed } from "./specification-sql";
|
|
@@ -167,7 +168,7 @@ export class PostgresStore implements Storage {
|
|
|
167
168
|
} = await this.connectionFactory.withTransaction(async (connection) => {
|
|
168
169
|
const factTypes = await storeFactTypes(facts, this.factTypeMap, connection);
|
|
169
170
|
const existingFacts = await findExistingFacts(facts, factTypes, connection);
|
|
170
|
-
const newFacts = facts.filter(f => !hasFact(existingFacts, f.hash, factTypes
|
|
171
|
+
const newFacts = facts.filter(f => !hasFact(existingFacts, f.hash, ensureGetFactTypeId(factTypes, f.type)));
|
|
171
172
|
if (newFacts.length === 0) {
|
|
172
173
|
return {
|
|
173
174
|
newEnvelopes: [],
|
|
@@ -235,6 +236,11 @@ export class PostgresStore implements Storage {
|
|
|
235
236
|
const factTypes = await this.loadFactTypesFromSpecification(specification);
|
|
236
237
|
const roleMap = await this.loadRolesFromSpecification(specification, factTypes);
|
|
237
238
|
|
|
239
|
+
// If any of the start facts are not known types, the specification cannot be satisfied.
|
|
240
|
+
if (start.filter(f => getFactTypeId(factTypes, f.type) === undefined).length > 0) {
|
|
241
|
+
return [];
|
|
242
|
+
}
|
|
243
|
+
|
|
238
244
|
const composer = resultSqlFromSpecification(start, specification, factTypes, roleMap);
|
|
239
245
|
if (composer === null) {
|
|
240
246
|
return [];
|
|
@@ -317,7 +323,7 @@ export class PostgresStore implements Storage {
|
|
|
317
323
|
private async loadRolesFromSteps(steps: Step[], factTypes: FactTypeMap, initialType: string) {
|
|
318
324
|
const roleMap = this.roleMap;
|
|
319
325
|
const unknownRoles = allRoles(steps, factTypes, getFactTypeId(factTypes, initialType))
|
|
320
|
-
.filter(r => !hasRole(roleMap, r.
|
|
326
|
+
.filter(r => !hasRole(roleMap, r.successor_type_id, r.role));
|
|
321
327
|
if (unknownRoles.length > 0) {
|
|
322
328
|
const loadedRoles = await this.connectionFactory.with(async (connection) => {
|
|
323
329
|
return await loadRoles(unknownRoles, roleMap, connection);
|
|
@@ -332,11 +338,12 @@ export class PostgresStore implements Storage {
|
|
|
332
338
|
async loadRolesFromSpecification(specification: Specification, factTypes: FactTypeMap): Promise<RoleMap> {
|
|
333
339
|
const roleMap = this.roleMap;
|
|
334
340
|
const unknownRoles = getAllRoles(specification)
|
|
341
|
+
.filter(r => getFactTypeId(factTypes, r.successorType))
|
|
335
342
|
.map(r => ({
|
|
336
|
-
|
|
343
|
+
successor_type_id: ensureGetFactTypeId(factTypes, r.successorType),
|
|
337
344
|
role: r.name
|
|
338
345
|
}))
|
|
339
|
-
.filter(r => !hasRole(roleMap, r.
|
|
346
|
+
.filter(r => !hasRole(roleMap, r.successor_type_id, r.role));
|
|
340
347
|
if (unknownRoles.length > 0) {
|
|
341
348
|
const loadedRoles = await this.connectionFactory.with(async (connection) => {
|
|
342
349
|
return await loadRoles(unknownRoles, roleMap, connection);
|
|
@@ -352,10 +359,10 @@ export class PostgresStore implements Storage {
|
|
|
352
359
|
const roleMap = this.roleMap;
|
|
353
360
|
const unknownRoles = getAllRolesFromFeed(feed)
|
|
354
361
|
.map(r => ({
|
|
355
|
-
|
|
362
|
+
successor_type_id: ensureGetFactTypeId(factTypes, r.successorType),
|
|
356
363
|
role: r.name
|
|
357
364
|
}))
|
|
358
|
-
.filter(r => !hasRole(roleMap, r.
|
|
365
|
+
.filter(r => !hasRole(roleMap, r.successor_type_id, r.role));
|
|
359
366
|
if (unknownRoles.length > 0) {
|
|
360
367
|
const loadedRoles = await this.connectionFactory.with(async (connection) => {
|
|
361
368
|
return await loadRoles(unknownRoles, roleMap, connection);
|
|
@@ -535,21 +542,21 @@ async function loadFactTypes(factTypeNames: string[], connection: PoolClient) {
|
|
|
535
542
|
async function storeRoles(facts: FactRecord[], factTypes: FactTypeMap, roleMap: RoleMap, connection: PoolClient) {
|
|
536
543
|
// Find distinct roles
|
|
537
544
|
const roles = flatten(facts, fact => {
|
|
538
|
-
const
|
|
545
|
+
const successor_type_id = ensureGetFactTypeId(factTypes, fact.type);
|
|
539
546
|
return Object.keys(fact.predecessors).map(role => ({
|
|
540
547
|
role,
|
|
541
|
-
|
|
548
|
+
successor_type_id
|
|
542
549
|
}));
|
|
543
550
|
}).filter((role, index, array) => array.findIndex(r =>
|
|
544
551
|
r.role === role.role &&
|
|
545
|
-
r.
|
|
552
|
+
r.successor_type_id === role.successor_type_id
|
|
546
553
|
) === index);
|
|
547
554
|
|
|
548
555
|
if (roles.length > 0) {
|
|
549
556
|
// Look up existing roles
|
|
550
557
|
const roleIds = await loadRoles(roles, roleMap, connection);
|
|
551
558
|
const remainingRoles = roles.filter(role => !hasRole(
|
|
552
|
-
roleIds, role.
|
|
559
|
+
roleIds, role.successor_type_id, role.role));
|
|
553
560
|
if (remainingRoles.length === 0) {
|
|
554
561
|
return roleIds;
|
|
555
562
|
}
|
|
@@ -562,7 +569,7 @@ async function storeRoles(facts: FactRecord[], factTypes: FactTypeMap, roleMap:
|
|
|
562
569
|
' RETURNING role_id, name, defining_fact_type_id;';
|
|
563
570
|
const remainingRoleParameters = flatten(remainingRoles, (role) => [
|
|
564
571
|
role.role,
|
|
565
|
-
role.
|
|
572
|
+
role.successor_type_id
|
|
566
573
|
]);
|
|
567
574
|
const { rows: newRows }: RoleResult = await connection.query(insertSql, remainingRoleParameters);
|
|
568
575
|
if (newRows.length !== remainingRoles.length) {
|
|
@@ -579,12 +586,12 @@ async function storeRoles(facts: FactRecord[], factTypes: FactTypeMap, roleMap:
|
|
|
579
586
|
}
|
|
580
587
|
}
|
|
581
588
|
|
|
582
|
-
async function loadRoles(roles: { role: string;
|
|
589
|
+
async function loadRoles(roles: { role: string; successor_type_id: number; }[], roleMap: RoleMap, connection: PoolClient) {
|
|
583
590
|
const roleValues = roles.map((role, index) =>
|
|
584
591
|
`($${index * 2 + 1}, $${index * 2 + 2}::integer)`);
|
|
585
592
|
const roleParameters = flatten(roles, (role) => [
|
|
586
593
|
role.role,
|
|
587
|
-
role.
|
|
594
|
+
role.successor_type_id
|
|
588
595
|
]);
|
|
589
596
|
|
|
590
597
|
const lookUpSql = 'SELECT role.name, role.defining_fact_type_id, role.role_id' +
|
|
@@ -646,7 +653,7 @@ async function insertFactsEdgesAndAncestors(facts: FactRecord[], factTypes: Fact
|
|
|
646
653
|
|
|
647
654
|
function sqlInsertFacts(facts: FactRecord[], roles: RoleMap, factTypes: FactTypeMap) {
|
|
648
655
|
const factValues = facts.map((f, i) => `(\$${i * 3 + 1}, \$${i * 3 + 2}::integer, \$${i * 3 + 3}::jsonb)`);
|
|
649
|
-
const factParameters = flatten(facts, (f) => [f.hash, factTypes
|
|
656
|
+
const factParameters = flatten(facts, (f) => [f.hash, ensureGetFactTypeId(factTypes, f.type), {
|
|
650
657
|
fields: f.fields,
|
|
651
658
|
predecessors: canonicalPredecessors(f.predecessors)
|
|
652
659
|
}]);
|
|
@@ -669,8 +676,8 @@ function sqlInsertFactsEdgesAndAncestors(facts: FactRecord[], factParameters: (s
|
|
|
669
676
|
let parameterOffset = factParameters.length;
|
|
670
677
|
const edgeValues = edgeRecords.map((e, i) => `(\$${i * 5 + 1 + parameterOffset}, \$${i * 5 + 2 + parameterOffset}::integer, \$${i * 5 + 3 + parameterOffset}, \$${i * 5 + 4 + parameterOffset}::integer, \$${i * 5 + 5 + parameterOffset}::integer)`);
|
|
671
678
|
const edgeParameters = flatten(edgeRecords, (e) => {
|
|
672
|
-
const successor_fact_type_id =
|
|
673
|
-
const predecessor_fact_type_id =
|
|
679
|
+
const successor_fact_type_id = ensureGetFactTypeId(factTypes, e.successor_type);
|
|
680
|
+
const predecessor_fact_type_id = ensureGetFactTypeId(factTypes, e.predecessor_type);
|
|
674
681
|
return [
|
|
675
682
|
e.successor_hash,
|
|
676
683
|
successor_fact_type_id,
|
|
@@ -833,7 +840,7 @@ async function storePublicKeys(envelopes: FactEnvelope[], connection: PoolClient
|
|
|
833
840
|
|
|
834
841
|
async function insertSignatures(envelopes: FactEnvelope[], allFacts: FactMap, factTypes: FactTypeMap, publicKey: PublicKeyMap, connection: PoolClient) {
|
|
835
842
|
const signatureRecords = flatten(envelopes, envelope => envelope.signatures.map(signature => ({
|
|
836
|
-
factId: getFactId(allFacts, envelope.fact.hash,
|
|
843
|
+
factId: getFactId(allFacts, envelope.fact.hash, ensureGetFactTypeId(factTypes, envelope.fact.type)),
|
|
837
844
|
publicKeyId: getPublicKeyId(publicKey, signature.publicKey),
|
|
838
845
|
signature: signature.signature
|
|
839
846
|
})));
|
|
@@ -862,35 +869,35 @@ function allFactTypes(steps: Step[]): string[] {
|
|
|
862
869
|
return [...factTypes, ...childFactTypes].filter(distinct);
|
|
863
870
|
}
|
|
864
871
|
|
|
865
|
-
function allRoles(steps: Step[], factTypes: FactTypeMap, initialTypeId: number) {
|
|
866
|
-
let roles: {
|
|
867
|
-
let
|
|
872
|
+
function allRoles(steps: Step[], factTypes: FactTypeMap, initialTypeId: number | undefined) {
|
|
873
|
+
let roles: { successor_type_id: number; role: string }[] = [];
|
|
874
|
+
let successor_type_id = initialTypeId;
|
|
868
875
|
let role: string | undefined = undefined;
|
|
869
876
|
|
|
870
877
|
for (const step of steps) {
|
|
871
878
|
if (step instanceof PropertyCondition) {
|
|
872
879
|
if (step.name === 'type') {
|
|
873
|
-
|
|
874
|
-
if (
|
|
875
|
-
roles.push({
|
|
880
|
+
successor_type_id = getFactTypeId(factTypes, step.value);
|
|
881
|
+
if (successor_type_id && role) {
|
|
882
|
+
roles.push({ successor_type_id: successor_type_id, role });
|
|
876
883
|
}
|
|
877
884
|
role = undefined;
|
|
878
885
|
}
|
|
879
886
|
}
|
|
880
887
|
else if (step instanceof Join) {
|
|
881
888
|
if (step.direction === Direction.Predecessor) {
|
|
882
|
-
if (
|
|
883
|
-
roles.push({
|
|
889
|
+
if (successor_type_id) {
|
|
890
|
+
roles.push({ successor_type_id: successor_type_id, role: step.role });
|
|
884
891
|
}
|
|
885
892
|
role = undefined;
|
|
886
893
|
}
|
|
887
894
|
else {
|
|
888
895
|
role = step.role;
|
|
889
896
|
}
|
|
890
|
-
|
|
897
|
+
successor_type_id = undefined;
|
|
891
898
|
}
|
|
892
899
|
else if (step instanceof ExistentialCondition) {
|
|
893
|
-
roles = roles.concat(allRoles(step.steps, factTypes,
|
|
900
|
+
roles = roles.concat(allRoles(step.steps, factTypes, successor_type_id));
|
|
894
901
|
}
|
|
895
902
|
}
|
|
896
903
|
|