@aloma.io/integration-sdk 3.0.2 → 3.0.3
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/build/builder/index.d.mts +1 -1
- package/build/builder/index.mjs +15 -11
- package/build/builder/runtime-context.d.mts +1 -1
- package/build/builder/runtime-context.mjs +10 -7
- package/build/builder/transform/index.mjs +18 -18
- package/build/cli.d.mts +2 -0
- package/build/cli.mjs +93 -0
- package/build/controller/index.mjs +5 -5
- package/build/index.d.mts +2 -2
- package/build/index.mjs +2 -2
- package/build/internal/dispatcher/index.cjs +41 -30
- package/build/internal/index.cjs +86 -71
- package/build/internal/util/jwe/cli.cjs +3 -3
- package/build/internal/util/jwe/index.cjs +10 -10
- package/build/internal/websocket/config.cjs +7 -7
- package/build/internal/websocket/connection/constants.cjs +3 -3
- package/build/internal/websocket/connection/index.cjs +9 -9
- package/build/internal/websocket/connection/registration.cjs +7 -7
- package/build/internal/websocket/index.cjs +3 -3
- package/build/internal/websocket/transport/durable.cjs +6 -6
- package/build/internal/websocket/transport/index.cjs +18 -18
- package/build/internal/websocket/transport/packet.cjs +2 -2
- package/build/internal/websocket/transport/processor.cjs +5 -5
- package/package.json +1 -1
package/build/builder/index.mjs
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
import fs from
|
2
|
-
import parseTypes from
|
3
|
-
import RuntimeContext from
|
4
|
-
import { fileURLToPath } from
|
5
|
-
import path from
|
1
|
+
import fs from "node:fs";
|
2
|
+
import parseTypes from "./transform/index.mjs";
|
3
|
+
import RuntimeContext from "./runtime-context.mjs";
|
4
|
+
import { fileURLToPath } from "node:url";
|
5
|
+
import path from "node:path";
|
6
6
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
7
7
|
const notEmpty = (what, name) => {
|
8
8
|
if (!what?.trim())
|
@@ -10,7 +10,9 @@ const notEmpty = (what, name) => {
|
|
10
10
|
return what;
|
11
11
|
};
|
12
12
|
export class Builder {
|
13
|
-
data = {
|
13
|
+
data = {
|
14
|
+
controller: "./build/controller/.controller-for-types.mts",
|
15
|
+
};
|
14
16
|
config(arg) {
|
15
17
|
this.data.config = arg;
|
16
18
|
return this;
|
@@ -27,17 +29,19 @@ export class Builder {
|
|
27
29
|
await this.parsePackageJson();
|
28
30
|
await this.discoverTypes();
|
29
31
|
// @ts-ignore
|
30
|
-
const Controller = (await import(__dirname +
|
32
|
+
const Controller = (await import(__dirname + "/../../../../../build/controller/index.mjs")).default;
|
31
33
|
return new RuntimeContext(new Controller(), this.data);
|
32
34
|
}
|
33
35
|
async parsePackageJson() {
|
34
36
|
const data = this.data;
|
35
|
-
const packageJson = JSON.parse(fs.readFileSync(__dirname +
|
36
|
-
|
37
|
-
|
37
|
+
const packageJson = JSON.parse(fs.readFileSync(__dirname + "/../../../../../package.json", {
|
38
|
+
encoding: "utf-8",
|
39
|
+
}));
|
40
|
+
notEmpty((data.id = packageJson.connectorId), "id");
|
41
|
+
notEmpty((data.version = packageJson.version), "version");
|
38
42
|
}
|
39
43
|
async discoverTypes() {
|
40
|
-
notEmpty(this.data.controller,
|
44
|
+
notEmpty(this.data.controller, "controller");
|
41
45
|
const content = fs.readFileSync(this.data.controller);
|
42
46
|
const { text, methods } = parseTypes(this.data.controller);
|
43
47
|
this.data.types = text;
|
@@ -1,5 +1,5 @@
|
|
1
|
-
import { AbstractController } from
|
2
|
-
import { Connector } from
|
1
|
+
import { AbstractController } from "../controller/index.mjs";
|
2
|
+
import { Connector } from "../internal/index.cjs";
|
3
3
|
export default class RuntimeContext {
|
4
4
|
controller;
|
5
5
|
data;
|
@@ -10,7 +10,7 @@ export default class RuntimeContext {
|
|
10
10
|
async start() {
|
11
11
|
const controller = this.controller;
|
12
12
|
if (!(controller instanceof AbstractController))
|
13
|
-
throw new Error(
|
13
|
+
throw new Error("the controller needs to extend AbstractController");
|
14
14
|
const data = this.data;
|
15
15
|
const connector = new Connector({
|
16
16
|
id: data.id,
|
@@ -19,7 +19,12 @@ export default class RuntimeContext {
|
|
19
19
|
});
|
20
20
|
const configuration = connector.configure().config(data.config || {});
|
21
21
|
const resolvers = {};
|
22
|
-
const methods = [
|
22
|
+
const methods = [
|
23
|
+
...data.methods,
|
24
|
+
"__endpoint",
|
25
|
+
"__configQuery",
|
26
|
+
"__default",
|
27
|
+
];
|
23
28
|
methods.forEach((method) => {
|
24
29
|
resolvers[method] = async (args) => {
|
25
30
|
if (!methods.includes(method))
|
@@ -27,9 +32,7 @@ export default class RuntimeContext {
|
|
27
32
|
return controller[method](args);
|
28
33
|
};
|
29
34
|
});
|
30
|
-
configuration
|
31
|
-
.types(data.types)
|
32
|
-
.resolvers(resolvers);
|
35
|
+
configuration.types(data.types).resolvers(resolvers);
|
33
36
|
if (data.options?.endpoint?.enabled) {
|
34
37
|
configuration.endpoint((arg) => controller.__endpoint(arg));
|
35
38
|
}
|
@@ -1,19 +1,19 @@
|
|
1
|
-
import { parseFromFiles } from
|
1
|
+
import { parseFromFiles } from "@ts-ast-parser/core";
|
2
2
|
const transform = (meta) => {
|
3
3
|
if (!meta?.length)
|
4
|
-
throw new Error(
|
4
|
+
throw new Error("metadata is empty");
|
5
5
|
meta = meta[0];
|
6
6
|
if (meta.getDeclarations()?.length !== 1) {
|
7
|
-
throw new Error(
|
7
|
+
throw new Error("connector file needs to export default class");
|
8
8
|
}
|
9
9
|
const methods = {};
|
10
10
|
const decl = meta.getDeclarations()[0];
|
11
11
|
const members = decl.getMethods().filter((member) => {
|
12
12
|
return !(member.isStatic() ||
|
13
13
|
member.isInherited() ||
|
14
|
-
member.getKind() !==
|
15
|
-
member.getModifier() !==
|
16
|
-
member.getName().startsWith(
|
14
|
+
member.getKind() !== "Method" ||
|
15
|
+
member.getModifier() !== "public" ||
|
16
|
+
member.getName().startsWith("_"));
|
17
17
|
});
|
18
18
|
const text = members
|
19
19
|
.map((member) => {
|
@@ -22,13 +22,13 @@ const transform = (meta) => {
|
|
22
22
|
.getSignatures()
|
23
23
|
.map((sig) => {
|
24
24
|
const docs = sig.getJSDoc().serialize() || [];
|
25
|
-
const desc = docs.find((what) => what.kind ===
|
25
|
+
const desc = docs.find((what) => what.kind === "description")?.value;
|
26
26
|
const paramDocs = docs
|
27
|
-
.filter((what) => what.kind ===
|
27
|
+
.filter((what) => what.kind === "param")
|
28
28
|
.map((what) => {
|
29
|
-
return ` * @param {${what.value.type}} ${what.value.name} - ${what.value.description ||
|
29
|
+
return ` * @param {${what.value.type}} ${what.value.name} - ${what.value.description || ""}`;
|
30
30
|
})
|
31
|
-
.join(
|
31
|
+
.join("\n") || " *";
|
32
32
|
const params = sig
|
33
33
|
.getParameters()
|
34
34
|
.map((param) => {
|
@@ -38,32 +38,32 @@ const transform = (meta) => {
|
|
38
38
|
const tmp = param
|
39
39
|
.getNamedElements()
|
40
40
|
.map((p) => {
|
41
|
-
const defaultVal = p.default != null ?
|
41
|
+
const defaultVal = p.default != null ? " = " + p.default : "";
|
42
42
|
return `${p.name}${defaultVal}`;
|
43
43
|
})
|
44
|
-
.join(
|
44
|
+
.join("; ");
|
45
45
|
return `{${tmp}}: ${param.getType().text}`;
|
46
46
|
case false:
|
47
47
|
return `${param.getName()}: ${param.getType().text}`;
|
48
48
|
}
|
49
49
|
})
|
50
|
-
.join(
|
50
|
+
.join(", ");
|
51
51
|
const retVal = sig
|
52
52
|
.getReturnType()
|
53
|
-
.type.text.replace(/^Promise</,
|
54
|
-
.replace(/>$/,
|
53
|
+
.type.text.replace(/^Promise</, "")
|
54
|
+
.replace(/>$/, "");
|
55
55
|
return `
|
56
56
|
/**
|
57
|
-
* ${desc ||
|
57
|
+
* ${desc || ""}
|
58
58
|
*
|
59
59
|
${paramDocs}
|
60
60
|
**/
|
61
61
|
declare function ${member.getName()}(${params}): ${retVal};
|
62
62
|
`;
|
63
63
|
})
|
64
|
-
.join(
|
64
|
+
.join("\n");
|
65
65
|
})
|
66
|
-
.join(
|
66
|
+
.join("");
|
67
67
|
return { text, methods: Object.keys(methods) };
|
68
68
|
};
|
69
69
|
export default (path) => {
|
package/build/cli.d.mts
ADDED
package/build/cli.mjs
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
#!/usr/bin/env node
|
2
|
+
import { Command } from "commander";
|
3
|
+
import fs from "node:fs";
|
4
|
+
import { fileURLToPath } from "node:url";
|
5
|
+
import path from "node:path";
|
6
|
+
import JWE from './internal/util/jwe/index.cjs';
|
7
|
+
import util from 'node:util';
|
8
|
+
import ChildProcess from 'node:child_process';
|
9
|
+
const exec = util.promisify(ChildProcess.exec);
|
10
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
11
|
+
const files = [
|
12
|
+
{ name: "index.mts", dir: "src/controller" },
|
13
|
+
{ name: "index.mts", dir: "src" },
|
14
|
+
{ name: "package.json", dir: "" },
|
15
|
+
{ name: "Containerfile", dir: "" },
|
16
|
+
{ name: "entrypoint.sh", dir: "" },
|
17
|
+
{ name: "tsconfig.json", dir: "" },
|
18
|
+
];
|
19
|
+
const extract = ({ target, name, connectorId }) => {
|
20
|
+
const source = `${__dirname}/../template/connector/`;
|
21
|
+
if (!fs.existsSync(source)) {
|
22
|
+
throw new Error(`source ${source} does not exist`);
|
23
|
+
}
|
24
|
+
files.forEach(({ name, dir }) => {
|
25
|
+
if (dir) {
|
26
|
+
fs.mkdirSync(`${target}/${dir}`, { recursive: true });
|
27
|
+
}
|
28
|
+
const content = fs.readFileSync(`${source}/${dir}/${name}`, {
|
29
|
+
encoding: "utf-8",
|
30
|
+
});
|
31
|
+
fs.writeFileSync(`${target}/${dir}/${name}`, content);
|
32
|
+
});
|
33
|
+
const content = JSON.parse(fs.readFileSync(`${target}/package.json`, { encoding: "utf-8" }));
|
34
|
+
content.name = name;
|
35
|
+
content.connectorId = connectorId;
|
36
|
+
fs.writeFileSync(`${target}/package.json`, JSON.stringify(content, null, 2));
|
37
|
+
fs.writeFileSync(`${target}/.gitignore`, `.DS_Store
|
38
|
+
node_modules
|
39
|
+
build
|
40
|
+
.env`);
|
41
|
+
};
|
42
|
+
const generateKeys = async ({ target }) => {
|
43
|
+
const jwe = new JWE({});
|
44
|
+
await jwe.newPair();
|
45
|
+
const priv = await jwe.exportPrivateAsBase64();
|
46
|
+
const pub = await jwe.exportPublicAsBase64();
|
47
|
+
const content = `REGISTRATION_TOKEN=
|
48
|
+
PRIVATE_KEY=${priv}
|
49
|
+
PUBLIC_KEY=${pub}
|
50
|
+
`;
|
51
|
+
fs.writeFileSync(`${target}/.env`, content);
|
52
|
+
};
|
53
|
+
const program = new Command();
|
54
|
+
program
|
55
|
+
.name("npx @aloma.io/integration-sdk")
|
56
|
+
.description("aloma.io integration sdk")
|
57
|
+
.version("0.8.0")
|
58
|
+
.showHelpAfterError();
|
59
|
+
program
|
60
|
+
.command("create")
|
61
|
+
.description("Create a new connector project")
|
62
|
+
.argument("<name>", "name of the project")
|
63
|
+
.requiredOption("--connector-id <id>", "id of the connector")
|
64
|
+
.action(async (name, options) => {
|
65
|
+
name = name.replace(/[\/\.]/gi, "");
|
66
|
+
if (!name)
|
67
|
+
throw new Error("name is empty");
|
68
|
+
const target = `${process.cwd()}/${name}`;
|
69
|
+
fs.mkdirSync(target);
|
70
|
+
console.log('Creating connector ...');
|
71
|
+
extract({ ...options, target, name });
|
72
|
+
console.log('Generating keys ...');
|
73
|
+
await generateKeys({ target });
|
74
|
+
console.log('Installing dependencies ...');
|
75
|
+
await exec(`cd ${target}; yarn`);
|
76
|
+
console.log('Building ...');
|
77
|
+
await exec(`cd ${target}; yarn build`);
|
78
|
+
console.log(`
|
79
|
+
Success!
|
80
|
+
|
81
|
+
1.) Add the connector to a workspace
|
82
|
+
2.) Edit ./${name}/.env and insert the registration token
|
83
|
+
3.) Start the connector with cd ./${name}/; yarn start`);
|
84
|
+
});
|
85
|
+
program
|
86
|
+
.command("build")
|
87
|
+
.description("Build the current connector project")
|
88
|
+
.action(async (str, options) => {
|
89
|
+
const { stdout, stderr } = await exec(`rm -rf build; mkdir -p build/controller; cp ./src/controller/index.mts ./build/controller/.controller-for-types.mts;`);
|
90
|
+
if (stdout)
|
91
|
+
console.log(stdout);
|
92
|
+
});
|
93
|
+
program.parse();
|
@@ -7,19 +7,19 @@ export class AbstractController {
|
|
7
7
|
return Promise.resolve({});
|
8
8
|
}
|
9
9
|
fallback(arg) {
|
10
|
-
throw new Error(
|
10
|
+
throw new Error("method not found");
|
11
11
|
}
|
12
12
|
endpoint(arg) {
|
13
|
-
throw new Error(
|
13
|
+
throw new Error("method not found");
|
14
14
|
}
|
15
15
|
async newTask(name, data) {
|
16
|
-
throw new Error(
|
16
|
+
throw new Error("not implemented");
|
17
17
|
}
|
18
18
|
getClient({ baseUrl }) {
|
19
|
-
throw new Error(
|
19
|
+
throw new Error("not implemented");
|
20
20
|
}
|
21
21
|
async updateTask(name, data) {
|
22
|
-
throw new Error(
|
22
|
+
throw new Error("not implemented");
|
23
23
|
}
|
24
24
|
async __endpoint(arg) {
|
25
25
|
return this.endpoint(arg);
|
package/build/index.d.mts
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
export * from
|
2
|
-
export * from
|
1
|
+
export * from "./builder/index.mjs";
|
2
|
+
export * from "./controller/index.mjs";
|
package/build/index.mjs
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
export * from
|
2
|
-
export * from
|
1
|
+
export * from "./builder/index.mjs";
|
2
|
+
export * from "./controller/index.mjs";
|
@@ -14,26 +14,26 @@ class Dispatcher {
|
|
14
14
|
oauth: true,
|
15
15
|
fields: {
|
16
16
|
oauthResult: {
|
17
|
-
name:
|
18
|
-
placeholder:
|
19
|
-
type:
|
17
|
+
name: "OAuth Result",
|
18
|
+
placeholder: "will be set by finishing the oauth flow",
|
19
|
+
type: "managed",
|
20
20
|
},
|
21
21
|
},
|
22
22
|
});
|
23
23
|
return this;
|
24
24
|
}
|
25
25
|
if (!arg.authorizationURL)
|
26
|
-
throw new Error(
|
26
|
+
throw new Error("need a authorizationURL");
|
27
27
|
if (!arg.tokenURL && !arg.finishOAuth)
|
28
|
-
throw new Error(
|
28
|
+
throw new Error("need a tokenURL or finishOAuth()");
|
29
29
|
this._oauth = { ...arg };
|
30
30
|
this.config({
|
31
31
|
oauth: true,
|
32
32
|
fields: {
|
33
33
|
oauthResult: {
|
34
|
-
name:
|
35
|
-
placeholder:
|
36
|
-
type:
|
34
|
+
name: "OAuth Result",
|
35
|
+
placeholder: "will be set by finishing the oauth flow",
|
36
|
+
type: "managed",
|
37
37
|
},
|
38
38
|
},
|
39
39
|
});
|
@@ -41,14 +41,14 @@ class Dispatcher {
|
|
41
41
|
this.config({
|
42
42
|
fields: {
|
43
43
|
clientId: {
|
44
|
-
name:
|
45
|
-
placeholder:
|
46
|
-
type:
|
44
|
+
name: "OAuth Client ID",
|
45
|
+
placeholder: "e.g. 1234",
|
46
|
+
type: "line",
|
47
47
|
},
|
48
48
|
clientSecret: {
|
49
|
-
name:
|
50
|
-
placeholder:
|
51
|
-
type:
|
49
|
+
name: "OAuth Client Secret",
|
50
|
+
placeholder: "e.g. axd5xde",
|
51
|
+
type: "line",
|
52
52
|
},
|
53
53
|
},
|
54
54
|
});
|
@@ -72,9 +72,9 @@ class Dispatcher {
|
|
72
72
|
this.config({
|
73
73
|
fields: {
|
74
74
|
_endpointToken: {
|
75
|
-
name:
|
76
|
-
placeholder:
|
77
|
-
type:
|
75
|
+
name: "Endpoint Token (set to enable the endpoint)",
|
76
|
+
placeholder: "e.g. 1234",
|
77
|
+
type: "line",
|
78
78
|
plain: true,
|
79
79
|
optional: true,
|
80
80
|
},
|
@@ -84,19 +84,19 @@ class Dispatcher {
|
|
84
84
|
return this;
|
85
85
|
}
|
86
86
|
startOAuth() {
|
87
|
-
throw new Error(
|
87
|
+
throw new Error("oauth not configured");
|
88
88
|
}
|
89
89
|
finishOAuth() {
|
90
|
-
throw new Error(
|
90
|
+
throw new Error("oauth not configured");
|
91
91
|
}
|
92
92
|
build() {
|
93
93
|
if (!this._types || !this._resolvers)
|
94
|
-
throw new Error(
|
94
|
+
throw new Error("missing types or resolvers");
|
95
95
|
var local = this;
|
96
96
|
const _resolvers = { ...this._resolvers };
|
97
97
|
const main = this._main || (() => { });
|
98
98
|
const start = async (transport) => {
|
99
|
-
console.log(
|
99
|
+
console.log("starting ...");
|
100
100
|
await main(transport);
|
101
101
|
};
|
102
102
|
const resolveMethod = (query) => {
|
@@ -110,33 +110,44 @@ class Dispatcher {
|
|
110
110
|
if (!Array.isArray(query))
|
111
111
|
query = [query];
|
112
112
|
query = query
|
113
|
-
.filter((what) => !!what?.trim() &&
|
113
|
+
.filter((what) => !!what?.trim() &&
|
114
|
+
![
|
115
|
+
"constructor",
|
116
|
+
"__proto__",
|
117
|
+
"toString",
|
118
|
+
"toSource",
|
119
|
+
"prototype",
|
120
|
+
].includes(what))
|
114
121
|
.slice(0, 20);
|
115
122
|
const method = resolveMethod(query);
|
116
123
|
if (!method && !_resolvers.__default)
|
117
124
|
throw new Error(`${query} not found`);
|
118
|
-
return method
|
125
|
+
return method
|
126
|
+
? method(variables)
|
127
|
+
: _resolvers.__default(variables ? { ...variables, __method: query } : variables);
|
119
128
|
};
|
120
129
|
const introspect = () => local._types;
|
121
130
|
const configSchema = () => local._config;
|
122
131
|
const processPacket = async (packet) => {
|
123
132
|
switch (packet.method()) {
|
124
|
-
case
|
133
|
+
case "connector.introspect":
|
125
134
|
const intro = await introspect({});
|
126
135
|
return { configSchema: local._config, introspect: intro };
|
127
|
-
case
|
136
|
+
case "connector.start-oauth":
|
128
137
|
return await local.startOAuth(packet.args());
|
129
|
-
case
|
138
|
+
case "connector.finish-oauth":
|
130
139
|
return await local.finishOAuth(packet.args());
|
131
|
-
case
|
140
|
+
case "connector.query":
|
132
141
|
const ret = await execute(packet.args());
|
133
|
-
return typeof ret ===
|
134
|
-
|
142
|
+
return typeof ret === "object" && !Array.isArray(ret)
|
143
|
+
? ret
|
144
|
+
: { [packet.args().query]: ret };
|
145
|
+
case "connector.set-config":
|
135
146
|
await local.onConfig({ ...packet.args().secrets });
|
136
147
|
return;
|
137
148
|
}
|
138
149
|
console.dir(packet, { depth: null });
|
139
|
-
throw new Error(
|
150
|
+
throw new Error("cannot handle packet");
|
140
151
|
};
|
141
152
|
return {
|
142
153
|
introspect,
|
package/build/internal/index.cjs
CHANGED
@@ -1,27 +1,27 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
// @ts-nocheck
|
4
|
-
require(
|
5
|
-
const fs = require(
|
6
|
-
const { Config } = require(
|
7
|
-
const { Connection } = require(
|
8
|
-
const { Transport } = require(
|
9
|
-
const { Dispatcher } = require(
|
10
|
-
const { WebsocketConnector } = require(
|
11
|
-
const JWE = require(
|
12
|
-
const fetch = require(
|
13
|
-
const cuid = require(
|
4
|
+
require("dotenv").config();
|
5
|
+
const fs = require("fs");
|
6
|
+
const { Config } = require("./websocket/config.cjs");
|
7
|
+
const { Connection } = require("./websocket/connection/index.cjs");
|
8
|
+
const { Transport } = require("./websocket/transport/index.cjs");
|
9
|
+
const { Dispatcher } = require("./dispatcher/index.cjs");
|
10
|
+
const { WebsocketConnector } = require("./websocket/index.cjs");
|
11
|
+
const JWE = require("./util/jwe/index.cjs");
|
12
|
+
const fetch = require("node-fetch");
|
13
|
+
const cuid = require("@paralleldrive/cuid2").init({ length: 32 });
|
14
14
|
// TODO fetch with retry
|
15
15
|
const handlePacketError = (packet, e, transport) => {
|
16
16
|
if (!packet.cb()) {
|
17
|
-
console.dir({ msg:
|
17
|
+
console.dir({ msg: "packet error", e, packet }, { depth: null });
|
18
18
|
return;
|
19
19
|
}
|
20
|
-
transport.send(transport.newPacket({ c: packet.cb(), a: { error:
|
20
|
+
transport.send(transport.newPacket({ c: packet.cb(), a: { error: "" + e } }));
|
21
21
|
};
|
22
22
|
const reply = (arg, packet, transport) => {
|
23
23
|
if (!packet.cb()) {
|
24
|
-
console.dir({ msg:
|
24
|
+
console.dir({ msg: "cannot reply to packet without cb", arg, packet }, { depth: null });
|
25
25
|
return;
|
26
26
|
}
|
27
27
|
transport.send(transport.newPacket({ c: packet.cb(), a: { ...arg } }));
|
@@ -30,7 +30,7 @@ const unwrap = async (ret, options) => {
|
|
30
30
|
if (options?.text)
|
31
31
|
return await ret.text();
|
32
32
|
if (options?.base64)
|
33
|
-
return (await ret.buffer()).toString(
|
33
|
+
return (await ret.buffer()).toString("base64");
|
34
34
|
return await ret.json();
|
35
35
|
};
|
36
36
|
class Fetcher {
|
@@ -57,13 +57,13 @@ class Fetcher {
|
|
57
57
|
if (retries == null)
|
58
58
|
retries = local.retry;
|
59
59
|
try {
|
60
|
-
const theURL = `${baseUrl?.endsWith(
|
60
|
+
const theURL = `${baseUrl?.endsWith("/") ? baseUrl : baseUrl + "/"}${url}`.replace(/\/\/+/gi, "/");
|
61
61
|
await local.customize(options, args);
|
62
62
|
const ret = await fetch(theURL, options);
|
63
63
|
const status = await ret.status;
|
64
64
|
if (status > 399) {
|
65
65
|
const text = await ret.text();
|
66
|
-
const e = new Error(status +
|
66
|
+
const e = new Error(status + " " + text);
|
67
67
|
e.status = status;
|
68
68
|
throw e;
|
69
69
|
}
|
@@ -92,14 +92,14 @@ class OAuthFetcher extends Fetcher {
|
|
92
92
|
return oauth.accessToken();
|
93
93
|
const refreshToken = oauth.refreshToken();
|
94
94
|
if (!refreshToken)
|
95
|
-
throw new Error(
|
95
|
+
throw new Error("have no access_token and no refresh_token");
|
96
96
|
const ret = await oauth.obtainViaRefreshToken(oauth.refreshToken());
|
97
97
|
if (ret.access_token) {
|
98
98
|
oauth.update(ret.access_token, ret.refresh_token);
|
99
99
|
return ret.access_token;
|
100
100
|
}
|
101
101
|
else {
|
102
|
-
throw new Error(
|
102
|
+
throw new Error("could not obtain access token via refresh token");
|
103
103
|
}
|
104
104
|
}
|
105
105
|
async onError(e, url, options, retries, args) {
|
@@ -107,7 +107,9 @@ class OAuthFetcher extends Fetcher {
|
|
107
107
|
return new Promise((resolve, reject) => {
|
108
108
|
setTimeout(async () => {
|
109
109
|
try {
|
110
|
-
resolve(await local.fetch(url, options, retries, {
|
110
|
+
resolve(await local.fetch(url, options, retries, {
|
111
|
+
forceTokenRefresh: e.status === 401,
|
112
|
+
}));
|
111
113
|
}
|
112
114
|
catch (e) {
|
113
115
|
reject(e);
|
@@ -163,36 +165,36 @@ class Connector {
|
|
163
165
|
async run() {
|
164
166
|
var local = this;
|
165
167
|
const makeMetrics = () => {
|
166
|
-
const metrics = require(
|
168
|
+
const metrics = require("prom-client");
|
167
169
|
const defaultLabels = {
|
168
170
|
service: local.name,
|
169
171
|
connectorId: local.id,
|
170
172
|
connectorVersion: local.version,
|
171
|
-
node: process.env.HOSTNAME ||
|
173
|
+
node: process.env.HOSTNAME || "test",
|
172
174
|
};
|
173
175
|
metrics.register.setDefaultLabels(defaultLabels);
|
174
176
|
metrics.collectDefaultMetrics();
|
175
177
|
return metrics;
|
176
178
|
};
|
177
179
|
const makeMetricsServer = (metrics) => {
|
178
|
-
const app = require(
|
179
|
-
app.get(
|
180
|
+
const app = require("express")();
|
181
|
+
app.get("/metrics", async (request, response, next) => {
|
180
182
|
response.status(200);
|
181
|
-
response.set(
|
183
|
+
response.set("Content-type", metrics.contentType);
|
182
184
|
response.send(await metrics.register.metrics());
|
183
185
|
response.end();
|
184
186
|
});
|
185
187
|
return app;
|
186
188
|
};
|
187
|
-
makeMetricsServer(makeMetrics()).listen(4050,
|
189
|
+
makeMetricsServer(makeMetrics()).listen(4050, "0.0.0.0");
|
188
190
|
const { processPacket, start, introspect, configSchema } = this.dispatcher.build();
|
189
191
|
const config = new Config({
|
190
192
|
id: this.id,
|
191
193
|
version: this.version,
|
192
194
|
name: process.env.HOSTNAME || this.name,
|
193
195
|
registrationToken: process.env.REGISTRATION_TOKEN,
|
194
|
-
endpoint: process.env.DEVICE_ENDPOINT ||
|
195
|
-
wsEndpoint: process.env.WEBSOCKET_ENDPOINT ||
|
196
|
+
endpoint: process.env.DEVICE_ENDPOINT || "https://connect.aloma.io/",
|
197
|
+
wsEndpoint: process.env.WEBSOCKET_ENDPOINT || "wss://transport.aloma.io/transport/",
|
196
198
|
privateKey: process.env.PRIVATE_KEY,
|
197
199
|
publicKey: process.env.PUBLIC_KEY,
|
198
200
|
introspect,
|
@@ -205,15 +207,15 @@ class Connector {
|
|
205
207
|
catch (e) {
|
206
208
|
const haveKey = !!process.env.PRIVATE_KEY;
|
207
209
|
const jwe = new JWE({});
|
208
|
-
var text =
|
210
|
+
var text = "Please double check the env variables";
|
209
211
|
if (!haveKey) {
|
210
212
|
await jwe.newPair();
|
211
213
|
text =
|
212
|
-
|
214
|
+
"fresh keys generated, set environment variables: \n\nPRIVATE_KEY: " +
|
213
215
|
(await jwe.exportPrivateAsBase64()) +
|
214
|
-
|
216
|
+
"\n\nPUBLIC_KEY: " +
|
215
217
|
(await jwe.exportPublicAsBase64()) +
|
216
|
-
|
218
|
+
"\n";
|
217
219
|
}
|
218
220
|
console.log(`
|
219
221
|
Error:
|
@@ -232,7 +234,7 @@ ${text}
|
|
232
234
|
const decrypted = {};
|
233
235
|
const fields = configSchema().fields;
|
234
236
|
const keys = Object.keys(secrets);
|
235
|
-
const jwe = await config.validateKeys(
|
237
|
+
const jwe = await config.validateKeys("RSA-OAEP-256");
|
236
238
|
for (var i = 0; i < keys.length; ++i) {
|
237
239
|
const key = keys[i];
|
238
240
|
const value = secrets[key];
|
@@ -246,17 +248,22 @@ ${text}
|
|
246
248
|
decrypted[key] = await jwe.decrypt(value, config.id());
|
247
249
|
}
|
248
250
|
catch (e) {
|
249
|
-
console.log(
|
251
|
+
console.log("failed to decrypt key", key, config.id(), e);
|
250
252
|
}
|
251
253
|
}
|
252
254
|
}
|
253
255
|
this.startOAuth = async function (args) {
|
254
256
|
if (!this._oauth)
|
255
|
-
throw new Error(
|
256
|
-
const clientId = this._oauth.clientId ||
|
257
|
+
throw new Error("oauth not configured");
|
258
|
+
const clientId = this._oauth.clientId ||
|
259
|
+
process.env.OAUTH_CLIENT_ID ||
|
260
|
+
decrypted.clientId;
|
257
261
|
if (!clientId)
|
258
|
-
throw new Error(
|
259
|
-
const scopes = this._oauth.scope ||
|
262
|
+
throw new Error("clientId not configured");
|
263
|
+
const scopes = this._oauth.scope ||
|
264
|
+
process.env.OAUTH_SCOPE ||
|
265
|
+
decrypted.scope ||
|
266
|
+
"";
|
260
267
|
const useCodeChallenge = !!that._oauth.useCodeChallenge;
|
261
268
|
return {
|
262
269
|
url: this._oauth.authorizationURL
|
@@ -268,19 +275,23 @@ ${text}
|
|
268
275
|
this.finishOAuth = async function (arg) {
|
269
276
|
var that = this;
|
270
277
|
if (!this._oauth)
|
271
|
-
throw new Error(
|
278
|
+
throw new Error("oauth not configured");
|
272
279
|
if (!this._oauth.tokenURL && !this._oauth.finishOAuth)
|
273
|
-
throw new Error(
|
280
|
+
throw new Error("need tokenURL or finishOAuth(arg)");
|
274
281
|
var data = null;
|
275
282
|
const doFinish = async () => {
|
276
283
|
if (!arg.code || !arg.redirectURI)
|
277
|
-
throw new Error(
|
278
|
-
const clientId = that._oauth.clientId ||
|
284
|
+
throw new Error("need code and redirectUri");
|
285
|
+
const clientId = that._oauth.clientId ||
|
286
|
+
process.env.OAUTH_CLIENT_ID ||
|
287
|
+
decrypted.clientId;
|
279
288
|
if (!clientId)
|
280
|
-
throw new Error(
|
281
|
-
const clientSecret = that._oauth.clientSecret ||
|
289
|
+
throw new Error("clientId not configured");
|
290
|
+
const clientSecret = that._oauth.clientSecret ||
|
291
|
+
process.env.OAUTH_CLIENT_SECRET ||
|
292
|
+
decrypted.clientSecret;
|
282
293
|
if (!clientSecret)
|
283
|
-
throw new Error(
|
294
|
+
throw new Error("clientSecret not configured");
|
284
295
|
const additionalTokenArgs = that._oauth.additionalTokenArgs || {};
|
285
296
|
const useAuthHeader = !!that._oauth.useAuthHeader;
|
286
297
|
const useCodeChallenge = !!that._oauth.useCodeChallenge;
|
@@ -293,8 +304,8 @@ ${text}
|
|
293
304
|
body.code_verifier = arg.codeVerifier;
|
294
305
|
}
|
295
306
|
let headers = {
|
296
|
-
|
297
|
-
Accept:
|
307
|
+
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
|
308
|
+
Accept: "application/json",
|
298
309
|
};
|
299
310
|
if (useAuthHeader) {
|
300
311
|
headers = {
|
@@ -310,7 +321,7 @@ ${text}
|
|
310
321
|
};
|
311
322
|
}
|
312
323
|
const response = await fetch(that._oauth.tokenURL, {
|
313
|
-
method:
|
324
|
+
method: "POST",
|
314
325
|
body: new URLSearchParams(body),
|
315
326
|
headers,
|
316
327
|
});
|
@@ -319,17 +330,17 @@ ${text}
|
|
319
330
|
if (status === 200) {
|
320
331
|
const ret = JSON.parse(text);
|
321
332
|
if (ret.error) {
|
322
|
-
throw new Error(`${status} ${ret.error} ${ret.error_description ||
|
333
|
+
throw new Error(`${status} ${ret.error} ${ret.error_description || ""}`);
|
323
334
|
}
|
324
335
|
else if (ret.access_token) {
|
325
336
|
return { ...ret };
|
326
337
|
}
|
327
338
|
else {
|
328
|
-
throw new Error(status +
|
339
|
+
throw new Error(status + " response has no access_token - " + text);
|
329
340
|
}
|
330
341
|
}
|
331
342
|
else {
|
332
|
-
throw new Error(status +
|
343
|
+
throw new Error(status + " " + text);
|
333
344
|
}
|
334
345
|
};
|
335
346
|
if (this._oauth.finishOAuth) {
|
@@ -342,26 +353,30 @@ ${text}
|
|
342
353
|
else {
|
343
354
|
data = await doFinish();
|
344
355
|
}
|
345
|
-
const jwe = await config.validateKeys(
|
346
|
-
return { value: await jwe.encrypt(data,
|
356
|
+
const jwe = await config.validateKeys("RSA-OAEP-256");
|
357
|
+
return { value: await jwe.encrypt(data, "none", config.id()) };
|
347
358
|
};
|
348
359
|
const saveOAuthResult = async (what) => {
|
349
|
-
const jwe = await config.validateKeys(
|
360
|
+
const jwe = await config.validateKeys("RSA-OAEP-256");
|
350
361
|
const packet = transport.newPacket({});
|
351
|
-
packet.method(
|
362
|
+
packet.method("connector.config-update");
|
352
363
|
packet.args({
|
353
|
-
value: await jwe.encrypt(what,
|
364
|
+
value: await jwe.encrypt(what, "none", config.id()),
|
354
365
|
});
|
355
366
|
transport.send(packet);
|
356
367
|
};
|
357
368
|
const that = this;
|
358
369
|
const getRefreshToken = async (refreshToken) => {
|
359
|
-
const clientId = that._oauth.clientId ||
|
370
|
+
const clientId = that._oauth.clientId ||
|
371
|
+
process.env.OAUTH_CLIENT_ID ||
|
372
|
+
decrypted.clientId;
|
360
373
|
if (!clientId)
|
361
|
-
throw new Error(
|
362
|
-
const clientSecret = that._oauth.clientSecret ||
|
374
|
+
throw new Error("clientId not configured");
|
375
|
+
const clientSecret = that._oauth.clientSecret ||
|
376
|
+
process.env.OAUTH_CLIENT_SECRET ||
|
377
|
+
decrypted.clientSecret;
|
363
378
|
if (!clientSecret)
|
364
|
-
throw new Error(
|
379
|
+
throw new Error("clientSecret not configured");
|
365
380
|
const useAuthHeader = !!that._oauth.useAuthHeader;
|
366
381
|
let headers = {};
|
367
382
|
if (useAuthHeader) {
|
@@ -371,16 +386,16 @@ ${text}
|
|
371
386
|
};
|
372
387
|
}
|
373
388
|
const response = await fetch(that._oauth.tokenURL, {
|
374
|
-
method:
|
389
|
+
method: "POST",
|
375
390
|
body: new URLSearchParams({
|
376
|
-
grant_type:
|
391
|
+
grant_type: "refresh_token",
|
377
392
|
refresh_token: refreshToken,
|
378
393
|
client_id: clientId,
|
379
394
|
client_secret: clientSecret,
|
380
395
|
}),
|
381
396
|
headers: {
|
382
|
-
|
383
|
-
Accept:
|
397
|
+
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
|
398
|
+
Accept: "application/json",
|
384
399
|
...headers,
|
385
400
|
},
|
386
401
|
});
|
@@ -390,7 +405,7 @@ ${text}
|
|
390
405
|
return JSON.parse(text);
|
391
406
|
}
|
392
407
|
else {
|
393
|
-
throw new Error(
|
408
|
+
throw new Error("could not get refresh token " + status + " " + text);
|
394
409
|
}
|
395
410
|
};
|
396
411
|
const theOAuth = decrypted.oauthResult
|
@@ -399,11 +414,11 @@ ${text}
|
|
399
414
|
start({
|
400
415
|
config: decrypted,
|
401
416
|
oauth: theOAuth,
|
402
|
-
getClient: (arg) =>
|
417
|
+
getClient: (arg) => theOAuth ? theOAuth.getClient(arg) : new Fetcher({ ...arg }),
|
403
418
|
newTask: (name, data) => {
|
404
419
|
return new Promise((resolve, reject) => {
|
405
420
|
const packet = transport.newPacket({}, (ret) => (ret?.error ? reject(ret.error) : resolve(ret)), `_req-${cuid()}`);
|
406
|
-
packet.method(
|
421
|
+
packet.method("connector.task.new");
|
407
422
|
packet.args({
|
408
423
|
name,
|
409
424
|
a: data,
|
@@ -414,7 +429,7 @@ ${text}
|
|
414
429
|
updateTask: (id, data) => {
|
415
430
|
return new Promise((resolve, reject) => {
|
416
431
|
const packet = transport.newPacket({}, (ret) => (ret?.error ? reject(ret.error) : resolve(ret)), `_req-${cuid()}`);
|
417
|
-
packet.method(
|
432
|
+
packet.method("connector.task.update");
|
418
433
|
packet.args({
|
419
434
|
id,
|
420
435
|
a: data,
|
@@ -447,14 +462,14 @@ ${text}
|
|
447
462
|
});
|
448
463
|
process.exit(0);
|
449
464
|
};
|
450
|
-
process.on(
|
465
|
+
process.on("uncaughtException", (e) => {
|
451
466
|
console.log(e);
|
452
467
|
});
|
453
|
-
process.on(
|
468
|
+
process.on("unhandledRejection", (e) => {
|
454
469
|
console.log(e);
|
455
470
|
});
|
456
|
-
process.on(
|
457
|
-
process.on(
|
471
|
+
process.on("SIGTERM", term);
|
472
|
+
process.on("SIGINT", term);
|
458
473
|
await server.start();
|
459
474
|
}
|
460
475
|
}
|
@@ -1,12 +1,12 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
const JWE = require(
|
3
|
+
const JWE = require("./index");
|
4
4
|
const main = async () => {
|
5
5
|
const jwe = new JWE({});
|
6
6
|
await jwe.newPair();
|
7
|
-
console.log(
|
7
|
+
console.log("private key");
|
8
8
|
console.log(await jwe.exportPrivateAsBase64());
|
9
|
-
console.log(
|
9
|
+
console.log("public key");
|
10
10
|
console.log(await jwe.exportPublicAsBase64());
|
11
11
|
};
|
12
12
|
setTimeout(() => null, 100);
|
@@ -1,9 +1,9 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
const jose = require(
|
3
|
+
const jose = require("jose");
|
4
4
|
class JWE {
|
5
|
-
constructor({ algorithm =
|
6
|
-
this.issuer =
|
5
|
+
constructor({ algorithm = "PS256" }) {
|
6
|
+
this.issuer = "home.aloma.io";
|
7
7
|
this.algorithm = algorithm;
|
8
8
|
}
|
9
9
|
async newPair() {
|
@@ -17,11 +17,11 @@ class JWE {
|
|
17
17
|
}
|
18
18
|
async exportPrivateAsBase64() {
|
19
19
|
const pair = await this.exportPair();
|
20
|
-
return Buffer.from(pair.privateKey).toString(
|
20
|
+
return Buffer.from(pair.privateKey).toString("base64");
|
21
21
|
}
|
22
22
|
async exportPublicAsBase64() {
|
23
23
|
const pair = await this.exportPair();
|
24
|
-
return Buffer.from(pair.publicKey).toString(
|
24
|
+
return Buffer.from(pair.publicKey).toString("base64");
|
25
25
|
}
|
26
26
|
async importPair({ publicKey, privateKey, algorithm }) {
|
27
27
|
this.pair = {
|
@@ -31,18 +31,18 @@ class JWE {
|
|
31
31
|
}
|
32
32
|
async importBase64Pair({ publicKey, privateKey, algorithm }) {
|
33
33
|
this.importPair({
|
34
|
-
publicKey: Buffer.from(publicKey,
|
35
|
-
privateKey: Buffer.from(privateKey,
|
34
|
+
publicKey: Buffer.from(publicKey, "base64").toString(),
|
35
|
+
privateKey: Buffer.from(privateKey, "base64").toString(),
|
36
36
|
algorithm,
|
37
37
|
});
|
38
38
|
}
|
39
|
-
async encrypt(what, expiration =
|
39
|
+
async encrypt(what, expiration = "7d", audience, algorithm = "RSA-OAEP-256") {
|
40
40
|
const item = new jose.EncryptJWT({ _data: { ...what } })
|
41
|
-
.setProtectedHeader({ alg: algorithm, enc:
|
41
|
+
.setProtectedHeader({ alg: algorithm, enc: "A256GCM" })
|
42
42
|
.setIssuedAt()
|
43
43
|
.setIssuer(this.issuer)
|
44
44
|
.setAudience(audience);
|
45
|
-
if (expiration && expiration !==
|
45
|
+
if (expiration && expiration !== "none")
|
46
46
|
item.setExpirationTime(expiration);
|
47
47
|
return await item.encrypt(this.pair.publicKey);
|
48
48
|
}
|
@@ -1,7 +1,7 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
const C = require(
|
4
|
-
const JWE = require(
|
3
|
+
const C = require("./connection/constants.cjs");
|
4
|
+
const JWE = require("../util/jwe/index.cjs");
|
5
5
|
class Config {
|
6
6
|
constructor({ registrationToken, version, name, id, endpoint, wsEndpoint, privateKey, publicKey, introspect, configSchema, }) {
|
7
7
|
this._token = null;
|
@@ -18,17 +18,17 @@ class Config {
|
|
18
18
|
this._introspect = introspect;
|
19
19
|
this._configSchema = configSchema;
|
20
20
|
if (!registrationToken)
|
21
|
-
throw new Error(
|
21
|
+
throw new Error("empty registration token (set env.REGISTRATION_TOKEN)");
|
22
22
|
if (!endpoint)
|
23
|
-
throw new Error(
|
23
|
+
throw new Error("empty endpoint (set env.DEVICE_ENDPOINT)");
|
24
24
|
if (!wsEndpoint)
|
25
|
-
throw new Error(
|
25
|
+
throw new Error("empty registration token (set env.WEBSOCKET_ENDPOINT)");
|
26
26
|
if (!this._id || !this._version)
|
27
|
-
throw new Error(
|
27
|
+
throw new Error("need connector id and version");
|
28
28
|
}
|
29
29
|
async validateKeys(algorithm) {
|
30
30
|
if (!this._privateKey || !this._publicKey)
|
31
|
-
throw new Error(
|
31
|
+
throw new Error("need private and public key");
|
32
32
|
await this._jwe.importBase64Pair({
|
33
33
|
publicKey: this._publicKey,
|
34
34
|
privateKey: this._privateKey,
|
@@ -1,11 +1,11 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
const AUTHORIZATION =
|
3
|
+
const AUTHORIZATION = "Authorization";
|
4
4
|
module.exports = {
|
5
5
|
augmentRequest: (what, config) => {
|
6
6
|
what.headers = {
|
7
7
|
...what.headers,
|
8
|
-
|
8
|
+
"User-Agent": config.id() + "/" + config.version(),
|
9
9
|
};
|
10
10
|
what.headers[AUTHORIZATION] = `Connector ${config.token()}`;
|
11
11
|
return what;
|
@@ -13,7 +13,7 @@ module.exports = {
|
|
13
13
|
augmentRegistration: (what, config) => {
|
14
14
|
what.headers = {
|
15
15
|
...what.headers,
|
16
|
-
|
16
|
+
"User-Agent": config.id() + "/" + config.version(),
|
17
17
|
};
|
18
18
|
what.headers[AUTHORIZATION] = `Connector ${config.registrationToken()}`;
|
19
19
|
return what;
|
@@ -1,8 +1,8 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
const fetch = require(
|
4
|
-
const { Registration } = require(
|
5
|
-
const C = require(
|
3
|
+
const fetch = require("node-fetch");
|
4
|
+
const { Registration } = require("./registration.cjs");
|
5
|
+
const C = require("./constants.cjs");
|
6
6
|
class Connection {
|
7
7
|
constructor({ config, onStart }) {
|
8
8
|
this.config = config;
|
@@ -11,10 +11,10 @@ class Connection {
|
|
11
11
|
async start() {
|
12
12
|
var local = this, config = local.config;
|
13
13
|
try {
|
14
|
-
const response = await fetch(config.url() +
|
15
|
-
method:
|
14
|
+
const response = await fetch(config.url() + "connect", C.augmentRequest({
|
15
|
+
method: "POST",
|
16
16
|
body: JSON.stringify({}),
|
17
|
-
headers: {
|
17
|
+
headers: { "Content-Type": "application/json" },
|
18
18
|
}, config));
|
19
19
|
if (response.status === 401) {
|
20
20
|
config.setToken(await new Registration(local.config).run());
|
@@ -39,10 +39,10 @@ class Connection {
|
|
39
39
|
}
|
40
40
|
async close() {
|
41
41
|
try {
|
42
|
-
await fetch(this.config.url() +
|
43
|
-
method:
|
42
|
+
await fetch(this.config.url() + "disconnect", C.augmentRequest({
|
43
|
+
method: "POST",
|
44
44
|
body: JSON.stringify({}),
|
45
|
-
headers: {
|
45
|
+
headers: { "Content-Type": "application/json" },
|
46
46
|
}, this.config));
|
47
47
|
}
|
48
48
|
catch (e) {
|
@@ -1,7 +1,7 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
const fetch = require(
|
4
|
-
const C = require(
|
3
|
+
const fetch = require("node-fetch");
|
4
|
+
const C = require("./constants.cjs");
|
5
5
|
class Registration {
|
6
6
|
constructor(config) {
|
7
7
|
this.config = config;
|
@@ -11,21 +11,21 @@ class Registration {
|
|
11
11
|
const config = this.config;
|
12
12
|
const configSchema = config.configSchema();
|
13
13
|
const intro = await config.introspect();
|
14
|
-
const response = await fetch(config.url() +
|
15
|
-
method:
|
14
|
+
const response = await fetch(config.url() + "register", C.augmentRegistration({
|
15
|
+
method: "POST",
|
16
16
|
body: JSON.stringify({
|
17
|
-
deployment: process.env.DEPLOYMENT ||
|
17
|
+
deployment: process.env.DEPLOYMENT || "",
|
18
18
|
name: config.name(),
|
19
19
|
version: config.version(),
|
20
20
|
id: config.id(),
|
21
21
|
publicKey: config.publicKey(),
|
22
22
|
schema: { configSchema, introspect: intro },
|
23
23
|
}),
|
24
|
-
headers: {
|
24
|
+
headers: { "Content-Type": "application/json" },
|
25
25
|
}, config));
|
26
26
|
if (response.status === 200)
|
27
27
|
return (await response.json()).key;
|
28
|
-
throw new Error(
|
28
|
+
throw new Error("authentication failed");
|
29
29
|
}
|
30
30
|
}
|
31
31
|
module.exports = { Registration };
|
@@ -1,8 +1,8 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
const WebSocket = require(
|
4
|
-
const { Connection } = require(
|
5
|
-
const { Transport } = require(
|
3
|
+
const WebSocket = require("ws");
|
4
|
+
const { Connection } = require("./connection/index.cjs");
|
5
|
+
const { Transport } = require("./transport/index.cjs");
|
6
6
|
class WebsocketConnector {
|
7
7
|
constructor({ config, onMessage, onConnect }) {
|
8
8
|
var local = this;
|
@@ -1,6 +1,6 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
const WebSocket = require(
|
3
|
+
const WebSocket = require("ws");
|
4
4
|
class DurableWebsocket {
|
5
5
|
constructor({ endpoint, secret, onConnect, onMessage }) {
|
6
6
|
this.endpoint = endpoint;
|
@@ -28,7 +28,7 @@ class DurableWebsocket {
|
|
28
28
|
rejectUnauthorized: false,
|
29
29
|
headers: { Authorization: `Bearer ${local.secret}` },
|
30
30
|
}));
|
31
|
-
ws.on(
|
31
|
+
ws.on("open", () => {
|
32
32
|
local.connecting = false;
|
33
33
|
local.fails = 0;
|
34
34
|
var item;
|
@@ -37,15 +37,15 @@ class DurableWebsocket {
|
|
37
37
|
}
|
38
38
|
local.onConnect(local);
|
39
39
|
});
|
40
|
-
ws.on(
|
40
|
+
ws.on("message", (message) => {
|
41
41
|
setImmediate(() => local.onMessage(JSON.parse(message)));
|
42
42
|
});
|
43
|
-
ws.on(
|
43
|
+
ws.on("error", (message) => {
|
44
44
|
if (local.fails > 50)
|
45
|
-
console.log(
|
45
|
+
console.log("error:", message.message);
|
46
46
|
++local.fails;
|
47
47
|
});
|
48
|
-
ws.on(
|
48
|
+
ws.on("close", (message) => {
|
49
49
|
local.connecting = false;
|
50
50
|
if (!local.closed)
|
51
51
|
setTimeout(() => local.start(), 5000);
|
@@ -1,11 +1,11 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
const fetch = require(
|
4
|
-
const C = require(
|
5
|
-
const cuid = require(
|
6
|
-
const { DurableWebsocket } = require(
|
7
|
-
const WebSocket = require(
|
8
|
-
const { Packet, Callback } = require(
|
3
|
+
const fetch = require("node-fetch");
|
4
|
+
const C = require("../connection/constants.cjs");
|
5
|
+
const cuid = require("@paralleldrive/cuid2").init({ length: 32 });
|
6
|
+
const { DurableWebsocket } = require("./durable.cjs");
|
7
|
+
const WebSocket = require("ws");
|
8
|
+
const { Packet, Callback } = require("./packet.cjs");
|
9
9
|
const cleanInterval = 45 * 1000;
|
10
10
|
const pingInterval = 30 * 1000;
|
11
11
|
class Transport {
|
@@ -38,7 +38,7 @@ class Transport {
|
|
38
38
|
local.ws.send(JSON.stringify({ p: packets }));
|
39
39
|
}
|
40
40
|
catch (e) {
|
41
|
-
console.log(
|
41
|
+
console.log("could not send packets ", e);
|
42
42
|
packets.forEach((packet) => local.packets.unshift(packet));
|
43
43
|
}
|
44
44
|
}
|
@@ -48,20 +48,20 @@ class Transport {
|
|
48
48
|
return;
|
49
49
|
local.close();
|
50
50
|
this.running = true;
|
51
|
-
const ws = (local.ws = new WebSocket(config.wsUrl(), [
|
52
|
-
ws.on(
|
53
|
-
console.log(
|
51
|
+
const ws = (local.ws = new WebSocket(config.wsUrl(), ["connector"], C.augmentRequest({ headers: {} }, config)));
|
52
|
+
ws.on("open", () => {
|
53
|
+
console.log("websocket connected");
|
54
54
|
local.connected = true;
|
55
55
|
local.pinger = setInterval(() => ws.ping(() => null), pingInterval);
|
56
56
|
local.onConnect(local);
|
57
57
|
});
|
58
|
-
ws.on(
|
58
|
+
ws.on("message", (message) => {
|
59
59
|
setTimeout(() => local.onMessages(JSON.parse(message)), 0);
|
60
60
|
});
|
61
|
-
ws.on(
|
62
|
-
console.log(
|
61
|
+
ws.on("error", (message) => {
|
62
|
+
console.log("error:", message);
|
63
63
|
});
|
64
|
-
ws.on(
|
64
|
+
ws.on("close", (message) => {
|
65
65
|
local.connected = false;
|
66
66
|
clearInterval(local.pinger);
|
67
67
|
if (local.running)
|
@@ -92,7 +92,7 @@ class Transport {
|
|
92
92
|
this.callbacks[packet.cb()].cb(packet.args());
|
93
93
|
}
|
94
94
|
catch (e) {
|
95
|
-
console.log(
|
95
|
+
console.log("error processing packet", e, packet);
|
96
96
|
}
|
97
97
|
finally {
|
98
98
|
delete this.callbacks[packet.cb()];
|
@@ -117,12 +117,12 @@ class Transport {
|
|
117
117
|
if (!cb)
|
118
118
|
return;
|
119
119
|
if (cb.created < then) {
|
120
|
-
console.log(
|
120
|
+
console.log("callback timeout", key);
|
121
121
|
try {
|
122
|
-
cb.cb({ error:
|
122
|
+
cb.cb({ error: "timeout" });
|
123
123
|
}
|
124
124
|
catch (e) {
|
125
|
-
console.log(
|
125
|
+
console.log("error while callback", key, cb, e);
|
126
126
|
}
|
127
127
|
delete local.callbacks[key];
|
128
128
|
}
|
@@ -1,7 +1,7 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
const fetch = require(
|
4
|
-
const cuid = require(
|
3
|
+
const fetch = require("node-fetch");
|
4
|
+
const cuid = require("@paralleldrive/cuid2").init({ length: 32 });
|
5
5
|
class Packet {
|
6
6
|
constructor(data = {}) {
|
7
7
|
this.data = data;
|
@@ -1,6 +1,6 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
const { Packet, Callback } = require(
|
3
|
+
const { Packet, Callback } = require("./packet.cjs");
|
4
4
|
class Processor {
|
5
5
|
constructor({ transport, processPacket }) {
|
6
6
|
var local = this;
|
@@ -33,24 +33,24 @@ class Processor {
|
|
33
33
|
callbacks[packet.cb()](packet.args());
|
34
34
|
}
|
35
35
|
catch (e) {
|
36
|
-
console.log(
|
36
|
+
console.log("error in callback", callbacks[packet.cb()], packet);
|
37
37
|
}
|
38
38
|
delete local.transport.callbacks[packet.cb()];
|
39
39
|
}
|
40
40
|
else if (packet.event()) {
|
41
|
-
console.log(
|
41
|
+
console.log("handle event packet", packet);
|
42
42
|
}
|
43
43
|
else {
|
44
44
|
try {
|
45
45
|
const result = await local._processPacket(packet);
|
46
46
|
const reply = local.transport.newPacket({});
|
47
|
-
reply.method(
|
47
|
+
reply.method("connector.reply");
|
48
48
|
reply.cb(original.cb());
|
49
49
|
reply.args({ ...result });
|
50
50
|
local.transport.send(reply);
|
51
51
|
}
|
52
52
|
catch (e) {
|
53
|
-
console.log(
|
53
|
+
console.log("error processing packet", e, packet);
|
54
54
|
}
|
55
55
|
}
|
56
56
|
}
|