@awesomate/sdk 0.34.0 → 0.45.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/index.d.ts +282 -11
- package/dist/index.js +71 -4
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
* Docs: https://hub.awesomate.ai/docs/sdk/
|
|
27
27
|
*/
|
|
28
28
|
/** This package's version, sent to the hub with every server call. */
|
|
29
|
-
export declare const VERSION = "0.
|
|
29
|
+
export declare const VERSION = "0.45.0";
|
|
30
30
|
/** Augmented by the generated awesomate.d.ts, so each kind's rows are typed. */
|
|
31
31
|
export interface Kinds {
|
|
32
32
|
}
|
|
@@ -135,7 +135,7 @@ export interface QueryOptions<T, S extends keyof T = keyof T> {
|
|
|
135
135
|
* read, tags included, any case. Narrows like where does, and the two combine.
|
|
136
136
|
*/
|
|
137
137
|
search?: string;
|
|
138
|
-
/** IANA zone for dates and time variables. Default
|
|
138
|
+
/** IANA zone for dates and time variables. Default: the business's time zone from Your business, Sydney if none is set. */
|
|
139
139
|
tz?: string;
|
|
140
140
|
}
|
|
141
141
|
/** What the hub assumed for a query (order, limit, time zone, what each time variable meant), so it can be said back. */
|
|
@@ -243,6 +243,28 @@ export interface TaskCard {
|
|
|
243
243
|
canDrop: boolean;
|
|
244
244
|
canEdit: boolean;
|
|
245
245
|
} | null;
|
|
246
|
+
/**
|
|
247
|
+
* Set for a task given to a role on the business map rather than a person (an agent's or a
|
|
248
|
+
* stage's): everyone in the role sees it until one of them takes it. `queued` while nobody has;
|
|
249
|
+
* `takenBy` once someone has; `mayTake` when this token's owner may take it with take(). Null or
|
|
250
|
+
* absent for every other card.
|
|
251
|
+
*/
|
|
252
|
+
role?: {
|
|
253
|
+
jobId: number;
|
|
254
|
+
slug: string | null;
|
|
255
|
+
title: string | null;
|
|
256
|
+
queued: boolean;
|
|
257
|
+
takenBy: TaskPerson | null;
|
|
258
|
+
/** Nobody took it in 4 business hours, so it went to the person responsible for the role. */
|
|
259
|
+
unclaimed?: boolean;
|
|
260
|
+
/** While it waits: when it goes to the person responsible if nobody takes it, and that as a sentence. */
|
|
261
|
+
goesTo?: {
|
|
262
|
+
at: string;
|
|
263
|
+
words: string;
|
|
264
|
+
} | null;
|
|
265
|
+
inRole: boolean;
|
|
266
|
+
mayTake: boolean;
|
|
267
|
+
} | null;
|
|
246
268
|
}
|
|
247
269
|
/** A card's one-tap action, by name (the hub page behind the card runs it). */
|
|
248
270
|
export type TaskCardAction = {
|
|
@@ -258,6 +280,11 @@ export type TaskCardAction = {
|
|
|
258
280
|
} | {
|
|
259
281
|
name: 'finish_task';
|
|
260
282
|
taskId: number;
|
|
283
|
+
}
|
|
284
|
+
/** A role's task nobody has taken yet: take() makes it yours. */
|
|
285
|
+
| {
|
|
286
|
+
name: 'take_task';
|
|
287
|
+
taskId: number;
|
|
261
288
|
} | {
|
|
262
289
|
name: 'approve_public_reply';
|
|
263
290
|
taskId: number;
|
|
@@ -337,6 +364,16 @@ export interface DecisionCard {
|
|
|
337
364
|
kind: 'person' | 'owners';
|
|
338
365
|
label: string;
|
|
339
366
|
};
|
|
367
|
+
/**
|
|
368
|
+
* A role's decision within the role's limits: anyone in `role` who can decide it may answer it, and
|
|
369
|
+
* the first answer decides it. `people` is how many may answer it now; `line` is the sentence the
|
|
370
|
+
* hub shows ("Any of you in Bookkeeping can answer."). Null or absent when only `decider` can.
|
|
371
|
+
*/
|
|
372
|
+
shared?: {
|
|
373
|
+
role: string;
|
|
374
|
+
people: number;
|
|
375
|
+
line: string;
|
|
376
|
+
} | null;
|
|
340
377
|
/** Work waits behind it: a yes lets it carry on. */
|
|
341
378
|
holdsWork: boolean;
|
|
342
379
|
/** What may be pressed now. Always empty for an account token: deciding is a person's tap in the hub. */
|
|
@@ -468,6 +505,13 @@ export interface GiveTask {
|
|
|
468
505
|
dueAt?: string;
|
|
469
506
|
/** A hub path the task points at, e.g. /contacts/people/... */
|
|
470
507
|
linkPath?: string;
|
|
508
|
+
/**
|
|
509
|
+
* Something that can't wait: a hot lead, a fault, a staff alert. It goes to the person's linked
|
|
510
|
+
* chats straight away, past their daily limit, and in their quiet hours only to the chat they chose
|
|
511
|
+
* to be woken in (or not until morning, if they chose none). At most five a day per person; urgent
|
|
512
|
+
* wears off a day after it is given. Leave it out for anything else.
|
|
513
|
+
*/
|
|
514
|
+
urgent?: boolean;
|
|
471
515
|
}
|
|
472
516
|
/** A file or folder in the account's Files (the folders on its automation account: public/, private/, temp/). */
|
|
473
517
|
export interface FileEntry {
|
|
@@ -722,6 +766,7 @@ export declare class AwesomateClient {
|
|
|
722
766
|
*
|
|
723
767
|
* @example
|
|
724
768
|
* await db.tasks.give({ title: 'Call Sam back about the leak', forEmail: 'jo@brightwater.example', dueAt: '2026-10-06T09:00:00+11:00' });
|
|
769
|
+
* await db.tasks.give({ title: 'Hot lead: Sam wants a quote today', forEmail: 'jo@brightwater.example', urgent: true });
|
|
725
770
|
*/
|
|
726
771
|
readonly tasks: {
|
|
727
772
|
/** The board: waiting now, put off, with someone else, recently decided. `all` shows everyone's, not only yours. hosting:read. */
|
|
@@ -745,15 +790,34 @@ export declare class AwesomateClient {
|
|
|
745
790
|
decisionRecord: (taskId: number | string) => Promise<TaskRecord & {
|
|
746
791
|
kind: "decision";
|
|
747
792
|
}>;
|
|
748
|
-
/**
|
|
793
|
+
/**
|
|
794
|
+
* Give a task. The person gets it on their board, an email when they are not the one giving it,
|
|
795
|
+
* and a card in any chat they linked, within their quiet hours and daily limit (`urgent` goes
|
|
796
|
+
* straight away). `urgent` in the result says whether it went as urgent: a person's sixth urgent
|
|
797
|
+
* task in a day goes as an ordinary one, and `note` says so. hosting:manage.
|
|
798
|
+
*/
|
|
749
799
|
give: (task: GiveTask) => Promise<{
|
|
750
800
|
key: string;
|
|
751
801
|
id: number;
|
|
752
802
|
holder: TaskPerson;
|
|
753
803
|
emailed: boolean;
|
|
804
|
+
urgent: boolean;
|
|
805
|
+
note?: string;
|
|
754
806
|
}>;
|
|
755
|
-
/**
|
|
756
|
-
|
|
807
|
+
/**
|
|
808
|
+
* Change a given task: whoever wrote it, or the owner. `urgent: false` takes urgent off; a task can
|
|
809
|
+
* only be marked urgent when it is given. hosting:manage.
|
|
810
|
+
*/
|
|
811
|
+
update: (id: number | string, patch: Partial<Omit<GiveTask, "forEmail" | "urgent">> & {
|
|
812
|
+
urgent?: false;
|
|
813
|
+
}) => Promise<void>;
|
|
814
|
+
/**
|
|
815
|
+
* Take a role's task (a card with `role.mayTake`): it becomes the owner's, and everyone else in
|
|
816
|
+
* the role sees who took it. Only someone in the role can take it, so this works for the owner
|
|
817
|
+
* only when they are in that role (serverCode `not_in_role` otherwise). Someone who got there
|
|
818
|
+
* first answers `taken`, with their name in the message. hosting:manage.
|
|
819
|
+
*/
|
|
820
|
+
take: (id: number | string) => Promise<void>;
|
|
757
821
|
/** Mark a given task done: the person who has it, whoever wrote it, or the owner. hosting:manage. */
|
|
758
822
|
done: (id: number | string) => Promise<void>;
|
|
759
823
|
/** Take a given task off the board without doing it: whoever wrote it, or the owner. hosting:manage. */
|
|
@@ -1022,6 +1086,19 @@ export declare class AwesomateClient {
|
|
|
1022
1086
|
addTags: (id: string, tags: string[]) => Promise<ContactTagsResult>;
|
|
1023
1087
|
/** Take tags off a person, up to 20 a call. Answers how many they had. */
|
|
1024
1088
|
removeTags: (id: string, tags: string[]) => Promise<ContactTagsResult>;
|
|
1089
|
+
/**
|
|
1090
|
+
* Record that the person asked to stop getting email, by reply, phone, in person or in writing
|
|
1091
|
+
* (`how`), at the time they asked (`askedAt`, default now, at most 30 days back). With no `list`
|
|
1092
|
+
* it stops every email, booking confirmations and other service emails included; with a list's
|
|
1093
|
+
* key, that list only. Recorded as the person's own withdrawal, so a later import never puts
|
|
1094
|
+
* them back. Answers `changed: false` when it was already recorded. The law gives 5 business
|
|
1095
|
+
* days from when they asked. A person with no email address is refused (validation).
|
|
1096
|
+
*/
|
|
1097
|
+
unsubscribe: (id: string, options: {
|
|
1098
|
+
how: ContactStopHow;
|
|
1099
|
+
list?: string;
|
|
1100
|
+
askedAt?: Date | string;
|
|
1101
|
+
}) => Promise<ContactUnsubscribeResult>;
|
|
1025
1102
|
/**
|
|
1026
1103
|
* Add a contact field. The hub makes its key from the label with a random part and answers it:
|
|
1027
1104
|
* use that key. Nothing here changes a field that exists. `ai_may_read` decides, once and now,
|
|
@@ -1151,6 +1228,18 @@ export declare class AwesomateClient {
|
|
|
1151
1228
|
get<K extends KindName>(kind: K, id: string, options?: {
|
|
1152
1229
|
tz?: string;
|
|
1153
1230
|
}): Promise<RowOf<K> | null>;
|
|
1231
|
+
/**
|
|
1232
|
+
* What points at one row: for each link from another kind (a job's customer, a memo's job), how
|
|
1233
|
+
* many rows point here and the newest of them (`limit`, default 20, at most 100), read as query()
|
|
1234
|
+
* reads that kind. Null when there is no such row. The account's token, crm:read.
|
|
1235
|
+
*
|
|
1236
|
+
* @example
|
|
1237
|
+
* const related = await db.related('contact', contactId);
|
|
1238
|
+
* for (const r of related ?? []) console.log(r.kind, r.link, r.count);
|
|
1239
|
+
*/
|
|
1240
|
+
related(kind: KindName, id: string, options?: {
|
|
1241
|
+
limit?: number;
|
|
1242
|
+
}): Promise<RelatedRows[] | null>;
|
|
1154
1243
|
/** The app kinds this account has defined. The account's token, crm:read, every plan; never an app key. */
|
|
1155
1244
|
kinds(): Promise<KindDescription[]>;
|
|
1156
1245
|
/**
|
|
@@ -1210,6 +1299,18 @@ export declare class AwesomateClient {
|
|
|
1210
1299
|
write<K extends KindName>(kind: K, data: Partial<RowOf<K>> | Record<string, unknown>, options?: WriteOptions): Promise<string>;
|
|
1211
1300
|
/** Archive a record: it leaves every read and is kept for a restore. Needs what write() needs. */
|
|
1212
1301
|
archive<K extends KindName>(kind: K, id: string): Promise<void>;
|
|
1302
|
+
/**
|
|
1303
|
+
* Create or change the record that mirrors one in another system, found by that system's name and
|
|
1304
|
+
* its id there (`ref.system`, lower case like `xero`; `ref.externalId`), so a sync run twice changes
|
|
1305
|
+
* the record instead of making a second one. The same checks as write(). A record with that id that
|
|
1306
|
+
* was archived is refused (`conflict`): a sync never undoes an archive or makes a second copy. Companies
|
|
1307
|
+
* are refused here: use companies.upsert(), which matches by ABN and name. The account's token only
|
|
1308
|
+
* (never an app key), crm:write, Support Plus and above.
|
|
1309
|
+
*
|
|
1310
|
+
* @example
|
|
1311
|
+
* const { id, created } = await db.upsertByRef('job', { system: 'servicem8', externalId: 'JOB-0042' }, { title: 'Possum in the roof' }, { links: { customer: contactId } });
|
|
1312
|
+
*/
|
|
1313
|
+
upsertByRef<K extends KindName>(kind: K, ref: RecordRef, data?: Partial<RowOf<K>> | Record<string, unknown>, options?: Omit<WriteOptions, 'id'>): Promise<UpsertByRefResult>;
|
|
1213
1314
|
/** The saved queries on this account. crm:read, every plan: the account's token or an app key. */
|
|
1214
1315
|
queries(): Promise<SavedQueryDescription[]>;
|
|
1215
1316
|
/**
|
|
@@ -1420,6 +1521,7 @@ export interface BusinessMapRole {
|
|
|
1420
1521
|
headsDepartment: boolean;
|
|
1421
1522
|
/** Runs its sub-department: the person responsible for it, and for its KPIs. */
|
|
1422
1523
|
headsSubDepartment: boolean;
|
|
1524
|
+
/** The sub-department's key (see BusinessMapSubDepartment.no): match it there for the name, never show it. */
|
|
1423
1525
|
subDepartmentNo: number | null;
|
|
1424
1526
|
reportsTo: {
|
|
1425
1527
|
id: number;
|
|
@@ -1436,17 +1538,91 @@ export interface BusinessMapRole {
|
|
|
1436
1538
|
level: BusinessMapLevel;
|
|
1437
1539
|
exceptions: string | null;
|
|
1438
1540
|
}>;
|
|
1541
|
+
/**
|
|
1542
|
+
* Its helpers. `look` says what the hub draws: an Awesomate agent's picture URL, a full link to the
|
|
1543
|
+
* hub (null: the hub draws its initials; always null when the account does not have Agents) and
|
|
1544
|
+
* whether it is on (null when that could not be read), an n8n agent's icon, an automation's bolt.
|
|
1545
|
+
*/
|
|
1439
1546
|
helpers: Array<BusinessMapHelper & {
|
|
1440
1547
|
id: number;
|
|
1441
1548
|
supervisor: string;
|
|
1442
1549
|
level: BusinessMapLevel | null;
|
|
1443
1550
|
exceptions: string | null;
|
|
1444
1551
|
minutesSavedPerRun: number | null;
|
|
1552
|
+
look: {
|
|
1553
|
+
kind: 'awesomate' | 'n8n' | 'automation' | 'external';
|
|
1554
|
+
picture: string | null;
|
|
1555
|
+
state: 'on' | 'off' | null;
|
|
1556
|
+
};
|
|
1445
1557
|
}>;
|
|
1446
1558
|
/** The tag this role's procedures carry in 1Brain, such as 'job:quotes'. The map keeps no procedure text. */
|
|
1447
1559
|
proceduresTag: string;
|
|
1448
1560
|
/** Quarterly priorities on this role, every quarter. */
|
|
1449
1561
|
priorities: BusinessMapPriority[];
|
|
1562
|
+
/** Its responsibilities as processes, in the same order: what writes each down and who does it. */
|
|
1563
|
+
processes: BusinessMapProcess[];
|
|
1564
|
+
/** How many processes it has, how many are written down, how many automated. */
|
|
1565
|
+
progress: {
|
|
1566
|
+
processes: number;
|
|
1567
|
+
written: number;
|
|
1568
|
+
automated: number;
|
|
1569
|
+
};
|
|
1570
|
+
/** Ready to hand over: the owner is still responsible for it and every process is written down or automated. */
|
|
1571
|
+
ready: boolean;
|
|
1572
|
+
/** The one line the map shows for it ("Booking reminders failed twice this week"), or null. */
|
|
1573
|
+
flag: string | null;
|
|
1574
|
+
}
|
|
1575
|
+
/** The one next step the map suggests, with its button's words and what the button does. */
|
|
1576
|
+
export interface BusinessMapNextStep {
|
|
1577
|
+
title: string;
|
|
1578
|
+
detail: string;
|
|
1579
|
+
button: string;
|
|
1580
|
+
action: {
|
|
1581
|
+
kind: 'hand_over';
|
|
1582
|
+
roleId: number;
|
|
1583
|
+
roleSlug: string;
|
|
1584
|
+
membershipId: number | null;
|
|
1585
|
+
} | {
|
|
1586
|
+
kind: 'open_role';
|
|
1587
|
+
roleId: number;
|
|
1588
|
+
roleSlug: string;
|
|
1589
|
+
} | {
|
|
1590
|
+
kind: 'link';
|
|
1591
|
+
path: string;
|
|
1592
|
+
} | {
|
|
1593
|
+
kind: 'add_role';
|
|
1594
|
+
departmentNo: number;
|
|
1595
|
+
} | {
|
|
1596
|
+
kind: 'edit_path';
|
|
1597
|
+
} | {
|
|
1598
|
+
kind: 'place_helpers';
|
|
1599
|
+
};
|
|
1600
|
+
}
|
|
1601
|
+
/**
|
|
1602
|
+
* One of a role's processes (a responsibility). Written down: a 1Brain page on the role's own list of
|
|
1603
|
+
* 1Brain systems is linked to it. Automated: an agent or automation on the role does it, at any level.
|
|
1604
|
+
*/
|
|
1605
|
+
export interface BusinessMapProcess {
|
|
1606
|
+
text: string;
|
|
1607
|
+
level: BusinessMapLevel;
|
|
1608
|
+
/** The 1Brain page that writes it down, by its ids and title; null when it is not written down yet. */
|
|
1609
|
+
procedure: {
|
|
1610
|
+
accountId: number;
|
|
1611
|
+
itemId: number;
|
|
1612
|
+
title: string;
|
|
1613
|
+
} | null;
|
|
1614
|
+
/** Who does it: the role's holder, or a helper on the role. */
|
|
1615
|
+
doneBy: {
|
|
1616
|
+
kind: 'holder';
|
|
1617
|
+
name: string | null;
|
|
1618
|
+
} | {
|
|
1619
|
+
kind: 'helper';
|
|
1620
|
+
helperId: number;
|
|
1621
|
+
label: string;
|
|
1622
|
+
helperKind: BusinessMapHelper['kind'];
|
|
1623
|
+
};
|
|
1624
|
+
/** How far whoever does it goes alone, in words: a helper's level, else the role's limits, else "A person". */
|
|
1625
|
+
mayActAlone: string;
|
|
1450
1626
|
}
|
|
1451
1627
|
/** A quarterly priority on a role: one of the few things it must move this quarter. */
|
|
1452
1628
|
export interface BusinessMapPriority {
|
|
@@ -1465,6 +1641,8 @@ export interface BusinessMapPathStep {
|
|
|
1465
1641
|
position: number;
|
|
1466
1642
|
label: string;
|
|
1467
1643
|
departmentNo: 1 | 2 | 3 | 4 | 5 | 6 | 7;
|
|
1644
|
+
/** The department's plain name ("Sales"): what people read. */
|
|
1645
|
+
name: string;
|
|
1468
1646
|
verb: string;
|
|
1469
1647
|
/** The role that looks after the step, when the owner named one. */
|
|
1470
1648
|
role: {
|
|
@@ -1480,11 +1658,25 @@ export interface BusinessMapPathStep {
|
|
|
1480
1658
|
/** Where this step hands over to the next, in the owner's words. */
|
|
1481
1659
|
handoffRule: string | null;
|
|
1482
1660
|
}
|
|
1483
|
-
/**
|
|
1661
|
+
/**
|
|
1662
|
+
* A sub-department and who runs it: the holder of the role that heads it, else whoever runs the
|
|
1663
|
+
* department (byDefault). Each business names, orders and adds its own, so they come in the
|
|
1664
|
+
* business's order and by its names.
|
|
1665
|
+
*/
|
|
1484
1666
|
export interface BusinessMapSubDepartment {
|
|
1667
|
+
/**
|
|
1668
|
+
* A key, never shown to people: 1 to 21 for a standard sub-department, 1001 and up for one the
|
|
1669
|
+
* owner added. A role's subDepartmentNo is this key.
|
|
1670
|
+
*/
|
|
1485
1671
|
no: number;
|
|
1672
|
+
/** The business's name for it: show this. */
|
|
1486
1673
|
name: string;
|
|
1487
|
-
|
|
1674
|
+
/** The standard name, or null for one the owner added. Differs from name when the owner renamed it. */
|
|
1675
|
+
standardName: string | null;
|
|
1676
|
+
/** The owner added it. */
|
|
1677
|
+
custom: boolean;
|
|
1678
|
+
/** What a standard one covers; null for one the owner added. */
|
|
1679
|
+
gloss: string | null;
|
|
1488
1680
|
runBy: {
|
|
1489
1681
|
name: string;
|
|
1490
1682
|
byDefault: boolean;
|
|
@@ -1513,6 +1705,7 @@ export interface BusinessMapDepartment {
|
|
|
1513
1705
|
helpers: Array<BusinessMapHelper & {
|
|
1514
1706
|
placedBy: string;
|
|
1515
1707
|
}>;
|
|
1708
|
+
/** In the business's order, by its names. */
|
|
1516
1709
|
subDepartments: BusinessMapSubDepartment[];
|
|
1517
1710
|
ideas: Array<{
|
|
1518
1711
|
label: string;
|
|
@@ -1527,7 +1720,7 @@ export interface BusinessMapDepartment {
|
|
|
1527
1720
|
question: string;
|
|
1528
1721
|
/** 1Brain Departments whose procedures belong in this department. */
|
|
1529
1722
|
oneBrainDepartments: string[];
|
|
1530
|
-
/** People on the map who hold no role yet. They sit in
|
|
1723
|
+
/** People on the map who hold no role yet. They sit in Team and systems (department 1) for display; empty for every other department. */
|
|
1531
1724
|
noRoleYet: Array<{
|
|
1532
1725
|
id: number;
|
|
1533
1726
|
name: string;
|
|
@@ -1591,6 +1784,26 @@ export interface BusinessMap {
|
|
|
1591
1784
|
departmentsWithHelpers: number;
|
|
1592
1785
|
roles: number;
|
|
1593
1786
|
};
|
|
1787
|
+
/**
|
|
1788
|
+
* How far the business has got: the roles the owner is still responsible for (their own included) of
|
|
1789
|
+
* every role, and the processes written down and automated, each of every process.
|
|
1790
|
+
*/
|
|
1791
|
+
progress: {
|
|
1792
|
+
rolesYouHold: {
|
|
1793
|
+
held: number;
|
|
1794
|
+
of: number;
|
|
1795
|
+
};
|
|
1796
|
+
written: {
|
|
1797
|
+
done: number;
|
|
1798
|
+
of: number;
|
|
1799
|
+
};
|
|
1800
|
+
automated: {
|
|
1801
|
+
done: number;
|
|
1802
|
+
of: number;
|
|
1803
|
+
};
|
|
1804
|
+
};
|
|
1805
|
+
/** The one next step: a ready role to hand over first, else the most important gap; null when there is none. */
|
|
1806
|
+
nextStep: BusinessMapNextStep | null;
|
|
1594
1807
|
/** Sources that could not be read just now: a missing helper may simply not have been read. */
|
|
1595
1808
|
unavailable: string[];
|
|
1596
1809
|
}
|
|
@@ -1653,7 +1866,12 @@ export interface BusinessMapRoleDetail {
|
|
|
1653
1866
|
levelLabel: string;
|
|
1654
1867
|
exceptions: string | null;
|
|
1655
1868
|
}>;
|
|
1869
|
+
/** Each responsibility as a process, in the same order. */
|
|
1870
|
+
processes: BusinessMapProcess[];
|
|
1871
|
+
progress: BusinessMapRole['progress'];
|
|
1872
|
+
/** `id` is what a process's `doneBy.helperId` and a proposal's `doneByHelperId` name. */
|
|
1656
1873
|
helpers: Array<{
|
|
1874
|
+
id: number;
|
|
1657
1875
|
kind: BusinessMapHelper['kind'];
|
|
1658
1876
|
ref: string;
|
|
1659
1877
|
label: string;
|
|
@@ -1662,6 +1880,7 @@ export interface BusinessMapRoleDetail {
|
|
|
1662
1880
|
levelLabel: string | null;
|
|
1663
1881
|
exceptions: string | null;
|
|
1664
1882
|
instructionLine: string;
|
|
1883
|
+
look: BusinessMapRole['helpers'][number]['look'];
|
|
1665
1884
|
}>;
|
|
1666
1885
|
}
|
|
1667
1886
|
/**
|
|
@@ -1731,11 +1950,13 @@ export interface BusinessMapDivision {
|
|
|
1731
1950
|
helpers: Array<BusinessMapHelper & {
|
|
1732
1951
|
placedBy: string;
|
|
1733
1952
|
}>;
|
|
1734
|
-
/** The sub-departments. */
|
|
1953
|
+
/** The sub-departments, in the business's order: standardName and custom as on BusinessMapSubDepartment. */
|
|
1735
1954
|
departments: Array<{
|
|
1736
1955
|
no: number;
|
|
1737
1956
|
name: string;
|
|
1738
|
-
|
|
1957
|
+
standardName?: string | null;
|
|
1958
|
+
custom?: boolean;
|
|
1959
|
+
gloss: string | null;
|
|
1739
1960
|
runBy: {
|
|
1740
1961
|
name: string;
|
|
1741
1962
|
byDefault: boolean;
|
|
@@ -1930,6 +2151,19 @@ export interface WriteOptions {
|
|
|
1930
2151
|
/** Set a link by its key ('<id>'), or end it (null). */
|
|
1931
2152
|
links?: Record<string, string | null>;
|
|
1932
2153
|
}
|
|
2154
|
+
/** Which record in another system a record mirrors, for upsertByRef(). */
|
|
2155
|
+
export interface RecordRef {
|
|
2156
|
+
/** That system's name, lower case: letters, digits, `_`, `.` or `-`, at most 40 characters (`xero`, `shopify`). */
|
|
2157
|
+
system: string;
|
|
2158
|
+
/** The record's id in that system, 1 to 200 characters. */
|
|
2159
|
+
externalId: string;
|
|
2160
|
+
}
|
|
2161
|
+
/** What upsertByRef() did. */
|
|
2162
|
+
export interface UpsertByRefResult {
|
|
2163
|
+
id: string;
|
|
2164
|
+
/** True when the record was made; false when the one with that id changed. */
|
|
2165
|
+
created: boolean;
|
|
2166
|
+
}
|
|
1933
2167
|
/** The type of a saved query's or recipe's parameter. */
|
|
1934
2168
|
export type ParamType = 'text' | 'number' | 'date' | 'datetime' | 'boolean' | 'uuid' | 'text_list' | 'number_list';
|
|
1935
2169
|
/** One parameter of a saved query or recipe. */
|
|
@@ -2101,7 +2335,7 @@ export interface Schema {
|
|
|
2101
2335
|
max_limit: number;
|
|
2102
2336
|
statement_timeout_ms: number;
|
|
2103
2337
|
};
|
|
2104
|
-
/** With the account's token: the time zone dates are read in unless a query says otherwise. */
|
|
2338
|
+
/** With the account's token: the time zone dates are read in unless a query says otherwise (the business's own, Sydney if none is set). */
|
|
2105
2339
|
default_timezone?: string;
|
|
2106
2340
|
/** With an app key: whether it can only read or can also write. */
|
|
2107
2341
|
access?: 'read' | 'write';
|
|
@@ -2351,6 +2585,43 @@ export interface ContactTagsResult {
|
|
|
2351
2585
|
/** Tags taken off them. */
|
|
2352
2586
|
removed: number;
|
|
2353
2587
|
}
|
|
2588
|
+
/** One link pointing at a row, from related(). */
|
|
2589
|
+
export interface RelatedRows {
|
|
2590
|
+
/** The kind the link starts from. */
|
|
2591
|
+
kind: string;
|
|
2592
|
+
/** That kind's name as the owner wrote it, plural ("Jobs"): show this beside the label. */
|
|
2593
|
+
kind_label: string;
|
|
2594
|
+
/** The link's key on that kind (its rows carry <link>_id). A company's people come as kind contact, link company. */
|
|
2595
|
+
link: string;
|
|
2596
|
+
/** What the link is called from this side, as its maker named it ("has" when they did not). */
|
|
2597
|
+
label: string;
|
|
2598
|
+
/** True when this link could not be read just now: count and rows are empty, never zero. */
|
|
2599
|
+
unavailable?: boolean;
|
|
2600
|
+
/** Fields and sections of this kind your role cannot see, when any were left out. */
|
|
2601
|
+
not_shown_to_you?: NotShownToYou;
|
|
2602
|
+
/** How many rows point here, up to 10,000 (count_capped past it). */
|
|
2603
|
+
count: number;
|
|
2604
|
+
count_capped: boolean;
|
|
2605
|
+
/** The newest of them, only columns query() would show. */
|
|
2606
|
+
rows: Array<Record<string, unknown>>;
|
|
2607
|
+
/** Pass to query() with where { <link>_id: id } and after, for more. */
|
|
2608
|
+
next: string | null;
|
|
2609
|
+
}
|
|
2610
|
+
/** How a person asked to stop getting email, for contacts.unsubscribe(). */
|
|
2611
|
+
export type ContactStopHow = 'reply' | 'phone' | 'in_person' | 'in_writing' | 'other';
|
|
2612
|
+
/** What contacts.unsubscribe() recorded. */
|
|
2613
|
+
export interface ContactUnsubscribeResult {
|
|
2614
|
+
id: string;
|
|
2615
|
+
/** False when it was already recorded. */
|
|
2616
|
+
changed: boolean;
|
|
2617
|
+
/** Whether email reaches them now. */
|
|
2618
|
+
email_status: ContactEmailStatus;
|
|
2619
|
+
/** The list they left, or null for every email. */
|
|
2620
|
+
list: string | null;
|
|
2621
|
+
how: ContactStopHow;
|
|
2622
|
+
/** When they asked, ISO 8601. */
|
|
2623
|
+
asked_at: string;
|
|
2624
|
+
}
|
|
2354
2625
|
/** The kinds of contact field contacts.createField() makes. */
|
|
2355
2626
|
export type ContactFieldType = 'text' | 'long_text' | 'number' | 'money' | 'date' | 'yes_no' | 'choice' | 'choices';
|
|
2356
2627
|
/** What contacts.createField() takes. */
|
package/dist/index.js
CHANGED
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
* Docs: https://hub.awesomate.ai/docs/sdk/
|
|
27
27
|
*/
|
|
28
28
|
/** This package's version, sent to the hub with every server call. */
|
|
29
|
-
export const VERSION = '0.
|
|
29
|
+
export const VERSION = '0.45.0';
|
|
30
30
|
const DEFAULT_BASE = 'https://hub.awesomate.ai';
|
|
31
31
|
/** Every record and contact id is a UUID; anything else can name no row. */
|
|
32
32
|
const RECORD_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -414,6 +414,7 @@ export class AwesomateClient {
|
|
|
414
414
|
*
|
|
415
415
|
* @example
|
|
416
416
|
* await db.tasks.give({ title: 'Call Sam back about the leak', forEmail: 'jo@brightwater.example', dueAt: '2026-10-06T09:00:00+11:00' });
|
|
417
|
+
* await db.tasks.give({ title: 'Hot lead: Sam wants a quote today', forEmail: 'jo@brightwater.example', urgent: true });
|
|
417
418
|
*/
|
|
418
419
|
tasks = {
|
|
419
420
|
/** The board: waiting now, put off, with someone else, recently decided. `all` shows everyone's, not only yours. hosting:read. */
|
|
@@ -431,15 +432,32 @@ export class AwesomateClient {
|
|
|
431
432
|
* token may not see reads as not found (serverCode `gone`). hosting:read.
|
|
432
433
|
*/
|
|
433
434
|
decisionRecord: (taskId) => this.tasksCall('GET', `/api/my-tasks/decisions/${encodeURIComponent(String(taskId))}/record`),
|
|
434
|
-
/**
|
|
435
|
+
/**
|
|
436
|
+
* Give a task. The person gets it on their board, an email when they are not the one giving it,
|
|
437
|
+
* and a card in any chat they linked, within their quiet hours and daily limit (`urgent` goes
|
|
438
|
+
* straight away). `urgent` in the result says whether it went as urgent: a person's sixth urgent
|
|
439
|
+
* task in a day goes as an ordinary one, and `note` says so. hosting:manage.
|
|
440
|
+
*/
|
|
435
441
|
give: async (task) => {
|
|
436
442
|
const r = await this.tasksCall('POST', '/api/my-tasks/tasks', task);
|
|
437
|
-
return { key: r.key, id: r.id, holder: r.holder, emailed: r.emailed };
|
|
443
|
+
return { key: r.key, id: r.id, holder: r.holder, emailed: r.emailed, urgent: r.urgent === true, ...(r.note ? { note: r.note } : {}) };
|
|
438
444
|
},
|
|
439
|
-
/**
|
|
445
|
+
/**
|
|
446
|
+
* Change a given task: whoever wrote it, or the owner. `urgent: false` takes urgent off; a task can
|
|
447
|
+
* only be marked urgent when it is given. hosting:manage.
|
|
448
|
+
*/
|
|
440
449
|
update: async (id, patch) => {
|
|
441
450
|
await this.tasksCall('PATCH', `/api/my-tasks/tasks/${encodeURIComponent(String(id))}`, patch);
|
|
442
451
|
},
|
|
452
|
+
/**
|
|
453
|
+
* Take a role's task (a card with `role.mayTake`): it becomes the owner's, and everyone else in
|
|
454
|
+
* the role sees who took it. Only someone in the role can take it, so this works for the owner
|
|
455
|
+
* only when they are in that role (serverCode `not_in_role` otherwise). Someone who got there
|
|
456
|
+
* first answers `taken`, with their name in the message. hosting:manage.
|
|
457
|
+
*/
|
|
458
|
+
take: async (id) => {
|
|
459
|
+
await this.tasksCall('POST', `/api/my-tasks/tasks/${encodeURIComponent(String(id))}/take`);
|
|
460
|
+
},
|
|
443
461
|
/** Mark a given task done: the person who has it, whoever wrote it, or the owner. hosting:manage. */
|
|
444
462
|
done: async (id) => {
|
|
445
463
|
await this.tasksCall('POST', `/api/my-tasks/tasks/${encodeURIComponent(String(id))}/done`);
|
|
@@ -786,6 +804,20 @@ export class AwesomateClient {
|
|
|
786
804
|
addTags: async (id, tags) => this.contactsWrite('POST', `/${contactIdOf(id)}/tags`, { add: tags }),
|
|
787
805
|
/** Take tags off a person, up to 20 a call. Answers how many they had. */
|
|
788
806
|
removeTags: async (id, tags) => this.contactsWrite('POST', `/${contactIdOf(id)}/tags`, { remove: tags }),
|
|
807
|
+
/**
|
|
808
|
+
* Record that the person asked to stop getting email, by reply, phone, in person or in writing
|
|
809
|
+
* (`how`), at the time they asked (`askedAt`, default now, at most 30 days back). With no `list`
|
|
810
|
+
* it stops every email, booking confirmations and other service emails included; with a list's
|
|
811
|
+
* key, that list only. Recorded as the person's own withdrawal, so a later import never puts
|
|
812
|
+
* them back. Answers `changed: false` when it was already recorded. The law gives 5 business
|
|
813
|
+
* days from when they asked. A person with no email address is refused (validation).
|
|
814
|
+
*/
|
|
815
|
+
unsubscribe: async (id, options) => {
|
|
816
|
+
const askedAt = options.askedAt instanceof Date ? options.askedAt.toISOString() : options.askedAt;
|
|
817
|
+
return this.contactsWrite('POST', `/${contactIdOf(id)}/unsubscribe`, {
|
|
818
|
+
how: options.how, ...(options.list !== undefined ? { list: options.list } : {}), ...(askedAt !== undefined ? { asked_at: askedAt } : {}),
|
|
819
|
+
});
|
|
820
|
+
},
|
|
789
821
|
/**
|
|
790
822
|
* Add a contact field. The hub makes its key from the label with a random part and answers it:
|
|
791
823
|
* use that key. Nothing here changes a field that exists. `ai_may_read` decides, once and now,
|
|
@@ -1010,6 +1042,22 @@ export class AwesomateClient {
|
|
|
1010
1042
|
throw err;
|
|
1011
1043
|
}
|
|
1012
1044
|
}
|
|
1045
|
+
/**
|
|
1046
|
+
* What points at one row: for each link from another kind (a job's customer, a memo's job), how
|
|
1047
|
+
* many rows point here and the newest of them (`limit`, default 20, at most 100), read as query()
|
|
1048
|
+
* reads that kind. Null when there is no such row. The account's token, crm:read.
|
|
1049
|
+
*
|
|
1050
|
+
* @example
|
|
1051
|
+
* const related = await db.related('contact', contactId);
|
|
1052
|
+
* for (const r of related ?? []) console.log(r.kind, r.link, r.count);
|
|
1053
|
+
*/
|
|
1054
|
+
async related(kind, id, options = {}) {
|
|
1055
|
+
if (!RECORD_ID.test(String(id)))
|
|
1056
|
+
return null;
|
|
1057
|
+
const qs = options.limit ? `?limit=${options.limit}` : '';
|
|
1058
|
+
const r = await nullIfMissing(this.request('GET', `/api/my-crm/v1/rows/${encodeURIComponent(kind)}/${encodeURIComponent(String(id))}/related${qs}`));
|
|
1059
|
+
return r ? r.related : null;
|
|
1060
|
+
}
|
|
1013
1061
|
/** The app kinds this account has defined. The account's token, crm:read, every plan; never an app key. */
|
|
1014
1062
|
async kinds() {
|
|
1015
1063
|
return (await this.request('GET', '/api/my-crm/v1/kinds')).kinds;
|
|
@@ -1087,6 +1135,25 @@ export class AwesomateClient {
|
|
|
1087
1135
|
async archive(kind, id) {
|
|
1088
1136
|
await this.request('POST', '/api/my-crm/v1/call', { fn: 'archive_record', args: { kind, id } }, false);
|
|
1089
1137
|
}
|
|
1138
|
+
/**
|
|
1139
|
+
* Create or change the record that mirrors one in another system, found by that system's name and
|
|
1140
|
+
* its id there (`ref.system`, lower case like `xero`; `ref.externalId`), so a sync run twice changes
|
|
1141
|
+
* the record instead of making a second one. The same checks as write(). A record with that id that
|
|
1142
|
+
* was archived is refused (`conflict`): a sync never undoes an archive or makes a second copy. Companies
|
|
1143
|
+
* are refused here: use companies.upsert(), which matches by ABN and name. The account's token only
|
|
1144
|
+
* (never an app key), crm:write, Support Plus and above.
|
|
1145
|
+
*
|
|
1146
|
+
* @example
|
|
1147
|
+
* const { id, created } = await db.upsertByRef('job', { system: 'servicem8', externalId: 'JOB-0042' }, { title: 'Possum in the roof' }, { links: { customer: contactId } });
|
|
1148
|
+
*/
|
|
1149
|
+
async upsertByRef(kind, ref, data = {}, options = {}) {
|
|
1150
|
+
if (this.appKey)
|
|
1151
|
+
throw new AwesomateError('forbidden', "upsertByRef needs the account's token (amt_pat_...). An app key writes records with write().", 0);
|
|
1152
|
+
const r = await this.request('POST', `/api/my-crm/v1/records/${encodeURIComponent(kind)}/by-ref`, {
|
|
1153
|
+
system: ref.system, external_id: ref.externalId, data, links: options.links ?? {},
|
|
1154
|
+
}, false);
|
|
1155
|
+
return r.result;
|
|
1156
|
+
}
|
|
1090
1157
|
/** The saved queries on this account. crm:read, every plan: the account's token or an app key. */
|
|
1091
1158
|
async queries() {
|
|
1092
1159
|
return (await this.request('GET', '/api/my-crm/v1/queries')).queries;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@awesomate/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.45.0",
|
|
4
4
|
"description": "Your own Awesomate data from Node and the browser: query contacts and app data with generated types, and sign your app's own users in",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|