@metagptx/web-sdk 0.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/README.md ADDED
@@ -0,0 +1,414 @@
1
+ # FuncSea WebSDK
2
+
3
+ A TypeScript SDK for interacting with FuncSea API, providing modules for authentication, entity management, API calls, and integrations.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @metagptx/web-sdk
9
+ # or
10
+ pnpm install @metagptx/web-sdk
11
+ # or
12
+ yarn add @metagptx/web-sdk
13
+ ```
14
+
15
+ ## Quick Start
16
+
17
+ ```typescript
18
+ import { createClient } from '@metagptx/web-sdk';
19
+
20
+ // Create client instance (no configuration needed)
21
+ const client = createClient();
22
+
23
+ // Use the client
24
+ const user = await client.auth.me();
25
+ ```
26
+
27
+ ## Modules
28
+
29
+ The SDK provides four main modules:
30
+
31
+ - **auth**: User authentication operations
32
+ - **entities**: Dynamic entity CRUD operations
33
+ - **apiCall**: Custom API calls
34
+ - **integrations**: Integration function invocations
35
+
36
+ ## API Reference
37
+
38
+ ### Auth Module
39
+
40
+ Handles user authentication and session management.
41
+
42
+ #### `auth.me()`
43
+
44
+ Get current user information.
45
+
46
+ **HTTP Details:**
47
+ - **Method:** `GET`
48
+ - **Path:** `/api/v1/auth/me`
49
+ - **Parameters:** None
50
+
51
+ **Example:**
52
+ ```typescript
53
+ const response = await client.auth.me();
54
+ console.log(response.data);
55
+ ```
56
+
57
+ #### `auth.logout()`
58
+
59
+ Logout the current user.
60
+
61
+ **HTTP Details:**
62
+ - **Method:** `POST`
63
+ - **Path:** `/api/v1/auth/logout`
64
+ - **Parameters:** None
65
+
66
+ **Example:**
67
+ ```typescript
68
+ await client.auth.logout();
69
+ ```
70
+
71
+ #### `auth.toLogin()`
72
+
73
+ Redirect to the login page. This is a utility function that redirects the browser to the login URL with the current page as the redirect parameter.
74
+
75
+ **Example:**
76
+ ```typescript
77
+ client.auth.toLogin();
78
+ ```
79
+
80
+ ---
81
+
82
+ ### Entities Module
83
+
84
+ Provides dynamic CRUD operations for any entity type. Access entities using property syntax: `client.entities.{entityName}.{operation}()`.
85
+
86
+ #### `entities[entityName].query(params?)`
87
+
88
+ Query entities with filtering, sorting, and pagination.
89
+
90
+ **HTTP Details:**
91
+ - **Method:** `GET`
92
+ - **Path:** `/api/entities/{entityName}`
93
+ - **Parameters:**
94
+ - `query` (optional): Query conditions object
95
+ - `sort` (optional): Sort field and order (e.g., `"-createdAt"`)
96
+ - `limit` (optional): Maximum number of results
97
+ - `skip` (optional): Number of results to skip
98
+ - `fields` (optional): Array of fields to return
99
+
100
+ **Example:**
101
+ ```typescript
102
+ const response = await client.entities.users.query({
103
+ query: { status: 'active' },
104
+ sort: '-createdAt',
105
+ limit: 10,
106
+ skip: 0,
107
+ fields: ['id', 'name', 'email'],
108
+ });
109
+ ```
110
+
111
+ #### `entities[entityName].get(params)`
112
+
113
+ Get a single entity by ID.
114
+
115
+ **HTTP Details:**
116
+ - **Method:** `GET`
117
+ - **Path:** `/api/entities/{entityName}/{id}`
118
+ - **Parameters:**
119
+ - `id` (required): Entity ID
120
+ - `fields` (optional): Array of fields to return
121
+
122
+ **Example:**
123
+ ```typescript
124
+ const response = await client.entities.users.get({
125
+ id: '12345',
126
+ fields: ['id', 'name', 'email'],
127
+ });
128
+ ```
129
+
130
+ #### `entities[entityName].create(params)`
131
+
132
+ Create a new entity.
133
+
134
+ **HTTP Details:**
135
+ - **Method:** `POST`
136
+ - **Path:** `/api/entities/{entityName}`
137
+ - **Body:**
138
+ - `data` (required): Entity data object
139
+
140
+ **Example:**
141
+ ```typescript
142
+ const response = await client.entities.users.create({
143
+ data: {
144
+ name: 'John Doe',
145
+ email: 'john@example.com',
146
+ status: 'active',
147
+ },
148
+ });
149
+ ```
150
+
151
+ #### `entities[entityName].update(params)`
152
+
153
+ Update an existing entity.
154
+
155
+ **HTTP Details:**
156
+ - **Method:** `PUT`
157
+ - **Path:** `/api/entities/{entityName}/{id}`
158
+ - **Body:**
159
+ - `id` (required): Entity ID
160
+ - `data` (required): Updated entity data
161
+
162
+ **Example:**
163
+ ```typescript
164
+ const response = await client.entities.users.update({
165
+ id: '12345',
166
+ data: {
167
+ name: 'Jane Doe',
168
+ status: 'inactive',
169
+ },
170
+ });
171
+ ```
172
+
173
+ #### `entities[entityName].delete(params)`
174
+
175
+ Delete a single entity by ID.
176
+
177
+ **HTTP Details:**
178
+ - **Method:** `DELETE`
179
+ - **Path:** `/api/entities/{entityName}/{id}`
180
+ - **Parameters:**
181
+ - `id` (required): Entity ID
182
+
183
+ **Example:**
184
+ ```typescript
185
+ await client.entities.users.delete({ id: '12345' });
186
+ ```
187
+
188
+ #### `entities[entityName].createBatch(params)`
189
+
190
+ Create multiple entities in a single request.
191
+
192
+ **HTTP Details:**
193
+ - **Method:** `POST`
194
+ - **Path:** `/api/entities/{entityName}/batch`
195
+ - **Body:**
196
+ - `data` (required): Array of entity data objects
197
+
198
+ **Example:**
199
+ ```typescript
200
+ const response = await client.entities.users.createBatch({
201
+ data: [
202
+ { name: 'John Doe', email: 'john@example.com' },
203
+ { name: 'Jane Smith', email: 'jane@example.com' },
204
+ ],
205
+ });
206
+ ```
207
+
208
+ #### `entities[entityName].updateBatch(params)`
209
+
210
+ Update multiple entities in a single request.
211
+
212
+ **HTTP Details:**
213
+ - **Method:** `PUT`
214
+ - **Path:** `/api/entities/{entityName}/batch`
215
+ - **Body:**
216
+ - `data` (required): Array of entity data objects (must include `id` for each)
217
+
218
+ **Example:**
219
+ ```typescript
220
+ const response = await client.entities.users.updateBatch({
221
+ data: [
222
+ { id: '12345', status: 'active' },
223
+ { id: '67890', status: 'inactive' },
224
+ ],
225
+ });
226
+ ```
227
+
228
+ #### `entities[entityName].deleteBatch(params)`
229
+
230
+ Delete multiple entities by their IDs.
231
+
232
+ **HTTP Details:**
233
+ - **Method:** `DELETE`
234
+ - **Path:** `/api/entities/{entityName}/batch`
235
+ - **Body:**
236
+ - `ids` (required): Array of entity IDs
237
+
238
+ **Example:**
239
+ ```typescript
240
+ await client.entities.users.deleteBatch({
241
+ ids: ['12345', '67890', '11111'],
242
+ });
243
+ ```
244
+
245
+ ---
246
+
247
+ ### API Call Module
248
+
249
+ Provides a flexible way to make custom API calls with any HTTP method.
250
+
251
+ #### `apiCall.invoke(params)`
252
+
253
+ Invoke a custom API call with specified method, URL, and data.
254
+
255
+ **HTTP Details:**
256
+ - **Method:** Configurable (GET, POST, PUT, PATCH, DELETE, etc.)
257
+ - **Path:** Configurable
258
+ - **Parameters:**
259
+ - `url` (required): API endpoint path
260
+ - `method` (optional): HTTP method (defaults to 'GET')
261
+ - `data` (optional): Request data (body for POST/PUT/PATCH, query params for GET/DELETE)
262
+ - `options` (optional): Additional axios request options
263
+
264
+ **Example:**
265
+ ```typescript
266
+ // GET request with query parameters
267
+ const response = await client.apiCall.invoke({
268
+ url: '/api/v1/custom/endpoint',
269
+ method: 'GET',
270
+ data: { filter: 'active' },
271
+ });
272
+
273
+ // POST request with body data
274
+ const response = await client.apiCall.invoke({
275
+ url: '/api/v1/custom/action',
276
+ method: 'POST',
277
+ data: { name: 'Test', value: 123 },
278
+ options: {
279
+ headers: { 'X-Custom-Header': 'value' },
280
+ },
281
+ });
282
+ ```
283
+
284
+ ---
285
+
286
+ ### Integrations Module
287
+
288
+ Provides dynamic access to integration functions. Access integrations using property syntax: `client.integrations.{packageName}.{functionName}(params)`.
289
+
290
+ #### `integrations.core[functionName](params?)`
291
+
292
+ Invoke a core integration function.
293
+
294
+ **HTTP Details:**
295
+ - **Method:** `POST`
296
+ - **Path:** `/api/integrations/core/{functionName}`
297
+ - **Body:**
298
+ - `payload` (optional): Function payload data (object or FormData)
299
+ - `option` (optional): Additional request options
300
+
301
+ **Example:**
302
+ ```typescript
303
+ const response = await client.integrations.core.sendEmail({
304
+ payload: {
305
+ to: 'user@example.com',
306
+ subject: 'Hello',
307
+ body: 'Welcome!',
308
+ },
309
+ });
310
+ ```
311
+
312
+ #### `integrations[packageName][functionName](params?)`
313
+
314
+ Invoke a provider-specific integration function.
315
+
316
+ **HTTP Details:**
317
+ - **Method:** `POST`
318
+ - **Path:** `/api/integrations/providers/{packageName}/{functionName}`
319
+ - **Body:**
320
+ - `payload` (optional): Function payload data (object or FormData)
321
+ - `option` (optional): Additional request options
322
+
323
+ **Example:**
324
+ ```typescript
325
+ // Regular JSON payload
326
+ const response = await client.integrations.stripe.createPayment({
327
+ payload: {
328
+ amount: 1000,
329
+ currency: 'usd',
330
+ },
331
+ });
332
+
333
+ // FormData payload for file uploads
334
+ const formData = new FormData();
335
+ formData.append('file', fileBlob);
336
+ formData.append('metadata', JSON.stringify({ key: 'value' }));
337
+
338
+ const response = await client.integrations.storage.uploadFile({
339
+ payload: formData,
340
+ });
341
+ ```
342
+
343
+ ---
344
+
345
+ ## Configuration
346
+
347
+ ### Client Configuration Options
348
+
349
+ In most cases, you don't need to pass any configuration:
350
+
351
+ ```typescript
352
+ // Default usage (recommended)
353
+ const client = createClient();
354
+ ```
355
+
356
+ However, you can optionally customize the client behavior for advanced use cases:
357
+
358
+ ```typescript
359
+ const client = createClient({
360
+ baseURL: '/custom-api', // Custom base URL (defaults to '/')
361
+ timeout: 30000, // Request timeout in milliseconds (defaults to 60000)
362
+ headers: { // Custom headers
363
+ 'X-Custom-Header': 'value',
364
+ },
365
+ // Any other axios configuration options
366
+ });
367
+ ```
368
+
369
+ **Note:** The `baseURL` and `timeout` options are reserved for future use or special deployment scenarios. Most users should rely on the default values.
370
+
371
+ ### Automatic 401 Handling
372
+
373
+ The SDK automatically handles 401 (Unauthorized) responses by redirecting to the login page. This behavior is built-in and requires no additional configuration.
374
+
375
+ ---
376
+
377
+ ## TypeScript Support
378
+
379
+ The SDK is written in TypeScript and provides full type definitions. You can use generic types for typed responses:
380
+
381
+ ```typescript
382
+ interface User {
383
+ id: string;
384
+ name: string;
385
+ email: string;
386
+ }
387
+
388
+ const response = await client.entities.users.get<User>({ id: '12345' });
389
+ const user: User = response.data;
390
+ ```
391
+
392
+ ---
393
+
394
+ ## Error Handling
395
+
396
+ All API calls return promises that may reject with an error. Always handle errors appropriately:
397
+
398
+ ```typescript
399
+ try {
400
+ const response = await client.entities.users.get({ id: '12345' });
401
+ console.log(response.data);
402
+ } catch (error) {
403
+ if (error.response) {
404
+ // Server responded with error status
405
+ console.error('Error:', error.response.status, error.response.data);
406
+ } else if (error.request) {
407
+ // Request made but no response received
408
+ console.error('No response received:', error.request);
409
+ } else {
410
+ // Error setting up the request
411
+ console.error('Error:', error.message);
412
+ }
413
+ }
414
+ ```
@@ -0,0 +1,108 @@
1
+ import * as axios0 from "axios";
2
+ import { AxiosRequestConfig } from "axios";
3
+
4
+ //#region src/utils/request.d.ts
5
+ /**
6
+ * Request instance configuration options
7
+ */
8
+ interface RequestConfig extends AxiosRequestConfig {
9
+ baseURL?: string;
10
+ timeout?: number;
11
+ onUnauthorized?: () => void;
12
+ }
13
+ /**
14
+ * Creates an axios request instance with default configuration
15
+ * @param config - Optional configuration for the request instance
16
+ * @returns Configured axios instance
17
+ */
18
+ //#endregion
19
+ //#region src/client.d.ts
20
+ interface ClientConfig extends RequestConfig {}
21
+ declare const createClient: (config?: ClientConfig) => {
22
+ auth: {
23
+ me(): Promise<axios0.AxiosResponse<any, any, {}>>;
24
+ logout(): Promise<axios0.AxiosResponse<any, any, {}>>;
25
+ toLogin: () => void;
26
+ };
27
+ entities: Record<string, {
28
+ query<T = any>(params?: {
29
+ query?: Record<string, unknown>;
30
+ sort?: string;
31
+ limit?: number;
32
+ skip?: number;
33
+ fields?: string[];
34
+ }): Promise<axios0.AxiosResponse<T, any, {}>>;
35
+ get<T = any>(params: {
36
+ id: string;
37
+ fields?: string[];
38
+ }): Promise<axios0.AxiosResponse<T, any, {}>>;
39
+ create<T = any>(params: {
40
+ data: Record<string, unknown>;
41
+ }): Promise<axios0.AxiosResponse<T, any, {}>>;
42
+ update<T = any>(params: {
43
+ id: string;
44
+ data: Record<string, unknown>;
45
+ }): Promise<axios0.AxiosResponse<T, any, {}>>;
46
+ delete<T = any>(params: {
47
+ id: string;
48
+ }): Promise<axios0.AxiosResponse<T, any, {}>>;
49
+ deleteBatch<T = any>(params: {
50
+ ids: string[];
51
+ }): Promise<axios0.AxiosResponse<T, any, {}>>;
52
+ createBatch<T = any>(params: {
53
+ data: Record<string, unknown>[];
54
+ }): Promise<axios0.AxiosResponse<T, any, {}>>;
55
+ updateBatch<T = any>(params: {
56
+ data: Record<string, unknown>[];
57
+ }): Promise<axios0.AxiosResponse<T, any, {}>>;
58
+ }>;
59
+ apiCall: {
60
+ invoke<T = any>(params: ApiCallParams): Promise<axios0.AxiosResponse<T, any, {}>>;
61
+ };
62
+ integrations: Record<string, Record<string, IntegrationFunction>>;
63
+ };
64
+ //#endregion
65
+ //#region src/types/index.d.ts
66
+ /**
67
+ * Common reusable types for the funcsea-websdk
68
+ */
69
+ type AnyType = any;
70
+ //#endregion
71
+ //#region src/modules/apiCall.d.ts
72
+ /**
73
+ * API call parameters interface
74
+ */
75
+ interface ApiCallParams {
76
+ url: string;
77
+ method?: string;
78
+ data?: Record<string, AnyType>;
79
+ options?: AxiosRequestConfig;
80
+ }
81
+ /**
82
+ * Creates an API call module for making custom HTTP requests
83
+ * @param params - Configuration object
84
+ * @param params.requestInstance - Axios instance for making HTTP requests
85
+ * @returns Object containing invoke method for API calls
86
+ */
87
+ //#endregion
88
+ //#region src/modules/integrations.d.ts
89
+ /**
90
+ * Integration function parameters interface
91
+ */
92
+ interface IntegrationParams {
93
+ payload?: Record<string, AnyType> | FormData;
94
+ option?: Record<string, AnyType>;
95
+ }
96
+ /**
97
+ * Integration function type
98
+ */
99
+ type IntegrationFunction = (params?: IntegrationParams) => Promise<AnyType>;
100
+ /**
101
+ * Creates an integrations module using proxy for dynamic package and function access
102
+ * @param params - Configuration object
103
+ * @param params.requestInstance - Axios instance for making HTTP requests
104
+ * @returns Proxy object that dynamically creates integration calls
105
+ */
106
+
107
+ //#endregion
108
+ export { type AnyType, type ApiCallParams, type ClientConfig, type IntegrationFunction, type IntegrationParams, type RequestConfig, createClient };
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ import e from"axios";import t from"qs";const n=(n={})=>{let{onUnauthorized:r,...i}=n,a={timeout:6e4,paramsSerializer:e=>t.stringify(e,{arrayFormat:`brackets`}),...i,headers:{"Content-Type":`application/json`,...i.headers}},o=e.create(a);return o.interceptors.request.use(e=>e,e=>Promise.reject(e)),o.interceptors.response.use(e=>e,e=>(e.response?.status===401&&r&&r(),Promise.reject(e))),o},r=e=>typeof e==`string`?e.startsWith(`_`)||e.startsWith(`$`)||e===`constructor`||e===`toString`||e===`valueOf`||e===`inspect`||e===`toJSON`:!0,i=()=>{let e=window.location.href,t=new URLSearchParams({from_url:e});window.location.href=`/api/v1/auth/login?${t.toString()}`},a=e=>{let{requestInstance:t}=e;return{async me(){return t.get(`/api/v1/auth/me`)},async logout(){return t.post(`/api/v1/auth/logout`)},toLogin:i}},o=e=>{let{requestInstance:t,entityName:n}=e,r=`/api/entities/${n}`;return{async query(e){return t.get(r,{params:e})},async get(e){let{id:n,...i}=e;return t.get(`${r}/${n}`,{params:i})},async create(e){return t.post(r,e.data)},async update(e){return t.put(`${r}/${e.id}`,e.data)},async delete(e){return t.delete(`${r}/${e.id}`)},async deleteBatch(e){return t.delete(`${r}/batch`,{data:{ids:e.ids}})},async createBatch(e){return t.post(`${r}/batch`,e.data)},async updateBatch(e){return t.put(`${r}/batch`,e.data)}}},s=e=>{let{requestInstance:t}=e,n=new Map;return new Proxy({},{get(e,i){if(!r(i))return n.has(i)||n.set(i,o({requestInstance:t,entityName:i})),n.get(i)}})},c=e=>{let{requestInstance:t}=e;return{async invoke(e){let{url:n,method:r=`GET`,data:i,options:a={}}=e,o={method:r.toUpperCase(),url:n,...a};return i&&[`POST`,`PUT`,`PATCH`].includes(o.method)?o.data=i:i&&[`GET`,`DELETE`].includes(o.method)&&(o.params=i),t.request(o)}}},l=e=>{let{requestInstance:t}=e;return new Proxy({},{get(e,n){if(!r(n))return new Proxy({},{get(e,i){if(!r(i))return(e={})=>{let r=`/api/integrations/core/${i}`;n!==`core`&&(r=`/api/integrations/providers/${n}/${i}`);let{payload:a={},option:o={}}=e,s=a instanceof FormData?{...o,headers:{...o.headers,"Content-Type":void 0}}:o;return t.post(r,a,s)}}})}})},u=(e={})=>{let t=n({baseURL:`/`,...e,onUnauthorized:i}),r=a({requestInstance:t}),o=s({requestInstance:t}),u=c({requestInstance:t}),d=l({requestInstance:t});return{auth:r,entities:o,apiCall:u,integrations:d}};export{u as createClient};
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "@metagptx/web-sdk",
3
+ "type": "module",
4
+ "version": "0.0.1",
5
+ "packageManager": "pnpm@10.15.0+sha512.486ebc259d3e999a4e8691ce03b5cac4a71cbeca39372a9b762cb500cfdf0873e2cb16abe3d951b1ee2cf012503f027b98b6584e4df22524e0c7450d9ec7aa7b",
6
+ "description": "TypeScript SDK for interacting with FuncSea API",
7
+ "author": "MetaGPTX",
8
+ "license": "MIT",
9
+ "exports": {
10
+ ".": "./dist/index.js",
11
+ "./package.json": "./package.json"
12
+ },
13
+ "main": "./dist/index.js",
14
+ "module": "./dist/index.js",
15
+ "types": "./dist/index.d.ts",
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "publishConfig": {
20
+ "access": "public"
21
+ },
22
+ "scripts": {
23
+ "build": "tsdown",
24
+ "dev": "tsdown --watch",
25
+ "test": "vitest run",
26
+ "test:coverage": "vitest --coverage run",
27
+ "typecheck": "tsc --noEmit",
28
+ "release": "bumpp && npm publish",
29
+ "lint": "eslint",
30
+ "lint:fix": "eslint --fix",
31
+ "precommit": "npm run typecheck && lint-staged && npm run test:coverage",
32
+ "commit-msg": "echo commit-msg"
33
+ },
34
+ "dependencies": {
35
+ "@types/qs": "^6.14.0",
36
+ "axios": "^1.12.2",
37
+ "eslint-config-prettier": "^10.1.8",
38
+ "eslint-plugin-prettier": "^5.5.4",
39
+ "lint-staged": "^16.2.3",
40
+ "qs": "^6.14.0",
41
+ "simple-git-hooks": "^2.13.1"
42
+ },
43
+ "devDependencies": {
44
+ "@antfu/eslint-config": "^5.4.1",
45
+ "@types/jest": "^30.0.0",
46
+ "@types/node": "^22.15.17",
47
+ "@vitest/coverage-v8": "^3.2.4",
48
+ "bumpp": "^10.1.0",
49
+ "eslint": "^9.36.0",
50
+ "tsdown": "^0.11.9",
51
+ "typescript": "^5.8.3",
52
+ "vitest": "^3.1.3"
53
+ },
54
+ "simple-git-hooks": {
55
+ "pre-commit": "npm run precommit",
56
+ "commit-msg": "npm run commit-msg"
57
+ },
58
+ "lint-staged": {
59
+ "*.{js,ts,mts,mjs,md}": [
60
+ "prettier --write",
61
+ "eslint --ext .js,.ts . --quiet"
62
+ ]
63
+ }
64
+ }