jopi-toolkit 3.0.5 → 3.0.11

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 (111) hide show
  1. package/README.md +1 -1
  2. package/dist/jk_crypto/jBundler_ifServer.d.ts +2 -2
  3. package/dist/jk_crypto/jBundler_ifServer.js +8 -8
  4. package/dist/jk_crypto/jBundler_ifServer.js.map +1 -1
  5. package/dist/jk_events/index.d.ts +5 -5
  6. package/dist/jk_events/index.js +20 -10
  7. package/dist/jk_events/index.js.map +1 -1
  8. package/dist/jk_fs/jBundler_ifBrowser.d.ts +2 -2
  9. package/dist/jk_fs/jBundler_ifBrowser.js +2 -2
  10. package/dist/jk_fs/jBundler_ifServer.d.ts +39 -3
  11. package/dist/jk_fs/jBundler_ifServer.js +152 -3
  12. package/dist/jk_fs/jBundler_ifServer.js.map +1 -1
  13. package/dist/jk_logs/index.d.ts +54 -0
  14. package/dist/jk_logs/index.js +316 -0
  15. package/dist/jk_logs/index.js.map +1 -0
  16. package/dist/jk_logs/jBundler_ifBrowser.js.map +1 -0
  17. package/dist/jk_logs/jBundler_ifServer.d.ts +2 -0
  18. package/dist/jk_logs/jBundler_ifServer.js +25 -0
  19. package/dist/jk_logs/jBundler_ifServer.js.map +1 -0
  20. package/dist/jk_schemas/index.js +2 -0
  21. package/dist/jk_schemas/index.js.map +1 -1
  22. package/dist/jk_timer/index.js +9 -4
  23. package/dist/jk_timer/index.js.map +1 -1
  24. package/dist/jk_tools/common.d.ts +29 -0
  25. package/{src/jk_tools/index.js → dist/jk_tools/common.js} +28 -21
  26. package/dist/jk_tools/common.js.map +1 -0
  27. package/dist/jk_tools/index.d.ts +1 -20
  28. package/dist/jk_tools/index.js +1 -71
  29. package/dist/jk_tools/index.js.map +1 -1
  30. package/dist/jk_tools/jBundler_ifBrowser.d.ts +1 -0
  31. package/dist/jk_tools/jBundler_ifBrowser.js +2 -0
  32. package/dist/jk_tools/jBundler_ifBrowser.js.map +1 -0
  33. package/dist/jk_tools/jBundler_ifServer.d.ts +22 -0
  34. package/dist/jk_tools/jBundler_ifServer.js +75 -0
  35. package/dist/jk_tools/jBundler_ifServer.js.map +1 -0
  36. package/package.json +11 -4
  37. package/src/jk_crypto/jBundler_ifServer.ts +8 -8
  38. package/src/jk_events/index.ts +24 -3
  39. package/src/jk_fs/jBundler_ifBrowser.ts +2 -2
  40. package/src/jk_fs/jBundler_ifServer.ts +171 -4
  41. package/src/jk_logs/index.ts +444 -0
  42. package/src/jk_logs/jBundler_ifBrowser.ts +2 -0
  43. package/src/jk_logs/jBundler_ifServer.ts +27 -0
  44. package/src/jk_tools/common.ts +99 -0
  45. package/src/jk_tools/index.ts +1 -82
  46. package/src/jk_tools/jBundler_ifBrowser.ts +1 -0
  47. package/src/jk_tools/jBundler_ifServer.ts +109 -0
  48. package/dist/jk_appResolver/common.d.ts +0 -40
  49. package/dist/jk_appResolver/common.js +0 -306
  50. package/dist/jk_appResolver/common.js.map +0 -1
  51. package/dist/jk_appResolver/index.d.ts +0 -30
  52. package/dist/jk_appResolver/index.js +0 -276
  53. package/dist/jk_appResolver/index.js.map +0 -1
  54. package/dist/jk_appResolver/jBundler_ifBrowser.js.map +0 -1
  55. package/dist/jk_appResolver/jBundler_ifServer.d.ts +0 -1
  56. package/dist/jk_appResolver/jBundler_ifServer.js +0 -9
  57. package/dist/jk_appResolver/jBundler_ifServer.js.map +0 -1
  58. package/dist/jk_linker/TypeComposite.d.ts +0 -12
  59. package/dist/jk_linker/TypeComposite.js +0 -112
  60. package/dist/jk_linker/TypeComposite.js.map +0 -1
  61. package/dist/jk_linker/arobaseType_List.d.ts +0 -44
  62. package/dist/jk_linker/arobaseType_List.js +0 -183
  63. package/dist/jk_linker/arobaseType_List.js.map +0 -1
  64. package/dist/jk_linker/arobaseTypes.d.ts +0 -45
  65. package/dist/jk_linker/arobaseTypes.js +0 -181
  66. package/dist/jk_linker/arobaseTypes.js.map +0 -1
  67. package/dist/jk_linker/binding.d.ts +0 -1
  68. package/dist/jk_linker/binding.js +0 -13
  69. package/dist/jk_linker/binding.js.map +0 -1
  70. package/dist/jk_linker/engine.d.ts +0 -119
  71. package/dist/jk_linker/engine.js +0 -553
  72. package/dist/jk_linker/engine.js.map +0 -1
  73. package/dist/jk_linker/index.d.ts +0 -1
  74. package/dist/jk_linker/index.js +0 -2
  75. package/dist/jk_linker/index.js.map +0 -1
  76. package/dist/jk_linker/install.d.ts +0 -4
  77. package/dist/jk_linker/install.js +0 -44
  78. package/dist/jk_linker/install.js.map +0 -1
  79. package/dist/jk_linker/jBundler_ifServer.d.ts +0 -3
  80. package/dist/jk_linker/jBundler_ifServer.js +0 -4
  81. package/dist/jk_linker/jBundler_ifServer.js.map +0 -1
  82. package/dist/jk_linker/modulesInitProcessor.d.ts +0 -7
  83. package/dist/jk_linker/modulesInitProcessor.js +0 -36
  84. package/dist/jk_linker/modulesInitProcessor.js.map +0 -1
  85. package/dist/jk_linker/typeChunks.d.ts +0 -15
  86. package/dist/jk_linker/typeChunks.js +0 -42
  87. package/dist/jk_linker/typeChunks.js.map +0 -1
  88. package/dist/jk_linker/typeComposites.d.ts +0 -13
  89. package/dist/jk_linker/typeComposites.js +0 -121
  90. package/dist/jk_linker/typeComposites.js.map +0 -1
  91. package/dist/jk_linker/typeEvents.d.ts +0 -5
  92. package/dist/jk_linker/typeEvents.js +0 -29
  93. package/dist/jk_linker/typeEvents.js.map +0 -1
  94. package/dist/jk_linker/typeList.d.ts +0 -30
  95. package/dist/jk_linker/typeList.js +0 -144
  96. package/dist/jk_linker/typeList.js.map +0 -1
  97. package/dist/jk_linker/typeListeners.d.ts +0 -21
  98. package/dist/jk_linker/typeListeners.js +0 -188
  99. package/dist/jk_linker/typeListeners.js.map +0 -1
  100. package/dist/jk_linker/typeReplaces.d.ts +0 -8
  101. package/dist/jk_linker/typeReplaces.js +0 -41
  102. package/dist/jk_linker/typeReplaces.js.map +0 -1
  103. package/dist/jk_registry/index.d.ts +0 -11
  104. package/dist/jk_registry/index.js +0 -36
  105. package/dist/jk_registry/index.js.map +0 -1
  106. package/src/jk_app/common.js +0 -442
  107. package/src/jk_events/index.js +0 -203
  108. package/src/jk_fs/index.js +0 -2
  109. package/src/jk_translate/index.js +0 -56
  110. /package/dist/{jk_appResolver → jk_logs}/jBundler_ifBrowser.d.ts +0 -0
  111. /package/dist/{jk_appResolver → jk_logs}/jBundler_ifBrowser.js +0 -0
@@ -1,72 +1,2 @@
1
- export function generateUUIDv4() {
2
- if (typeof crypto !== 'undefined' && crypto.randomUUID) {
3
- return crypto.randomUUID();
4
- }
5
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
6
- const r = Math.random() * 16 | 0;
7
- const v = c === 'x' ? r : (r & 0x3 | 0x8);
8
- return v.toString(16);
9
- });
10
- }
11
- export function isUUIDv4(text) {
12
- return /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(text);
13
- }
14
- export function getErrorMessage(e) {
15
- if (e instanceof Error)
16
- return e.message;
17
- return "" + e;
18
- }
19
- export function applyDefaults(source, defaults) {
20
- if (!source)
21
- source = {};
22
- return { ...defaults, ...source };
23
- }
24
- /**
25
- * Allow knowing the file path of the function calling us.
26
- */
27
- export function getCallerFilePath() {
28
- try {
29
- throw new Error("");
30
- }
31
- catch (e) {
32
- let error = e;
33
- if (!error.stack)
34
- return undefined;
35
- const stackLines = error.stack.split('\n');
36
- if (stackLines.length < 4)
37
- return undefined;
38
- // Here we have something like:
39
- // at file:///Users/johan/Projets/jopi-rewrite-workspace/__tests/jopi-ui-sample/dist/mod_sample/routes/tests/test3.page.js:4:1
40
- //
41
- let fileUrl = stackLines[3].trim();
42
- let idx = fileUrl.indexOf("file://");
43
- fileUrl = fileUrl.substring(idx);
44
- idx = fileUrl.lastIndexOf(":");
45
- fileUrl = fileUrl.substring(0, idx);
46
- idx = fileUrl.lastIndexOf(":");
47
- if (idx !== -1)
48
- fileUrl = fileUrl.substring(0, idx);
49
- return fileUrl;
50
- }
51
- }
52
- export var PriorityLevel;
53
- (function (PriorityLevel) {
54
- PriorityLevel[PriorityLevel["veryLow"] = -200] = "veryLow";
55
- PriorityLevel[PriorityLevel["low"] = -100] = "low";
56
- PriorityLevel[PriorityLevel["default"] = 0] = "default";
57
- PriorityLevel[PriorityLevel["high"] = 100] = "high";
58
- PriorityLevel[PriorityLevel["veryHigh"] = 200] = "veryHigh";
59
- })(PriorityLevel || (PriorityLevel = {}));
60
- export function sortByPriority(values) {
61
- if (values === undefined)
62
- return undefined;
63
- values.sort((a, b) => {
64
- if (a.priority < b.priority)
65
- return -1;
66
- if (a.priority > b.priority)
67
- return 1;
68
- return 0;
69
- });
70
- return values.map(v => v.value);
71
- }
1
+ export * from "./jBundler_ifServer.js";
72
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/jk_tools/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/jk_tools/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC"}
@@ -0,0 +1 @@
1
+ export * from "./common.ts";
@@ -0,0 +1,2 @@
1
+ export * from "./common.js";
2
+ //# sourceMappingURL=jBundler_ifBrowser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jBundler_ifBrowser.js","sourceRoot":"","sources":["../../src/jk_tools/jBundler_ifBrowser.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC"}
@@ -0,0 +1,22 @@
1
+ export * from "./common.ts";
2
+ export interface GithubDownloadParams {
3
+ /**
4
+ * The file or directory to download.
5
+ * Must be of type: https://github.com/ownerName/repoName/tree/branchName/path/to/folder
6
+ */
7
+ url: string;
8
+ /**
9
+ * Where to save the files.
10
+ * If downloading a directory: download the directory inside this folder.
11
+ * If downloading a file: this path is the name of the downloaded file.
12
+ */
13
+ downloadPath: string;
14
+ /**
15
+ * If true, then log the download progress.
16
+ */
17
+ log?: boolean;
18
+ }
19
+ /**
20
+ * Download a file or a directory from a GitHub repository.
21
+ */
22
+ export declare function githubDownload(params: GithubDownloadParams): Promise<void>;
@@ -0,0 +1,75 @@
1
+ import * as fs from 'node:fs/promises';
2
+ import * as path from 'node:path';
3
+ export * from "./common.js";
4
+ import * as jk_timer from "jopi-toolkit/jk_timer";
5
+ /**
6
+ * Download a file or a directory from a GitHub repository.
7
+ */
8
+ export async function githubDownload(params) {
9
+ async function downloadFile(localPath, contentUrl) {
10
+ const localDir = path.dirname(localPath);
11
+ const headers = {};
12
+ await fs.mkdir(localDir, { recursive: true });
13
+ const response = await fetch(contentUrl, { headers: headers, });
14
+ if (!response.ok) {
15
+ throw new Error(`Github download error: ${response.status} ${response.statusText}`);
16
+ }
17
+ const buffer = await response.arrayBuffer();
18
+ await fs.writeFile(localPath, Buffer.from(buffer));
19
+ if (params.log)
20
+ console.log("Downloaded", contentUrl);
21
+ }
22
+ async function fetchAndProcessContent(currentPath, downloadRoot) {
23
+ const apiUrl = `https://api.github.com/repos/${repoOwner}/${repoName}/contents/${currentPath}?ref=${branchName}`;
24
+ const headers = {};
25
+ const response = await fetch(apiUrl, { headers });
26
+ if (!response.ok) {
27
+ throw new Error(`Github download error: ${response.status} ${response.statusText}`);
28
+ }
29
+ const data = await response.json();
30
+ const isFile = !Array.isArray(data) && (data.type === 'file');
31
+ if (isFile && isFirst) {
32
+ await downloadFile(downloadRoot, data.download_url);
33
+ return;
34
+ }
35
+ const contents = Array.isArray(data) ? data : [data];
36
+ isFirst = false;
37
+ for (const item of contents) {
38
+ // Reduce, otherwise we get a "403 rate limit exceed" error.
39
+ await jk_timer.tick(gRateLimit);
40
+ if (item.type === 'file' && item.download_url) {
41
+ let itemPath = item.path;
42
+ itemPath = itemPath.substring(pathInsideRepo.length + 1);
43
+ await downloadFile(path.join(downloadRoot, itemPath), item.download_url);
44
+ }
45
+ else if (item.type === 'dir') {
46
+ await fetchAndProcessContent(item.path, downloadRoot);
47
+ }
48
+ }
49
+ }
50
+ let isFirst = true;
51
+ let url = params.url;
52
+ if (!url.startsWith("https://github.com/"))
53
+ throw new Error("Invalid URL - Must be of type https://github.com/ownerName/repoName/tree/branchName/path/to/folder");
54
+ url = url.substring("https://github.com/".length);
55
+ let parts = url.split("/").reverse();
56
+ let repoOwner = parts.pop();
57
+ let repoName = parts.pop();
58
+ let tree = parts.pop();
59
+ if (tree !== "tree")
60
+ throw new Error("Invalid URL - Must be of type https://github.com/ownerName/repoName/tree/branchName/path/to/folder");
61
+ let branchName = parts.pop();
62
+ const pathInsideRepo = parts.reverse().join("/");
63
+ await fetchAndProcessContent(pathInsideRepo, params.downloadPath);
64
+ }
65
+ function getRateLimit() {
66
+ let sLimit = process.env.GITHUB_API_LIMIT_SECONDS;
67
+ if (!sLimit)
68
+ return 50;
69
+ let res = parseInt(sLimit);
70
+ if (isNaN(res))
71
+ return 50;
72
+ return res;
73
+ }
74
+ const gRateLimit = getRateLimit();
75
+ //# sourceMappingURL=jBundler_ifServer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jBundler_ifServer.js","sourceRoot":"","sources":["../../src/jk_tools/jBundler_ifServer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,OAAO,KAAK,QAAQ,MAAM,uBAAuB,CAAC;AAsBlD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,MAA4B;IAC7D,KAAK,UAAU,YAAY,CAAC,SAAiB,EAAE,UAAkB;QAC7D,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACzC,MAAM,OAAO,GAAgB,EAAE,CAAC;QAEhC,MAAM,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAE9C,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE,EAAC,OAAO,EAAE,OAAO,GAAE,CAAC,CAAC;QAE9D,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,0BAA0B,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;QACxF,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC;QAC5C,MAAM,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;QAEnD,IAAI,MAAM,CAAC,GAAG;YAAE,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,UAAU,CAAC,CAAA;IACzD,CAAC;IAED,KAAK,UAAU,sBAAsB,CAAC,WAAmB,EAAE,YAAoB;QAC3E,MAAM,MAAM,GAAG,gCAAgC,SAAS,IAAI,QAAQ,aAAa,WAAW,QAAQ,UAAU,EAAE,CAAC;QACjH,MAAM,OAAO,GAAgB,EAAE,CAAC;QAEhC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;QAElD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,0BAA0B,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;QACxF,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnC,MAAM,MAAM,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;QAE9D,IAAI,MAAM,IAAI,OAAO,EAAE,CAAC;YACpB,MAAM,YAAY,CAAC,YAAY,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;YACpD,OAAO;QACX,CAAC;QAED,MAAM,QAAQ,GAAU,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC5D,OAAO,GAAG,KAAK,CAAC;QAEhB,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;YAC1B,4DAA4D;YAC5D,MAAM,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAEhC,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;gBAC5C,IAAI,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC;gBACzB,QAAQ,GAAG,QAAQ,CAAC,SAAS,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;gBACzD,MAAM,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;YAC7E,CAAC;iBAAM,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;gBAC7B,MAAM,sBAAsB,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;YAC1D,CAAC;QACL,CAAC;IACL,CAAC;IAED,IAAI,OAAO,GAAG,IAAI,CAAC;IAEnB,IAAI,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;IACrB,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,qBAAqB,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,oGAAoG,CAAC,CAAC;IAElK,GAAG,GAAG,GAAG,CAAC,SAAS,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAClD,IAAI,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;IAErC,IAAI,SAAS,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC;IAC5B,IAAI,QAAQ,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC;IAC3B,IAAI,IAAI,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC;IACvB,IAAI,IAAI,KAAG,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,oGAAoG,CAAC,CAAC;IACzI,IAAI,UAAU,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC;IAC7B,MAAM,cAAc,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEjD,MAAM,sBAAsB,CAAC,cAAc,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC;AACtE,CAAC;AAED,SAAS,YAAY;IACjB,IAAI,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC;IAClD,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IACvB,IAAI,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC3B,IAAI,KAAK,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IAC1B,OAAO,GAAG,CAAC;AACf,CAAC;AAED,MAAM,UAAU,GAAG,YAAY,EAAE,CAAC"}
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "3.0.5",
2
+ "version": "3.0.11",
3
3
  "name": "jopi-toolkit",
4
4
  "license": "MIT",
5
5
  "homepage": "https://github.com/johanpiquet/jopi-toolkit",
@@ -21,20 +21,23 @@
21
21
  "clean": "rm -rf ./dist .turbo tsconfig.tsbuildinfo",
22
22
  "tsc": "tsc",
23
23
  "bun-publish": "npx tsc && bun publish",
24
- "untrack": "git rm -r --cached -- ./dist/**;"
24
+ "untrack": "git rm -r --cached -- ./dist/**;",
25
+ "jopiLink": "npx jopi-mono link-add"
25
26
  },
26
27
  "devDependencies": {
28
+ "@types/adm-zip": "^0.5.7",
27
29
  "@types/bun": "latest",
28
30
  "@types/mime-types": "latest",
29
31
  "@types/node": "latest"
30
32
  },
31
33
  "dependencies": {
32
34
  "@types/ws": "^8.18.1",
35
+ "adm-zip": "^0.5.9",
33
36
  "mime-types": "^3.0.1",
34
37
  "ws": "^8.18.3"
35
38
  },
36
- "publishedDate": "11/19/2025",
37
- "publicPublishedDate": "11/19/2025",
39
+ "publishedDate": "12/8/2025",
40
+ "publicPublishedDate": "12/8/2025",
38
41
  "exports": {
39
42
  "./jk_schema": {
40
43
  "bun": "./src/jk_schemas/index.ts",
@@ -95,6 +98,10 @@
95
98
  "./jk_webSocket": {
96
99
  "bun": "./src/jk_webSocket/index.ts",
97
100
  "default": "./dist/jk_webSocket/index.js"
101
+ },
102
+ "./jk_logs": {
103
+ "bun": "./src/jk_logs/index.ts",
104
+ "default": "./dist/jk_logs/index.js"
98
105
  }
99
106
  }
100
107
  }
@@ -1,20 +1,20 @@
1
1
  import crypto from "node:crypto";
2
2
  import {isNodeJS} from "jopi-toolkit/jk_what";
3
3
 
4
- function node_md5(text: string): string {
5
- return crypto.createHash('md5').update(text).digest('hex');
4
+ function node_md5(data: string | Uint8Array): string {
5
+ return crypto.createHash('md5').update(data).digest('hex');
6
6
  }
7
7
 
8
- function node_fastHash(text: string): string {
9
- return crypto.createHash('sha256').update(text).digest('hex');
8
+ function node_fastHash(data: string | Uint8Array): string {
9
+ return crypto.createHash('sha256').update(data).digest('hex');
10
10
  }
11
11
 
12
- function bun_fastHash(text: string): string {
13
- return Bun.hash(text).toString();
12
+ function bun_fastHash(data: string | Uint8Array): string {
13
+ return Bun.hash(data, 12346).toString();
14
14
  }
15
15
 
16
- function bun_md5(text: string): string {
17
- return Bun.MD5.hash(text, "hex");
16
+ function bun_md5(data: string | Uint8Array): string {
17
+ return Bun.MD5.hash(data, "hex");
18
18
  }
19
19
 
20
20
  export const md5 = isNodeJS ? node_md5 : bun_md5;
@@ -43,6 +43,10 @@ export class EventGroup {
43
43
  }
44
44
 
45
45
  async sendAsyncEvent(eventName: string, e?: any|undefined): Promise<void> {
46
+ if (eventName[0]!=='@') {
47
+ throw new Error(`Async events ${eventName} must start with @`);
48
+ }
49
+
46
50
  if (this.evenSpy) this.evenSpy(eventName, e);
47
51
 
48
52
  let events = this.listenersFor[eventName];
@@ -135,7 +139,15 @@ interface PriorityArrayEntry<T> {
135
139
 
136
140
  //endregion
137
141
 
138
- export class StaticEvent {
142
+ export interface StaticEvent {
143
+ send<T>(data: T): T;
144
+ }
145
+
146
+ export interface SEventController {
147
+ addListener(listener: SyncEventListener): (() => void);
148
+ }
149
+
150
+ class StaticEventImpl implements StaticEvent, SEventController {
139
151
  constructor(public readonly eventName: string, private readonly eventItems: SyncEventListener[]) {
140
152
  }
141
153
 
@@ -146,10 +158,19 @@ export class StaticEvent {
146
158
 
147
159
  return data;
148
160
  }
161
+
162
+ addListener(listener: SyncEventListener): () => void {
163
+ this.eventItems.push(listener);
164
+
165
+ return () => {
166
+ let idx = this.eventItems.indexOf(listener);
167
+ if (idx >= 0) this.eventItems.splice(idx, 1);
168
+ };
169
+ }
149
170
  }
150
171
 
151
- export function createStaticEvent(eventName: string, eventItems: EventListener[]): StaticEvent {
152
- return new StaticEvent(eventName, eventItems);
172
+ export function createStaticEvent(eventName: string, eventItems: SyncEventListener[]): StaticEvent {
173
+ return new StaticEventImpl(eventName, eventItems);
153
174
  }
154
175
 
155
176
  export const defaultEventGroup = new EventGroup();
@@ -56,7 +56,7 @@ export async function writeTextToFile(filePath: string, text: string, createDir:
56
56
  throw new Error("Not implemented");
57
57
  }
58
58
 
59
- export function writeTextSyncToFile(filePath: string, text: string, createDir: boolean = true): void {
59
+ export function writeTextToFileSync(filePath: string, text: string, createDir: boolean = true): void {
60
60
  throw new Error("Not implemented");
61
61
  }
62
62
 
@@ -64,7 +64,7 @@ export function readTextFromFile(filePath: string): Promise<string> {
64
64
  throw new Error("Not implemented");
65
65
  }
66
66
 
67
- export function readTextSyncFromFile(filePath: string): string {
67
+ export function readTextFromFileSync(filePath: string): string {
68
68
  throw new Error("Not implemented");
69
69
  }
70
70
 
@@ -1,13 +1,15 @@
1
1
  // noinspection JSUnusedGlobalSymbols
2
2
 
3
3
  import fs from "node:fs/promises";
4
- import fss, {createReadStream} from "node:fs";
4
+ import fss, {createReadStream, createWriteStream} from "node:fs";
5
5
  import {fileURLToPath as n_fileURLToPath, pathToFileURL as n_pathToFileURL } from "node:url";
6
6
  import {lookup} from "mime-types";
7
7
  import {Readable} from "node:stream";
8
8
  import path from "node:path";
9
+ import {createHash} from "node:crypto";
9
10
  import {isBunJS} from "jopi-toolkit/jk_what";
10
11
  import type {DirItem, FileState} from "./common.ts";
12
+ import AdmZip from 'adm-zip';
11
13
 
12
14
  class WebToNodeReadableStreamAdapter extends Readable {
13
15
  private webStreamReader: ReadableStreamDefaultReader<any>;
@@ -170,7 +172,7 @@ export async function writeTextToFile(filePath: string, text: string, createDir:
170
172
  await fs.writeFile(filePath, text, {encoding: 'utf8', flag: 'w'});
171
173
  }
172
174
 
173
- export function writeTextSyncToFile(filePath: string, text: string, createDir: boolean = true): void {
175
+ export function writeTextToFileSync(filePath: string, text: string, createDir: boolean = true): void {
174
176
  if (createDir) {
175
177
  try {
176
178
  fss.mkdirSync(path.dirname(filePath), {recursive: true});
@@ -183,7 +185,12 @@ export function readTextFromFile(filePath: string): Promise<string> {
183
185
  return fs.readFile(filePath, 'utf8');
184
186
  }
185
187
 
186
- export function readTextSyncFromFile(filePath: string): string {
188
+ export async function readJsonFromFile<T = any>(filePath: string): Promise<T> {
189
+ let txt = await fs.readFile(filePath, 'utf8');
190
+ return JSON.parse(txt) as T;
191
+ }
192
+
193
+ export function readTextFromFileSync(filePath: string): string {
187
194
  return fss.readFileSync(filePath, 'utf8');
188
195
  }
189
196
 
@@ -287,6 +294,56 @@ export async function listDir(dirPath: string): Promise<DirItem[]> {
287
294
  return result;
288
295
  }
289
296
 
297
+ const MEGA = 1024 * 1024;
298
+
299
+ async function calcFileHash_bun(filePath: string): Promise<string|undefined> {
300
+ const file = Bun.file(filePath);
301
+ if (!await file.exists()) return undefined;
302
+
303
+ if (file.size>10 * MEGA) {
304
+ return calcFileHash_bun_streamed(file)
305
+ }
306
+
307
+ return Bun.hash(await file.arrayBuffer(), 12346).toString();
308
+ }
309
+
310
+ async function calcFileHash_bun_streamed(file: Bun.BunFile): Promise<string|undefined> {
311
+ const stream = file.stream();
312
+ const reader = stream.getReader();
313
+ const hasher = new Bun.CryptoHasher("sha256");
314
+
315
+ try {
316
+ while (true) {
317
+ const { done, value } = await reader.read();
318
+ if (done) break;
319
+ hasher.update(value);
320
+ }
321
+
322
+ return hasher.digest("hex");
323
+ } finally {
324
+ reader.releaseLock();
325
+ }
326
+ }
327
+
328
+ function calcFileHash_node(filePath: string): Promise<string|undefined> {
329
+ if (!isFile(filePath)) return Promise.resolve(undefined);
330
+
331
+ return new Promise((resolve, reject) => {
332
+ const hash = createHash('sha256');
333
+ const stream = createReadStream(filePath);
334
+ stream.on('data', (data) => hash.update(data));
335
+ stream.on('end', () => resolve(hash.digest('hex')));
336
+ stream.on('error', (error) => reject(error));
337
+ });
338
+ }
339
+
340
+ /**
341
+ * Calculate the hash of a file.
342
+ * Allows using it for HTTP ETag or another change proof.
343
+ * This version is optimized to use streams and avoid loading the whole file in memory.
344
+ */
345
+ export const calcFileHash = isBunJS ? calcFileHash_bun : calcFileHash_node;
346
+
290
347
  /**
291
348
  * Convert a simple win32 path to a linux path.
292
349
  */
@@ -294,6 +351,114 @@ export function win32ToLinuxPath(filePath: string): string {
294
351
  return filePath.replace(/\\/g, '/');
295
352
  }
296
353
 
354
+ /**
355
+ * Copy a directory recursively.
356
+ * Is optimized for large files.
357
+ */
358
+ export async function copyDirectory(srcDir: string, destDir: string): Promise<void> {
359
+ if (!await isDirectory(srcDir)) {
360
+ throw new Error(`Directory doesn't exist : ${srcDir}`);
361
+ }
362
+
363
+ await mkDir(destDir);
364
+ const entries = await fs.readdir(srcDir, { withFileTypes: true });
365
+
366
+ await Promise.all(entries.map(async (entry) => {
367
+ const srcPath = path.join(srcDir, entry.name);
368
+ const destPath = path.join(destDir, entry.name);
369
+
370
+ if (entry.isDirectory()) {
371
+ await copyDirectory(srcPath, destPath);
372
+ } else {
373
+ try {
374
+ await copyFile(srcPath, destPath);
375
+ } catch {
376
+ console.warn(`jk_fs.copyDirectory - Failed to copy file ${srcPath}`);
377
+ }
378
+ }
379
+ }));
380
+ }
381
+
382
+ /**
383
+ * Copy of a file.
384
+ * Is optimized for large files.
385
+ */
386
+ export async function copyFile(srcPath: string, destPath: string): Promise<void> {
387
+ let stat = await getFileStat(srcPath);
388
+ if (!stat) return;
389
+
390
+ // Assert the symlink exist.
391
+ if (stat.isSymbolicLink()) {
392
+ const symStat = await fs.lstat(srcPath);
393
+ if (!symStat) return;
394
+ if (!symStat.isFile()) return;
395
+ }
396
+
397
+ return new Promise<void>((resolve, reject) => {
398
+ const readStream = createReadStream(srcPath);
399
+ const writeStream = createWriteStream(destPath);
400
+
401
+ readStream.on('error', reject);
402
+ writeStream.on('error', reject);
403
+ writeStream.on('finish', resolve);
404
+
405
+ readStream.pipe(writeStream);
406
+ });
407
+ }
408
+
409
+ /**
410
+ * Unzip a .zip file in an optimized way.
411
+ * Note was using : "@types/unzipper": "^0.10.11"
412
+ * which has some bug, files/folders was forgottens.
413
+ * import * as unzipper from "unzipper";
414
+ */
415
+ /*export async function unzipFile_old(zipFilePath: string, outputDir: string): Promise<void> {
416
+ if (!await isFile(zipFilePath)) {
417
+ throw new Error(`File doesn't exist : ${zipFilePath}`);
418
+ }
419
+
420
+ if (!await isDirectory(outputDir)) {
421
+ await mkDir(outputDir);
422
+ }
423
+
424
+ await createReadStream(zipFilePath)
425
+ .pipe(unzipper.Extract({path: outputDir}))
426
+ .promise();
427
+ }*/
428
+
429
+ /**
430
+ * Unzip a .zip file in an optimized way.
431
+ */
432
+ export async function unzipFile(zipFilePath: string, outputDir: string): Promise<void> {
433
+ if (!await isFile(zipFilePath)) {
434
+ throw new Error(`File doesn't exist : ${zipFilePath}`);
435
+ }
436
+
437
+ if (!await isDirectory(outputDir)) {
438
+ await mkDir(outputDir);
439
+ }
440
+
441
+ const zip = new AdmZip(zipFilePath);
442
+ zip.extractAllTo(outputDir, true);
443
+ }
444
+
445
+ /**
446
+ * Create a temporary directory.
447
+ * Return an object containing the directory path and a cleanup function.
448
+ */
449
+ export async function createTempDir(prefix: string): Promise<{path: string, remove: ()=>Promise<void>}> {
450
+ const dirPath = await fs.mkdtemp(prefix);
451
+
452
+ return {
453
+ path: dirPath,
454
+ remove: async () => {
455
+ return fs.rm(dirPath, {recursive: true, force: true});
456
+ }
457
+ }
458
+ }
459
+
460
+ //region Node.js functions
461
+
297
462
  export const join = path.join;
298
463
  export const resolve = path.resolve;
299
464
  export const dirname = path.dirname;
@@ -305,4 +470,6 @@ export const normalize = path.normalize;
305
470
  export const basename = path.basename;
306
471
 
307
472
  export const symlink = fs.symlink;
308
- export const rename = fs.rename;
473
+ export const rename = fs.rename;
474
+
475
+ //endregion