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