jinaga-server 2.4.2 → 2.6.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 (62) hide show
  1. package/dist/authorization/authorization-keystore.d.ts +5 -4
  2. package/dist/authorization/authorization-keystore.js +16 -13
  3. package/dist/authorization/authorization-keystore.js.map +1 -1
  4. package/dist/http/router.d.ts +5 -3
  5. package/dist/http/router.js +125 -52
  6. package/dist/http/router.js.map +1 -1
  7. package/dist/http/stream.d.ts +10 -0
  8. package/dist/http/stream.js +35 -0
  9. package/dist/http/stream.js.map +1 -0
  10. package/dist/index.d.ts +2 -3
  11. package/dist/index.js +3 -3
  12. package/dist/index.js.map +1 -1
  13. package/dist/jinaga-server.js +7 -8
  14. package/dist/jinaga-server.js.map +1 -1
  15. package/dist/postgres/connection.js +1 -3
  16. package/dist/postgres/connection.js.map +1 -1
  17. package/dist/postgres/postgres-store.d.ts +4 -4
  18. package/dist/postgres/postgres-store.js +2 -2
  19. package/dist/postgres/postgres-store.js.map +1 -1
  20. package/dist/postgres/query-description.d.ts +75 -0
  21. package/dist/postgres/query-description.js +283 -0
  22. package/dist/postgres/query-description.js.map +1 -0
  23. package/dist/postgres/specification-result-sql.d.ts +2 -2
  24. package/dist/postgres/specification-result-sql.js +39 -324
  25. package/dist/postgres/specification-result-sql.js.map +1 -1
  26. package/dist/postgres/specification-sql.d.ts +2 -2
  27. package/dist/postgres/specification-sql.js +60 -163
  28. package/dist/postgres/specification-sql.js.map +1 -1
  29. package/http/sans-auth/.env.local +1 -0
  30. package/http/sans-auth/Create post sans auth.http +27 -0
  31. package/http/sans-auth/Create site sans auth.http +11 -0
  32. package/http/sans-auth/Feed sites.http +1 -0
  33. package/http/sans-auth/Feeds sites.http +12 -0
  34. package/http/sans-auth/Get posts sans auth.http +35 -0
  35. package/http/sans-auth/Get sites sans auth.http +12 -0
  36. package/http/sans-auth/stream.sh +2 -0
  37. package/integration-test/jinaga-test/Dockerfile +1 -1
  38. package/integration-test/jinaga-test/package-lock.json +917 -748
  39. package/integration-test/jinaga-test/package.json +3 -3
  40. package/package.json +2 -2
  41. package/replicator/package-lock.json +16 -16
  42. package/replicator/package.json +1 -1
  43. package/src/authorization/authorization-keystore.ts +23 -14
  44. package/src/http/router.ts +154 -64
  45. package/src/http/stream.ts +32 -0
  46. package/src/index.ts +3 -4
  47. package/src/jinaga-server.ts +8 -8
  48. package/src/postgres/connection.ts +1 -3
  49. package/src/postgres/postgres-store.ts +5 -8
  50. package/src/postgres/query-description.ts +435 -0
  51. package/src/postgres/specification-result-sql.ts +56 -489
  52. package/src/postgres/specification-sql.ts +71 -232
  53. package/test/authorization/authorizationSpec.ts +12 -2
  54. package/test/postgres/postgresSpecificationSpec.ts +15 -15
  55. package/dist/http/feed-cache.d.ts +0 -12
  56. package/dist/http/feed-cache.js +0 -3
  57. package/dist/http/feed-cache.js.map +0 -1
  58. package/dist/memory/memory-feed-cache.d.ts +0 -6
  59. package/dist/memory/memory-feed-cache.js +0 -17
  60. package/dist/memory/memory-feed-cache.js.map +0 -1
  61. package/src/http/feed-cache.ts +0 -14
  62. package/src/memory/memory-feed-cache.ts +0 -14
@@ -1,15 +1,11 @@
1
1
  import {
2
2
  buildFeeds,
3
- EdgeDescription as FeedEdgeDescription,
4
3
  FactReference,
5
- Feed,
6
- InputDescription as FeedInputDescription,
7
- NotExistsConditionDescription as FeedNotExistsConditionDescription,
8
- OutputDescription as FeedOutputDescription,
9
4
  Specification,
5
+ validateGiven
10
6
  } from "jinaga";
11
7
 
12
- import { FactTypeMap, getFactTypeId, getRoleId, RoleMap } from "./maps";
8
+ import { EdgeDescription, ExistentialConditionDescription, QueryDescription, QueryDescriptionBuider } from "./query-description";
13
9
 
14
10
  interface SpecificationLabel {
15
11
  type: string;
@@ -23,67 +19,40 @@ interface SpecificationSqlQuery {
23
19
  bookmark: string;
24
20
  };
25
21
 
26
- interface InputDescription {
27
- factIndex: number;
28
- factTypeParameter: number;
29
- factHashParameter: number;
30
- }
31
- interface OutputDescription {
32
- type: string;
33
- factIndex: number;
34
- }
35
- interface EdgeDescription {
36
- edgeIndex: number;
37
- predecessorFactIndex: number;
38
- successorFactIndex: number;
39
- roleParameter: number;
40
- }
41
- interface NotExistsConditionDescription {
42
- edges: EdgeDescription[];
43
- }
44
- class QueryDescription {
45
- constructor(
46
- private readonly inputs: InputDescription[],
47
- private readonly parameters: (string | number)[],
48
- private readonly outputs: OutputDescription[],
49
- private readonly edges: EdgeDescription[],
50
- private readonly notExistsConditions: NotExistsConditionDescription[] = []
51
- ) {}
52
-
53
- generateSqlQuery(schema: string, bookmark: string, limit: number): SpecificationSqlQuery {
54
- const hashes = this.outputs
55
- .map(output => `f${output.factIndex}.hash as hash${output.factIndex}`)
56
- .join(", ");
57
- const factIds = this.outputs
58
- .map(output => `f${output.factIndex}.fact_id`)
59
- .join(", ");
60
- const firstEdge = this.edges[0];
61
- const predecessorFact = this.inputs.find(i => i.factIndex === firstEdge.predecessorFactIndex);
62
- const successorFact = this.inputs.find(i => i.factIndex === firstEdge.successorFactIndex);
63
- const firstFactIndex = predecessorFact ? predecessorFact.factIndex : successorFact!.factIndex;
64
- const writtenFactIndexes = new Set<number>().add(firstFactIndex);
65
- const joins: string[] = generateJoins(schema, this.edges, writtenFactIndexes);
66
- const inputWhereClauses = this.inputs
67
- .filter(input => input.factTypeParameter !== 0)
68
- .map(input => `f${input.factIndex}.fact_type_id = $${input.factTypeParameter} AND f${input.factIndex}.hash = $${input.factHashParameter}`)
69
- .join(" AND ");
70
- const notExistsWhereClauses = this.notExistsConditions
71
- .map(notExistsWhereClause => ` AND NOT EXISTS (${generateNotExistsWhereClause(schema, notExistsWhereClause, writtenFactIndexes)})`)
72
- .join("");
73
- const bookmarkParameter = this.parameters.length + 1;
74
- const limitParameter = bookmarkParameter + 1;
75
- const sql = `SELECT ${hashes}, sort(array[${factIds}], 'desc') as bookmark FROM ${schema}.fact f${firstFactIndex}${joins.join("")} WHERE ${inputWhereClauses}${notExistsWhereClauses} AND sort(array[${factIds}], 'desc') > $${bookmarkParameter} ORDER BY bookmark ASC LIMIT $${limitParameter}`;
76
- const bookmarkValue: number[] = parseBookmark(bookmark);
77
- return {
78
- sql,
79
- parameters: [...this.parameters, bookmarkValue, limit],
80
- labels: this.outputs.map(output => ({
81
- type: output.type,
82
- index: output.factIndex
83
- })),
84
- bookmark: "[]"
85
- };
86
- }
22
+ function generateSqlQuery(queryDescription: QueryDescription, schema: string, bookmark: string, limit: number): SpecificationSqlQuery {
23
+ const hashes = queryDescription.outputs
24
+ .map(output => `f${output.factIndex}.hash as hash${output.factIndex}`)
25
+ .join(", ");
26
+ const factIds = queryDescription.outputs
27
+ .map(output => `f${output.factIndex}.fact_id`)
28
+ .join(", ");
29
+ const firstEdge = queryDescription.edges[0];
30
+ const predecessorFact = queryDescription.inputs.find(i => i.factIndex === firstEdge.predecessorFactIndex);
31
+ const successorFact = queryDescription.inputs.find(i => i.factIndex === firstEdge.successorFactIndex);
32
+ const firstFactIndex = predecessorFact ? predecessorFact.factIndex : successorFact!.factIndex;
33
+ const writtenFactIndexes = new Set<number>().add(firstFactIndex);
34
+ const joins: string[] = generateJoins(schema, queryDescription.edges, writtenFactIndexes);
35
+ const inputWhereClauses = queryDescription.inputs
36
+ .filter(input => input.factTypeParameter !== 0)
37
+ .map(input => `f${input.factIndex}.fact_type_id = $${input.factTypeParameter} AND f${input.factIndex}.hash = $${input.factHashParameter}`)
38
+ .join(" AND ");
39
+ const notExistsWhereClauses = (queryDescription.existentialConditions
40
+ .filter(c => c.exists === false))
41
+ .map(notExistsWhereClause => ` AND NOT EXISTS (${generateNotExistsWhereClause(schema, notExistsWhereClause, writtenFactIndexes)})`)
42
+ .join("");
43
+ const bookmarkParameter = queryDescription.parameters.length + 1;
44
+ const limitParameter = bookmarkParameter + 1;
45
+ const sql = `SELECT ${hashes}, sort(array[${factIds}], 'desc') as bookmark FROM ${schema}.fact f${firstFactIndex}${joins.join("")} WHERE ${inputWhereClauses}${notExistsWhereClauses} AND sort(array[${factIds}], 'desc') > $${bookmarkParameter} ORDER BY bookmark ASC LIMIT $${limitParameter}`;
46
+ const bookmarkValue: number[] = parseBookmark(bookmark);
47
+ return {
48
+ sql,
49
+ parameters: [...queryDescription.parameters, bookmarkValue, limit],
50
+ labels: queryDescription.outputs.map(output => ({
51
+ type: output.type,
52
+ index: output.factIndex
53
+ })),
54
+ bookmark: "[]"
55
+ };
87
56
  }
88
57
 
89
58
  function generateJoins(schema: string, edges: EdgeDescription[], writtenFactIndexes: Set<number>) {
@@ -130,7 +99,7 @@ function generateJoins(schema: string, edges: EdgeDescription[], writtenFactInde
130
99
  return joins;
131
100
  }
132
101
 
133
- function generateNotExistsWhereClause(schema: string, notExistsWhereClause: NotExistsConditionDescription, outerFactIndexes: Set<number>): string {
102
+ function generateNotExistsWhereClause(schema: string, notExistsWhereClause: ExistentialConditionDescription, outerFactIndexes: Set<number>): string {
134
103
  const firstEdge = notExistsWhereClause.edges[0];
135
104
  const writtenFactIndexes = new Set<number>(outerFactIndexes);
136
105
  const firstJoin: string[] = [];
@@ -192,182 +161,52 @@ function parseBookmark(bookmark: string): number[] {
192
161
  }
193
162
  }
194
163
 
195
- class DescriptionBuilder {
196
- constructor(
197
- private factTypes: FactTypeMap,
198
- private roleMap: RoleMap
199
- ) { }
200
-
201
- isSatisfiable(feed: Feed, edges: FeedEdgeDescription[]): boolean {
202
- for (const edge of edges) {
203
- const successor = feed.facts.find(f => f.factIndex === edge.successorFactIndex);
204
- if (!successor) {
205
- return false;
206
- }
207
-
208
- const predecessor = feed.facts.find(f => f.factIndex === edge.predecessorFactIndex);
209
- if (!predecessor) {
210
- return false;
211
- }
212
-
213
- const successorFactTypeId = getFactTypeId(this.factTypes, successor.factType);
214
- if (!successorFactTypeId) {
215
- return false;
216
- }
217
-
218
- if (!getRoleId(this.roleMap, successorFactTypeId, edge.roleName)) {
219
- return false;
220
- }
221
-
222
- const predecessorFactTypeId = getFactTypeId(this.factTypes, predecessor.factType);
223
- if (!predecessorFactTypeId) {
224
- return false;
225
- }
226
- }
227
-
228
- return true;
229
- }
230
-
231
- buildDescription(feed: Feed, start: FactReference[]): QueryDescription {
232
- const parameters: (string | number)[] = [];
233
- function addParameter(value: string | number) {
234
- parameters.push(value);
235
- return parameters.length;
236
- }
237
-
238
- // Allocate parameters for the inputs.
239
- const inputs: InputDescription[] = feed.inputs.map(input =>
240
- this.buildInputDescription(feed, input, start, addParameter)
241
- );
242
-
243
- // Allocate parameters for the edge roles.
244
- const edges: EdgeDescription[] = feed.edges.map(edge =>
245
- this.buildEdgeDescription(feed, edge, addParameter)
246
- );
247
-
248
- // Allocate parameters for the conditional roles.
249
- const satisfiableNotExistsConditions = feed.notExistsConditions.filter(condition =>
250
- this.isSatisfiable(feed, condition.edges)
251
- );
252
- const notExistsConditions: NotExistsConditionDescription[] = satisfiableNotExistsConditions.map(condition =>
253
- this.buildNotExistsConditionDescription(feed, condition, addParameter)
254
- );
255
-
256
- const outputs: OutputDescription[] = feed.outputs.map(output =>
257
- this.buildOutputDescription(feed, output)
258
- );
259
-
260
- return new QueryDescription(
261
- inputs,
262
- parameters,
263
- outputs,
264
- edges,
265
- notExistsConditions
266
- );
267
- }
268
-
269
- private buildInputDescription(feed: Feed, input: FeedInputDescription, start: FactReference[], addParameter: (value: string | number) => number): InputDescription {
270
- const fact = feed.facts.find(f => f.factIndex === input.factIndex);
271
- if (!fact) {
272
- throw new Error(`Fact not found: ${input.factIndex}`);
273
- }
274
-
275
- const factTypeId = getFactTypeId(this.factTypes, fact.factType);
276
- if (!factTypeId) {
277
- throw new Error(`Fact type not found: ${fact.factType}`);
278
- }
279
-
280
- const factTypeParameter = addParameter(factTypeId);
281
- const factHashParameter = addParameter(start[input.inputIndex].hash);
282
- return {
283
- factIndex: input.factIndex,
284
- factTypeParameter,
285
- factHashParameter
286
- };
287
- }
288
-
289
- private buildEdgeDescription(feed: Feed, edge: FeedEdgeDescription, addParameter: (value: string | number) => number) {
290
- const fact = feed.facts.find(f => f.factIndex === edge.successorFactIndex);
291
- if (!fact) {
292
- throw new Error(`Fact not found: ${edge.successorFactIndex}`);
293
- }
294
-
295
- const factTypeId = getFactTypeId(this.factTypes, fact.factType);
296
- if (!factTypeId) {
297
- throw new Error(`Fact type not found: ${fact.factType}`);
298
- }
299
-
300
- const roleId = getRoleId(this.roleMap, factTypeId, edge.roleName);
301
- if (!roleId) {
302
- throw new Error(`Role not found: ${fact.factType}.${edge.roleName}`);
303
- }
304
-
305
- const roleParameter = addParameter(roleId);
306
- return <EdgeDescription>{
307
- edgeIndex: edge.edgeIndex,
308
- predecessorFactIndex: edge.predecessorFactIndex,
309
- successorFactIndex: edge.successorFactIndex,
310
- roleParameter
311
- };
312
- }
313
-
314
- private buildOutputDescription(feed: Feed, output: FeedOutputDescription) {
315
- const fact = feed.facts.find(f => f.factIndex === output.factIndex);
316
- if (!fact) {
317
- throw new Error(`Fact not found: ${output.factIndex}`);
318
- }
319
-
320
- return <OutputDescription>{
321
- factIndex: output.factIndex,
322
- type: fact.factType
323
- };
324
- }
325
-
326
- private buildNotExistsConditionDescription(feed: Feed, condition: FeedNotExistsConditionDescription, addParameter: (value: string | number) => number): NotExistsConditionDescription {
327
- const edges = condition.edges.map(edge =>
328
- this.buildEdgeDescription(feed, edge, addParameter)
329
- );
330
-
331
- return {
332
- edges
333
- }
334
- }
335
- }
336
-
337
164
  export function sqlFromSpecification(start: FactReference[], schema: string, bookmarks: string[], limit: number, specification: Specification, factTypes: Map<string, number>, roleMap: Map<number, Map<string, number>>): SpecificationSqlQuery[] {
338
- // Verify that the number of start facts equals the number of inputs
339
- if (start.length !== specification.given.length) {
340
- throw new Error(`The number of start facts (${start.length}) does not equal the number of inputs (${specification.given.length})`);
341
- }
342
- // Verify that the input type matches the start fact type
343
- for (let i = 0; i < start.length; i++) {
344
- if (start[i].type !== specification.given[i].type) {
345
- throw new Error(`The type of start fact ${i} (${start[i].type}) does not match the type of input ${i} (${specification.given[i].type})`);
346
- }
347
- }
165
+ validateGiven(start, specification);
166
+
167
+ const labeledStart = start.map((s, index) => ({
168
+ name: specification.given[index].name,
169
+ reference: s
170
+ })).reduce((map, s) => {
171
+ map.set(s.name, s.reference);
172
+ return map;
173
+ }, new Map<string, FactReference>());
348
174
 
349
175
  const feeds = buildFeeds(specification);
350
- const descriptionBuilder = new DescriptionBuilder(factTypes, roleMap);
176
+ const queryDescriptionBuilder = new QueryDescriptionBuider(factTypes, roleMap);
351
177
  const feedAndBookmark = feeds.map((feed, index) => ({
352
178
  feed,
353
179
  bookmark: bookmarks[index]
354
180
  }));
355
- const satisfiableFeedsAndBookmarks = feedAndBookmark.filter(fb =>
356
- descriptionBuilder.isSatisfiable(fb.feed, fb.feed.edges));
357
- const sqlQueries = satisfiableFeedsAndBookmarks.map(fb => {
358
- const description = descriptionBuilder.buildDescription(fb.feed, start);
359
- const sql = description.generateSqlQuery(schema, fb.bookmark, limit);
360
- return sql;
181
+ const queryDescriptionsAndBookmarks = feedAndBookmark.map(fb => {
182
+ const feedStart = fb.feed.given.map(s => labeledStart.get(s.name)!);
183
+ return {
184
+ queryDescription: buildQueryDescription(queryDescriptionBuilder, fb.feed, feedStart),
185
+ bookmark: fb.bookmark
186
+ };
361
187
  });
188
+ const satisfiableQueryDescriptionsAndBookmarks = queryDescriptionsAndBookmarks.filter(qb =>
189
+ qb.queryDescription.isSatisfiable());
190
+ const sqlQueries = satisfiableQueryDescriptionsAndBookmarks.map(qdb =>
191
+ generateSqlQuery(qdb.queryDescription, schema, qdb.bookmark, limit));
362
192
  return sqlQueries;
363
193
  }
364
194
 
365
- export function sqlFromFeed(feed: Feed, start: FactReference[], schema: string, bookmark: string, limit: number, factTypes: Map<string, number>, roleMap: Map<number, Map<string, number>>): SpecificationSqlQuery | null {
366
- const descriptionBuilder = new DescriptionBuilder(factTypes, roleMap);
367
- if (!descriptionBuilder.isSatisfiable(feed, feed.edges)) {
195
+ export function sqlFromFeed(feed: Specification, start: FactReference[], schema: string, bookmark: string, limit: number, factTypes: Map<string, number>, roleMap: Map<number, Map<string, number>>): SpecificationSqlQuery | null {
196
+ const queryDescriptionBuilder = new QueryDescriptionBuider(factTypes, roleMap);
197
+ const queryDescription = buildQueryDescription(queryDescriptionBuilder, feed, start);
198
+ if (!queryDescription.isSatisfiable()) {
368
199
  return null;
369
200
  }
370
- const description = descriptionBuilder.buildDescription(feed, start);
371
- const sql = description.generateSqlQuery(schema, bookmark, limit);
201
+ const sql = generateSqlQuery(queryDescription, schema, bookmark, limit);
372
202
  return sql;
373
203
  }
204
+
205
+ function buildQueryDescription(queryDescriptionBuilder: QueryDescriptionBuider, specification: Specification, start: FactReference[]): QueryDescription {
206
+ const { queryDescription } = queryDescriptionBuilder.addEdges(
207
+ QueryDescription.unsatisfiable,
208
+ specification.given,
209
+ start, {}, [],
210
+ specification.matches);
211
+ return queryDescription;
212
+ }
@@ -1,11 +1,16 @@
1
1
  import {
2
+ AuthenticationNoOp,
2
3
  AuthorizationRules,
3
4
  dehydrateFact,
4
5
  ensure,
6
+ FactManager,
5
7
  FactRecord,
6
8
  hydrate,
7
9
  Jinaga as j,
8
- MemoryStore
10
+ MemoryStore,
11
+ NetworkNoOp,
12
+ ObservableSource,
13
+ PassThroughFork
9
14
  } from "jinaga";
10
15
 
11
16
  import { AuthorizationKeystore } from "../../src/authorization/authorization-keystore";
@@ -160,6 +165,11 @@ function givenStorage() {
160
165
  function givenAuthorizationWithStorage(storage: MemoryStore) {
161
166
  const keystore = new MemoryKeystore();
162
167
  keystore.getOrCreateUserFact(givenMockUserIdentity());
168
+ const authentication = new AuthenticationNoOp();
169
+ const fork = new PassThroughFork(storage);
170
+ const observableSource = new ObservableSource(storage);
171
+ const network = new NetworkNoOp();
172
+ const factManager = new FactManager(authentication, fork, observableSource, storage, network);
163
173
  const authorizationRules = new AuthorizationRules(undefined)
164
174
  .any('Hashtag')
165
175
  .no('Jinaga.User')
@@ -167,7 +177,7 @@ function givenAuthorizationWithStorage(storage: MemoryStore) {
167
177
  .type('Like', j.for(likeUser))
168
178
  .type('Delete', j.for(deleteSender))
169
179
  ;
170
- return new AuthorizationKeystore(storage, keystore, authorizationRules, null);
180
+ return new AuthorizationKeystore(factManager, storage, keystore, authorizationRules, null);
171
181
  }
172
182
 
173
183
  function givenOtherUser() {
@@ -291,14 +291,14 @@ describe("Postgres query generator", () => {
291
291
  'f3.hash as hash3, ' +
292
292
  'sort(array[f2.fact_id, f3.fact_id], \'desc\') as bookmark ' +
293
293
  'FROM public.fact f1 ' +
294
- 'JOIN public.edge e1 ON e1.predecessor_fact_id = f1.fact_id AND e1.role_id = $5 ' +
294
+ 'JOIN public.edge e1 ON e1.predecessor_fact_id = f1.fact_id AND e1.role_id = $3 ' +
295
295
  'JOIN public.fact f2 ON f2.fact_id = e1.successor_fact_id ' +
296
- 'JOIN public.edge e2 ON e2.predecessor_fact_id = f2.fact_id AND e2.role_id = $6 ' +
296
+ 'JOIN public.edge e2 ON e2.predecessor_fact_id = f2.fact_id AND e2.role_id = $4 ' +
297
297
  'JOIN public.fact f3 ON f3.fact_id = e2.successor_fact_id ' +
298
298
  'JOIN public.edge e3 ON e3.successor_fact_id = f3.fact_id AND e3.role_id = $7 ' +
299
299
  'JOIN public.fact f4 ON f4.fact_id = e3.predecessor_fact_id ' +
300
300
  'WHERE f1.fact_type_id = $1 AND f1.hash = $2 ' +
301
- 'AND f4.fact_type_id = $3 AND f4.hash = $4 ' +
301
+ 'AND f4.fact_type_id = $5 AND f4.hash = $6 ' +
302
302
  'AND sort(array[f2.fact_id, f3.fact_id], \'desc\') > $8 ' +
303
303
  'ORDER BY bookmark ASC ' +
304
304
  'LIMIT $9'
@@ -306,10 +306,10 @@ describe("Postgres query generator", () => {
306
306
  expect(sqlQueries[0].parameters).toEqual([
307
307
  getFactTypeId(factTypes, "Root"),
308
308
  rootHash,
309
- getFactTypeId(factTypes, "Jinaga.User"),
310
- userHash,
311
309
  roleParameter(roleMap, factTypes, "MyApplication.Project", "root"),
312
310
  roleParameter(roleMap, factTypes, "MyApplication.Assignment", "project"),
311
+ getFactTypeId(factTypes, "Jinaga.User"),
312
+ userHash,
313
313
  roleParameter(roleMap, factTypes, "MyApplication.Assignment", "user"),
314
314
  [],
315
315
  100
@@ -344,15 +344,15 @@ describe("Postgres query generator", () => {
344
344
  'SELECT f2.hash as hash2, ' +
345
345
  'f3.hash as hash3, ' +
346
346
  'sort(array[f2.fact_id, f3.fact_id], \'desc\') as bookmark ' +
347
- 'FROM public.fact f1 ' +
348
- 'JOIN public.edge e1 ON e1.predecessor_fact_id = f1.fact_id AND e1.role_id = $5 ' +
349
- 'JOIN public.fact f2 ON f2.fact_id = e1.successor_fact_id ' +
350
- 'JOIN public.edge e2 ON e2.predecessor_fact_id = f2.fact_id AND e2.role_id = $6 ' +
351
- 'JOIN public.fact f3 ON f3.fact_id = e2.successor_fact_id ' +
352
- 'JOIN public.edge e3 ON e3.successor_fact_id = f3.fact_id AND e3.role_id = $7 ' +
353
- 'JOIN public.fact f4 ON f4.fact_id = e3.predecessor_fact_id ' +
347
+ 'FROM public.fact f1 ' + // root
348
+ 'JOIN public.edge e1 ON e1.predecessor_fact_id = f1.fact_id AND e1.role_id = $3 ' + // project->root
349
+ 'JOIN public.fact f2 ON f2.fact_id = e1.successor_fact_id ' + // project
350
+ 'JOIN public.edge e2 ON e2.predecessor_fact_id = f2.fact_id AND e2.role_id = $4 ' + // assignment->project
351
+ 'JOIN public.fact f3 ON f3.fact_id = e2.successor_fact_id ' + // assignment
352
+ 'JOIN public.edge e3 ON e3.successor_fact_id = f3.fact_id AND e3.role_id = $7 ' + // assignment->user
353
+ 'JOIN public.fact f4 ON f4.fact_id = e3.predecessor_fact_id ' + // user
354
354
  'WHERE f1.fact_type_id = $1 AND f1.hash = $2 ' +
355
- 'AND f4.fact_type_id = $3 AND f4.hash = $4 ' +
355
+ 'AND f4.fact_type_id = $5 AND f4.hash = $6 ' +
356
356
  'AND sort(array[f2.fact_id, f3.fact_id], \'desc\') > $8 ' +
357
357
  'ORDER BY bookmark ASC ' +
358
358
  'LIMIT $9'
@@ -360,10 +360,10 @@ describe("Postgres query generator", () => {
360
360
  expect(sqlQueries[0].parameters).toEqual([
361
361
  getFactTypeId(factTypes, "Root"),
362
362
  rootHash,
363
- getFactTypeId(factTypes, "Jinaga.User"),
364
- userHash,
365
363
  roleParameter(roleMap, factTypes, "MyApplication.Project", "root"),
366
364
  roleParameter(roleMap, factTypes, "MyApplication.Assignment", "project"),
365
+ getFactTypeId(factTypes, "Jinaga.User"),
366
+ userHash,
367
367
  roleParameter(roleMap, factTypes, "MyApplication.Assignment", "user"),
368
368
  [],
369
369
  100
@@ -1,12 +0,0 @@
1
- import { FactReference, Feed } from "jinaga";
2
- export interface FeedDefinition {
3
- start: {
4
- factReference: FactReference;
5
- index: number;
6
- }[];
7
- feed: Feed;
8
- }
9
- export interface FeedCache {
10
- storeFeed(feedHash: string, feedDefinition: FeedDefinition): Promise<void>;
11
- getFeed(feedHash: string): Promise<FeedDefinition | undefined>;
12
- }
@@ -1,3 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- //# sourceMappingURL=feed-cache.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"feed-cache.js","sourceRoot":"","sources":["../../src/http/feed-cache.ts"],"names":[],"mappings":""}
@@ -1,6 +0,0 @@
1
- import { FeedCache, FeedDefinition } from "../http/feed-cache";
2
- export declare class MemoryFeedCache implements FeedCache {
3
- private feedDefinitions;
4
- storeFeed(feedHash: string, feedDefinition: FeedDefinition): Promise<void>;
5
- getFeed(feedHash: string): Promise<FeedDefinition | undefined>;
6
- }
@@ -1,17 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MemoryFeedCache = void 0;
4
- class MemoryFeedCache {
5
- constructor() {
6
- this.feedDefinitions = {};
7
- }
8
- storeFeed(feedHash, feedDefinition) {
9
- this.feedDefinitions[feedHash] = feedDefinition;
10
- return Promise.resolve();
11
- }
12
- getFeed(feedHash) {
13
- return Promise.resolve(this.feedDefinitions[feedHash]);
14
- }
15
- }
16
- exports.MemoryFeedCache = MemoryFeedCache;
17
- //# sourceMappingURL=memory-feed-cache.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"memory-feed-cache.js","sourceRoot":"","sources":["../../src/memory/memory-feed-cache.ts"],"names":[],"mappings":";;;AAEA,MAAa,eAAe;IAA5B;QACY,oBAAe,GAA2C,EAAE,CAAC;IAUzE,CAAC;IARG,SAAS,CAAC,QAAgB,EAAE,cAA8B;QACtD,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,GAAG,cAAc,CAAC;QAChD,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC7B,CAAC;IAED,OAAO,CAAC,QAAgB;QACpB,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC3D,CAAC;CACJ;AAXD,0CAWC"}
@@ -1,14 +0,0 @@
1
- import { FactReference, Feed } from "jinaga";
2
-
3
- export interface FeedDefinition {
4
- start: {
5
- factReference: FactReference,
6
- index: number
7
- }[],
8
- feed: Feed
9
- }
10
-
11
- export interface FeedCache {
12
- storeFeed(feedHash: string, feedDefinition: FeedDefinition): Promise<void>;
13
- getFeed(feedHash: string): Promise<FeedDefinition | undefined>;
14
- }
@@ -1,14 +0,0 @@
1
- import { FeedCache, FeedDefinition } from "../http/feed-cache";
2
-
3
- export class MemoryFeedCache implements FeedCache {
4
- private feedDefinitions: { [feedHash: string]: FeedDefinition } = {};
5
-
6
- storeFeed(feedHash: string, feedDefinition: FeedDefinition): Promise<void> {
7
- this.feedDefinitions[feedHash] = feedDefinition;
8
- return Promise.resolve();
9
- }
10
-
11
- getFeed(feedHash: string): Promise<FeedDefinition | undefined> {
12
- return Promise.resolve(this.feedDefinitions[feedHash]);
13
- }
14
- }