@flowripple/sdk 0.1.0 → 1.0.1

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/package.json CHANGED
@@ -1,7 +1,13 @@
1
1
  {
2
2
  "name": "@flowripple/sdk",
3
- "version": "0.1.0",
3
+ "version": "1.0.1",
4
4
  "description": "FlowRipple SDK",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist"
10
+ ],
5
11
  "repository": {
6
12
  "type": "git",
7
13
  "url": "https://github.com/FlowRipple/sdk.git"
@@ -1,8 +0,0 @@
1
- # Changesets
2
-
3
- Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
4
- with multi-package repos, or single-package repos to help you version and publish your code. You can
5
- find the full documentation for it [in our repository](https://github.com/changesets/changesets)
6
-
7
- We have a quick list of common questions to get you started engaging with this project in
8
- [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
@@ -1,11 +0,0 @@
1
- {
2
- "$schema": "https://unpkg.com/@changesets/config@3.0.5/schema.json",
3
- "changelog": "@changesets/cli/changelog",
4
- "commit": false,
5
- "fixed": [],
6
- "linked": [],
7
- "access": "restricted",
8
- "baseBranch": "main",
9
- "updateInternalDependencies": "patch",
10
- "ignore": []
11
- }
package/.env.test DELETED
@@ -1,3 +0,0 @@
1
- FLOWRIPPLE_API_CLIENT_ID=1
2
- FLOWRIPPLE_API_KEY=f7add1c7-d147-470c-85fb-6c99da9a9e95
3
- FLOWRIPPLE_BASE_URL=https://api.flowripple.com
package/.env.test.example DELETED
@@ -1,3 +0,0 @@
1
- FLOWRIPPLE_API_KEY=
2
- FLOWRIPPLE_BASE_URL=
3
- FLOWRIPPLE_API_CLIENT_ID=
@@ -1,71 +0,0 @@
1
- name: Release CI/CD
2
-
3
- on:
4
- push:
5
- branches:
6
- - main
7
-
8
- # Avoid overlapping runs on the same branch
9
- concurrency: ${{ github.workflow }}-${{ github.ref }}
10
-
11
- permissions:
12
- contents: write # to push changes (e.g., tags or changeset PR)
13
- pull-requests: write # to create or update release PR
14
- packages: write # to publish to npm
15
- id-token: write # for provenance (optional, requires Node 16+)
16
-
17
- jobs:
18
- release:
19
- runs-on: ubuntu-latest
20
- steps:
21
- - name: Checkout code
22
- uses: actions/checkout@v3
23
-
24
- - uses: pnpm/action-setup@v2 # Install pnpm first
25
- with:
26
- version: 9 # specify pnpm version (e.g., v8 or v9)
27
-
28
- - name: Setup Node.js 20.x and pnpm
29
- uses: actions/setup-node@v4
30
- with:
31
- node-version: 20.x
32
- cache: "pnpm"
33
- registry-url: "https://registry.npmjs.org" # use npm registry
34
-
35
- - name: Install dependencies
36
- run: pnpm install --frozen-lockfile
37
-
38
- - name: Build package
39
- run: pnpm build
40
-
41
- - name: Validate environment
42
- run: |
43
- if [ -z "${{ secrets.NPM_TOKEN }}" ]; then
44
- echo "NPM_TOKEN is not set"
45
- exit 1
46
- fi
47
- if [ -z "${{ secrets.FLOWRIPPLE_API_KEY }}" ]; then
48
- echo "FLOWRIPPLE_API_KEY is not set"
49
- exit 1
50
- fi
51
-
52
- - name: Run tests
53
- run: |
54
- echo "FLOWRIPPLE_API_CLIENT_ID=${{ secrets.FLOWRIPPLE_API_CLIENT_ID }}" >> .env.test
55
- echo "FLOWRIPPLE_API_KEY=${{ secrets.FLOWRIPPLE_API_KEY }}" >> .env.test
56
- echo "FLOWRIPPLE_BASE_URL=${{ secrets.FLOWRIPPLE_BASE_URL }}" >> .env.test
57
- pnpm test # Runs Jest tests
58
- env:
59
- FLOWRIPPLE_API_CLIENT_ID: ${{ secrets.FLOWRIPPLE_API_CLIENT_ID }}
60
- FLOWRIPPLE_API_KEY: ${{ secrets.FLOWRIPPLE_API_KEY }}
61
- FLOWRIPPLE_BASE_URL: ${{ secrets.FLOWRIPPLE_BASE_URL }}
62
-
63
-
64
- - name: Create Release PR or Publish
65
- id: changesets
66
- uses: changesets/action@v1
67
- with:
68
- publish: pnpm run ci:publish # run publish script (defined in package.json)
69
- env:
70
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
71
- NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
@@ -1,94 +0,0 @@
1
- import { FlowrippleClient } from '../src/index';
2
-
3
- const baseUrl = process.env.FLOWRIPPLE_BASE_URL || 'http://localhost:3000';
4
- const validApiClientId = parseInt(process.env.FLOWRIPPLE_API_CLIENT_ID || '1');
5
- const validApiKey = process.env.FLOWRIPPLE_API_KEY || 'test-api-key';
6
-
7
- describe('FlowrippleClient', () => {
8
- describe('constructor', () => {
9
- it('should set default baseUrl if not provided', () => {
10
- const client = new FlowrippleClient({
11
- apiClientId: validApiClientId,
12
- apiKey: validApiKey,
13
- });
14
- expect(client['baseUrl']).toBe('https://api.flowripple.com');
15
- });
16
-
17
- it('should use provided baseUrl', () => {
18
- const client = new FlowrippleClient({
19
- apiClientId: validApiClientId,
20
- apiKey: validApiKey,
21
- baseUrl: 'http://custom.url',
22
- });
23
- expect(client['baseUrl']).toBe('http://custom.url');
24
- });
25
- });
26
-
27
- describe('capture method', () => {
28
- describe('success cases', () => {
29
- it('should successfully capture an event', async () => {
30
- const client = new FlowrippleClient({
31
- apiClientId: validApiClientId,
32
- apiKey: validApiKey,
33
- baseUrl,
34
- });
35
-
36
- const eventName = 'test.event';
37
- const payload = { userId: '123', action: 'test' };
38
-
39
- const result = await client.capture(eventName, payload);
40
- expect(result).toBeUndefined();
41
- });
42
-
43
- it('should handle successful capture in silent mode', async () => {
44
- const client = new FlowrippleClient({
45
- apiClientId: validApiClientId,
46
- apiKey: validApiKey,
47
- baseUrl,
48
- silent: true,
49
- });
50
-
51
- const result = await client.capture('test.event', { userId: '123' });
52
- expect(result).toBeUndefined();
53
- });
54
- });
55
-
56
- describe('error cases', () => {
57
- it('should throw error with descriptive message in normal mode', async () => {
58
- const client = new FlowrippleClient({
59
- apiClientId: -1, // Invalid ID to force error
60
- apiKey: validApiKey,
61
- baseUrl,
62
- });
63
-
64
- await expect(client.capture('test.event', {})).rejects.toThrow(
65
- 'Failed to capture event',
66
- );
67
- });
68
-
69
- it('should return false in silent mode on error', async () => {
70
- const client = new FlowrippleClient({
71
- apiClientId: -1, // Invalid ID to force error
72
- apiKey: validApiKey,
73
- baseUrl,
74
- silent: true,
75
- });
76
-
77
- const result = await client.capture('test.event', {});
78
- expect(result).toBe(false);
79
- });
80
-
81
- it('should handle invalid API responses', async () => {
82
- const client = new FlowrippleClient({
83
- apiClientId: validApiClientId,
84
- apiKey: 'invalid-key', // Invalid key to force error
85
- baseUrl,
86
- });
87
-
88
- await expect(client.capture('test.event', {})).rejects.toThrow(
89
- 'Failed to capture event',
90
- );
91
- });
92
- });
93
- });
94
- });
package/test/mock.test.ts DELETED
@@ -1,129 +0,0 @@
1
- import { FlowrippleClient } from '../src/index';
2
- import axios from 'axios';
3
-
4
- const baseUrl = process.env.FLOWRIPPLE_BASE_URL || 'http://localhost:3000';
5
- const validApiClientId = parseInt(process.env.FLOWRIPPLE_API_CLIENT_ID || '1');
6
- const validApiKey = process.env.FLOWRIPPLE_API_KEY || 'test-api-key';
7
-
8
- jest.mock('axios');
9
- const mockedAxios = axios as jest.Mocked<typeof axios>;
10
-
11
- describe('FlowrippleClient', () => {
12
- beforeEach(() => {
13
- jest.clearAllMocks();
14
- });
15
-
16
- describe('constructor', () => {
17
- it('should set default baseUrl if not provided', () => {
18
- const client = new FlowrippleClient({
19
- apiClientId: validApiClientId,
20
- apiKey: validApiKey,
21
- });
22
- expect(client['baseUrl']).toBe('https://api.flowripple.com');
23
- });
24
-
25
- it('should use provided baseUrl', () => {
26
- const client = new FlowrippleClient({
27
- apiClientId: validApiClientId,
28
- apiKey: validApiKey,
29
- baseUrl: 'http://custom.url',
30
- });
31
- expect(client['baseUrl']).toBe('http://custom.url');
32
- });
33
- });
34
-
35
- describe('capture method', () => {
36
- describe('success cases', () => {
37
- beforeEach(() => {
38
- mockedAxios.post.mockResolvedValue({ data: {} });
39
- });
40
-
41
- it('should send correct request payload and headers', async () => {
42
- const client = new FlowrippleClient({
43
- apiClientId: validApiClientId,
44
- apiKey: validApiKey,
45
- baseUrl,
46
- });
47
-
48
- const eventName = 'test.event';
49
- const payload = { userId: '123', action: 'test' };
50
-
51
- await client.capture(eventName, payload);
52
-
53
- expect(mockedAxios.post).toHaveBeenCalledTimes(1);
54
- const [url, body, config] = mockedAxios.post.mock.calls[0] ?? [];
55
-
56
- expect(url).toBe(`${baseUrl}/sdk/v1/capture`);
57
- expect(body).toEqual({ event: eventName, payload });
58
- expect(config?.headers).toMatchObject({
59
- 'Content-Type': 'application/json',
60
- 'X-Flowripple-Api-Client-Id': validApiClientId,
61
- 'X-Flowripple-Signature': expect.any(String),
62
- 'X-Flowripple-Timestamp': expect.any(String),
63
- });
64
- });
65
-
66
- it('should handle successful capture in silent mode', async () => {
67
- const client = new FlowrippleClient({
68
- apiClientId: validApiClientId,
69
- apiKey: validApiKey,
70
- baseUrl,
71
- silent: true,
72
- });
73
-
74
- const result = await client.capture('test.event', { userId: '123' });
75
- expect(result).toBeUndefined();
76
- });
77
- });
78
-
79
- describe('error cases', () => {
80
- beforeEach(() => {
81
- mockedAxios.post.mockRejectedValue(new Error('Network error'));
82
- });
83
-
84
- it('should throw error with descriptive message in normal mode', async () => {
85
- const client = new FlowrippleClient({
86
- apiClientId: validApiClientId,
87
- apiKey: validApiKey,
88
- baseUrl,
89
- });
90
-
91
- await expect(client.capture('test.event', {})).rejects.toThrow(
92
- 'Failed to capture event: Network error',
93
- );
94
- });
95
-
96
- it('should return false in silent mode on error', async () => {
97
- const client = new FlowrippleClient({
98
- apiClientId: validApiClientId,
99
- apiKey: validApiKey,
100
- baseUrl,
101
- silent: true,
102
- });
103
-
104
- const result = await client.capture('test.event', {});
105
- expect(result).toBe(false);
106
- });
107
-
108
- it('should handle malformed API responses', async () => {
109
- mockedAxios.post.mockRejectedValue({
110
- isAxiosError: true,
111
- response: {
112
- status: 400,
113
- data: { message: 'Invalid payload' },
114
- },
115
- });
116
-
117
- const client = new FlowrippleClient({
118
- apiClientId: validApiClientId,
119
- apiKey: validApiKey,
120
- baseUrl,
121
- });
122
-
123
- await expect(client.capture('test.event', {})).rejects.toThrow(
124
- 'Failed to capture event',
125
- );
126
- });
127
- });
128
- });
129
- });
package/test/setup.ts DELETED
@@ -1,5 +0,0 @@
1
- import { config } from 'dotenv';
2
- import { resolve } from 'path';
3
-
4
- // Load test environment variables
5
- config({ path: resolve(__dirname, '../.env.test') });