@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/src/types.ts
DELETED
|
@@ -1,447 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Nucleus SDK — Type System
|
|
3
|
-
*
|
|
4
|
-
* Bucket types are transcribed from docs/NUCLEUS_PIVOT.md §7 (Bucket Definitions).
|
|
5
|
-
* Each bucket type contains only that bucket's fields.
|
|
6
|
-
* The scope-to-type inference intersects selected bucket types at compile time.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
// ─── Utility types ────────────────────────────────────────────────────────────
|
|
10
|
-
|
|
11
|
-
// Converts a union to an intersection: A | B → A & B
|
|
12
|
-
export type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends (
|
|
13
|
-
k: infer I,
|
|
14
|
-
) => void
|
|
15
|
-
? I
|
|
16
|
-
: never;
|
|
17
|
-
|
|
18
|
-
// Returned when a resource has no declared scopes — accessing any field is a compile error
|
|
19
|
-
export type NoScope = Record<never, never>;
|
|
20
|
-
|
|
21
|
-
// ─── Result types (§3.5) ─────────────────────────────────────────────────────
|
|
22
|
-
|
|
23
|
-
export type ErrorCode =
|
|
24
|
-
| 'FORBIDDEN'
|
|
25
|
-
| 'NOT_FOUND'
|
|
26
|
-
| 'INVALID_SCOPE'
|
|
27
|
-
| 'RATE_LIMITED'
|
|
28
|
-
| 'NETWORK_ERROR';
|
|
29
|
-
|
|
30
|
-
export type ErrorResult = {
|
|
31
|
-
error: { code: ErrorCode; message: string };
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
export type SuccessResult<T> = { data: T };
|
|
35
|
-
|
|
36
|
-
export type ListMeta = {
|
|
37
|
-
total: number;
|
|
38
|
-
page: number;
|
|
39
|
-
pageSize: number;
|
|
40
|
-
hasMore: boolean;
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
export type ListResult<T> = { data: T[]; meta: ListMeta };
|
|
44
|
-
|
|
45
|
-
export type SingleResult<T> = SuccessResult<T> | ErrorResult;
|
|
46
|
-
export type PaginatedResult<T> = ListResult<T> | ErrorResult;
|
|
47
|
-
|
|
48
|
-
export function isError<T>(
|
|
49
|
-
result: SuccessResult<T> | ListResult<T> | ErrorResult,
|
|
50
|
-
): result is ErrorResult {
|
|
51
|
-
return 'error' in result;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// ─── §7.1 Employees — bucket types ──────────────────────────────────────────
|
|
55
|
-
|
|
56
|
-
export type EmployeeIdentity = {
|
|
57
|
-
id: string;
|
|
58
|
-
displayName: string;
|
|
59
|
-
firstName: string;
|
|
60
|
-
lastName: string;
|
|
61
|
-
email: string;
|
|
62
|
-
pictureUrl: string | null;
|
|
63
|
-
jobTitle: string | null;
|
|
64
|
-
department: string | null;
|
|
65
|
-
employmentStatus: string;
|
|
66
|
-
isExternal: boolean;
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
export type EmployeeContact = {
|
|
70
|
-
profile: {
|
|
71
|
-
phone?: string | null;
|
|
72
|
-
city?: string | null;
|
|
73
|
-
country?: string | null;
|
|
74
|
-
};
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
export type EmployeeEmployment = {
|
|
78
|
-
startDate: string | null;
|
|
79
|
-
weeklyCapacity: number | null;
|
|
80
|
-
managerId: string | null;
|
|
81
|
-
partnerId: string | null;
|
|
82
|
-
/** IANA timezone string, e.g. "Asia/Colombo". Null when not yet set. */
|
|
83
|
-
timezone: string | null;
|
|
84
|
-
profile: {
|
|
85
|
-
biography?: string | null;
|
|
86
|
-
};
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
export type EmployeeSensitive = {
|
|
90
|
-
birthday: string | null;
|
|
91
|
-
profile: {
|
|
92
|
-
emergencyContact?: {
|
|
93
|
-
name: string | null;
|
|
94
|
-
phone: string | null;
|
|
95
|
-
} | null;
|
|
96
|
-
};
|
|
97
|
-
customFields: Record<string, unknown> | null;
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
export type EmployeeCompensation = {
|
|
101
|
-
currentCompensation: {
|
|
102
|
-
hourlyCostRate: number | null;
|
|
103
|
-
hourlyBillableRate: number | null;
|
|
104
|
-
monthlyCostRate: number | null;
|
|
105
|
-
monthlyBillableRate: number | null;
|
|
106
|
-
currencyCode: string;
|
|
107
|
-
effectiveFrom: string;
|
|
108
|
-
} | null;
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
export type EmployeeCompensationHistory = {
|
|
112
|
-
compensationHistory: Array<{
|
|
113
|
-
hourlyCostRate: number | null;
|
|
114
|
-
hourlyBillableRate: number | null;
|
|
115
|
-
monthlyCostRate: number | null;
|
|
116
|
-
monthlyBillableRate: number | null;
|
|
117
|
-
currencyCode: string;
|
|
118
|
-
effectiveFrom: string;
|
|
119
|
-
effectiveTo: string | null;
|
|
120
|
-
}>;
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
export type EmployeeBucketMap = {
|
|
124
|
-
identity: EmployeeIdentity;
|
|
125
|
-
contact: EmployeeContact;
|
|
126
|
-
employment: EmployeeEmployment;
|
|
127
|
-
sensitive: EmployeeSensitive;
|
|
128
|
-
compensation: EmployeeCompensation;
|
|
129
|
-
compensation_history: EmployeeCompensationHistory;
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
// ─── §7.2 Projects — bucket types ───────────────────────────────────────────
|
|
133
|
-
|
|
134
|
-
export type ProjectMembership = {
|
|
135
|
-
employeeId: string;
|
|
136
|
-
role: string | null;
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
export type ProjectCore = {
|
|
140
|
-
id: string;
|
|
141
|
-
name: string;
|
|
142
|
-
status: string;
|
|
143
|
-
colorTag: string | null;
|
|
144
|
-
iconName: string | null;
|
|
145
|
-
startDate: string | null;
|
|
146
|
-
endDate: string | null;
|
|
147
|
-
projectTypeId: string | null;
|
|
148
|
-
clientId: string | null;
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
export type ProjectTeam = {
|
|
152
|
-
projectManagerId: string | null;
|
|
153
|
-
engagementLeadId: string | null;
|
|
154
|
-
memberships: ProjectMembership[];
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
export type ProjectFinancials = Record<never, never>; // reserved — no fields yet
|
|
158
|
-
|
|
159
|
-
export type ProjectIntegrations = {
|
|
160
|
-
source: string | null;
|
|
161
|
-
clockifyProjectId: string | null;
|
|
162
|
-
clockifyWorkspaceId: string | null;
|
|
163
|
-
apolloDealId: string | null;
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
export type ProjectBucketMap = {
|
|
167
|
-
core: ProjectCore;
|
|
168
|
-
team: ProjectTeam;
|
|
169
|
-
financials: ProjectFinancials;
|
|
170
|
-
integrations: ProjectIntegrations;
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
// ─── §7.3 Clients — bucket types ────────────────────────────────────────────
|
|
174
|
-
|
|
175
|
-
export type ClientIdentity = {
|
|
176
|
-
id: string;
|
|
177
|
-
name: string;
|
|
178
|
-
code: string | null;
|
|
179
|
-
industry: string | null;
|
|
180
|
-
website: string | null;
|
|
181
|
-
country: string | null;
|
|
182
|
-
};
|
|
183
|
-
|
|
184
|
-
export type ClientContact = {
|
|
185
|
-
primaryContactName: string | null;
|
|
186
|
-
primaryContactEmail: string | null;
|
|
187
|
-
contactPhone: string | null;
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
export type ClientFinancials = {
|
|
191
|
-
defaultCurrency: string | null;
|
|
192
|
-
};
|
|
193
|
-
|
|
194
|
-
export type ClientNotes = {
|
|
195
|
-
notes: string | null;
|
|
196
|
-
};
|
|
197
|
-
|
|
198
|
-
export type ClientBucketMap = {
|
|
199
|
-
identity: ClientIdentity;
|
|
200
|
-
contact: ClientContact;
|
|
201
|
-
financials: ClientFinancials;
|
|
202
|
-
notes: ClientNotes;
|
|
203
|
-
};
|
|
204
|
-
|
|
205
|
-
// ─── §7.4 Partners — bucket types ───────────────────────────────────────────
|
|
206
|
-
|
|
207
|
-
export type PartnerIdentity = {
|
|
208
|
-
id: string;
|
|
209
|
-
name: string;
|
|
210
|
-
};
|
|
211
|
-
|
|
212
|
-
export type PartnerContact = {
|
|
213
|
-
contactName: string | null;
|
|
214
|
-
contactEmail: string | null;
|
|
215
|
-
contactPhone: string | null;
|
|
216
|
-
};
|
|
217
|
-
|
|
218
|
-
export type PartnerNotes = {
|
|
219
|
-
notes: string | null;
|
|
220
|
-
};
|
|
221
|
-
|
|
222
|
-
export type PartnerBucketMap = {
|
|
223
|
-
identity: PartnerIdentity;
|
|
224
|
-
contact: PartnerContact;
|
|
225
|
-
notes: PartnerNotes;
|
|
226
|
-
};
|
|
227
|
-
|
|
228
|
-
// ─── §7.5 Departments ───────────────────────────────────────────────────────
|
|
229
|
-
|
|
230
|
-
export type DepartmentCore = {
|
|
231
|
-
id: string;
|
|
232
|
-
name: string;
|
|
233
|
-
titles: string[];
|
|
234
|
-
sortOrder: number;
|
|
235
|
-
};
|
|
236
|
-
|
|
237
|
-
export type DepartmentBucketMap = {
|
|
238
|
-
core: DepartmentCore;
|
|
239
|
-
};
|
|
240
|
-
|
|
241
|
-
// ─── §7.6 Project Types ─────────────────────────────────────────────────────
|
|
242
|
-
|
|
243
|
-
export type ProjectTypeCore = {
|
|
244
|
-
id: string;
|
|
245
|
-
name: string;
|
|
246
|
-
description: string | null;
|
|
247
|
-
sortOrder: number;
|
|
248
|
-
};
|
|
249
|
-
|
|
250
|
-
export type ProjectTypeBucketMap = {
|
|
251
|
-
core: ProjectTypeCore;
|
|
252
|
-
};
|
|
253
|
-
|
|
254
|
-
// ─── §7.7 Currencies ────────────────────────────────────────────────────────
|
|
255
|
-
|
|
256
|
-
export type CurrencyCore = {
|
|
257
|
-
code: string;
|
|
258
|
-
name: string;
|
|
259
|
-
symbol: string | null;
|
|
260
|
-
isDefault: boolean;
|
|
261
|
-
sortOrder: number;
|
|
262
|
-
};
|
|
263
|
-
|
|
264
|
-
export type CurrencyBucketMap = {
|
|
265
|
-
core: CurrencyCore;
|
|
266
|
-
};
|
|
267
|
-
|
|
268
|
-
// ─── §7.8 Generic Rates ─────────────────────────────────────────────────────
|
|
269
|
-
|
|
270
|
-
export type GenericRateCore = {
|
|
271
|
-
id: string;
|
|
272
|
-
title: string;
|
|
273
|
-
department: string;
|
|
274
|
-
currencyCode: string;
|
|
275
|
-
};
|
|
276
|
-
|
|
277
|
-
export type GenericRateFinancials = {
|
|
278
|
-
costRate: number;
|
|
279
|
-
billableRate: number;
|
|
280
|
-
};
|
|
281
|
-
|
|
282
|
-
export type GenericRateBucketMap = {
|
|
283
|
-
core: GenericRateCore;
|
|
284
|
-
financials: GenericRateFinancials;
|
|
285
|
-
};
|
|
286
|
-
|
|
287
|
-
// ─── Scope declaration ────────────────────────────────────────────────────────
|
|
288
|
-
|
|
289
|
-
export type ScopeDeclaration = {
|
|
290
|
-
employees?: readonly (keyof EmployeeBucketMap)[];
|
|
291
|
-
projects?: readonly (keyof ProjectBucketMap)[];
|
|
292
|
-
clients?: readonly (keyof ClientBucketMap)[];
|
|
293
|
-
partners?: readonly (keyof PartnerBucketMap)[];
|
|
294
|
-
departments?: readonly (keyof DepartmentBucketMap)[];
|
|
295
|
-
projectTypes?: readonly (keyof ProjectTypeBucketMap)[];
|
|
296
|
-
currencies?: readonly (keyof CurrencyBucketMap)[];
|
|
297
|
-
genericRates?: readonly (keyof GenericRateBucketMap)[];
|
|
298
|
-
};
|
|
299
|
-
|
|
300
|
-
// ─── Scope resolution ────────────────────────────────────────────────────────
|
|
301
|
-
//
|
|
302
|
-
// ResolveBuckets<BucketMap, Buckets> intersects the bucket types selected by
|
|
303
|
-
// the developer. When no scopes are declared, returns NoScope so that accessing
|
|
304
|
-
// any field is a compile-time error.
|
|
305
|
-
|
|
306
|
-
type ResolveBuckets<M, B> = B extends readonly (keyof M)[]
|
|
307
|
-
? [B[number]] extends [never]
|
|
308
|
-
? NoScope
|
|
309
|
-
: UnionToIntersection<M[B[number]]>
|
|
310
|
-
: NoScope;
|
|
311
|
-
|
|
312
|
-
export type ResolveEmployee<S extends ScopeDeclaration> = ResolveBuckets<
|
|
313
|
-
EmployeeBucketMap,
|
|
314
|
-
S['employees']
|
|
315
|
-
>;
|
|
316
|
-
|
|
317
|
-
export type ResolveProject<S extends ScopeDeclaration> = ResolveBuckets<
|
|
318
|
-
ProjectBucketMap,
|
|
319
|
-
S['projects']
|
|
320
|
-
>;
|
|
321
|
-
|
|
322
|
-
export type ResolveClient<S extends ScopeDeclaration> = ResolveBuckets<
|
|
323
|
-
ClientBucketMap,
|
|
324
|
-
S['clients']
|
|
325
|
-
>;
|
|
326
|
-
|
|
327
|
-
export type ResolvePartner<S extends ScopeDeclaration> = ResolveBuckets<
|
|
328
|
-
PartnerBucketMap,
|
|
329
|
-
S['partners']
|
|
330
|
-
>;
|
|
331
|
-
|
|
332
|
-
export type ResolveDepartment<S extends ScopeDeclaration> = ResolveBuckets<
|
|
333
|
-
DepartmentBucketMap,
|
|
334
|
-
S['departments']
|
|
335
|
-
>;
|
|
336
|
-
|
|
337
|
-
export type ResolveProjectType<S extends ScopeDeclaration> = ResolveBuckets<
|
|
338
|
-
ProjectTypeBucketMap,
|
|
339
|
-
S['projectTypes']
|
|
340
|
-
>;
|
|
341
|
-
|
|
342
|
-
export type ResolveCurrency<S extends ScopeDeclaration> = ResolveBuckets<
|
|
343
|
-
CurrencyBucketMap,
|
|
344
|
-
S['currencies']
|
|
345
|
-
>;
|
|
346
|
-
|
|
347
|
-
export type ResolveGenericRate<S extends ScopeDeclaration> = ResolveBuckets<
|
|
348
|
-
GenericRateBucketMap,
|
|
349
|
-
S['genericRates']
|
|
350
|
-
>;
|
|
351
|
-
|
|
352
|
-
// ─── Expand paths (§3.7, §7) — max two levels, no three-segment paths ────────
|
|
353
|
-
|
|
354
|
-
export type EmployeeExpandPath = 'manager' | 'partner';
|
|
355
|
-
|
|
356
|
-
// Expand contributions added to the base employee type
|
|
357
|
-
export type WithEmployeeExpand<
|
|
358
|
-
T,
|
|
359
|
-
E extends readonly EmployeeExpandPath[],
|
|
360
|
-
S extends ScopeDeclaration,
|
|
361
|
-
> = T &
|
|
362
|
-
('manager' extends E[number] ? { manager: ResolveEmployee<S> | null } : unknown) &
|
|
363
|
-
('partner' extends E[number] ? { partner: PartnerIdentity | null } : unknown);
|
|
364
|
-
|
|
365
|
-
export type ProjectExpandPath =
|
|
366
|
-
| 'projectType'
|
|
367
|
-
| 'client'
|
|
368
|
-
| 'projectManager'
|
|
369
|
-
| 'projectManager.manager'
|
|
370
|
-
| 'engagementLead'
|
|
371
|
-
| 'engagementLead.manager'
|
|
372
|
-
| 'memberships.employee';
|
|
373
|
-
|
|
374
|
-
// Expand contributions for projects. Handles depth-2 paths by nesting manager.
|
|
375
|
-
// memberships.employee overrides the memberships[] type to include employee.
|
|
376
|
-
type ProjectMembershipExpanded<S extends ScopeDeclaration> = {
|
|
377
|
-
employeeId: string;
|
|
378
|
-
role: string | null;
|
|
379
|
-
employee: ResolveEmployee<S>;
|
|
380
|
-
};
|
|
381
|
-
|
|
382
|
-
export type WithProjectExpand<
|
|
383
|
-
T,
|
|
384
|
-
E extends readonly ProjectExpandPath[],
|
|
385
|
-
S extends ScopeDeclaration,
|
|
386
|
-
> = ('memberships.employee' extends E[number]
|
|
387
|
-
? Omit<T, 'memberships'> & { memberships: Array<ProjectMembershipExpanded<S>> }
|
|
388
|
-
: T) &
|
|
389
|
-
('client' extends E[number] ? { client: ResolveClient<S> | null } : unknown) &
|
|
390
|
-
('projectType' extends E[number] ? { projectType: ProjectTypeCore | null } : unknown) &
|
|
391
|
-
('projectManager.manager' extends E[number]
|
|
392
|
-
? { projectManager: (ResolveEmployee<S> & { manager: ResolveEmployee<S> | null }) | null }
|
|
393
|
-
: 'projectManager' extends E[number]
|
|
394
|
-
? { projectManager: ResolveEmployee<S> | null }
|
|
395
|
-
: unknown) &
|
|
396
|
-
('engagementLead.manager' extends E[number]
|
|
397
|
-
? { engagementLead: (ResolveEmployee<S> & { manager: ResolveEmployee<S> | null }) | null }
|
|
398
|
-
: 'engagementLead' extends E[number]
|
|
399
|
-
? { engagementLead: ResolveEmployee<S> | null }
|
|
400
|
-
: unknown);
|
|
401
|
-
|
|
402
|
-
export type ClientExpandPath = 'projects';
|
|
403
|
-
|
|
404
|
-
export type WithClientExpand<
|
|
405
|
-
T,
|
|
406
|
-
E extends readonly ClientExpandPath[],
|
|
407
|
-
S extends ScopeDeclaration,
|
|
408
|
-
> = T & ('projects' extends E[number] ? { projects: Array<ResolveProject<S>> } : unknown);
|
|
409
|
-
|
|
410
|
-
export type PartnerExpandPath = 'employees';
|
|
411
|
-
|
|
412
|
-
export type WithPartnerExpand<
|
|
413
|
-
T,
|
|
414
|
-
E extends readonly PartnerExpandPath[],
|
|
415
|
-
S extends ScopeDeclaration,
|
|
416
|
-
> = T & ('employees' extends E[number] ? { employees: Array<ResolveEmployee<S>> } : unknown);
|
|
417
|
-
|
|
418
|
-
// ─── apps.me() response ──────────────────────────────────────────────────────
|
|
419
|
-
|
|
420
|
-
export type AppScopeInfo = {
|
|
421
|
-
id: string;
|
|
422
|
-
resource: string;
|
|
423
|
-
buckets: string[];
|
|
424
|
-
status: 'active' | 'pending' | 'rejected';
|
|
425
|
-
reviewNote: string | null;
|
|
426
|
-
};
|
|
427
|
-
|
|
428
|
-
export type AppInfo = {
|
|
429
|
-
id: string;
|
|
430
|
-
appId: string;
|
|
431
|
-
name: string;
|
|
432
|
-
description: string | null;
|
|
433
|
-
icon: string | null;
|
|
434
|
-
environment: string;
|
|
435
|
-
status: string;
|
|
436
|
-
scopes: AppScopeInfo[];
|
|
437
|
-
tokens: {
|
|
438
|
-
id: string;
|
|
439
|
-
tokenPrefix: string;
|
|
440
|
-
environment: string;
|
|
441
|
-
status: string;
|
|
442
|
-
lastUsedAt: string | null;
|
|
443
|
-
expiresAt: string | null;
|
|
444
|
-
createdAt: string;
|
|
445
|
-
}[];
|
|
446
|
-
createdAt: string;
|
|
447
|
-
};
|
package/tsconfig.json
DELETED
package/tsconfig.verify.json
DELETED
|
Binary file
|
package/verify.ts
DELETED
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Compile-time type verification for the Nucleus SDK.
|
|
3
|
-
*
|
|
4
|
-
* This file is never executed — it only needs to pass `tsc --noEmit`.
|
|
5
|
-
* Each block demonstrates an expected compile-time behaviour.
|
|
6
|
-
* Lines marked @ts-expect-error MUST produce a type error; if they don't,
|
|
7
|
-
* the check fails.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { NucleusClient, isError, type ResolveEmployee, type ScopeDeclaration } from './src/index';
|
|
11
|
-
|
|
12
|
-
// ─── 1. identity-only scope ──────────────────────────────────────────────────
|
|
13
|
-
|
|
14
|
-
declare const nucleus1: NucleusClient<{
|
|
15
|
-
employees: ['identity'];
|
|
16
|
-
}>;
|
|
17
|
-
|
|
18
|
-
async function check1() {
|
|
19
|
-
const result = await nucleus1.employees.getById('emp_123');
|
|
20
|
-
if (isError(result)) return;
|
|
21
|
-
|
|
22
|
-
const emp = result.data;
|
|
23
|
-
|
|
24
|
-
// identity fields — must be accessible
|
|
25
|
-
const _email: string = emp.email;
|
|
26
|
-
const _displayName: string = emp.displayName;
|
|
27
|
-
const _id: string = emp.id;
|
|
28
|
-
|
|
29
|
-
// @ts-expect-error — 'phone' is in the contact bucket, not declared
|
|
30
|
-
const _phone = emp.phone;
|
|
31
|
-
|
|
32
|
-
// @ts-expect-error — 'managerId' is in the employment bucket, not declared
|
|
33
|
-
const _mgr = emp.managerId;
|
|
34
|
-
|
|
35
|
-
// @ts-expect-error — 'birthday' is in the sensitive bucket, not declared
|
|
36
|
-
const _bday = emp.birthday;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// ─── 2. identity + employment scope ─────────────────────────────────────────
|
|
40
|
-
|
|
41
|
-
declare const nucleus2: NucleusClient<{
|
|
42
|
-
employees: ['identity', 'employment'];
|
|
43
|
-
}>;
|
|
44
|
-
|
|
45
|
-
async function check2() {
|
|
46
|
-
const result = await nucleus2.employees.getById('emp_123');
|
|
47
|
-
if (isError(result)) return;
|
|
48
|
-
|
|
49
|
-
const emp = result.data;
|
|
50
|
-
|
|
51
|
-
// both buckets accessible
|
|
52
|
-
const _email: string = emp.email;
|
|
53
|
-
const _managerId: string | null = emp.managerId;
|
|
54
|
-
const _weeklyCapacity: number | null = emp.weeklyCapacity;
|
|
55
|
-
|
|
56
|
-
// @ts-expect-error — still no contact scope
|
|
57
|
-
const _phone = emp.phone;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// ─── 3. expand: ['manager'] changes type ─────────────────────────────────────
|
|
61
|
-
|
|
62
|
-
declare const nucleus3: NucleusClient<{
|
|
63
|
-
employees: ['identity', 'employment'];
|
|
64
|
-
}>;
|
|
65
|
-
|
|
66
|
-
async function check3() {
|
|
67
|
-
const result = await nucleus3.employees.getById('emp_123', {
|
|
68
|
-
expand: ['manager'],
|
|
69
|
-
});
|
|
70
|
-
if (isError(result)) return;
|
|
71
|
-
|
|
72
|
-
const emp = result.data;
|
|
73
|
-
|
|
74
|
-
// manager is now an object (or null) — not just a managerId string
|
|
75
|
-
if (emp.manager) {
|
|
76
|
-
const _mgrEmail: string = emp.manager.email;
|
|
77
|
-
const _mgrName: string = emp.manager.displayName;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// ─── 4. three-segment expand path is a compile error ────────────────────────
|
|
82
|
-
|
|
83
|
-
declare const nucleus4: NucleusClient<{
|
|
84
|
-
projects: ['core', 'team'];
|
|
85
|
-
employees: ['identity'];
|
|
86
|
-
clients: ['identity'];
|
|
87
|
-
}>;
|
|
88
|
-
|
|
89
|
-
async function check4() {
|
|
90
|
-
await nucleus4.projects.getById('proj_123', {
|
|
91
|
-
// @ts-expect-error — 'client.projects.something' has 3 segments → not a valid ProjectExpandPath
|
|
92
|
-
expand: ['client.projects.something'],
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
// Two-segment paths are valid
|
|
96
|
-
const result = await nucleus4.projects.getById('proj_123', {
|
|
97
|
-
expand: ['projectManager', 'projectManager.manager'],
|
|
98
|
-
});
|
|
99
|
-
if (isError(result)) return;
|
|
100
|
-
|
|
101
|
-
const proj = result.data;
|
|
102
|
-
if (proj.projectManager) {
|
|
103
|
-
const _name: string = proj.projectManager.displayName;
|
|
104
|
-
if (proj.projectManager.manager) {
|
|
105
|
-
const _mgrName: string = proj.projectManager.manager.displayName;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// ─── 5. list() returns meta with hasMore ─────────────────────────────────────
|
|
111
|
-
|
|
112
|
-
declare const nucleus5: NucleusClient<{ employees: ['identity'] }>;
|
|
113
|
-
|
|
114
|
-
async function check5() {
|
|
115
|
-
const result = await nucleus5.employees.list({ page: 1, pageSize: 20 });
|
|
116
|
-
if (isError(result)) return;
|
|
117
|
-
|
|
118
|
-
const _total: number = result.meta.total;
|
|
119
|
-
const _hasMore: boolean = result.meta.hasMore;
|
|
120
|
-
const _page: number = result.meta.page;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// ─── 6. isError() narrow helper ──────────────────────────────────────────────
|
|
124
|
-
|
|
125
|
-
declare const nucleus6: NucleusClient<{ employees: ['identity'] }>;
|
|
126
|
-
|
|
127
|
-
async function check6() {
|
|
128
|
-
const result = await nucleus6.employees.getById('emp_x');
|
|
129
|
-
|
|
130
|
-
if (isError(result)) {
|
|
131
|
-
// code is typed, not just string
|
|
132
|
-
const _code: 'FORBIDDEN' | 'NOT_FOUND' | 'INVALID_SCOPE' | 'RATE_LIMITED' | 'NETWORK_ERROR' =
|
|
133
|
-
result.error.code;
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// TypeScript knows result.data is available here
|
|
138
|
-
const _id: string = result.data.id;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// ─── 7. apps.me() return type ────────────────────────────────────────────────
|
|
142
|
-
|
|
143
|
-
declare const nucleus7: NucleusClient<{}>;
|
|
144
|
-
|
|
145
|
-
async function check7() {
|
|
146
|
-
const result = await nucleus7.apps.me();
|
|
147
|
-
if (isError(result)) return;
|
|
148
|
-
|
|
149
|
-
const _name: string = result.data.name;
|
|
150
|
-
const _scopes = result.data.scopes; // AppScopeInfo[]
|
|
151
|
-
const _status = _scopes[0]?.status; // 'active' | 'pending' | 'rejected' | undefined
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// ─── 8. no scope declared → NoScope type ────────────────────────────────────
|
|
155
|
-
|
|
156
|
-
declare const nucleus8: NucleusClient<{}>;
|
|
157
|
-
|
|
158
|
-
async function check8() {
|
|
159
|
-
const result = await nucleus8.employees.getById('emp_x');
|
|
160
|
-
if (isError(result)) return;
|
|
161
|
-
|
|
162
|
-
// @ts-expect-error — no employees scope declared at all
|
|
163
|
-
const _email = result.data.email;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// ─── 9. type helper: ResolveEmployee ─────────────────────────────────────────
|
|
167
|
-
|
|
168
|
-
type S = { employees: ['identity', 'compensation'] };
|
|
169
|
-
type Emp = ResolveEmployee<S>;
|
|
170
|
-
// Should have identity fields
|
|
171
|
-
type _hasId = Emp extends { id: string } ? true : false; // true
|
|
172
|
-
type _hasComp = Emp extends { currentCompensation: unknown } ? true : false; // true
|
|
173
|
-
|
|
174
|
-
// ─── Suppress unused-variable warnings ───────────────────────────────────────
|
|
175
|
-
void check1;
|
|
176
|
-
void check2;
|
|
177
|
-
void check3;
|
|
178
|
-
void check4;
|
|
179
|
-
void check5;
|
|
180
|
-
void check6;
|
|
181
|
-
void check7;
|
|
182
|
-
void check8;
|