@hailer/app-sdk 2.8.0 → 2.13.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.
@@ -15,6 +15,7 @@ import { Payment } from './modules/payment';
15
15
  import { Admin } from './modules/admin';
16
16
  import { MetricsApi } from './modules/metrics';
17
17
  import { HttpApi } from './modules/http';
18
+ import { CredentialApi } from './modules/credential';
18
19
  export interface Options {
19
20
  /** When connected is called the host is ready to receive calls */
20
21
  connected?: () => void;
@@ -52,6 +53,8 @@ export declare class HailerApi {
52
53
  metrics: MetricsApi;
53
54
  /** HTTP proxy for making authenticated HTTP/WebSocket requests through the parent frame */
54
55
  http: HttpApi;
56
+ /** Securely store and retrieve credentials (API keys, username/password pairs, etc.) */
57
+ credential: CredentialApi;
55
58
  /** All public endpoints, which can be accessed while not logged in to Hailer. */
56
59
  public: HailerPublicApi;
57
60
  /** User interface commands */
@@ -1,5 +1,5 @@
1
1
  import { Client } from '@wishcore/wish-rpc';
2
- import { ActivityCreateOptions, ActivityListOptions, Activity, ActivityFieldUpdateValue, ActivityUpdateOptions, ActivityFieldValue, PrintRequest, PrintResponse } from '../types';
2
+ import { ActivityCreateOptions, ActivityListOptions, Activity, ActivityFieldUpdateValue, ActivityUpdateOptions, ActivityFieldValue, PrintRequest, PrintOptions, PrintResponse } from '../types';
3
3
  import { Kanban } from './activity/kanban';
4
4
  import { Ball } from './activity/ball';
5
5
  export declare class ActivityApi {
@@ -76,10 +76,12 @@ export declare class ActivityApi {
76
76
  * @param requests[].templateId Template ID for regular templates
77
77
  * @param requests[].templateName Template name for multi-pdf templates (when templateId is empty)
78
78
  * @param requests[].savePdf Whether to save the generated PDF
79
+ * @param options.openNative Also open the document in the device's own viewer where the host supports it
80
+ * (the Hailer Android app); see `openedNatively` in the response
79
81
  *
80
82
  * @returns PDF data with filename, base64 data, and mimeType
81
83
  *
82
84
  * @throws {HailerError} if request is incorrect
83
85
  */
84
- print(requests: PrintRequest[]): Promise<PrintResponse>;
86
+ print(requests: PrintRequest[], options?: PrintOptions): Promise<PrintResponse>;
85
87
  }
@@ -0,0 +1,48 @@
1
+ import { Client } from '@wishcore/wish-rpc';
2
+ import { CredentialCreateResponse, CredentialData, CredentialDetails, CredentialListItem, CredentialType, CredentialUpdate } from '../types';
3
+ /**
4
+ * Securely store and retrieve credentials — API keys, username/password pairs,
5
+ * or any custom key-value secret.
6
+ *
7
+ * Every operation is scoped to credentials bound to your app: the host tags each
8
+ * credential you create with your app's id and re-checks that tag on every read
9
+ * and write, so you can never reach another app's credentials. Credentials
10
+ * created through the SDK are always **personal** — visible only to the acting
11
+ * user — and cannot be deleted through the SDK.
12
+ *
13
+ * A workspace app additionally sees, in `list`, the workspace credentials tagged
14
+ * with it that the acting user may read, and can `get` them; those cannot be
15
+ * modified through the SDK.
16
+ *
17
+ * `credential.get` returns the decrypted payload directly — there is no token
18
+ * exchange.
19
+ */
20
+ export declare class CredentialApi {
21
+ private client;
22
+ constructor(client: Client);
23
+ /**
24
+ * Store a new encrypted credential. The credential is personal (owner-only)
25
+ * and is automatically bound to your app — the host forces the app
26
+ * association and drops any workspace or reader association.
27
+ *
28
+ * @throws {HailerError} if the request fails or the caller lacks permission
29
+ */
30
+ create(name: string, type: CredentialType, secret: CredentialData): Promise<CredentialCreateResponse>;
31
+ /**
32
+ * List your app's credentials. Encrypted fields are never returned. Results
33
+ * are always scoped to credentials bound to your app.
34
+ */
35
+ list(): Promise<CredentialListItem[]>;
36
+ /**
37
+ * Fetch and decrypt one of your app's credentials. The plaintext payload is
38
+ * returned directly in the RPC response — no token exchange.
39
+ */
40
+ get<T extends CredentialData = CredentialData>(credentialId: string): Promise<CredentialDetails<T>>;
41
+ /**
42
+ * Rename or rotate the secret of one of your app's personal credentials. At
43
+ * least one field must be provided in `updates`, and `secret` replaces the
44
+ * entire stored payload — there is no key-level merge. Workspace
45
+ * credentials cannot be updated through the SDK.
46
+ */
47
+ update(credentialId: string, updates: CredentialUpdate): Promise<boolean>;
48
+ }
@@ -1,5 +1,5 @@
1
1
  import { Client } from '@wishcore/wish-rpc';
2
- import { InsightData, InsightDoc } from '../types';
2
+ import { InsightData, InsightDoc, InsightQueryResult, InsightSource } from '../types';
3
3
  export declare class InsightApi {
4
4
  private client;
5
5
  constructor(client: Client);
@@ -32,4 +32,16 @@ export declare class InsightApi {
32
32
  * @throws {HailerError} if request is incorrect
33
33
  */
34
34
  update(insightId: string, update: Partial<InsightDoc>): Promise<InsightDoc[]>;
35
+ /**
36
+ * Run an ad-hoc query against Insight sources
37
+ *
38
+ * @param workspaceId the workspace to query within
39
+ * @param sources the Insight sources to query
40
+ * @param query the query string
41
+ *
42
+ * @returns query result with headers, rows, and details
43
+ *
44
+ * @throws {HailerError} if request is incorrect
45
+ */
46
+ query(workspaceId: string, sources: InsightSource[], query: string): Promise<InsightQueryResult>;
35
47
  }
@@ -8,26 +8,22 @@ export interface MetricDefinition {
8
8
  supportsBreakdown: boolean;
9
9
  }
10
10
  export interface MetricData {
11
- metricType: string;
12
- timestamp: number;
13
- current: {
14
- value: number;
15
- labels?: any;
16
- };
11
+ /** Current scalar value (when not grouped into a series) */
12
+ value?: number;
13
+ /** Labels attached to the value */
14
+ labels?: Record<string, string>;
15
+ /** One series per group, each a list of { timestamp, value } */
17
16
  timeSeries?: Array<{
18
- timestamp: number;
19
- value: number;
17
+ labels: Record<string, string>;
18
+ values: Array<{
19
+ timestamp: number;
20
+ value: number;
21
+ }>;
20
22
  }>;
21
- breakdown?: {
22
- byWorkspace?: Record<string, number>;
23
- byUser?: Record<string, number>;
24
- };
25
- metadata: {
26
- scope?: any;
27
- permissions?: any;
28
- source: string;
29
- executionTime?: number;
30
- };
23
+ /** Set if this metric failed */
24
+ error?: boolean;
25
+ /** Failure detail */
26
+ errorMessage?: string;
31
27
  }
32
28
  export interface MetricOptions {
33
29
  workspaceId?: string;
@@ -39,17 +35,13 @@ export interface MetricOptions {
39
35
  interval?: '1m' | '5m' | '15m' | '30m' | '1h' | '5h';
40
36
  /** Aggregation function to apply */
41
37
  aggregation?: 'sum' | 'avg' | 'max' | 'min' | 'count' | 'rate' | 'increase';
42
- /** Group results by specified labels (max 3). Allowed: userId, userRole, workspaceId, teamId, processId, workflowId, discussionId */
38
+ /** Group results by specified labels (max 3). Allowed: userId, userRole, workspaceId, teamId, processId, workflowId, discussionId, activityId, signal, type */
43
39
  groupBy?: string[];
44
40
  /** Limit results to top N values (1-100) */
45
41
  topk?: number;
46
- /** Additional label filters. Allowed keys: userId, userRole, workspaceId, teamId, processId, workflowId, discussionId */
42
+ /** Additional label filters. Allowed keys: userId, userRole, workspaceId, teamId, processId, workflowId, discussionId, activityId, signal, type */
47
43
  labelFilters?: Record<string, string>;
48
44
  }
49
- export interface MetricListOptions {
50
- category?: string;
51
- includeDetails?: boolean;
52
- }
53
45
  export interface WorkspaceMetricsListOptions {
54
46
  /** Array of workspace IDs to look up */
55
47
  workspaceIds?: string[];
@@ -74,15 +66,14 @@ export declare class MetricsApi {
74
66
  constructor(client: Client);
75
67
  /**
76
68
  * Get list of available metrics for current user based on permissions
77
- * @param options Optional filtering options
78
69
  * @returns Array of metric IDs or detailed metric definitions
79
70
  */
80
- list(options?: MetricListOptions): Promise<string[] | MetricDefinition[]>;
71
+ list(): Promise<string[] | MetricDefinition[]>;
81
72
  /**
82
73
  * Get metrics data with optional Query Builder
83
74
  * @param metricTypes Single metric or array of metrics to fetch
84
75
  * @param options Optional filtering, time range, and Query Builder options
85
- * @returns Metric data with values and optional time series
76
+ * @returns Array of metric data, one entry per requested metric (in request order)
86
77
  *
87
78
  * @example
88
79
  * // Simple query
@@ -98,7 +89,7 @@ export declare class MetricsApi {
98
89
  * topk: 10
99
90
  * });
100
91
  */
101
- get(metricTypes: string | string[], options?: MetricOptions): Promise<MetricData>;
92
+ get(metricTypes: string | string[], options?: MetricOptions): Promise<MetricData[]>;
102
93
  /**
103
94
  * Admin endpoints for metrics management
104
95
  */
package/lib/types.d.ts CHANGED
@@ -295,6 +295,18 @@ export interface InsightResponseAsObjectItem {
295
295
  [key: string]: any;
296
296
  }
297
297
  export type InsightResponseAsObjects = InsightResponseAsObjectItem[];
298
+ export type InsightSource = InsightWorkflowSource;
299
+ export interface InsightQueryResult {
300
+ headers: string[];
301
+ rows: (string | number | null)[][];
302
+ /** Per-table breakdown of the temporary tables built from sources */
303
+ details: {
304
+ [tableName: string]: {
305
+ headers: string[];
306
+ rows: number;
307
+ };
308
+ };
309
+ }
298
310
  export interface KanbanListResponse {
299
311
  map: {
300
312
  [phaseId: string]: {
@@ -416,16 +428,84 @@ export interface PrintRequest {
416
428
  /** Whether to save the PDF to the file system */
417
429
  savePdf?: boolean;
418
430
  }
431
+ export interface PrintOptions {
432
+ /**
433
+ * Open the generated document in the device's own viewer, where the host supports it.
434
+ * Currently only the Hailer Android app does: the document is saved to Downloads and opened
435
+ * in the system PDF viewer, where the user can print or share it. Elsewhere the document is
436
+ * only returned, as without this option; check `openedNatively` in the response.
437
+ */
438
+ openNative?: boolean;
439
+ }
419
440
  export interface PrintResponse {
420
441
  filename: string;
421
442
  /** Base64-encoded document data */
422
443
  data: string;
423
444
  mimeType: string;
445
+ /**
446
+ * Only set when `openNative` was requested: `true` if the host handed the document to the
447
+ * device's own viewer, `false` if it couldn't (web, iOS). Older Hailer versions leave it unset,
448
+ * so treat anything but `true` as "not opened".
449
+ */
450
+ openedNatively?: boolean;
424
451
  }
425
452
  export interface Settings {
426
453
  theme: 'light' | 'dark';
427
454
  preferredLanguages: string[];
428
455
  }
456
+ export type CredentialType = 'basic' | 'apiKey' | 'custom';
457
+ export interface CredentialBasicData {
458
+ username: string;
459
+ password: string;
460
+ }
461
+ export interface CredentialApiKeyData {
462
+ apiKey: string;
463
+ }
464
+ /** Any JSON-serialisable value that can live inside a `custom` secret. */
465
+ export type CredentialJsonValue = string | number | boolean | null | CredentialJsonValue[] | {
466
+ [key: string]: CredentialJsonValue;
467
+ };
468
+ /**
469
+ * Free-form secret for `custom` credentials — any JSON object with 1–50
470
+ * top-level keys.
471
+ */
472
+ export interface CredentialCustomData {
473
+ [key: string]: CredentialJsonValue;
474
+ }
475
+ export type CredentialData = CredentialBasicData | CredentialApiKeyData | CredentialCustomData;
476
+ /**
477
+ * Reader entry granting access to a workspace credential. Credentials created
478
+ * through the app SDK are personal and have no readers; readers only appear on
479
+ * workspace credentials bound to your app and surfaced in `list`.
480
+ */
481
+ export type CredentialReader = `network_${string}` | `team_${string}` | `user_${string}`;
482
+ export interface CredentialCreateResponse {
483
+ _id: string;
484
+ }
485
+ export interface CredentialListItem {
486
+ _id: string;
487
+ name: string;
488
+ type: CredentialType;
489
+ /** Set only on workspace credentials — absent on personal ones. */
490
+ workspaceId?: string;
491
+ /** The app the credential is bound to; always your own app's id. */
492
+ appId?: string;
493
+ /** Workspace credentials only. */
494
+ readers?: CredentialReader[];
495
+ createdBy: string;
496
+ created: number;
497
+ updated: number;
498
+ }
499
+ export interface CredentialUpdate {
500
+ name?: string;
501
+ /** Replaces the entire stored payload — there is no key-level merge. */
502
+ secret?: CredentialData;
503
+ }
504
+ /** Decrypted credential as returned by `credential.get`. */
505
+ export interface CredentialDetails<T extends CredentialData = CredentialData> {
506
+ type: CredentialType;
507
+ secret: T;
508
+ }
429
509
  export interface ApiInfo {
430
510
  /** Url of the Hailer instance hosting the API */
431
511
  hostUrl?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hailer/app-sdk",
3
- "version": "2.8.0",
3
+ "version": "2.13.0",
4
4
  "description": "SDK for building Hailer Apps",
5
5
  "author": "",
6
6
  "license": "ISC",