@scryme/chat 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 +166 -0
- package/dist/client.d.ts +2 -0
- package/dist/client.js +2 -0
- package/dist/custom-instance.d.ts +5 -0
- package/dist/custom-instance.js +100 -0
- package/dist/generated/v3-client.d.ts +7879 -0
- package/dist/generated/v3-client.js +6762 -0
- package/dist/generated/v3-server.d.ts +1679 -0
- package/dist/generated/v3-server.js +2050 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/sdk.d.ts +78 -0
- package/dist/sdk.js +421 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.js +3 -0
- package/package.json +50 -0
- package/src/__tests__/sdk.test.ts +227 -0
- package/src/client.ts +2 -0
- package/src/custom-instance.ts +118 -0
- package/src/generated/v3-client.ts +17309 -0
- package/src/generated/v3-server.ts +5225 -0
- package/src/index.ts +3 -0
- package/src/sdk.ts +298 -0
- package/src/server.ts +3 -0
package/README.md
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# Scryme Chat TypeScript SDK (`@scryme/chat`)
|
|
2
|
+
|
|
3
|
+
A high-performance, developer-friendly, fully typed TypeScript/JavaScript SDK for interacting with the Skyrme Chat V2 and V3 Enterprise APIs.
|
|
4
|
+
|
|
5
|
+
Designed primarily for backend integrations, servers, and automated Machine-to-Machine (M2M) environments, this SDK provides unmatched DX with automatic OAuth2 token management, dynamic API proxying, and fluent nested helper chains.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- **OAuth2 Client Credentials Grant**: Built-in, fully automated caching and renewal of M2M access tokens with timing-safe, proactive expiration buffers.
|
|
12
|
+
- **Dynamic Method Proxying (`sdk.raw`)**: Automatic injection of Bearer token and Base URL headers into any of the 100+ generated V3 API endpoints with complete TypeScript autocompletion.
|
|
13
|
+
- **Fluent Nested Namespaces**: High-level, developer-friendly helper routes (`sdk.workspace`, `sdk.channel`, `sdk.message`, etc.) for seamless workspace, department, team, and member administration.
|
|
14
|
+
- **Isomorphic Support**: Works out-of-the-box in Node.js, Next.js (server/client), Vite, and React Native.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install @scryme/chat
|
|
22
|
+
# or
|
|
23
|
+
pnpm add @scryme/chat
|
|
24
|
+
# or
|
|
25
|
+
yarn add @scryme/chat
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Getting Started
|
|
31
|
+
|
|
32
|
+
### 1. Initialize the SDK
|
|
33
|
+
|
|
34
|
+
You can initialize `ScrymeSDK` using a static bearer token or using M2M client credentials (`clientId` and `clientSecret`) to enable auto-authentication.
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
import { ScrymeSDK } from '@scryme/chat';
|
|
38
|
+
|
|
39
|
+
// Option A: Machine-to-Machine (M2M) Auth (Highly recommended for servers/bots)
|
|
40
|
+
const sdk = new ScrymeSDK({
|
|
41
|
+
baseURL: 'https://api.chat.scryme.tech',
|
|
42
|
+
clientId: 'm2m_client_abc123',
|
|
43
|
+
clientSecret: 'sk_m2m_secret_xyz789',
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// Option B: Static Bearer Token Auth
|
|
47
|
+
const sdkWithToken = new ScrymeSDK({
|
|
48
|
+
baseURL: 'https://api.chat.scryme.tech',
|
|
49
|
+
token: 'oat_your_token_here',
|
|
50
|
+
});
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Usage Guide
|
|
56
|
+
|
|
57
|
+
### High-Level Fluent Namespaces (Excellent DX)
|
|
58
|
+
|
|
59
|
+
For standard CRUD workflows, utilize our intuitive nested namespace chains:
|
|
60
|
+
|
|
61
|
+
#### Workspaces
|
|
62
|
+
```typescript
|
|
63
|
+
// List all workspaces associated with the organization
|
|
64
|
+
const workspaces = await sdk.workspace.list();
|
|
65
|
+
|
|
66
|
+
// Provision/Create a new tenant workspace
|
|
67
|
+
const newWorkspace = await sdk.workspace.create({
|
|
68
|
+
name: 'Acme Corp',
|
|
69
|
+
slug: 'acme-corp',
|
|
70
|
+
ownerEmail: 'admin@acme.com',
|
|
71
|
+
channels: ['general', 'engineering'],
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Retrieve detailed workspace metadata
|
|
75
|
+
const workspace = await sdk.workspace.get('acme-corp');
|
|
76
|
+
|
|
77
|
+
// Update workspace branding or details
|
|
78
|
+
await sdk.workspace.update('acme-corp', {
|
|
79
|
+
name: 'Acme Corp International',
|
|
80
|
+
description: 'Updated team workspace',
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// Delete a workspace
|
|
84
|
+
await sdk.workspace.delete('acme-corp');
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
#### Workspace Members
|
|
88
|
+
```typescript
|
|
89
|
+
// List workspace members
|
|
90
|
+
const members = await sdk.workspace.members.list('acme-corp');
|
|
91
|
+
|
|
92
|
+
// Invite/Add a new member
|
|
93
|
+
await sdk.workspace.members.add('acme-corp', {
|
|
94
|
+
email: 'developer@acme.com',
|
|
95
|
+
role: 'member',
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// Remove a member
|
|
99
|
+
await sdk.workspace.members.delete('acme-corp', 'member_id_xyz');
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
#### Channels & Messaging
|
|
103
|
+
```typescript
|
|
104
|
+
// List channels in a workspace
|
|
105
|
+
const channels = await sdk.workspace.channels.list('acme-corp');
|
|
106
|
+
|
|
107
|
+
// Create a new channel
|
|
108
|
+
const channel = await sdk.workspace.channels.create('acme-corp', {
|
|
109
|
+
name: 'announcements',
|
|
110
|
+
type: 'text',
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// Send a message to a channel
|
|
114
|
+
await sdk.channel.message.create('channel_id_123', {
|
|
115
|
+
content: 'Hello Team! This is automated via our new TS SDK 🚀',
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// Fetch channel messages
|
|
119
|
+
const messages = await sdk.channel.message.list('channel_id_123', { limit: 10 });
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
### Dynamic API Proxying (`sdk.raw`)
|
|
125
|
+
|
|
126
|
+
If you need lower-level control or need to access raw Orval/Axios endpoints not wrapped in our helper namespaces, use `sdk.raw`.
|
|
127
|
+
|
|
128
|
+
Every raw endpoint:
|
|
129
|
+
1. Offers **full TypeScript types** for parameters, request body, and response.
|
|
130
|
+
2. **Automatically injects** the required Bearer Authorization header (fetching or refreshing the M2M token on the fly).
|
|
131
|
+
3. Resolves to the correct configured API Base URL.
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
// Access lower-level generated controller methods directly
|
|
135
|
+
const health = await sdk.raw.appControllerGetHealth();
|
|
136
|
+
|
|
137
|
+
// User search
|
|
138
|
+
const users = await sdk.raw.usersControllerSearchUsers({ q: 'alice' });
|
|
139
|
+
|
|
140
|
+
// Fully typed update workspace webhook call
|
|
141
|
+
const webhook = await sdk.raw.v3WebhooksControllerCreateWebhook('acme-corp', {
|
|
142
|
+
name: 'Slack Sync Sync',
|
|
143
|
+
url: 'https://hooks.slack.com/services/...',
|
|
144
|
+
events: ['message.created'],
|
|
145
|
+
});
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Development
|
|
151
|
+
|
|
152
|
+
### Compile the SDK
|
|
153
|
+
```bash
|
|
154
|
+
pnpm build
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Run Unit Tests
|
|
158
|
+
```bash
|
|
159
|
+
pnpm test
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## License
|
|
165
|
+
|
|
166
|
+
MIT © Skyrme Chat Enterprise
|
package/dist/client.d.ts
ADDED
package/dist/client.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { AxiosRequestConfig, AxiosError } from 'axios';
|
|
2
|
+
export declare const AXIOS_INSTANCE: import("axios").AxiosInstance;
|
|
3
|
+
export declare const customInstance: <T>(config: AxiosRequestConfig, options?: AxiosRequestConfig) => Promise<T>;
|
|
4
|
+
export type ErrorType<Error> = AxiosError<Error>;
|
|
5
|
+
export type BodyType<Body> = Body;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
12
|
+
import axios from 'axios';
|
|
13
|
+
// Helper to safely access env variables across Vite, Next.js and React Native
|
|
14
|
+
var getEnv = function (name) {
|
|
15
|
+
var _a, _b, _c;
|
|
16
|
+
var g = globalThis;
|
|
17
|
+
// Try various common locations for env variables
|
|
18
|
+
// Avoid explicit import.meta to prevent TS1470
|
|
19
|
+
var env = ((_a = g.process) === null || _a === void 0 ? void 0 : _a.env) || ((_c = (_b = g.import) === null || _b === void 0 ? void 0 : _b.meta) === null || _c === void 0 ? void 0 : _c.env) || g.__env__;
|
|
20
|
+
if (!env)
|
|
21
|
+
return undefined;
|
|
22
|
+
return (env[name] || env["VITE_".concat(name)] || env["NEXT_PUBLIC_".concat(name)] || env["EXPO_PUBLIC_".concat(name)] || env["TAURI_".concat(name)]);
|
|
23
|
+
};
|
|
24
|
+
var getBaseURL = function () {
|
|
25
|
+
var url = '';
|
|
26
|
+
if (typeof window !== 'undefined') {
|
|
27
|
+
var customUrl = window.localStorage.getItem('CUSTOM_API_URL');
|
|
28
|
+
if (customUrl) {
|
|
29
|
+
url = customUrl;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (!url) {
|
|
33
|
+
var isProd = (typeof process !== 'undefined' && process.env && process.env.NODE_ENV === 'production') ||
|
|
34
|
+
getEnv('NODE_ENV') === 'production' ||
|
|
35
|
+
(typeof window !== 'undefined' && window.location.hostname !== 'localhost' && window.location.hostname !== '127.0.0.1');
|
|
36
|
+
url = getEnv('API_URL') || getEnv('NEXT_PUBLIC_API_URL') || (isProd ? 'https://api.chat.scryme.tech' : 'http://localhost:3000');
|
|
37
|
+
}
|
|
38
|
+
return url.replace(/\/$/, '') + '/api';
|
|
39
|
+
};
|
|
40
|
+
export var AXIOS_INSTANCE = axios.create({
|
|
41
|
+
baseURL: getBaseURL(),
|
|
42
|
+
timeout: 10000,
|
|
43
|
+
withCredentials: true,
|
|
44
|
+
});
|
|
45
|
+
AXIOS_INSTANCE.interceptors.request.use(function (config) {
|
|
46
|
+
if (typeof window !== 'undefined') {
|
|
47
|
+
var getCookie = function (name) {
|
|
48
|
+
var _a;
|
|
49
|
+
var value = "; ".concat(document.cookie);
|
|
50
|
+
var parts = value.split("; ".concat(name, "="));
|
|
51
|
+
if (parts.length === 2)
|
|
52
|
+
return ((_a = parts.pop()) === null || _a === void 0 ? void 0 : _a.split(';').shift()) || null;
|
|
53
|
+
return null;
|
|
54
|
+
};
|
|
55
|
+
var token = window.localStorage.getItem('better-auth.session-token') ||
|
|
56
|
+
window.localStorage.getItem('better-auth.session_token') ||
|
|
57
|
+
window.localStorage.getItem('bearer_token');
|
|
58
|
+
if (!token) {
|
|
59
|
+
token =
|
|
60
|
+
getCookie('better-auth.session_token') ||
|
|
61
|
+
getCookie('better-auth.session-token') ||
|
|
62
|
+
getCookie('bearer_token');
|
|
63
|
+
if (token) {
|
|
64
|
+
window.localStorage.setItem('better-auth.session_token', token);
|
|
65
|
+
window.localStorage.setItem('better-auth.session-token', token);
|
|
66
|
+
window.localStorage.setItem('bearer_token', token);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
// Keep everything in sync
|
|
71
|
+
if (!window.localStorage.getItem('bearer_token')) {
|
|
72
|
+
window.localStorage.setItem('bearer_token', token);
|
|
73
|
+
}
|
|
74
|
+
if (!window.localStorage.getItem('better-auth.session_token')) {
|
|
75
|
+
window.localStorage.setItem('better-auth.session_token', token);
|
|
76
|
+
}
|
|
77
|
+
if (!window.localStorage.getItem('better-auth.session-token')) {
|
|
78
|
+
window.localStorage.setItem('better-auth.session-token', token);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (token) {
|
|
82
|
+
config.headers.Authorization = "Bearer ".concat(token);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return config;
|
|
86
|
+
});
|
|
87
|
+
export var customInstance = function (config, options) {
|
|
88
|
+
var source = axios.CancelToken.source();
|
|
89
|
+
// Merge headers carefully so that options.headers does not overwrite config.headers completely
|
|
90
|
+
var mergedHeaders = __assign(__assign({}, config.headers), options === null || options === void 0 ? void 0 : options.headers);
|
|
91
|
+
var promise = AXIOS_INSTANCE(__assign(__assign(__assign({}, config), options), { headers: mergedHeaders, cancelToken: source.token })).then(function (_a) {
|
|
92
|
+
var data = _a.data;
|
|
93
|
+
return data;
|
|
94
|
+
});
|
|
95
|
+
// @ts-ignore
|
|
96
|
+
promise.cancel = function () {
|
|
97
|
+
source.cancel('Query was cancelled by React Query');
|
|
98
|
+
};
|
|
99
|
+
return promise;
|
|
100
|
+
};
|