@magemetrics/core 0.1.4 → 0.1.5

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,11 @@ 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
+ };
512
522
  /**
513
523
  * Add an event listener for authentication state changes
514
524
  * @param type the type of the event
@@ -528,9 +538,13 @@ export declare class MageMetricsClient {
528
538
  waitForAuth(): Promise<void>;
529
539
  updateExternalJwt(jwt: string): Promise<void>;
530
540
  get state(): AuthState;
531
- getAuthHeaders(): Promise<Record<string, string>>;
541
+ getHeaders(): Promise<Record<string, string>>;
532
542
  private clearStorage;
533
543
  logout(): Promise<void>;
544
+ auth: {
545
+ startAutoRefresh: () => Promise<void> | undefined;
546
+ stopAuthRefresh: () => Promise<void> | undefined;
547
+ };
534
548
  /**
535
549
  * Public API methods that automatically wait for authentication
536
550
  */
@@ -547,7 +561,22 @@ export declare class MageMetricsClient {
547
561
  data: Blob | string;
548
562
  }>;
549
563
  generateContextualInsight: (payload: GenerateInsightParam) => Promise<ExtractInsightResponse>;
550
- getChat: (flowId: string, options?: MageMetricsChatTransportOptions) => MageMetricsChatTransport;
564
+ getChatTransport: (flowId: string, options?: MageMetricsChatTransportOptions) => MageMetricsChatTransport;
565
+ getChatMessages: (flowId: string) => Promise<MMChatUIMessage[]>;
566
+ fetchReportData: (reportId: number, { columns, limit, sorting, filters, cursor }: ReportDataFilters) => Promise<Record<string, unknown>[]>;
567
+ getReport: (reportId: number) => Promise<{
568
+ columns: {
569
+ name: string;
570
+ data_type: string;
571
+ dataType: string;
572
+ renderType?: string;
573
+ unit?: string;
574
+ }[];
575
+ rowCount: {
576
+ count: number;
577
+ };
578
+ data: (reportId: number, { columns, limit, sorting, filters, cursor }: ReportDataFilters) => Promise<Record<string, unknown>[]>;
579
+ }>;
551
580
  };
552
581
  /**
553
582
  * Perform the complete authentication flow
@@ -624,7 +653,7 @@ export declare class MemoryStorageAdapter implements AsyncStorage {
624
653
  removeItem(key: string): Promise<void>;
625
654
  }
626
655
 
627
- declare type MMChatUIMessage = UIMessage<unknown, CustomDataParts, MMUiTools>;
656
+ export declare type MMChatUIMessage = UIMessage<unknown, CustomDataParts, MMUiTools>;
628
657
 
629
658
  declare type MMUiTools = {
630
659
  generateDataReport: UiTool;
@@ -4152,6 +4181,14 @@ declare type RemoveParamsConfig = Simplify<{
4152
4181
  cookie?: string;
4153
4182
  }>;
4154
4183
 
4184
+ declare type ReportDataFilters = {
4185
+ columns?: string[];
4186
+ limit: number;
4187
+ sorting: SortingState;
4188
+ filters: TableFilters;
4189
+ cursor?: number;
4190
+ };
4191
+
4155
4192
  declare const SignalWithReportIdSchema: z.ZodObject<{
4156
4193
  rule: z.ZodString;
4157
4194
  metric: z.ZodString;
@@ -4173,6 +4210,10 @@ declare const SignalWithReportIdSchema: z.ZodObject<{
4173
4210
  reportId: number;
4174
4211
  }>;
4175
4212
 
4213
+ declare type SortingState = ColumnSort[];
4214
+
4215
+ declare type TableFilters = Record<string, string | number>;
4216
+
4176
4217
  /**
4177
4218
  * Token storage keys
4178
4219
  */
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.5"};
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,12 @@ 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
+ };
2470
2678
  }
2471
2679
  /**
2472
2680
  * Add an event listener for authentication state changes
@@ -2507,7 +2715,7 @@ var MageMetricsClient = class {
2507
2715
  get state() {
2508
2716
  return this.authState;
2509
2717
  }
2510
- async getAuthHeaders() {
2718
+ async getHeaders() {
2511
2719
  await this.waitForAuth();
2512
2720
  if (!this.supabaseClient) {
2513
2721
  return {};
@@ -2518,6 +2726,7 @@ var MageMetricsClient = class {
2518
2726
  }
2519
2727
  const { access_token } = session.data.session;
2520
2728
  return {
2729
+ [HEADER_CLIENT_VERSION]: MM_CLIENT_VERSION,
2521
2730
  "sp-access-token": access_token
2522
2731
  };
2523
2732
  }
@@ -2534,6 +2743,10 @@ var MageMetricsClient = class {
2534
2743
  }
2535
2744
  await this.clearStorage();
2536
2745
  }
2746
+ auth = {
2747
+ startAutoRefresh: () => this.supabaseClient?.startAutoRefresh(),
2748
+ stopAuthRefresh: () => this.supabaseClient?.startAutoRefresh()
2749
+ };
2537
2750
  /**
2538
2751
  * Public API methods that automatically wait for authentication
2539
2752
  */
@@ -2674,19 +2887,102 @@ var MageMetricsClient = class {
2674
2887
  }
2675
2888
  return data;
2676
2889
  },
2677
- getChat: (flowId, options) => {
2890
+ getChatTransport: (flowId, options) => {
2678
2891
  return new MageMetricsChatTransport(this.config.apiUrl, flowId, {
2679
2892
  ...options,
2680
2893
  headers: async () => {
2681
- const authHeaders = await this.getAuthHeaders();
2894
+ const authHeaders = await this.getHeaders();
2682
2895
  const headers = await resolve(options?.headers);
2683
2896
  return {
2684
2897
  ...headers,
2685
- ...authHeaders,
2686
- [HEADER_CLIENT_VERSION]: MM_CLIENT_VERSION
2898
+ ...authHeaders
2687
2899
  };
2688
2900
  }
2689
2901
  });
2902
+ },
2903
+ getChatMessages: async (flowId) => {
2904
+ const { data, error, response } = await this.internalApiClient.GET(
2905
+ ChatMessages.path,
2906
+ {
2907
+ params: {
2908
+ path: {
2909
+ flowId
2910
+ }
2911
+ }
2912
+ }
2913
+ );
2914
+ if (error) {
2915
+ throw new ApiError(error.error, response, {
2916
+ status: response.status,
2917
+ statusText: response.statusText,
2918
+ url: response.url,
2919
+ method: "GET"
2920
+ });
2921
+ }
2922
+ return data;
2923
+ },
2924
+ fetchReportData: async (reportId, { columns, limit, sorting, filters, cursor }) => {
2925
+ const params = toSearchParams({ limit, sorting, filters, cursor });
2926
+ const { data, error } = await this.internalApiClient.GET(
2927
+ GetReportData.path,
2928
+ {
2929
+ params: {
2930
+ path: {
2931
+ report_id: reportId.toString()
2932
+ },
2933
+ query: {
2934
+ columns: columns?.join(","),
2935
+ limit: params.limit,
2936
+ order: params.order,
2937
+ cursor: params.cursor,
2938
+ filter: params.filter
2939
+ }
2940
+ }
2941
+ }
2942
+ );
2943
+ if (error) {
2944
+ console.error(
2945
+ `Failed to fetch data for report ${reportId}: ${error.error}`
2946
+ );
2947
+ throw new Error(`Failed to fetch data for flow data ${reportId}`);
2948
+ }
2949
+ return data;
2950
+ },
2951
+ getReport: async (reportId) => {
2952
+ const params = { params: { path: { report_id: String(reportId) } } };
2953
+ const columnsPromise = this.internalApiClient.GET(
2954
+ GetReportColumns.path,
2955
+ params
2956
+ );
2957
+ const rowCountPromise = this.internalApiClient.GET(
2958
+ GetReportRowCount.path,
2959
+ params
2960
+ );
2961
+ const [
2962
+ { data: columns, error: columnsError, response: columnsResponse },
2963
+ { data: rowCount, error: rowCountError, response: rowCountResponse }
2964
+ ] = await Promise.all([columnsPromise, rowCountPromise]);
2965
+ if (columnsError) {
2966
+ throw new ApiError(columnsError.error, columnsResponse, {
2967
+ status: columnsResponse.status,
2968
+ statusText: columnsResponse.statusText,
2969
+ url: columnsResponse.url,
2970
+ method: "GET"
2971
+ });
2972
+ }
2973
+ if (rowCountError) {
2974
+ throw new ApiError(rowCountError.error, rowCountResponse, {
2975
+ status: rowCountResponse.status,
2976
+ statusText: rowCountResponse.statusText,
2977
+ url: rowCountResponse.url,
2978
+ method: "GET"
2979
+ });
2980
+ }
2981
+ return {
2982
+ columns,
2983
+ rowCount,
2984
+ data: this.api.fetchReportData
2985
+ };
2690
2986
  }
2691
2987
  };
2692
2988
  /**
@@ -2735,7 +3031,9 @@ var MageMetricsClient = class {
2735
3031
  storageKey: TOKEN_STORAGE_KEY,
2736
3032
  headers: {
2737
3033
  apiKey: anonKey
2738
- }
3034
+ },
3035
+ storage: this.storageAdapter,
3036
+ ...this.authOptions
2739
3037
  });
2740
3038
  this.supabaseClient.onAuthStateChange((event, session) => {
2741
3039
  console.debug("Supabase auth state change:", event, !!session);
@@ -2829,7 +3127,7 @@ var MageMetricsClient = class {
2829
3127
  createSupabaseHeaderMiddleware() {
2830
3128
  return {
2831
3129
  onRequest: async ({ request }) => {
2832
- const headers = await this.getAuthHeaders();
3130
+ const headers = await this.getHeaders();
2833
3131
  if (!this.supabaseClient) {
2834
3132
  return request;
2835
3133
  }