@contrail/cli 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/.vscode/settings.json +6 -0
  2. package/bin/init +4 -0
  3. package/lib/auth/login.d.ts +1 -0
  4. package/lib/auth/login.js +79 -0
  5. package/lib/cli.d.ts +5 -0
  6. package/lib/cli.js +30 -0
  7. package/lib/create-app/create.d.ts +1 -0
  8. package/lib/create-app/create.js +48 -0
  9. package/lib/create-app/setup-template.d.ts +1 -0
  10. package/lib/create-app/setup-template.js +48 -0
  11. package/lib/deploy-app/actions-deployer.d.ts +10 -0
  12. package/lib/deploy-app/actions-deployer.js +78 -0
  13. package/lib/deploy-app/actions.d.ts +5 -0
  14. package/lib/deploy-app/actions.js +17 -0
  15. package/lib/deploy-app/app-declaration.d.ts +20 -0
  16. package/lib/deploy-app/app-declaration.js +0 -0
  17. package/lib/deploy-app/app-deployer.d.ts +9 -0
  18. package/lib/deploy-app/app-deployer.js +58 -0
  19. package/lib/deploy-app/app.d.ts +8 -0
  20. package/lib/deploy-app/app.js +56 -0
  21. package/lib/deploy-app/deploy.d.ts +2 -0
  22. package/lib/deploy-app/deploy.js +30 -0
  23. package/lib/deploy-app/interfaces.d.ts +34 -0
  24. package/lib/deploy-app/interfaces.js +0 -0
  25. package/package.json +63 -0
  26. package/src/auth/login.ts +89 -0
  27. package/src/cli.ts +33 -0
  28. package/src/create-app/create.ts +58 -0
  29. package/src/create-app/setup-template.ts +61 -0
  30. package/src/deploy-app/actions-deployer.ts +87 -0
  31. package/src/deploy-app/app-deployer.ts +63 -0
  32. package/src/deploy-app/deploy.ts +34 -0
  33. package/src/deploy-app/interfaces.ts +35 -0
  34. package/templates/javascript/actions/example/action.js +38 -0
  35. package/templates/javascript/app.yml +42 -0
  36. package/templates/javascript/package.json +23 -0
  37. package/tsconfig.json +23 -0
  38. package/tslint.json +57 -0
@@ -0,0 +1,6 @@
1
+ {
2
+ "editor.tabSize": 2,
3
+ "editor.codeActionsOnSave": {
4
+ "source.fixAll.tslint": true
5
+ }
6
+ }
package/bin/init ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+
3
+ require = require('esm')(module /*, options*/);
4
+ require('../lib/cli').cli(process.argv);
@@ -0,0 +1 @@
1
+ export declare function authUser(): Promise<unknown>;
@@ -0,0 +1,79 @@
1
+ const AmazonCognitoIdentity = require('amazon-cognito-identity-js');
2
+ import inquirer from 'inquirer';
3
+ import { setConfig } from '@contrail/sdk';
4
+ const CONFIGURATION = {
5
+ userPoolId: 'us-east-1_x8hXZUsL6',
6
+ clientId: process.env.CONTRAIL_COGNITO_CLIENT_ID || '2oubek96sue5rsncovtqhs3scm',
7
+ };
8
+ export async function authUser() {
9
+ const questions = [];
10
+ if (!process.env.CONTRAIL_CLI_EMAIL) {
11
+ questions.push({
12
+ type: 'input',
13
+ name: 'email',
14
+ validate: (val) => !!val,
15
+ message: 'Email',
16
+ });
17
+ }
18
+ if (!process.env.CONTRAIL_CLI_PASSWORD) {
19
+ questions.push({
20
+ type: 'password',
21
+ name: 'password',
22
+ validate: (val) => !!val,
23
+ message: 'Password',
24
+ });
25
+ }
26
+ if (!process.env.CONTRAIL_CLI_ORGSLUG) {
27
+ questions.push({
28
+ type: 'input',
29
+ name: 'orgSlug',
30
+ validate: (val) => !!val,
31
+ message: 'Org (slug)',
32
+ });
33
+ }
34
+ const answers = await inquirer.prompt(questions);
35
+ const params = {
36
+ email: process.env.CONTRAIL_CLI_EMAIL || answers.email,
37
+ password: process.env.CONTRAIL_CLI_PASSWORD || answers.password,
38
+ orgSlug: process.env.CONTRAIL_CLI_ORGSLUG || answers.orgSlug,
39
+ };
40
+ if (!params.email || !params.password) {
41
+ throw new Error('email and password required');
42
+ }
43
+ const poolData = {
44
+ UserPoolId: CONFIGURATION.userPoolId,
45
+ ClientId: CONFIGURATION.clientId,
46
+ };
47
+ const userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);
48
+ const authData = {
49
+ Username: params.email,
50
+ Password: params.password,
51
+ };
52
+ const authDetails = new AmazonCognitoIdentity.AuthenticationDetails(authData);
53
+ const userData = {
54
+ Username: params.email,
55
+ Pool: userPool,
56
+ };
57
+ const cognitoUser = new AmazonCognitoIdentity.CognitoUser(userData);
58
+ return new Promise((resolve, reject) => {
59
+ cognitoUser.authenticateUser(authDetails, {
60
+ onSuccess: async (result) => {
61
+ const user = result;
62
+ await setSDKConfig(user, params.orgSlug);
63
+ resolve({ success: true, data: result });
64
+ },
65
+ onFailure: (err) => {
66
+ console.log('authUser error: ' + err);
67
+ reject(err);
68
+ },
69
+ });
70
+ });
71
+ }
72
+ async function setSDKConfig(user, orgSlug) {
73
+ // console.log('user:', user);
74
+ setConfig({
75
+ apiUserToken: user.idToken.jwtToken,
76
+ apiGateway: process.env.API_GATEWAY,
77
+ orgSlug,
78
+ });
79
+ }
package/lib/cli.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Built using documentation here:
3
+ * https://www.twilio.com/blog/how-to-build-a-cli-with-node-js
4
+ */
5
+ export declare function cli(args: any): Promise<void>;
package/lib/cli.js ADDED
@@ -0,0 +1,30 @@
1
+ import { create } from './create-app/create';
2
+ import { deployApp, removeApp } from './deploy-app/deploy';
3
+ /**
4
+ * Built using documentation here:
5
+ * https://www.twilio.com/blog/how-to-build-a-cli-with-node-js
6
+ */
7
+ export async function cli(args) {
8
+ const command = args[2];
9
+ switch (command) {
10
+ case 'create-app': {
11
+ create(args);
12
+ break;
13
+ }
14
+ case 'deploy-app': {
15
+ deployApp(args);
16
+ break;
17
+ }
18
+ case 'remove-app': {
19
+ removeApp(args);
20
+ break;
21
+ }
22
+ case 'extract-types': {
23
+ removeApp(args);
24
+ break;
25
+ }
26
+ default: {
27
+ console.log('Illegal command.');
28
+ }
29
+ }
30
+ }
@@ -0,0 +1 @@
1
+ export declare function create(args: any): Promise<void>;
@@ -0,0 +1,48 @@
1
+ import arg from 'arg';
2
+ import inquirer from 'inquirer';
3
+ import chalk from 'chalk';
4
+ import { setUpTemplate } from './setup-template';
5
+ function parseArgumentsIntoOptions(rawArgs) {
6
+ const args = arg({
7
+ '--create-app': Boolean,
8
+ '--app-name': String,
9
+ '-c': '--create-app',
10
+ '-n': '--app-name',
11
+ }, {
12
+ argv: rawArgs.slice(2),
13
+ });
14
+ return {
15
+ createApp: args['--create-app'] || false,
16
+ appName: args['--app-name']
17
+ };
18
+ }
19
+ async function promptForMissingOptions(options) {
20
+ const defaultTemplate = 'JavaScript';
21
+ if (options.skipPrompts) {
22
+ return {
23
+ ...options,
24
+ template: options.template || defaultTemplate,
25
+ };
26
+ }
27
+ const questions = [];
28
+ if (!options.appName) {
29
+ questions.push({
30
+ type: 'input',
31
+ name: 'appName',
32
+ validate: (val) => { return !!val; },
33
+ message: 'What is the name of your app?',
34
+ });
35
+ }
36
+ const answers = await inquirer.prompt(questions);
37
+ return {
38
+ ...options,
39
+ appName: options.appName || answers.appName,
40
+ };
41
+ }
42
+ export async function create(args) {
43
+ let options = parseArgumentsIntoOptions(args);
44
+ options = await promptForMissingOptions(options);
45
+ console.log("%s Setting up new new contrail application.", chalk.blue.bold('START'));
46
+ await setUpTemplate();
47
+ console.log('%s Application initialized successfully.', chalk.green.bold('COMPLETE'));
48
+ }
@@ -0,0 +1 @@
1
+ export declare function setUpTemplate(): Promise<void>;
@@ -0,0 +1,48 @@
1
+ import ncp from 'ncp';
2
+ import path from 'path';
3
+ import { promisify } from 'util';
4
+ import execa from 'execa';
5
+ const Listr = require('listr');
6
+ import { projectInstall } from 'pkg-install';
7
+ const copy = promisify(ncp);
8
+ const TARGET_DIR = process.cwd();
9
+ const currentFileUrl = import.meta.url;
10
+ const TEMPLATE_DIR = path.resolve(new URL(currentFileUrl).pathname, '../../../templates/javascript').replace(/\\/g, '\\').replace(/C:\\C:/g, '');
11
+ // console.log("TEMPLATE_DIR: ", TEMPLATE_DIR)
12
+ // console.log("TARGET_DIR: ", TARGET_DIR)
13
+ function copyTemplate() {
14
+ return copy(TEMPLATE_DIR, TARGET_DIR, {
15
+ clobber: false,
16
+ });
17
+ }
18
+ function npmInstall() {
19
+ async function initGit(options) {
20
+ const result = await execa('git', ['init'], {
21
+ cwd: options.targetDirectory,
22
+ });
23
+ if (result.failed) {
24
+ return Promise.reject(new Error('Failed to initialize git'));
25
+ }
26
+ return;
27
+ }
28
+ }
29
+ export async function setUpTemplate() {
30
+ try {
31
+ const tasks = new Listr([
32
+ {
33
+ title: 'Copy template files',
34
+ task: () => copyTemplate(),
35
+ },
36
+ {
37
+ title: 'Install dependencies',
38
+ task: () => projectInstall({
39
+ cwd: TARGET_DIR,
40
+ }),
41
+ },
42
+ ]);
43
+ await tasks.run();
44
+ }
45
+ catch (e) {
46
+ console.log('Error copying template: ', e);
47
+ }
48
+ }
@@ -0,0 +1,10 @@
1
+ import { App, AppDeclartion, AppActionDeclaration } from './interfaces';
2
+ export declare class ActionsDeployer {
3
+ deployActions(appDeclaration: AppDeclartion, app: App): Promise<void>;
4
+ getActionsForApp(app: App): Promise<any>;
5
+ deployAction(actionKey: string, actionDeclaration: AppActionDeclaration, app: App, existingActions: Array<any>): Promise<void>;
6
+ private createNewActionDefinition;
7
+ private updateActionDefinition;
8
+ getActionDeclarationIdentifier(actionKey: any, app: App): string;
9
+ getFunction(actionDeclaration: AppActionDeclaration): Promise<string>;
10
+ }
@@ -0,0 +1,78 @@
1
+ import { Entities } from '@contrail/sdk';
2
+ import chalk from 'chalk';
3
+ import fs from 'fs';
4
+ export class ActionsDeployer {
5
+ async deployActions(appDeclaration, app) {
6
+ // FETCH ALL ACTIONS FROM THE API.
7
+ const existingActions = await this.getActionsForApp(app);
8
+ console.log('existingActions: ', existingActions);
9
+ // UPSERT / DELETE BASED ON ACTION IDENTIFIER
10
+ console.log('%s \tDeploying actions.', chalk.yellow.bold('ACTION'));
11
+ for (const actionKey of Object.keys(appDeclaration.actions)) {
12
+ await this.deployAction(actionKey, appDeclaration.actions[actionKey], app, existingActions);
13
+ }
14
+ }
15
+ async getActionsForApp(app) {
16
+ return await new Entities().get({ entityName: 'event-workflow-action-definition',
17
+ criteria: { ownerKey: `app:${app.id}` } });
18
+ }
19
+ async deployAction(actionKey, actionDeclaration, app, existingActions) {
20
+ console.log(`%s \tDeploying action: ${actionKey}`, chalk.yellow.bold('ACTION'));
21
+ const identifier = this.getActionDeclarationIdentifier(actionKey, app);
22
+ const existingDefinition = existingActions.find(ad => ad.identifier === identifier);
23
+ if (!existingDefinition) {
24
+ await this.createNewActionDefinition(actionKey, actionDeclaration, app);
25
+ }
26
+ else {
27
+ await this.updateActionDefinition(existingDefinition, actionDeclaration);
28
+ }
29
+ }
30
+ async createNewActionDefinition(actionKey, actionDeclaration, app) {
31
+ const newObject = {
32
+ identifier: this.getActionDeclarationIdentifier(actionKey, app),
33
+ name: actionDeclaration.name,
34
+ ownerKey: `app:${app.id}`,
35
+ public: !app.private,
36
+ };
37
+ const functionString = await this.getFunction(actionDeclaration);
38
+ if (functionString) {
39
+ newObject.executeFunctionString = functionString;
40
+ }
41
+ const actionDefinition = await new Entities().create({
42
+ entityName: 'event-workflow-action-definition',
43
+ object: newObject
44
+ });
45
+ console.log(`%s Created new action defintion: ${actionKey}`, chalk.yellow.bold('APP'));
46
+ return actionDefinition;
47
+ }
48
+ async updateActionDefinition(existingActionDefinition, actionDeclaration) {
49
+ const updates = {
50
+ name: actionDeclaration.name,
51
+ };
52
+ const functionString = await this.getFunction(actionDeclaration);
53
+ if (functionString) {
54
+ updates.executeFunctionString = functionString;
55
+ }
56
+ const actionDefinition = await new Entities().update({
57
+ entityName: 'event-workflow-action-definition',
58
+ id: existingActionDefinition.id,
59
+ object: updates
60
+ });
61
+ console.log(`%s Updated existingaction defintion: ${actionDefinition.identifier}`, chalk.yellow.bold('APP'));
62
+ return actionDefinition;
63
+ }
64
+ getActionDeclarationIdentifier(actionKey, app) {
65
+ return app.identifier + ':' + actionKey;
66
+ }
67
+ async getFunction(actionDeclaration) {
68
+ if (!actionDeclaration.handler) {
69
+ return;
70
+ }
71
+ const CURRENT_DIR = process.cwd();
72
+ const functionLocaiton = CURRENT_DIR + '\\' + actionDeclaration.handler;
73
+ console.log('getFunction: ', functionLocaiton);
74
+ const content = fs.readFileSync(functionLocaiton);
75
+ console.log('content: ', content.toString());
76
+ return content.toString();
77
+ }
78
+ }
@@ -0,0 +1,5 @@
1
+ import { AppDeclartion } from './app-declaration';
2
+ export interface EventWorkflowActionDefinition {
3
+ id?: string;
4
+ }
5
+ export declare function deployActions(appDeclaration: AppDeclartion): Promise<void>;
@@ -0,0 +1,17 @@
1
+ import { Entities } from '@contrail/sdk';
2
+ import chalk from 'chalk';
3
+ export async function deployActions(appDeclaration) {
4
+ // FETCH ALL ACTIONS FROM THE API.
5
+ // UPSERT / DELETE BASED ON ACTION IDENTIFIER
6
+ console.log('%s \tDeploying actions.', chalk.yellow.bold('ACTION'));
7
+ for (const action of Object.keys(appDeclaration.actions)) {
8
+ console.log(`%s \tDeploying action: ${action}`, chalk.yellow.bold('ACTION'));
9
+ }
10
+ }
11
+ /**
12
+ *
13
+ */
14
+ async function getActionsForApp() {
15
+ const workspaces = await new Entities().get({ entityName: 'event-workflow-actions' });
16
+ console.log('workspaces: ', workspaces);
17
+ }
@@ -0,0 +1,20 @@
1
+ /** Describes the derivative JSON / object represented
2
+ * in app.yml file.
3
+ */
4
+ export interface AppDeclartion {
5
+ appIdentifier: string;
6
+ appName: string;
7
+ appDescription?: string;
8
+ visibility: 'private' | 'public';
9
+ publisher: string;
10
+ version: string;
11
+ thumbnail?: string;
12
+ actions?: {
13
+ [key: string]: AppActionDeclaration;
14
+ };
15
+ }
16
+ export interface AppActionDeclaration {
17
+ handler: string;
18
+ name: string;
19
+ description?: string;
20
+ }
File without changes
@@ -0,0 +1,9 @@
1
+ import { AppDeclartion } from './interfaces';
2
+ export declare class AppDeployer {
3
+ private app;
4
+ deploy(appDeclaration: AppDeclartion): Promise<void>;
5
+ remove(appDeclaration: AppDeclartion): Promise<void>;
6
+ getExistingApp(appDeclaration: AppDeclartion): Promise<any>;
7
+ updateExistingApp(appDeclaration: AppDeclartion, existingApp: any): Promise<any>;
8
+ private createNewApp;
9
+ }
@@ -0,0 +1,58 @@
1
+ import { Entities } from '@contrail/sdk';
2
+ import chalk from 'chalk';
3
+ import { ActionsDeployer } from './actions-deployer';
4
+ export class AppDeployer {
5
+ async deploy(appDeclaration) {
6
+ let app = await this.getExistingApp(appDeclaration);
7
+ if (!app) {
8
+ app = await this.createNewApp(appDeclaration);
9
+ }
10
+ else {
11
+ app = await this.updateExistingApp(appDeclaration, app);
12
+ }
13
+ this.app = app;
14
+ await new ActionsDeployer().deployActions(appDeclaration, this.app);
15
+ }
16
+ async remove(appDeclaration) {
17
+ let app = await this.getExistingApp(appDeclaration);
18
+ if (app) {
19
+ app = await new Entities().delete({ entityName: 'app', id: app.id });
20
+ console.log(`%s Deleted app: ${app.name}`, chalk.yellow.bold('APP'));
21
+ }
22
+ else {
23
+ console.log(`%s App not found. Can not remove`, chalk.red.bold('APP'));
24
+ }
25
+ }
26
+ async getExistingApp(appDeclaration) {
27
+ const apps = await new Entities().get({ entityName: 'app', criteria: { orgId: '-VMrLJrt3clDKPi0', private: (appDeclaration.visibility === 'private') } });
28
+ // console.log('Existing: ', apps);
29
+ return apps.find(app => app.identifier === appDeclaration.appIdentifier);
30
+ }
31
+ async updateExistingApp(appDeclaration, existingApp) {
32
+ const updates = {
33
+ name: appDeclaration.appName,
34
+ public: appDeclaration.visibility === 'public',
35
+ description: appDeclaration.appDescription,
36
+ publisher: appDeclaration.publisher,
37
+ thumbnail: appDeclaration.thumbnail,
38
+ eventWorkflowTriggerKeyMapping: 'NONE',
39
+ };
40
+ const app = await new Entities().update({ entityName: 'app', id: existingApp.id, object: updates });
41
+ console.log(`%s Updated app: ${app.name}`, chalk.yellow.bold('APP'));
42
+ return app;
43
+ }
44
+ async createNewApp(appDeclaration) {
45
+ const newApp = {
46
+ identifier: appDeclaration.appIdentifier,
47
+ name: appDeclaration.appName,
48
+ public: appDeclaration.visibility === 'public',
49
+ description: appDeclaration.appDescription,
50
+ publisher: appDeclaration.publisher,
51
+ thumbnail: appDeclaration.thumbnail,
52
+ eventWorkflowTriggerKeyMapping: 'NONE',
53
+ };
54
+ const app = await new Entities().create({ entityName: 'app', object: newApp });
55
+ console.log(`%s Created new app: ${app.name}`, chalk.yellow.bold('APP'));
56
+ return app;
57
+ }
58
+ }
@@ -0,0 +1,8 @@
1
+ import { AppDeclartion } from './app-declaration';
2
+ export declare class AppDeployer {
3
+ deploy(appDeclaration: AppDeclartion): Promise<void>;
4
+ remove(appDeclaration: AppDeclartion): Promise<void>;
5
+ getExistingApp(appDeclaration: AppDeclartion): Promise<any>;
6
+ updateExistingApp(appDeclaration: AppDeclartion, existingApp: any): Promise<any>;
7
+ private createNewApp;
8
+ }
@@ -0,0 +1,56 @@
1
+ import { Entities } from '@contrail/sdk';
2
+ import chalk from 'chalk';
3
+ export class AppDeployer {
4
+ async deploy(appDeclaration) {
5
+ let app = await this.getExistingApp(appDeclaration);
6
+ if (!app) {
7
+ app = await this.createNewApp(appDeclaration);
8
+ }
9
+ else {
10
+ app = await this.updateExistingApp(appDeclaration, app);
11
+ }
12
+ }
13
+ async remove(appDeclaration) {
14
+ const app = await this.getExistingApp(appDeclaration);
15
+ if (app) {
16
+ await new Entities().delete({ entityName: 'app', id: app.id });
17
+ console.log(`%s Deleted app: ${app.name}`, chalk.yellow.bold('APP'));
18
+ }
19
+ else {
20
+ console.log(`%s App not found. Can not remove`, chalk.red.bold('APP'));
21
+ }
22
+ }
23
+ async getExistingApp(appDeclaration) {
24
+ const apps = await new Entities().get({ entityName: 'app', criteria: { orgId: '-VMrLJrt3clDKPi0', private: (appDeclaration.visibility === 'private') } });
25
+ console.log('Existing: ', apps);
26
+ const existing = apps.find(app => app.identifier === appDeclaration.appIdentifier);
27
+ return existing;
28
+ }
29
+ async updateExistingApp(appDeclaration, existingApp) {
30
+ const updates = {
31
+ name: appDeclaration.appName,
32
+ public: appDeclaration.visibility === 'public',
33
+ description: appDeclaration.appDescription,
34
+ publisher: appDeclaration.publisher,
35
+ thumbnail: appDeclaration.thumbnail,
36
+ eventWorkflowTriggerKeyMapping: 'NONE',
37
+ };
38
+ const app = await new Entities().update({ entityName: 'app', id: existingApp.id, object: updates });
39
+ console.log(`%s Updated app: ${app.name}`, chalk.yellow.bold('APP'));
40
+ return app;
41
+ }
42
+ async createNewApp(appDeclaration) {
43
+ const newApp = {
44
+ identifier: appDeclaration.appIdentifier,
45
+ name: appDeclaration.appName,
46
+ public: appDeclaration.visibility === 'public',
47
+ description: appDeclaration.appDescription,
48
+ publisher: appDeclaration.publisher,
49
+ thumbnail: appDeclaration.thumbnail,
50
+ eventWorkflowTriggerKeyMapping: 'NONE',
51
+ };
52
+ const app = await new Entities().create({ entityName: 'app', object: newApp });
53
+ console.log(`%s Created new app: ${app.name}`, chalk.yellow.bold('APP'));
54
+ return app;
55
+ }
56
+ }
@@ -0,0 +1,2 @@
1
+ export declare function deployApp(args: any): Promise<void>;
2
+ export declare function removeApp(args: any): Promise<void>;
@@ -0,0 +1,30 @@
1
+ import chalk from 'chalk';
2
+ import fs from 'fs';
3
+ import { authUser } from '../auth/login';
4
+ import { AppDeployer } from './app-deployer';
5
+ const yaml = require('js-yaml');
6
+ function loadAppConfig() {
7
+ const TARGET_DIR = process.cwd();
8
+ try {
9
+ const doc = yaml.load(fs.readFileSync(TARGET_DIR + '/app.yml', 'utf8'));
10
+ console.log(doc);
11
+ return doc;
12
+ }
13
+ catch (e) {
14
+ console.log('ERROR PARSING YAML: ', e);
15
+ }
16
+ }
17
+ export async function deployApp(args) {
18
+ const appDeclaration = loadAppConfig();
19
+ console.log(`%s Deploying application. ${appDeclaration.appIdentifier}`, chalk.blue.bold('START'));
20
+ const user = await authUser();
21
+ await new AppDeployer().deploy(appDeclaration);
22
+ console.log('%s Deployment complete.', chalk.green.bold('COMPLETE'));
23
+ }
24
+ export async function removeApp(args) {
25
+ const appDeclaration = loadAppConfig();
26
+ console.log(`%s Removing application. ${appDeclaration.appIdentifier}`, chalk.blue.bold('START'));
27
+ await authUser();
28
+ await new AppDeployer().remove(appDeclaration);
29
+ console.log('%s Removing complete.', chalk.green.bold('COMPLETE'));
30
+ }
@@ -0,0 +1,34 @@
1
+ /** Describes the derivative JSON / object represented
2
+ * in app.yml file.
3
+ */
4
+ export interface AppDeclartion {
5
+ appIdentifier: string;
6
+ appName: string;
7
+ appDescription?: string;
8
+ visibility: 'private' | 'public';
9
+ publisher: string;
10
+ version: string;
11
+ thumbnail?: string;
12
+ actions?: {
13
+ [key: string]: AppActionDeclaration;
14
+ };
15
+ }
16
+ export interface AppActionDeclaration {
17
+ handler: string;
18
+ name: string;
19
+ description?: string;
20
+ }
21
+ export interface App {
22
+ id: string;
23
+ identifier: string;
24
+ name: string;
25
+ private: boolean;
26
+ }
27
+ export interface EventWorkflowActionDefinition {
28
+ id?: string;
29
+ identifier?: string;
30
+ name?: string;
31
+ executeFunctionString?: string;
32
+ ownerKey?: string;
33
+ public?: boolean;
34
+ }
File without changes
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@contrail/cli",
3
+ "version": "1.0.0",
4
+ "description": "VibeIQ's Contrail Platform CLI.",
5
+ "main": "lib/index.js",
6
+ "bin": {
7
+ "@contrail/contrail-cli": "bin/init",
8
+ "contrail": "bin/init"
9
+ },
10
+ "publishConfig": {
11
+ "access": "public"
12
+ },
13
+ "keywords": [
14
+ "cli",
15
+ "contrail-cli"
16
+ ],
17
+ "scripts": {
18
+ "build": "tsc",
19
+ "format": "prettier --write \"src/**/*.ts\" \"src/**/*.js\"",
20
+ "lint": "tslint -p tsconfig.json",
21
+ "test": "jest --watch"
22
+ },
23
+ "author": "",
24
+ "license": "ISC",
25
+ "dependencies": {
26
+ "@contrail/sdk": "^1.0.91",
27
+ "amazon-cognito-identity-js": "^5.2.3",
28
+ "arg": "^4.0.1",
29
+ "aws-sdk": "^2.1044.0",
30
+ "chalk": "^4.0.0",
31
+ "esm": "^3.2.25",
32
+ "execa": "^5.0.0",
33
+ "inquirer": "^8.2.0",
34
+ "js-yaml": "^4.1.0",
35
+ "listr": "^0.14.3",
36
+ "ncp": "^2.0.0",
37
+ "pkg-install": "^1.0.0"
38
+ },
39
+ "devDependencies": {
40
+ "@types/jest": "^23.3.14",
41
+ "jest": "^23.6.0",
42
+ "prettier": "^1.19.1",
43
+ "ts-jest": "^23.10.5",
44
+ "tslint": "^5.11.0",
45
+ "tslint-config-prettier": "^1.18.0",
46
+ "typescript": "^3.0.1",
47
+ "@types/node": "^14.6.4"
48
+ },
49
+ "jest": {
50
+ "moduleFileExtensions": [
51
+ "js",
52
+ "json",
53
+ "ts"
54
+ ],
55
+ "rootDir": "src",
56
+ "testRegex": ".spec.ts$",
57
+ "transform": {
58
+ "^.+\\.(t|j)s$": "ts-jest"
59
+ },
60
+ "coverageDirectory": "../coverage",
61
+ "testEnvironment": "node"
62
+ }
63
+ }
@@ -0,0 +1,89 @@
1
+ const AmazonCognitoIdentity = require('amazon-cognito-identity-js');
2
+ import inquirer from 'inquirer';
3
+ import { Entities, setConfig } from '@contrail/sdk';
4
+
5
+ const CONFIGURATION = {
6
+ userPoolId: 'us-east-1_x8hXZUsL6',
7
+ clientId: process.env.CONTRAIL_COGNITO_CLIENT_ID || '2oubek96sue5rsncovtqhs3scm',
8
+ };
9
+
10
+ export async function authUser(){
11
+ const questions = [];
12
+ if (!process.env.CONTRAIL_CLI_EMAIL) {
13
+ questions.push({
14
+ type: 'input',
15
+ name: 'email',
16
+ validate: (val) => !!val,
17
+ message: 'Email',
18
+ });
19
+ }
20
+ if (!process.env.CONTRAIL_CLI_PASSWORD) {
21
+ questions.push({
22
+ type: 'password',
23
+ name: 'password',
24
+ validate: (val) => !!val,
25
+ message: 'Password',
26
+ });
27
+ }
28
+ if (!process.env.CONTRAIL_CLI_ORGSLUG) {
29
+ questions.push({
30
+ type: 'input',
31
+ name: 'orgSlug',
32
+ validate: (val) => !!val,
33
+ message: 'Org (slug)',
34
+ });
35
+ }
36
+
37
+ const answers = await inquirer.prompt(questions);
38
+ const params = {
39
+ email: process.env.CONTRAIL_CLI_EMAIL || answers.email,
40
+ password: process.env.CONTRAIL_CLI_PASSWORD || answers.password,
41
+ orgSlug: process.env.CONTRAIL_CLI_ORGSLUG || answers.orgSlug,
42
+ };
43
+ if (!params.email || !params.password){
44
+ throw new Error('email and password required');
45
+ }
46
+
47
+ const poolData = {
48
+ UserPoolId: CONFIGURATION.userPoolId,
49
+ ClientId: CONFIGURATION.clientId,
50
+ };
51
+
52
+ const userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);
53
+ const authData = {
54
+ Username: params.email,
55
+ Password: params.password,
56
+ };
57
+
58
+ const authDetails = new AmazonCognitoIdentity.AuthenticationDetails(authData);
59
+ const userData = {
60
+ Username: params.email,
61
+ Pool: userPool,
62
+ };
63
+
64
+ const cognitoUser = new AmazonCognitoIdentity.CognitoUser(userData);
65
+
66
+ return new Promise( (resolve, reject) => {
67
+ cognitoUser.authenticateUser(authDetails, {
68
+ onSuccess: async (result) => {
69
+ const user = result;
70
+ await setSDKConfig(user, params.orgSlug);
71
+ resolve({success: true, data: result});
72
+ },
73
+ onFailure: (err) => {
74
+ console.log('authUser error: ' + err);
75
+ reject(err);
76
+ },
77
+ });
78
+ });
79
+
80
+ }
81
+
82
+ async function setSDKConfig(user, orgSlug){
83
+ // console.log('user:', user);
84
+ setConfig({
85
+ apiUserToken: user.idToken.jwtToken,
86
+ apiGateway: process.env.API_GATEWAY,
87
+ orgSlug,
88
+ });
89
+ }
package/src/cli.ts ADDED
@@ -0,0 +1,33 @@
1
+
2
+ import { create } from './create-app/create';
3
+ import { deployApp, removeApp } from './deploy-app/deploy';
4
+ /**
5
+ * Built using documentation here:
6
+ * https://www.twilio.com/blog/how-to-build-a-cli-with-node-js
7
+ */
8
+
9
+ export async function cli(args) {
10
+ const command = args[2];
11
+ switch (command) {
12
+ case 'create-app': {
13
+ create(args);
14
+ break;
15
+ }
16
+ case 'deploy-app': {
17
+ deployApp(args);
18
+ break;
19
+ }
20
+ case 'remove-app': {
21
+ removeApp(args);
22
+ break;
23
+ }
24
+ case 'extract-types': {
25
+ removeApp(args);
26
+ break;
27
+ }
28
+ default: {
29
+ console.log('Illegal command.');
30
+ }
31
+ }
32
+ }
33
+
@@ -0,0 +1,58 @@
1
+ import arg from 'arg';
2
+ import inquirer from 'inquirer';
3
+ import ncp from 'ncp';
4
+ import chalk from 'chalk'
5
+ import { setUpTemplate } from './setup-template';
6
+
7
+ function parseArgumentsIntoOptions(rawArgs) {
8
+ const args = arg(
9
+ {
10
+ '--create-app': Boolean,
11
+ '--app-name': String,
12
+ '-c': '--create-app',
13
+ '-n': '--app-name',
14
+ },
15
+ {
16
+ argv: rawArgs.slice(2),
17
+ }
18
+ );
19
+ return {
20
+ createApp: args['--create-app'] || false,
21
+ appName: args['--app-name']
22
+ };
23
+ }
24
+ async function promptForMissingOptions(options) {
25
+ const defaultTemplate = 'JavaScript';
26
+ if (options.skipPrompts) {
27
+ return {
28
+ ...options,
29
+ template: options.template || defaultTemplate,
30
+ };
31
+ }
32
+
33
+ const questions = [];
34
+ if (!options.appName) {
35
+ questions.push({
36
+ type: 'input',
37
+ name: 'appName',
38
+ validate: (val) => { return !!val },
39
+ message: 'What is the name of your app?',
40
+ });
41
+ }
42
+
43
+ const answers = await inquirer.prompt(questions);
44
+ return {
45
+ ...options,
46
+ appName: options.appName || answers.appName,
47
+ };
48
+ }
49
+
50
+
51
+ export async function create(args) {
52
+
53
+ let options = parseArgumentsIntoOptions(args);
54
+ options = await promptForMissingOptions(options);
55
+ console.log("%s Setting up new new contrail application.", chalk.blue.bold('START'));
56
+ await setUpTemplate();
57
+ console.log('%s Application initialized successfully.', chalk.green.bold('COMPLETE'));
58
+ }
@@ -0,0 +1,61 @@
1
+
2
+ import ncp from 'ncp';
3
+ import path from 'path';
4
+ import { promisify } from 'util';
5
+ import execa from 'execa';
6
+ const Listr = require('listr');
7
+ import { projectInstall } from 'pkg-install';
8
+ const copy = promisify(ncp);
9
+ const TARGET_DIR = process.cwd();
10
+
11
+ const currentFileUrl = import .meta.url;
12
+ const TEMPLATE_DIR = path.resolve(
13
+ new URL(currentFileUrl).pathname,
14
+ '../../../templates/javascript',
15
+ ).replace(/\\/g, '\\').replace(/C:\\C:/g, '');
16
+
17
+ // console.log("TEMPLATE_DIR: ", TEMPLATE_DIR)
18
+ // console.log("TARGET_DIR: ", TARGET_DIR)
19
+
20
+ function copyTemplate(){
21
+ return copy(TEMPLATE_DIR, TARGET_DIR, {
22
+ clobber: false,
23
+ });
24
+ }
25
+
26
+ function npmInstall(){
27
+ async function initGit(options) {
28
+ const result = await execa('git', ['init'], {
29
+ cwd: options.targetDirectory,
30
+ });
31
+ if (result.failed) {
32
+ return Promise.reject(new Error('Failed to initialize git'));
33
+ }
34
+ return;
35
+ }
36
+ }
37
+
38
+ export async function setUpTemplate() {
39
+ try {
40
+ const tasks = new Listr([
41
+ {
42
+ title: 'Copy template files',
43
+ task: () => copyTemplate(),
44
+ },
45
+ {
46
+ title: 'Install dependencies',
47
+ task: () =>
48
+ projectInstall({
49
+ cwd: TARGET_DIR,
50
+ }),
51
+ // skip: () =>
52
+ // !options.runInstall
53
+ // ? 'Pass --install to automatically install dependencies'
54
+ // : undefined,
55
+ },
56
+ ]);
57
+ await tasks.run();
58
+ } catch (e) {
59
+ console.log('Error copying template: ', e);
60
+ }
61
+ }
@@ -0,0 +1,87 @@
1
+ import { Entities } from '@contrail/sdk';
2
+ import chalk from 'chalk';
3
+ import { App, AppDeclartion, AppActionDeclaration, EventWorkflowActionDefinition } from './interfaces';
4
+ import fs from 'fs';
5
+
6
+ export class ActionsDeployer {
7
+ async deployActions(appDeclaration: AppDeclartion, app: App) {
8
+
9
+ // FETCH ALL ACTIONS FROM THE API.
10
+ const existingActions = await this.getActionsForApp(app);
11
+ console.log('existingActions: ', existingActions);
12
+ // UPSERT / DELETE BASED ON ACTION IDENTIFIER
13
+ console.log('%s \tDeploying actions.', chalk.yellow.bold('ACTION'));
14
+ for (const actionKey of Object.keys(appDeclaration.actions)) {
15
+ await this.deployAction(actionKey, appDeclaration.actions[actionKey], app, existingActions);
16
+ }
17
+ }
18
+
19
+ async getActionsForApp(app: App){
20
+ return await new Entities().get({ entityName: 'event-workflow-action-definition',
21
+ criteria: { ownerKey: `app:${app.id}`}});
22
+ }
23
+
24
+ async deployAction(actionKey: string,
25
+ actionDeclaration: AppActionDeclaration,
26
+ app: App,
27
+ existingActions: Array<any>){
28
+ console.log(`%s \tDeploying action: ${actionKey}`, chalk.yellow.bold('ACTION'));
29
+ const identifier = this.getActionDeclarationIdentifier(actionKey, app);
30
+ const existingDefinition = existingActions.find(ad => ad.identifier === identifier);
31
+ if (!existingDefinition) {
32
+ await this.createNewActionDefinition(actionKey, actionDeclaration, app);
33
+ } else {
34
+ await this.updateActionDefinition(existingDefinition, actionDeclaration);
35
+ }
36
+ }
37
+ private async createNewActionDefinition(actionKey: string,
38
+ actionDeclaration: AppActionDeclaration,
39
+ app: App) {
40
+ const newObject: EventWorkflowActionDefinition = {
41
+ identifier: this.getActionDeclarationIdentifier(actionKey, app),
42
+ name: actionDeclaration.name,
43
+ ownerKey: `app:${app.id}`,
44
+ public: !app.private,
45
+ };
46
+ const functionString = await this.getFunction(actionDeclaration);
47
+ if (functionString) {
48
+ newObject.executeFunctionString = functionString;
49
+ }
50
+ const actionDefinition = await new Entities().create({
51
+ entityName: 'event-workflow-action-definition',
52
+ object: newObject });
53
+ console.log(`%s Created new action defintion: ${actionKey}`, chalk.yellow.bold('APP'));
54
+ return actionDefinition;
55
+ }
56
+ private async updateActionDefinition(existingActionDefinition: EventWorkflowActionDefinition,
57
+ actionDeclaration: AppActionDeclaration) {
58
+ const updates: EventWorkflowActionDefinition = {
59
+ name: actionDeclaration.name,
60
+ };
61
+ const functionString = await this.getFunction(actionDeclaration);
62
+ if (functionString) {
63
+ updates.executeFunctionString = functionString;
64
+ }
65
+ const actionDefinition = await new Entities().update({
66
+ entityName: 'event-workflow-action-definition',
67
+ id: existingActionDefinition.id,
68
+ object: updates });
69
+ console.log(`%s Updated existingaction defintion: ${actionDefinition.identifier}`, chalk.yellow.bold('APP'));
70
+ return actionDefinition;
71
+ }
72
+ getActionDeclarationIdentifier(actionKey, app: App) {
73
+ return app.identifier + ':' + actionKey;
74
+ }
75
+
76
+ async getFunction(actionDeclaration: AppActionDeclaration): Promise<string> {
77
+ if (!actionDeclaration.handler) {
78
+ return;
79
+ }
80
+ const CURRENT_DIR = process.cwd();
81
+ const functionLocaiton = CURRENT_DIR + '\\' + actionDeclaration.handler;
82
+ console.log('getFunction: ', functionLocaiton);
83
+ const content = fs.readFileSync(functionLocaiton);
84
+ console.log('content: ', content.toString());
85
+ return content.toString();
86
+ }
87
+ }
@@ -0,0 +1,63 @@
1
+ import { Entities } from '@contrail/sdk';
2
+ import chalk from 'chalk';
3
+ import { ActionsDeployer } from './actions-deployer';
4
+ import { App, AppDeclartion } from './interfaces';
5
+
6
+ export class AppDeployer {
7
+ private app: App;
8
+ public async deploy(appDeclaration: AppDeclartion) {
9
+ let app = await this.getExistingApp(appDeclaration);
10
+ if (!app) {
11
+ app = await this.createNewApp(appDeclaration);
12
+ } else {
13
+ app = await this.updateExistingApp(appDeclaration, app);
14
+ }
15
+ this.app = app;
16
+ await new ActionsDeployer().deployActions(appDeclaration, this.app);
17
+ }
18
+
19
+ public async remove(appDeclaration: AppDeclartion) {
20
+ let app = await this.getExistingApp(appDeclaration);
21
+ if (app) {
22
+ app = await new Entities().delete({ entityName: 'app', id: app.id});
23
+ console.log(`%s Deleted app: ${app.name}`, chalk.yellow.bold('APP'));
24
+ } else {
25
+ console.log(`%s App not found. Can not remove`, chalk.red.bold('APP'));
26
+ }
27
+ }
28
+
29
+ public async getExistingApp(appDeclaration: AppDeclartion) {
30
+ const apps = await new Entities().get({ entityName: 'app', criteria: { orgId: '-VMrLJrt3clDKPi0', private: (appDeclaration.visibility === 'private')}});
31
+ // console.log('Existing: ', apps);
32
+ return apps.find(app => app.identifier === appDeclaration.appIdentifier);
33
+ }
34
+ public async updateExistingApp(appDeclaration: AppDeclartion, existingApp) {
35
+ const updates = {
36
+ name: appDeclaration.appName,
37
+ public: appDeclaration.visibility === 'public',
38
+ description: appDeclaration.appDescription,
39
+ publisher: appDeclaration.publisher,
40
+ thumbnail: appDeclaration.thumbnail,
41
+ eventWorkflowTriggerKeyMapping: 'NONE',
42
+ };
43
+ const app = await new Entities().update({ entityName: 'app', id: existingApp.id, object: updates });
44
+ console.log(`%s Updated app: ${app.name}`, chalk.yellow.bold('APP'));
45
+ return app;
46
+
47
+ }
48
+ private async createNewApp(appDeclaration: AppDeclartion) {
49
+ const newApp = {
50
+ identifier: appDeclaration.appIdentifier,
51
+ name: appDeclaration.appName,
52
+ public: appDeclaration.visibility === 'public',
53
+ description: appDeclaration.appDescription,
54
+ publisher: appDeclaration.publisher,
55
+ thumbnail: appDeclaration.thumbnail,
56
+ eventWorkflowTriggerKeyMapping: 'NONE',
57
+
58
+ };
59
+ const app = await new Entities().create({ entityName: 'app', object: newApp });
60
+ console.log(`%s Created new app: ${app.name}`, chalk.yellow.bold('APP'));
61
+ return app;
62
+ }
63
+ }
@@ -0,0 +1,34 @@
1
+ import chalk from 'chalk';
2
+ import fs from 'fs';
3
+ import { authUser } from '../auth/login';
4
+ import { AppDeployer } from './app-deployer';
5
+ import { AppDeclartion } from './interfaces';
6
+ const yaml = require('js-yaml');
7
+
8
+ function loadAppConfig(){
9
+ const TARGET_DIR = process.cwd();
10
+ try {
11
+ const doc = yaml.load(fs.readFileSync(TARGET_DIR + '/app.yml', 'utf8'));
12
+ console.log(doc);
13
+ return doc;
14
+ } catch (e) {
15
+ console.log('ERROR PARSING YAML: ', e);
16
+ }
17
+ }
18
+
19
+ export async function deployApp(args) {
20
+ const appDeclaration: AppDeclartion = loadAppConfig();
21
+
22
+ console.log(`%s Deploying application. ${appDeclaration.appIdentifier}`, chalk.blue.bold('START'));
23
+ const user = await authUser();
24
+ await new AppDeployer().deploy(appDeclaration);
25
+ console.log('%s Deployment complete.', chalk.green.bold('COMPLETE'));
26
+ }
27
+
28
+ export async function removeApp(args) {
29
+ const appDeclaration: AppDeclartion = loadAppConfig();
30
+ console.log(`%s Removing application. ${appDeclaration.appIdentifier}`, chalk.blue.bold('START'));
31
+ await authUser();
32
+ await new AppDeployer().remove(appDeclaration);
33
+ console.log('%s Removing complete.', chalk.green.bold('COMPLETE'));
34
+ }
@@ -0,0 +1,35 @@
1
+ /** Describes the derivative JSON / object represented
2
+ * in app.yml file.
3
+ */
4
+ export interface AppDeclartion {
5
+ appIdentifier: string;
6
+ appName: string;
7
+ appDescription?: string;
8
+ visibility: 'private' | 'public';
9
+ publisher: string;
10
+ version: string;
11
+ thumbnail?: string;
12
+ actions?: { [key: string]: AppActionDeclaration };
13
+ }
14
+
15
+ export interface AppActionDeclaration {
16
+ handler: string;
17
+ name: string;
18
+ description?: string;
19
+ }
20
+
21
+ export interface App {
22
+ id: string;
23
+ identifier: string;
24
+ name: string;
25
+ private: boolean;
26
+ }
27
+
28
+ export interface EventWorkflowActionDefinition {
29
+ id?: string;
30
+ identifier?: string;
31
+ name?: string;
32
+ executeFunctionString?: string;
33
+ ownerKey?: string;
34
+ public?: boolean;
35
+ }
@@ -0,0 +1,38 @@
1
+ async function execute(config, event, Functions) {
2
+ const getBodyFromEvent = (config, event) => {
3
+ let body = Functions.StringUtil.parseVariables(config.message, event);
4
+ console.log('body: ', body);
5
+ if (config.sendDetails) {
6
+ const data = event;
7
+ const properties = {};
8
+ let addedProperty = false;
9
+ for (const property of config.fieldsToForward) {
10
+ const variableLevels = property.split('.');
11
+ let replacementValue = data;
12
+ for (let i = 0; i < variableLevels.length; i++) {
13
+ replacementValue = replacementValue[variableLevels[i]];
14
+ }
15
+ properties[property] = replacementValue;
16
+ addedProperty = true;
17
+ }
18
+ if (addedProperty) {
19
+ body = body + ' Properties: ' + JSON.stringify(properties) + '.';
20
+ }
21
+ }
22
+ return JSON.stringify({ text: body });
23
+ };
24
+ const body = getBodyFromEvent(config, event);
25
+ console.log('Sending message: ', body);
26
+ const response = await Functions.fetch(config.url, {
27
+ method: 'POST',
28
+ body: body,
29
+ headers: { 'Content-Type': 'application/json' }
30
+ });
31
+ if (!response.ok) {
32
+ console.log('Webhook event failed to publish');
33
+ console.log('Response: ', JSON.stringify(response));
34
+ }
35
+ else {
36
+ console.log('Published!');
37
+ }
38
+ }
@@ -0,0 +1,42 @@
1
+ appIdentifier: "@your-co/app-name"
2
+ appName: "Your App Name"
3
+ appDescription: "Your app description."
4
+ visibility: public
5
+ publisher: "Your company name"
6
+ version: 1.0
7
+
8
+ appConfiguration:
9
+ apiHost:
10
+ label: "API Host"
11
+ propertyType: "string"
12
+ userName:
13
+ label: "User Name"
14
+ propertyType: "string"
15
+ password:
16
+ label: "Password"
17
+ propertyType: "string"
18
+
19
+ actions:
20
+ updateProduct:
21
+ handler: actions/example/action.js
22
+ name: "Update Product"
23
+ description: "Updates a product in the destination system."
24
+
25
+ triggers:
26
+ trigger1:
27
+ key: product|create
28
+ name: "Produt Created"
29
+
30
+ workflows:
31
+ workflow1:
32
+ name: "Update item on product creation"
33
+ triggerKey: product|create
34
+ paths:
35
+ path1:
36
+ conditional: "{retailPrice} > 10"
37
+ actions:
38
+ updateItem:
39
+ actionId: updateItem
40
+ configuration:
41
+
42
+
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "test-app",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "index.js",
6
+ "bin": {
7
+ "@contrail/contrail-cli": "bin/init",
8
+ "contrail": "bin/init"
9
+ },
10
+ "publishConfig": {
11
+ "access": "public"
12
+ },
13
+ "scripts": {
14
+ "test": "echo \"Error: no test specified\" && exit 1"
15
+ },
16
+ "keywords": [
17
+ ],
18
+ "author": "",
19
+ "license": "ISC",
20
+ "dependencies": {
21
+ "chalk": "^4.0.0"
22
+ }
23
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "esnext",
4
+ "module": "esnext",
5
+ "declaration": true,
6
+ "esModuleInterop": true,
7
+ "outDir": "./lib",
8
+ "strict": false,
9
+ "experimentalDecorators": true,
10
+ "strictPropertyInitialization": false,
11
+ "noImplicitAny": false,
12
+ "emitDecoratorMetadata": true,
13
+ "skipLibCheck": true,
14
+ "moduleResolution": "node"
15
+ },
16
+ "include": [
17
+ "src"
18
+ ],
19
+ "exclude": [
20
+ "node_modules",
21
+ "**/__tests__/*"
22
+ ]
23
+ }
package/tslint.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "defaultSeverity": "error",
3
+ "extends": [
4
+ "tslint:recommended"
5
+ ],
6
+ "jsRules": {
7
+ "no-unused-expression": true
8
+ },
9
+ "rules": {
10
+ "eofline": false,
11
+ "quotemark": [
12
+ true,
13
+ "single"
14
+ ],
15
+ "no-shadowed-variable": false,
16
+ "indent": false,
17
+ "member-access": [
18
+ false
19
+ ],
20
+ "no-string-literal": false,
21
+ "ordered-imports": [
22
+ false
23
+ ],
24
+ "max-line-length": [
25
+ false,
26
+ 150
27
+ ],
28
+ "member-ordering": [
29
+ false
30
+ ],
31
+ "curly": false,
32
+ "interface-name": [
33
+ false
34
+ ],
35
+ "array-type": [
36
+ false
37
+ ],
38
+ "no-empty-interface": false,
39
+ "no-empty": false,
40
+ "arrow-parens": false,
41
+ "object-literal-sort-keys": false,
42
+ "no-unused-expression": false,
43
+ "max-classes-per-file": [
44
+ false
45
+ ],
46
+ "variable-name": [
47
+ false
48
+ ],
49
+ "one-line": [
50
+ false
51
+ ],
52
+ "one-variable-per-declaration": [
53
+ false
54
+ ]
55
+ },
56
+ "rulesDirectory": []
57
+ }