kmod-cli 1.8.2 → 1.10.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 +1 -0
- package/component-templates/providers/refine-provider.tsx +261 -101
- package/component-templates/utils/hash/fanhash.ts +107 -0
- package/components.json +39 -108
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -135,10 +135,30 @@ export interface DataProviderError {
|
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
export interface DataProviderOptions {
|
|
138
|
+
/**
|
|
139
|
+
* Time to live for cached data (default: 5 * 60 * 1000) - 5 minutes
|
|
140
|
+
*/
|
|
138
141
|
cacheTime?: number;
|
|
142
|
+
/**
|
|
143
|
+
* Time to live for stale data (default: 5 * 60 * 1000) - 5 minutes
|
|
144
|
+
*/
|
|
145
|
+
staleTime?: number;
|
|
146
|
+
/**
|
|
147
|
+
* Retry count (default: 1)
|
|
148
|
+
*/
|
|
139
149
|
retryCount?: number;
|
|
150
|
+
/**
|
|
151
|
+
* Retry delay (ms) (default: 1000) - 1 second
|
|
152
|
+
*/
|
|
140
153
|
retryDelay?: number;
|
|
154
|
+
/**
|
|
155
|
+
* Debug mode (default: false)
|
|
156
|
+
*/
|
|
141
157
|
debug?: boolean;
|
|
158
|
+
/**
|
|
159
|
+
* Persist data in memory, local storage, or session storage (default: memory)
|
|
160
|
+
*/
|
|
161
|
+
persist?: "memory" | "local" | "session";
|
|
142
162
|
}
|
|
143
163
|
|
|
144
164
|
interface CacheItem<T = any> {
|
|
@@ -149,6 +169,7 @@ interface CacheItem<T = any> {
|
|
|
149
169
|
export interface UseListOptions {
|
|
150
170
|
refetchInterval?: number;
|
|
151
171
|
enabled?: boolean;
|
|
172
|
+
cache?: boolean;
|
|
152
173
|
}
|
|
153
174
|
|
|
154
175
|
export interface UseOneOptions {
|
|
@@ -221,6 +242,8 @@ class DataProvider {
|
|
|
221
242
|
private cache: Map<string, CacheItem>;
|
|
222
243
|
private options: Required<DataProviderOptions>;
|
|
223
244
|
|
|
245
|
+
private cachePrefix = "__DP_CACHE__:";
|
|
246
|
+
|
|
224
247
|
constructor(
|
|
225
248
|
httpClient: AxiosInstance = axios.create(),
|
|
226
249
|
options: DataProviderOptions = {},
|
|
@@ -239,11 +262,31 @@ class DataProvider {
|
|
|
239
262
|
this.cache = new Map();
|
|
240
263
|
this.options = {
|
|
241
264
|
cacheTime: 5 * 60 * 1000,
|
|
265
|
+
staleTime: 30 * 1000,
|
|
266
|
+
persist: "memory",
|
|
242
267
|
retryCount: 1,
|
|
243
268
|
retryDelay: 1000,
|
|
244
269
|
debug: false,
|
|
245
270
|
...options,
|
|
246
271
|
};
|
|
272
|
+
|
|
273
|
+
this.cache = new Map();
|
|
274
|
+
this.loadPersistCache();
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
private loadPersistCache() {
|
|
278
|
+
if (this.options.persist === "memory") return;
|
|
279
|
+
|
|
280
|
+
const storage =
|
|
281
|
+
this.options.persist === "local" ? localStorage : sessionStorage;
|
|
282
|
+
|
|
283
|
+
Object.keys(storage).forEach((key) => {
|
|
284
|
+
if (!key.startsWith(this.cachePrefix)) return;
|
|
285
|
+
try {
|
|
286
|
+
const value = JSON.parse(storage.getItem(key)!);
|
|
287
|
+
this.cache.set(key.replace(this.cachePrefix, ""), value);
|
|
288
|
+
} catch {}
|
|
289
|
+
});
|
|
247
290
|
}
|
|
248
291
|
|
|
249
292
|
private log(message: string, data?: any): void {
|
|
@@ -257,27 +300,40 @@ class DataProvider {
|
|
|
257
300
|
return `${resource}:${JSON.stringify(params || {})}`;
|
|
258
301
|
}
|
|
259
302
|
|
|
260
|
-
private getCache<T
|
|
303
|
+
private getCache<T>(key: string): {
|
|
304
|
+
data: T;
|
|
305
|
+
isStale: boolean;
|
|
306
|
+
} | null {
|
|
261
307
|
const cached = this.cache.get(key);
|
|
262
308
|
if (!cached) return null;
|
|
263
309
|
|
|
264
|
-
const
|
|
265
|
-
|
|
310
|
+
const age = Date.now() - cached.timestamp;
|
|
311
|
+
|
|
312
|
+
if (age > this.options.cacheTime) {
|
|
266
313
|
this.cache.delete(key);
|
|
267
|
-
// this.log('Cache expired', key);
|
|
268
314
|
return null;
|
|
269
315
|
}
|
|
270
316
|
|
|
271
|
-
|
|
272
|
-
|
|
317
|
+
return {
|
|
318
|
+
data: cached.data as T,
|
|
319
|
+
isStale: age > this.options.staleTime,
|
|
320
|
+
};
|
|
273
321
|
}
|
|
274
322
|
|
|
275
|
-
private setCache<T
|
|
276
|
-
|
|
323
|
+
private setCache<T>(key: string, data: T) {
|
|
324
|
+
const item = {
|
|
277
325
|
data,
|
|
278
326
|
timestamp: Date.now(),
|
|
279
|
-
}
|
|
280
|
-
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
this.cache.set(key, item);
|
|
330
|
+
|
|
331
|
+
if (this.options.persist !== "memory") {
|
|
332
|
+
const storage =
|
|
333
|
+
this.options.persist === "local" ? localStorage : sessionStorage;
|
|
334
|
+
|
|
335
|
+
storage.setItem(this.cachePrefix + key, JSON.stringify(item));
|
|
336
|
+
}
|
|
281
337
|
}
|
|
282
338
|
|
|
283
339
|
public invalidateCache(resource: string, id?: string | number): void {
|
|
@@ -347,10 +403,21 @@ class DataProvider {
|
|
|
347
403
|
useCache: boolean = true,
|
|
348
404
|
): Promise<GetListResponse<T>> {
|
|
349
405
|
const cacheKey = this.getCacheKey(resource, params);
|
|
406
|
+
const cached = useCache
|
|
407
|
+
? this.getCache<GetListResponse<T>>(cacheKey)
|
|
408
|
+
: null;
|
|
409
|
+
|
|
410
|
+
if (cached) {
|
|
411
|
+
if (!cached.isStale) {
|
|
412
|
+
return cached.data;
|
|
413
|
+
}
|
|
350
414
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
415
|
+
// stale → trả data cũ + background refetch
|
|
416
|
+
this.getList(resource, params, false).then((fresh) => {
|
|
417
|
+
this.setCache(cacheKey, fresh);
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
return cached.data;
|
|
354
421
|
}
|
|
355
422
|
|
|
356
423
|
const { pagination, filters, sorters, meta } = params;
|
|
@@ -437,10 +504,16 @@ class DataProvider {
|
|
|
437
504
|
): Promise<GetOneResponse<T>> {
|
|
438
505
|
const { id, meta } = params;
|
|
439
506
|
const cacheKey = this.getCacheKey(`${resource}/${id}`, {});
|
|
507
|
+
const cached = useCache ? this.getCache<GetOneResponse<T>>(cacheKey) : null;
|
|
508
|
+
|
|
509
|
+
if (cached) {
|
|
510
|
+
if (!cached.isStale) return cached.data;
|
|
511
|
+
|
|
512
|
+
this.getOne(resource, params, false).then((fresh) => {
|
|
513
|
+
this.setCache(cacheKey, fresh);
|
|
514
|
+
});
|
|
440
515
|
|
|
441
|
-
|
|
442
|
-
const cached = this.getCache<GetOneResponse<T>>(cacheKey);
|
|
443
|
-
if (cached) return cached;
|
|
516
|
+
return cached.data;
|
|
444
517
|
}
|
|
445
518
|
|
|
446
519
|
const url = `${this.apiUrl}/${resource}/${id}`;
|
|
@@ -743,32 +816,36 @@ export function useList<T = any>(
|
|
|
743
816
|
|
|
744
817
|
const dataProvider = useDataProvider();
|
|
745
818
|
|
|
746
|
-
const { refetchInterval, enabled = true } = options;
|
|
819
|
+
const { refetchInterval, enabled = true, cache = true } = options;
|
|
747
820
|
const paramsStr = JSON.stringify(params);
|
|
748
821
|
|
|
749
|
-
const refetch = useCallback(
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
822
|
+
const refetch = useCallback(
|
|
823
|
+
async (force = false) => {
|
|
824
|
+
if (!enabled) {
|
|
825
|
+
setLoading(false);
|
|
826
|
+
return;
|
|
827
|
+
}
|
|
754
828
|
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
829
|
+
try {
|
|
830
|
+
setLoading(true);
|
|
831
|
+
setError(null);
|
|
832
|
+
const result = await dataProvider.getList<T>(
|
|
833
|
+
resource,
|
|
834
|
+
JSON.parse(paramsStr),
|
|
835
|
+
!force,
|
|
836
|
+
);
|
|
837
|
+
setData(result.data || []);
|
|
838
|
+
setTotal(result.total || 0);
|
|
839
|
+
} catch (err) {
|
|
840
|
+
setError(err as DataProviderError);
|
|
841
|
+
setData([]);
|
|
842
|
+
setTotal(0);
|
|
843
|
+
} finally {
|
|
844
|
+
setLoading(false);
|
|
845
|
+
}
|
|
846
|
+
},
|
|
847
|
+
[dataProvider, resource, paramsStr, enabled],
|
|
848
|
+
);
|
|
772
849
|
|
|
773
850
|
useEffect(() => {
|
|
774
851
|
refetch();
|
|
@@ -797,24 +874,27 @@ export function useOne<T = any>(
|
|
|
797
874
|
|
|
798
875
|
const { enabled = true } = options;
|
|
799
876
|
|
|
800
|
-
const refetch = useCallback(
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
877
|
+
const refetch = useCallback(
|
|
878
|
+
async (force = false) => {
|
|
879
|
+
if (!enabled || !id) {
|
|
880
|
+
setLoading(false);
|
|
881
|
+
return;
|
|
882
|
+
}
|
|
805
883
|
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
884
|
+
try {
|
|
885
|
+
setLoading(true);
|
|
886
|
+
setError(null);
|
|
887
|
+
const result = await dataProvider.getOne<T>(resource, { id }, !force);
|
|
888
|
+
setData(result.data);
|
|
889
|
+
} catch (err) {
|
|
890
|
+
setError(err as DataProviderError);
|
|
891
|
+
setData(null);
|
|
892
|
+
} finally {
|
|
893
|
+
setLoading(false);
|
|
894
|
+
}
|
|
895
|
+
},
|
|
896
|
+
[dataProvider, resource, id, enabled],
|
|
897
|
+
);
|
|
818
898
|
|
|
819
899
|
useEffect(() => {
|
|
820
900
|
refetch();
|
|
@@ -1290,78 +1370,158 @@ export const cookiesProvider = {
|
|
|
1290
1370
|
},
|
|
1291
1371
|
};
|
|
1292
1372
|
|
|
1293
|
-
// ===================
|
|
1294
|
-
|
|
1295
|
-
// create httpClient - (can create multiple httpClients for different apis)
|
|
1373
|
+
// =================== 1. Create httpClient ===================
|
|
1296
1374
|
|
|
1297
1375
|
// const TOKEN = "token";
|
|
1298
1376
|
|
|
1299
1377
|
// const httpClient = createHttpClient({
|
|
1300
|
-
// url:
|
|
1378
|
+
// url: process.env.NEXT_PUBLIC_API_URL,
|
|
1301
1379
|
// options: {
|
|
1302
1380
|
// authorizationType: "Bearer",
|
|
1303
1381
|
// tokenName: TOKEN,
|
|
1304
|
-
// tokenStorage: "cookie",
|
|
1305
|
-
// withCredentials: true,
|
|
1382
|
+
// tokenStorage: "cookie", // or "http-only" | "local" | "session"
|
|
1383
|
+
// withCredentials: true, // optional (auto true if tokenStorage = "http-only")
|
|
1306
1384
|
// },
|
|
1307
1385
|
// });
|
|
1308
1386
|
|
|
1309
|
-
//
|
|
1387
|
+
// =================== 2. Create DataProvider ===================
|
|
1310
1388
|
|
|
1311
|
-
//
|
|
1389
|
+
// IMPORTANT:
|
|
1390
|
+
// persist !== "memory" --> to CACHE data and prevent F5 from calling API again
|
|
1391
|
+
|
|
1392
|
+
// const dataProvider = new DataProvider(httpClient, {
|
|
1393
|
+
// persist: "session", // "memory" | "session" | "local"
|
|
1394
|
+
// cacheTime: 5 * 60 * 1000, // 5 minutes
|
|
1395
|
+
// staleTime: 30 * 1000, // 30 seconds
|
|
1396
|
+
// });
|
|
1397
|
+
|
|
1398
|
+
// =================== 3. Auth Provider URLs ===================
|
|
1312
1399
|
|
|
1313
1400
|
// const urls = {
|
|
1314
|
-
//
|
|
1315
|
-
//
|
|
1316
|
-
//
|
|
1317
|
-
//
|
|
1401
|
+
// loginUrl: "/auth/login", // POST
|
|
1402
|
+
// logoutUrl: "/auth/logout", // POST
|
|
1403
|
+
// meUrl: "/auth/me", // GET (by token)
|
|
1404
|
+
// };
|
|
1318
1405
|
|
|
1319
|
-
//
|
|
1406
|
+
// const keysRemoveOnLogout = [TOKEN, "refreshToken", "user"];
|
|
1320
1407
|
|
|
1321
|
-
//
|
|
1322
|
-
|
|
1408
|
+
// =================== 4. Wrap Providers ===================
|
|
1409
|
+
|
|
1410
|
+
// <DataProviderContainer dataProvider={dataProvider}>
|
|
1323
1411
|
// <AuthProvider
|
|
1324
|
-
//
|
|
1325
|
-
//
|
|
1326
|
-
//
|
|
1412
|
+
// urls={urls}
|
|
1413
|
+
// tokenKey={TOKEN}
|
|
1414
|
+
// keysCleanUpOnLogout={keysRemoveOnLogout}
|
|
1327
1415
|
// >
|
|
1328
1416
|
// <App />
|
|
1329
1417
|
// </AuthProvider>
|
|
1330
|
-
// </
|
|
1418
|
+
// </DataProviderContainer>
|
|
1419
|
+
|
|
1420
|
+
// =================== 5. Auth Hooks ===================
|
|
1421
|
+
|
|
1422
|
+
// const { login, logout, getMe, isAuthenticated } = useAuth();
|
|
1423
|
+
|
|
1424
|
+
// =================== 6. useList ===================
|
|
1425
|
+
|
|
1426
|
+
// Auto load on mount
|
|
1427
|
+
// Use cache if exists (F5 will NOT refetch if persist !== memory)
|
|
1428
|
+
|
|
1429
|
+
// const {
|
|
1430
|
+
// data,
|
|
1431
|
+
// total,
|
|
1432
|
+
// loading,
|
|
1433
|
+
// error,
|
|
1434
|
+
// refetch,
|
|
1435
|
+
// } = useList<User>(
|
|
1436
|
+
// "users",
|
|
1437
|
+
// {
|
|
1438
|
+
// meta: {
|
|
1439
|
+
// params: {
|
|
1440
|
+
// role: "admin",
|
|
1441
|
+
// },
|
|
1442
|
+
// },
|
|
1443
|
+
// },
|
|
1444
|
+
// {
|
|
1445
|
+
// cache: true,
|
|
1446
|
+
// },
|
|
1447
|
+
// );
|
|
1448
|
+
|
|
1449
|
+
// Force refetch (bypass cache)
|
|
1450
|
+
// refetch(true);
|
|
1451
|
+
|
|
1452
|
+
// =================== 7. useOne ===================
|
|
1453
|
+
|
|
1454
|
+
// const {
|
|
1455
|
+
// data,
|
|
1456
|
+
// loading,
|
|
1457
|
+
// error,
|
|
1458
|
+
// refetch,
|
|
1459
|
+
// } = useOne<User>(
|
|
1460
|
+
// "users",
|
|
1461
|
+
// userId,
|
|
1462
|
+
// {
|
|
1463
|
+
// enabled: !!userId,
|
|
1464
|
+
// },
|
|
1465
|
+
// );
|
|
1331
1466
|
|
|
1332
|
-
//
|
|
1467
|
+
// Force refetch (ignore cache)
|
|
1468
|
+
// refetch(true);
|
|
1333
1469
|
|
|
1334
|
-
//
|
|
1470
|
+
// =================== 8. useCreate ===================
|
|
1335
1471
|
|
|
1336
|
-
//
|
|
1472
|
+
// const { mutate, loading, error } = useCreate<User, CreateUserPayload>(
|
|
1473
|
+
// "users",
|
|
1474
|
+
// {
|
|
1475
|
+
// onSuccess: (data) => {
|
|
1476
|
+
// console.log("Created:", data);
|
|
1477
|
+
// },
|
|
1478
|
+
// },
|
|
1479
|
+
// );
|
|
1337
1480
|
|
|
1338
|
-
//
|
|
1339
|
-
//
|
|
1481
|
+
// mutate({
|
|
1482
|
+
// name: "John",
|
|
1483
|
+
// email: "john@mail.com",
|
|
1340
1484
|
// });
|
|
1341
1485
|
|
|
1342
|
-
//
|
|
1343
|
-
// url: '/route_name/:id',
|
|
1344
|
-
// id: 1,
|
|
1345
|
-
// });
|
|
1486
|
+
// =================== 9. useUpdate ===================
|
|
1346
1487
|
|
|
1347
|
-
// const {
|
|
1348
|
-
//
|
|
1349
|
-
//
|
|
1350
|
-
//
|
|
1488
|
+
// const { mutate, loading, error } = useUpdate<User, UpdateUserPayload>(
|
|
1489
|
+
// "users",
|
|
1490
|
+
// {
|
|
1491
|
+
// onSuccess: (data) => {
|
|
1492
|
+
// console.log("Updated:", data);
|
|
1493
|
+
// },
|
|
1494
|
+
// },
|
|
1495
|
+
// );
|
|
1351
1496
|
|
|
1352
|
-
//
|
|
1353
|
-
//
|
|
1354
|
-
// id: 1,
|
|
1355
|
-
// payload: {},
|
|
1497
|
+
// mutate(1, {
|
|
1498
|
+
// name: "New name",
|
|
1356
1499
|
// });
|
|
1357
1500
|
|
|
1358
|
-
//
|
|
1359
|
-
// url: '/route_name/:id',
|
|
1360
|
-
// id: 1,
|
|
1361
|
-
// });
|
|
1501
|
+
// =================== 10. useDelete ===================
|
|
1362
1502
|
|
|
1363
|
-
// const {
|
|
1364
|
-
//
|
|
1365
|
-
//
|
|
1366
|
-
//
|
|
1367
|
-
//
|
|
1503
|
+
// const { mutate, loading } = useDelete<User>(
|
|
1504
|
+
// "users",
|
|
1505
|
+
// {
|
|
1506
|
+
// onSuccess: () => {
|
|
1507
|
+
// console.log("Deleted");
|
|
1508
|
+
// },
|
|
1509
|
+
// },
|
|
1510
|
+
// );
|
|
1511
|
+
|
|
1512
|
+
// mutate(1);
|
|
1513
|
+
|
|
1514
|
+
// =================== 11. useCustom ===================
|
|
1515
|
+
|
|
1516
|
+
// const { mutate, data, loading, error } = useCustom<CustomResponse>(
|
|
1517
|
+
// "/reports/export",
|
|
1518
|
+
// {
|
|
1519
|
+
// method: "post",
|
|
1520
|
+
// payload: {
|
|
1521
|
+
// from: "2024-01-01",
|
|
1522
|
+
// to: "2024-12-31",
|
|
1523
|
+
// },
|
|
1524
|
+
// },
|
|
1525
|
+
// );
|
|
1526
|
+
|
|
1527
|
+
// mutate();
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SHA_256 clearly
|
|
3
|
+
*/
|
|
4
|
+
function _sha256Internal(ascii: string): string {
|
|
5
|
+
const rightRotate = (v: number, a: number): number => (v >>> a) | (v << (32 - a));
|
|
6
|
+
const maxWord = Math.pow(2, 32);
|
|
7
|
+
let hash = [0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19];
|
|
8
|
+
const k = [
|
|
9
|
+
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
|
10
|
+
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
|
11
|
+
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
|
12
|
+
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
|
13
|
+
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
|
14
|
+
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
|
15
|
+
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
|
16
|
+
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
let str = ascii + '\x80';
|
|
20
|
+
while (str.length % 64 - 56) str += '\x00';
|
|
21
|
+
const words: number[] = [];
|
|
22
|
+
for (let i = 0; i < str.length; i++) words[i >> 2] |= str.charCodeAt(i) << ((3 - i) % 4) * 8;
|
|
23
|
+
words[words.length] = ((ascii.length * 8 / maxWord) | 0);
|
|
24
|
+
words[words.length] = (ascii.length * 8 | 0);
|
|
25
|
+
|
|
26
|
+
for (let j = 0; j < words.length;) {
|
|
27
|
+
const w = words.slice(j, j += 16);
|
|
28
|
+
const oldHash = [...hash];
|
|
29
|
+
for (let i = 0; i < 64; i++) {
|
|
30
|
+
if (i >= 16) {
|
|
31
|
+
const s0 = rightRotate(w[i - 15], 7) ^ rightRotate(w[i - 15], 18) ^ (w[i - 15] >>> 3);
|
|
32
|
+
const s1 = rightRotate(w[i - 2], 17) ^ rightRotate(w[i - 2], 19) ^ (w[i - 2] >>> 10);
|
|
33
|
+
w[i] = (w[i - 16] + s0 + w[i - 7] + s1) | 0;
|
|
34
|
+
}
|
|
35
|
+
const t1 = (hash[7] + (rightRotate(hash[4], 6) ^ rightRotate(hash[4], 11) ^ rightRotate(hash[4], 25)) + ((hash[4] & hash[5]) ^ (~hash[4] & hash[6])) + k[i] + (w[i] | 0)) | 0;
|
|
36
|
+
const t2 = ((rightRotate(hash[0], 2) ^ rightRotate(hash[0], 13) ^ rightRotate(hash[0], 22)) + ((hash[0] & hash[1]) ^ (hash[0] & hash[2]) ^ (hash[1] & hash[2]))) | 0;
|
|
37
|
+
hash = [(t1 + t2) | 0, ...hash.slice(0, 7)];
|
|
38
|
+
hash[4] = (hash[4] + t1) | 0;
|
|
39
|
+
}
|
|
40
|
+
for (let i = 0; i < 8; i++) hash[i] = (hash[i] + oldHash[i]) | 0;
|
|
41
|
+
}
|
|
42
|
+
return hash.map(h => (h >>> 0).toString(16).padStart(8, '0')).join('');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Encrypts a password
|
|
47
|
+
*/
|
|
48
|
+
export function encryptFanHash(password: string, useXor: boolean = false): string {
|
|
49
|
+
const hex = _sha256Internal(password);
|
|
50
|
+
const data: Uint8Array = new Uint8Array(hex.match(/.{1,2}/g)!.map(b => parseInt(b, 16)));
|
|
51
|
+
const n: number = 61 + (password.length % 11);
|
|
52
|
+
|
|
53
|
+
for (let k = 0; k < n; k++) {
|
|
54
|
+
const offset = k % data.length;
|
|
55
|
+
for (let i = offset; i < data.length - 1; i += 2) {
|
|
56
|
+
// Permutation (Swap)
|
|
57
|
+
[data[i], data[i + 1]] = [data[i + 1], data[i]];
|
|
58
|
+
// Bitwise XOR
|
|
59
|
+
if (useXor) {
|
|
60
|
+
const charCode = password.charCodeAt(i % password.length);
|
|
61
|
+
data[i] ^= (charCode + k) % 256;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const finalHex = Array.from(data).map(b => b.toString(16).padStart(2, '0')).join('');
|
|
66
|
+
return finalHex.match(/.{1,8}/g)!.join('.');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Verifies a stored FanHash against a raw password.
|
|
71
|
+
*/
|
|
72
|
+
export function verifyFanHash(password: string, storedHash: string, useXor: boolean = false): boolean {
|
|
73
|
+
const clean = storedHash.replace(/\./g, '');
|
|
74
|
+
const data: Uint8Array = new Uint8Array(clean.match(/.{1,2}/g)!.map(b => parseInt(b, 16)));
|
|
75
|
+
const n: number = 61 + (password.length % 11);
|
|
76
|
+
|
|
77
|
+
for (let k = n - 1; k >= 0; k--) {
|
|
78
|
+
const offset = k % data.length;
|
|
79
|
+
for (let i = offset; i < data.length - 1; i += 2) {
|
|
80
|
+
if (useXor) {
|
|
81
|
+
const charCode = password.charCodeAt(i % password.length);
|
|
82
|
+
data[i] ^= (charCode + k) % 256;
|
|
83
|
+
}
|
|
84
|
+
[data[i], data[i + 1]] = [data[i + 1], data[i]];
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return Array.from(data).map(b => b.toString(16).padStart(2, '0')).join('') === _sha256Internal(password);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* @method encrypt
|
|
92
|
+
* @method veriify
|
|
93
|
+
*/
|
|
94
|
+
export class FanHashEngine {
|
|
95
|
+
public static encrypt(password: string, useXor: boolean = false): string {
|
|
96
|
+
return encryptFanHash(password, useXor);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
public static verify(password: string, storedHash: string, useXor: boolean = false): boolean {
|
|
100
|
+
return verifyFanHash(password, storedHash, useXor);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// const myPass = "Abc@123456";
|
|
105
|
+
// const myHash = encryptFanHash(myPass, true);
|
|
106
|
+
// console.log("Hash:", myHash);
|
|
107
|
+
// console.log("Valid:", verifyFanHash(myPass, myHash, true));
|
package/components.json
CHANGED
|
@@ -1,46 +1,32 @@
|
|
|
1
1
|
{
|
|
2
2
|
"access-denied": {
|
|
3
3
|
"path": "component-templates/components/access-denied.tsx",
|
|
4
|
-
"dependencies": [
|
|
5
|
-
"lucide-react"
|
|
6
|
-
],
|
|
4
|
+
"dependencies": ["lucide-react"],
|
|
7
5
|
"devDependencies": []
|
|
8
6
|
},
|
|
9
7
|
"breadcumb": {
|
|
10
8
|
"path": "component-templates/components/breadcumb.tsx",
|
|
11
|
-
"dependencies": [
|
|
12
|
-
"lucide-react"
|
|
13
|
-
],
|
|
9
|
+
"dependencies": ["lucide-react"],
|
|
14
10
|
"devDependencies": []
|
|
15
11
|
},
|
|
16
12
|
"count-down": {
|
|
17
13
|
"path": "component-templates/hooks/count-down.ts",
|
|
18
|
-
"dependencies": [
|
|
19
|
-
"zustand"
|
|
20
|
-
],
|
|
14
|
+
"dependencies": ["zustand"],
|
|
21
15
|
"devDependencies": []
|
|
22
16
|
},
|
|
23
17
|
"count-input": {
|
|
24
18
|
"path": "component-templates/components/count-input.tsx",
|
|
25
|
-
"dependencies": [
|
|
26
|
-
"lucide-react"
|
|
27
|
-
],
|
|
19
|
+
"dependencies": ["lucide-react"],
|
|
28
20
|
"devDependencies": []
|
|
29
21
|
},
|
|
30
22
|
"button": {
|
|
31
23
|
"path": "component-templates/components/datetime-picker/button.tsx",
|
|
32
|
-
"dependencies": [
|
|
33
|
-
"class-variance-authority",
|
|
34
|
-
"@radix-ui/react-slot"
|
|
35
|
-
],
|
|
24
|
+
"dependencies": ["class-variance-authority", "@radix-ui/react-slot"],
|
|
36
25
|
"devDependencies": []
|
|
37
26
|
},
|
|
38
27
|
"calendar": {
|
|
39
28
|
"path": "component-templates/components/datetime-picker/calendar.tsx",
|
|
40
|
-
"dependencies": [
|
|
41
|
-
"lucide-react",
|
|
42
|
-
"react-day-picker"
|
|
43
|
-
],
|
|
29
|
+
"dependencies": ["lucide-react", "react-day-picker"],
|
|
44
30
|
"devDependencies": []
|
|
45
31
|
},
|
|
46
32
|
"date-input": {
|
|
@@ -50,47 +36,32 @@
|
|
|
50
36
|
},
|
|
51
37
|
"date-range-picker": {
|
|
52
38
|
"path": "component-templates/components/date-range-calendar/date-range-picker.tsx",
|
|
53
|
-
"dependencies": [
|
|
54
|
-
"@radix-ui/react-icons"
|
|
55
|
-
],
|
|
39
|
+
"dependencies": ["@radix-ui/react-icons"],
|
|
56
40
|
"devDependencies": []
|
|
57
41
|
},
|
|
58
42
|
"label": {
|
|
59
43
|
"path": "component-templates/components/datetime-picker/label.tsx",
|
|
60
|
-
"dependencies": [
|
|
61
|
-
"class-variance-authority",
|
|
62
|
-
"@radix-ui/react-label"
|
|
63
|
-
],
|
|
44
|
+
"dependencies": ["class-variance-authority", "@radix-ui/react-label"],
|
|
64
45
|
"devDependencies": []
|
|
65
46
|
},
|
|
66
47
|
"popover": {
|
|
67
48
|
"path": "component-templates/components/datetime-picker/popover.tsx",
|
|
68
|
-
"dependencies": [
|
|
69
|
-
"@radix-ui/react-popover"
|
|
70
|
-
],
|
|
49
|
+
"dependencies": ["@radix-ui/react-popover"],
|
|
71
50
|
"devDependencies": []
|
|
72
51
|
},
|
|
73
52
|
"select": {
|
|
74
53
|
"path": "component-templates/components/datetime-picker/select.tsx",
|
|
75
|
-
"dependencies": [
|
|
76
|
-
"@radix-ui/react-icons",
|
|
77
|
-
"@radix-ui/react-select"
|
|
78
|
-
],
|
|
54
|
+
"dependencies": ["@radix-ui/react-icons", "@radix-ui/react-select"],
|
|
79
55
|
"devDependencies": []
|
|
80
56
|
},
|
|
81
57
|
"switch": {
|
|
82
58
|
"path": "component-templates/components/date-range-calendar/switch.tsx",
|
|
83
|
-
"dependencies": [
|
|
84
|
-
"@radix-ui/react-switch"
|
|
85
|
-
],
|
|
59
|
+
"dependencies": ["@radix-ui/react-switch"],
|
|
86
60
|
"devDependencies": []
|
|
87
61
|
},
|
|
88
62
|
"datetime-picker": {
|
|
89
63
|
"path": "component-templates/components/datetime-picker/datetime-picker.tsx",
|
|
90
|
-
"dependencies": [
|
|
91
|
-
"date-fns",
|
|
92
|
-
"lucide-react"
|
|
93
|
-
],
|
|
64
|
+
"dependencies": ["date-fns", "lucide-react"],
|
|
94
65
|
"devDependencies": []
|
|
95
66
|
},
|
|
96
67
|
"input": {
|
|
@@ -125,16 +96,12 @@
|
|
|
125
96
|
},
|
|
126
97
|
"gradient-svg": {
|
|
127
98
|
"path": "component-templates/components/gradient-svg.tsx",
|
|
128
|
-
"dependencies": [
|
|
129
|
-
"react-svg"
|
|
130
|
-
],
|
|
99
|
+
"dependencies": ["react-svg"],
|
|
131
100
|
"devDependencies": []
|
|
132
101
|
},
|
|
133
102
|
"grid-layout": {
|
|
134
103
|
"path": "component-templates/components/grid-layout.tsx",
|
|
135
|
-
"dependencies": [
|
|
136
|
-
"tailwind-merge"
|
|
137
|
-
],
|
|
104
|
+
"dependencies": ["tailwind-merge"],
|
|
138
105
|
"devDependencies": []
|
|
139
106
|
},
|
|
140
107
|
"hydrate-guard": {
|
|
@@ -168,17 +135,12 @@
|
|
|
168
135
|
},
|
|
169
136
|
"modal": {
|
|
170
137
|
"path": "component-templates/components/modal.tsx",
|
|
171
|
-
"dependencies": [
|
|
172
|
-
"react-dom"
|
|
173
|
-
],
|
|
138
|
+
"dependencies": ["react-dom"],
|
|
174
139
|
"devDependencies": []
|
|
175
140
|
},
|
|
176
141
|
"multi-select": {
|
|
177
142
|
"path": "component-templates/components/multi-select.tsx",
|
|
178
|
-
"dependencies": [
|
|
179
|
-
"class-variance-authority",
|
|
180
|
-
"lucide-react"
|
|
181
|
-
],
|
|
143
|
+
"dependencies": ["class-variance-authority", "lucide-react"],
|
|
182
144
|
"devDependencies": []
|
|
183
145
|
},
|
|
184
146
|
"non-hydration": {
|
|
@@ -188,9 +150,7 @@
|
|
|
188
150
|
},
|
|
189
151
|
"portal": {
|
|
190
152
|
"path": "component-templates/components/portal.tsx",
|
|
191
|
-
"dependencies": [
|
|
192
|
-
"react-dom"
|
|
193
|
-
],
|
|
153
|
+
"dependencies": ["react-dom"],
|
|
194
154
|
"devDependencies": []
|
|
195
155
|
},
|
|
196
156
|
"scroll-spy": {
|
|
@@ -205,9 +165,7 @@
|
|
|
205
165
|
},
|
|
206
166
|
"single-select": {
|
|
207
167
|
"path": "component-templates/components/single-select.tsx",
|
|
208
|
-
"dependencies": [
|
|
209
|
-
"lucide-react"
|
|
210
|
-
],
|
|
168
|
+
"dependencies": ["lucide-react"],
|
|
211
169
|
"devDependencies": []
|
|
212
170
|
},
|
|
213
171
|
"stroke-circle": {
|
|
@@ -217,23 +175,17 @@
|
|
|
217
175
|
},
|
|
218
176
|
"column-table": {
|
|
219
177
|
"path": "component-templates/components/table/column-table.tsx",
|
|
220
|
-
"dependencies": [
|
|
221
|
-
"@tanstack/react-table"
|
|
222
|
-
],
|
|
178
|
+
"dependencies": ["@tanstack/react-table"],
|
|
223
179
|
"devDependencies": []
|
|
224
180
|
},
|
|
225
181
|
"data-table": {
|
|
226
182
|
"path": "component-templates/components/table/data-table.tsx",
|
|
227
|
-
"dependencies": [
|
|
228
|
-
"@tanstack/react-table"
|
|
229
|
-
],
|
|
183
|
+
"dependencies": ["@tanstack/react-table"],
|
|
230
184
|
"devDependencies": []
|
|
231
185
|
},
|
|
232
186
|
"readme": {
|
|
233
187
|
"path": "component-templates/components/table/readme.tsx",
|
|
234
|
-
"dependencies": [
|
|
235
|
-
"@tanstack/react-table"
|
|
236
|
-
],
|
|
188
|
+
"dependencies": ["@tanstack/react-table"],
|
|
237
189
|
"devDependencies": []
|
|
238
190
|
},
|
|
239
191
|
"table": {
|
|
@@ -243,9 +195,7 @@
|
|
|
243
195
|
},
|
|
244
196
|
"text-hover-effect": {
|
|
245
197
|
"path": "component-templates/components/text-hover-effect.tsx",
|
|
246
|
-
"dependencies": [
|
|
247
|
-
"motion/react"
|
|
248
|
-
],
|
|
198
|
+
"dependencies": ["motion"],
|
|
249
199
|
"devDependencies": []
|
|
250
200
|
},
|
|
251
201
|
"timout-loader": {
|
|
@@ -255,10 +205,7 @@
|
|
|
255
205
|
},
|
|
256
206
|
"toast": {
|
|
257
207
|
"path": "component-templates/components/toast.tsx",
|
|
258
|
-
"dependencies": [
|
|
259
|
-
"react-dom",
|
|
260
|
-
"lucide-react"
|
|
261
|
-
],
|
|
208
|
+
"dependencies": ["react-dom", "lucide-react"],
|
|
262
209
|
"devDependencies": []
|
|
263
210
|
},
|
|
264
211
|
"config": {
|
|
@@ -278,9 +225,7 @@
|
|
|
278
225
|
},
|
|
279
226
|
"api-service": {
|
|
280
227
|
"path": "component-templates/core/api-service.ts",
|
|
281
|
-
"dependencies": [
|
|
282
|
-
"axios"
|
|
283
|
-
],
|
|
228
|
+
"dependencies": ["axios"],
|
|
284
229
|
"devDependencies": []
|
|
285
230
|
},
|
|
286
231
|
"calculate": {
|
|
@@ -290,17 +235,12 @@
|
|
|
290
235
|
},
|
|
291
236
|
"idb": {
|
|
292
237
|
"path": "component-templates/core/idb.ts",
|
|
293
|
-
"dependencies": [
|
|
294
|
-
"idb"
|
|
295
|
-
],
|
|
238
|
+
"dependencies": ["idb"],
|
|
296
239
|
"devDependencies": []
|
|
297
240
|
},
|
|
298
241
|
"lib": {
|
|
299
242
|
"path": "component-templates/core/lib.ts",
|
|
300
|
-
"dependencies": [
|
|
301
|
-
"clsx",
|
|
302
|
-
"tailwind-merge"
|
|
303
|
-
],
|
|
243
|
+
"dependencies": ["clsx", "tailwind-merge"],
|
|
304
244
|
"devDependencies": []
|
|
305
245
|
},
|
|
306
246
|
"storage": {
|
|
@@ -315,9 +255,7 @@
|
|
|
315
255
|
},
|
|
316
256
|
"safe-action": {
|
|
317
257
|
"path": "component-templates/hooks/safe-action.ts",
|
|
318
|
-
"dependencies": [
|
|
319
|
-
"lodash"
|
|
320
|
-
],
|
|
258
|
+
"dependencies": ["lodash"],
|
|
321
259
|
"devDependencies": []
|
|
322
260
|
},
|
|
323
261
|
"spam-guard": {
|
|
@@ -327,10 +265,7 @@
|
|
|
327
265
|
},
|
|
328
266
|
"utils": {
|
|
329
267
|
"path": "component-templates/lib/utils.ts",
|
|
330
|
-
"dependencies": [
|
|
331
|
-
"clsx",
|
|
332
|
-
"tailwind-merge"
|
|
333
|
-
],
|
|
268
|
+
"dependencies": ["clsx", "tailwind-merge"],
|
|
334
269
|
"devDependencies": []
|
|
335
270
|
},
|
|
336
271
|
"feature-guard": {
|
|
@@ -345,10 +280,7 @@
|
|
|
345
280
|
},
|
|
346
281
|
"refine-provider": {
|
|
347
282
|
"path": "component-templates/providers/refine-provider.tsx",
|
|
348
|
-
"dependencies": [
|
|
349
|
-
"axios",
|
|
350
|
-
"js-cookie"
|
|
351
|
-
],
|
|
283
|
+
"dependencies": ["axios", "js-cookie"],
|
|
352
284
|
"devDependencies": []
|
|
353
285
|
},
|
|
354
286
|
"query": {
|
|
@@ -358,9 +290,7 @@
|
|
|
358
290
|
},
|
|
359
291
|
"color-by-text": {
|
|
360
292
|
"path": "component-templates/utils/colors/color-by-text.ts",
|
|
361
|
-
"dependencies": [
|
|
362
|
-
"unidecode"
|
|
363
|
-
],
|
|
293
|
+
"dependencies": ["unidecode"],
|
|
364
294
|
"devDependencies": []
|
|
365
295
|
},
|
|
366
296
|
"stripe-effect": {
|
|
@@ -370,21 +300,22 @@
|
|
|
370
300
|
},
|
|
371
301
|
"kookies": {
|
|
372
302
|
"path": "component-templates/utils/cookies/kookies.ts",
|
|
373
|
-
"dependencies": [
|
|
374
|
-
|
|
375
|
-
|
|
303
|
+
"dependencies": ["js-cookie"],
|
|
304
|
+
"devDependencies": []
|
|
305
|
+
},
|
|
306
|
+
"fanhash": {
|
|
307
|
+
"path": "component-templates/utils/hash/fanhash.ts",
|
|
308
|
+
"dependencies": [],
|
|
376
309
|
"devDependencies": []
|
|
377
310
|
},
|
|
378
311
|
"hash-aes": {
|
|
379
312
|
"path": "component-templates/utils/hash/hash-aes.ts",
|
|
380
|
-
"dependencies": [
|
|
381
|
-
"crypto-js"
|
|
382
|
-
],
|
|
313
|
+
"dependencies": ["crypto-js"],
|
|
383
314
|
"devDependencies": []
|
|
384
315
|
},
|
|
385
316
|
"simple-validate": {
|
|
386
317
|
"path": "component-templates/utils/validator/simple-validate.ts",
|
|
387
|
-
"dependencies": [],
|
|
318
|
+
"dependencies": ["@/utils/validate/simple-validate"],
|
|
388
319
|
"devDependencies": []
|
|
389
320
|
}
|
|
390
|
-
}
|
|
321
|
+
}
|