jinaga-server 1.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/LICENSE +22 -0
- package/dist/authentication/authentication-device.d.ts +20 -0
- package/dist/authentication/authentication-device.js +61 -0
- package/dist/authentication/authentication-device.js.map +1 -0
- package/dist/authentication/authentication-impl.d.ts +21 -0
- package/dist/authentication/authentication-impl.js +61 -0
- package/dist/authentication/authentication-impl.js.map +1 -0
- package/dist/authentication/authentication-session.d.ts +23 -0
- package/dist/authentication/authentication-session.js +85 -0
- package/dist/authentication/authentication-session.js.map +1 -0
- package/dist/authentication/authentication.d.ts +5 -0
- package/dist/authentication/authentication.js +3 -0
- package/dist/authentication/authentication.js.map +1 -0
- package/dist/authentication.d.ts +17 -0
- package/dist/authentication.js +52 -0
- package/dist/authentication.js.map +1 -0
- package/dist/authorization/authorization-keystore.d.ts +13 -0
- package/dist/authorization/authorization-keystore.js +61 -0
- package/dist/authorization/authorization-keystore.js.map +1 -0
- package/dist/http/node-http.d.ts +7 -0
- package/dist/http/node-http.js +126 -0
- package/dist/http/node-http.js.map +1 -0
- package/dist/http/router.d.ts +20 -0
- package/dist/http/router.js +223 -0
- package/dist/http/router.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/jinaga-server.d.ts +18 -0
- package/dist/jinaga-server.js +101 -0
- package/dist/jinaga-server.js.map +1 -0
- package/dist/keystore.d.ts +9 -0
- package/dist/keystore.js +3 -0
- package/dist/keystore.js.map +1 -0
- package/dist/memory/memory-keystore.d.ts +16 -0
- package/dist/memory/memory-keystore.js +86 -0
- package/dist/memory/memory-keystore.js.map +1 -0
- package/dist/postgres/connection.d.ts +12 -0
- package/dist/postgres/connection.js +83 -0
- package/dist/postgres/connection.js.map +1 -0
- package/dist/postgres/edge-record.d.ts +9 -0
- package/dist/postgres/edge-record.js +30 -0
- package/dist/postgres/edge-record.js.map +1 -0
- package/dist/postgres/maps.d.ts +21 -0
- package/dist/postgres/maps.js +86 -0
- package/dist/postgres/maps.js.map +1 -0
- package/dist/postgres/postgres-keystore.d.ts +20 -0
- package/dist/postgres/postgres-keystore.js +168 -0
- package/dist/postgres/postgres-keystore.js.map +1 -0
- package/dist/postgres/postgres-store.d.ts +20 -0
- package/dist/postgres/postgres-store.js +717 -0
- package/dist/postgres/postgres-store.js.map +1 -0
- package/dist/postgres/query-description-builder.d.ts +13 -0
- package/dist/postgres/query-description-builder.js +104 -0
- package/dist/postgres/query-description-builder.js.map +1 -0
- package/dist/postgres/query-description.d.ts +71 -0
- package/dist/postgres/query-description.js +256 -0
- package/dist/postgres/query-description.js.map +1 -0
- package/dist/postgres/specification-result-sql.d.ts +41 -0
- package/dist/postgres/specification-result-sql.js +260 -0
- package/dist/postgres/specification-result-sql.js.map +1 -0
- package/dist/postgres/specification-sql.d.ts +3 -0
- package/dist/postgres/specification-sql.js +119 -0
- package/dist/postgres/specification-sql.js.map +1 -0
- package/dist/postgres/sql.d.ts +10 -0
- package/dist/postgres/sql.js +396 -0
- package/dist/postgres/sql.js.map +1 -0
- package/dist/util/fn.d.ts +6 -0
- package/dist/util/fn.js +81 -0
- package/dist/util/fn.js.map +1 -0
- package/dist/util/promise.d.ts +1 -0
- package/dist/util/promise.js +10 -0
- package/dist/util/promise.js.map +1 -0
- package/docs/registrations.sql +22 -0
- package/docs/specification.txt +41 -0
- package/docs/sql-generator.gv +25 -0
- package/integration-test/docker-compose.yaml +13 -0
- package/integration-test/jinaga-test/Dockerfile +12 -0
- package/integration-test/jinaga-test/jinaga.test.js +425 -0
- package/integration-test/jinaga-test/package-lock.json +6767 -0
- package/integration-test/jinaga-test/package.json +25 -0
- package/integration-test/postgres/0-init-app-db.sh +16 -0
- package/integration-test/postgres/1-setup.sql +219 -0
- package/integration-test/postgres/2-grant.sh +17 -0
- package/integration-test/postgres/Dockerfile +5 -0
- package/integration-test/run.sh +17 -0
- package/integration-test/start_db.sh +2 -0
- package/integration-test/stop_db.sh +3 -0
- package/integration-test/test.sh +8 -0
- package/interactive/index.js +56 -0
- package/jest.config.js +12 -0
- package/package.json +51 -0
- package/scripts/combined.sql +46 -0
- package/scripts/cte.sql +55 -0
- package/scripts/separate.sql +27 -0
- package/setup.sh +34 -0
- package/setup.sql +329 -0
- package/src/authentication/authentication-device.ts +68 -0
- package/src/authentication/authentication-impl.ts +59 -0
- package/src/authentication/authentication-session.ts +95 -0
- package/src/authentication/authentication.ts +6 -0
- package/src/authentication.ts +45 -0
- package/src/authorization/authorization-keystore.ts +67 -0
- package/src/http/node-http.ts +106 -0
- package/src/http/router.ts +237 -0
- package/src/index.ts +1 -0
- package/src/jinaga-server.ts +125 -0
- package/src/keystore.ts +10 -0
- package/src/memory/memory-keystore.ts +93 -0
- package/src/postgres/connection.ts +73 -0
- package/src/postgres/edge-record.ts +36 -0
- package/src/postgres/maps.ts +89 -0
- package/src/postgres/postgres-keystore.ts +167 -0
- package/src/postgres/postgres-store.ts +874 -0
- package/src/postgres/query-description-builder.ts +116 -0
- package/src/postgres/query-description.ts +385 -0
- package/src/postgres/specification-result-sql.ts +362 -0
- package/src/postgres/specification-sql.ts +138 -0
- package/src/postgres/sql.ts +482 -0
- package/src/util/fn.ts +63 -0
- package/src/util/promise.ts +5 -0
- package/test/authorization/authorizationSpec.ts +209 -0
- package/test/postgres/postgresSpec.ts +385 -0
- package/test/postgres/postgresSpecificationSpec.ts +742 -0
- package/test/reporter.js +25 -0
- package/tsconfig.json +25 -0
- package/upgrade.sh +21 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "jinaga-test",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Integration tests for Jinaga.JS",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "jest --reporters jest-compact-reporter",
|
|
8
|
+
"test:verbose": "jest --silent=false --verbose false"
|
|
9
|
+
},
|
|
10
|
+
"jest": {
|
|
11
|
+
"verbose": false
|
|
12
|
+
},
|
|
13
|
+
"author": "Michael L Perry",
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"express": "^4.17.2",
|
|
17
|
+
"jest": "^28.1.0",
|
|
18
|
+
"jest-compact-reporter": "^1.2.9",
|
|
19
|
+
"node-forge": "^1.3.0",
|
|
20
|
+
"passport": "^0.5.2",
|
|
21
|
+
"pg": "^8.7.1",
|
|
22
|
+
"tweetnacl": "^1.0.3",
|
|
23
|
+
"tweetnacl-util": "^0.15.1"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -e
|
|
3
|
+
|
|
4
|
+
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
|
|
5
|
+
SELECT '$APP_USERNAME';
|
|
6
|
+
CREATE USER $APP_USERNAME WITH
|
|
7
|
+
LOGIN
|
|
8
|
+
ENCRYPTED PASSWORD '$APP_PASSWORD'
|
|
9
|
+
NOSUPERUSER
|
|
10
|
+
INHERIT
|
|
11
|
+
NOCREATEDB
|
|
12
|
+
NOCREATEROLE
|
|
13
|
+
NOREPLICATION
|
|
14
|
+
VALID UNTIL 'infinity';
|
|
15
|
+
CREATE DATABASE $APP_DATABASE;
|
|
16
|
+
EOSQL
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
--
|
|
2
|
+
-- Create tables for a Jinaga database
|
|
3
|
+
--
|
|
4
|
+
-- Before executing, be sure you have created the database and the dev role.
|
|
5
|
+
--
|
|
6
|
+
-- CREATE DATABASE myapplication;
|
|
7
|
+
-- \connect myapplication
|
|
8
|
+
--
|
|
9
|
+
-- CREATE USER dev WITH
|
|
10
|
+
-- LOGIN
|
|
11
|
+
-- ENCRYPTED PASSWORD 'devpassword'
|
|
12
|
+
-- NOSUPERUSER
|
|
13
|
+
-- INHERIT
|
|
14
|
+
-- NOCREATEDB
|
|
15
|
+
-- NOCREATEROLE
|
|
16
|
+
-- NOREPLICATION
|
|
17
|
+
-- VALID UNTIL 'infinity';
|
|
18
|
+
--
|
|
19
|
+
|
|
20
|
+
\set appdatabase `echo "$APP_DATABASE"`
|
|
21
|
+
|
|
22
|
+
\connect :appdatabase
|
|
23
|
+
|
|
24
|
+
DO
|
|
25
|
+
$do$
|
|
26
|
+
BEGIN
|
|
27
|
+
|
|
28
|
+
CREATE EXTENSION IF NOT EXISTS intarray;
|
|
29
|
+
|
|
30
|
+
--
|
|
31
|
+
-- Fact Type
|
|
32
|
+
--
|
|
33
|
+
|
|
34
|
+
IF (SELECT to_regclass('public.fact_type')) IS NULL THEN
|
|
35
|
+
|
|
36
|
+
CREATE TABLE fact_type (
|
|
37
|
+
fact_type_id serial PRIMARY KEY,
|
|
38
|
+
name character varying(50) NOT NULL
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
ALTER TABLE public.fact_type OWNER TO postgres;
|
|
43
|
+
|
|
44
|
+
CREATE UNIQUE INDEX ux_fact_type ON fact_type (name);
|
|
45
|
+
|
|
46
|
+
END IF;
|
|
47
|
+
|
|
48
|
+
--
|
|
49
|
+
-- Role
|
|
50
|
+
--
|
|
51
|
+
|
|
52
|
+
IF (SELECT to_regclass('public.role')) IS NULL THEN
|
|
53
|
+
|
|
54
|
+
CREATE TABLE role (
|
|
55
|
+
role_id serial PRIMARY KEY,
|
|
56
|
+
defining_fact_type_id integer NOT NULL,
|
|
57
|
+
CONSTRAINT fk_defining_fact_type_id
|
|
58
|
+
FOREIGN KEY (defining_fact_type_id)
|
|
59
|
+
REFERENCES fact_type (fact_type_id),
|
|
60
|
+
name character varying(20) NOT NULL
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
ALTER TABLE public.role OWNER TO postgres;
|
|
65
|
+
|
|
66
|
+
CREATE UNIQUE INDEX ux_role ON public.role USING btree (defining_fact_type_id, name);
|
|
67
|
+
|
|
68
|
+
END IF;
|
|
69
|
+
|
|
70
|
+
--
|
|
71
|
+
-- Fact
|
|
72
|
+
--
|
|
73
|
+
|
|
74
|
+
IF (SELECT to_regclass('public.fact') IS NULL) THEN
|
|
75
|
+
|
|
76
|
+
CREATE TABLE public.fact (
|
|
77
|
+
fact_id SERIAL PRIMARY KEY,
|
|
78
|
+
fact_type_id integer NOT NULL,
|
|
79
|
+
CONSTRAINT fk_fact_type_id
|
|
80
|
+
FOREIGN KEY (fact_type_id)
|
|
81
|
+
REFERENCES fact_type (fact_type_id),
|
|
82
|
+
hash character varying(100),
|
|
83
|
+
data jsonb,
|
|
84
|
+
date_learned timestamp NOT NULL
|
|
85
|
+
DEFAULT (now() at time zone 'utc')
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
ALTER TABLE public.fact OWNER TO postgres;
|
|
90
|
+
|
|
91
|
+
CREATE UNIQUE INDEX ux_fact ON public.fact USING btree (hash, fact_type_id);
|
|
92
|
+
|
|
93
|
+
END IF;
|
|
94
|
+
|
|
95
|
+
--
|
|
96
|
+
-- Edge
|
|
97
|
+
--
|
|
98
|
+
|
|
99
|
+
IF (SELECT to_regclass('public.edge') IS NULL) THEN
|
|
100
|
+
|
|
101
|
+
CREATE TABLE public.edge (
|
|
102
|
+
role_id integer NOT NULL,
|
|
103
|
+
CONSTRAINT fk_role_id
|
|
104
|
+
FOREIGN KEY (role_id)
|
|
105
|
+
REFERENCES role (role_id),
|
|
106
|
+
successor_fact_id integer NOT NULL,
|
|
107
|
+
CONSTRAINT fk_successor_fact_id
|
|
108
|
+
FOREIGN KEY (successor_fact_id)
|
|
109
|
+
REFERENCES fact (fact_id),
|
|
110
|
+
predecessor_fact_id integer NOT NULL,
|
|
111
|
+
CONSTRAINT fk_predecessor_fact_id
|
|
112
|
+
FOREIGN KEY (predecessor_fact_id)
|
|
113
|
+
REFERENCES fact (fact_id)
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
ALTER TABLE public.edge OWNER TO postgres;
|
|
118
|
+
|
|
119
|
+
-- Most unique first, for fastest uniqueness check on insert.
|
|
120
|
+
CREATE UNIQUE INDEX ux_edge ON public.edge USING btree (successor_fact_id, predecessor_fact_id, role_id);
|
|
121
|
+
-- Covering index based on successor, favoring most likely members of WHERE clause.
|
|
122
|
+
CREATE INDEX ix_successor ON public.edge USING btree (successor_fact_id, role_id, predecessor_fact_id);
|
|
123
|
+
-- Covering index based on predecessor, favoring most likely members of WHERE clause.
|
|
124
|
+
CREATE INDEX ix_predecessor ON public.edge USING btree (predecessor_fact_id, role_id, successor_fact_id);
|
|
125
|
+
|
|
126
|
+
END IF;
|
|
127
|
+
|
|
128
|
+
--
|
|
129
|
+
-- Ancestor
|
|
130
|
+
--
|
|
131
|
+
|
|
132
|
+
IF (SELECT to_regclass('public.ancestor') IS NULL) THEN
|
|
133
|
+
|
|
134
|
+
CREATE TABLE public.ancestor (
|
|
135
|
+
fact_id integer NOT NULL,
|
|
136
|
+
CONSTRAINT fk_fact_id
|
|
137
|
+
FOREIGN KEY (fact_id)
|
|
138
|
+
REFERENCES fact (fact_id),
|
|
139
|
+
ancestor_fact_id integer NOT NULL,
|
|
140
|
+
CONSTRAINT fk_ancestor_fact_id
|
|
141
|
+
FOREIGN KEY (ancestor_fact_id)
|
|
142
|
+
REFERENCES fact (fact_id)
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
ALTER TABLE public.ancestor OWNER TO postgres;
|
|
147
|
+
|
|
148
|
+
CREATE UNIQUE INDEX ux_ancestor ON public.ancestor USING btree (fact_id, ancestor_fact_id);
|
|
149
|
+
|
|
150
|
+
END IF;
|
|
151
|
+
|
|
152
|
+
--
|
|
153
|
+
-- Public Key
|
|
154
|
+
--
|
|
155
|
+
|
|
156
|
+
IF (SELECT to_regclass('public.public_key') IS NULL) THEN
|
|
157
|
+
|
|
158
|
+
CREATE TABLE public.public_key (
|
|
159
|
+
public_key_id serial PRIMARY KEY,
|
|
160
|
+
public_key character varying(500) NOT NULL
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
ALTER TABLE public.public_key OWNER TO postgres;
|
|
165
|
+
|
|
166
|
+
CREATE UNIQUE INDEX ux_public_key ON public.public_key (public_key);
|
|
167
|
+
|
|
168
|
+
END IF;
|
|
169
|
+
|
|
170
|
+
--
|
|
171
|
+
-- Signature
|
|
172
|
+
--
|
|
173
|
+
|
|
174
|
+
IF (SELECT to_regclass('public.signature') IS NULL) THEN
|
|
175
|
+
|
|
176
|
+
CREATE TABLE public."signature" (
|
|
177
|
+
fact_id integer NOT NULL,
|
|
178
|
+
CONSTRAINT fk_fact_id
|
|
179
|
+
FOREIGN KEY (fact_id)
|
|
180
|
+
REFERENCES fact (fact_id),
|
|
181
|
+
public_key_id integer NOT NULL,
|
|
182
|
+
CONSTRAINT fk_public_key_id
|
|
183
|
+
FOREIGN KEY (public_key_id)
|
|
184
|
+
REFERENCES public_key (public_key_id),
|
|
185
|
+
signature character varying(400),
|
|
186
|
+
date_learned timestamp NOT NULL
|
|
187
|
+
DEFAULT (now() at time zone 'utc')
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
ALTER TABLE public."signature" OWNER TO postgres;
|
|
192
|
+
|
|
193
|
+
CREATE UNIQUE INDEX ux_signature ON public."signature" USING btree (fact_id, public_key_id);
|
|
194
|
+
|
|
195
|
+
END IF;
|
|
196
|
+
|
|
197
|
+
--
|
|
198
|
+
-- User
|
|
199
|
+
--
|
|
200
|
+
|
|
201
|
+
IF (SELECT to_regclass('public.user') IS NULL) THEN
|
|
202
|
+
|
|
203
|
+
CREATE TABLE public."user" (
|
|
204
|
+
provider character varying(100),
|
|
205
|
+
user_identifier character varying(50),
|
|
206
|
+
private_key character varying(1800),
|
|
207
|
+
public_key character varying(500)
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
ALTER TABLE public."user" OWNER TO postgres;
|
|
212
|
+
|
|
213
|
+
CREATE UNIQUE INDEX ux_user ON public."user" USING btree (user_identifier, provider);
|
|
214
|
+
CREATE UNIQUE INDEX ux_user_public_key ON public."user" (public_key);
|
|
215
|
+
|
|
216
|
+
END IF;
|
|
217
|
+
|
|
218
|
+
END
|
|
219
|
+
$do$
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -e
|
|
3
|
+
|
|
4
|
+
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$APP_DATABASE" <<-EOSQL
|
|
5
|
+
GRANT SELECT,INSERT ON TABLE public.fact_type TO $APP_USERNAME;
|
|
6
|
+
GRANT SELECT, USAGE ON SEQUENCE fact_type_fact_type_id_seq TO $APP_USERNAME;
|
|
7
|
+
GRANT SELECT,INSERT ON TABLE public.role TO $APP_USERNAME;
|
|
8
|
+
GRANT SELECT, USAGE ON SEQUENCE role_role_id_seq TO $APP_USERNAME;
|
|
9
|
+
GRANT SELECT,INSERT ON TABLE public.fact TO $APP_USERNAME;
|
|
10
|
+
GRANT SELECT, USAGE ON SEQUENCE fact_fact_id_seq TO $APP_USERNAME;
|
|
11
|
+
GRANT SELECT,INSERT ON TABLE public.edge TO $APP_USERNAME;
|
|
12
|
+
GRANT SELECT,INSERT ON TABLE public.ancestor TO $APP_USERNAME;
|
|
13
|
+
GRANT SELECT,INSERT ON TABLE public.public_key TO $APP_USERNAME;
|
|
14
|
+
GRANT SELECT, USAGE ON SEQUENCE public_key_public_key_id_seq TO $APP_USERNAME;
|
|
15
|
+
GRANT SELECT,INSERT ON TABLE public.signature TO $APP_USERNAME;
|
|
16
|
+
GRANT SELECT,INSERT ON TABLE public.user TO $APP_USERNAME;
|
|
17
|
+
EOSQL
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -e
|
|
3
|
+
|
|
4
|
+
docker build -t jinaga-postgres-fact-keystore ./postgres
|
|
5
|
+
|
|
6
|
+
mkdir -p ./jinaga-test/jinaga
|
|
7
|
+
cp -R ../dist ./jinaga-test/jinaga/dist
|
|
8
|
+
cp ../package.json ./jinaga-test/jinaga/package.json
|
|
9
|
+
docker build -t jinaga-test ./jinaga-test
|
|
10
|
+
|
|
11
|
+
cleanup() {
|
|
12
|
+
docker compose down -v
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
trap cleanup EXIT
|
|
16
|
+
|
|
17
|
+
docker compose up --exit-code-from jinaga-test --renew-anon-volumes
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
npm run build
|
|
3
|
+
|
|
4
|
+
cp ./dist/index.js ./integration-test/jinaga-test/jinaga.js
|
|
5
|
+
cp ./dist/index.js.map ./integration-test/jinaga-test/
|
|
6
|
+
|
|
7
|
+
npm --prefix ./integration-test/jinaga-test install
|
|
8
|
+
npm --prefix ./integration-test/jinaga-test run test:verbose
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
const { SpecificationParser } = require("../dist/specification/specification-parser");
|
|
2
|
+
const { dehydrateFact } = require("../dist/fact/hydrate");
|
|
3
|
+
const { PostgresStore } = require("../dist/postgres/postgres-store")
|
|
4
|
+
const fs = require("fs");
|
|
5
|
+
|
|
6
|
+
var user = {"publicKey":"-----BEGIN RSA PUBLIC KEY-----\nMIGJAoGBAIBsKomutukULWw2zoTW2ECMrM8VmD2xvfpl3R4qh1whzuXV+A4EfRKMb/UAjEfw\n5nBmWvcObGyYUgygKrlNeOhf3MnDj706rej6ln9cKGL++ZNsJgJsogaAtmkPihWVGi908fdP\nLQrWTF5be0b/ZP258Zs3CTpcRTpTvhzS5TC1AgMBAAE=\n-----END RSA PUBLIC KEY-----\n","type":"Jinaga.User"};
|
|
7
|
+
|
|
8
|
+
async function run() {
|
|
9
|
+
try {
|
|
10
|
+
var postgresStore = new PostgresStore("postgresql://dev:devpw@localhost:5432/improvingu");
|
|
11
|
+
try {
|
|
12
|
+
var input = fs.readFileSync(0, 'utf-8');
|
|
13
|
+
const parser = new SpecificationParser(input);
|
|
14
|
+
parser.skipWhitespace();
|
|
15
|
+
const userRecord = dehydrateFact(user)[0];
|
|
16
|
+
const knownFacts = {
|
|
17
|
+
me: {
|
|
18
|
+
fact: userRecord,
|
|
19
|
+
reference: {
|
|
20
|
+
type: userRecord.type,
|
|
21
|
+
hash: userRecord.hash
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
var declaration = parser.parseDeclaration(knownFacts);
|
|
26
|
+
var specification = parser.parseSpecification();
|
|
27
|
+
|
|
28
|
+
// Select starting facts that match the inputs
|
|
29
|
+
const start = specification.given.map(input => {
|
|
30
|
+
const fact = declaration[input.name];
|
|
31
|
+
if (!fact) {
|
|
32
|
+
throw new Error(`No fact named ${input.name} was declared`);
|
|
33
|
+
}
|
|
34
|
+
return fact.reference;
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const args = process.argv.slice(2);
|
|
38
|
+
const produceResults = args.includes("--results");
|
|
39
|
+
if (produceResults) {
|
|
40
|
+
const results = await postgresStore.resultsFromSpecification(start, specification);
|
|
41
|
+
console.log(JSON.stringify(results, null, 2));
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
const streams = await postgresStore.streamsFromSpecification(start, [], 3, specification);
|
|
45
|
+
console.log(JSON.stringify(streams, null, 2));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
postgresStore.close();
|
|
50
|
+
}
|
|
51
|
+
} catch (e) {
|
|
52
|
+
console.error(e);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
run();
|
package/jest.config.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "jinaga-server",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Application-agnostic back end for web applications",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"clean": "rimraf dist/ && rimraf integration-test/jinaga-test/jinaga/ && rimraf integration-test/jinaga-test/node_modules/",
|
|
9
|
+
"build": "tsc",
|
|
10
|
+
"test": "jest",
|
|
11
|
+
"test:watch": "jest --watch",
|
|
12
|
+
"prepublishOnly": "npm run clean && npm run build && npm run test",
|
|
13
|
+
"integration": "npm run build && cd ./integration-test && ./run.sh",
|
|
14
|
+
"interactive": "nodemon -w docs/specification.txt -x \"cat docs/specification.txt | node interactive\"",
|
|
15
|
+
"interactive:results": "nodemon -w docs/specification.txt -x \"cat docs/specification.txt | node interactive --results\""
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/jinaga/jinaga-server.git"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"messaging"
|
|
23
|
+
],
|
|
24
|
+
"author": "Michael L Perry",
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/jinaga/jinaga-server/issues"
|
|
28
|
+
},
|
|
29
|
+
"homepage": "https://jinaga.com",
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/express": "^4.17.13",
|
|
32
|
+
"@types/jest": "^27.5.1",
|
|
33
|
+
"@types/node-forge": "^0.10.10",
|
|
34
|
+
"@types/passport": "^1.0.7",
|
|
35
|
+
"@types/pg": "^8.6.1",
|
|
36
|
+
"jest": "^28.1.0",
|
|
37
|
+
"nodemon": "^2.0.15",
|
|
38
|
+
"rimraf": "^3.0.2",
|
|
39
|
+
"source-map-support": "^0.5.21",
|
|
40
|
+
"ts-jest": "^28.0.3",
|
|
41
|
+
"ts-node": "^10.8.0",
|
|
42
|
+
"typescript": "^4.7.2"
|
|
43
|
+
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"express": "^4.18.1",
|
|
46
|
+
"jinaga": "^4.0.1",
|
|
47
|
+
"node-forge": "^1.3.1",
|
|
48
|
+
"passport": "^0.6.0",
|
|
49
|
+
"pg": "^8.7.1"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
BEGIN TRANSACTION;
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
INSERT INTO public.fact (hash, fact_type_id, data)
|
|
5
|
+
VALUES ('hash1', 1, '{ "data": 1 }'::jsonb), ('hash2', 2, '{ "data": 2 }'::jsonb)
|
|
6
|
+
ON CONFLICT DO NOTHING;
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
INSERT INTO public.edge
|
|
10
|
+
(role_id, successor_fact_id, predecessor_fact_id)
|
|
11
|
+
SELECT v.role_id, successor.fact_id, predecessor.fact_id
|
|
12
|
+
FROM (VALUES ('hash2', 2, 'hash1', 1, 1)) AS v (successor_hash, successor_fact_type_id, predecessor_hash, predecessor_fact_type_id, role_id)
|
|
13
|
+
JOIN public.fact AS successor
|
|
14
|
+
ON successor.hash = v.successor_hash AND successor.fact_type_id = v.successor_fact_type_id
|
|
15
|
+
JOIN public.fact AS predecessor
|
|
16
|
+
ON predecessor.hash = v.predecessor_hash AND predecessor.fact_type_id = v.predecessor_fact_type_id
|
|
17
|
+
ON CONFLICT DO NOTHING;
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
WITH e AS (
|
|
21
|
+
SELECT successor.fact_id AS successor_fact_id, predecessor.fact_id AS predecessor_fact_id
|
|
22
|
+
FROM (VALUES ('hash2', 2, 'hash1', 1)) AS v (successor_hash, successor_fact_type_id, predecessor_hash, predecessor_fact_type_id)
|
|
23
|
+
JOIN public.fact AS successor
|
|
24
|
+
ON successor.hash = v.successor_hash AND successor.fact_type_id = v.successor_fact_type_id
|
|
25
|
+
JOIN public.fact AS predecessor
|
|
26
|
+
ON predecessor.hash = v.predecessor_hash AND predecessor.fact_type_id = v.predecessor_fact_type_id
|
|
27
|
+
)
|
|
28
|
+
INSERT INTO public.ancestor
|
|
29
|
+
(fact_id, ancestor_fact_id)
|
|
30
|
+
SELECT e.successor_fact_id, e.predecessor_fact_id
|
|
31
|
+
FROM e
|
|
32
|
+
UNION ALL
|
|
33
|
+
SELECT e.successor_fact_id, ancestor_fact_id
|
|
34
|
+
FROM e
|
|
35
|
+
JOIN public.ancestor
|
|
36
|
+
ON ancestor.fact_id = e.predecessor_fact_id
|
|
37
|
+
ON CONFLICT DO NOTHING;
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
SELECT fact.fact_id, v.fact_type_id, v.hash
|
|
41
|
+
FROM public.fact
|
|
42
|
+
JOIN (VALUES ('hash1', 1), ('hash2', 2)) AS v (hash, fact_type_id)
|
|
43
|
+
ON fact.hash = v.hash AND fact.fact_type_id = v.fact_type_id;
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
ROLLBACK TRANSACTION;
|
package/scripts/cte.sql
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
WITH new_fact AS (
|
|
2
|
+
SELECT hash, fact_type_id, data
|
|
3
|
+
FROM (VALUES ($1, $2::integer, $3::jsonb))
|
|
4
|
+
AS fv (hash, fact_type_id, data)
|
|
5
|
+
),
|
|
6
|
+
new_edge AS (
|
|
7
|
+
SELECT successor_hash, successor_fact_type_id, predecessor_hash, predecessor_fact_type_id, role_id
|
|
8
|
+
FROM (VALUES ($4, $5::integer, $6, $7::integer, $8::integer))
|
|
9
|
+
AS ev (successor_hash, successor_fact_type_id, predecessor_hash, predecessor_fact_type_id, role_id)
|
|
10
|
+
),
|
|
11
|
+
inserted_fact AS (
|
|
12
|
+
INSERT INTO public.fact (hash, fact_type_id, data)
|
|
13
|
+
SELECT hash, fact_type_id, data
|
|
14
|
+
FROM new_fact
|
|
15
|
+
RETURNING fact_id, fact_type_id, hash
|
|
16
|
+
),
|
|
17
|
+
edge_id AS (
|
|
18
|
+
SELECT
|
|
19
|
+
new_edge.role_id,
|
|
20
|
+
successor.fact_id AS successor_fact_id,
|
|
21
|
+
predecessor.fact_id AS predecessor_fact_id
|
|
22
|
+
FROM new_edge
|
|
23
|
+
JOIN inserted_fact AS successor
|
|
24
|
+
ON successor.hash = new_edge.successor_hash
|
|
25
|
+
AND successor.fact_type_id = new_edge.successor_fact_type_id
|
|
26
|
+
JOIN (
|
|
27
|
+
SELECT fact_id, fact_type_id, hash
|
|
28
|
+
FROM inserted_fact
|
|
29
|
+
UNION ALL
|
|
30
|
+
SELECT fact_id, fact_type_id, hash
|
|
31
|
+
FROM public.fact
|
|
32
|
+
) AS predecessor
|
|
33
|
+
ON predecessor.hash = new_edge.predecessor_hash
|
|
34
|
+
AND predecessor.fact_type_id = new_edge.predecessor_fact_type_id
|
|
35
|
+
),
|
|
36
|
+
inserted_edge AS (
|
|
37
|
+
INSERT INTO public.edge
|
|
38
|
+
(role_id, successor_fact_id, predecessor_fact_id)
|
|
39
|
+
SELECT role_id, successor_fact_id, predecessor_fact_id
|
|
40
|
+
FROM edge_id ON CONFLICT DO NOTHING
|
|
41
|
+
),
|
|
42
|
+
inserted_ancestor AS (
|
|
43
|
+
INSERT INTO public.ancestor
|
|
44
|
+
(fact_id, ancestor_fact_id)
|
|
45
|
+
SELECT edge_id.successor_fact_id, edge_id.predecessor_fact_id
|
|
46
|
+
FROM edge_id
|
|
47
|
+
UNION ALL
|
|
48
|
+
SELECT edge_id.successor_fact_id, ancestor_fact_id
|
|
49
|
+
FROM edge_id
|
|
50
|
+
JOIN public.ancestor
|
|
51
|
+
ON ancestor.fact_id = edge_id.predecessor_fact_id
|
|
52
|
+
ON CONFLICT DO NOTHING
|
|
53
|
+
)
|
|
54
|
+
SELECT fact_id, fact_type_id, hash
|
|
55
|
+
FROM inserted_fact;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
BEGIN TRANSACTION;
|
|
2
|
+
|
|
3
|
+
INSERT INTO public.fact (hash, fact_type_id, data)
|
|
4
|
+
(SELECT hash, fact_type_id, data
|
|
5
|
+
FROM (VALUES ('hash1', 1, '{ "data": 1 }'::jsonb), ('hash2', 2, '{ "data": 2 }'::jsonb)) AS v (hash, fact_type_id, data))
|
|
6
|
+
RETURNING fact_id, fact_type_id, hash;
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
INSERT INTO public.edge
|
|
10
|
+
(role_id, successor_fact_id, predecessor_fact_id)
|
|
11
|
+
(VALUES (1, 2, 3), (4, 5, 6))
|
|
12
|
+
ON CONFLICT DO NOTHING;
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
INSERT INTO public.ancestor
|
|
16
|
+
(fact_id, ancestor_fact_id)
|
|
17
|
+
SELECT 3, predecessor_fact_id
|
|
18
|
+
FROM (VALUES (1), (2)) AS v (predecessor_fact_id)
|
|
19
|
+
UNION ALL
|
|
20
|
+
SELECT 1, ancestor_fact_id
|
|
21
|
+
FROM (VALUES (1), (2)) AS v (predecessor_fact_id)
|
|
22
|
+
JOIN public.ancestor
|
|
23
|
+
ON ancestor.fact_id = predecessor_fact_id
|
|
24
|
+
ON CONFLICT DO NOTHING;
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
ROLLBACK TRANSACTION;
|
package/setup.sh
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -e
|
|
3
|
+
|
|
4
|
+
JINAGA_ADMIN_CONNECTION_STRING=postgresql://$JINAGA_POSTGRES_ADMIN_USER:$JINAGA_POSTGRES_ADMIN_PASSWORD@$JINAGA_POSTGRES_HOST:$JINAGA_POSTGRES_PORT/$JINAGA_POSTGRES_APP_DATABASE
|
|
5
|
+
|
|
6
|
+
psql -v ON_ERROR_STOP=1 $JINAGA_ADMIN_CONNECTION_STRING <<-EOSQL
|
|
7
|
+
CREATE USER $JINAGA_POSTGRES_APP_USER WITH
|
|
8
|
+
LOGIN
|
|
9
|
+
ENCRYPTED PASSWORD '$JINAGA_POSTGRES_APP_PASSWORD'
|
|
10
|
+
NOSUPERUSER
|
|
11
|
+
INHERIT
|
|
12
|
+
NOCREATEDB
|
|
13
|
+
NOCREATEROLE
|
|
14
|
+
NOREPLICATION
|
|
15
|
+
VALID UNTIL 'infinity';
|
|
16
|
+
CREATE DATABASE $JINAGA_POSTGRES_APP_DATABASE;
|
|
17
|
+
EOSQL
|
|
18
|
+
|
|
19
|
+
cat ./setup.sql | psql -v ON_ERROR_STOP=1 $JINAGA_ADMIN_CONNECTION_STRING
|
|
20
|
+
|
|
21
|
+
psql -v ON_ERROR_STOP=1 $JINAGA_ADMIN_CONNECTION_STRING <<-EOSQL
|
|
22
|
+
GRANT SELECT,INSERT ON TABLE public.fact_type TO $JINAGA_POSTGRES_APP_USER;
|
|
23
|
+
GRANT SELECT, USAGE ON SEQUENCE fact_type_fact_type_id_seq TO $JINAGA_POSTGRES_APP_USER;
|
|
24
|
+
GRANT SELECT,INSERT ON TABLE public.role TO $JINAGA_POSTGRES_APP_USER;
|
|
25
|
+
GRANT SELECT, USAGE ON SEQUENCE role_role_id_seq TO $JINAGA_POSTGRES_APP_USER;
|
|
26
|
+
GRANT SELECT,INSERT ON TABLE public.fact TO $JINAGA_POSTGRES_APP_USER;
|
|
27
|
+
GRANT SELECT, USAGE ON SEQUENCE fact_fact_id_seq TO $JINAGA_POSTGRES_APP_USER;
|
|
28
|
+
GRANT SELECT,INSERT ON TABLE public.edge TO $JINAGA_POSTGRES_APP_USER;
|
|
29
|
+
GRANT SELECT,INSERT ON TABLE public.ancestor TO $JINAGA_POSTGRES_APP_USER;
|
|
30
|
+
GRANT SELECT,INSERT ON TABLE public.public_key TO $JINAGA_POSTGRES_APP_USER;
|
|
31
|
+
GRANT SELECT, USAGE ON SEQUENCE public_key_public_key_id_seq TO $JINAGA_POSTGRES_APP_USER;
|
|
32
|
+
GRANT SELECT,INSERT ON TABLE public.signature TO $JINAGA_POSTGRES_APP_USER;
|
|
33
|
+
GRANT SELECT,INSERT ON TABLE public.user TO $JINAGA_POSTGRES_APP_USER;
|
|
34
|
+
EOSQL
|