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.
Files changed (89) hide show
  1. package/README.md +12 -0
  2. package/dist/authentication/authentication-device.d.ts +3 -2
  3. package/dist/authentication/authentication-device.js +6 -0
  4. package/dist/authentication/authentication-device.js.map +1 -1
  5. package/dist/authentication/authentication-impl.d.ts +3 -2
  6. package/dist/authentication/authentication-impl.js +6 -0
  7. package/dist/authentication/authentication-impl.js.map +1 -1
  8. package/dist/authentication/authentication-noop.d.ts +20 -0
  9. package/dist/authentication/authentication-noop.js +52 -0
  10. package/dist/authentication/authentication-noop.js.map +1 -0
  11. package/dist/authentication/authentication-session.d.ts +3 -2
  12. package/dist/authentication/authentication-session.js +6 -0
  13. package/dist/authentication/authentication-session.js.map +1 -1
  14. package/dist/authentication.d.ts +3 -2
  15. package/dist/authentication.js +6 -0
  16. package/dist/authentication.js.map +1 -1
  17. package/dist/authorization/authorization-keystore.d.ts +3 -4
  18. package/dist/authorization/authorization-keystore.js +9 -4
  19. package/dist/authorization/authorization-keystore.js.map +1 -1
  20. package/dist/debug.d.ts +1 -0
  21. package/dist/debug.js +30 -0
  22. package/dist/debug.js.map +1 -0
  23. package/dist/http/router.js.map +1 -1
  24. package/dist/jinaga-server.js +15 -7
  25. package/dist/jinaga-server.js.map +1 -1
  26. package/dist/memory/memory-keystore.js +0 -6
  27. package/dist/memory/memory-keystore.js.map +1 -1
  28. package/dist/postgres/connection.js +1 -0
  29. package/dist/postgres/connection.js.map +1 -1
  30. package/dist/postgres/maps.d.ts +7 -6
  31. package/dist/postgres/maps.js +9 -1
  32. package/dist/postgres/maps.js.map +1 -1
  33. package/dist/postgres/postgres-keystore.js +0 -6
  34. package/dist/postgres/postgres-keystore.js.map +1 -1
  35. package/dist/postgres/postgres-store.d.ts +1 -2
  36. package/dist/postgres/postgres-store.js +29 -24
  37. package/dist/postgres/postgres-store.js.map +1 -1
  38. package/dist/postgres/specification-result-sql.d.ts +4 -5
  39. package/dist/postgres/specification-result-sql.js +139 -112
  40. package/dist/postgres/specification-result-sql.js.map +1 -1
  41. package/dist/postgres/specification-sql.js.map +1 -1
  42. package/dist/postgres/sql.d.ts +1 -1
  43. package/dist/postgres/sql.js +15 -7
  44. package/dist/postgres/sql.js.map +1 -1
  45. package/dist/util/maps.d.ts +0 -0
  46. package/dist/util/maps.js +2 -0
  47. package/dist/util/maps.js.map +1 -0
  48. package/docs/sql/SQL Generator (projection).png +0 -0
  49. package/docs/sql/SQLFromSpecification.md +396 -0
  50. package/docs/sql/example.sql +49 -0
  51. package/docs/sql/first-path.gv +9 -0
  52. package/docs/sql/first-path.png +0 -0
  53. package/docs/sql/model.gv +20 -0
  54. package/docs/sql/model.png +0 -0
  55. package/integration-test/jinaga-test/Dockerfile +2 -2
  56. package/integration-test/jinaga-test/jinaga.test.js +3 -3
  57. package/integration-test/jinaga-test/package-lock.json +745 -3484
  58. package/integration-test/jinaga-test/package.json +2 -0
  59. package/integration-test/run.sh +3 -3
  60. package/package.json +5 -6
  61. package/replicator/index.ts +31 -0
  62. package/replicator/package-lock.json +855 -0
  63. package/replicator/package.json +27 -0
  64. package/replicator/tsconfig.json +15 -0
  65. package/src/authentication/authentication-device.ts +11 -1
  66. package/src/authentication/authentication-impl.ts +9 -2
  67. package/src/authentication/authentication-noop.ts +65 -0
  68. package/src/authentication/authentication-session.ts +11 -1
  69. package/src/authentication.ts +12 -2
  70. package/src/authorization/authorization-keystore.ts +12 -7
  71. package/src/debug.ts +30 -0
  72. package/src/http/router.ts +2 -2
  73. package/src/jinaga-server.ts +18 -8
  74. package/src/memory/memory-keystore.ts +0 -6
  75. package/src/postgres/connection.ts +2 -1
  76. package/src/postgres/maps.ts +8 -0
  77. package/src/postgres/postgres-keystore.ts +2 -8
  78. package/src/postgres/postgres-store.ts +37 -30
  79. package/src/postgres/specification-result-sql.ts +200 -145
  80. package/src/postgres/specification-sql.ts +1 -1
  81. package/src/postgres/sql.ts +23 -12
  82. package/src/util/maps.ts +0 -0
  83. package/test/postgres/postgresReadSpec.ts +292 -0
  84. package/test/postgres/postgresSpec.ts +31 -31
  85. package/test/postgres/postgresSpecificationSpec.ts +1 -1
  86. package/tsconfig.json +1 -0
  87. package/tsconfig.test.json +26 -0
  88. package/docs/specification.txt +0 -41
  89. 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.get(f.type)));
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.defining_fact_type_id, r.role));
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
- defining_fact_type_id: getFactTypeId(factTypes, r.definingFactType),
343
+ successor_type_id: ensureGetFactTypeId(factTypes, r.successorType),
337
344
  role: r.name
338
345
  }))
339
- .filter(r => !hasRole(roleMap, r.defining_fact_type_id, r.role));
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
- defining_fact_type_id: getFactTypeId(factTypes, r.definingFactType),
362
+ successor_type_id: ensureGetFactTypeId(factTypes, r.successorType),
356
363
  role: r.name
357
364
  }))
358
- .filter(r => !hasRole(roleMap, r.defining_fact_type_id, r.role));
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 defining_fact_type_id = factTypes.get(fact.type);
545
+ const successor_type_id = ensureGetFactTypeId(factTypes, fact.type);
539
546
  return Object.keys(fact.predecessors).map(role => ({
540
547
  role,
541
- defining_fact_type_id
548
+ successor_type_id
542
549
  }));
543
550
  }).filter((role, index, array) => array.findIndex(r =>
544
551
  r.role === role.role &&
545
- r.defining_fact_type_id === role.defining_fact_type_id
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.defining_fact_type_id, role.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.defining_fact_type_id
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; defining_fact_type_id: number; }[], roleMap: RoleMap, connection: PoolClient) {
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.defining_fact_type_id
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.get(f.type), {
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 = getFactTypeId(factTypes, e.successor_type);
673
- const predecessor_fact_type_id = getFactTypeId(factTypes, e.predecessor_type);
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, getFactTypeId(factTypes, envelope.fact.type)),
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: { defining_fact_type_id: number; role: string }[] = [];
867
- let defining_fact_type_id = initialTypeId;
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
- defining_fact_type_id = getFactTypeId(factTypes, step.value);
874
- if (defining_fact_type_id && role) {
875
- roles.push({ defining_fact_type_id, role });
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 (defining_fact_type_id) {
883
- roles.push({ defining_fact_type_id, role: step.role });
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
- defining_fact_type_id = undefined;
897
+ successor_type_id = undefined;
891
898
  }
892
899
  else if (step instanceof ExistentialCondition) {
893
- roles = roles.concat(allRoles(step.steps, factTypes, defining_fact_type_id));
900
+ roles = roles.concat(allRoles(step.steps, factTypes, successor_type_id));
894
901
  }
895
902
  }
896
903