@aloma.io/integration-sdk 3.0.0-4 → 3.0.0-6

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 ADDED
@@ -0,0 +1,9 @@
1
+ # nodejs - Aloma Integration SDK
2
+
3
+ ## Prerequisites
4
+
5
+ * You can find the `REGISTRATION_TOKEN` in your aloma workspace in the integration section.
6
+
7
+ ## Integration Examples
8
+
9
+ See `examples` directory.
@@ -1,8 +1,6 @@
1
1
  import RuntimeContext from './runtime-context.mjs';
2
2
  export declare class Builder {
3
3
  private data;
4
- id(what: string): Builder;
5
- version(what: string): Builder;
6
4
  config(arg: any): Builder;
7
5
  options(arg: any): Builder;
8
6
  auth(arg: any): Builder;
@@ -1,4 +1,4 @@
1
- import fs from 'fs';
1
+ import fs from 'node:fs';
2
2
  import parseTypes from './transform/index.mjs';
3
3
  import RuntimeContext from './runtime-context.mjs';
4
4
  import { fileURLToPath } from 'node:url';
@@ -11,18 +11,11 @@ const notEmpty = (what, name) => {
11
11
  };
12
12
  export class Builder {
13
13
  data = { controller: './build/controller/.controller-for-types.mts' };
14
- id(what) {
15
- this.data.id = notEmpty(what, 'id');
16
- return this;
17
- }
18
- version(what) {
19
- this.data.version = notEmpty(what, 'version');
20
- return this;
21
- }
22
14
  config(arg) {
23
15
  return this;
24
16
  }
25
17
  options(arg) {
18
+ this.data.options = arg;
26
19
  return this;
27
20
  }
28
21
  auth(arg) {
@@ -30,13 +23,13 @@ export class Builder {
30
23
  }
31
24
  async build() {
32
25
  const data = this.data;
33
- notEmpty(data.id, 'id');
34
- notEmpty(data.version, 'version');
35
26
  await this.discoverTypes();
36
27
  // validate config
37
28
  // validate options
38
29
  // validate auth
39
- console.log('dirname', __dirname);
30
+ const packageJson = JSON.parse(fs.readFileSync(__dirname + '/../../../../../package.json', { encoding: 'utf-8' }));
31
+ notEmpty(data.id = packageJson.connectorId, 'id');
32
+ notEmpty(data.version = packageJson.version, 'version');
40
33
  // @ts-ignore
41
34
  const Controller = (await import(__dirname + '/../../../../../build/controller/index.mjs')).default;
42
35
  return new RuntimeContext(new Controller(), this.data);
@@ -1,3 +1,4 @@
1
+ import { AbstractController } from '../controller/index.mjs';
1
2
  import { Connector } from '../internal/index.cjs';
2
3
  export default class RuntimeContext {
3
4
  controller;
@@ -8,13 +9,17 @@ export default class RuntimeContext {
8
9
  }
9
10
  async start() {
10
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;
11
15
  const connector = new Connector({
12
- id: this.data.id,
13
- version: this.data.version,
14
- name: `${this.data.id}/${this.data.version}`,
16
+ id: data.id,
17
+ version: data.version,
18
+ name: `${data.id}/${data.version}`,
15
19
  });
20
+ const configuration = connector.configure();
16
21
  const resolvers = {};
17
- const methods = [...this.data.methods, '__endpoint', '__configQuery', '__default'];
22
+ const methods = [...data.methods, '__endpoint', '__configQuery', '__default'];
18
23
  methods.forEach((method) => {
19
24
  resolvers[method] = async (args) => {
20
25
  console.log('call', method, args);
@@ -23,12 +28,11 @@ export default class RuntimeContext {
23
28
  return controller[method](args);
24
29
  };
25
30
  });
26
- console.log(this.data.types);
27
- connector
28
- .configure()
29
- .types(this.data.types)
30
- .resolvers(resolvers)
31
- .main(async ({ newTask, updateTask, config, oauth, getClient }) => {
31
+ configuration.types(data.types).resolvers(resolvers);
32
+ if (data.options?.endpoint) {
33
+ configuration.endpoint((arg) => controller.__endpoint(arg));
34
+ }
35
+ configuration.main(async ({ newTask, updateTask, config, oauth, getClient }) => {
32
36
  try {
33
37
  await controller._doStop();
34
38
  await controller._doStart(config, oauth, newTask, updateTask, getClient);
@@ -22,7 +22,7 @@ export class AbstractController {
22
22
  throw new Error('not implemented');
23
23
  }
24
24
  async __endpoint(arg) {
25
- return Promise.resolve(null);
25
+ return this.endpoint(arg);
26
26
  }
27
27
  async __configQuery(arg) {
28
28
  return this.configQuery(arg);
@@ -0,0 +1,17 @@
1
+ FROM node:16-alpine3.18
2
+
3
+ ENV NODE_ENV production
4
+
5
+ WORKDIR /connector/
6
+
7
+ COPY ./package.json ./
8
+ COPY ./entrypoint.sh ./
9
+ COPY ./src ./src
10
+
11
+ RUN set -e; adduser -S -u 1111 connector
12
+
13
+ RUN set -e; apk add --no-cache git; yarn config set --home enableTelemetry 0; chmod 755 /connector/entrypoint.sh; cd /connector/; yarn install; rm -rf package.json; rm -rf yarn.lock;
14
+
15
+ USER connector
16
+
17
+ ENTRYPOINT ["/connector/entrypoint.sh"]
@@ -0,0 +1,5 @@
1
+ #!/bin/sh -e
2
+
3
+ cd /connector/
4
+
5
+ exec node src/index.js $@
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "hello-world",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "author": "aloma.io",
6
+ "license": "Apache-2.0",
7
+ "scripts": {},
8
+ "dependencies": {
9
+ "@aloma.io/integration-sdk": "^3"
10
+ }
11
+ }
@@ -0,0 +1,14 @@
1
+ class Controller
2
+ {
3
+ setConfig({newTask, config})
4
+ {
5
+ // blank
6
+ }
7
+
8
+ async hello(args)
9
+ {
10
+ return "world";
11
+ }
12
+ }
13
+
14
+ module.exports = {Controller}
@@ -0,0 +1,29 @@
1
+ const {Connector} = require('@aloma-io/integration-sdk');
2
+ const {Controller} = require('./controller');
3
+
4
+ const connector = new Connector({id: 'TODO your connector id', version: '1.0.0'});
5
+ const controller = new Controller();
6
+
7
+ connector.configure()
8
+ // types are the calls available in the step, these are typescript definitions
9
+ .types
10
+ (`
11
+ declare function hello(arg: {}): any;
12
+ `)
13
+ // resolvers hold the calls
14
+ .resolvers
15
+ ({
16
+ hello: async (args) =>
17
+ {
18
+ return controller.hello(args);
19
+ },
20
+ })
21
+ // main will be called once the connector is connected
22
+ .main(({newTask, config}) =>
23
+ {
24
+ // the config might have changed, so the connector should be able to deal with multiple setConfigs over it's lifetime
25
+ controller.setConfig({newTask, config});
26
+ });
27
+
28
+ // start the connector
29
+ connector.run();
@@ -0,0 +1,26 @@
1
+ const {Connector} = require('@aloma-io/integration-sdk');
2
+
3
+ const connector = new Connector({id: 'TODO your connector id', version: '1.0.0'});
4
+
5
+ connector.configure()
6
+ // types are the calls available in the step, these are typescript definitions
7
+ .types
8
+ (`
9
+ declare function hello(arg: {}): any;
10
+ `)
11
+ // resolvers hold the calls
12
+ .resolvers
13
+ ({
14
+ hello: async (args) =>
15
+ {
16
+ return "world";
17
+ },
18
+ })
19
+ // main will be called once the connector is connected
20
+ .main(({newTask, config}) =>
21
+ {
22
+ // the config might have changed, so the connector should be able to deal with multiple setConfigs over it's lifetime
23
+ });
24
+
25
+ // start the connector
26
+ connector.run();
@@ -0,0 +1,54 @@
1
+ const {Connector} = require('@aloma-io/integration-sdk');
2
+
3
+ const connector = new Connector({id: 'TODO your connector id', version: '1.0.0'});
4
+
5
+ connector.configure()
6
+ // these config fields can be configured from the aloma ui. these require a private and a public key which the connector will generate on start
7
+ .config({fields:
8
+ {
9
+ // this is then available from config.type
10
+ type: {
11
+ // name and placeholder for ui configuration
12
+ name: 'Database Type',
13
+ placeholder: 'e.g. mysql, pg, tedious',
14
+ // type
15
+ type: 'line',
16
+ // this is an unencrypted value, by default everything is encrypted
17
+ plain: true
18
+ },
19
+ user: {
20
+ name: 'User',
21
+ placeholder: 'e.g. john',
22
+ type: 'line',
23
+ plain: true,
24
+ // this is marked as optional in the ui, so does not have to be provided, everything else is mandatory
25
+ optional: true
26
+ },
27
+ // this is encrypted in the ui via public key, can only be decrypted by the connector having the private key
28
+ password: {
29
+ name: 'Password',
30
+ placeholder: 'e.g. x3gsadg',
31
+ type: 'line',
32
+ optional: true
33
+ },
34
+
35
+ }})
36
+ .types
37
+ (`
38
+ declare function hello(arg: {}): any;
39
+ `)
40
+ .resolvers
41
+ ({
42
+ hello: async (args) =>
43
+ {
44
+ return "world";
45
+ },
46
+ })
47
+ .main(({newTask, config}) =>
48
+ {
49
+ console.log(config.type)
50
+ console.log(config.password)
51
+ console.log(config.user)
52
+ });
53
+
54
+ connector.run();
@@ -0,0 +1,36 @@
1
+ const {Connector} = require('@aloma-io/integration-sdk');
2
+
3
+ const connector = new Connector({id: 'TODO your connector id', version: '1.0.0'});
4
+
5
+ connector.configure()
6
+ // these require a private and a public key which the connector will generate on start
7
+ // after a connector is added to a workspace it can be connected from the aloma ui
8
+ .oauth
9
+ ({
10
+ // the authorization url, the placeholders {{clientId}}, {{redirectURI}}, {{scope}} will be filled in by aloma
11
+ authorizationURL: 'https://github.com/login/oauth/authorize?client_id={{clientId}}&redirect_uri={{redirectURI}}&scope={{scope}}&allow_signup=false',
12
+ tokenURL: 'https://github.com/login/oauth/access_token',
13
+ clientId: 'clientId',
14
+ clientSecret: 'clientSecret',
15
+ scope: 'repo, user:email'
16
+ })
17
+ .types
18
+ (`
19
+ declare function hello(arg: {}): any;
20
+ `)
21
+ .resolvers
22
+ ({
23
+ hello: async (args) =>
24
+ {
25
+ return "world";
26
+ },
27
+ })
28
+ .main(({newTask, config, oauth}) =>
29
+ {
30
+ // one can access oauth.accessToken()
31
+ // one can get a fetch client: oauth.getClient()
32
+ // the client supports retries and will also do an automatic token refresh if a refresh_token is provided
33
+ // oauth.getClient().fetch({url, options = {method: 'POST', headers: {}, body: ''})
34
+ });
35
+
36
+ connector.run();
package/index.js ADDED
@@ -0,0 +1,3 @@
1
+ const {Connector} = require('./src/')
2
+
3
+ module.exports = {Connector}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aloma.io/integration-sdk",
3
- "version": "3.0.0-4",
3
+ "version": "3.0.0-6",
4
4
  "description": "",
5
5
  "author": "aloma.io",
6
6
  "license": "Apache-2.0",
@@ -1,4 +1,4 @@
1
- import fs from 'fs';
1
+ import fs from 'node:fs';
2
2
  import parseTypes from './transform/index.mjs';
3
3
  import RuntimeContext from './runtime-context.mjs';
4
4
  import {fileURLToPath} from 'node:url';
@@ -15,23 +15,12 @@ const notEmpty = (what, name) => {
15
15
  export class Builder {
16
16
  private data: any = {controller: './build/controller/.controller-for-types.mts'};
17
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
18
  config(arg: any): Builder {
31
19
  return this;
32
20
  }
33
21
 
34
22
  options(arg: any): Builder {
23
+ this.data.options = arg;
35
24
  return this;
36
25
  }
37
26
 
@@ -42,16 +31,18 @@ export class Builder {
42
31
  async build(): Promise<RuntimeContext> {
43
32
  const data = this.data;
44
33
 
45
- notEmpty(data.id, 'id');
46
- notEmpty(data.version, 'version');
47
-
48
34
  await this.discoverTypes();
49
35
 
50
36
  // validate config
51
37
  // validate options
52
38
  // validate auth
53
39
 
54
- console.log('dirname', __dirname);
40
+
41
+ const packageJson = JSON.parse(fs.readFileSync(__dirname + '/../../../../../package.json', {encoding: 'utf-8'}));
42
+
43
+ notEmpty(data.id = packageJson.connectorId, 'id');
44
+ notEmpty(data.version= packageJson.version, 'version');
45
+
55
46
  // @ts-ignore
56
47
  const Controller = (await import(__dirname + '/../../../../../build/controller/index.mjs')).default;
57
48
 
@@ -64,7 +55,7 @@ export class Builder {
64
55
  const content = fs.readFileSync(this.data.controller);
65
56
  const {text, methods} = parseTypes(this.data.controller);
66
57
 
67
- this.data.types = text;
58
+ this.data.types = text;
68
59
  this.data.methods = methods;
69
60
  }
70
61
  }
@@ -6,15 +6,20 @@ export default class RuntimeContext {
6
6
 
7
7
  async start(): Promise<void> {
8
8
  const controller = this.controller;
9
-
9
+
10
+ if (!(controller instanceof AbstractController)) throw new Error('the controller needs to extend AbstractController');
11
+ const data:any = this.data;
12
+
10
13
  const connector = new Connector({
11
- id: this.data.id,
12
- version: this.data.version,
13
- name: `${this.data.id}/${this.data.version}`,
14
+ id: data.id,
15
+ version: data.version,
16
+ name: `${data.id}/${data.version}`,
14
17
  });
15
18
 
19
+ const configuration = connector.configure();
20
+
16
21
  const resolvers: any = {};
17
- const methods: string[] = [...this.data.methods, '__endpoint', '__configQuery', '__default'];
22
+ const methods: string[] = [...data.methods, '__endpoint', '__configQuery', '__default'];
18
23
 
19
24
  methods.forEach((method) => {
20
25
  resolvers[method] = async (args) => {
@@ -24,14 +29,15 @@ export default class RuntimeContext {
24
29
  return controller[method](args);
25
30
  };
26
31
  });
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}) => {
32
+
33
+ configuration.types(data.types).resolvers(resolvers);
34
+
35
+ if (data.options?.endpoint)
36
+ {
37
+ configuration.endpoint((arg) => controller.__endpoint(arg));
38
+ }
39
+
40
+ configuration.main(async ({newTask, updateTask, config, oauth, getClient}) => {
35
41
  try {
36
42
  await controller._doStop();
37
43
  await controller._doStart(config, oauth, newTask, updateTask, getClient);
@@ -31,7 +31,7 @@ export abstract class AbstractController {
31
31
  }
32
32
 
33
33
  async __endpoint(arg: any): Promise<any | null> {
34
- return Promise.resolve(null);
34
+ return this.endpoint(arg);
35
35
  }
36
36
 
37
37
  async __configQuery(arg: any): Promise<any | null> {