core-3nweb-client-lib 0.45.2 → 0.46.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.
@@ -69,8 +69,8 @@ class ASMail {
69
69
  address: this.address,
70
70
  cryptor: this.cryptor,
71
71
  getSigner,
72
- asmailResolver: makeResolver('asmail'),
73
- midResolver: makeResolver('mailerid'),
72
+ asmailResolver: makeResolver('asmail', this.logger.logError),
73
+ midResolver: makeResolver('mailerid', this.logger.logError),
74
74
  correspondents: {
75
75
  needIntroKeyFor: this.keyring.needIntroKeyFor,
76
76
  generateKeysToSend: this.keyring.generateKeysToSend,
@@ -92,12 +92,12 @@ class ASMail {
92
92
  cryptor: this.cryptor,
93
93
  getSigner,
94
94
  getStorages,
95
- asmailResolver: makeResolver('asmail'),
95
+ asmailResolver: makeResolver('asmail', this.logger.logError),
96
96
  correspondents: {
97
97
  msgDecryptor: this.keyring.decrypt,
98
98
  markOwnSendingParamsAsUsed: this.sendingParams.thisSide.setAsUsed,
99
99
  saveParamsForSendingTo: this.sendingParams.otherSides.set,
100
- midResolver: makeResolver('mailerid')
100
+ midResolver: makeResolver('mailerid', this.logger.logError)
101
101
  },
102
102
  makeNet: this.makeNet,
103
103
  logError: this.logger.logError
@@ -93,7 +93,7 @@ class Core {
93
93
  });
94
94
  try {
95
95
  // 1) init of id manager without setting fs
96
- const stepTwo = await id_manager_1.IdManager.initWithoutStore(u.address, this.makeResolver('mailerid'), this.makeNet, this.logger.logError, this.logger.logWarning);
96
+ const stepTwo = await id_manager_1.IdManager.initWithoutStore(u.address, this.makeResolver('mailerid', this.logger.logError), this.makeNet, this.logger.logError, this.logger.logWarning);
97
97
  if (!stepTwo) {
98
98
  const message = `MailerId server doesn't recognize identity ${u.address}`;
99
99
  emitBootEvent({ message, isError: true });
@@ -111,7 +111,7 @@ class Core {
111
111
  const { idManager, setupManagerStorage } = idManagerInit;
112
112
  // 3) initialize all storages
113
113
  emitBootEvent({ message: `Setting up main storage for new user` });
114
- const storesUp = await this.storages.initFreshForNewUser(u.address, idManager.getSigner, u.storeParams, u.storeSKey, this.makeNet, this.makeResolver('3nstorage'), this.logger.logError);
114
+ const storesUp = await this.storages.initFreshForNewUser(u.address, idManager.getSigner, u.storeParams, u.storeSKey, this.makeNet, this.makeResolver('3nstorage', this.logger.logError), this.logger.logError);
115
115
  if (!storesUp) {
116
116
  const message = `Main store failed to initialize for new user`;
117
117
  emitBootEvent({ message, isError: true });
@@ -141,7 +141,7 @@ class Core {
141
141
  });
142
142
  try {
143
143
  // 1) init of id manager without setting fs
144
- const stepTwo = await id_manager_1.IdManager.initWithoutStore(address, this.makeResolver('mailerid'), this.makeNet, this.logger.logError, this.logger.logWarning);
144
+ const stepTwo = await id_manager_1.IdManager.initWithoutStore(address, this.makeResolver('mailerid', this.logger.logError), this.makeNet, this.logger.logError, this.logger.logWarning);
145
145
  if (!stepTwo) {
146
146
  emitBootEvent({
147
147
  isError: true, message: `MailerId server doesn't recognize identity ${address}`
@@ -163,7 +163,7 @@ class Core {
163
163
  const { idManager, setupManagerStorage } = idManagerInit;
164
164
  // 3) initialize all storages
165
165
  emitBootEvent({ message: `Setting up main storage without local cache` });
166
- const storeDone = await this.storages.initFromRemote(address, idManager.getSigner, storageKey, this.makeNet, this.makeResolver('3nstorage'), this.logger.logError);
166
+ const storeDone = await this.storages.initFromRemote(address, idManager.getSigner, storageKey, this.makeNet, this.makeResolver('3nstorage', this.logger.logError), this.logger.logError);
167
167
  if (!storeDone) {
168
168
  emitBootEvent({ message: `Main store failed to initialize`, isError: true });
169
169
  return false;
@@ -204,7 +204,7 @@ class Core {
204
204
  });
205
205
  try {
206
206
  emitBootEvent({ message: `Unlocking data from local cache with provided password/key` });
207
- const completeStorageInit = await this.storages.startInitFromCache(address, storageKey, this.makeNet, this.makeResolver('3nstorage'), this.logger.logError);
207
+ const completeStorageInit = await this.storages.startInitFromCache(address, storageKey, this.makeNet, this.makeResolver('3nstorage', this.logger.logError), this.logger.logError);
208
208
  if (!completeStorageInit) {
209
209
  emitBootEvent({
210
210
  isError: true, message: `password/key is incorrect to decrypt local caches, or caches are damaged`
@@ -212,7 +212,7 @@ class Core {
212
212
  return false;
213
213
  }
214
214
  emitBootEvent({ message: `✔️ main storage is opened` });
215
- const idManager = await id_manager_1.IdManager.initFromCachedStore(address, await this.storages.makeSyncedFSForApp(constants_1.MAILERID_APP_NAME), this.makeResolver('mailerid'), this.makeNet, this.logger.logError, this.logger.logWarning);
215
+ const idManager = await id_manager_1.IdManager.initFromCachedStore(address, await this.storages.makeSyncedFSForApp(constants_1.MAILERID_APP_NAME), this.makeResolver('mailerid', this.logger.logError), this.makeNet, this.logger.logError, this.logger.logWarning);
216
216
  if (!idManager) {
217
217
  return false;
218
218
  }
@@ -319,7 +319,7 @@ class Core {
319
319
  try {
320
320
  const address = this.idManager.getId();
321
321
  const getSigner = this.idManager.getSigner;
322
- const asmailServerConfig = new config_1.ConfigOfASMailServer(address, getSigner, this.makeResolver('asmail'), this.makeNet());
322
+ const asmailServerConfig = new config_1.ConfigOfASMailServer(address, getSigner, this.makeResolver('asmail', this.logger.logError), this.makeNet());
323
323
  emitBootEvent({ coreApp: constants_1.KEYRINGS_APP_NAME, message: `starting initialization` });
324
324
  const keyringsSyncedFS = await this.storages.makeSyncedFSForApp(constants_1.KEYRINGS_APP_NAME);
325
325
  await this.keyrings.init(keyringsSyncedFS, this.idManager.getSigner, asmailServerConfig.makeParamSetterAndGetter('init-pub-key'));
@@ -0,0 +1,2 @@
1
+ import { PlatformDeviceFS } from './platform-devfs';
2
+ export declare function makePlatformDeviceFS(): PlatformDeviceFS;
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (C) 2026 3NSoft Inc.
4
+
5
+ This program is free software: you can redistribute it and/or modify it under
6
+ the terms of the GNU General Public License as published by the Free Software
7
+ Foundation, either version 3 of the License, or (at your option) any later
8
+ version.
9
+
10
+ This program is distributed in the hope that it will be useful, but
11
+ WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
+ See the GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License along with
16
+ this program. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.makePlatformDeviceFS = makePlatformDeviceFS;
20
+ const fs_1 = require("fs");
21
+ const file_1 = require("../lib-common/exceptions/file");
22
+ function makeFileExceptionFromNodesAndThrow(nodeExc) {
23
+ throw (0, file_1.makeFileExceptionFromCode)(nodeExc.code, nodeExc.path, undefined, 1);
24
+ }
25
+ function wrapNodeFn(nodePromisingFn) {
26
+ return function wrapOfNodePromisingFn(...args) {
27
+ return nodePromisingFn.call(undefined, ...args).catch(makeFileExceptionFromNodesAndThrow);
28
+ };
29
+ }
30
+ function makePlatformDeviceFS() {
31
+ return {
32
+ readFile: wrapNodeFn(fs_1.promises.readFile),
33
+ writeFile: wrapNodeFn(fs_1.promises.writeFile),
34
+ appendFile: wrapNodeFn(fs_1.promises.appendFile),
35
+ mkdir: wrapNodeFn(fs_1.promises.mkdir),
36
+ open: wrapNodeFn(fs_1.promises.open),
37
+ symlink: wrapNodeFn(fs_1.promises.symlink),
38
+ readlink: wrapNodeFn(fs_1.promises.readlink),
39
+ lstat: wrapNodeFn(fs_1.promises.lstat),
40
+ stat: wrapNodeFn(fs_1.promises.stat),
41
+ readdir: wrapNodeFn(fs_1.promises.readdir),
42
+ rmdir: wrapNodeFn(fs_1.promises.rmdir),
43
+ unlink: wrapNodeFn(fs_1.promises.unlink),
44
+ rename: wrapNodeFn(fs_1.promises.rename),
45
+ truncate: wrapNodeFn(fs_1.promises.truncate),
46
+ copyFile: (src, dst, overwrite = false, dstMode = '660') => {
47
+ return new Promise((resolve, reject) => {
48
+ const srcStream = (0, fs_1.createReadStream)(src);
49
+ const dstStream = (0, fs_1.createWriteStream)(dst, {
50
+ mode: parseInt(dstMode, 8),
51
+ flags: (overwrite ? 'w' : 'wx')
52
+ });
53
+ srcStream.pipe(dstStream);
54
+ dstStream.on('finish', () => {
55
+ resolve();
56
+ });
57
+ const isRejected = false;
58
+ const onErr = (err) => {
59
+ if (!isRejected) {
60
+ reject(err);
61
+ srcStream.unpipe();
62
+ }
63
+ };
64
+ srcStream.on('error', onErr);
65
+ dstStream.on('error', onErr);
66
+ });
67
+ },
68
+ };
69
+ }
70
+ Object.freeze(exports);
@@ -0,0 +1,31 @@
1
+ import type { promises as fsFns } from 'fs';
2
+ export type { Stats } from 'fs';
3
+ export type { FileException } from '../lib-common/exceptions/file';
4
+ export type FileHandle = fsFns.FileHandle;
5
+ /**
6
+ * This should be injected at globalThis.platform.device_fs
7
+ */
8
+ export interface PlatformDeviceFS {
9
+ readFile: typeof fsFns['readFile'];
10
+ writeFile: typeof fsFns['writeFile'];
11
+ appendFile: typeof fsFns['appendFile'];
12
+ mkdir: typeof fsFns['mkdir'];
13
+ open: typeof fsFns['open'];
14
+ symlink: typeof fsFns['symlink'];
15
+ readlink: typeof fsFns['readlink'];
16
+ lstat: typeof fsFns['lstat'];
17
+ stat: typeof fsFns['stat'];
18
+ readdir: typeof fsFns['readdir'];
19
+ rmdir: typeof fsFns['rmdir'];
20
+ unlink: typeof fsFns['unlink'];
21
+ rename: typeof fsFns['rename'];
22
+ truncate: typeof fsFns['truncate'];
23
+ /**
24
+ * This pipes source file into destination file.
25
+ * @param src
26
+ * @param dst
27
+ * @param overwrite
28
+ * @return a promise, resolvable when piping completes.
29
+ */
30
+ copyFile(src: string, dst: string, overwrite?: boolean, dstMode?: string): Promise<void>;
31
+ }
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (C) 2026 3NSoft Inc.
4
+
5
+ This program is free software: you can redistribute it and/or modify it under
6
+ the terms of the GNU General Public License as published by the Free Software
7
+ Foundation, either version 3 of the License, or (at your option) any later
8
+ version.
9
+
10
+ This program is distributed in the hope that it will be useful, but
11
+ WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
+ See the GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License along with
16
+ this program. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ Object.freeze(exports);
@@ -19,7 +19,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
19
19
  exports.dohAt = dohAt;
20
20
  const https = require("https");
21
21
  const request_utils_1 = require("./request-utils");
22
- const service_locator_1 = require("./service-locator");
22
+ const dns_1 = require("dns");
23
23
  function dohAt(dohServerUrl) {
24
24
  async function resolveTxt(domain) {
25
25
  const answer = await sendDohQuestion(dohServerUrl, domain, 'TXT');
@@ -42,27 +42,27 @@ async function sendDohQuestion(serverUrl, domain, type) {
42
42
  const reply = await (0, request_utils_1.processRequest)(opts => https.request(opts), httpsOpts, opts, undefined)
43
43
  .catch((exc) => {
44
44
  if (exc.type === 'connect') {
45
- throw { code: service_locator_1.DNS_ERR_CODE.ECONNREFUSED, hostname: domain, cause: exc };
45
+ throw { code: dns_1.CONNREFUSED, hostname: domain, cause: exc };
46
46
  }
47
47
  else {
48
- throw { code: service_locator_1.DNS_ERR_CODE.ESERVFAIL, hostname: domain, cause: exc };
48
+ throw { code: dns_1.SERVFAIL, hostname: domain, cause: exc };
49
49
  }
50
50
  });
51
51
  const { status, data } = reply;
52
52
  if (status !== 200) {
53
53
  throw {
54
- code: service_locator_1.DNS_ERR_CODE.ESERVFAIL, hostname: domain,
54
+ code: dns_1.SERVFAIL, hostname: domain,
55
55
  message: `status ${reply.status} from DoH server`
56
56
  };
57
57
  }
58
58
  if (data.Status !== 0) {
59
- throw { code: service_locator_1.DNS_ERR_CODE.NOTFOUND, hostname: domain };
59
+ throw { code: dns_1.NOTFOUND, hostname: domain };
60
60
  }
61
61
  if (data.Answer) {
62
62
  return data.Answer;
63
63
  }
64
64
  else {
65
- throw { code: service_locator_1.DNS_ERR_CODE.NODATA, hostname: domain };
65
+ throw { code: dns_1.NODATA, hostname: domain };
66
66
  }
67
67
  }
68
68
  Object.freeze(exports);
@@ -58,6 +58,7 @@ Log level: error.${msg ? `
58
58
  ${msg}` : ''}
59
59
  ${(0, error_1.stringifyErr)(err)}`;
60
60
  await appendLog(entry, now);
61
+ console.error(`[duplicating log message into console] ${entry}`);
61
62
  }
62
63
  catch (err2) {
63
64
  console.error(err);
@@ -130,7 +130,7 @@ async function checkSignup(client, signupURL, signupToken) {
130
130
  const srvLocator = (0, service_locator_1.makeServiceLocator)({ resolveTxt: dns_1.promises.resolveTxt }, (0, doh_1.dohAt)(`https://cloudflare-dns.com/dns-query`), (0, doh_1.dohAt)(`https://dns.google/resolve`));
131
131
  async function checkUserDomainDNS(service, domain) {
132
132
  try {
133
- const serviceUrl = await (srvLocator(service))(`u@${domain}`);
133
+ const serviceUrl = await (srvLocator(service, noop))(`u@${domain}`);
134
134
  return {
135
135
  service,
136
136
  isOk: true,
@@ -166,4 +166,5 @@ async function checkUserDomainDNS(service, domain) {
166
166
  };
167
167
  }
168
168
  }
169
+ async function noop() { }
169
170
  Object.freeze(exports);
@@ -2,6 +2,7 @@ import { NetClient } from './request-utils';
2
2
  import { promises as dnsPromises } from 'dns';
3
3
  import { StorageRootRoute } from '../lib-common/service-api/3nstorage/root-route';
4
4
  import { ASMailRootRoute } from '../lib-common/service-api/asmail/root-route';
5
+ import { LogError } from './logging/log-to-file';
5
6
  type SignedLoad = web3n.keys.SignedLoad;
6
7
  /**
7
8
  * This returns a promise, resolvable to ASMailRootRoute object.
@@ -26,15 +27,8 @@ export declare function mailerIdInfoAt(client: NetClient, url: string): Promise<
26
27
  * @param url
27
28
  */
28
29
  export declare function storageInfoAt(client: NetClient, url: string): Promise<StorageRootRoute>;
29
- export declare const DNS_ERR_CODE: {
30
- NODATA: string;
31
- NOTFOUND: string;
32
- ESERVFAIL: string;
33
- ECONNREFUSED: string;
34
- ETIMEOUT: string;
35
- };
36
30
  export type ServiceTypeDNSLabel = 'mailerid' | 'asmail' | '3nstorage';
37
- export type ServiceLocatorMaker = (serviceLabel: ServiceTypeDNSLabel) => ServiceLocator;
31
+ export type ServiceLocatorMaker = (serviceLabel: ServiceTypeDNSLabel, logError: LogError) => ServiceLocator;
38
32
  export type ServiceLocator = (address: string) => Promise<string>;
39
33
  export interface DnsResolver {
40
34
  resolveTxt: (typeof dnsPromises)['resolveTxt'];
@@ -16,13 +16,13 @@
16
16
  this program. If not, see <http://www.gnu.org/licenses/>.
17
17
  */
18
18
  Object.defineProperty(exports, "__esModule", { value: true });
19
- exports.DNS_ERR_CODE = void 0;
20
19
  exports.asmailInfoAt = asmailInfoAt;
21
20
  exports.mailerIdInfoAt = mailerIdInfoAt;
22
21
  exports.storageInfoAt = storageInfoAt;
23
22
  exports.makeServiceLocator = makeServiceLocator;
24
23
  exports.getMailerIdInfoFor = getMailerIdInfoFor;
25
24
  const jwkeys_1 = require("../lib-common/jwkeys");
25
+ const dns_1 = require("dns");
26
26
  const runtime_1 = require("../lib-common/exceptions/runtime");
27
27
  const http_1 = require("../lib-common/exceptions/http");
28
28
  async function readJSONLocatedAt(client, url) {
@@ -216,22 +216,15 @@ function getRecordAtStartOf(txt) {
216
216
  value: txt
217
217
  };
218
218
  }
219
- exports.DNS_ERR_CODE = {
220
- NODATA: 'ENODATA',
221
- NOTFOUND: 'ENOTFOUND',
222
- ESERVFAIL: 'ESERVFAIL',
223
- ECONNREFUSED: 'ECONNREFUSED',
224
- ETIMEOUT: 'ETIMEOUT'
225
- };
226
- Object.freeze(exports.DNS_ERR_CODE);
227
219
  function makeServiceLocator(...resolvers) {
228
220
  if (resolvers.length === 0) {
229
221
  throw Error(`no DNS resolvers given`);
230
222
  }
231
- return serviceLabel => async (address) => {
223
+ return (serviceLabel, logError) => async (address) => {
232
224
  const domain = domainOfAddress(address);
233
225
  let prevConnectionExc = undefined;
234
- for (const resolver of resolvers) {
226
+ for (let i = 0; i < resolvers.length; i += 1) {
227
+ const resolver = resolvers[i];
235
228
  try {
236
229
  const txtRecords = await resolver.resolveTxt(domain);
237
230
  const recValue = extractPair(txtRecords, serviceLabel);
@@ -242,25 +235,25 @@ function makeServiceLocator(...resolvers) {
242
235
  return url;
243
236
  }
244
237
  catch (err) {
238
+ await logError(err, `Resolver ${i + 1} fails to get TXT records of ${domain}`);
245
239
  const { code, hostname, message } = err;
246
- if (code === exports.DNS_ERR_CODE.NODATA) {
240
+ if (code === dns_1.NODATA) {
247
241
  throw noServiceRecordExc(address);
248
242
  }
249
- else if ((code === exports.DNS_ERR_CODE.ESERVFAIL)
250
- || (code === exports.DNS_ERR_CODE.ECONNREFUSED)
251
- || (code === exports.DNS_ERR_CODE.ETIMEOUT)) {
243
+ else if ((code === dns_1.SERVFAIL)
244
+ || (code === dns_1.CONNREFUSED)
245
+ || (code === dns_1.TIMEOUT)) {
252
246
  if (!prevConnectionExc) {
253
247
  prevConnectionExc = noConnectionExc({ code, hostname, message });
254
248
  }
255
249
  }
256
- else if ((code === exports.DNS_ERR_CODE.NOTFOUND) || hostname) {
250
+ else if ((code === dns_1.NOTFOUND) || hostname) {
257
251
  throw domainNotFoundExc(address, { code, hostname, message });
258
252
  }
259
253
  else {
260
254
  if (!prevConnectionExc) {
261
255
  prevConnectionExc = err;
262
256
  }
263
- throw err;
264
257
  }
265
258
  }
266
259
  }
@@ -1,22 +1,11 @@
1
- import * as fs from 'fs';
2
1
  import { Readable, Writable } from 'stream';
3
- export type { Stats } from 'fs';
4
- export type { FileException } from './exceptions/file';
5
- export type FileHandle = fs.promises.FileHandle;
6
- export declare const readFile: typeof fs.promises.readFile;
7
- export declare const writeFile: typeof fs.promises.writeFile;
8
- export declare const appendFile: typeof fs.promises.appendFile;
9
- export declare const mkdir: typeof fs.promises.mkdir;
10
- export declare const open: typeof fs.promises.open;
11
- export declare const symlink: typeof fs.promises.symlink;
12
- export declare const readlink: typeof fs.promises.readlink;
13
- export declare const lstat: typeof fs.promises.lstat;
14
- export declare const stat: typeof fs.promises.stat;
15
- export declare const readdir: typeof fs.promises.readdir;
16
- export declare const rmdir: typeof fs.promises.rmdir;
17
- export declare const unlink: typeof fs.promises.unlink;
18
- export declare const rename: typeof fs.promises.rename;
19
- export declare const truncate: typeof fs.promises.truncate;
2
+ import type { FileHandle } from '../injected-globals/platform-devfs';
3
+ export type { FileHandle, FileException, Stats } from '../injected-globals/platform-devfs';
4
+ /**
5
+ * fs functions follow node's type, and are injected via global object to allow injection in
6
+ * non-node environments, like Android or browser.
7
+ */
8
+ export declare const appendFile: typeof import("fs/promises").appendFile, lstat: typeof import("fs/promises").lstat, mkdir: typeof import("fs/promises").mkdir, open: typeof import("fs/promises").open, readFile: typeof import("fs/promises").readFile, readdir: typeof import("fs/promises").readdir, readlink: typeof import("fs/promises").readlink, rename: typeof import("fs/promises").rename, rmdir: typeof import("fs/promises").rmdir, stat: typeof import("fs/promises").stat, symlink: typeof import("fs/promises").symlink, truncate: typeof import("fs/promises").truncate, unlink: typeof import("fs/promises").unlink, writeFile: typeof import("fs/promises").writeFile, copyFile: (src: string, dst: string, overwrite?: boolean, dstMode?: string) => Promise<void>;
20
9
  /**
21
10
  * @param fh is an open file handle
22
11
  * @param pos is a position in the file, from which reading should start
@@ -53,16 +42,6 @@ export declare function createEmptyFile(filePath: string, fileSize: number, keep
53
42
  * or false, if it does not.
54
43
  */
55
44
  export declare function existsFolder(path: string): Promise<boolean>;
56
- /**
57
- * @param path
58
- * @return true, if given path represents directory, or false, if it does not.
59
- */
60
- export declare function existsFolderSync(path: string): boolean;
61
- /**
62
- * @param path
63
- * @return true, if given path represents file, or false, if it does not.
64
- */
65
- export declare function existsFileSync(path: string): boolean;
66
45
  /**
67
46
  * @param filePath
68
47
  * @return a promise, resolvable to file's size.
@@ -126,26 +105,6 @@ export declare function rmDirWithContent(folder: string): Promise<void>;
126
105
  * sink completes.
127
106
  */
128
107
  export declare function streamFromFile(filePath: string, pos: number, len: number, sink: Writable, bufSize: number): Promise<void>;
129
- /**
130
- * This pipes source file into destination file.
131
- * @param src
132
- * @param dst
133
- * @param overwrite
134
- * @return a promise, resolvable when piping completes.
135
- */
136
- export declare function copyFile(src: string, dst: string, overwrite?: boolean, dstMode?: string): Promise<void>;
137
- /**
138
- * This copies tree of files from source to destination folders.
139
- * Target folders may exist in a destination tree.
140
- * Objects that are neither files, nor folders, are ignored.
141
- * @param src
142
- * @param dst
143
- * @param fileOverwrite when set to true, allows to overwrite files in a
144
- * destination tree. Otherwise, exception is thrown on already existing files.
145
- * @return a promise resolvable when the whole tree is copied from source to
146
- * destination.
147
- */
148
- export declare function copyTree(src: string, dst: string, fileOverwrite?: boolean): Promise<void>;
149
108
  /**
150
109
  * This function checks that given folder exists. If folder is not present,
151
110
  * it is created, recreating whole folder tree, if needed.
@@ -15,14 +15,13 @@
15
15
  You should have received a copy of the GNU General Public License along with
16
16
  this program. If not, see <http://www.gnu.org/licenses/>.
17
17
  */
18
+ var _a;
18
19
  Object.defineProperty(exports, "__esModule", { value: true });
19
- exports.truncate = exports.rename = exports.unlink = exports.rmdir = exports.readdir = exports.stat = exports.lstat = exports.readlink = exports.symlink = exports.open = exports.mkdir = exports.appendFile = exports.writeFile = exports.readFile = void 0;
20
+ exports.copyFile = exports.writeFile = exports.unlink = exports.truncate = exports.symlink = exports.stat = exports.rmdir = exports.rename = exports.readlink = exports.readdir = exports.readFile = exports.open = exports.mkdir = exports.lstat = exports.appendFile = void 0;
20
21
  exports.readToBuf = readToBuf;
21
22
  exports.writeFromBuf = writeFromBuf;
22
23
  exports.createEmptyFile = createEmptyFile;
23
24
  exports.existsFolder = existsFolder;
24
- exports.existsFolderSync = existsFolderSync;
25
- exports.existsFileSync = existsFileSync;
26
25
  exports.getFileSize = getFileSize;
27
26
  exports.getFolderContentSize = getFolderContentSize;
28
27
  exports.write = write;
@@ -31,40 +30,18 @@ exports.streamToExistingFile = streamToExistingFile;
31
30
  exports.read = read;
32
31
  exports.rmDirWithContent = rmDirWithContent;
33
32
  exports.streamFromFile = streamFromFile;
34
- exports.copyFile = copyFile;
35
- exports.copyTree = copyTree;
36
33
  exports.ensureFolderExists = ensureFolderExists;
37
- const fs = require("fs");
38
- const fs_1 = require("fs");
39
34
  const file_1 = require("./exceptions/file");
40
35
  const synced_1 = require("./processes/synced");
41
36
  const deferred_1 = require("./processes/deferred");
42
37
  const bytes_fifo_buffer_1 = require("./byte-streaming/bytes-fifo-buffer");
43
38
  const buffer_utils_1 = require("./buffer-utils");
44
- const path_1 = require("path");
45
- function makeFileExceptionFromNodesAndThrow(nodeExc) {
46
- throw (0, file_1.makeFileExceptionFromCode)(nodeExc.code, nodeExc.path, undefined, 1);
47
- }
48
- function wrapNodeFn(nodePromisingFn) {
49
- return function wrapOfNodePromisingFn(...args) {
50
- return nodePromisingFn.call(undefined, ...args).catch(makeFileExceptionFromNodesAndThrow);
51
- };
52
- }
53
39
  function noop() { }
54
- exports.readFile = wrapNodeFn(fs.promises.readFile);
55
- exports.writeFile = wrapNodeFn(fs.promises.writeFile);
56
- exports.appendFile = wrapNodeFn(fs.promises.appendFile);
57
- exports.mkdir = wrapNodeFn(fs.promises.mkdir);
58
- exports.open = wrapNodeFn(fs.promises.open);
59
- exports.symlink = wrapNodeFn(fs.promises.symlink);
60
- exports.readlink = wrapNodeFn(fs.promises.readlink);
61
- exports.lstat = wrapNodeFn(fs.promises.lstat);
62
- exports.stat = wrapNodeFn(fs.promises.stat);
63
- exports.readdir = wrapNodeFn(fs.promises.readdir);
64
- exports.rmdir = wrapNodeFn(fs.promises.rmdir);
65
- exports.unlink = wrapNodeFn(fs.promises.unlink);
66
- exports.rename = wrapNodeFn(fs.promises.rename);
67
- exports.truncate = wrapNodeFn(fs.promises.truncate);
40
+ /**
41
+ * fs functions follow node's type, and are injected via global object to allow injection in
42
+ * non-node environments, like Android or browser.
43
+ */
44
+ _a = globalThis.platform.device_fs, exports.appendFile = _a.appendFile, exports.lstat = _a.lstat, exports.mkdir = _a.mkdir, exports.open = _a.open, exports.readFile = _a.readFile, exports.readdir = _a.readdir, exports.readlink = _a.readlink, exports.rename = _a.rename, exports.rmdir = _a.rmdir, exports.stat = _a.stat, exports.symlink = _a.symlink, exports.truncate = _a.truncate, exports.unlink = _a.unlink, exports.writeFile = _a.writeFile, exports.copyFile = _a.copyFile;
68
45
  /**
69
46
  * @param fh is an open file handle
70
47
  * @param pos is a position in the file, from which reading should start
@@ -164,46 +141,6 @@ async function existsFolder(path) {
164
141
  throw e;
165
142
  }
166
143
  }
167
- /**
168
- * @param path
169
- * @return true, if given path represents directory, or false, if it does not.
170
- */
171
- function existsFolderSync(path) {
172
- try {
173
- if ((0, fs_1.statSync)(path).isDirectory()) {
174
- return true;
175
- }
176
- else {
177
- throw (0, file_1.makeFileException)('notDirectory', path);
178
- }
179
- }
180
- catch (e) {
181
- if (e.code === file_1.Code.notFound) {
182
- return false;
183
- }
184
- throw e;
185
- }
186
- }
187
- /**
188
- * @param path
189
- * @return true, if given path represents file, or false, if it does not.
190
- */
191
- function existsFileSync(path) {
192
- try {
193
- if ((0, fs_1.statSync)(path).isFile()) {
194
- return true;
195
- }
196
- else {
197
- throw (0, file_1.makeFileException)('notFile', path);
198
- }
199
- }
200
- catch (e) {
201
- if (e.code === file_1.Code.notFound) {
202
- return false;
203
- }
204
- throw e;
205
- }
206
- }
207
144
  /**
208
145
  * @param filePath
209
146
  * @return a promise, resolvable to file's size.
@@ -485,73 +422,6 @@ async function streamFromFile(filePath, pos, len, sink, bufSize) {
485
422
  byteCount += buf.length;
486
423
  }
487
424
  }
488
- /**
489
- * This pipes source file into destination file.
490
- * @param src
491
- * @param dst
492
- * @param overwrite
493
- * @return a promise, resolvable when piping completes.
494
- */
495
- function copyFile(src, dst, overwrite = false, dstMode = '660') {
496
- return new Promise((resolve, reject) => {
497
- const srcStream = (0, fs_1.createReadStream)(src);
498
- const dstStream = (0, fs_1.createWriteStream)(dst, {
499
- mode: parseInt(dstMode, 8),
500
- flags: (overwrite ? 'w' : 'wx')
501
- });
502
- srcStream.pipe(dstStream);
503
- dstStream.on('finish', () => {
504
- resolve();
505
- });
506
- const isRejected = false;
507
- const onErr = (err) => {
508
- if (!isRejected) {
509
- reject(err);
510
- srcStream.unpipe();
511
- }
512
- };
513
- srcStream.on('error', onErr);
514
- dstStream.on('error', onErr);
515
- });
516
- }
517
- /**
518
- * This copies tree of files from source to destination folders.
519
- * Target folders may exist in a destination tree.
520
- * Objects that are neither files, nor folders, are ignored.
521
- * @param src
522
- * @param dst
523
- * @param fileOverwrite when set to true, allows to overwrite files in a
524
- * destination tree. Otherwise, exception is thrown on already existing files.
525
- * @return a promise resolvable when the whole tree is copied from source to
526
- * destination.
527
- */
528
- async function copyTree(src, dst, fileOverwrite = false) {
529
- // destination folder, non-exclusively
530
- await (0, exports.mkdir)(dst, { recursive: true })
531
- .catch(async (exc) => {
532
- if (!exc.alreadyExists) {
533
- throw exc;
534
- }
535
- });
536
- // copy files and folders from src folder
537
- const srcFNames = await (0, exports.readdir)(src);
538
- const cpTasks = [];
539
- for (const fName of srcFNames) {
540
- const srcPath = (0, path_1.join)(src, fName);
541
- const dstPath = (0, path_1.join)(dst, fName);
542
- const task = (0, exports.stat)(srcPath)
543
- .then((stats) => {
544
- if (stats.isFile()) {
545
- return copyFile(srcPath, dstPath, fileOverwrite);
546
- }
547
- else if (stats.isDirectory()) {
548
- return copyTree(srcPath, dstPath, fileOverwrite);
549
- }
550
- });
551
- cpTasks.push(task);
552
- }
553
- await Promise.all(cpTasks);
554
- }
555
425
  /**
556
426
  * This function checks that given folder exists. If folder is not present,
557
427
  * it is created, recreating whole folder tree, if needed.
@@ -14,3 +14,4 @@ export { makeLogger } from './lib-client/logging/log-to-file';
14
14
  export declare const SYSTEM_DOMAIN = "3nweb.computer";
15
15
  export { checkServicesStartingFromSignup } from './lib-client/service-checks';
16
16
  export { dohAt } from './lib-client/doh';
17
+ export * as injectOnNode from './injected-globals/inject-on-node';
@@ -30,7 +30,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
30
30
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
31
31
  };
32
32
  Object.defineProperty(exports, "__esModule", { value: true });
33
- exports.dohAt = exports.checkServicesStartingFromSignup = exports.SYSTEM_DOMAIN = exports.makeLogger = exports.DeviceFS = exports.sysFolders = exports.appDirs = exports.makeNetClient = exports.makeServiceLocator = exports.ASMail = exports.SignIn = exports.reverseDomain = exports.Storages = exports.IdManager = exports.SignUp = void 0;
33
+ exports.injectOnNode = exports.dohAt = exports.checkServicesStartingFromSignup = exports.SYSTEM_DOMAIN = exports.makeLogger = exports.DeviceFS = exports.sysFolders = exports.appDirs = exports.makeNetClient = exports.makeServiceLocator = exports.ASMail = exports.SignIn = exports.reverseDomain = exports.Storages = exports.IdManager = exports.SignUp = void 0;
34
34
  __exportStar(require("./core"), exports);
35
35
  var sign_up_1 = require("./core/startup/sign-up");
36
36
  Object.defineProperty(exports, "SignUp", { enumerable: true, get: function () { return sign_up_1.SignUp; } });
@@ -60,4 +60,5 @@ var service_checks_1 = require("./lib-client/service-checks");
60
60
  Object.defineProperty(exports, "checkServicesStartingFromSignup", { enumerable: true, get: function () { return service_checks_1.checkServicesStartingFromSignup; } });
61
61
  var doh_1 = require("./lib-client/doh");
62
62
  Object.defineProperty(exports, "dohAt", { enumerable: true, get: function () { return doh_1.dohAt; } });
63
+ exports.injectOnNode = require("./injected-globals/inject-on-node");
63
64
  Object.freeze(exports);
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  /*
3
- Copyright (C) 2016, 2020 - 2022, 2025 3NSoft Inc.
3
+ Copyright (C) 2016, 2020 - 2022, 2025 - 2026 3NSoft Inc.
4
4
 
5
5
  This program is free software: you can redistribute it and/or modify it under
6
6
  the terms of the GNU General Public License as published by the Free Software
@@ -17,6 +17,11 @@
17
17
  */
18
18
  Object.defineProperty(exports, "__esModule", { value: true });
19
19
  const jasmine = require("jasmine");
20
+ const inject_on_node_1 = require("../injected-globals/inject-on-node");
21
+ // injecting global's expected to be on node
22
+ globalThis.platform = {
23
+ device_fs: (0, inject_on_node_1.makePlatformDeviceFS)()
24
+ };
20
25
  const jas = new jasmine({});
21
26
  const specsFromCLI = [];
22
27
  for (let i = 2; i < process.argv.length; i += 1) {
@@ -60,7 +60,7 @@ describe('ObjFolders without timed generations', () => {
60
60
  await (0, async_fs_node_1.rmDirWithContent)(TEST_DATA);
61
61
  });
62
62
  (0, jasmine_utils_1.itCond)(`static folder content`, async () => {
63
- expect((0, async_fs_node_1.existsFolderSync)((0, path_1.join)(TEST_DATA, ACCESS_DIR))).toBeTrue();
63
+ expect(await (0, async_fs_node_1.existsFolder)((0, path_1.join)(TEST_DATA, ACCESS_DIR))).toBeTrue();
64
64
  const cfg = await readJSONFile((0, path_1.join)(TEST_DATA, CONFIG_FILE));
65
65
  expect(cfg.charsInSplit).withContext('default config value').toBe(charsInSplit);
66
66
  expect(cfg.numOfSplits).withContext('default config value').toBe(numOfSplits);
@@ -68,13 +68,13 @@ describe('ObjFolders without timed generations', () => {
68
68
  (0, jasmine_utils_1.itCond)(`null id for root object`, async () => {
69
69
  const rootObjPath = (0, path_1.join)(objsDir, ROOT_OBJ_DIR);
70
70
  // behaviour with missing obj folder and no creation
71
- expect((0, async_fs_node_1.existsFolderSync)(rootObjPath)).not.toBeTrue();
71
+ expect(await (0, async_fs_node_1.existsFolder)(rootObjPath)).not.toBeTrue();
72
72
  let folderPath = await folders.getFolderAccessFor(null);
73
73
  expect(folderPath).withContext(`obj folder not present, and is not created`).toBeUndefined();
74
- expect((0, async_fs_node_1.existsFolderSync)(rootObjPath)).not.toBeTrue();
74
+ expect(await (0, async_fs_node_1.existsFolder)(rootObjPath)).not.toBeTrue();
75
75
  folderPath = await folders.getFolderAccessFor(null, true);
76
76
  expect(folderPath).toBe(rootObjPath);
77
- expect((0, async_fs_node_1.existsFolderSync)(folderPath)).toBeTrue();
77
+ expect(await (0, async_fs_node_1.existsFolder)(folderPath)).toBeTrue();
78
78
  await writeFilesTo(folderPath, 4);
79
79
  // behaviour with exiting obj folder
80
80
  let existingPath = await folders.getFolderAccessFor(null);
@@ -95,11 +95,11 @@ describe('ObjFolders without timed generations', () => {
95
95
  const sameThirdIdPart = idA.slice(charsInSplit * 2, charsInSplit * 3);
96
96
  const fstDepthCount = await numOfItemsIn(objsDir);
97
97
  // behaviour with missing obj folder and no creation
98
- expect((0, async_fs_node_1.existsFolderSync)((0, path_1.join)(objsDir, sameFstIdPart))).not.toBeTrue();
98
+ expect(await (0, async_fs_node_1.existsFolder)((0, path_1.join)(objsDir, sameFstIdPart))).not.toBeTrue();
99
99
  let folderA = await folders.getFolderAccessFor(idA);
100
100
  expect(folderA).withContext(`obj folder not present, and is not created`).toBeUndefined();
101
101
  folderA = await folders.getFolderAccessFor(idA, true);
102
- expect((0, async_fs_node_1.existsFolderSync)(folderA)).toBeTrue();
102
+ expect(await (0, async_fs_node_1.existsFolder)(folderA)).toBeTrue();
103
103
  expect((0, path_1.basename)(folderA)).toBe(idA.slice(numOfSplits * charsInSplit));
104
104
  const threeLevelsDown = (0, path_1.join)(objsDir, sameFstIdPart, sameSndIdPart, sameThirdIdPart);
105
105
  expect(await numOfItemsIn(threeLevelsDown)).toBe(1);
@@ -110,18 +110,18 @@ describe('ObjFolders without timed generations', () => {
110
110
  existingPath = await folders.getFolderAccessFor(idA);
111
111
  expect(existingPath).toBe(folderA);
112
112
  expect(await numOfItemsIn(objsDir)).toBe(fstDepthCount + 1);
113
- expect((0, async_fs_node_1.existsFolderSync)((0, path_1.join)(objsDir, sameFstIdPart))).toBeTrue();
113
+ expect(await (0, async_fs_node_1.existsFolder)((0, path_1.join)(objsDir, sameFstIdPart))).toBeTrue();
114
114
  const twoLevelsDown = (0, path_1.join)(objsDir, sameFstIdPart, sameSndIdPart);
115
115
  const thirdDepthCount = await numOfItemsIn(twoLevelsDown);
116
116
  const folderB = await folders.getFolderAccessFor(idB, true);
117
- expect((0, async_fs_node_1.existsFolderSync)(folderB)).toBeTrue();
117
+ expect(await (0, async_fs_node_1.existsFolder)(folderB)).toBeTrue();
118
118
  expect((0, path_1.basename)(folderB)).toBe(idB.slice(numOfSplits * charsInSplit));
119
119
  expect(await numOfItemsIn(objsDir)).toBe(fstDepthCount + 1);
120
120
  expect(await numOfItemsIn(twoLevelsDown)).toBe(thirdDepthCount);
121
121
  expect(await numOfItemsIn(threeLevelsDown)).toBe(2);
122
122
  await writeFilesTo(folderB, 4);
123
123
  const folderC = await folders.getFolderAccessFor(idC, true);
124
- expect((0, async_fs_node_1.existsFolderSync)(folderC)).toBeTrue();
124
+ expect(await (0, async_fs_node_1.existsFolder)(folderC)).toBeTrue();
125
125
  expect((0, path_1.basename)(folderC)).toBe(idC.slice(numOfSplits * charsInSplit));
126
126
  expect(await numOfItemsIn(objsDir)).toBe(fstDepthCount + 1);
127
127
  expect(await numOfItemsIn(twoLevelsDown)).toBe(thirdDepthCount + 1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "core-3nweb-client-lib",
3
- "version": "0.45.2",
3
+ "version": "0.46.0",
4
4
  "description": "3NWeb client core library, embeddable into different environments",
5
5
  "main": "build/lib-index.js",
6
6
  "types": "build/lib-index.d.ts",
@@ -44,7 +44,7 @@
44
44
  },
45
45
  "devDependencies": {
46
46
  "@types/jasmine": "^5.1.13",
47
- "@types/node": "^22.13.14",
47
+ "@types/node": "^24.1.0",
48
48
  "@types/punycode": "^2.1.1",
49
49
  "@types/ws": "^8.18.1",
50
50
  "jasmine": "^5.13.0",