smooth-sail / smoothsail-manager

SmoothSail Node.js backend API server for feature flag management and SDK authentication.

Home Page:https://smooth-sail.github.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

SmoothSail Manager platform set up

How to run locally

Install the required prerequisites and then follow the steps below.

Prerequisites

You'll need:

Run the following commands:

git clone https://github.com/smooth-sail/smoothsail-manager.git
cd smoothsail-manager
npm install

Configuration

Create a .env file with the following:

PORT=3000

PGUSER=<username>
PGHOST=localhost
PGDATABASE=<ffdatabasename>
SDKKEYSDB=<sdkkeysdatabasename>
PGPASSWORD=<yourpassword>
PGPORT=5432
SECRET_KEY=<yoursecret> (Must be 32 chars)
NATS_SERVER="nats://localhost:<portnumber>"
LOGLEVEL=info
NODE_ENV=dev
  • PORT is the port the Manager will be running on
  • SDKKEYSDB and PGDATABASE should be the names of databases created on Postgres
  • replace anything that has <> with your own credentials
  • the SECRET_KEY will also need to be used for the SmoothSail SDK Service
  • if PGPORT is not set it will use default value of 5432
  • PGPASSWORD does not have to be set if you don't have a password
  • LOGLEVEL desired log level (examples: verbose, info, warn). If not specified, defaults to warn
  • NODE_ENV - set to test before running tests

Running SmoothSail Manager platform

Before running the Node.js application, it's essential to start the NATS server as a separate service. The NATS server is responsible for message routing and communication. :

nats-server -js -p <portnumber>

From the root of smoothsail-manager run the following command to start the manager:

npm run dev

The SmoothSail dashboard will be available at http://localhost:3000 (unless default port was changed)

You'll need the SDK Service in order to communicate feature flag data to consumer applications. If you haven't yet head on over there to get that running.

SmoothSail Manager platform API

SDK keys endpoints

Get current SDK Key

GET /key

 

Returns on success:

Status code: 200

{
  payload: sdkKey;
}

If no key exists in the database, it will create a new valid key.

 

Returns on error:

Status codes: 500

{
  error: error_message;
}



Invalidate existing SDK Key

POST /key

 

Caution

Invalidates any existing key

 

Expects:

no body

 

Returns on success: returns a new valid key.

Status code: 200

{
  payload: sdkKey;
}

 

Returns on error:

Status codes: 500

{
  error: error_message;
}




Flag endpoints

Flag Object

{
  fKey: string,
  title: string,
  description: string,
  isActive: boolean,
  createdAt: dateTime,
  updatedAt: dateTime,
}



Get all flags

GET /api/flags

 

Expects:

no body.

 

Returns on success:

Status code: 200

{ payload: [ flag1, flag2, flag3,  ] } // ASC order by date created

 

Returns on error:

Status codes: 500

{
  error: error_message;
}



Get a flag by a flag key

GET /api/flags/:fKey

 

Expects:

no body.

fKey ⇒ feature flag key (an HTTP path parameter)

 

Returns on success:

Status code: 200

{
  payload: flag;
}

 

Returns on error:

Status codes: 404, 500

{
  error: error_message;
}



Create a new flag

POST /api/flags

 

Expects:

{
  fKey: fKey,
  title: title,
  description: description
}

 

Returns on success:

Status code: 201

{
  payload: flag;
}

 

Returns on error:

Status codes: 400, 409, 500

{
  error: error_message;
}



Delete flag

DELETE /api/flags/:fKey

 

Expects:

no body.

fKey ⇒ feature flag key (an HTTP path parameter)

 

Returns on success:

Status code: 200

{
  message: "Flag successfully deleted.";
}

 

Returns on error:

Status codes: 404, 500

{
  error: error_message;
}



Change the existing flag

PATCH /api/flags/:fKey

 

Expects:

fKey ⇒ key of the feature flag (an HTTP path parameter)

body:

{
	action:  action,
	payload: payload
}

Supported action types and expected payloads for that action type:

  • body update{ title, description }
  • toggle{ isActive: bool }
  • segment add{ sKey }
  • segment remove{ sKey }

where isActive is true or false (desired toggled stated).

 

Returns on success:

Status code: 200

Reply body for each action type:

body update

{
  payload: flag;
}

toggle

{
  payload: flag;
}

segment add

{
  payload: segment;
}

segment remove

{
  payload: {
    message: "Segment was successfully removed.";
  }
}

 

Returns on error:

Status codes: 400, 404, 500

{
  error: error_message;
}




Segment endpoints

Segment Object

{
	sKey: string,
	title: string,
	description: string,
	rulesOperator: string,
	rules: [
		{
			rKey: integer,
			aKey: string,
			type: 'boolean' || 'string' || 'number',
			operator: string,
			value: bool || string || number,
		},
	]
}



Get all segments

GET /api/segments

 

Expects:

no body.

query params supported:

Possible query params: fKey to filter for a given flag. Example: /api/segments?fKey=flag-1

 

Returns on success:

Status code: 200

{ payload: [ seg1, seg2, seg3,  ] } // sorted by sKey value

 

Returns on error:

Status codes: 404, 500

{
  error: error_message;
}



Get a segment by a segment key

GET /api/segments/:sKey

 

Returns on success:

Status code: 200

{
  payload: segment;
}

 

Returns on error:

Status codes: 404, 500

{
  error: error_message;
}



Creta new segment

POST /api/segments

 

Expects:

{
  sKey: sKey,
  title: title,
  description: description,
  rulesOperator: rulesOperator
}

description is optional rulesOperator is optional (default will be used, default value is all) title must be unique value

 

Returns on success:

Status code: 200

{
  payload: segment;
}

 

Note

Returns segment with empty rules array. To add rules, you need to create a segment first and then add a rule separately (see below)

 

Returns on error:

Status codes: 400, 409, 500

{
  error: error_message;
}



Delete segment

DELETE /api/segments/:sKey

 

Expects:

no body.

sKey ⇒ key of the segment (an HTTP path parameter)

 

Returns on success:

Status code: 200

{
  message: "Segment successfully deleted.";
}

 

Returns on error:

Status codes: 404, 409, 500

{
  error: error_message;
}



Change existing segment

PATCH /api/segments/:sKey

 

Expects:

sKey ⇒ key of the feature flag (an HTTP path parameter)

body:

{
	action: action,
	payload: payload
}

Supported action types and expected request body for that action type:

  • body update{ title, description, rulesOperator }
  • rule add{ aKey, operator, value }
  • rule remove{ rKey }
  • rule update{ operator, value, aKey, rKey }

 

Returns on success:

Status code: 200

Reply body for each action type:

body update

{
  payload: segment;
}

Note

returned segment does not contain attribute rules

rule add

{
    payload: {
        aKey: aKey,
        rKey: rKey,
        sKey: sKey,
        type: type,
        operator: operator,
        value: value
    }
}

rule remove

{ "message": "Rule successfully deleted." }

rule update

{ payload: {
    rKey: rKey,
    aKey: aKey,
    operator: operator,
    value: value,
    type: type,
    sKey: sKey
    }
}

 

Returns on error:

Status codes: 400, 404, 409, 500

{
  error: error_message;
}




Attribute endpoints

Attribute object

{
	aKey: string,
	name: string,
	type: 'boolean' || 'string' || 'number',
}



Get all attributes

GET /api/attributes

 

Expects:

no body.

 

Returns on success:

Status code: 200

{ payload: [ attr1, attr2, attr3,  ] } // ASC order by date created

 

Returns on error:

Status codes: 500

{
  error: error_message;
}



Get attribute by attribute key

GET /api/attributes/:aKey

 

Expects:

no body.

aKey ⇒ key of the attribute (an HTTP path parameter)

 

Returns on success:

Status code: 200

{
  payload: attribute;
}

 

Returns on error:

Status codes: 404, 500

{
  error: error_message;
}



Create a new attribute

POST /api/attributes

 

Expects:

{
  aKey: aKey,
  name: name,
  type: type
}

name - optional (default: an empty string)

 

Returns on success:

Status code: 200

{
  payload: attribute;
}

 

Returns on error:

Status codes: 400, 409, 500

{
  error: error_message;
}



Delete attribute

DELETE /api/attributes/:aKey

 

Expects:

no body.

aKey ⇒ key of the attribute (an HTTP path parameter)

Caution

If an attribute is used in a rule & if you delete this attribute, all the rules that involve this attribute will be automatically deleted.

 

Returns on success:

Status code: 200

{
  message: "Attribute successfully deleted.";
}

 

Returns on error:

Status codes: 404, 500

{
  error: error_message;
}



Change existing attribute

PUT /api/attributes/:aKey

 

Expects:

aKey ⇒ current key of the attribute (an HTTP path parameter)

Request body:

{
    aKey: aKey, // new aKey
    name: name
}

name is optional (default: an empty string)

 

Returns on success:

Status code: 200

{
  payload: attribute;
}

 

Returns on error:

Status codes: 400, 404, 500

{
  error: error_message;
}

About

SmoothSail Node.js backend API server for feature flag management and SDK authentication.

https://smooth-sail.github.io


Languages

Language:TypeScript 73.8%Language:JavaScript 25.8%Language:HTML 0.3%Language:Dockerfile 0.1%Language:CSS 0.0%