@aloma.io/integration-sdk 3.0.0-4
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 +11 -0
- package/build/builder/index.mjs +51 -0
- package/build/builder/runtime-context.d.mts +7 -0
- package/build/builder/runtime-context.mjs +42 -0
- package/build/builder/transform/index.d.mts +5 -0
- package/build/builder/transform/index.mjs +72 -0
- package/build/controller/index.d.mts +19 -0
- package/build/controller/index.mjs +44 -0
- package/build/index.d.mts +2 -0
- package/build/index.mjs +2 -0
- package/build/internal/dispatcher/index.cjs +151 -0
- package/build/internal/dispatcher/index.d.cts +32 -0
- package/build/internal/index.cjs +461 -0
- package/build/internal/index.d.cts +14 -0
- package/build/internal/util/jwe/cli.cjs +13 -0
- package/build/internal/util/jwe/cli.d.cts +1 -0
- package/build/internal/util/jwe/index.cjs +57 -0
- package/build/internal/util/jwe/index.d.cts +32 -0
- package/build/internal/websocket/config.cjs +79 -0
- package/build/internal/websocket/config.d.cts +41 -0
- package/build/internal/websocket/connection/constants.cjs +21 -0
- package/build/internal/websocket/connection/constants.d.cts +2 -0
- package/build/internal/websocket/connection/index.cjs +53 -0
- package/build/internal/websocket/connection/index.d.cts +11 -0
- package/build/internal/websocket/connection/registration.cjs +31 -0
- package/build/internal/websocket/connection/registration.d.cts +5 -0
- package/build/internal/websocket/index.cjs +41 -0
- package/build/internal/websocket/index.d.cts +16 -0
- package/build/internal/websocket/transport/durable.cjs +61 -0
- package/build/internal/websocket/transport/durable.d.cts +20 -0
- package/build/internal/websocket/transport/index.cjs +148 -0
- package/build/internal/websocket/transport/index.d.cts +37 -0
- package/build/internal/websocket/transport/packet.cjs +44 -0
- package/build/internal/websocket/transport/packet.d.cts +16 -0
- package/build/internal/websocket/transport/processor.cjs +58 -0
- package/build/internal/websocket/transport/processor.d.cts +11 -0
- package/package.json +44 -0
- package/src/builder/index.mts +70 -0
- package/src/builder/runtime-context.mts +45 -0
- package/src/builder/transform/index.mts +89 -0
- package/src/controller/index.mts +58 -0
- package/src/index.mts +2 -0
- package/src/internal/dispatcher/index.cjs +189 -0
- package/src/internal/index.cjs +547 -0
- package/src/internal/util/jwe/cli.cjs +14 -0
- package/src/internal/util/jwe/index.cjs +69 -0
- package/src/internal/websocket/config.cjs +103 -0
- package/src/internal/websocket/connection/constants.cjs +25 -0
- package/src/internal/websocket/connection/index.cjs +70 -0
- package/src/internal/websocket/connection/registration.cjs +40 -0
- package/src/internal/websocket/index.cjs +46 -0
- package/src/internal/websocket/transport/durable.cjs +71 -0
- package/src/internal/websocket/transport/index.cjs +183 -0
- package/src/internal/websocket/transport/packet.cjs +54 -0
- package/src/internal/websocket/transport/processor.cjs +66 -0
- package/tsconfig.json +27 -0
@@ -0,0 +1,70 @@
|
|
1
|
+
import fs from '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
|
+
|
7
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
8
|
+
|
9
|
+
const notEmpty = (what, name) => {
|
10
|
+
if (!what?.trim()) throw new Error(`${name} cannot be empty`);
|
11
|
+
|
12
|
+
return what;
|
13
|
+
};
|
14
|
+
|
15
|
+
export class Builder {
|
16
|
+
private data: any = {controller: './build/controller/.controller-for-types.mts'};
|
17
|
+
|
18
|
+
id(what: string): Builder {
|
19
|
+
this.data.id = notEmpty(what, 'id');
|
20
|
+
|
21
|
+
return this;
|
22
|
+
}
|
23
|
+
|
24
|
+
version(what: string): Builder {
|
25
|
+
this.data.version = notEmpty(what, 'version');
|
26
|
+
|
27
|
+
return this;
|
28
|
+
}
|
29
|
+
|
30
|
+
config(arg: any): Builder {
|
31
|
+
return this;
|
32
|
+
}
|
33
|
+
|
34
|
+
options(arg: any): Builder {
|
35
|
+
return this;
|
36
|
+
}
|
37
|
+
|
38
|
+
auth(arg: any): Builder {
|
39
|
+
return this;
|
40
|
+
}
|
41
|
+
|
42
|
+
async build(): Promise<RuntimeContext> {
|
43
|
+
const data = this.data;
|
44
|
+
|
45
|
+
notEmpty(data.id, 'id');
|
46
|
+
notEmpty(data.version, 'version');
|
47
|
+
|
48
|
+
await this.discoverTypes();
|
49
|
+
|
50
|
+
// validate config
|
51
|
+
// validate options
|
52
|
+
// validate auth
|
53
|
+
|
54
|
+
console.log('dirname', __dirname);
|
55
|
+
// @ts-ignore
|
56
|
+
const Controller = (await import(__dirname + '/../../../../../build/controller/index.mjs')).default;
|
57
|
+
|
58
|
+
return new RuntimeContext(new Controller(), this.data);
|
59
|
+
}
|
60
|
+
|
61
|
+
private async discoverTypes() {
|
62
|
+
notEmpty(this.data.controller, 'controller');
|
63
|
+
|
64
|
+
const content = fs.readFileSync(this.data.controller);
|
65
|
+
const {text, methods} = parseTypes(this.data.controller);
|
66
|
+
|
67
|
+
this.data.types = text;
|
68
|
+
this.data.methods = methods;
|
69
|
+
}
|
70
|
+
}
|
@@ -0,0 +1,45 @@
|
|
1
|
+
import {AbstractController} from '../controller/index.mjs';
|
2
|
+
import {Connector} from '../internal/index.cjs';
|
3
|
+
|
4
|
+
export default class RuntimeContext {
|
5
|
+
constructor(private controller: AbstractController, private data: any) {}
|
6
|
+
|
7
|
+
async start(): Promise<void> {
|
8
|
+
const controller = this.controller;
|
9
|
+
|
10
|
+
const connector = new Connector({
|
11
|
+
id: this.data.id,
|
12
|
+
version: this.data.version,
|
13
|
+
name: `${this.data.id}/${this.data.version}`,
|
14
|
+
});
|
15
|
+
|
16
|
+
const resolvers: any = {};
|
17
|
+
const methods: string[] = [...this.data.methods, '__endpoint', '__configQuery', '__default'];
|
18
|
+
|
19
|
+
methods.forEach((method) => {
|
20
|
+
resolvers[method] = async (args) => {
|
21
|
+
console.log('call', method, args);
|
22
|
+
if (!methods.includes(method)) throw new Error(`${method} not found`);
|
23
|
+
|
24
|
+
return controller[method](args);
|
25
|
+
};
|
26
|
+
});
|
27
|
+
|
28
|
+
console.log(this.data.types);
|
29
|
+
|
30
|
+
connector
|
31
|
+
.configure()
|
32
|
+
.types(this.data.types)
|
33
|
+
.resolvers(resolvers)
|
34
|
+
.main(async ({newTask, updateTask, config, oauth, getClient}) => {
|
35
|
+
try {
|
36
|
+
await controller._doStop();
|
37
|
+
await controller._doStart(config, oauth, newTask, updateTask, getClient);
|
38
|
+
} catch (e) {
|
39
|
+
console.log(e);
|
40
|
+
}
|
41
|
+
});
|
42
|
+
|
43
|
+
connector.run();
|
44
|
+
}
|
45
|
+
}
|
@@ -0,0 +1,89 @@
|
|
1
|
+
import {parseFromFiles} from '@ts-ast-parser/core';
|
2
|
+
|
3
|
+
const transform = (meta: any) => {
|
4
|
+
if (!meta?.length) throw new Error('metadata is empty');
|
5
|
+
meta = meta[0];
|
6
|
+
|
7
|
+
if (meta.getDeclarations()?.length !== 1) {
|
8
|
+
throw new Error('connector file needs to export default class');
|
9
|
+
}
|
10
|
+
|
11
|
+
const methods = {};
|
12
|
+
const decl = meta.getDeclarations()[0];
|
13
|
+
|
14
|
+
// todo validate getConstructors
|
15
|
+
|
16
|
+
const members = decl.getMethods().filter((member: any) => {
|
17
|
+
return !(
|
18
|
+
member.isStatic() ||
|
19
|
+
member.isInherited() ||
|
20
|
+
member.getKind() !== 'Method' ||
|
21
|
+
member.getModifier() !== 'public' ||
|
22
|
+
member.getName().startsWith('_')
|
23
|
+
);
|
24
|
+
});
|
25
|
+
|
26
|
+
const text = members
|
27
|
+
.map((member: any) => {
|
28
|
+
methods[member.getName()] = true;
|
29
|
+
|
30
|
+
return member
|
31
|
+
.getSignatures()
|
32
|
+
.map((sig: any) => {
|
33
|
+
const docs = sig.getJSDoc().serialize() || [];
|
34
|
+
const desc = docs.find((what: any) => what.kind === 'description')?.value;
|
35
|
+
|
36
|
+
const paramDocs =
|
37
|
+
docs
|
38
|
+
.filter((what: any) => what.kind === 'param')
|
39
|
+
.map((what: any) => {
|
40
|
+
return ` * @param {${what.value.type}} ${what.value.name} - ${what.value.description || ''}`;
|
41
|
+
})
|
42
|
+
.join('\n') || ' *';
|
43
|
+
|
44
|
+
const params = sig
|
45
|
+
.getParameters()
|
46
|
+
.map((param: any) => {
|
47
|
+
const serialized = param.serialize();
|
48
|
+
|
49
|
+
switch (!!param.isNamed()) {
|
50
|
+
case true:
|
51
|
+
const tmp = param
|
52
|
+
.getNamedElements()
|
53
|
+
.map((p) => {
|
54
|
+
const defaultVal = p.default != null ? ' = ' + p.default : '';
|
55
|
+
|
56
|
+
return `${p.name}${defaultVal}`;
|
57
|
+
})
|
58
|
+
.join('; ');
|
59
|
+
return `{${tmp}}: ${param.getType().text}`;
|
60
|
+
case false:
|
61
|
+
return `${param.getName()}: ${param.getType().text}`;
|
62
|
+
}
|
63
|
+
})
|
64
|
+
.join(', ');
|
65
|
+
|
66
|
+
const retVal = sig
|
67
|
+
.getReturnType()
|
68
|
+
.type.text.replace(/^Promise</, '')
|
69
|
+
.replace(/>$/, '');
|
70
|
+
|
71
|
+
return `
|
72
|
+
/**
|
73
|
+
* ${desc || ''}
|
74
|
+
*
|
75
|
+
${paramDocs}
|
76
|
+
**/
|
77
|
+
declare function ${member.getName()}(${params}): ${retVal};
|
78
|
+
`;
|
79
|
+
})
|
80
|
+
.join('\n');
|
81
|
+
})
|
82
|
+
.join('');
|
83
|
+
|
84
|
+
return {text, methods: Object.keys(methods)};
|
85
|
+
};
|
86
|
+
|
87
|
+
export default (path: string) => {
|
88
|
+
return transform(parseFromFiles([path]));
|
89
|
+
};
|
@@ -0,0 +1,58 @@
|
|
1
|
+
export abstract class AbstractController {
|
2
|
+
protected config;
|
3
|
+
protected client;
|
4
|
+
|
5
|
+
protected async start(): Promise<void> {}
|
6
|
+
|
7
|
+
protected async stop(): Promise<void> {}
|
8
|
+
|
9
|
+
protected configQuery(arg: any): Promise<any> {
|
10
|
+
return Promise.resolve({});
|
11
|
+
}
|
12
|
+
|
13
|
+
protected fallback(arg: any): Promise<any> {
|
14
|
+
throw new Error('method not found');
|
15
|
+
}
|
16
|
+
|
17
|
+
protected endpoint(arg: any): Promise<any> {
|
18
|
+
throw new Error('method not found');
|
19
|
+
}
|
20
|
+
|
21
|
+
protected async newTask(name: string, data: any): Promise<string> {
|
22
|
+
throw new Error('not implemented');
|
23
|
+
}
|
24
|
+
|
25
|
+
protected getClient({baseUrl}: {baseUrl: string}): Promise<any> {
|
26
|
+
throw new Error('not implemented');
|
27
|
+
}
|
28
|
+
|
29
|
+
protected async updateTask(name: string, data: any): Promise<string> {
|
30
|
+
throw new Error('not implemented');
|
31
|
+
}
|
32
|
+
|
33
|
+
async __endpoint(arg: any): Promise<any | null> {
|
34
|
+
return Promise.resolve(null);
|
35
|
+
}
|
36
|
+
|
37
|
+
async __configQuery(arg: any): Promise<any | null> {
|
38
|
+
return this.configQuery(arg);
|
39
|
+
}
|
40
|
+
|
41
|
+
async __default(arg: any): Promise<any | null> {
|
42
|
+
return this.fallback(arg);
|
43
|
+
}
|
44
|
+
|
45
|
+
async _doStart(config: any, client: any, newTask: any, updateTask: any, getClient: any): Promise<void> {
|
46
|
+
this.config = config;
|
47
|
+
this.client = client;
|
48
|
+
this.newTask = newTask;
|
49
|
+
this.updateTask = updateTask;
|
50
|
+
this.getClient = getClient;
|
51
|
+
|
52
|
+
await this.start();
|
53
|
+
}
|
54
|
+
|
55
|
+
async _doStop(): Promise<void> {
|
56
|
+
await this.stop();
|
57
|
+
}
|
58
|
+
}
|
package/src/index.mts
ADDED
@@ -0,0 +1,189 @@
|
|
1
|
+
class Dispatcher {
|
2
|
+
constructor() {
|
3
|
+
this._config = {fields: {}};
|
4
|
+
}
|
5
|
+
|
6
|
+
main(what) {
|
7
|
+
this._main = what;
|
8
|
+
|
9
|
+
return this;
|
10
|
+
}
|
11
|
+
|
12
|
+
oauth(arg) {
|
13
|
+
if (arg.platformOAuth) {
|
14
|
+
this.config({
|
15
|
+
oauth: true,
|
16
|
+
fields: {
|
17
|
+
oauthResult: {
|
18
|
+
name: 'OAuth Result',
|
19
|
+
placeholder: 'will be set by finishing the oauth flow',
|
20
|
+
type: 'managed',
|
21
|
+
},
|
22
|
+
},
|
23
|
+
});
|
24
|
+
|
25
|
+
return this;
|
26
|
+
}
|
27
|
+
|
28
|
+
if (!arg.authorizationURL) throw new Error('need a authorizationURL');
|
29
|
+
if (!arg.tokenURL && !arg.finishOAuth) throw new Error('need a tokenURL or finishOAuth()');
|
30
|
+
|
31
|
+
this._oauth = {...arg};
|
32
|
+
|
33
|
+
this.config({
|
34
|
+
oauth: true,
|
35
|
+
fields: {
|
36
|
+
oauthResult: {
|
37
|
+
name: 'OAuth Result',
|
38
|
+
placeholder: 'will be set by finishing the oauth flow',
|
39
|
+
type: 'managed',
|
40
|
+
},
|
41
|
+
},
|
42
|
+
});
|
43
|
+
|
44
|
+
if (arg.configurableClient) {
|
45
|
+
this.config({
|
46
|
+
fields: {
|
47
|
+
clientId: {
|
48
|
+
name: 'OAuth Client ID',
|
49
|
+
placeholder: 'e.g. 1234',
|
50
|
+
type: 'line',
|
51
|
+
},
|
52
|
+
clientSecret: {
|
53
|
+
name: 'OAuth Client Secret',
|
54
|
+
placeholder: 'e.g. axd5xde',
|
55
|
+
type: 'line',
|
56
|
+
},
|
57
|
+
},
|
58
|
+
});
|
59
|
+
}
|
60
|
+
|
61
|
+
return this;
|
62
|
+
}
|
63
|
+
|
64
|
+
types(what) {
|
65
|
+
this._types = what;
|
66
|
+
|
67
|
+
return this;
|
68
|
+
}
|
69
|
+
|
70
|
+
config({fields, oauth}) {
|
71
|
+
this._config.oauth = this._config.oauth || oauth;
|
72
|
+
this._config.fields = {...fields, ...this._config.fields};
|
73
|
+
|
74
|
+
return this;
|
75
|
+
}
|
76
|
+
|
77
|
+
resolvers(what) {
|
78
|
+
this._resolvers = {...this._resolvers, ...what};
|
79
|
+
|
80
|
+
return this;
|
81
|
+
}
|
82
|
+
|
83
|
+
endpoint(what) {
|
84
|
+
this.config({
|
85
|
+
fields: {
|
86
|
+
_endpointToken: {
|
87
|
+
name: 'Endpoint Token (set to enable the endpoint)',
|
88
|
+
placeholder: 'e.g. 1234',
|
89
|
+
type: 'line',
|
90
|
+
plain: true,
|
91
|
+
optional: true,
|
92
|
+
},
|
93
|
+
},
|
94
|
+
});
|
95
|
+
|
96
|
+
this.resolvers({_endpoint: what});
|
97
|
+
|
98
|
+
return this;
|
99
|
+
}
|
100
|
+
|
101
|
+
startOAuth() {
|
102
|
+
throw new Error('oauth not configured');
|
103
|
+
}
|
104
|
+
|
105
|
+
finishOAuth() {
|
106
|
+
throw new Error('oauth not configured');
|
107
|
+
}
|
108
|
+
|
109
|
+
build() {
|
110
|
+
if (!this._types || !this._resolvers) throw new Error('missing types or resolvers');
|
111
|
+
var local = this;
|
112
|
+
|
113
|
+
const _resolvers = {...this._resolvers};
|
114
|
+
|
115
|
+
const main = this._main || (() => {});
|
116
|
+
|
117
|
+
const start = async (transport) => {
|
118
|
+
console.log('starting ...');
|
119
|
+
await main(transport);
|
120
|
+
};
|
121
|
+
|
122
|
+
const resolveMethod = (query) => {
|
123
|
+
let current = _resolvers;
|
124
|
+
|
125
|
+
while (query.length && current) {
|
126
|
+
current = current[query.shift()];
|
127
|
+
}
|
128
|
+
|
129
|
+
return current;
|
130
|
+
};
|
131
|
+
|
132
|
+
const execute = async ({query, variables}) => {
|
133
|
+
if (!Array.isArray(query)) query = [query];
|
134
|
+
|
135
|
+
query = query
|
136
|
+
.filter(
|
137
|
+
(what) => !!what?.trim() && !['constructor', '__proto__', 'toString', 'toSource', 'prototype'].includes(what)
|
138
|
+
)
|
139
|
+
.slice(0, 20);
|
140
|
+
|
141
|
+
const method = resolveMethod(query);
|
142
|
+
console.log('found method', query, method);
|
143
|
+
if (!method && !_resolvers.__default) throw new Error(`${query} not found`);
|
144
|
+
|
145
|
+
return method ? method(variables) : _resolvers.__default(variables ? {...variables, __method: query} : variables);
|
146
|
+
};
|
147
|
+
|
148
|
+
const introspect = () => local._types;
|
149
|
+
const configSchema = () => local._config;
|
150
|
+
|
151
|
+
const processPacket = async (packet) => {
|
152
|
+
switch (packet.method()) {
|
153
|
+
case 'connector.introspect':
|
154
|
+
const intro = await introspect({});
|
155
|
+
|
156
|
+
return {configSchema: local._config, introspect: intro};
|
157
|
+
|
158
|
+
case 'connector.start-oauth':
|
159
|
+
return await local.startOAuth(packet.args());
|
160
|
+
|
161
|
+
case 'connector.finish-oauth':
|
162
|
+
return await local.finishOAuth(packet.args());
|
163
|
+
|
164
|
+
case 'connector.query':
|
165
|
+
const ret = await execute(packet.args());
|
166
|
+
|
167
|
+
return typeof ret === 'object' && !Array.isArray(ret) ? ret : {[packet.args().query]: ret};
|
168
|
+
|
169
|
+
case 'connector.set-config':
|
170
|
+
await local.onConfig({...packet.args().secrets});
|
171
|
+
|
172
|
+
return;
|
173
|
+
}
|
174
|
+
|
175
|
+
console.dir(packet, {depth: null});
|
176
|
+
throw new Error('cannot handle packet');
|
177
|
+
};
|
178
|
+
|
179
|
+
return {
|
180
|
+
introspect,
|
181
|
+
configSchema,
|
182
|
+
execute,
|
183
|
+
processPacket,
|
184
|
+
start,
|
185
|
+
};
|
186
|
+
}
|
187
|
+
}
|
188
|
+
|
189
|
+
module.exports = {Dispatcher};
|