@taruvi/refine-providers 1.0.8 → 1.0.10

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.cjs CHANGED
@@ -1,6 +1,11 @@
1
1
  'use strict';
2
2
 
3
3
  var sdk = require('@taruvi/sdk');
4
+ var DataLoader = require('dataloader');
5
+
6
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
7
+
8
+ var DataLoader__default = /*#__PURE__*/_interopDefault(DataLoader);
4
9
 
5
10
  // src/dataProvider.ts
6
11
  var REFINE_TO_SDK_OPERATOR = {
@@ -43,7 +48,7 @@ function applyFilters(query, filters) {
43
48
  }
44
49
  let sdkValue;
45
50
  if (operator === "in" || operator === "nin") {
46
- sdkValue = Array.isArray(value) ? value.join(",") : String(value);
51
+ sdkValue = Array.isArray(value) ? value : [value];
47
52
  } else if (operator === "null" || operator === "nnull") {
48
53
  sdkValue = true;
49
54
  } else if (typeof value === "boolean" || typeof value === "number") {
@@ -114,7 +119,7 @@ function dataProvider(client) {
114
119
  const tableName = getTableName(resource, taruviMeta);
115
120
  const idColumn = getIdColumn(taruviMeta);
116
121
  let query = new sdk.Database(client).from(tableName);
117
- query = query.filter(idColumn, "in", ids.map(String).join(","));
122
+ query = query.filter(idColumn, "in", ids.map(String));
118
123
  query = applyPopulate(query, taruviMeta);
119
124
  const response = await query.execute();
120
125
  return { data: response.data };
@@ -426,43 +431,119 @@ function functionsDataProvider(client) {
426
431
  const baseApiUrl = `${config.baseUrl}/api/apps/${config.appSlug}`;
427
432
  const functions = new sdk.Functions(client);
428
433
  return {
429
- custom: async (params) => {
430
- const { url: functionSlug, payload, meta } = params;
434
+ /**
435
+ * Execute an edge function.
436
+ *
437
+ * @param resource - The function slug to execute
438
+ * @param variables - Parameters to pass to the function
439
+ * @param meta.async - Whether to execute asynchronously (default: false)
440
+ */
441
+ create: async ({
442
+ resource,
443
+ variables,
444
+ meta
445
+ }) => {
431
446
  const functionMeta = meta;
432
- const response = await functions.execute(functionSlug, {
447
+ const response = await functions.execute(resource, {
433
448
  async: functionMeta?.async ?? false,
434
- params: payload
449
+ params: variables
435
450
  });
436
451
  return { data: response.data };
437
452
  },
438
453
  getApiUrl: () => baseApiUrl,
439
- // Edge functions don't support CRUD operations
454
+ // Edge functions don't support custom method - use create() instead
455
+ custom: async () => {
456
+ throw new Error(
457
+ "custom is not supported for edge functions. Use useCreate to execute functions."
458
+ );
459
+ },
460
+ // Edge functions don't support other CRUD operations
440
461
  getList: async () => {
441
- throw new Error("getList is not supported for edge functions");
462
+ throw new Error(
463
+ "getList is not supported for edge functions. Use useCreate to execute functions."
464
+ );
465
+ },
466
+ getOne: async () => {
467
+ throw new Error(
468
+ "getOne is not supported for edge functions. Use useCreate to execute functions."
469
+ );
470
+ },
471
+ getMany: async () => {
472
+ throw new Error(
473
+ "getMany is not supported for edge functions. Use useCreate to execute functions."
474
+ );
475
+ },
476
+ createMany: async () => {
477
+ throw new Error(
478
+ "createMany is not supported for edge functions. Use useCreate to execute functions."
479
+ );
480
+ },
481
+ update: async () => {
482
+ throw new Error(
483
+ "update is not supported for edge functions. Use useCreate to execute functions."
484
+ );
485
+ },
486
+ updateMany: async () => {
487
+ throw new Error(
488
+ "updateMany is not supported for edge functions. Use useCreate to execute functions."
489
+ );
490
+ },
491
+ deleteOne: async () => {
492
+ throw new Error(
493
+ "deleteOne is not supported for edge functions. Use useCreate to execute functions."
494
+ );
495
+ },
496
+ deleteMany: async () => {
497
+ throw new Error(
498
+ "deleteMany is not supported for edge functions. Use useCreate to execute functions."
499
+ );
500
+ }
501
+ };
502
+ }
503
+ function appDataProvider(client) {
504
+ const config = client.getConfig();
505
+ const baseApiUrl = `${config.baseUrl}/api/apps/${config.appSlug}`;
506
+ return {
507
+ getList: async (params) => {
508
+ const { resource } = params;
509
+ if (resource === "roles") {
510
+ const app = new sdk.App(client);
511
+ const response = await app.roles().execute();
512
+ return {
513
+ data: response.data || response,
514
+ total: response.total ?? (Array.isArray(response) ? response.length : response.data?.length ?? 0)
515
+ };
516
+ }
517
+ throw new Error(`Unknown app resource: ${resource}. Supported resources: roles`);
442
518
  },
519
+ getApiUrl: () => baseApiUrl,
520
+ // App resources are read-only
443
521
  getOne: async () => {
444
- throw new Error("getOne is not supported for edge functions");
522
+ throw new Error("getOne is not supported for app resources");
445
523
  },
446
524
  getMany: async () => {
447
- throw new Error("getMany is not supported for edge functions");
525
+ throw new Error("getMany is not supported for app resources");
448
526
  },
449
527
  create: async () => {
450
- throw new Error("create is not supported for edge functions");
528
+ throw new Error("create is not supported for app resources");
451
529
  },
452
530
  createMany: async () => {
453
- throw new Error("createMany is not supported for edge functions");
531
+ throw new Error("createMany is not supported for app resources");
454
532
  },
455
533
  update: async () => {
456
- throw new Error("update is not supported for edge functions");
534
+ throw new Error("update is not supported for app resources");
457
535
  },
458
536
  updateMany: async () => {
459
- throw new Error("updateMany is not supported for edge functions");
537
+ throw new Error("updateMany is not supported for app resources");
460
538
  },
461
539
  deleteOne: async () => {
462
- throw new Error("deleteOne is not supported for edge functions");
540
+ throw new Error("deleteOne is not supported for app resources");
463
541
  },
464
542
  deleteMany: async () => {
465
- throw new Error("deleteMany is not supported for edge functions");
543
+ throw new Error("deleteMany is not supported for app resources");
544
+ },
545
+ custom: async () => {
546
+ throw new Error("custom is not supported for app resources");
466
547
  }
467
548
  };
468
549
  }
@@ -526,41 +607,68 @@ function analyticsDataProvider(client) {
526
607
  const baseApiUrl = `${config.baseUrl}/api/apps/${config.appSlug}`;
527
608
  const analytics = new sdk.Analytics(client);
528
609
  return {
529
- custom: async (params) => {
530
- const { url: querySlug, payload } = params;
531
- const response = await analytics.execute(querySlug, {
532
- params: payload
610
+ /**
611
+ * Execute an analytics query.
612
+ *
613
+ * @param resource - The query slug to execute
614
+ * @param variables - Parameters to pass to the query
615
+ */
616
+ create: async ({
617
+ resource,
618
+ variables
619
+ }) => {
620
+ const response = await analytics.execute(resource, {
621
+ params: variables
533
622
  });
534
623
  return { data: response.data };
535
624
  },
536
625
  getApiUrl: () => baseApiUrl,
537
- // Analytics queries don't support standard CRUD operations
626
+ // Analytics don't support custom method - use create() instead
627
+ custom: async () => {
628
+ throw new Error(
629
+ "custom is not supported for analytics. Use useCreate to execute queries."
630
+ );
631
+ },
632
+ // Analytics queries don't support other CRUD operations
538
633
  getList: async () => {
539
- throw new Error("getList is not supported for analytics. Use custom() to execute queries");
634
+ throw new Error(
635
+ "getList is not supported for analytics. Use useCreate to execute queries."
636
+ );
540
637
  },
541
638
  getOne: async () => {
542
- throw new Error("getOne is not supported for analytics. Use custom() to execute queries");
639
+ throw new Error(
640
+ "getOne is not supported for analytics. Use useCreate to execute queries."
641
+ );
543
642
  },
544
643
  getMany: async () => {
545
- throw new Error("getMany is not supported for analytics. Use custom() to execute queries");
546
- },
547
- create: async () => {
548
- throw new Error("create is not supported for analytics. Use custom() to execute queries");
644
+ throw new Error(
645
+ "getMany is not supported for analytics. Use useCreate to execute queries."
646
+ );
549
647
  },
550
648
  createMany: async () => {
551
- throw new Error("createMany is not supported for analytics. Use custom() to execute queries");
649
+ throw new Error(
650
+ "createMany is not supported for analytics. Use useCreate to execute queries."
651
+ );
552
652
  },
553
653
  update: async () => {
554
- throw new Error("update is not supported for analytics. Use custom() to execute queries");
654
+ throw new Error(
655
+ "update is not supported for analytics. Use useCreate to execute queries."
656
+ );
555
657
  },
556
658
  updateMany: async () => {
557
- throw new Error("updateMany is not supported for analytics. Use custom() to execute queries");
659
+ throw new Error(
660
+ "updateMany is not supported for analytics. Use useCreate to execute queries."
661
+ );
558
662
  },
559
663
  deleteOne: async () => {
560
- throw new Error("deleteOne is not supported for analytics. Use custom() to execute queries");
664
+ throw new Error(
665
+ "deleteOne is not supported for analytics. Use useCreate to execute queries."
666
+ );
561
667
  },
562
668
  deleteMany: async () => {
563
- throw new Error("deleteMany is not supported for analytics. Use custom() to execute queries");
669
+ throw new Error(
670
+ "deleteMany is not supported for analytics. Use useCreate to execute queries."
671
+ );
564
672
  }
565
673
  };
566
674
  }
@@ -682,60 +790,97 @@ function authProvider(client) {
682
790
  }
683
791
  };
684
792
  }
685
- function accessControlProvider(client) {
793
+ function accessControlProvider(client, options) {
686
794
  const policy = new sdk.Policy(client);
687
795
  const auth = new sdk.Auth(client);
688
- return {
689
- can: async ({ resource, action, params }) => {
796
+ const { batchDelayMs = 50 } = options ?? {};
797
+ const permissionLoader = new DataLoader__default.default(
798
+ async (checks) => {
690
799
  const user = auth.getCurrentUser();
691
800
  if (!user) {
692
- return {
801
+ return checks.map(() => ({
693
802
  can: false,
694
803
  reason: "User not authenticated"
695
- };
804
+ }));
696
805
  }
697
- if (!resource) {
698
- return {
699
- can: false,
700
- reason: "Resource not specified"
701
- };
806
+ const uniqueResources = /* @__PURE__ */ new Map();
807
+ for (const check of checks) {
808
+ const recordId = check.params?.id ? String(check.params.id) : "*";
809
+ const key = `${check.resource}:${recordId}`;
810
+ if (!uniqueResources.has(key)) {
811
+ uniqueResources.set(key, {
812
+ entityType: check.entityType,
813
+ tableName: check.resource,
814
+ recordId,
815
+ attributes: check.params || {},
816
+ actions: /* @__PURE__ */ new Set()
817
+ });
818
+ }
819
+ uniqueResources.get(key).actions.add(check.action);
702
820
  }
821
+ const batchPayload = Array.from(uniqueResources.values()).map((entry) => ({
822
+ entityType: entry.entityType ?? entry.tableName,
823
+ // Default to tableName if entityType not specified
824
+ tableName: entry.tableName,
825
+ recordId: entry.recordId,
826
+ attributes: entry.attributes,
827
+ actions: Array.from(entry.actions)
828
+ }));
703
829
  try {
704
- const entityType = params?.resource?.meta?.entityType;
705
- const resources = [
706
- {
707
- entityType,
708
- tableName: resource,
709
- recordId: params?.id ? String(params.id) : "*",
710
- attributes: params || {},
711
- actions: [action]
712
- }
713
- ];
714
- const result = await policy.checkResource(resources);
715
- if (result && typeof result === "object") {
716
- const actionResult = result.results?.[0]?.actions?.[action];
717
- const allowed = actionResult === "EFFECT_ALLOW" || result.allowed === true;
830
+ const result = await policy.checkResource(batchPayload);
831
+ const resultsByResource = /* @__PURE__ */ new Map();
832
+ result?.results?.forEach((r, index) => {
833
+ const payload = batchPayload[index];
834
+ const key = `${payload.tableName}:${payload.recordId}`;
835
+ resultsByResource.set(key, r.actions || {});
836
+ });
837
+ return checks.map((check) => {
838
+ const recordId = check.params?.id ? String(check.params.id) : "*";
839
+ const key = `${check.resource}:${recordId}`;
840
+ const actions = resultsByResource.get(key) || {};
841
+ const allowed = actions[check.action] === "EFFECT_ALLOW";
718
842
  return {
719
843
  can: allowed,
720
- reason: result.reason || (allowed ? void 0 : "Permission denied by policy")
844
+ reason: allowed ? void 0 : "Permission denied by policy"
721
845
  };
722
- }
723
- return {
724
- can: false,
725
- reason: "Invalid policy response"
726
- };
846
+ });
727
847
  } catch (error) {
728
- console.error("Cerbos permission check failed:", error);
729
- return {
848
+ console.error("Batch permission check failed:", error);
849
+ return checks.map(() => ({
730
850
  can: false,
731
851
  reason: error instanceof Error ? error.message : "Permission check failed"
732
- };
852
+ }));
853
+ }
854
+ },
855
+ {
856
+ batchScheduleFn: (callback) => setTimeout(callback, batchDelayMs),
857
+ cache: false
858
+ // TanStack Query handles caching
859
+ }
860
+ );
861
+ return {
862
+ can: async ({ resource, action, params }) => {
863
+ if (!resource) {
864
+ return { can: false, reason: "Resource not specified" };
733
865
  }
866
+ const entityType = params?.resource?.meta?.entityType;
867
+ return permissionLoader.load({
868
+ resource,
869
+ action,
870
+ params,
871
+ entityType
872
+ });
734
873
  },
735
874
  options: {
736
875
  buttons: {
737
876
  enableAccessControl: true,
738
- hideIfUnauthorized: false
877
+ hideIfUnauthorized: true
878
+ },
879
+ queryOptions: {
880
+ staleTime: 5 * 60 * 1e3,
881
+ // 5 minutes
882
+ gcTime: 10 * 60 * 1e3
883
+ // 10 minutes
739
884
  }
740
885
  }
741
886
  };
@@ -772,6 +917,7 @@ Object.defineProperty(exports, "User", {
772
917
  exports.REFINE_OPERATOR_MAP = REFINE_OPERATOR_MAP;
773
918
  exports.accessControlProvider = accessControlProvider;
774
919
  exports.analyticsDataProvider = analyticsDataProvider;
920
+ exports.appDataProvider = appDataProvider;
775
921
  exports.authProvider = authProvider;
776
922
  exports.buildQueryString = buildQueryString;
777
923
  exports.buildRefineQueryParams = buildRefineQueryParams;