@magemetrics/core 0.1.4 → 0.1.6

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 CHANGED
@@ -1,5 +1,6 @@
1
1
  import { Client } from 'openapi-fetch';
2
2
  import { DefaultChatTransport } from 'ai';
3
+ import { GoTrueClientOptions } from '@supabase/auth-js';
3
4
  import { HttpChatTransportInitOptions } from 'ai';
4
5
  import type { InferUITool } from 'ai';
5
6
  import type { Simplify } from 'type-fest';
@@ -78,6 +79,11 @@ export declare class BrowserStorageAdapter implements AsyncStorage {
78
79
 
79
80
  export declare const CHECK_KEY = "mm-ai-check-key";
80
81
 
82
+ export declare interface ColumnSort {
83
+ desc: boolean;
84
+ id: string;
85
+ }
86
+
81
87
  declare interface components {
82
88
  schemas: {
83
89
  VisualizationData: {
@@ -508,7 +514,15 @@ export declare class MageMetricsClient {
508
514
  private userId;
509
515
  private storageAdapter;
510
516
  private events;
511
- constructor(config: MageMetricsClientConfig);
517
+ private authOptions;
518
+ constructor(config: MageMetricsClientConfig, auth?: Pick<GoTrueClientOptions, "fetch">);
519
+ toJSON(): {
520
+ config: string;
521
+ };
522
+ get apiConfig(): {
523
+ apiUrl: string;
524
+ apiKey: string;
525
+ };
512
526
  /**
513
527
  * Add an event listener for authentication state changes
514
528
  * @param type the type of the event
@@ -528,9 +542,13 @@ export declare class MageMetricsClient {
528
542
  waitForAuth(): Promise<void>;
529
543
  updateExternalJwt(jwt: string): Promise<void>;
530
544
  get state(): AuthState;
531
- getAuthHeaders(): Promise<Record<string, string>>;
545
+ getHeaders(): Promise<Record<string, string>>;
532
546
  private clearStorage;
533
547
  logout(): Promise<void>;
548
+ auth: {
549
+ startAutoRefresh: () => Promise<void> | undefined;
550
+ stopAuthRefresh: () => Promise<void> | undefined;
551
+ };
534
552
  /**
535
553
  * Public API methods that automatically wait for authentication
536
554
  */
@@ -547,7 +565,22 @@ export declare class MageMetricsClient {
547
565
  data: Blob | string;
548
566
  }>;
549
567
  generateContextualInsight: (payload: GenerateInsightParam) => Promise<ExtractInsightResponse>;
550
- getChat: (flowId: string, options?: MageMetricsChatTransportOptions) => MageMetricsChatTransport;
568
+ getChatTransport: (flowId: string, options?: MageMetricsChatTransportOptions) => MageMetricsChatTransport;
569
+ getChatMessages: (flowId: string) => Promise<MMChatUIMessage[]>;
570
+ fetchReportData: (reportId: number, { columns, limit, sorting, filters, cursor }: ReportDataFilters) => Promise<Record<string, unknown>[]>;
571
+ getReport: (reportId: number) => Promise<{
572
+ columns: {
573
+ name: string;
574
+ data_type: string;
575
+ dataType: string;
576
+ renderType?: string;
577
+ unit?: string;
578
+ }[];
579
+ rowCount: {
580
+ count: number;
581
+ };
582
+ data: (reportId: number, { columns, limit, sorting, filters, cursor }: ReportDataFilters) => Promise<Record<string, unknown>[]>;
583
+ }>;
551
584
  };
552
585
  /**
553
586
  * Perform the complete authentication flow
@@ -624,7 +657,7 @@ export declare class MemoryStorageAdapter implements AsyncStorage {
624
657
  removeItem(key: string): Promise<void>;
625
658
  }
626
659
 
627
- declare type MMChatUIMessage = UIMessage<unknown, CustomDataParts, MMUiTools>;
660
+ export declare type MMChatUIMessage = UIMessage<unknown, CustomDataParts, MMUiTools>;
628
661
 
629
662
  declare type MMUiTools = {
630
663
  generateDataReport: UiTool;
@@ -4152,6 +4185,14 @@ declare type RemoveParamsConfig = Simplify<{
4152
4185
  cookie?: string;
4153
4186
  }>;
4154
4187
 
4188
+ declare type ReportDataFilters = {
4189
+ columns?: string[];
4190
+ limit: number;
4191
+ sorting: SortingState;
4192
+ filters: TableFilters;
4193
+ cursor?: number;
4194
+ };
4195
+
4155
4196
  declare const SignalWithReportIdSchema: z.ZodObject<{
4156
4197
  rule: z.ZodString;
4157
4198
  metric: z.ZodString;
@@ -4173,6 +4214,10 @@ declare const SignalWithReportIdSchema: z.ZodObject<{
4173
4214
  reportId: number;
4174
4215
  }>;
4175
4216
 
4217
+ declare type SortingState = ColumnSort[];
4218
+
4219
+ declare type TableFilters = Record<string, string | number>;
4220
+
4176
4221
  /**
4177
4222
  * Token storage keys
4178
4223
  */
package/dist/index.js CHANGED
@@ -305,10 +305,6 @@ var Edge = z.object({
305
305
  source: z.string(),
306
306
  target: z.string()
307
307
  });
308
- z.object({
309
- score: z.number(),
310
- reason: z.string()
311
- });
312
308
  var LLMColumnsLineageResponse = z.record(z.string(), z.object({
313
309
  nodes: z.array(Node3),
314
310
  edges: z.array(Edge)
@@ -995,7 +991,7 @@ var RetrieveRecentFlows = createRoute({
995
991
  }
996
992
  }
997
993
  });
998
- createRoute({
994
+ var GetReportColumns = createRoute({
999
995
  method: "get",
1000
996
  path: "/api/v1/data-reports/{report_id}/columns",
1001
997
  operationId: "getDataReportColumns",
@@ -1118,7 +1114,7 @@ createRoute({
1118
1114
  }
1119
1115
  }
1120
1116
  });
1121
- createRoute({
1117
+ var GetReportData = createRoute({
1122
1118
  method: "get",
1123
1119
  path: "/api/v1/data-reports/{report_id}/data",
1124
1120
  operationId: "getDataReportData",
@@ -1211,7 +1207,7 @@ createRoute({
1211
1207
  }
1212
1208
  }
1213
1209
  });
1214
- createRoute({
1210
+ var GetReportRowCount = createRoute({
1215
1211
  method: "get",
1216
1212
  path: "/api/v1/data-reports/{report_id}/count",
1217
1213
  operationId: "getDataReportRowCount",
@@ -2367,10 +2363,216 @@ var hashString = (value) => {
2367
2363
  const hash = sha256(data);
2368
2364
  return Array.from(hash).map((b) => b.toString(16).padStart(2, "0")).join("");
2369
2365
  };
2366
+ var QuickActionSchema = z.object({
2367
+ label: z.string(),
2368
+ explanation: z.string()
2369
+ });
2370
+ var QuickActionsSchema = QuickActionSchema.array();
2371
+ var FrontendTimelineItemSchema = z.discriminatedUnion("type", [
2372
+ z.object({
2373
+ type: z.literal("dataReport"),
2374
+ flowDataId: z.number(),
2375
+ flowId: z.string(),
2376
+ title: z.string(),
2377
+ bookmarked: z.boolean(),
2378
+ answer: z.string().nullable()
2379
+ }),
2380
+ z.object({
2381
+ type: z.literal("visualization"),
2382
+ flowId: z.string(),
2383
+ flowDataId: z.number(),
2384
+ flowDataVisualizationId: z.number(),
2385
+ title: z.string(),
2386
+ bookmarked: z.boolean()
2387
+ }),
2388
+ z.object({
2389
+ type: z.literal("message")
2390
+ })
2391
+ ]);
2392
+
2393
+ // ../shared/dist/src/endpoints/companion/chat.routes.js
2394
+ createRoute({
2395
+ hide: true,
2396
+ method: "get",
2397
+ path: "/api/v1/chat/{flowId}/timeline",
2398
+ operationId: "retrieveChatTimeline",
2399
+ request: {
2400
+ headers: SupabaseHeaderSchema,
2401
+ params: FlowIdParam
2402
+ },
2403
+ responses: {
2404
+ 200: {
2405
+ description: "The timeline of generated insights for the flow",
2406
+ content: {
2407
+ "application/json": {
2408
+ schema: FrontendTimelineItemSchema.array()
2409
+ }
2410
+ }
2411
+ },
2412
+ 404: {
2413
+ content: {
2414
+ "application/json": {
2415
+ schema: z.object({ error: z.string() })
2416
+ }
2417
+ },
2418
+ description: "Unable to retrieve flow with this id"
2419
+ },
2420
+ 500: {
2421
+ description: "Something wrong happened",
2422
+ content: {
2423
+ "application/json": {
2424
+ schema: z.object({
2425
+ error: z.string()
2426
+ })
2427
+ }
2428
+ }
2429
+ }
2430
+ }
2431
+ });
2432
+ var ChatMessages = createRoute({
2433
+ method: "get",
2434
+ path: "/api/v1/chat/{flowId}/messages",
2435
+ operationId: "retrieveChatMessages",
2436
+ request: {
2437
+ headers: SupabaseHeaderSchema,
2438
+ params: FlowIdParam
2439
+ },
2440
+ responses: {
2441
+ 200: {
2442
+ description: "The messages from the given flow",
2443
+ content: {
2444
+ "application/json": {
2445
+ // we don't want to have to write a parser for Vercel AI messages
2446
+ schema: z.object({ messages: z.object({}).passthrough().array() })
2447
+ }
2448
+ }
2449
+ },
2450
+ 404: {
2451
+ content: {
2452
+ "application/json": {
2453
+ schema: z.object({ error: z.string() })
2454
+ }
2455
+ },
2456
+ description: "Unable to retrieve flow with this id"
2457
+ },
2458
+ 500: {
2459
+ description: "Something wrong happened",
2460
+ content: {
2461
+ "application/json": {
2462
+ schema: z.object({
2463
+ error: z.string()
2464
+ })
2465
+ }
2466
+ }
2467
+ }
2468
+ }
2469
+ });
2470
+ createRoute({
2471
+ hide: true,
2472
+ method: "post",
2473
+ path: "/api/v1/chat/{flowId}/quick-actions",
2474
+ request: {
2475
+ headers: SupabaseHeaderSchema,
2476
+ params: FlowIdParam,
2477
+ body: {
2478
+ content: {
2479
+ "application/json": {
2480
+ schema: z.object({
2481
+ content: z.string()
2482
+ })
2483
+ }
2484
+ }
2485
+ }
2486
+ },
2487
+ responses: {
2488
+ 200: {
2489
+ description: "The quick actions for the given message",
2490
+ content: {
2491
+ "application/json": {
2492
+ schema: QuickActionsSchema
2493
+ }
2494
+ }
2495
+ },
2496
+ 400: {
2497
+ content: {
2498
+ "application/json": {
2499
+ schema: z.object({ error: z.string() })
2500
+ }
2501
+ },
2502
+ description: "The provided content is invalid"
2503
+ },
2504
+ 404: {
2505
+ content: {
2506
+ "application/json": {
2507
+ schema: z.object({ error: z.string() })
2508
+ }
2509
+ },
2510
+ description: "Unable to retrieve flow with this id"
2511
+ },
2512
+ 500: {
2513
+ description: "Something wrong happened",
2514
+ content: {
2515
+ "application/json": {
2516
+ schema: z.object({
2517
+ error: z.string()
2518
+ })
2519
+ }
2520
+ }
2521
+ }
2522
+ }
2523
+ });
2524
+ var DataTableSchema = z.object({
2525
+ id: z.number(),
2526
+ dataset: z.string(),
2527
+ table_name: z.string(),
2528
+ description: z.string().nullable(),
2529
+ primary_key_names: z.string().array(),
2530
+ row_count: z.number().nullable(),
2531
+ created_at: z.string(),
2532
+ updated_at: z.string(),
2533
+ source_id: z.number(),
2534
+ parent_table_id: z.number().nullable()
2535
+ });
2536
+ var DataTableColumnSchema = z.object({
2537
+ id: z.number(),
2538
+ name: z.string(),
2539
+ data_type: z.string().nullable(),
2540
+ description: z.string().nullable(),
2541
+ null_percentage: z.number().nullable(),
2542
+ unique_values: z.number().nullable(),
2543
+ sample_values: z.array(z.unknown()).nullable()
2544
+ });
2545
+ DataTableSchema.extend({
2546
+ columns: z.array(DataTableColumnSchema)
2547
+ });
2548
+ var toSearchParams = ({ cursor, filters, sorting, limit }) => {
2549
+ const params = {};
2550
+ if (limit !== void 0) {
2551
+ params.limit = limit;
2552
+ }
2553
+ if (cursor !== void 0) {
2554
+ params.cursor = cursor;
2555
+ }
2556
+ const sortingParams = sorting?.map((c) => `${c.id}:${c.desc ? "DESC" : "ASC"}`).join(",");
2557
+ if (sortingParams) {
2558
+ params.order = sortingParams;
2559
+ }
2560
+ if (filters) {
2561
+ const filterParams = Object.entries(filters).flatMap(([key, value]) => {
2562
+ if (!(typeof value === "string" || typeof value === "boolean" || typeof value === "number"))
2563
+ return [];
2564
+ return `${key}:${encodeURIComponent(value)}`;
2565
+ }).join(",");
2566
+ if (filterParams.length > 0) {
2567
+ params.filter = filterParams;
2568
+ }
2569
+ }
2570
+ return params;
2571
+ };
2370
2572
 
2371
2573
  // package.json
2372
2574
  var package_default = {
2373
- version: "0.1.4"};
2575
+ version: "0.1.6"};
2374
2576
  var MageMetricsChatTransport = class extends DefaultChatTransport {
2375
2577
  constructor(apiUrl, flowId, options) {
2376
2578
  super({
@@ -2458,7 +2660,8 @@ var MageMetricsClient = class {
2458
2660
  userId = null;
2459
2661
  storageAdapter;
2460
2662
  events = new MageMetricsEventEmitter();
2461
- constructor(config) {
2663
+ authOptions;
2664
+ constructor(config, auth) {
2462
2665
  this.config = config;
2463
2666
  this.storageAdapter = config.storageAdapter || createStorageAdapter();
2464
2667
  this.internalApiClient = createApiClient({
@@ -2466,7 +2669,18 @@ var MageMetricsClient = class {
2466
2669
  });
2467
2670
  this.internalApiClient.use(throwOnError);
2468
2671
  this.internalApiClient.use(this.createSupabaseHeaderMiddleware());
2469
- this.internalApiClient.use(addVersionHeader(MM_CLIENT_VERSION));
2672
+ this.authOptions = auth || {};
2673
+ }
2674
+ toJSON() {
2675
+ return {
2676
+ config: this.encodeCheckKey(this.config.apiKey, this.config.apiUrl)
2677
+ };
2678
+ }
2679
+ get apiConfig() {
2680
+ return {
2681
+ apiUrl: this.config.apiUrl,
2682
+ apiKey: this.config.apiKey
2683
+ };
2470
2684
  }
2471
2685
  /**
2472
2686
  * Add an event listener for authentication state changes
@@ -2507,7 +2721,7 @@ var MageMetricsClient = class {
2507
2721
  get state() {
2508
2722
  return this.authState;
2509
2723
  }
2510
- async getAuthHeaders() {
2724
+ async getHeaders() {
2511
2725
  await this.waitForAuth();
2512
2726
  if (!this.supabaseClient) {
2513
2727
  return {};
@@ -2518,6 +2732,7 @@ var MageMetricsClient = class {
2518
2732
  }
2519
2733
  const { access_token } = session.data.session;
2520
2734
  return {
2735
+ [HEADER_CLIENT_VERSION]: MM_CLIENT_VERSION,
2521
2736
  "sp-access-token": access_token
2522
2737
  };
2523
2738
  }
@@ -2534,6 +2749,10 @@ var MageMetricsClient = class {
2534
2749
  }
2535
2750
  await this.clearStorage();
2536
2751
  }
2752
+ auth = {
2753
+ startAutoRefresh: () => this.supabaseClient?.startAutoRefresh(),
2754
+ stopAuthRefresh: () => this.supabaseClient?.startAutoRefresh()
2755
+ };
2537
2756
  /**
2538
2757
  * Public API methods that automatically wait for authentication
2539
2758
  */
@@ -2674,19 +2893,102 @@ var MageMetricsClient = class {
2674
2893
  }
2675
2894
  return data;
2676
2895
  },
2677
- getChat: (flowId, options) => {
2896
+ getChatTransport: (flowId, options) => {
2678
2897
  return new MageMetricsChatTransport(this.config.apiUrl, flowId, {
2679
2898
  ...options,
2680
2899
  headers: async () => {
2681
- const authHeaders = await this.getAuthHeaders();
2900
+ const authHeaders = await this.getHeaders();
2682
2901
  const headers = await resolve(options?.headers);
2683
2902
  return {
2684
2903
  ...headers,
2685
- ...authHeaders,
2686
- [HEADER_CLIENT_VERSION]: MM_CLIENT_VERSION
2904
+ ...authHeaders
2687
2905
  };
2688
2906
  }
2689
2907
  });
2908
+ },
2909
+ getChatMessages: async (flowId) => {
2910
+ const { data, error, response } = await this.internalApiClient.GET(
2911
+ ChatMessages.path,
2912
+ {
2913
+ params: {
2914
+ path: {
2915
+ flowId
2916
+ }
2917
+ }
2918
+ }
2919
+ );
2920
+ if (error) {
2921
+ throw new ApiError(error.error, response, {
2922
+ status: response.status,
2923
+ statusText: response.statusText,
2924
+ url: response.url,
2925
+ method: "GET"
2926
+ });
2927
+ }
2928
+ return data.messages;
2929
+ },
2930
+ fetchReportData: async (reportId, { columns, limit, sorting, filters, cursor }) => {
2931
+ const params = toSearchParams({ limit, sorting, filters, cursor });
2932
+ const { data, error } = await this.internalApiClient.GET(
2933
+ GetReportData.path,
2934
+ {
2935
+ params: {
2936
+ path: {
2937
+ report_id: reportId.toString()
2938
+ },
2939
+ query: {
2940
+ columns: columns?.join(","),
2941
+ limit: params.limit,
2942
+ order: params.order,
2943
+ cursor: params.cursor,
2944
+ filter: params.filter
2945
+ }
2946
+ }
2947
+ }
2948
+ );
2949
+ if (error) {
2950
+ console.error(
2951
+ `Failed to fetch data for report ${reportId}: ${error.error}`
2952
+ );
2953
+ throw new Error(`Failed to fetch data for flow data ${reportId}`);
2954
+ }
2955
+ return data;
2956
+ },
2957
+ getReport: async (reportId) => {
2958
+ const params = { params: { path: { report_id: String(reportId) } } };
2959
+ const columnsPromise = this.internalApiClient.GET(
2960
+ GetReportColumns.path,
2961
+ params
2962
+ );
2963
+ const rowCountPromise = this.internalApiClient.GET(
2964
+ GetReportRowCount.path,
2965
+ params
2966
+ );
2967
+ const [
2968
+ { data: columns, error: columnsError, response: columnsResponse },
2969
+ { data: rowCount, error: rowCountError, response: rowCountResponse }
2970
+ ] = await Promise.all([columnsPromise, rowCountPromise]);
2971
+ if (columnsError) {
2972
+ throw new ApiError(columnsError.error, columnsResponse, {
2973
+ status: columnsResponse.status,
2974
+ statusText: columnsResponse.statusText,
2975
+ url: columnsResponse.url,
2976
+ method: "GET"
2977
+ });
2978
+ }
2979
+ if (rowCountError) {
2980
+ throw new ApiError(rowCountError.error, rowCountResponse, {
2981
+ status: rowCountResponse.status,
2982
+ statusText: rowCountResponse.statusText,
2983
+ url: rowCountResponse.url,
2984
+ method: "GET"
2985
+ });
2986
+ }
2987
+ return {
2988
+ columns,
2989
+ rowCount,
2990
+ data: this.api.fetchReportData
2991
+ };
2690
2992
  }
2691
2993
  };
2692
2994
  /**
@@ -2735,7 +3037,9 @@ var MageMetricsClient = class {
2735
3037
  storageKey: TOKEN_STORAGE_KEY,
2736
3038
  headers: {
2737
3039
  apiKey: anonKey
2738
- }
3040
+ },
3041
+ storage: this.storageAdapter,
3042
+ ...this.authOptions
2739
3043
  });
2740
3044
  this.supabaseClient.onAuthStateChange((event, session) => {
2741
3045
  console.debug("Supabase auth state change:", event, !!session);
@@ -2829,7 +3133,7 @@ var MageMetricsClient = class {
2829
3133
  createSupabaseHeaderMiddleware() {
2830
3134
  return {
2831
3135
  onRequest: async ({ request }) => {
2832
- const headers = await this.getAuthHeaders();
3136
+ const headers = await this.getHeaders();
2833
3137
  if (!this.supabaseClient) {
2834
3138
  return request;
2835
3139
  }