@babelforce/manager-sdk 0.2.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/CHANGELOG.md +20 -0
- package/LICENSE +201 -0
- package/NOTICE +6 -0
- package/README.md +59 -0
- package/dist/index.d.ts +395 -0
- package/dist/index.js +592 -0
- package/package.json +40 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `@babelforce/manager-sdk` are documented here. This project adheres to
|
|
4
|
+
[Semantic Versioning](https://semver.org/).
|
|
5
|
+
|
|
6
|
+
## 0.2.0
|
|
7
|
+
|
|
8
|
+
- Add the `tasks` resource (v3 task automations): `create`, `createFromTemplate`, `list` /
|
|
9
|
+
`listAll` (auto-paginated), `get`, `update`, `interrupt`, plus `tasks.schedules`
|
|
10
|
+
(`list` / `create` / `get` / `delete`).
|
|
11
|
+
|
|
12
|
+
## 0.1.0
|
|
13
|
+
|
|
14
|
+
Initial release.
|
|
15
|
+
|
|
16
|
+
- `ManagerClient` facade with one-shot auth configuration.
|
|
17
|
+
- Auth modes: API key (`X-Auth-Access-Id` / `X-Auth-Access-Token`), bearer, and OAuth2 password
|
|
18
|
+
grant with transparent token refresh.
|
|
19
|
+
- `users` resource: auto-paginated `list()` / `listAll()`, `create`, `enable`, `disable`, `delete`.
|
|
20
|
+
- Typed `ManagerApiError` for non-2xx responses.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or Derivative
|
|
95
|
+
Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and do
|
|
117
|
+
not modify the License. You may add Your own attribution notices
|
|
118
|
+
within Derivative Works that You distribute, alongside or as an
|
|
119
|
+
addendum to the NOTICE text from the Work, provided that such
|
|
120
|
+
additional attribution notices cannot be construed as modifying
|
|
121
|
+
the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or additional liability.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
179
|
+
|
|
180
|
+
To apply the Apache License to your work, attach the following
|
|
181
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
182
|
+
replaced with your own identifying information. (Don't include
|
|
183
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
184
|
+
comment syntax for the file format. We also recommend that a
|
|
185
|
+
file or class name and description of purpose be included on the
|
|
186
|
+
same "printed page" as the copyright notice for easier
|
|
187
|
+
identification within third-party archives.
|
|
188
|
+
|
|
189
|
+
Copyright 2026 babelforce GmbH
|
|
190
|
+
|
|
191
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
|
+
you may not use this file except in compliance with the License.
|
|
193
|
+
You may obtain a copy of the License at
|
|
194
|
+
|
|
195
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
196
|
+
|
|
197
|
+
Unless required by applicable law or agreed to in writing, software
|
|
198
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
199
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
200
|
+
See the License for the specific language governing permissions and
|
|
201
|
+
limitations under the License.
|
package/NOTICE
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# @babelforce/manager-sdk
|
|
2
|
+
|
|
3
|
+
TypeScript SDK for the babelforce **manager APIs** — auth, user & agent management, call
|
|
4
|
+
reporting, metrics, and task automations.
|
|
5
|
+
|
|
6
|
+
One client, configured once, exposes resource namespaces over the API. Authentication, paging, and
|
|
7
|
+
error handling are handled for you.
|
|
8
|
+
|
|
9
|
+
📖 **Docs:** https://babelforce.github.io/manager-sdk/
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @babelforce/manager-sdk
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
ESM, ships with types. Node 18+ (for global `fetch`).
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import { ManagerClient } from "@babelforce/manager-sdk";
|
|
23
|
+
|
|
24
|
+
const mgr = await ManagerClient.connect({
|
|
25
|
+
environment: "production",
|
|
26
|
+
auth: { kind: "apiKey", accessId, accessToken }, // or { kind: "password", user, pass }
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// list users (auto-paginated)
|
|
30
|
+
for await (const user of mgr.users.list()) {
|
|
31
|
+
console.log(user.email);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
await mgr.users.create({ email: "new.user@acme.com", roles: [] });
|
|
35
|
+
await mgr.users.enable(["new.user@acme.com"]);
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Authentication
|
|
39
|
+
|
|
40
|
+
- `{ kind: "apiKey", accessId, accessToken }` — sends `X-Auth-Access-Id` / `X-Auth-Access-Token`.
|
|
41
|
+
- `{ kind: "bearer", token }` — a token you already hold.
|
|
42
|
+
- `{ kind: "password", user, pass }` — OAuth2 password grant with transparent refresh.
|
|
43
|
+
|
|
44
|
+
### Errors
|
|
45
|
+
|
|
46
|
+
Non-2xx responses throw a `ManagerApiError` with `status`, `code`, and `body`.
|
|
47
|
+
|
|
48
|
+
### Custom host
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
await ManagerClient.connect({
|
|
52
|
+
baseUrl: "https://acme.babelforce.com",
|
|
53
|
+
auth: { kind: "bearer", token },
|
|
54
|
+
});
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## License
|
|
58
|
+
|
|
59
|
+
Apache-2.0
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
import { Client } from '@hey-api/client-fetch';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* How the SDK authenticates against the manager API.
|
|
5
|
+
*
|
|
6
|
+
* - `apiKey` — the primary server-to-server mode; sends the `X-Auth-Access-Id` /
|
|
7
|
+
* `X-Auth-Access-Token` header pair on every request.
|
|
8
|
+
* - `bearer` — a bearer token you already obtained.
|
|
9
|
+
* - `password` — OAuth2 password grant against `/oauth/token`; the token is fetched lazily on the
|
|
10
|
+
* first request and refreshed transparently before it expires. Convenience for interactive/dev use.
|
|
11
|
+
*/
|
|
12
|
+
type Auth = {
|
|
13
|
+
kind: 'apiKey';
|
|
14
|
+
accessId: string;
|
|
15
|
+
accessToken: string;
|
|
16
|
+
} | {
|
|
17
|
+
kind: 'bearer';
|
|
18
|
+
token: string;
|
|
19
|
+
} | {
|
|
20
|
+
kind: 'password';
|
|
21
|
+
user: string;
|
|
22
|
+
pass: string;
|
|
23
|
+
clientId?: string;
|
|
24
|
+
};
|
|
25
|
+
interface TokenResponse {
|
|
26
|
+
access_token: string;
|
|
27
|
+
expires_in?: number;
|
|
28
|
+
token_type?: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Exchange a username/password for a bearer token via the manager OAuth2 password grant
|
|
32
|
+
* (`POST {baseUrl}/oauth/token`). Exposed for callers who want to manage tokens themselves.
|
|
33
|
+
*/
|
|
34
|
+
declare function passwordGrant(opts: {
|
|
35
|
+
baseUrl: string;
|
|
36
|
+
user: string;
|
|
37
|
+
pass: string;
|
|
38
|
+
clientId?: string;
|
|
39
|
+
fetch?: typeof fetch;
|
|
40
|
+
}): Promise<TokenResponse>;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Named babelforce environment the SDK can target. Use the `baseUrl` option to target other
|
|
44
|
+
* (e.g. per-customer or non-production) hosts.
|
|
45
|
+
*/
|
|
46
|
+
type Environment = 'production';
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* A role associated with the Account
|
|
50
|
+
*/
|
|
51
|
+
type AccountRole = 'manager' | 'owner' | 'reporter' | 'user' | 'agent' | 'supervisor' | 'sales' | 'router' | 'scheduler';
|
|
52
|
+
type CreateManagedUserRequest = {
|
|
53
|
+
password?: string;
|
|
54
|
+
email: string;
|
|
55
|
+
activated?: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* A List of Roles which are associated with the current User
|
|
58
|
+
*/
|
|
59
|
+
roles: Array<AccountRole>;
|
|
60
|
+
};
|
|
61
|
+
type ManagedUser = {
|
|
62
|
+
/**
|
|
63
|
+
* The unique Identifier (UUID) of the object
|
|
64
|
+
*/
|
|
65
|
+
id: string;
|
|
66
|
+
email: string;
|
|
67
|
+
enabled?: boolean;
|
|
68
|
+
/**
|
|
69
|
+
* A List of Roles which are associated with the current User
|
|
70
|
+
*/
|
|
71
|
+
roles: Array<AccountRole>;
|
|
72
|
+
};
|
|
73
|
+
type ManagedUserItemResponse = {
|
|
74
|
+
item: ManagedUser;
|
|
75
|
+
/**
|
|
76
|
+
* Whether the Request was successful or not
|
|
77
|
+
*/
|
|
78
|
+
success: boolean;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
interface ListUsersQuery {
|
|
82
|
+
/** Filter by email address. */
|
|
83
|
+
email?: string;
|
|
84
|
+
}
|
|
85
|
+
/** User management — `/api/v2/users`. */
|
|
86
|
+
declare class UsersResource {
|
|
87
|
+
private readonly client;
|
|
88
|
+
constructor(client: Client);
|
|
89
|
+
/**
|
|
90
|
+
* List users, auto-paginating across pages.
|
|
91
|
+
*
|
|
92
|
+
* ```ts
|
|
93
|
+
* for await (const user of mgr.users.list()) console.log(user.email);
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
list(query?: ListUsersQuery): AsyncGenerator<ManagedUser>;
|
|
97
|
+
/** Collect every user into an array (convenience over {@link list}). */
|
|
98
|
+
listAll(query?: ListUsersQuery): Promise<ManagedUser[]>;
|
|
99
|
+
/** Create a user. */
|
|
100
|
+
create(user: CreateManagedUserRequest): Promise<ManagedUserItemResponse>;
|
|
101
|
+
/** Enable the given users (by email). */
|
|
102
|
+
enable(emails: string[]): Promise<void>;
|
|
103
|
+
/** Disable the given users (by email). */
|
|
104
|
+
disable(emails: string[]): Promise<void>;
|
|
105
|
+
/** Delete the given users (by email). */
|
|
106
|
+
delete(emails: string[]): Promise<void>;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* a unique identifier
|
|
111
|
+
*/
|
|
112
|
+
type Id = string;
|
|
113
|
+
/**
|
|
114
|
+
* a unique identifier
|
|
115
|
+
*/
|
|
116
|
+
type Uuid = string;
|
|
117
|
+
/**
|
|
118
|
+
* Timestamp in milliseconds UTC
|
|
119
|
+
*/
|
|
120
|
+
type TimestampInMsUtc = number;
|
|
121
|
+
/**
|
|
122
|
+
* Milliseconds
|
|
123
|
+
*/
|
|
124
|
+
type Milliseconds = number;
|
|
125
|
+
type TaskType = string;
|
|
126
|
+
type TaskCompletionSettings = {
|
|
127
|
+
/**
|
|
128
|
+
* True = tasks are not waiting for agent interactions when pending. False = task may wait forever in pending state until an agent or the system completes the task.
|
|
129
|
+
*/
|
|
130
|
+
autoComplete?: boolean;
|
|
131
|
+
};
|
|
132
|
+
/**
|
|
133
|
+
* Time in milliseconds the agent has to accept a task before it is auto rejected.
|
|
134
|
+
*/
|
|
135
|
+
type AcceptTimeout = number;
|
|
136
|
+
/**
|
|
137
|
+
* Time in milliseconds the agent has to complete a task before it is auto canceled.
|
|
138
|
+
*/
|
|
139
|
+
type CompleteTimeout = number;
|
|
140
|
+
/**
|
|
141
|
+
* Time in milliseconds the task is delayed after rescheduling.
|
|
142
|
+
*/
|
|
143
|
+
type RescheduleDelay = number;
|
|
144
|
+
/**
|
|
145
|
+
* A time in milliseconds after task scheduling, if it is reached the task will be canceled
|
|
146
|
+
*/
|
|
147
|
+
type ExpireIn = number;
|
|
148
|
+
type SelectionEngine = 'legacy' | 'acd';
|
|
149
|
+
type TaskSelectionSettings = {
|
|
150
|
+
/**
|
|
151
|
+
* True = agent selection is enabled False = No agent selection will be attempted
|
|
152
|
+
*/
|
|
153
|
+
enable?: boolean;
|
|
154
|
+
/**
|
|
155
|
+
* True = the selected agent has to accept the task before it will be assigned to him. False = the agent will get the task forceably assigned
|
|
156
|
+
*/
|
|
157
|
+
auto_accept?: boolean;
|
|
158
|
+
/**
|
|
159
|
+
* 0 = lowest priority ... 256 = higher priority ... max integer = highest priority
|
|
160
|
+
*/
|
|
161
|
+
priority?: number;
|
|
162
|
+
expire_in?: ExpireIn;
|
|
163
|
+
accept_timeout?: AcceptTimeout;
|
|
164
|
+
complete_timeout?: CompleteTimeout;
|
|
165
|
+
reschedule_delay?: RescheduleDelay;
|
|
166
|
+
selection_engine?: SelectionEngine;
|
|
167
|
+
legacy_settings?: TaskSelectionLegacySettings;
|
|
168
|
+
acd_settings?: TaskSelectionAcdSettings;
|
|
169
|
+
};
|
|
170
|
+
type TaskSelectionLegacySettings = {
|
|
171
|
+
line_status?: string;
|
|
172
|
+
reachable_by_phone?: boolean;
|
|
173
|
+
max?: number;
|
|
174
|
+
call_id?: string;
|
|
175
|
+
exclusive?: boolean;
|
|
176
|
+
};
|
|
177
|
+
type TaskSelectionAcdSettings = {
|
|
178
|
+
line_status?: string;
|
|
179
|
+
reachable_by_phone?: boolean;
|
|
180
|
+
priority?: number;
|
|
181
|
+
timeout?: number;
|
|
182
|
+
};
|
|
183
|
+
type ActionSetting = {
|
|
184
|
+
transitions: TaskStateEvents;
|
|
185
|
+
/**
|
|
186
|
+
* When set to true, action events on_* will run asynchronously with further state transitions.action will not block
|
|
187
|
+
*/
|
|
188
|
+
async?: boolean;
|
|
189
|
+
timeout?: Milliseconds;
|
|
190
|
+
};
|
|
191
|
+
type TaskStateEvents = 'on_scheduled' | 'on_rescheduled' | 'on_selecting' | 'on_accepted' | 'on_rejected' | 'on_assigned' | 'on_processing' | 'on_pending' | 'on_completed' | 'on_canceled' | 'on_failed';
|
|
192
|
+
type TaskState = 'Scheduled' | 'Rescheduled' | 'Selecting' | 'Accepted' | 'Rejected' | 'Assigned' | 'Processing' | 'Pending' | 'Completed' | 'Canceled' | 'Failed';
|
|
193
|
+
type Actions = {
|
|
194
|
+
on_scheduled?: Array<Action>;
|
|
195
|
+
on_rescheduled?: Array<Action>;
|
|
196
|
+
on_selecting?: Array<Action>;
|
|
197
|
+
on_accepted?: Array<Action>;
|
|
198
|
+
on_rejected?: Array<Action>;
|
|
199
|
+
on_assigned?: Array<Action>;
|
|
200
|
+
on_processing?: Array<Action>;
|
|
201
|
+
on_pending?: Array<Action>;
|
|
202
|
+
on_completed?: Array<Action>;
|
|
203
|
+
on_canceled?: Array<Action>;
|
|
204
|
+
on_failed?: Array<Action>;
|
|
205
|
+
settings?: Array<ActionSetting>;
|
|
206
|
+
};
|
|
207
|
+
type Action = {
|
|
208
|
+
action_type: string;
|
|
209
|
+
[key: string]: unknown | string;
|
|
210
|
+
};
|
|
211
|
+
type Body = unknown;
|
|
212
|
+
/**
|
|
213
|
+
* true - an error occured during task execution, false - no errors during execution
|
|
214
|
+
*/
|
|
215
|
+
type _Error = boolean;
|
|
216
|
+
/**
|
|
217
|
+
* defines when the task will be scheduled for execution. now - as soon as possible at 1654075565950 - at the given timestamp in 1w 3d 5h 10min 5sec - in 1 week 3 days 5 hours 10 minutes and 5 seconds
|
|
218
|
+
*/
|
|
219
|
+
type ScheduledAt = string;
|
|
220
|
+
type SubmitTask = {
|
|
221
|
+
id?: Uuid;
|
|
222
|
+
queue_id?: Id;
|
|
223
|
+
type?: TaskType;
|
|
224
|
+
body?: Body;
|
|
225
|
+
actions?: Actions;
|
|
226
|
+
task_completion?: TaskCompletionSettings;
|
|
227
|
+
selection_settings?: TaskSelectionSettings;
|
|
228
|
+
scheduled_at?: ScheduledAt;
|
|
229
|
+
};
|
|
230
|
+
type BaseTask = {
|
|
231
|
+
id?: Uuid;
|
|
232
|
+
queue_id?: Id;
|
|
233
|
+
session_id?: Id;
|
|
234
|
+
customer_id?: Id;
|
|
235
|
+
agent_id?: Id;
|
|
236
|
+
created_at?: TimestampInMsUtc;
|
|
237
|
+
body: Body;
|
|
238
|
+
type?: TaskType;
|
|
239
|
+
state?: TaskState;
|
|
240
|
+
actions?: Actions;
|
|
241
|
+
task_completion?: TaskCompletionSettings;
|
|
242
|
+
selection_settings?: TaskSelectionSettings;
|
|
243
|
+
scheduled_at?: ScheduledAt;
|
|
244
|
+
};
|
|
245
|
+
type Task = BaseTask & {
|
|
246
|
+
has_error?: _Error;
|
|
247
|
+
};
|
|
248
|
+
type InterruptionTargetStates = 'Completed' | 'Canceled' | 'Failed';
|
|
249
|
+
type ManualActionRequest = {
|
|
250
|
+
reason: string;
|
|
251
|
+
};
|
|
252
|
+
type TemplateOverride = {
|
|
253
|
+
[key: string]: unknown;
|
|
254
|
+
};
|
|
255
|
+
type SubmitTaskBody = SubmitTask;
|
|
256
|
+
type UpdateTaskBody = Task;
|
|
257
|
+
type ManualAction = ManualActionRequest;
|
|
258
|
+
type TaskTemplateOverrides = TemplateOverride;
|
|
259
|
+
|
|
260
|
+
type PageMetadata = {
|
|
261
|
+
page?: number;
|
|
262
|
+
per_page?: number;
|
|
263
|
+
page_count?: number;
|
|
264
|
+
total_count?: number;
|
|
265
|
+
};
|
|
266
|
+
type TemplateStyle = 'flat' | 'hierarchy';
|
|
267
|
+
/**
|
|
268
|
+
* A valid IANA timezone for examples see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. Note: Be careful when setting fire times between the hours of the morning when “daylight savings” changes occur in your locale (for US locales, this would typically be the hour before and after 2:00 AM - because the time shift can cause a skip or a repeat depending on whether the time moves back or jumps forward. You may find this wikipedia entry helpful in determining the specifics to your locale https://secure.wikimedia.org/wikipedia/en/wiki/Daylight_saving_time_around_the_world
|
|
269
|
+
*/
|
|
270
|
+
type Timezone = string;
|
|
271
|
+
type SubmitTaskSchedule = {
|
|
272
|
+
cron: string;
|
|
273
|
+
name: string;
|
|
274
|
+
task: {
|
|
275
|
+
[key: string]: unknown;
|
|
276
|
+
};
|
|
277
|
+
template_id?: string;
|
|
278
|
+
template_style?: TemplateStyle;
|
|
279
|
+
timezone?: Timezone;
|
|
280
|
+
};
|
|
281
|
+
type TaskSchedule = {
|
|
282
|
+
cron: string;
|
|
283
|
+
name?: string;
|
|
284
|
+
task?: {
|
|
285
|
+
[key: string]: unknown;
|
|
286
|
+
};
|
|
287
|
+
template_id?: string;
|
|
288
|
+
template_style?: TemplateStyle;
|
|
289
|
+
timezone?: Timezone;
|
|
290
|
+
};
|
|
291
|
+
type TaskScheduleList = {
|
|
292
|
+
_metadata?: PageMetadata;
|
|
293
|
+
records?: Array<TaskSchedule>;
|
|
294
|
+
};
|
|
295
|
+
type SubmitTaskScheduleBody = SubmitTaskSchedule;
|
|
296
|
+
|
|
297
|
+
interface ListTasksQuery {
|
|
298
|
+
/** Server-side filter expression. */
|
|
299
|
+
filter?: string;
|
|
300
|
+
/** Page size (1..100); defaults to 100. */
|
|
301
|
+
pageSize?: number;
|
|
302
|
+
}
|
|
303
|
+
/** Task automations — `/api/v3/tasks`. */
|
|
304
|
+
declare class TasksResource {
|
|
305
|
+
private readonly client;
|
|
306
|
+
/** Recurring task schedules — `/api/v3/tasks/schedules`. */
|
|
307
|
+
readonly schedules: TaskSchedulesResource;
|
|
308
|
+
constructor(client: Client);
|
|
309
|
+
/**
|
|
310
|
+
* List tasks, auto-paginating across pages.
|
|
311
|
+
*
|
|
312
|
+
* ```ts
|
|
313
|
+
* for await (const task of mgr.tasks.list({ filter: "state==active" })) { … }
|
|
314
|
+
* ```
|
|
315
|
+
*/
|
|
316
|
+
list(query?: ListTasksQuery): AsyncGenerator<Task>;
|
|
317
|
+
/** Collect every task into an array. */
|
|
318
|
+
listAll(query?: ListTasksQuery): Promise<Task[]>;
|
|
319
|
+
/** Create a task. */
|
|
320
|
+
create(body: SubmitTaskBody): Promise<Task>;
|
|
321
|
+
/** Create a task from a template, with overrides. */
|
|
322
|
+
createFromTemplate(template: string, overrides: TaskTemplateOverrides): Promise<Task>;
|
|
323
|
+
/** Get a task by id. */
|
|
324
|
+
get(taskId: string): Promise<Task>;
|
|
325
|
+
/** Update a task. */
|
|
326
|
+
update(taskId: string, body: UpdateTaskBody): Promise<Task>;
|
|
327
|
+
/** Manager-interrupt a task, transitioning it to the given target state. */
|
|
328
|
+
interrupt(taskId: string, interruptTo: InterruptionTargetStates, action?: ManualAction): Promise<void>;
|
|
329
|
+
}
|
|
330
|
+
/** Recurring task schedules — `/api/v3/tasks/schedules`. */
|
|
331
|
+
declare class TaskSchedulesResource {
|
|
332
|
+
private readonly client;
|
|
333
|
+
constructor(client: Client);
|
|
334
|
+
/** List task schedules. */
|
|
335
|
+
list(): Promise<TaskScheduleList>;
|
|
336
|
+
/** Create a task schedule. */
|
|
337
|
+
create(schedule: SubmitTaskScheduleBody): Promise<void>;
|
|
338
|
+
/** Get a task schedule by name. */
|
|
339
|
+
get(taskScheduleName: string): Promise<TaskSchedule>;
|
|
340
|
+
/** Delete a task schedule by name. */
|
|
341
|
+
delete(taskScheduleName: string): Promise<void>;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
interface ManagerClientOptions {
|
|
345
|
+
/** Named environment whose host to use. Defaults to `production`. Ignored if `baseUrl` is set. */
|
|
346
|
+
environment?: Environment;
|
|
347
|
+
/** Explicit base URL override (e.g. a per-customer host). */
|
|
348
|
+
baseUrl?: string;
|
|
349
|
+
/** How to authenticate. */
|
|
350
|
+
auth: Auth;
|
|
351
|
+
/** Extra headers added to every request. */
|
|
352
|
+
headers?: Record<string, string>;
|
|
353
|
+
/** Custom fetch implementation (testing, proxies, retries). */
|
|
354
|
+
fetch?: typeof fetch;
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* The babelforce manager SDK client.
|
|
358
|
+
*
|
|
359
|
+
* One client, configured once, exposes resource namespaces over the manager API. The underlying
|
|
360
|
+
* generated clients and the v2/v3 host details are hidden behind this facade.
|
|
361
|
+
*
|
|
362
|
+
* ```ts
|
|
363
|
+
* const mgr = await ManagerClient.connect({
|
|
364
|
+
* environment: "production",
|
|
365
|
+
* auth: { kind: "apiKey", accessId, accessToken },
|
|
366
|
+
* });
|
|
367
|
+
* for await (const u of mgr.users.list()) console.log(u.email);
|
|
368
|
+
* ```
|
|
369
|
+
*/
|
|
370
|
+
declare class ManagerClient {
|
|
371
|
+
/** The underlying fetch client (escape hatch for advanced use). */
|
|
372
|
+
readonly client: Client;
|
|
373
|
+
/** User management — `/api/v2/users`. */
|
|
374
|
+
readonly users: UsersResource;
|
|
375
|
+
/** Task automations — `/api/v3/tasks`. */
|
|
376
|
+
readonly tasks: TasksResource;
|
|
377
|
+
private constructor();
|
|
378
|
+
/** Create and configure a client. */
|
|
379
|
+
static connect(options: ManagerClientOptions): Promise<ManagerClient>;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/** Error thrown by the SDK when the manager API returns a non-2xx response. */
|
|
383
|
+
declare class ManagerApiError extends Error {
|
|
384
|
+
/** HTTP status code. */
|
|
385
|
+
readonly status: number;
|
|
386
|
+
/** API error code, when the response body carries one. */
|
|
387
|
+
readonly code?: string;
|
|
388
|
+
/** The parsed response body (object, string, or undefined). */
|
|
389
|
+
readonly body: unknown;
|
|
390
|
+
constructor(status: number, message: string, body: unknown, code?: string);
|
|
391
|
+
/** Build a {@link ManagerApiError} from a fetch Response and its (already-parsed) body. */
|
|
392
|
+
static from(response: Response, body: unknown): ManagerApiError;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
export { type AccountRole, type Auth, type CreateManagedUserRequest, type Environment, type InterruptionTargetStates, type ListTasksQuery, type ListUsersQuery, type ManagedUser, type ManagedUserItemResponse, ManagerApiError, ManagerClient, type ManagerClientOptions, type SubmitTaskBody, type SubmitTaskScheduleBody, type Task, type TaskSchedule, TaskSchedulesResource, type TaskTemplateOverrides, TasksResource, type TokenResponse, type UpdateTaskBody, UsersResource, passwordGrant };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,592 @@
|
|
|
1
|
+
import { createClient, createConfig } from '@hey-api/client-fetch';
|
|
2
|
+
|
|
3
|
+
// src/client.ts
|
|
4
|
+
|
|
5
|
+
// src/auth.ts
|
|
6
|
+
async function passwordGrant(opts) {
|
|
7
|
+
const base = opts.baseUrl.replace(/\/+$/, "");
|
|
8
|
+
const body = new URLSearchParams({
|
|
9
|
+
grant_type: "password",
|
|
10
|
+
username: opts.user,
|
|
11
|
+
password: opts.pass,
|
|
12
|
+
client_id: opts.clientId ?? "manager"
|
|
13
|
+
});
|
|
14
|
+
const doFetch = opts.fetch ?? fetch;
|
|
15
|
+
const resp = await doFetch(`${base}/oauth/token`, {
|
|
16
|
+
method: "POST",
|
|
17
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
18
|
+
body
|
|
19
|
+
});
|
|
20
|
+
const json = await resp.json().catch(() => ({}));
|
|
21
|
+
if (!resp.ok || !json.access_token) {
|
|
22
|
+
throw new Error(`password grant failed (status ${resp.status})`);
|
|
23
|
+
}
|
|
24
|
+
return json;
|
|
25
|
+
}
|
|
26
|
+
var TokenManager = class {
|
|
27
|
+
constructor(baseUrl, creds, fetchImpl) {
|
|
28
|
+
this.baseUrl = baseUrl;
|
|
29
|
+
this.creds = creds;
|
|
30
|
+
this.fetchImpl = fetchImpl;
|
|
31
|
+
}
|
|
32
|
+
baseUrl;
|
|
33
|
+
creds;
|
|
34
|
+
fetchImpl;
|
|
35
|
+
token;
|
|
36
|
+
expiresAt = 0;
|
|
37
|
+
async get() {
|
|
38
|
+
if (this.token && Date.now() < this.expiresAt - 3e4) return this.token;
|
|
39
|
+
const tok = await passwordGrant({ baseUrl: this.baseUrl, ...this.creds, fetch: this.fetchImpl });
|
|
40
|
+
this.token = tok.access_token;
|
|
41
|
+
this.expiresAt = Date.now() + (tok.expires_in ? tok.expires_in * 1e3 : 36e5);
|
|
42
|
+
return this.token;
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
function buildAuthConfig(auth, baseUrl, fetchImpl) {
|
|
46
|
+
switch (auth.kind) {
|
|
47
|
+
case "apiKey":
|
|
48
|
+
return {
|
|
49
|
+
headers: {
|
|
50
|
+
"X-Auth-Access-Id": auth.accessId,
|
|
51
|
+
"X-Auth-Access-Token": auth.accessToken
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
case "bearer":
|
|
55
|
+
return { auth: (scheme) => scheme.scheme === "bearer" ? auth.token : void 0 };
|
|
56
|
+
case "password": {
|
|
57
|
+
const tokens = new TokenManager(baseUrl, auth, fetchImpl);
|
|
58
|
+
return { auth: (scheme) => scheme.scheme === "bearer" ? tokens.get() : void 0 };
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// src/environments.ts
|
|
64
|
+
var HOSTS = {
|
|
65
|
+
production: "https://services.babelforce.com"
|
|
66
|
+
};
|
|
67
|
+
function resolveBaseUrl(environment) {
|
|
68
|
+
const host = HOSTS[environment];
|
|
69
|
+
if (!host) throw new Error(`unknown environment: ${String(environment)}`);
|
|
70
|
+
return host;
|
|
71
|
+
}
|
|
72
|
+
var client = createClient(createConfig({
|
|
73
|
+
baseUrl: "https://services.babelforce.com"
|
|
74
|
+
}));
|
|
75
|
+
|
|
76
|
+
// src/gen/manager/sdk.gen.ts
|
|
77
|
+
var listUsers = (options) => {
|
|
78
|
+
return (options?.client ?? client).get({
|
|
79
|
+
security: [
|
|
80
|
+
{
|
|
81
|
+
scheme: "bearer",
|
|
82
|
+
type: "http"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
name: "X-Auth-Access-Id",
|
|
86
|
+
type: "apiKey"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: "X-Auth-Access-Token",
|
|
90
|
+
type: "apiKey"
|
|
91
|
+
}
|
|
92
|
+
],
|
|
93
|
+
url: "/api/v2/users",
|
|
94
|
+
...options
|
|
95
|
+
});
|
|
96
|
+
};
|
|
97
|
+
var createUser = (options) => {
|
|
98
|
+
return (options?.client ?? client).post({
|
|
99
|
+
security: [
|
|
100
|
+
{
|
|
101
|
+
scheme: "bearer",
|
|
102
|
+
type: "http"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
name: "X-Auth-Access-Id",
|
|
106
|
+
type: "apiKey"
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: "X-Auth-Access-Token",
|
|
110
|
+
type: "apiKey"
|
|
111
|
+
}
|
|
112
|
+
],
|
|
113
|
+
url: "/api/v2/users",
|
|
114
|
+
...options,
|
|
115
|
+
headers: {
|
|
116
|
+
"Content-Type": "application/json",
|
|
117
|
+
...options?.headers
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
};
|
|
121
|
+
var deleteUsers = (options) => {
|
|
122
|
+
return (options?.client ?? client).post({
|
|
123
|
+
security: [
|
|
124
|
+
{
|
|
125
|
+
scheme: "bearer",
|
|
126
|
+
type: "http"
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
name: "X-Auth-Access-Id",
|
|
130
|
+
type: "apiKey"
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
name: "X-Auth-Access-Token",
|
|
134
|
+
type: "apiKey"
|
|
135
|
+
}
|
|
136
|
+
],
|
|
137
|
+
url: "/api/v2/users/delete",
|
|
138
|
+
...options,
|
|
139
|
+
headers: {
|
|
140
|
+
"Content-Type": "application/json",
|
|
141
|
+
...options?.headers
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
};
|
|
145
|
+
var disableUsers = (options) => {
|
|
146
|
+
return (options?.client ?? client).post({
|
|
147
|
+
security: [
|
|
148
|
+
{
|
|
149
|
+
scheme: "bearer",
|
|
150
|
+
type: "http"
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
name: "X-Auth-Access-Id",
|
|
154
|
+
type: "apiKey"
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
name: "X-Auth-Access-Token",
|
|
158
|
+
type: "apiKey"
|
|
159
|
+
}
|
|
160
|
+
],
|
|
161
|
+
url: "/api/v2/users/disable",
|
|
162
|
+
...options,
|
|
163
|
+
headers: {
|
|
164
|
+
"Content-Type": "application/json",
|
|
165
|
+
...options?.headers
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
};
|
|
169
|
+
var enableUsers = (options) => {
|
|
170
|
+
return (options?.client ?? client).post({
|
|
171
|
+
security: [
|
|
172
|
+
{
|
|
173
|
+
scheme: "bearer",
|
|
174
|
+
type: "http"
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
name: "X-Auth-Access-Id",
|
|
178
|
+
type: "apiKey"
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
name: "X-Auth-Access-Token",
|
|
182
|
+
type: "apiKey"
|
|
183
|
+
}
|
|
184
|
+
],
|
|
185
|
+
url: "/api/v2/users/enable",
|
|
186
|
+
...options,
|
|
187
|
+
headers: {
|
|
188
|
+
"Content-Type": "application/json",
|
|
189
|
+
...options?.headers
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
// src/errors.ts
|
|
195
|
+
var ManagerApiError = class _ManagerApiError extends Error {
|
|
196
|
+
/** HTTP status code. */
|
|
197
|
+
status;
|
|
198
|
+
/** API error code, when the response body carries one. */
|
|
199
|
+
code;
|
|
200
|
+
/** The parsed response body (object, string, or undefined). */
|
|
201
|
+
body;
|
|
202
|
+
constructor(status, message, body, code) {
|
|
203
|
+
super(message);
|
|
204
|
+
this.name = "ManagerApiError";
|
|
205
|
+
this.status = status;
|
|
206
|
+
this.body = body;
|
|
207
|
+
this.code = code;
|
|
208
|
+
}
|
|
209
|
+
/** Build a {@link ManagerApiError} from a fetch Response and its (already-parsed) body. */
|
|
210
|
+
static from(response, body) {
|
|
211
|
+
let code;
|
|
212
|
+
let message = `${response.status} ${response.statusText}`.trim();
|
|
213
|
+
if (body && typeof body === "object") {
|
|
214
|
+
const b = body;
|
|
215
|
+
if (typeof b.code === "string") code = b.code;
|
|
216
|
+
const detail = b.message ?? b.error ?? b.detail;
|
|
217
|
+
if (typeof detail === "string" && detail.length > 0) message = detail;
|
|
218
|
+
} else if (typeof body === "string" && body.length > 0) {
|
|
219
|
+
message = body;
|
|
220
|
+
}
|
|
221
|
+
return new _ManagerApiError(response.status, message, body, code);
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
// src/http.ts
|
|
226
|
+
async function unwrap(result) {
|
|
227
|
+
const { data, error, response } = await result;
|
|
228
|
+
if (!response.ok) throw ManagerApiError.from(response, error ?? data);
|
|
229
|
+
return data;
|
|
230
|
+
}
|
|
231
|
+
async function* paginate(fetchPage) {
|
|
232
|
+
let page = 1;
|
|
233
|
+
for (; ; ) {
|
|
234
|
+
const { items, pagination } = await fetchPage(page);
|
|
235
|
+
for (const item of items) yield item;
|
|
236
|
+
if (!pagination || items.length === 0 || pagination.current >= pagination.pages) return;
|
|
237
|
+
page = pagination.current + 1;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// src/resources/users.ts
|
|
242
|
+
var UsersResource = class {
|
|
243
|
+
constructor(client4) {
|
|
244
|
+
this.client = client4;
|
|
245
|
+
}
|
|
246
|
+
client;
|
|
247
|
+
/**
|
|
248
|
+
* List users, auto-paginating across pages.
|
|
249
|
+
*
|
|
250
|
+
* ```ts
|
|
251
|
+
* for await (const user of mgr.users.list()) console.log(user.email);
|
|
252
|
+
* ```
|
|
253
|
+
*/
|
|
254
|
+
list(query = {}) {
|
|
255
|
+
const client4 = this.client;
|
|
256
|
+
return paginate(async () => {
|
|
257
|
+
const page = await unwrap(listUsers({ client: client4, query }));
|
|
258
|
+
return { items: page.items, pagination: page.pagination };
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
/** Collect every user into an array (convenience over {@link list}). */
|
|
262
|
+
async listAll(query = {}) {
|
|
263
|
+
const users = [];
|
|
264
|
+
for await (const user of this.list(query)) users.push(user);
|
|
265
|
+
return users;
|
|
266
|
+
}
|
|
267
|
+
/** Create a user. */
|
|
268
|
+
async create(user) {
|
|
269
|
+
return unwrap(createUser({ client: this.client, body: user }));
|
|
270
|
+
}
|
|
271
|
+
/** Enable the given users (by email). */
|
|
272
|
+
async enable(emails) {
|
|
273
|
+
await unwrap(enableUsers({ client: this.client, body: emailList(emails) }));
|
|
274
|
+
}
|
|
275
|
+
/** Disable the given users (by email). */
|
|
276
|
+
async disable(emails) {
|
|
277
|
+
await unwrap(disableUsers({ client: this.client, body: emailList(emails) }));
|
|
278
|
+
}
|
|
279
|
+
/** Delete the given users (by email). */
|
|
280
|
+
async delete(emails) {
|
|
281
|
+
await unwrap(deleteUsers({ client: this.client, body: emailList(emails) }));
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
function emailList(emails) {
|
|
285
|
+
return { emails };
|
|
286
|
+
}
|
|
287
|
+
var client2 = createClient(createConfig({
|
|
288
|
+
baseUrl: "https://services.babelforce.com"
|
|
289
|
+
}));
|
|
290
|
+
|
|
291
|
+
// src/gen/task-automation/sdk.gen.ts
|
|
292
|
+
var managerInterruptOnTask = (options) => {
|
|
293
|
+
return (options.client ?? client2).post({
|
|
294
|
+
security: [
|
|
295
|
+
{
|
|
296
|
+
scheme: "bearer",
|
|
297
|
+
type: "http"
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
scheme: "bearer",
|
|
301
|
+
type: "http"
|
|
302
|
+
}
|
|
303
|
+
],
|
|
304
|
+
url: "/api/v3/tasks/{taskId}/interrupt/{interruptTo}",
|
|
305
|
+
...options,
|
|
306
|
+
headers: {
|
|
307
|
+
"Content-Type": "application/json",
|
|
308
|
+
...options?.headers
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
};
|
|
312
|
+
var submitTaskTemplate = (options) => {
|
|
313
|
+
return (options.client ?? client2).post({
|
|
314
|
+
security: [
|
|
315
|
+
{
|
|
316
|
+
scheme: "bearer",
|
|
317
|
+
type: "http"
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
scheme: "bearer",
|
|
321
|
+
type: "http"
|
|
322
|
+
}
|
|
323
|
+
],
|
|
324
|
+
url: "/api/v3/tasks/template/{template}",
|
|
325
|
+
...options,
|
|
326
|
+
headers: {
|
|
327
|
+
"Content-Type": "application/json",
|
|
328
|
+
...options?.headers
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
};
|
|
332
|
+
var tasks = (options) => {
|
|
333
|
+
return (options?.client ?? client2).get({
|
|
334
|
+
security: [
|
|
335
|
+
{
|
|
336
|
+
scheme: "bearer",
|
|
337
|
+
type: "http"
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
scheme: "bearer",
|
|
341
|
+
type: "http"
|
|
342
|
+
}
|
|
343
|
+
],
|
|
344
|
+
url: "/api/v3/tasks",
|
|
345
|
+
...options
|
|
346
|
+
});
|
|
347
|
+
};
|
|
348
|
+
var submitTask = (options) => {
|
|
349
|
+
return (options.client ?? client2).post({
|
|
350
|
+
security: [
|
|
351
|
+
{
|
|
352
|
+
scheme: "bearer",
|
|
353
|
+
type: "http"
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
scheme: "bearer",
|
|
357
|
+
type: "http"
|
|
358
|
+
}
|
|
359
|
+
],
|
|
360
|
+
url: "/api/v3/tasks",
|
|
361
|
+
...options,
|
|
362
|
+
headers: {
|
|
363
|
+
"Content-Type": "application/json",
|
|
364
|
+
...options?.headers
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
};
|
|
368
|
+
var task = (options) => {
|
|
369
|
+
return (options.client ?? client2).get({
|
|
370
|
+
security: [
|
|
371
|
+
{
|
|
372
|
+
scheme: "bearer",
|
|
373
|
+
type: "http"
|
|
374
|
+
},
|
|
375
|
+
{
|
|
376
|
+
scheme: "bearer",
|
|
377
|
+
type: "http"
|
|
378
|
+
}
|
|
379
|
+
],
|
|
380
|
+
url: "/api/v3/tasks/{taskId}",
|
|
381
|
+
...options
|
|
382
|
+
});
|
|
383
|
+
};
|
|
384
|
+
var updateTask = (options) => {
|
|
385
|
+
return (options.client ?? client2).put({
|
|
386
|
+
security: [
|
|
387
|
+
{
|
|
388
|
+
scheme: "bearer",
|
|
389
|
+
type: "http"
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
scheme: "bearer",
|
|
393
|
+
type: "http"
|
|
394
|
+
}
|
|
395
|
+
],
|
|
396
|
+
url: "/api/v3/tasks/{taskId}",
|
|
397
|
+
...options,
|
|
398
|
+
headers: {
|
|
399
|
+
"Content-Type": "application/json",
|
|
400
|
+
...options?.headers
|
|
401
|
+
}
|
|
402
|
+
});
|
|
403
|
+
};
|
|
404
|
+
var client3 = createClient(createConfig({
|
|
405
|
+
baseUrl: "https://services.babelforce.com"
|
|
406
|
+
}));
|
|
407
|
+
|
|
408
|
+
// src/gen/task-schedule/sdk.gen.ts
|
|
409
|
+
var getTaskSchedules = (options) => {
|
|
410
|
+
return (options?.client ?? client3).get({
|
|
411
|
+
security: [
|
|
412
|
+
{
|
|
413
|
+
scheme: "bearer",
|
|
414
|
+
type: "http"
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
scheme: "bearer",
|
|
418
|
+
type: "http"
|
|
419
|
+
}
|
|
420
|
+
],
|
|
421
|
+
url: "/api/v3/tasks/schedules",
|
|
422
|
+
...options
|
|
423
|
+
});
|
|
424
|
+
};
|
|
425
|
+
var submitTaskSchedule = (options) => {
|
|
426
|
+
return (options.client ?? client3).post({
|
|
427
|
+
security: [
|
|
428
|
+
{
|
|
429
|
+
scheme: "bearer",
|
|
430
|
+
type: "http"
|
|
431
|
+
},
|
|
432
|
+
{
|
|
433
|
+
scheme: "bearer",
|
|
434
|
+
type: "http"
|
|
435
|
+
}
|
|
436
|
+
],
|
|
437
|
+
url: "/api/v3/tasks/schedules",
|
|
438
|
+
...options,
|
|
439
|
+
headers: {
|
|
440
|
+
"Content-Type": "application/json",
|
|
441
|
+
...options?.headers
|
|
442
|
+
}
|
|
443
|
+
});
|
|
444
|
+
};
|
|
445
|
+
var deleteScheduleTask = (options) => {
|
|
446
|
+
return (options.client ?? client3).delete({
|
|
447
|
+
security: [
|
|
448
|
+
{
|
|
449
|
+
scheme: "bearer",
|
|
450
|
+
type: "http"
|
|
451
|
+
},
|
|
452
|
+
{
|
|
453
|
+
scheme: "bearer",
|
|
454
|
+
type: "http"
|
|
455
|
+
}
|
|
456
|
+
],
|
|
457
|
+
url: "/api/v3/tasks/schedules/{taskScheduleName}",
|
|
458
|
+
...options
|
|
459
|
+
});
|
|
460
|
+
};
|
|
461
|
+
var getTaskSchedule = (options) => {
|
|
462
|
+
return (options.client ?? client3).get({
|
|
463
|
+
security: [
|
|
464
|
+
{
|
|
465
|
+
scheme: "bearer",
|
|
466
|
+
type: "http"
|
|
467
|
+
},
|
|
468
|
+
{
|
|
469
|
+
scheme: "bearer",
|
|
470
|
+
type: "http"
|
|
471
|
+
}
|
|
472
|
+
],
|
|
473
|
+
url: "/api/v3/tasks/schedules/{taskScheduleName}",
|
|
474
|
+
...options
|
|
475
|
+
});
|
|
476
|
+
};
|
|
477
|
+
|
|
478
|
+
// src/resources/tasks.ts
|
|
479
|
+
var TasksResource = class {
|
|
480
|
+
constructor(client4) {
|
|
481
|
+
this.client = client4;
|
|
482
|
+
this.schedules = new TaskSchedulesResource(client4);
|
|
483
|
+
}
|
|
484
|
+
client;
|
|
485
|
+
/** Recurring task schedules — `/api/v3/tasks/schedules`. */
|
|
486
|
+
schedules;
|
|
487
|
+
/**
|
|
488
|
+
* List tasks, auto-paginating across pages.
|
|
489
|
+
*
|
|
490
|
+
* ```ts
|
|
491
|
+
* for await (const task of mgr.tasks.list({ filter: "state==active" })) { … }
|
|
492
|
+
* ```
|
|
493
|
+
*/
|
|
494
|
+
async *list(query = {}) {
|
|
495
|
+
const pageSize = query.pageSize ?? 100;
|
|
496
|
+
for (let page = 1; ; page++) {
|
|
497
|
+
const data = await unwrap(
|
|
498
|
+
tasks({ client: this.client, query: { filter: query.filter, page, page_size: pageSize } })
|
|
499
|
+
);
|
|
500
|
+
const records = data.records ?? [];
|
|
501
|
+
for (const task2 of records) yield task2;
|
|
502
|
+
const pages = data._metadata?.page_count;
|
|
503
|
+
if (records.length === 0) return;
|
|
504
|
+
if (pages != null) {
|
|
505
|
+
if (page >= pages) return;
|
|
506
|
+
} else if (records.length < pageSize) {
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
/** Collect every task into an array. */
|
|
512
|
+
async listAll(query = {}) {
|
|
513
|
+
const out = [];
|
|
514
|
+
for await (const task2 of this.list(query)) out.push(task2);
|
|
515
|
+
return out;
|
|
516
|
+
}
|
|
517
|
+
/** Create a task. */
|
|
518
|
+
async create(body) {
|
|
519
|
+
return unwrap(submitTask({ client: this.client, body }));
|
|
520
|
+
}
|
|
521
|
+
/** Create a task from a template, with overrides. */
|
|
522
|
+
async createFromTemplate(template, overrides) {
|
|
523
|
+
return unwrap(submitTaskTemplate({ client: this.client, path: { template }, body: overrides }));
|
|
524
|
+
}
|
|
525
|
+
/** Get a task by id. */
|
|
526
|
+
async get(taskId) {
|
|
527
|
+
return unwrap(task({ client: this.client, path: { taskId } }));
|
|
528
|
+
}
|
|
529
|
+
/** Update a task. */
|
|
530
|
+
async update(taskId, body) {
|
|
531
|
+
return unwrap(updateTask({ client: this.client, path: { taskId }, body }));
|
|
532
|
+
}
|
|
533
|
+
/** Manager-interrupt a task, transitioning it to the given target state. */
|
|
534
|
+
async interrupt(taskId, interruptTo, action) {
|
|
535
|
+
await unwrap(
|
|
536
|
+
managerInterruptOnTask({ client: this.client, path: { taskId, interruptTo }, body: action })
|
|
537
|
+
);
|
|
538
|
+
}
|
|
539
|
+
};
|
|
540
|
+
var TaskSchedulesResource = class {
|
|
541
|
+
constructor(client4) {
|
|
542
|
+
this.client = client4;
|
|
543
|
+
}
|
|
544
|
+
client;
|
|
545
|
+
/** List task schedules. */
|
|
546
|
+
async list() {
|
|
547
|
+
return unwrap(getTaskSchedules({ client: this.client }));
|
|
548
|
+
}
|
|
549
|
+
/** Create a task schedule. */
|
|
550
|
+
async create(schedule) {
|
|
551
|
+
await unwrap(submitTaskSchedule({ client: this.client, body: schedule }));
|
|
552
|
+
}
|
|
553
|
+
/** Get a task schedule by name. */
|
|
554
|
+
async get(taskScheduleName) {
|
|
555
|
+
return unwrap(getTaskSchedule({ client: this.client, path: { taskScheduleName } }));
|
|
556
|
+
}
|
|
557
|
+
/** Delete a task schedule by name. */
|
|
558
|
+
async delete(taskScheduleName) {
|
|
559
|
+
await unwrap(deleteScheduleTask({ client: this.client, path: { taskScheduleName } }));
|
|
560
|
+
}
|
|
561
|
+
};
|
|
562
|
+
|
|
563
|
+
// src/client.ts
|
|
564
|
+
var ManagerClient = class _ManagerClient {
|
|
565
|
+
/** The underlying fetch client (escape hatch for advanced use). */
|
|
566
|
+
client;
|
|
567
|
+
/** User management — `/api/v2/users`. */
|
|
568
|
+
users;
|
|
569
|
+
/** Task automations — `/api/v3/tasks`. */
|
|
570
|
+
tasks;
|
|
571
|
+
constructor(client4) {
|
|
572
|
+
this.client = client4;
|
|
573
|
+
this.users = new UsersResource(client4);
|
|
574
|
+
this.tasks = new TasksResource(client4);
|
|
575
|
+
}
|
|
576
|
+
/** Create and configure a client. */
|
|
577
|
+
static async connect(options) {
|
|
578
|
+
const baseUrl = options.baseUrl ?? resolveBaseUrl(options.environment ?? "production");
|
|
579
|
+
const authConfig = buildAuthConfig(options.auth, baseUrl, options.fetch);
|
|
580
|
+
const client4 = createClient(
|
|
581
|
+
createConfig({
|
|
582
|
+
baseUrl,
|
|
583
|
+
headers: { ...authConfig.headers, ...options.headers },
|
|
584
|
+
...authConfig.auth ? { auth: authConfig.auth } : {},
|
|
585
|
+
...options.fetch ? { fetch: options.fetch } : {}
|
|
586
|
+
})
|
|
587
|
+
);
|
|
588
|
+
return new _ManagerClient(client4);
|
|
589
|
+
}
|
|
590
|
+
};
|
|
591
|
+
|
|
592
|
+
export { ManagerApiError, ManagerClient, TaskSchedulesResource, TasksResource, UsersResource, passwordGrant };
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@babelforce/manager-sdk",
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "TypeScript SDK for the babelforce manager APIs — auth, user & agent management, call reporting, metrics, and task automations.",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"README.md",
|
|
11
|
+
"CHANGELOG.md",
|
|
12
|
+
"LICENSE",
|
|
13
|
+
"NOTICE"
|
|
14
|
+
],
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"import": "./dist/index.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"scripts": {
|
|
22
|
+
"generate": "node scripts/generate.mjs",
|
|
23
|
+
"typecheck": "tsc --noEmit",
|
|
24
|
+
"build": "tsup",
|
|
25
|
+
"test": "npm run build && node --test test/*.test.mjs",
|
|
26
|
+
"prepublishOnly": "npm run typecheck && npm run build && npm test"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@hey-api/client-fetch": "^0.13.1"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@hey-api/openapi-ts": "^0.64.0",
|
|
33
|
+
"tsup": "^8.3.0",
|
|
34
|
+
"typescript": "^5.7.0"
|
|
35
|
+
},
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public",
|
|
38
|
+
"registry": "https://registry.npmjs.org/"
|
|
39
|
+
}
|
|
40
|
+
}
|