core-3nweb-client-lib 0.45.1 → 0.45.3

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'));
@@ -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
  }
@@ -143,6 +143,7 @@ export declare class FolderNode extends NodeInFS<FolderPersistance> {
143
143
  createFile(name: string, exclusive: boolean): Promise<FileNode>;
144
144
  createLink(name: string, params: LinkParameters<any>): Promise<void>;
145
145
  removeChild(f: NodeInFS<any>): Promise<void>;
146
+ removeChildEntryUnconditionally(name: string): Promise<void>;
146
147
  private changeChildName;
147
148
  moveChildTo(childName: string, dst: FolderNode, nameInDst: string): Promise<void>;
148
149
  private moveChildOut;
@@ -612,6 +612,16 @@ class FolderNode extends node_in_fs_1.NodeInFS {
612
612
  // stays consistent
613
613
  this.callRemoveObjOn('local', f);
614
614
  }
615
+ async removeChildEntryUnconditionally(name) {
616
+ await this.doTransition(async (state, version) => {
617
+ const child = state.nodes[name];
618
+ if (!child) {
619
+ return [];
620
+ }
621
+ delete state.nodes[name];
622
+ return this.makeEntryRemovalEvent(version, 'local', child);
623
+ });
624
+ }
615
625
  changeChildName(oldName, newName) {
616
626
  return this.doTransition(async (state, version) => {
617
627
  const child = state.nodes[oldName];
@@ -146,32 +146,62 @@ class XspFS {
146
146
  if (typeof folderName !== 'string') {
147
147
  throw new Error('Cannot remove root folder');
148
148
  }
149
- const folder = (await parentFolder.getFolder(folderName)
150
- .catch(setExcPath(path)));
151
- if (!removeContent && !folder.isEmpty()) {
152
- throw (0, file_1.makeFileException)('notEmpty', path);
149
+ try {
150
+ const folder = (await parentFolder.getFolder(folderName)
151
+ .catch(setExcPath(path)));
152
+ if (!removeContent && !folder.isEmpty()) {
153
+ throw (0, file_1.makeFileException)('notEmpty', path);
154
+ }
155
+ // note that internal folder.delete() removes all children as a matter
156
+ // of not leaving inaccessible nodes, i.e. content is removed implicitly
157
+ await parentFolder.removeChild(folder);
158
+ }
159
+ catch (exc) {
160
+ if (exc.type === 'secondary') {
161
+ await parentFolder.removeChildEntryUnconditionally(folderName);
162
+ }
163
+ else {
164
+ throw exc;
165
+ }
153
166
  }
154
- // note that internal folder.delete() removes all children as a matter
155
- // of not leaving inaccessible nodes, i.e. content is removed implicitly
156
- await parentFolder.removeChild(folder);
157
167
  }
158
168
  async deleteFile(path) {
159
169
  const { fileName, folderPath } = split(path);
160
170
  const root = this.v.getRootIfNotClosed(path);
161
171
  const parentFolder = await root.getFolderInThisSubTree(folderPath)
162
172
  .catch(setExcPath(path));
163
- const file = await parentFolder.getFile(fileName)
164
- .catch(setExcPath(path));
165
- await parentFolder.removeChild(file);
173
+ try {
174
+ const file = await parentFolder.getFile(fileName)
175
+ .catch(setExcPath(path));
176
+ await parentFolder.removeChild(file);
177
+ }
178
+ catch (exc) {
179
+ if (exc.type === 'secondary') {
180
+ await parentFolder.removeChildEntryUnconditionally(fileName);
181
+ }
182
+ else {
183
+ throw exc;
184
+ }
185
+ }
166
186
  }
167
187
  async deleteLink(path) {
168
188
  const { fileName, folderPath } = split(path);
169
189
  const root = this.v.getRootIfNotClosed(path);
170
190
  const parentFolder = await root.getFolderInThisSubTree(folderPath)
171
191
  .catch(setExcPath(path));
172
- const link = await parentFolder.getLink(fileName)
173
- .catch(setExcPath(path));
174
- await parentFolder.removeChild(link);
192
+ try {
193
+ const link = await parentFolder.getLink(fileName)
194
+ .catch(setExcPath(path));
195
+ await parentFolder.removeChild(link);
196
+ }
197
+ catch (exc) {
198
+ if (exc.type === 'secondary') {
199
+ await parentFolder.removeChildEntryUnconditionally(fileName);
200
+ }
201
+ else {
202
+ throw exc;
203
+ }
204
+ }
175
205
  }
176
206
  async move(initPath, newPath) {
177
207
  const srcFolderPath = splitPathIntoParts(initPath);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "core-3nweb-client-lib",
3
- "version": "0.45.1",
3
+ "version": "0.45.3",
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,11 +44,11 @@
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
- "napi-nacl": "^1.2.0",
51
50
  "jasmine": "^5.13.0",
51
+ "napi-nacl": "^1.2.1",
52
52
  "protobufjs-cli": "^1.0.2",
53
53
  "spec-3nweb-server": "^1.8.5",
54
54
  "tsuml2": "^0.17.1",