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.
- package/README.md +1 -1
- package/dist/jk_crypto/jBundler_ifServer.d.ts +2 -2
- package/dist/jk_crypto/jBundler_ifServer.js +8 -8
- package/dist/jk_crypto/jBundler_ifServer.js.map +1 -1
- package/dist/jk_events/index.d.ts +5 -5
- package/dist/jk_events/index.js +20 -10
- package/dist/jk_events/index.js.map +1 -1
- package/dist/jk_fs/jBundler_ifBrowser.d.ts +2 -2
- package/dist/jk_fs/jBundler_ifBrowser.js +2 -2
- package/dist/jk_fs/jBundler_ifServer.d.ts +39 -3
- package/dist/jk_fs/jBundler_ifServer.js +152 -3
- package/dist/jk_fs/jBundler_ifServer.js.map +1 -1
- package/dist/jk_logs/index.d.ts +54 -0
- package/dist/jk_logs/index.js +316 -0
- package/dist/jk_logs/index.js.map +1 -0
- package/dist/jk_logs/jBundler_ifBrowser.js.map +1 -0
- package/dist/jk_logs/jBundler_ifServer.d.ts +2 -0
- package/dist/jk_logs/jBundler_ifServer.js +25 -0
- package/dist/jk_logs/jBundler_ifServer.js.map +1 -0
- package/dist/jk_schemas/index.js +2 -0
- package/dist/jk_schemas/index.js.map +1 -1
- package/dist/jk_timer/index.js +9 -4
- package/dist/jk_timer/index.js.map +1 -1
- package/dist/jk_tools/common.d.ts +29 -0
- package/{src/jk_tools/index.js → dist/jk_tools/common.js} +28 -21
- package/dist/jk_tools/common.js.map +1 -0
- package/dist/jk_tools/index.d.ts +1 -20
- package/dist/jk_tools/index.js +1 -71
- package/dist/jk_tools/index.js.map +1 -1
- package/dist/jk_tools/jBundler_ifBrowser.d.ts +1 -0
- package/dist/jk_tools/jBundler_ifBrowser.js +2 -0
- package/dist/jk_tools/jBundler_ifBrowser.js.map +1 -0
- package/dist/jk_tools/jBundler_ifServer.d.ts +22 -0
- package/dist/jk_tools/jBundler_ifServer.js +75 -0
- package/dist/jk_tools/jBundler_ifServer.js.map +1 -0
- package/package.json +11 -4
- package/src/jk_crypto/jBundler_ifServer.ts +8 -8
- package/src/jk_events/index.ts +24 -3
- package/src/jk_fs/jBundler_ifBrowser.ts +2 -2
- package/src/jk_fs/jBundler_ifServer.ts +171 -4
- package/src/jk_logs/index.ts +444 -0
- package/src/jk_logs/jBundler_ifBrowser.ts +2 -0
- package/src/jk_logs/jBundler_ifServer.ts +27 -0
- package/src/jk_tools/common.ts +99 -0
- package/src/jk_tools/index.ts +1 -82
- package/src/jk_tools/jBundler_ifBrowser.ts +1 -0
- package/src/jk_tools/jBundler_ifServer.ts +109 -0
- package/dist/jk_appResolver/common.d.ts +0 -40
- package/dist/jk_appResolver/common.js +0 -306
- package/dist/jk_appResolver/common.js.map +0 -1
- package/dist/jk_appResolver/index.d.ts +0 -30
- package/dist/jk_appResolver/index.js +0 -276
- package/dist/jk_appResolver/index.js.map +0 -1
- package/dist/jk_appResolver/jBundler_ifBrowser.js.map +0 -1
- package/dist/jk_appResolver/jBundler_ifServer.d.ts +0 -1
- package/dist/jk_appResolver/jBundler_ifServer.js +0 -9
- package/dist/jk_appResolver/jBundler_ifServer.js.map +0 -1
- package/dist/jk_linker/TypeComposite.d.ts +0 -12
- package/dist/jk_linker/TypeComposite.js +0 -112
- package/dist/jk_linker/TypeComposite.js.map +0 -1
- package/dist/jk_linker/arobaseType_List.d.ts +0 -44
- package/dist/jk_linker/arobaseType_List.js +0 -183
- package/dist/jk_linker/arobaseType_List.js.map +0 -1
- package/dist/jk_linker/arobaseTypes.d.ts +0 -45
- package/dist/jk_linker/arobaseTypes.js +0 -181
- package/dist/jk_linker/arobaseTypes.js.map +0 -1
- package/dist/jk_linker/binding.d.ts +0 -1
- package/dist/jk_linker/binding.js +0 -13
- package/dist/jk_linker/binding.js.map +0 -1
- package/dist/jk_linker/engine.d.ts +0 -119
- package/dist/jk_linker/engine.js +0 -553
- package/dist/jk_linker/engine.js.map +0 -1
- package/dist/jk_linker/index.d.ts +0 -1
- package/dist/jk_linker/index.js +0 -2
- package/dist/jk_linker/index.js.map +0 -1
- package/dist/jk_linker/install.d.ts +0 -4
- package/dist/jk_linker/install.js +0 -44
- package/dist/jk_linker/install.js.map +0 -1
- package/dist/jk_linker/jBundler_ifServer.d.ts +0 -3
- package/dist/jk_linker/jBundler_ifServer.js +0 -4
- package/dist/jk_linker/jBundler_ifServer.js.map +0 -1
- package/dist/jk_linker/modulesInitProcessor.d.ts +0 -7
- package/dist/jk_linker/modulesInitProcessor.js +0 -36
- package/dist/jk_linker/modulesInitProcessor.js.map +0 -1
- package/dist/jk_linker/typeChunks.d.ts +0 -15
- package/dist/jk_linker/typeChunks.js +0 -42
- package/dist/jk_linker/typeChunks.js.map +0 -1
- package/dist/jk_linker/typeComposites.d.ts +0 -13
- package/dist/jk_linker/typeComposites.js +0 -121
- package/dist/jk_linker/typeComposites.js.map +0 -1
- package/dist/jk_linker/typeEvents.d.ts +0 -5
- package/dist/jk_linker/typeEvents.js +0 -29
- package/dist/jk_linker/typeEvents.js.map +0 -1
- package/dist/jk_linker/typeList.d.ts +0 -30
- package/dist/jk_linker/typeList.js +0 -144
- package/dist/jk_linker/typeList.js.map +0 -1
- package/dist/jk_linker/typeListeners.d.ts +0 -21
- package/dist/jk_linker/typeListeners.js +0 -188
- package/dist/jk_linker/typeListeners.js.map +0 -1
- package/dist/jk_linker/typeReplaces.d.ts +0 -8
- package/dist/jk_linker/typeReplaces.js +0 -41
- package/dist/jk_linker/typeReplaces.js.map +0 -1
- package/dist/jk_registry/index.d.ts +0 -11
- package/dist/jk_registry/index.js +0 -36
- package/dist/jk_registry/index.js.map +0 -1
- package/src/jk_app/common.js +0 -442
- package/src/jk_events/index.js +0 -203
- package/src/jk_fs/index.js +0 -2
- package/src/jk_translate/index.js +0 -56
- /package/dist/{jk_appResolver → jk_logs}/jBundler_ifBrowser.d.ts +0 -0
- /package/dist/{jk_appResolver → jk_logs}/jBundler_ifBrowser.js +0 -0
package/dist/jk_tools/index.js
CHANGED
|
@@ -1,72 +1,2 @@
|
|
|
1
|
-
export
|
|
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":"AAAA,
|
|
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 @@
|
|
|
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":"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"}
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "3.0.
|
|
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": "
|
|
37
|
-
"publicPublishedDate": "
|
|
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(
|
|
5
|
-
return crypto.createHash('md5').update(
|
|
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(
|
|
9
|
-
return crypto.createHash('sha256').update(
|
|
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(
|
|
13
|
-
return Bun.hash(
|
|
12
|
+
function bun_fastHash(data: string | Uint8Array): string {
|
|
13
|
+
return Bun.hash(data, 12346).toString();
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
function bun_md5(
|
|
17
|
-
return Bun.MD5.hash(
|
|
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;
|
package/src/jk_events/index.ts
CHANGED
|
@@ -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
|
|
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:
|
|
152
|
-
return new
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|