@channel.io/app-sdk-server 0.1.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.
- package/dist/__tests__/decorators.test.d.ts +2 -0
- package/dist/__tests__/decorators.test.d.ts.map +1 -0
- package/dist/__tests__/decorators.test.js +259 -0
- package/dist/__tests__/decorators.test.js.map +1 -0
- package/dist/__tests__/testing-utils.test.d.ts +2 -0
- package/dist/__tests__/testing-utils.test.d.ts.map +1 -0
- package/dist/__tests__/testing-utils.test.js +118 -0
- package/dist/__tests__/testing-utils.test.js.map +1 -0
- package/dist/appstore/client.d.ts +70 -0
- package/dist/appstore/client.d.ts.map +1 -0
- package/dist/appstore/client.js +141 -0
- package/dist/appstore/client.js.map +1 -0
- package/dist/appstore/index.d.ts +3 -0
- package/dist/appstore/index.d.ts.map +1 -0
- package/dist/appstore/index.js +3 -0
- package/dist/appstore/index.js.map +1 -0
- package/dist/appstore/types.d.ts +87 -0
- package/dist/appstore/types.d.ts.map +1 -0
- package/dist/appstore/types.js +5 -0
- package/dist/appstore/types.js.map +1 -0
- package/dist/decorators/extension.decorator.d.ts +33 -0
- package/dist/decorators/extension.decorator.d.ts.map +1 -0
- package/dist/decorators/extension.decorator.js +36 -0
- package/dist/decorators/extension.decorator.js.map +1 -0
- package/dist/decorators/function.decorator.d.ts +34 -0
- package/dist/decorators/function.decorator.d.ts.map +1 -0
- package/dist/decorators/function.decorator.js +45 -0
- package/dist/decorators/function.decorator.js.map +1 -0
- package/dist/decorators/index.d.ts +5 -0
- package/dist/decorators/index.d.ts.map +1 -0
- package/dist/decorators/index.js +9 -0
- package/dist/decorators/index.js.map +1 -0
- package/dist/decorators/param.decorator.d.ts +49 -0
- package/dist/decorators/param.decorator.d.ts.map +1 -0
- package/dist/decorators/param.decorator.js +62 -0
- package/dist/decorators/param.decorator.js.map +1 -0
- package/dist/decorators/schema.decorator.d.ts +48 -0
- package/dist/decorators/schema.decorator.d.ts.map +1 -0
- package/dist/decorators/schema.decorator.js +59 -0
- package/dist/decorators/schema.decorator.js.map +1 -0
- package/dist/discovery/extension-discovery.service.d.ts +45 -0
- package/dist/discovery/extension-discovery.service.d.ts.map +1 -0
- package/dist/discovery/extension-discovery.service.js +192 -0
- package/dist/discovery/extension-discovery.service.js.map +1 -0
- package/dist/discovery/index.d.ts +3 -0
- package/dist/discovery/index.d.ts.map +1 -0
- package/dist/discovery/index.js +2 -0
- package/dist/discovery/index.js.map +1 -0
- package/dist/discovery/metadata.interface.d.ts +42 -0
- package/dist/discovery/metadata.interface.d.ts.map +1 -0
- package/dist/discovery/metadata.interface.js +2 -0
- package/dist/discovery/metadata.interface.js.map +1 -0
- package/dist/guards/index.d.ts +3 -0
- package/dist/guards/index.d.ts.map +1 -0
- package/dist/guards/index.js +3 -0
- package/dist/guards/index.js.map +1 -0
- package/dist/guards/signature.guard.d.ts +65 -0
- package/dist/guards/signature.guard.d.ts.map +1 -0
- package/dist/guards/signature.guard.js +156 -0
- package/dist/guards/signature.guard.js.map +1 -0
- package/dist/guards/signature.middleware.d.ts +76 -0
- package/dist/guards/signature.middleware.d.ts.map +1 -0
- package/dist/guards/signature.middleware.js +110 -0
- package/dist/guards/signature.middleware.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/native/client.d.ts +105 -0
- package/dist/native/client.d.ts.map +1 -0
- package/dist/native/client.js +210 -0
- package/dist/native/client.js.map +1 -0
- package/dist/native/index.d.ts +3 -0
- package/dist/native/index.d.ts.map +1 -0
- package/dist/native/index.js +3 -0
- package/dist/native/index.js.map +1 -0
- package/dist/native/types.d.ts +198 -0
- package/dist/native/types.d.ts.map +1 -0
- package/dist/native/types.js +8 -0
- package/dist/native/types.js.map +1 -0
- package/dist/nestjs/channel-app.controller.d.ts +22 -0
- package/dist/nestjs/channel-app.controller.d.ts.map +1 -0
- package/dist/nestjs/channel-app.controller.js +87 -0
- package/dist/nestjs/channel-app.controller.js.map +1 -0
- package/dist/nestjs/channel-app.module.d.ts +47 -0
- package/dist/nestjs/channel-app.module.d.ts.map +1 -0
- package/dist/nestjs/channel-app.module.js +93 -0
- package/dist/nestjs/channel-app.module.js.map +1 -0
- package/dist/nestjs/channel-app.service.d.ts +44 -0
- package/dist/nestjs/channel-app.service.d.ts.map +1 -0
- package/dist/nestjs/channel-app.service.js +190 -0
- package/dist/nestjs/channel-app.service.js.map +1 -0
- package/dist/nestjs/index.d.ts +5 -0
- package/dist/nestjs/index.d.ts.map +1 -0
- package/dist/nestjs/index.js +5 -0
- package/dist/nestjs/index.js.map +1 -0
- package/dist/nestjs/types.d.ts +70 -0
- package/dist/nestjs/types.d.ts.map +1 -0
- package/dist/nestjs/types.js +5 -0
- package/dist/nestjs/types.js.map +1 -0
- package/dist/simple/channel-app.d.ts +80 -0
- package/dist/simple/channel-app.d.ts.map +1 -0
- package/dist/simple/channel-app.js +253 -0
- package/dist/simple/channel-app.js.map +1 -0
- package/dist/simple/index.d.ts +2 -0
- package/dist/simple/index.d.ts.map +1 -0
- package/dist/simple/index.js +2 -0
- package/dist/simple/index.js.map +1 -0
- package/dist/testing/index.d.ts +9 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +9 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/mock-context.d.ts +32 -0
- package/dist/testing/mock-context.d.ts.map +1 -0
- package/dist/testing/mock-context.js +33 -0
- package/dist/testing/mock-context.js.map +1 -0
- package/dist/testing/test-extension.d.ts +60 -0
- package/dist/testing/test-extension.d.ts.map +1 -0
- package/dist/testing/test-extension.js +113 -0
- package/dist/testing/test-extension.js.map +1 -0
- package/dist/token/cache.d.ts +31 -0
- package/dist/token/cache.d.ts.map +1 -0
- package/dist/token/cache.js +69 -0
- package/dist/token/cache.js.map +1 -0
- package/dist/token/index.d.ts +4 -0
- package/dist/token/index.d.ts.map +1 -0
- package/dist/token/index.js +4 -0
- package/dist/token/index.js.map +1 -0
- package/dist/token/manager.d.ts +111 -0
- package/dist/token/manager.d.ts.map +1 -0
- package/dist/token/manager.js +246 -0
- package/dist/token/manager.js.map +1 -0
- package/dist/token/types.d.ts +85 -0
- package/dist/token/types.d.ts.map +1 -0
- package/dist/token/types.js +5 -0
- package/dist/token/types.js.map +1 -0
- package/package.json +69 -0
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import { InMemoryTokenCache } from "./cache.js";
|
|
2
|
+
/**
|
|
3
|
+
* Default refresh buffer: 5 minutes before expiry
|
|
4
|
+
*/
|
|
5
|
+
const DEFAULT_REFRESH_BUFFER_MS = 5 * 60 * 1000;
|
|
6
|
+
/**
|
|
7
|
+
* Default Channel.io API base URL
|
|
8
|
+
*/
|
|
9
|
+
const DEFAULT_API_BASE_URL = "https://api.channel.io";
|
|
10
|
+
/**
|
|
11
|
+
* Token manager for Channel.io App SDK
|
|
12
|
+
*
|
|
13
|
+
* Handles token issuance, caching, and automatic refresh for:
|
|
14
|
+
* - Manager tokens (for desk/agent operations)
|
|
15
|
+
* - User tokens (for user-facing operations)
|
|
16
|
+
* - Channel tokens (for channel-level operations)
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* import { TokenManager } from '@channel.io/app-sdk-server';
|
|
21
|
+
*
|
|
22
|
+
* const tokenManager = new TokenManager({
|
|
23
|
+
* appId: process.env.APP_ID,
|
|
24
|
+
* appSecret: process.env.APP_SECRET,
|
|
25
|
+
* });
|
|
26
|
+
*
|
|
27
|
+
* // Get a manager token (with automatic caching and refresh)
|
|
28
|
+
* const token = await tokenManager.getManagerToken({
|
|
29
|
+
* channelId: 'channel-123',
|
|
30
|
+
* managerId: 'manager-456',
|
|
31
|
+
* });
|
|
32
|
+
*
|
|
33
|
+
* // Use the token for API calls
|
|
34
|
+
* await fetch('https://api.channel.io/...', {
|
|
35
|
+
* headers: {
|
|
36
|
+
* 'Authorization': `Bearer ${token.accessToken}`,
|
|
37
|
+
* },
|
|
38
|
+
* });
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export class TokenManager {
|
|
42
|
+
config;
|
|
43
|
+
cache;
|
|
44
|
+
debug;
|
|
45
|
+
constructor(config) {
|
|
46
|
+
this.config = {
|
|
47
|
+
...config,
|
|
48
|
+
apiBaseUrl: config.apiBaseUrl ?? DEFAULT_API_BASE_URL,
|
|
49
|
+
refreshBufferMs: config.refreshBufferMs ?? DEFAULT_REFRESH_BUFFER_MS,
|
|
50
|
+
};
|
|
51
|
+
this.cache = config.cacheStorage ?? new InMemoryTokenCache();
|
|
52
|
+
this.debug = config.debug ?? false;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Get a manager token with automatic caching and refresh
|
|
56
|
+
*/
|
|
57
|
+
async getManagerToken(request) {
|
|
58
|
+
const cacheKey = this.buildCacheKey("manager", request.channelId, request.managerId);
|
|
59
|
+
return this.getOrRefreshToken(cacheKey, () => this.issueManagerToken(request));
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Get a user token with automatic caching and refresh
|
|
63
|
+
*/
|
|
64
|
+
async getUserToken(request) {
|
|
65
|
+
const cacheKey = this.buildCacheKey("user", request.channelId, request.userId);
|
|
66
|
+
return this.getOrRefreshToken(cacheKey, () => this.issueUserToken(request));
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Get a channel token with automatic caching and refresh
|
|
70
|
+
*/
|
|
71
|
+
async getChannelToken(request) {
|
|
72
|
+
const cacheKey = this.buildCacheKey("channel", request.channelId);
|
|
73
|
+
return this.getOrRefreshToken(cacheKey, () => this.issueChannelToken(request));
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Manually refresh a token (bypass cache)
|
|
77
|
+
*/
|
|
78
|
+
async refreshToken(refreshToken) {
|
|
79
|
+
const response = await this.apiRequest("/app/v1/token/refresh", {
|
|
80
|
+
method: "POST",
|
|
81
|
+
body: JSON.stringify({ refreshToken }),
|
|
82
|
+
});
|
|
83
|
+
return this.normalizeTokenResponse(response);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Invalidate a cached token
|
|
87
|
+
*/
|
|
88
|
+
async invalidateToken(type, channelId, entityId) {
|
|
89
|
+
const cacheKey = this.buildCacheKey(type, channelId, entityId);
|
|
90
|
+
await this.cache.delete(cacheKey);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Clear all cached tokens
|
|
94
|
+
*/
|
|
95
|
+
async clearCache() {
|
|
96
|
+
await this.cache.clear();
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Get or refresh a token with automatic caching
|
|
100
|
+
*/
|
|
101
|
+
async getOrRefreshToken(cacheKey, issueToken) {
|
|
102
|
+
// Try to get from cache
|
|
103
|
+
const cached = await this.cache.get(cacheKey);
|
|
104
|
+
if (cached) {
|
|
105
|
+
// Check if token needs refresh (within buffer period)
|
|
106
|
+
const now = Date.now();
|
|
107
|
+
const expiresAt = cached.token.expiresAt;
|
|
108
|
+
const needsRefresh = now >= expiresAt - this.config.refreshBufferMs;
|
|
109
|
+
if (!needsRefresh) {
|
|
110
|
+
this.log(`Cache hit for ${cacheKey}`);
|
|
111
|
+
return cached.token;
|
|
112
|
+
}
|
|
113
|
+
// Try to refresh using refresh token
|
|
114
|
+
this.log(`Token expiring soon, refreshing for ${cacheKey}`);
|
|
115
|
+
try {
|
|
116
|
+
const refreshed = await this.refreshToken(cached.token.refreshToken);
|
|
117
|
+
await this.cacheToken(cacheKey, refreshed);
|
|
118
|
+
return refreshed;
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
this.log(`Refresh failed, re-issuing token for ${cacheKey}`, error);
|
|
122
|
+
// Fall through to issue new token
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// Issue new token
|
|
126
|
+
this.log(`Issuing new token for ${cacheKey}`);
|
|
127
|
+
const token = await issueToken();
|
|
128
|
+
await this.cacheToken(cacheKey, token);
|
|
129
|
+
return token;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Issue a manager token
|
|
133
|
+
*/
|
|
134
|
+
async issueManagerToken(request) {
|
|
135
|
+
const response = await this.apiRequest(`/app/v1/channels/${request.channelId}/managers/${request.managerId}/token`, { method: "POST" });
|
|
136
|
+
return this.normalizeTokenResponse(response);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Issue a user token
|
|
140
|
+
*/
|
|
141
|
+
async issueUserToken(request) {
|
|
142
|
+
const response = await this.apiRequest(`/app/v1/channels/${request.channelId}/users/${request.userId}/token`, { method: "POST" });
|
|
143
|
+
return this.normalizeTokenResponse(response);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Issue a channel token
|
|
147
|
+
*/
|
|
148
|
+
async issueChannelToken(request) {
|
|
149
|
+
const response = await this.apiRequest(`/app/v1/channels/${request.channelId}/token`, { method: "POST" });
|
|
150
|
+
return this.normalizeTokenResponse(response);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Cache a token
|
|
154
|
+
*/
|
|
155
|
+
async cacheToken(key, token) {
|
|
156
|
+
const cached = {
|
|
157
|
+
token,
|
|
158
|
+
cachedAt: Date.now(),
|
|
159
|
+
key,
|
|
160
|
+
};
|
|
161
|
+
// TTL is until token expires
|
|
162
|
+
const ttlMs = token.expiresAt - Date.now();
|
|
163
|
+
await this.cache.set(key, cached, ttlMs > 0 ? ttlMs : undefined);
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Build a cache key
|
|
167
|
+
*/
|
|
168
|
+
buildCacheKey(type, channelId, entityId) {
|
|
169
|
+
const parts = [this.config.appId, type, channelId];
|
|
170
|
+
if (entityId)
|
|
171
|
+
parts.push(entityId);
|
|
172
|
+
return parts.join(":");
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Make an API request to Channel.io
|
|
176
|
+
*/
|
|
177
|
+
async apiRequest(path, options = {}) {
|
|
178
|
+
const url = `${this.config.apiBaseUrl}${path}`;
|
|
179
|
+
const headers = {
|
|
180
|
+
"Content-Type": "application/json",
|
|
181
|
+
"X-App-Id": this.config.appId,
|
|
182
|
+
"X-App-Secret": this.config.appSecret,
|
|
183
|
+
...options.headers,
|
|
184
|
+
};
|
|
185
|
+
const response = await fetch(url, {
|
|
186
|
+
...options,
|
|
187
|
+
headers,
|
|
188
|
+
});
|
|
189
|
+
if (!response.ok) {
|
|
190
|
+
const errorBody = await response.text();
|
|
191
|
+
throw new TokenManagerError(`API request failed: ${String(response.status)} ${response.statusText}`, response.status, errorBody);
|
|
192
|
+
}
|
|
193
|
+
return response.json();
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Normalize token response (handle different API response formats)
|
|
197
|
+
*/
|
|
198
|
+
normalizeTokenResponse(response) {
|
|
199
|
+
const expiresIn = response.expiresIn ?? response.expires_in ?? 3600;
|
|
200
|
+
const refreshTokenExpiresIn = response.refreshTokenExpiresIn ?? response.refresh_token_expires_in ?? 604800;
|
|
201
|
+
return {
|
|
202
|
+
accessToken: response.accessToken ?? response.access_token ?? "",
|
|
203
|
+
refreshToken: response.refreshToken ?? response.refresh_token ?? "",
|
|
204
|
+
expiresIn,
|
|
205
|
+
expiresAt: response.expiresAt ?? Date.now() + expiresIn * 1000,
|
|
206
|
+
refreshTokenExpiresAt: response.refreshTokenExpiresAt ?? Date.now() + refreshTokenExpiresIn * 1000,
|
|
207
|
+
tokenType: response.tokenType ?? response.token_type ?? "Bearer",
|
|
208
|
+
scopes: response.scopes ?? (response.scope ? response.scope.split(" ") : []),
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Debug logging
|
|
213
|
+
*/
|
|
214
|
+
log(message, error) {
|
|
215
|
+
if (this.debug) {
|
|
216
|
+
if (error) {
|
|
217
|
+
console.debug(`[TokenManager] ${message}`, error);
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
console.debug(`[TokenManager] ${message}`);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Cleanup resources (call when shutting down)
|
|
226
|
+
*/
|
|
227
|
+
destroy() {
|
|
228
|
+
if (this.cache instanceof InMemoryTokenCache) {
|
|
229
|
+
this.cache.destroy();
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Token manager error
|
|
235
|
+
*/
|
|
236
|
+
export class TokenManagerError extends Error {
|
|
237
|
+
statusCode;
|
|
238
|
+
responseBody;
|
|
239
|
+
constructor(message, statusCode, responseBody) {
|
|
240
|
+
super(message);
|
|
241
|
+
this.statusCode = statusCode;
|
|
242
|
+
this.responseBody = responseBody;
|
|
243
|
+
this.name = "TokenManagerError";
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
//# sourceMappingURL=manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/token/manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token types and interfaces for Channel.io App SDK
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Token response from Channel.io token issuance
|
|
6
|
+
*/
|
|
7
|
+
export interface TokenResponse {
|
|
8
|
+
/** Access token for API calls */
|
|
9
|
+
accessToken: string;
|
|
10
|
+
/** Refresh token for token renewal */
|
|
11
|
+
refreshToken: string;
|
|
12
|
+
/** Token expiration time in seconds */
|
|
13
|
+
expiresIn: number;
|
|
14
|
+
/** Token expiration timestamp (Unix milliseconds) */
|
|
15
|
+
expiresAt: number;
|
|
16
|
+
/** Refresh token expiration timestamp (Unix milliseconds) */
|
|
17
|
+
refreshTokenExpiresAt: number;
|
|
18
|
+
/** Token type (usually "Bearer") */
|
|
19
|
+
tokenType: string;
|
|
20
|
+
/** Granted scopes */
|
|
21
|
+
scopes: string[];
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Cached token entry with metadata
|
|
25
|
+
*/
|
|
26
|
+
export interface CachedToken {
|
|
27
|
+
/** The token response */
|
|
28
|
+
token: TokenResponse;
|
|
29
|
+
/** When this cache entry was created */
|
|
30
|
+
cachedAt: number;
|
|
31
|
+
/** Cache key identifier */
|
|
32
|
+
key: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Token cache storage interface
|
|
36
|
+
* Implement this to use custom storage (Redis, database, etc.)
|
|
37
|
+
*/
|
|
38
|
+
export interface TokenCacheStorage {
|
|
39
|
+
/** Get a cached token by key */
|
|
40
|
+
get(key: string): Promise<CachedToken | null>;
|
|
41
|
+
/** Set a cached token */
|
|
42
|
+
set(key: string, token: CachedToken, ttlMs?: number): Promise<void>;
|
|
43
|
+
/** Delete a cached token */
|
|
44
|
+
delete(key: string): Promise<void>;
|
|
45
|
+
/** Clear all cached tokens */
|
|
46
|
+
clear(): Promise<void>;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Token manager configuration
|
|
50
|
+
*/
|
|
51
|
+
export interface TokenManagerConfig {
|
|
52
|
+
/** App ID */
|
|
53
|
+
appId: string;
|
|
54
|
+
/** App secret */
|
|
55
|
+
appSecret: string;
|
|
56
|
+
/** Channel.io API base URL (default: https://api.channel.io) */
|
|
57
|
+
apiBaseUrl?: string;
|
|
58
|
+
/** Custom cache storage (default: in-memory) */
|
|
59
|
+
cacheStorage?: TokenCacheStorage;
|
|
60
|
+
/** Buffer time before expiry to trigger refresh (default: 5 minutes) */
|
|
61
|
+
refreshBufferMs?: number;
|
|
62
|
+
/** Enable debug logging */
|
|
63
|
+
debug?: boolean;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Token request for issuing manager token
|
|
67
|
+
*/
|
|
68
|
+
export interface ManagerTokenRequest {
|
|
69
|
+
channelId: string;
|
|
70
|
+
managerId: string;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Token request for issuing user token
|
|
74
|
+
*/
|
|
75
|
+
export interface UserTokenRequest {
|
|
76
|
+
channelId: string;
|
|
77
|
+
userId: string;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Token request for issuing channel token
|
|
81
|
+
*/
|
|
82
|
+
export interface ChannelTokenRequest {
|
|
83
|
+
channelId: string;
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/token/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,iCAAiC;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,YAAY,EAAE,MAAM,CAAC;IACrB,uCAAuC;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,SAAS,EAAE,MAAM,CAAC;IAClB,6DAA6D;IAC7D,qBAAqB,EAAE,MAAM,CAAC;IAC9B,oCAAoC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,qBAAqB;IACrB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,yBAAyB;IACzB,KAAK,EAAE,aAAa,CAAC;IACrB,wCAAwC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,2BAA2B;IAC3B,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,gCAAgC;IAChC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC9C,yBAAyB;IACzB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,4BAA4B;IAC5B,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,8BAA8B;IAC9B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,aAAa;IACb,KAAK,EAAE,MAAM,CAAC;IACd,iBAAiB;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,gEAAgE;IAChE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,YAAY,CAAC,EAAE,iBAAiB,CAAC;IACjC,wEAAwE;IACxE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;CACnB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/token/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
package/package.json
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@channel.io/app-sdk-server",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "NestJS server SDK for Channel.io apps",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./nestjs": {
|
|
14
|
+
"types": "./dist/nestjs/index.d.ts",
|
|
15
|
+
"import": "./dist/nestjs/index.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist"
|
|
20
|
+
],
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"zod": "^3.24.1",
|
|
23
|
+
"zod-to-json-schema": "^3.24.1",
|
|
24
|
+
"@channel.io/app-sdk-core": "0.1.0"
|
|
25
|
+
},
|
|
26
|
+
"peerDependencies": {
|
|
27
|
+
"@nestjs/common": ">=10.0.0",
|
|
28
|
+
"@nestjs/core": ">=10.0.0",
|
|
29
|
+
"reflect-metadata": ">=0.1.0"
|
|
30
|
+
},
|
|
31
|
+
"peerDependenciesMeta": {
|
|
32
|
+
"@nestjs/common": {
|
|
33
|
+
"optional": false
|
|
34
|
+
},
|
|
35
|
+
"@nestjs/core": {
|
|
36
|
+
"optional": false
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@nestjs/common": "^10.4.15",
|
|
41
|
+
"@nestjs/core": "^10.4.15",
|
|
42
|
+
"@nestjs/platform-express": "^10.4.15",
|
|
43
|
+
"@nestjs/testing": "^10.4.15",
|
|
44
|
+
"@types/express": "^5.0.6",
|
|
45
|
+
"reflect-metadata": "^0.2.2",
|
|
46
|
+
"rxjs": "^7.8.1",
|
|
47
|
+
"typescript": "^5.7.2",
|
|
48
|
+
"vitest": "^2.1.8"
|
|
49
|
+
},
|
|
50
|
+
"repository": {
|
|
51
|
+
"type": "git",
|
|
52
|
+
"url": "https://github.com/channel-io/app-sdk.git",
|
|
53
|
+
"directory": "packages/server"
|
|
54
|
+
},
|
|
55
|
+
"license": "MIT",
|
|
56
|
+
"publishConfig": {
|
|
57
|
+
"access": "public"
|
|
58
|
+
},
|
|
59
|
+
"scripts": {
|
|
60
|
+
"build": "tsc",
|
|
61
|
+
"dev": "tsc --watch",
|
|
62
|
+
"lint": "eslint src/",
|
|
63
|
+
"lint:fix": "eslint src/ --fix",
|
|
64
|
+
"typecheck": "tsc --noEmit",
|
|
65
|
+
"test": "vitest run",
|
|
66
|
+
"test:watch": "vitest",
|
|
67
|
+
"clean": "rm -rf dist"
|
|
68
|
+
}
|
|
69
|
+
}
|