@awesomate/sdk 0.7.0 → 0.9.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/README.md CHANGED
@@ -146,6 +146,36 @@ and takes a fresh copy when it does. Up to 200 rows a list and 20 lists a connec
146
146
  `{ onRows, onError }` to hear about a list the server refused (a column that does not exist).
147
147
  Outside a browser, give it a WebSocket: `createAppClient({ publishableKey, WebSocket })`.
148
148
 
149
+ ### Staff find a customer
150
+
151
+ People in an app read no contacts but their own, so by default staff cannot put a job under a
152
+ customer. Switch it on per app for the roles that need it (`awesomate_crm_apps`,
153
+ `customer_lookup`, never the role customers sign in with). Those roles can then search by name or
154
+ email and point a record at any customer:
155
+
156
+ ```ts
157
+ const [jo] = await app.lookupCustomers({ q: 'jo' }); // or { ids: [...] }, up to 50
158
+ await app.write('job', { title: 'Gutters' }, { links: { customer: jo.id } });
159
+ ```
160
+
161
+ Name, email and phone only, and nothing the owner marked sensitive. Anyone else is refused.
162
+
163
+ An attribute can also be visible to some roles only (`awesomate_crm_kinds`, `set_visibility`, for
164
+ example a cost only `staff` see). For everyone else it comes back `null` and a write that sets it
165
+ is refused, whatever the app asks for.
166
+
167
+ Some things a customer should do without being able to edit the record: accept their quote, say.
168
+ Save it as a write recipe and open it to their role (`awesomate_crm_recipes`, `run_by`, Pro and
169
+ above), then:
170
+
171
+ ```ts
172
+ await app.call('accept_quote', { job: job.id });
173
+ ```
174
+
175
+ The database lets them do exactly the recipe's steps: only its params take their values, every
176
+ other value is fixed, and an existing record must be one they can already read. A recipe not
177
+ opened to their role is "not found".
178
+
149
179
  The rules are kept in your own database, which applies them to every read and write, so a mistake
150
180
  in the app cannot show anyone more than their role allows. A disabled person is refused on their
151
181
  next call. Sessions are kept in `localStorage`; in a Capacitor app pass `storage` (Preferences) and
package/dist/index.d.ts CHANGED
@@ -370,6 +370,13 @@ export interface AppUser {
370
370
  role: string;
371
371
  contact_id: string | null;
372
372
  }
373
+ /** A customer as lookupCustomers() returns them. A field the owner marked sensitive is null. */
374
+ export interface Customer {
375
+ id: string;
376
+ name: string | null;
377
+ email: string | null;
378
+ phone: string | null;
379
+ }
373
380
  export interface AppClientOptions {
374
381
  /** The app's publishable key (pk_...). Not a secret: it belongs in browser code. */
375
382
  publishableKey: string;
@@ -485,6 +492,23 @@ export declare class AwesomateAppClient {
485
492
  /** Create a record (returns its id) or change one with options.id, inside the kind's write rule for this user. */
486
493
  write<K extends KindName>(kind: K, data: Partial<RowOf<K>> | Record<string, unknown>, options?: WriteOptions): Promise<string>;
487
494
  archive<K extends KindName>(kind: K, id: string): Promise<void>;
495
+ /**
496
+ * Run a recipe the account opened to this person's role: "accept this quote", something their
497
+ * write rule would not let them do by hand. Every step commits or none does; a recipe they may
498
+ * not run reads as not found. Never retried once sent: a write that may have landed is not safe
499
+ * to send twice (a refused sign-in is, and is retried after a refresh like every data call).
500
+ */
501
+ call<R extends RecipeName>(recipe: R, args?: ArgsOf<R>): Promise<RecipeResult>;
502
+ /**
503
+ * Customers by name or email (two characters or more), or by id, so staff can find one and put
504
+ * a record under them. Only for a role the account lets look customers up in this app; anyone
505
+ * else gets a forbidden error. Name, email and phone only, at most 50.
506
+ */
507
+ lookupCustomers(options: {
508
+ q?: string;
509
+ ids?: string[];
510
+ limit?: number;
511
+ }): Promise<Customer[]>;
488
512
  /**
489
513
  * A list kept current: onRows gets the whole list (up to 200 rows, the query's order) at first
490
514
  * and again whenever a row in it is added, changed, removed, or stops being one this person may
package/dist/index.js CHANGED
@@ -514,6 +514,23 @@ export class AwesomateAppClient {
514
514
  async archive(kind, id) {
515
515
  await this.data('POST', '/call', { fn: 'archive_record', args: { kind, id } });
516
516
  }
517
+ /**
518
+ * Run a recipe the account opened to this person's role: "accept this quote", something their
519
+ * write rule would not let them do by hand. Every step commits or none does; a recipe they may
520
+ * not run reads as not found. Never retried once sent: a write that may have landed is not safe
521
+ * to send twice (a refused sign-in is, and is retried after a refresh like every data call).
522
+ */
523
+ async call(recipe, args = {}) {
524
+ return (await this.data('POST', '/call', { fn: recipe, args })).result;
525
+ }
526
+ /**
527
+ * Customers by name or email (two characters or more), or by id, so staff can find one and put
528
+ * a record under them. Only for a role the account lets look customers up in this app; anyone
529
+ * else gets a forbidden error. Name, email and phone only, at most 50.
530
+ */
531
+ async lookupCustomers(options) {
532
+ return (await this.data('POST', '/customers/lookup', options)).customers;
533
+ }
517
534
  /**
518
535
  * A list kept current: onRows gets the whole list (up to 200 rows, the query's order) at first
519
536
  * and again whenever a row in it is added, changed, removed, or stops being one this person may
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@awesomate/sdk",
3
- "version": "0.7.0",
3
+ "version": "0.9.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",