jopi-toolkit 3.1.25 → 3.1.34

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.
Files changed (78) hide show
  1. package/dist/jk_app/common.d.ts +1 -0
  2. package/dist/jk_app/common.js +9 -2
  3. package/dist/jk_app/common.js.map +1 -1
  4. package/dist/jk_data/browserActions.d.ts +8 -0
  5. package/dist/jk_data/browserActions.js +9 -0
  6. package/dist/jk_data/browserActions.js.map +1 -0
  7. package/dist/jk_data/bundler_ifServer.d.ts +2 -0
  8. package/dist/jk_data/bundler_ifServer.js +2 -0
  9. package/dist/jk_data/bundler_ifServer.js.map +1 -0
  10. package/dist/jk_data/common.d.ts +8 -0
  11. package/dist/jk_data/common.js +2 -0
  12. package/dist/jk_data/common.js.map +1 -0
  13. package/dist/jk_data/core.d.ts +13 -0
  14. package/dist/jk_data/core.js +85 -0
  15. package/dist/jk_data/core.js.map +1 -0
  16. package/dist/jk_data/dataTableProxy.d.ts +21 -0
  17. package/dist/jk_data/dataTableProxy.js +49 -0
  18. package/dist/jk_data/dataTableProxy.js.map +1 -0
  19. package/dist/jk_data/ifServerSide.d.ts +0 -0
  20. package/dist/jk_data/ifServerSide.js +2 -0
  21. package/dist/jk_data/ifServerSide.js.map +1 -0
  22. package/dist/jk_data/index.d.ts +3 -55
  23. package/dist/jk_data/index.js +3 -105
  24. package/dist/jk_data/index.js.map +1 -1
  25. package/dist/jk_data/interfaces.d.ts +107 -0
  26. package/dist/jk_data/interfaces.js +2 -0
  27. package/dist/jk_data/interfaces.js.map +1 -0
  28. package/dist/jk_data/jBundler_common.d.ts +12 -0
  29. package/dist/jk_data/jBundler_common.js +2 -0
  30. package/dist/jk_data/jBundler_common.js.map +1 -0
  31. package/dist/jk_data/jBundler_ifBrowser.d.ts +2 -0
  32. package/dist/jk_data/jBundler_ifBrowser.js +2 -0
  33. package/dist/jk_data/jBundler_ifBrowser.js.map +1 -0
  34. package/dist/jk_data/jBundler_ifServer.1.d.ts +2 -0
  35. package/dist/jk_data/jBundler_ifServer.1.js +2 -0
  36. package/dist/jk_data/jBundler_ifServer.1.js.map +1 -0
  37. package/dist/jk_data/jBundler_ifServer.d.ts +2 -0
  38. package/dist/jk_data/jBundler_ifServer.js +2 -0
  39. package/dist/jk_data/jBundler_ifServer.js.map +1 -0
  40. package/dist/jk_data/proxy.d.ts +24 -0
  41. package/dist/jk_data/proxy.js +82 -0
  42. package/dist/jk_data/proxy.js.map +1 -0
  43. package/dist/jk_fs/jBundler_ifServer.d.ts +2 -1
  44. package/dist/jk_fs/jBundler_ifServer.js +1 -0
  45. package/dist/jk_fs/jBundler_ifServer.js.map +1 -1
  46. package/dist/jk_logs/index.js +2 -2
  47. package/dist/jk_logs/index.js.map +1 -1
  48. package/dist/jk_memcache/_logs.d.ts +1 -0
  49. package/dist/jk_memcache/_logs.js +3 -0
  50. package/dist/jk_memcache/_logs.js.map +1 -0
  51. package/dist/jk_memcache/index.d.ts +128 -0
  52. package/dist/jk_memcache/index.js +411 -0
  53. package/dist/jk_memcache/index.js.map +1 -0
  54. package/dist/jk_schemas/index.d.ts +20 -16
  55. package/dist/jk_schemas/index.js +13 -15
  56. package/dist/jk_schemas/index.js.map +1 -1
  57. package/dist/jk_tools/common.d.ts +6 -0
  58. package/dist/jk_tools/common.js +6 -0
  59. package/dist/jk_tools/common.js.map +1 -1
  60. package/dist/jk_tools/index.d.ts +1 -0
  61. package/package.json +8 -4
  62. package/src/jk_app/common.ts +12 -2
  63. package/src/jk_data/core.ts +92 -0
  64. package/src/jk_data/index.ts +3 -166
  65. package/src/jk_data/interfaces.ts +140 -0
  66. package/src/jk_data/proxy.ts +102 -0
  67. package/src/jk_fs/jBundler_ifServer.ts +1 -0
  68. package/src/jk_logs/index.ts +2 -2
  69. package/src/jk_memcache/README.md +66 -0
  70. package/src/jk_memcache/_logs.ts +3 -0
  71. package/src/jk_memcache/index.ts +494 -0
  72. package/src/jk_schemas/index.ts +29 -27
  73. package/src/jk_tools/common.ts +6 -0
  74. package/src/jk_tools/index.ts +3 -1
  75. package/src/jk_compress/index.js +0 -1
  76. package/src/jk_compress/jBundler_ifServer.js +0 -10
  77. package/src/jk_data/index.js +0 -155
  78. package/src/jk_schemas/index.js +0 -330
@@ -1 +1 @@
1
- {"version":3,"file":"common.js","sourceRoot":"","sources":["../../src/jk_tools/common.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"common.js","sourceRoot":"","sources":["../../src/jk_tools/common.ts"],"names":[],"mappings":"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"}
@@ -1 +1,2 @@
1
1
  export * from "./jBundler_ifServer.ts";
2
+ export type Translatable = string | Record<string, string>;
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "3.1.25",
2
+ "version": "3.1.34",
3
3
  "name": "jopi-toolkit",
4
4
  "license": "MIT",
5
5
  "homepage": "https://github.com/johanpiquet/jopi-toolkit",
@@ -18,7 +18,6 @@
18
18
  ],
19
19
  "scripts": {
20
20
  "jopiLink": "npx jopi-mono link-add",
21
- "bunLink": "bun link",
22
21
  "dev:build": "tsc",
23
22
  "dev:tsc-watch": "tsc --watch",
24
23
  "dev:tsc-check": "tsc --noEmit"
@@ -33,8 +32,8 @@
33
32
  "mime-types": "^3.0.1",
34
33
  "ws": "^8.18.3"
35
34
  },
36
- "publishedDate": "1/12/2026",
37
- "publicPublishedDate": "1/12/2026",
35
+ "publishedDate": "1/29/2026",
36
+ "publicPublishedDate": "1/29/2026",
38
37
  "exports": {
39
38
  "./jk_schema": {
40
39
  "types": "./src/jk_schemas/index.ts",
@@ -115,6 +114,11 @@
115
114
  "types": "./src/jk_logs/index.ts",
116
115
  "bun": "./src/jk_logs/index.ts",
117
116
  "default": "./dist/jk_logs/index.js"
117
+ },
118
+ "./jk_memcache": {
119
+ "types": "./src/jk_memcache/index.ts",
120
+ "bun": "./src/jk_memcache/index.ts",
121
+ "default": "./dist/jk_memcache/index.js"
118
122
  }
119
123
  }
120
124
  }
@@ -291,12 +291,22 @@ export function getCompiledCodeDir(): string {
291
291
  return rootDir;
292
292
  }
293
293
 
294
+ export function toSourceCodeDir(itemPath: string): string {
295
+ const compiledDir = getCompiledCodeDir();
296
+
297
+ if (itemPath.startsWith(compiledDir)) {
298
+ return getSourceCodeDir() + itemPath.substring(compiledDir.length);
299
+ }
300
+
301
+ return itemPath;
302
+ }
303
+
294
304
  export function getCompiledFilePathFor(sourceFilePath: string, replaceExtension = true): string {
295
305
  const compiledCodeDir = getCompiledCodeDir();
296
306
  const sourceCodeDir = getSourceCodeDir();
297
307
 
298
308
  if (!sourceFilePath.startsWith(sourceCodeDir)) {
299
- throw new Error("jopi-loader - The source file must be in the source code directory: " + sourceFilePath);
309
+ return sourceFilePath;
300
310
  }
301
311
 
302
312
  let filePath = sourceFilePath.substring(sourceCodeDir.length);
@@ -321,7 +331,7 @@ export function getSourcesCodePathFor(compiledFilePath: string): string {
321
331
  const sourceCodeDir = getSourceCodeDir();
322
332
 
323
333
  if (!compiledFilePath.startsWith(compiledCodeDir)) {
324
- throw new Error("jopi-loader - The compiled file must be in the compiled code directory: " + compiledFilePath);
334
+ return compiledCodeDir;
325
335
  }
326
336
 
327
337
  let filePath = jk_fs.join(sourceCodeDir, compiledFilePath.substring(compiledCodeDir.length));
@@ -0,0 +1,92 @@
1
+ import {type Schema} from "jopi-toolkit/jk_schema";
2
+ import type { JopiDataTable, JDataReadParams, JDataReadResult, JRowArrayFilter } from "./interfaces.ts";
3
+ export * from "./interfaces.ts";
4
+
5
+ //region Rows Arrays
6
+
7
+ /**
8
+ * Filter the row content according to rules.
9
+ */
10
+ export function simpleRowArrayFilter(rows: any[], params: JRowArrayFilter): JDataReadResult {
11
+ // > Apply filter.
12
+
13
+ if (params.filter) {
14
+ const f = params.filter;
15
+
16
+ rows = rows.filter(r => {
17
+ if (f.field) {
18
+ let v = r[f.field];
19
+ if (v===undefined) return false;
20
+ return String(v).includes(f.value);
21
+ } else {
22
+ for (let v of Object.values(r)) {
23
+ if (v===undefined) continue;
24
+ if (String(v).includes(f.value)) return true;
25
+ }
26
+
27
+ return false;
28
+ }
29
+ });
30
+ }
31
+
32
+ // > Apply sorting.
33
+
34
+ if (params.sorting && params.sorting.length) {
35
+ const sorting = params.sorting[0];
36
+ const sortField = sorting.id;
37
+ const sortDesc = sorting.desc;
38
+
39
+ rows = rows.sort((a, b) => {
40
+ let av = a[sortField];
41
+ let bv = b[sortField];
42
+
43
+ if (av === undefined) av = "";
44
+ if (bv === undefined) bv = "";
45
+
46
+ const avIsNumber = typeof av === "number";
47
+ const bvIsNumber = typeof bv === "number";
48
+
49
+ if (avIsNumber && bvIsNumber) {
50
+ if (sortDesc) {
51
+ return bv - av;
52
+ } else {
53
+ return av - bv;
54
+ }
55
+ } else {
56
+ const avStr = String(av);
57
+ const bvStr = String(bv);
58
+
59
+ if (sortDesc) {
60
+ return bvStr.localeCompare(avStr);
61
+ } else {
62
+ return avStr.localeCompare(bvStr);
63
+ }
64
+ }
65
+ });
66
+ }
67
+
68
+ const totalWithoutPagination = rows.length;
69
+ let offset = 0;
70
+
71
+ if (params.page) {
72
+ offset = params.page.pageIndex * params.page.pageSize;
73
+ rows = rows.slice(offset, offset + params.page.pageSize);
74
+ }
75
+
76
+ return {rows, total: totalWithoutPagination, offset};
77
+ }
78
+
79
+ //endregion
80
+
81
+ //region JDataBinding
82
+
83
+ export class JDataBinding_UseArray implements JopiDataTable {
84
+ public constructor(public readonly schema: Schema, private readonly rows: any[]) {
85
+ }
86
+
87
+ async read(params: JDataReadParams): Promise<JDataReadResult> {
88
+ return simpleRowArrayFilter(this.rows, params);
89
+ }
90
+ }
91
+
92
+ //endregion
@@ -1,166 +1,3 @@
1
- import {type Schema} from "jopi-toolkit/jk_schema";
2
-
3
- //region Rows Arrays
4
-
5
- export interface JFieldSorting {
6
- id: string;
7
- desc: boolean;
8
- }
9
-
10
- export interface JFieldFilter {
11
- value?: string | number | boolean;
12
- constraint: JFieldConstraintType;
13
- caseSensitive?: boolean;
14
- }
15
-
16
- export type JFieldConstraintType =
17
- | "$eq" // Equals
18
- | "$ne" // Not equals
19
- | "$gt" // Greater than
20
- | "$gte" // Greater than or equals
21
- | "$lt" // Less than
22
- | "$lte" // Less than or equals
23
- | "$in" // In an array of values
24
- | "$nin" // Not in an array of values
25
- | "$like" // Like search %endsWith or startsWith%
26
-
27
- export interface JRowsFilter {
28
- field?: string;
29
- value: string;
30
- }
31
-
32
- export interface JPageExtraction {
33
- pageIndex: number;
34
- pageSize: number;
35
- }
36
-
37
- export interface JRowArrayFilter {
38
- page?: JPageExtraction;
39
- filter?: JRowsFilter;
40
- sorting?: JFieldSorting[];
41
- fieldFilters?: Record<string, JFieldFilter[]>;
42
- }
43
-
44
- /**
45
- * Filter the row content according to rules.
46
- */
47
- export function simpleRowArrayFilter(rows: any[], params: JRowArrayFilter): JTableDs_ReadResult {
48
- // > Apply filter.
49
-
50
- if (params.filter) {
51
- const f = params.filter;
52
-
53
- rows = rows.filter(r => {
54
- if (f.field) {
55
- let v = r[f.field];
56
- if (v===undefined) return false;
57
- return String(v).includes(f.value);
58
- } else {
59
- for (let v of Object.values(r)) {
60
- if (v===undefined) continue;
61
- if (String(v).includes(f.value)) return true;
62
- }
63
-
64
- return false;
65
- }
66
- });
67
- }
68
-
69
- // > Apply sorting.
70
-
71
- if (params.sorting && params.sorting.length) {
72
- const sorting = params.sorting[0];
73
- const sortField = sorting.id;
74
- const sortDesc = sorting.desc;
75
-
76
- rows = rows.sort((a, b) => {
77
- let av = a[sortField];
78
- let bv = b[sortField];
79
-
80
- if (av === undefined) av = "";
81
- if (bv === undefined) bv = "";
82
-
83
- const avIsNumber = typeof av === "number";
84
- const bvIsNumber = typeof bv === "number";
85
-
86
- if (avIsNumber && bvIsNumber) {
87
- if (sortDesc) {
88
- return bv - av;
89
- } else {
90
- return av - bv;
91
- }
92
- } else {
93
- const avStr = String(av);
94
- const bvStr = String(bv);
95
-
96
- if (sortDesc) {
97
- return bvStr.localeCompare(avStr);
98
- } else {
99
- return avStr.localeCompare(bvStr);
100
- }
101
- }
102
- });
103
- }
104
-
105
- const totalWithoutPagination = rows.length;
106
- let offset = 0;
107
-
108
- if (params.page) {
109
- offset = params.page.pageIndex * params.page.pageSize;
110
- rows = rows.slice(offset, offset + params.page.pageSize);
111
- }
112
-
113
- return {rows, total: totalWithoutPagination, offset};
114
- }
115
-
116
- //endregion
117
-
118
- //region JTableDs
119
-
120
- export interface JTableDs_ReadParams extends JRowArrayFilter {
121
- }
122
-
123
- export interface JTableDs_ReadResult {
124
- rows: any[];
125
- total?: number;
126
- offset?: number;
127
- }
128
-
129
- export interface JTableDs {
130
- get name(): string;
131
- get schema(): Schema;
132
- read(params: JTableDs_ReadParams): Promise<JTableDs_ReadResult>;
133
- }
134
-
135
- export class JTableDs_UseArray implements JTableDs {
136
- public constructor(public readonly name: string, public readonly schema: Schema, private readonly rows: any[]) {
137
- }
138
-
139
- async read(params: JTableDs_ReadParams): Promise<JTableDs_ReadResult> {
140
- return simpleRowArrayFilter(this.rows, params);
141
- }
142
- }
143
-
144
- export class JTableDs_HttpProxy implements JTableDs {
145
- public constructor(public readonly name: string, private readonly url: string, public readonly schema: Schema) {
146
- }
147
-
148
- async read(params: JTableDs_ReadParams): Promise<JTableDs_ReadResult> {
149
- let toSend = {dsName: this.name, read: params};
150
-
151
- let res = await fetch(this.url, {
152
- method: "POST",
153
- headers: {"Content-Type": "application/json"},
154
- body: JSON.stringify(toSend)
155
- });
156
-
157
- if (res.status !== 200) {
158
- throw new Error(`Error while reading data source "${this.name}"`);
159
- }
160
-
161
- let asJson = await res.json();
162
- return asJson as JTableDs_ReadResult;
163
- }
164
- }
165
-
166
- //endregion
1
+ export * from "./core.ts";
2
+ export * from "./proxy.ts";
3
+ export * from "./interfaces.ts";
@@ -0,0 +1,140 @@
1
+ import { type Schema } from "jopi-toolkit/jk_schema";
2
+ import type {Translatable} from "../jk_tools";
3
+
4
+ export interface JFieldSorting {
5
+ id: string;
6
+ desc: boolean;
7
+ }
8
+
9
+ export interface IActionContext {
10
+ refresh: () => void;
11
+ }
12
+
13
+ export interface JFieldFilter {
14
+ value?: string | number | boolean;
15
+ constraint: JFieldConstraintType;
16
+ caseSensitive?: boolean;
17
+ }
18
+
19
+ export type JFieldConstraintType =
20
+ | "$eq" // Equals
21
+ | "$ne" // Not equals
22
+ | "$gt" // Greater than
23
+ | "$gte" // Greater than or equals
24
+ | "$lt" // Less than
25
+ | "$lte" // Less than or equals
26
+ | "$in" // In an array of values
27
+ | "$nin" // Not in an array of values
28
+ | "$like" // Like search %endsWith or startsWith%
29
+ ;
30
+
31
+ export interface JGlobalFilter {
32
+ field?: string;
33
+ value: string;
34
+ }
35
+
36
+ export interface JPageExtraction {
37
+ pageIndex: number;
38
+ pageSize: number;
39
+ }
40
+
41
+ export interface JRowArrayFilter {
42
+ page?: JPageExtraction;
43
+ filter?: JGlobalFilter;
44
+ sorting?: JFieldSorting[];
45
+ fieldFilters?: Record<string, JFieldFilter[]>;
46
+ }
47
+
48
+ export interface JDataReadParams extends JRowArrayFilter {
49
+ }
50
+
51
+ export interface JDataReadResult {
52
+ rows: any[];
53
+ total?: number;
54
+ offset?: number;
55
+ }
56
+
57
+ export interface JActionDef {
58
+ id: string;
59
+ title?: Translatable;
60
+ separator?: boolean;
61
+ }
62
+
63
+ export interface JopiDataTable {
64
+ readonly schema: Schema;
65
+ readonly actions?: JActionDef[];
66
+ read(params: JDataReadParams): Promise<JDataReadResult>;
67
+ }
68
+
69
+ export interface JDataTable extends JopiDataTable {
70
+ readonly name: string;
71
+ executeAction?: (rows: any[], actionName: string, context?: IActionContext) => Promise<JActionResult | void>
72
+ isActionEnabled?: (actionName: string, rows: any[], context?: IActionContext) => boolean;
73
+ }
74
+
75
+ export interface JActionPreProcessParams {
76
+ rows: any[];
77
+ context?: IActionContext;
78
+ }
79
+
80
+ export interface JActionResult {
81
+ isOk?: boolean;
82
+ errorCode?: string;
83
+ errorMessage?: string;
84
+ userMessage?: string;
85
+ data?: any;
86
+ }
87
+
88
+ export interface JActionPreProcessResult extends JActionResult {
89
+ rows?: any[];
90
+ }
91
+
92
+ export interface JActionPostProcessParams {
93
+ rows: any[];
94
+ context?: IActionContext;
95
+
96
+ data?: any[];
97
+ userMessage?: string;
98
+ }
99
+
100
+ /**
101
+ * Defines the behavior of a custom action in the browser for a Jopi table.
102
+ * allowing to hook into the action lifecycle (pre-process, server call, post-process).
103
+ */
104
+ export interface JopiTableBrowserActionItem {
105
+ /**
106
+ * Callback invoked when an error occurs during the action execution.
107
+ * This can be triggered by a failure in the `action` handler or a server-side error.
108
+ */
109
+ onError?: (params: JActionResult) => Promise<void>,
110
+
111
+ /**
112
+ * The main client-side action handler.
113
+ * - Can be used to perform checks or data transformation before sending to the server.
114
+ * - Can be used as a standalone action if `disableServerCall` is true.
115
+ * - Return `void` to proceed with the default flow.
116
+ * - Return a `JActionPreProcessResult` to control flow (e.g., stop execution if `isOk` is false) or modify data sent to server.
117
+ */
118
+ action?: (params: JActionPreProcessParams) => Promise<JActionPreProcessResult|void>,
119
+
120
+ /**
121
+ * Callback invoked after the server-side action has successfully completed.
122
+ * Useful for showing notifications, refreshing data, or triggering other UI updates.
123
+ */
124
+ afterServerCall?: (params: JActionPostProcessParams) => Promise<void>;
125
+
126
+ /**
127
+ * Function to determine if the action should be enabled/clickable.
128
+ * Based on the currently selected rows and the current action context.
129
+ * If not provided, the action is assumed to be always enabled.
130
+ */
131
+ canEnable?: (rows: any[], context?: IActionContext) => boolean;
132
+
133
+ /**
134
+ * If set to true, the framework will NOT assume there is a corresponding server-side action to call.
135
+ * Use this for actions that are purely client-side (e.g., "Copy to clipboard").
136
+ */
137
+ disableServerCall?: boolean;
138
+ }
139
+
140
+ export type JopiTableBrowserActions = Record<string, JopiTableBrowserActionItem>
@@ -0,0 +1,102 @@
1
+ import type { IActionContext, JopiTableBrowserActions, JDataReadParams, JDataReadResult, JDataTable, JActionDef, JActionResult } from "./interfaces.ts";
2
+ import { schema, type Schema } from "jopi-toolkit/jk_schema";
3
+
4
+ export interface ProxyParams {
5
+ name: string;
6
+ apiUrl: string;
7
+ actions?: JActionDef[];
8
+ schema: { meta: any; desc: any; };
9
+ }
10
+
11
+ export class Proxy implements JDataTable {
12
+ readonly name: string;
13
+ readonly schema: Schema;
14
+ readonly actions?: JActionDef[];
15
+ private readonly url: string;
16
+
17
+ readonly browserActions: JopiTableBrowserActions;
18
+
19
+ constructor(params: ProxyParams, browserActions: JopiTableBrowserActions) {
20
+ this.name = params.name;
21
+ this.url = params.apiUrl;
22
+ this.actions = params.actions;
23
+ this.schema = schema(params.schema.desc, params.schema.meta);
24
+ this.browserActions = browserActions;
25
+ }
26
+
27
+ async read(params: JDataReadParams): Promise<JDataReadResult> {
28
+ const asJson = await this.callServer({ dsName: this.name, read: params });
29
+ return asJson as JDataReadResult;
30
+ }
31
+
32
+ isActionEnabled(actionName: string, rows: any[], context?: IActionContext): boolean {
33
+ let actionEntry = this.browserActions[actionName];
34
+ if (!actionEntry) return false;
35
+ if (!actionEntry.canEnable) return true;
36
+ return actionEntry.canEnable(rows, context);
37
+ }
38
+
39
+ async executeAction(rows: any[], actionName: string, context?: IActionContext): Promise<JActionResult|void> {
40
+ async function processError(res: JActionResult | undefined) {
41
+ if (!res) return true;
42
+
43
+ if (res.isOk===false||res.errorCode||res.errorMessage) {
44
+ if (actionEntry.onError) {
45
+ await actionEntry.onError(res);
46
+ return false;
47
+ }
48
+ }
49
+
50
+ return true;
51
+ }
52
+
53
+ let actionEntry = this.browserActions[actionName];
54
+ if (!actionEntry) return;
55
+
56
+ if (actionEntry.action) {
57
+ let res = await actionEntry.action({ rows, context });
58
+
59
+ if (res) {
60
+ if (!processError(res)) return;
61
+
62
+ if (res.rows !== undefined) {
63
+ rows = res.rows;
64
+ }
65
+ }
66
+ }
67
+
68
+ if (actionEntry.disableServerCall === true) {
69
+ return;
70
+ }
71
+
72
+ let serverRes = await this.callServer({ action: actionName, rows });
73
+ if (!processError(serverRes)) return;
74
+
75
+ if (actionEntry.afterServerCall) {
76
+ await actionEntry.afterServerCall({
77
+ rows,
78
+ context,
79
+ data: serverRes?.data,
80
+ userMessage: serverRes?.userMessage
81
+ });
82
+ }
83
+ }
84
+
85
+ async callServer(data: any): Promise<any> {
86
+ let res = await fetch(this.url, {
87
+ method: "POST",
88
+ headers: {"Content-Type": "application/json"},
89
+ body: JSON.stringify(data)
90
+ });
91
+
92
+ if (res.status !== 200) {
93
+ throw new Error(`Error while calling data source "${this.name}"`);
94
+ }
95
+
96
+ return await res.json();
97
+ }
98
+ }
99
+
100
+ export function toDataTableProxy(params: ProxyParams, browserActions?: JopiTableBrowserActions): JDataTable {
101
+ return new Proxy(params, browserActions || {});
102
+ }
@@ -516,6 +516,7 @@ export const join = path.join;
516
516
  export const resolve = path.resolve;
517
517
  export const dirname = path.dirname;
518
518
  export const extname = path.extname;
519
+ export const relative = path.relative;
519
520
 
520
521
  export const sep = path.sep;
521
522
  export const isAbsolute = path.isAbsolute;
@@ -51,7 +51,7 @@ export const formater_dateTypeTitleSourceData: LogEntryFormater = (entry: LogEnt
51
51
  const date = formatDate1(entry.date);
52
52
 
53
53
  let json = entry.data ? JSON.stringify(entry.data) : "";
54
- const title = (entry.title || "").padEnd(50, " ");
54
+ const title = String(entry.title || "").padEnd(50, " ");
55
55
 
56
56
  json = entry.logger + " |>" + json;
57
57
 
@@ -71,7 +71,7 @@ export const formater_dateTypeTitleSourceData: LogEntryFormater = (entry: LogEnt
71
71
 
72
72
  export const formater_typeTitleSourceData_colored: LogEntryFormater = (entry: LogEntry) => {
73
73
  let json = entry.data ? JSON.stringify(entry.data) : "";
74
- const title = (entry.title || "").padEnd(50, " ");
74
+ const title = String(entry.title || "").padEnd(50, " ");
75
75
 
76
76
  json = entry.timeDif === undefined
77
77
  ? `${entry.logger} ${json}` : `${entry.logger} (${entry.timeDif} ms) ${json}`;
@@ -0,0 +1,66 @@
1
+
2
+ # JkMemCache (`jk_memcache`)
3
+
4
+ A robust, in-memory caching system, designed with optimization and memory management in mind.
5
+
6
+ ## Features
7
+
8
+ - **Store Anything**: Supports `string`, `ArrayBuffer`, and `Object` (automatically serialized).
9
+ - **Memory Management**:
10
+ - **Memory Limit**: Define a maximum size in bytes.
11
+ - **Count Limit**: Define a maximum number of entries.
12
+ - **Garbage Collection (GC)**: Automatic cleanup of expired items and intelligent eviction when full.
13
+ - **Smart Eviction**:
14
+ - **Importance Levels**: Mark entries as critical to prevent them from being discarded easily.
15
+ - **Access Tracking**: Tracks how often items are used to prioritize keeping frequently accessed data.
16
+ - **Expiration**: Support for TTL (Time To Live) and absolute expiration dates.
17
+
18
+ ## Usage
19
+
20
+ ### basic
21
+
22
+ ```typescript
23
+ import { JkMemCache } from '@jopi-toolkit/jk_memcache';
24
+
25
+ // Create a cache with limits
26
+ const cache = new JkMemCache({
27
+ maxCount: 1000, // Max 1000 items
28
+ maxSize: 5 * 1024 * 1024, // Max 5MB
29
+ cleanupInterval: 30000 // Cleanup every 30s
30
+ });
31
+
32
+ // Store data
33
+ cache.set('user:123', { name: 'John', role: 'admin' }, {
34
+ ttl: 60000, // Expires in 1 minute
35
+ importance: 5 // High importance (default is 1)
36
+ });
37
+
38
+ // Retrieve data
39
+ const user = cache.get('user:123'); // { name: 'John', ... }
40
+ ```
41
+
42
+ ### Options
43
+
44
+ #### Constructor Options
45
+
46
+ | Option | Type | Default | Description |
47
+ |yyy|yyy|yyy|yyy|
48
+ | `maxCount` | `number` | `Infinity` | Maximum number of items allowed in the cache. |
49
+ | `maxSize` | `number` | `50MB` | Maximum estimated memory size in bytes. |
50
+ | `cleanupInterval` | `number` | `60000` | Interval (ms) for running the background cleanup (removes expired items). |
51
+
52
+ #### `set(key, value, options)` Options
53
+
54
+ | Option | Type | Default | Description |
55
+ |yyy|yyy|yyy|yyy|
56
+ | `importance` | `number` | `1` | Importance level. Higher values protect the item from eviction when memory is full. |
57
+ | `ttl` | `number` | - | Time To Live in milliseconds. |
58
+ | `expiresAt` | `Date` \| `number` | - | Absolute date when the item expires. |
59
+
60
+ ## Eviction Strategy
61
+
62
+ When the cache reaches its memory or count limit, the Garbage Collector runs immediately upon the next `set` operation. It selects victims based on a scoring system:
63
+
64
+ 1. **Low Importance**: Items with lower importance are targeted first.
65
+ 2. **Low Usage**: Least frequently accessed items are targeted next.
66
+ 3. **Age**: Older items are targeted last if importance and usage are equal.
@@ -0,0 +1,3 @@
1
+ import {getLogger} from "jopi-toolkit/jk_logs";
2
+
3
+ export const logMemCache = getLogger("jk_memcache");