jinaga-server 2.3.0 → 2.3.2
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/dist/authentication/authentication-device.d.ts +0 -1
- package/dist/authentication/authentication-device.js +0 -1
- package/dist/authentication/authentication-device.js.map +1 -1
- package/dist/authorization/authorization-keystore.d.ts +1 -1
- package/dist/authorization/authorization-keystore.js +4 -1
- package/dist/authorization/authorization-keystore.js.map +1 -1
- package/dist/index.d.ts +10 -0
- package/dist/index.js +17 -1
- package/dist/index.js.map +1 -1
- package/dist/jinaga-server.js +0 -6
- package/dist/jinaga-server.js.map +1 -1
- package/dist/postgres/postgres-store.js +2 -2
- package/dist/postgres/postgres-store.js.map +1 -1
- package/dist/postgres/specification-sql.js +17 -9
- package/dist/postgres/specification-sql.js.map +1 -1
- package/dist/util/fn.d.ts +0 -4
- package/dist/util/fn.js +1 -59
- package/dist/util/fn.js.map +1 -1
- package/docs/sql/SQL Generation.ipynb +2427 -0
- package/package.json +1 -1
- package/src/authentication/authentication-device.ts +1 -1
- package/src/authorization/authorization-keystore.ts +3 -2
- package/src/index.ts +10 -0
- package/src/jinaga-server.ts +3 -11
- package/src/postgres/postgres-store.ts +2 -2
- package/src/postgres/specification-sql.ts +18 -14
- package/src/util/fn.ts +0 -43
- package/test/postgres/postgresReadSpec.ts +51 -0
- package/dist/util/maps.d.ts +0 -0
- package/dist/util/maps.js +0 -2
- package/dist/util/maps.js.map +0 -1
- package/docs/registrations.sql +0 -22
- package/docs/sql/example.sql +0 -49
- package/docs/sql-generator.gv +0 -25
- package/src/util/maps.ts +0 -0
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@ export class AuthenticationDevice implements Authentication {
|
|
|
6
6
|
private authorizationEngine: AuthorizationEngine | null;
|
|
7
7
|
|
|
8
8
|
constructor(
|
|
9
|
-
|
|
9
|
+
inner: Storage,
|
|
10
10
|
private keystore: Keystore,
|
|
11
11
|
authorizationRules: AuthorizationRules | null,
|
|
12
12
|
private localDeviceIdentity: UserIdentity
|
|
@@ -43,8 +43,9 @@ export class AuthorizationKeystore implements Authorization {
|
|
|
43
43
|
return this.store.query(start, query);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
read(userIdentity: UserIdentity, start: FactReference[], specification: Specification) {
|
|
47
|
-
|
|
46
|
+
async read(userIdentity: UserIdentity, start: FactReference[], specification: Specification) {
|
|
47
|
+
const projectedResult = await this.store.read(start, specification);
|
|
48
|
+
return projectedResult.map(p => p.result);
|
|
48
49
|
}
|
|
49
50
|
|
|
50
51
|
feed(userIdentity: UserIdentity, feed: Feed, bookmark: string): Promise<FactFeed> {
|
package/src/index.ts
CHANGED
|
@@ -1 +1,11 @@
|
|
|
1
|
+
export { AuthenticationDevice } from "./authentication/authentication-device";
|
|
2
|
+
export { AuthenticationSession } from "./authentication/authentication-session";
|
|
3
|
+
export { AuthorizationKeystore } from "./authorization/authorization-keystore";
|
|
4
|
+
export { Keystore } from "./keystore";
|
|
5
|
+
export { FeedCache } from "./http/feed-cache";
|
|
6
|
+
export { HttpRouter, RequestUser } from "./http/router";
|
|
1
7
|
export { JinagaServer, JinagaServerConfig, JinagaServerInstance, tracePool } from "./jinaga-server";
|
|
8
|
+
export { MemoryFeedCache } from "./memory/memory-feed-cache";
|
|
9
|
+
export { MemoryKeystore } from "./memory/memory-keystore";
|
|
10
|
+
export { PostgresKeystore } from "./postgres/postgres-keystore";
|
|
11
|
+
export { PostgresStore } from "./postgres/postgres-store";
|
package/src/jinaga-server.ts
CHANGED
|
@@ -5,17 +5,17 @@ import {
|
|
|
5
5
|
AuthorizationNoOp,
|
|
6
6
|
AuthorizationRules,
|
|
7
7
|
FactManager,
|
|
8
|
-
|
|
8
|
+
Jinaga,
|
|
9
9
|
MemoryStore,
|
|
10
10
|
Model,
|
|
11
|
-
Network,
|
|
12
11
|
NetworkNoOp,
|
|
13
12
|
ObservableSource,
|
|
14
13
|
ObservableSourceImpl,
|
|
15
14
|
PassThroughFork,
|
|
16
15
|
Storage,
|
|
17
16
|
SyncStatusNotifier,
|
|
18
|
-
Trace,
|
|
17
|
+
Trace,
|
|
18
|
+
UserIdentity
|
|
19
19
|
} from "jinaga";
|
|
20
20
|
import { Pool } from "pg";
|
|
21
21
|
|
|
@@ -94,10 +94,6 @@ function createStore(config: JinagaServerConfig, pools: { [uri: string]: Pool })
|
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
function createFork(config: JinagaServerConfig, store: Storage, syncStatusNotifier: SyncStatusNotifier): Fork {
|
|
98
|
-
return new PassThroughFork(store);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
97
|
function createKeystore(config: JinagaServerConfig, pools: { [uri: string]: Pool }): Keystore | null {
|
|
102
98
|
const uriOrPool = config.pgKeystore;
|
|
103
99
|
if (uriOrPool) {
|
|
@@ -124,10 +120,6 @@ function createAuthentication(store: Storage, keystore: Keystore | null, authori
|
|
|
124
120
|
return keystore ? new AuthenticationDevice(store, keystore, authorizationRules, localDeviceIdentity) : new AuthenticationNoOp();
|
|
125
121
|
}
|
|
126
122
|
|
|
127
|
-
function createNetwork(config: JinagaServerConfig): Network {
|
|
128
|
-
return new NetworkNoOp();
|
|
129
|
-
}
|
|
130
|
-
|
|
131
123
|
function getPool(uriOrPool: string | Pool, pools: { [uri: string]: Pool; }): Pool {
|
|
132
124
|
if (typeof uriOrPool === 'string') {
|
|
133
125
|
const uri = uriOrPool;
|
|
@@ -478,11 +478,11 @@ export class PostgresStore implements Storage {
|
|
|
478
478
|
}
|
|
479
479
|
|
|
480
480
|
getMruDate(specificationHash: string): Promise<Date | null> {
|
|
481
|
-
|
|
481
|
+
return Promise.resolve(null);
|
|
482
482
|
}
|
|
483
483
|
|
|
484
484
|
setMruDate(specificationHash: string, mruDate: Date): Promise<void> {
|
|
485
|
-
|
|
485
|
+
return Promise.resolve();
|
|
486
486
|
}
|
|
487
487
|
}
|
|
488
488
|
|
|
@@ -25,8 +25,6 @@ interface SpecificationSqlQuery {
|
|
|
25
25
|
|
|
26
26
|
interface InputDescription {
|
|
27
27
|
factIndex: number;
|
|
28
|
-
factTypeId: number;
|
|
29
|
-
factHash: string;
|
|
30
28
|
factTypeParameter: number;
|
|
31
29
|
factHashParameter: number;
|
|
32
30
|
}
|
|
@@ -42,7 +40,6 @@ interface EdgeDescription {
|
|
|
42
40
|
}
|
|
43
41
|
interface NotExistsConditionDescription {
|
|
44
42
|
edges: EdgeDescription[];
|
|
45
|
-
notExistsConditions: NotExistsConditionDescription[];
|
|
46
43
|
}
|
|
47
44
|
class QueryDescription {
|
|
48
45
|
constructor(
|
|
@@ -174,11 +171,24 @@ function generateNotExistsWhereClause(schema: string, notExistsWhereClause: NotE
|
|
|
174
171
|
}
|
|
175
172
|
|
|
176
173
|
function parseBookmark(bookmark: string): number[] {
|
|
177
|
-
|
|
178
|
-
|
|
174
|
+
try {
|
|
175
|
+
if (bookmark === undefined || bookmark === null || bookmark === "") {
|
|
176
|
+
return [];
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
return bookmark.split(".").map(str => strictParseInt(str));
|
|
180
|
+
}
|
|
179
181
|
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
+
catch (e) {
|
|
183
|
+
throw new Error(`Invalid bookmark: "${bookmark}"`);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function strictParseInt(str: string): number {
|
|
187
|
+
const parsed = parseInt(str);
|
|
188
|
+
if (isNaN(parsed)) {
|
|
189
|
+
throw new Error("NaN");
|
|
190
|
+
}
|
|
191
|
+
return parsed;
|
|
182
192
|
}
|
|
183
193
|
}
|
|
184
194
|
|
|
@@ -271,9 +281,7 @@ class DescriptionBuilder {
|
|
|
271
281
|
const factHashParameter = addParameter(input.factHash);
|
|
272
282
|
return {
|
|
273
283
|
factIndex: input.factIndex,
|
|
274
|
-
factTypeId,
|
|
275
284
|
factTypeParameter,
|
|
276
|
-
factHash: input.factHash,
|
|
277
285
|
factHashParameter
|
|
278
286
|
};
|
|
279
287
|
}
|
|
@@ -319,13 +327,9 @@ class DescriptionBuilder {
|
|
|
319
327
|
const edges = condition.edges.map(edge =>
|
|
320
328
|
this.buildEdgeDescription(feed, edge, addParameter)
|
|
321
329
|
);
|
|
322
|
-
const notExistsConditions = condition.notExistsConditions.map(condition =>
|
|
323
|
-
this.buildNotExistsConditionDescription(feed, condition, addParameter)
|
|
324
|
-
);
|
|
325
330
|
|
|
326
331
|
return {
|
|
327
|
-
edges
|
|
328
|
-
notExistsConditions
|
|
332
|
+
edges
|
|
329
333
|
}
|
|
330
334
|
}
|
|
331
335
|
}
|
package/src/util/fn.ts
CHANGED
|
@@ -6,16 +6,6 @@ function safeFlatten<U>(results: U[][]) {
|
|
|
6
6
|
return flat ? flat : [];
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
export async function flattenAsync<T, U>(collection: T[], selector: (element: T) => Promise<U[]>) {
|
|
10
|
-
if (collection.length === 0) {
|
|
11
|
-
return [];
|
|
12
|
-
}
|
|
13
|
-
else {
|
|
14
|
-
const results = await Promise.all(collection.map(selector));
|
|
15
|
-
return safeFlatten(results);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
9
|
export function flatten<T, U>(collection: T[], selector: (element: T) => U[]) {
|
|
20
10
|
if (collection.length === 0) {
|
|
21
11
|
return [];
|
|
@@ -25,39 +15,6 @@ export function flatten<T, U>(collection: T[], selector: (element: T) => U[]) {
|
|
|
25
15
|
}
|
|
26
16
|
}
|
|
27
17
|
|
|
28
|
-
export async function mapAsync<T, U>(collection: T[], action: (element: T) => Promise<U>) {
|
|
29
|
-
if (collection.length === 0) {
|
|
30
|
-
return [];
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
33
|
-
return await Promise.all(collection.map(action));
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export async function filterAsync<T>(collection: T[], predicate: (element: T) => Promise<boolean>) {
|
|
38
|
-
if (collection.length === 0) {
|
|
39
|
-
return [];
|
|
40
|
-
}
|
|
41
|
-
else {
|
|
42
|
-
const filters = await Promise.all(collection.map(async element => ({
|
|
43
|
-
include: await predicate(element),
|
|
44
|
-
element
|
|
45
|
-
})));
|
|
46
|
-
|
|
47
|
-
return filters.filter(f => f.include).map(f => f.element);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export function findIndex<T>(array: T[], predicate: ((element: T) => boolean)): number {
|
|
52
|
-
for (let index = 0; index < array.length; index++) {
|
|
53
|
-
if (predicate(array[index])) {
|
|
54
|
-
return index;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return -1;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
18
|
export function distinct<T>(value: T, index: number, self: T[]) {
|
|
62
19
|
return self.indexOf(value) === index;
|
|
63
20
|
}
|
|
@@ -184,6 +184,57 @@ describe("Postgres read", () => {
|
|
|
184
184
|
]);
|
|
185
185
|
});
|
|
186
186
|
|
|
187
|
+
it("should read nested existential conditions", () => {
|
|
188
|
+
const { composer, factTypes, roleMap } = sqlFor(`
|
|
189
|
+
(company: Company) {
|
|
190
|
+
project: Project [
|
|
191
|
+
project->company: Company = company
|
|
192
|
+
!E {
|
|
193
|
+
deleted: Project.Deleted [
|
|
194
|
+
deleted->project: Project = project
|
|
195
|
+
!E {
|
|
196
|
+
restored: Project.Restored [
|
|
197
|
+
restored->deleted: Project.Deleted = deleted
|
|
198
|
+
]
|
|
199
|
+
}
|
|
200
|
+
]
|
|
201
|
+
}
|
|
202
|
+
]
|
|
203
|
+
} => project
|
|
204
|
+
`);
|
|
205
|
+
|
|
206
|
+
const tree = composer.getSqlQueries();
|
|
207
|
+
const sql = tree.sqlQuery.sql;
|
|
208
|
+
expect(sql).toEqual(
|
|
209
|
+
`SELECT f2.hash as hash2, f2.fact_id as id2, f2.data as data2 ` +
|
|
210
|
+
`FROM public.fact f1 ` +
|
|
211
|
+
`JOIN public.edge e1 ` +
|
|
212
|
+
`ON e1.predecessor_fact_id = f1.fact_id ` +
|
|
213
|
+
`AND e1.role_id = $3 ` +
|
|
214
|
+
`JOIN public.fact f2 ` +
|
|
215
|
+
`ON f2.fact_id = e1.successor_fact_id ` +
|
|
216
|
+
`WHERE f1.fact_type_id = $1 AND f1.hash = $2 ` +
|
|
217
|
+
`AND NOT EXISTS (` +
|
|
218
|
+
`SELECT 1 ` +
|
|
219
|
+
`FROM public.edge e2 ` +
|
|
220
|
+
`JOIN public.fact f3 ` +
|
|
221
|
+
`ON f3.fact_id = e2.successor_fact_id ` +
|
|
222
|
+
`WHERE e2.predecessor_fact_id = f2.fact_id ` +
|
|
223
|
+
`AND e2.role_id = $4 ` +
|
|
224
|
+
`AND NOT EXISTS (` +
|
|
225
|
+
`SELECT 1 ` +
|
|
226
|
+
`FROM public.edge e3 ` +
|
|
227
|
+
`JOIN public.fact f4 ` +
|
|
228
|
+
`ON f4.fact_id = e3.successor_fact_id ` +
|
|
229
|
+
`WHERE e3.predecessor_fact_id = f3.fact_id ` +
|
|
230
|
+
`AND e3.role_id = $5` +
|
|
231
|
+
`)` +
|
|
232
|
+
`) ` +
|
|
233
|
+
`ORDER BY f2.fact_id ASC`
|
|
234
|
+
);
|
|
235
|
+
expect(tree.sqlQuery.parameters).toEqual
|
|
236
|
+
});
|
|
237
|
+
|
|
187
238
|
it("should read complex specifications", () => {
|
|
188
239
|
const { composer, factTypes, roleMap } = sqlFor(`
|
|
189
240
|
(company: Company, user: Jinaga.User) {
|
package/dist/util/maps.d.ts
DELETED
|
File without changes
|
package/dist/util/maps.js
DELETED
package/dist/util/maps.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"maps.js","sourceRoot":"","sources":["../../src/util/maps.ts"],"names":[],"mappings":""}
|
package/docs/registrations.sql
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
SELECT F3.HASH AS HASH3,
|
|
2
|
-
F4.HASH AS HASH4,
|
|
3
|
-
F6.HASH AS HASH6,
|
|
4
|
-
sort(array[F3.FACT_ID, F4.FACT_ID, F6.FACT_ID], 'desc') as bookmark
|
|
5
|
-
FROM PUBLIC.FACT F1
|
|
6
|
-
JOIN PUBLIC.EDGE E1 ON E1.PREDECESSOR_FACT_ID = F1.FACT_ID
|
|
7
|
-
AND E1.ROLE_ID = 44
|
|
8
|
-
JOIN PUBLIC.FACT F3 ON F3.FACT_ID = E1.SUCCESSOR_FACT_ID
|
|
9
|
-
JOIN PUBLIC.EDGE E2 ON E2.PREDECESSOR_FACT_ID = F3.FACT_ID
|
|
10
|
-
AND e2.ROLE_ID = 46
|
|
11
|
-
JOIN PUBLIC.FACT F4 ON F4.FACT_ID = E2.SUCCESSOR_FACT_ID
|
|
12
|
-
JOIN PUBLIC.EDGE E4 ON E4.PREDECESSOR_FACT_ID = F4.FACT_ID
|
|
13
|
-
AND E4.ROLE_ID = 18
|
|
14
|
-
JOIN PUBLIC.FACT F6 ON F6.FACT_ID = E4.SUCCESSOR_FACT_ID
|
|
15
|
-
JOIN PUBLIC.EDGE E5 ON E5.SUCCESSOR_FACT_ID = F6.FACT_ID
|
|
16
|
-
AND E5.ROLE_ID = 23
|
|
17
|
-
JOIN PUBLIC.FACT F2 ON F2.FACT_ID = E5.PREDECESSOR_FACT_ID
|
|
18
|
-
WHERE F1.FACT_TYPE_ID = 35
|
|
19
|
-
AND F1.HASH = '5kIRDvVO/wP4v7G9vhDAPMVi2q0cXsZtp9YuyAjan7yyDUhFFPiwwNnzTor6jFdkC11CYnDmoZueMAqxF9MPTQ=='
|
|
20
|
-
AND F2.FACT_TYPE_ID = 24
|
|
21
|
-
AND F2.HASH = '0WWlFbZH+gMoP3QGXO7/mf6hIQC/2iN7wd0peEQKFVvnJMp3gTVvi4eXfVd3DSa81MSzAVp7zVxXIiRnJTF0Kw=='
|
|
22
|
-
ORDER BY bookmark ASC
|
package/docs/sql/example.sql
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
SELECT f4.hash AS hash4, f4.fact_id AS id4, f4.data AS data4
|
|
2
|
-
, f7.hash AS hash7, f7.fact_id AS id7, f7.data AS data7
|
|
3
|
-
, f9.hash AS hash9, f9.fact_id AS id9, f9.data AS data9
|
|
4
|
-
FROM public.fact f1
|
|
5
|
-
JOIN public.edge e1
|
|
6
|
-
ON e1.predecessor_fact_id = f1.fact_id
|
|
7
|
-
AND e1.role_id = $3
|
|
8
|
-
JOIN public.fact f3
|
|
9
|
-
ON f3.fact_id = e1.successor_fact_id
|
|
10
|
-
JOIN public.edge e2
|
|
11
|
-
ON e2.predecessor_fact_id = f3.fact_id
|
|
12
|
-
AND e2.role_id = $4
|
|
13
|
-
JOIN public.fact f4
|
|
14
|
-
ON f4.fact_id = e2.successor_fact_id
|
|
15
|
-
JOIN public.edge e5
|
|
16
|
-
ON e5.predecessor_fact_id = f4.fact_id
|
|
17
|
-
AND e5.role_id = $7
|
|
18
|
-
JOIN public.fact f7
|
|
19
|
-
ON f7.fact_id = e5.successor_fact_id
|
|
20
|
-
JOIN public.edge e6
|
|
21
|
-
ON e6.successor_fact_id = f7.fact_id
|
|
22
|
-
AND e6.role_id = $10
|
|
23
|
-
JOIN public.fact f2
|
|
24
|
-
ON f2.fact_id = e6.predecessor_fact_id
|
|
25
|
-
JOIN public.edge e8
|
|
26
|
-
ON e8.predecessor_fact_id = f4.fact_id
|
|
27
|
-
AND e8.role_id = $12
|
|
28
|
-
JOIN public.fact f9
|
|
29
|
-
ON f9.fact_id = e8.successor_fact_id
|
|
30
|
-
WHERE 1=1
|
|
31
|
-
AND f1.fact_type_id = $1
|
|
32
|
-
AND f1.hash = $2
|
|
33
|
-
AND f2.fact_type_id = $8
|
|
34
|
-
AND f2.hash = $9
|
|
35
|
-
AND NOT EXISTS (SELECT 1
|
|
36
|
-
FROM public.edge e3
|
|
37
|
-
JOIN public.fact f5
|
|
38
|
-
ON f5.fact_id = e3.successor_fact_id
|
|
39
|
-
WHERE 1=1
|
|
40
|
-
AND e3.predecessor_fact_id = f4.fact_id
|
|
41
|
-
AND e3.role_id = $5)
|
|
42
|
-
AND NOT EXISTS (SELECT 1
|
|
43
|
-
FROM public.edge e7
|
|
44
|
-
JOIN public.fact f8
|
|
45
|
-
ON f8.fact_id = e7.successor_fact_id
|
|
46
|
-
WHERE 1=1
|
|
47
|
-
AND e7.predecessor_fact_id = f7.fact_id
|
|
48
|
-
AND e7.role_id = $11)
|
|
49
|
-
ORDER BY f4.fact_id ASC, f7.fact_id ASC, f9.fact_id ASC
|
package/docs/sql-generator.gv
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
digraph {
|
|
2
|
-
subgraph cluster_states {
|
|
3
|
-
color=transparent
|
|
4
|
-
PredecessorType -> PredecessorJoin [label="Predecessor\nemit edge"]
|
|
5
|
-
PredecessorJoin -> PredecessorType [label="Type"]
|
|
6
|
-
PredecessorType -> SuccessorJoin [label="Successor" constraint=false]
|
|
7
|
-
|
|
8
|
-
SuccessorType -> SuccessorJoin [label="Successor"]
|
|
9
|
-
SuccessorJoin -> SuccessorType [label="Type\nemit edge"]
|
|
10
|
-
SuccessorType -> PredecessorJoin [label="Predecessor\nemit fact\nemit edge" constraint=false]
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
subgraph cluster_terminal {
|
|
14
|
-
color=transparent
|
|
15
|
-
success
|
|
16
|
-
error
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
SuccessorJoin -> error [label="end"]
|
|
20
|
-
SuccessorType -> success [label="end\nemit fact"]
|
|
21
|
-
PredecessorType -> success [label="end\nemit fact"]
|
|
22
|
-
PredecessorJoin -> success [label="end\nemit fact"]
|
|
23
|
-
|
|
24
|
-
// {rank=same; SuccessorType; success }
|
|
25
|
-
}
|
package/src/util/maps.ts
DELETED
|
File without changes
|