@typeb-digital/nucleus-sdk 0.0.1 → 0.0.3
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 +236 -0
- package/dist/cjs/index.cjs +683 -0
- package/dist/cjs/index.d.cts +567 -0
- package/dist/cjs/index.d.cts.map +1 -0
- package/dist/es/index.d.ts +567 -0
- package/dist/es/index.d.ts.map +1 -0
- package/dist/es/index.js +683 -0
- package/package.json +5 -1
- package/src/apps.ts +0 -19
- package/src/client.ts +0 -75
- package/src/index.ts +0 -82
- package/src/resources/clients.ts +0 -65
- package/src/resources/currencies.ts +0 -41
- package/src/resources/departments.ts +0 -43
- package/src/resources/employees.ts +0 -65
- package/src/resources/files.ts +0 -105
- package/src/resources/generic-rates.ts +0 -43
- package/src/resources/partners.ts +0 -61
- package/src/resources/project-types.ts +0 -41
- package/src/resources/projects.ts +0 -65
- package/src/transform.ts +0 -266
- package/src/transport.ts +0 -145
- package/src/types.ts +0 -447
- package/tsconfig.json +0 -12
- package/tsconfig.verify.json +0 -11
- package/typeb-digital-nucleus-sdk-0.0.1.tgz +0 -0
- package/verify.ts +0 -182
package/README.md
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
# @typeb-digital/nucleus-sdk
|
|
2
|
+
|
|
3
|
+
Server-side TypeScript SDK for the **Nucleus data platform** — the company source of truth for people, projects, and clients.
|
|
4
|
+
|
|
5
|
+
Install this in your **app backend** (Node.js). It holds the app token and handles all data access. Never import it in browser code.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @typeb-digital/nucleus-sdk
|
|
13
|
+
# or
|
|
14
|
+
yarn add @typeb-digital/nucleus-sdk
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Requires Node.js ≥ 18.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Quick start
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
import { NucleusClient } from '@typeb-digital/nucleus-sdk';
|
|
25
|
+
|
|
26
|
+
export const nucleus = new NucleusClient({
|
|
27
|
+
token: process.env.NUCLEUS_TOKEN!,
|
|
28
|
+
scopes: {
|
|
29
|
+
employees: ['identity', 'employment'],
|
|
30
|
+
projects: ['core'],
|
|
31
|
+
clients: ['identity'],
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The `scopes` object is the heart of the type system. Declare it once; every method on the client returns types that reflect exactly those buckets — nothing more, nothing less. TypeScript infers the types automatically; no explicit type parameters needed.
|
|
37
|
+
|
|
38
|
+
> **Get your token and init script** from the Nucleus dashboard → Apps → your app → Init Script.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Scopes & buckets
|
|
43
|
+
|
|
44
|
+
Nucleus groups fields into **buckets** per resource. Your app only receives fields for the buckets you've been approved for.
|
|
45
|
+
|
|
46
|
+
| Resource | Available buckets |
|
|
47
|
+
| -------------- | ------------------------------------------------------------------------------------------------ |
|
|
48
|
+
| `employees` | `identity` · `contact` · `employment` · `sensitive`¹ · `compensation`¹ · `compensation_history`¹ |
|
|
49
|
+
| `projects` | `core` · `team` · `financials` · `integrations` |
|
|
50
|
+
| `clients` | `identity` · `contact` · `financials` · `notes` |
|
|
51
|
+
| `partners` | `identity` · `contact` · `notes` |
|
|
52
|
+
| `departments` | `core` |
|
|
53
|
+
| `projectTypes` | `core` |
|
|
54
|
+
| `currencies` | `core` |
|
|
55
|
+
| `genericRates` | `core` · `financials`¹ |
|
|
56
|
+
|
|
57
|
+
¹ Requires platform-team approval.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Data access
|
|
62
|
+
|
|
63
|
+
### Employees
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
// List — type reflects declared buckets
|
|
67
|
+
const result = await nucleus.employees.list({
|
|
68
|
+
department: 'Engineering',
|
|
69
|
+
page: 1,
|
|
70
|
+
pageSize: 50,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
if (!isError(result)) {
|
|
74
|
+
result.data; // Employee[] typed to your scopes
|
|
75
|
+
result.meta.total; // number
|
|
76
|
+
result.meta.hasMore; // boolean
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Single record
|
|
80
|
+
const { data: emp } = await nucleus.employees.getById('emp_123');
|
|
81
|
+
|
|
82
|
+
// With expansion — manager is typed as an Employee object, not just a string ID
|
|
83
|
+
const { data: emp } = await nucleus.employees.getById('emp_123', {
|
|
84
|
+
expand: ['manager'],
|
|
85
|
+
});
|
|
86
|
+
if (emp.manager) {
|
|
87
|
+
emp.manager.email; // ✓ typed
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Projects
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
const result = await nucleus.projects.list({ status: 'active' });
|
|
95
|
+
|
|
96
|
+
// Expand client and team members in one call
|
|
97
|
+
const { data: project } = await nucleus.projects.getById('proj_123', {
|
|
98
|
+
expand: ['client', 'projectManager', 'memberships.employee'],
|
|
99
|
+
});
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Clients, Partners, Departments, Currencies, Generic Rates
|
|
103
|
+
|
|
104
|
+
Same pattern — `list(params?)` and `getById(id, options?)` on every resource accessor.
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Result type
|
|
109
|
+
|
|
110
|
+
Every method returns a result object — **never throws** by default:
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
import { NucleusClient, isError } from '@typeb-digital/nucleus-sdk';
|
|
114
|
+
|
|
115
|
+
const result = await nucleus.employees.getById('emp_123');
|
|
116
|
+
|
|
117
|
+
if (isError(result)) {
|
|
118
|
+
// result.error.code: 'FORBIDDEN' | 'NOT_FOUND' | 'INVALID_SCOPE' | 'RATE_LIMITED' | 'NETWORK_ERROR'
|
|
119
|
+
console.error(result.error.message);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// result.data is fully typed here
|
|
124
|
+
console.log(result.data.email);
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## File storage
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
// Upload — app provides a path-style key; upsert semantics
|
|
133
|
+
const { data: file } = await nucleus.files.upload({
|
|
134
|
+
key: 'users/123/avatar',
|
|
135
|
+
file: buffer, // Buffer
|
|
136
|
+
mimeType: 'image/png',
|
|
137
|
+
visibility: 'private',
|
|
138
|
+
allowedUsers: ['emp_123'], // optional — omit for app-wide access
|
|
139
|
+
metadata: { type: 'avatar' },
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
// Resolve a URL to pass to your frontend
|
|
143
|
+
// Public → CDN URL (instant, no signing)
|
|
144
|
+
// Private → fresh short-lived pre-signed URL
|
|
145
|
+
const { data } = await nucleus.files.getUrl('users/123/avatar');
|
|
146
|
+
// data.url — hand this to the browser
|
|
147
|
+
|
|
148
|
+
// Private file scoped to a specific user
|
|
149
|
+
const { data } = await nucleus.files.getUrl('users/123/avatar', {
|
|
150
|
+
asUser: userAccessToken, // from the client SDK's getSession().accessToken
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
// List files
|
|
154
|
+
const result = await nucleus.files.list({ prefix: 'users/123/' });
|
|
155
|
+
|
|
156
|
+
// Soft delete
|
|
157
|
+
await nucleus.files.delete('users/123/avatar');
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Self-service app info
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
const { data: app } = await nucleus.apps.me();
|
|
166
|
+
// app.name, app.scopes (declared), app.status per-bucket
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Pagination
|
|
172
|
+
|
|
173
|
+
All `list()` methods return explicit pagination metadata:
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
const result = await nucleus.employees.list({ page: 2, pageSize: 25 });
|
|
177
|
+
|
|
178
|
+
if (!isError(result)) {
|
|
179
|
+
result.meta.total; // total records
|
|
180
|
+
result.meta.page; // current page
|
|
181
|
+
result.meta.pageSize; // records per page
|
|
182
|
+
result.meta.hasMore; // boolean shortcut
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Expansion
|
|
189
|
+
|
|
190
|
+
Related records are not included by default. Request them explicitly:
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
// Depth 1
|
|
194
|
+
const { data } = await nucleus.projects.getById('proj_123', {
|
|
195
|
+
expand: ['client', 'projectManager'],
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
// Depth 2 (max)
|
|
199
|
+
const { data } = await nucleus.projects.getById('proj_123', {
|
|
200
|
+
expand: ['projectManager.manager'],
|
|
201
|
+
});
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Valid expand paths per resource are typed — invalid paths or three-segment paths are compile errors.
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## TypeScript
|
|
209
|
+
|
|
210
|
+
The SDK is fully typed with no `any`. Bucket scopes drive the return types at compile time:
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
// scopes.employees = ['identity'] only
|
|
214
|
+
const { data: emp } = await nucleus.employees.getById('emp_123');
|
|
215
|
+
emp.email; // ✓ string
|
|
216
|
+
emp.phone; // ✗ compile error — contact bucket not declared
|
|
217
|
+
emp.managerId; // ✗ compile error — employment bucket not declared
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Configuration
|
|
223
|
+
|
|
224
|
+
```typescript
|
|
225
|
+
new NucleusClient({
|
|
226
|
+
token: process.env.NUCLEUS_TOKEN!, // required
|
|
227
|
+
baseUrl: 'https://nucleus.example.com', // optional, defaults to platform URL
|
|
228
|
+
scopes: { ... }, // required
|
|
229
|
+
})
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## License
|
|
235
|
+
|
|
236
|
+
MIT — Type B Digital
|