core-3nweb-client-lib 0.45.0 → 0.45.2
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/build/lib-client/doh.d.ts +2 -0
- package/build/lib-client/doh.js +68 -0
- package/build/lib-client/request-utils.js +1 -1
- package/build/lib-client/service-checks.js +3 -11
- package/build/lib-client/service-locator.d.ts +10 -2
- package/build/lib-client/service-locator.js +40 -27
- package/build/lib-client/xsp-fs/folder-node.d.ts +1 -0
- package/build/lib-client/xsp-fs/folder-node.js +10 -0
- package/build/lib-client/xsp-fs/fs.js +43 -13
- package/build/lib-index.d.ts +1 -0
- package/build/lib-index.js +3 -1
- package/package.json +2 -2
|
@@ -0,0 +1,68 @@
|
|
|
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.dohAt = dohAt;
|
|
20
|
+
const https = require("https");
|
|
21
|
+
const request_utils_1 = require("./request-utils");
|
|
22
|
+
const service_locator_1 = require("./service-locator");
|
|
23
|
+
function dohAt(dohServerUrl) {
|
|
24
|
+
async function resolveTxt(domain) {
|
|
25
|
+
const answer = await sendDohQuestion(dohServerUrl, domain, 'TXT');
|
|
26
|
+
let txt = [];
|
|
27
|
+
for (const { data: line } of answer) {
|
|
28
|
+
txt.push([line]);
|
|
29
|
+
}
|
|
30
|
+
return txt;
|
|
31
|
+
}
|
|
32
|
+
return { resolveTxt };
|
|
33
|
+
}
|
|
34
|
+
async function sendDohQuestion(serverUrl, domain, type) {
|
|
35
|
+
const opts = {
|
|
36
|
+
method: 'GET',
|
|
37
|
+
url: `${serverUrl}?name=${domain}&type=${type}`,
|
|
38
|
+
responseType: 'json'
|
|
39
|
+
};
|
|
40
|
+
const httpsOpts = (0, request_utils_1.formHttpsReqOpts)(opts);
|
|
41
|
+
httpsOpts.headers.accept = 'application/dns-json';
|
|
42
|
+
const reply = await (0, request_utils_1.processRequest)(opts => https.request(opts), httpsOpts, opts, undefined)
|
|
43
|
+
.catch((exc) => {
|
|
44
|
+
if (exc.type === 'connect') {
|
|
45
|
+
throw { code: service_locator_1.DNS_ERR_CODE.ECONNREFUSED, hostname: domain, cause: exc };
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
throw { code: service_locator_1.DNS_ERR_CODE.ESERVFAIL, hostname: domain, cause: exc };
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
const { status, data } = reply;
|
|
52
|
+
if (status !== 200) {
|
|
53
|
+
throw {
|
|
54
|
+
code: service_locator_1.DNS_ERR_CODE.ESERVFAIL, hostname: domain,
|
|
55
|
+
message: `status ${reply.status} from DoH server`
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
if (data.Status !== 0) {
|
|
59
|
+
throw { code: service_locator_1.DNS_ERR_CODE.NOTFOUND, hostname: domain };
|
|
60
|
+
}
|
|
61
|
+
if (data.Answer) {
|
|
62
|
+
return data.Answer;
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
throw { code: service_locator_1.DNS_ERR_CODE.NODATA, hostname: domain };
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
Object.freeze(exports);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/*
|
|
3
|
-
Copyright (C) 2025 3NSoft Inc.
|
|
3
|
+
Copyright (C) 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
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
19
|
exports.checkServicesStartingFromSignup = checkServicesStartingFromSignup;
|
|
20
20
|
const _3nweb_signup_1 = require("./3nweb-signup");
|
|
21
|
+
const doh_1 = require("./doh");
|
|
21
22
|
const service_locator_1 = require("./service-locator");
|
|
22
23
|
const dns_1 = require("dns");
|
|
23
24
|
async function checkServicesStartingFromSignup(client, signupUrl, signupToken, progress) {
|
|
@@ -126,16 +127,7 @@ async function checkSignup(client, signupURL, signupToken) {
|
|
|
126
127
|
};
|
|
127
128
|
}
|
|
128
129
|
}
|
|
129
|
-
const srvLocator = (0, service_locator_1.makeServiceLocator)({
|
|
130
|
-
resolveTxt: domain => new Promise((resolve, reject) => (0, dns_1.resolveTxt)(domain, (err, texts) => {
|
|
131
|
-
if (err) {
|
|
132
|
-
reject(err);
|
|
133
|
-
}
|
|
134
|
-
else {
|
|
135
|
-
resolve(texts);
|
|
136
|
-
}
|
|
137
|
-
}))
|
|
138
|
-
});
|
|
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`));
|
|
139
131
|
async function checkUserDomainDNS(service, domain) {
|
|
140
132
|
try {
|
|
141
133
|
const serviceUrl = await (srvLocator(service))(`u@${domain}`);
|
|
@@ -26,12 +26,20 @@ export declare function mailerIdInfoAt(client: NetClient, url: string): Promise<
|
|
|
26
26
|
* @param url
|
|
27
27
|
*/
|
|
28
28
|
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
|
+
};
|
|
29
36
|
export type ServiceTypeDNSLabel = 'mailerid' | 'asmail' | '3nstorage';
|
|
30
37
|
export type ServiceLocatorMaker = (serviceLabel: ServiceTypeDNSLabel) => ServiceLocator;
|
|
31
38
|
export type ServiceLocator = (address: string) => Promise<string>;
|
|
32
|
-
export
|
|
39
|
+
export interface DnsResolver {
|
|
33
40
|
resolveTxt: (typeof dnsPromises)['resolveTxt'];
|
|
34
|
-
}
|
|
41
|
+
}
|
|
42
|
+
export declare function makeServiceLocator(...resolvers: DnsResolver[]): ServiceLocatorMaker;
|
|
35
43
|
/**
|
|
36
44
|
* @param resolver
|
|
37
45
|
* @param address
|
|
@@ -16,6 +16,7 @@
|
|
|
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;
|
|
19
20
|
exports.asmailInfoAt = asmailInfoAt;
|
|
20
21
|
exports.mailerIdInfoAt = mailerIdInfoAt;
|
|
21
22
|
exports.storageInfoAt = storageInfoAt;
|
|
@@ -215,43 +216,55 @@ function getRecordAtStartOf(txt) {
|
|
|
215
216
|
value: txt
|
|
216
217
|
};
|
|
217
218
|
}
|
|
218
|
-
|
|
219
|
+
exports.DNS_ERR_CODE = {
|
|
219
220
|
NODATA: 'ENODATA',
|
|
220
221
|
NOTFOUND: 'ENOTFOUND',
|
|
221
222
|
ESERVFAIL: 'ESERVFAIL',
|
|
222
223
|
ECONNREFUSED: 'ECONNREFUSED',
|
|
223
224
|
ETIMEOUT: 'ETIMEOUT'
|
|
224
225
|
};
|
|
225
|
-
Object.freeze(DNS_ERR_CODE);
|
|
226
|
-
function makeServiceLocator(
|
|
226
|
+
Object.freeze(exports.DNS_ERR_CODE);
|
|
227
|
+
function makeServiceLocator(...resolvers) {
|
|
228
|
+
if (resolvers.length === 0) {
|
|
229
|
+
throw Error(`no DNS resolvers given`);
|
|
230
|
+
}
|
|
227
231
|
return serviceLabel => async (address) => {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
const { code, hostname, message } = err;
|
|
240
|
-
if (code === DNS_ERR_CODE.NODATA) {
|
|
241
|
-
throw noServiceRecordExc(address);
|
|
242
|
-
}
|
|
243
|
-
else if ((code === DNS_ERR_CODE.ESERVFAIL)
|
|
244
|
-
|| (code === DNS_ERR_CODE.ECONNREFUSED)
|
|
245
|
-
|| (code === DNS_ERR_CODE.ETIMEOUT)) {
|
|
246
|
-
throw noConnectionExc({ code, hostname, message });
|
|
247
|
-
}
|
|
248
|
-
else if (hostname) {
|
|
249
|
-
throw domainNotFoundExc(address, { code, hostname, message });
|
|
232
|
+
const domain = domainOfAddress(address);
|
|
233
|
+
let prevConnectionExc = undefined;
|
|
234
|
+
for (const resolver of resolvers) {
|
|
235
|
+
try {
|
|
236
|
+
const txtRecords = await resolver.resolveTxt(domain);
|
|
237
|
+
const recValue = extractPair(txtRecords, serviceLabel);
|
|
238
|
+
if (!recValue) {
|
|
239
|
+
throw noServiceRecordExc(address);
|
|
240
|
+
}
|
|
241
|
+
const url = checkAndPrepareURL(recValue);
|
|
242
|
+
return url;
|
|
250
243
|
}
|
|
251
|
-
|
|
252
|
-
|
|
244
|
+
catch (err) {
|
|
245
|
+
const { code, hostname, message } = err;
|
|
246
|
+
if (code === exports.DNS_ERR_CODE.NODATA) {
|
|
247
|
+
throw noServiceRecordExc(address);
|
|
248
|
+
}
|
|
249
|
+
else if ((code === exports.DNS_ERR_CODE.ESERVFAIL)
|
|
250
|
+
|| (code === exports.DNS_ERR_CODE.ECONNREFUSED)
|
|
251
|
+
|| (code === exports.DNS_ERR_CODE.ETIMEOUT)) {
|
|
252
|
+
if (!prevConnectionExc) {
|
|
253
|
+
prevConnectionExc = noConnectionExc({ code, hostname, message });
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
else if ((code === exports.DNS_ERR_CODE.NOTFOUND) || hostname) {
|
|
257
|
+
throw domainNotFoundExc(address, { code, hostname, message });
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
if (!prevConnectionExc) {
|
|
261
|
+
prevConnectionExc = err;
|
|
262
|
+
}
|
|
263
|
+
throw err;
|
|
264
|
+
}
|
|
253
265
|
}
|
|
254
266
|
}
|
|
267
|
+
throw prevConnectionExc;
|
|
255
268
|
};
|
|
256
269
|
}
|
|
257
270
|
/**
|
|
@@ -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
|
-
|
|
150
|
-
.
|
|
151
|
-
|
|
152
|
-
|
|
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
|
-
|
|
164
|
-
.
|
|
165
|
-
|
|
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
|
-
|
|
173
|
-
.
|
|
174
|
-
|
|
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/build/lib-index.d.ts
CHANGED
|
@@ -13,3 +13,4 @@ export { DeviceFS } from './lib-client/local-files/device-fs';
|
|
|
13
13
|
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
|
+
export { dohAt } from './lib-client/doh';
|
package/build/lib-index.js
CHANGED
|
@@ -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.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.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; } });
|
|
@@ -58,4 +58,6 @@ Object.defineProperty(exports, "makeLogger", { enumerable: true, get: function (
|
|
|
58
58
|
exports.SYSTEM_DOMAIN = '3nweb.computer';
|
|
59
59
|
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
|
+
var doh_1 = require("./lib-client/doh");
|
|
62
|
+
Object.defineProperty(exports, "dohAt", { enumerable: true, get: function () { return doh_1.dohAt; } });
|
|
61
63
|
Object.freeze(exports);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "core-3nweb-client-lib",
|
|
3
|
-
"version": "0.45.
|
|
3
|
+
"version": "0.45.2",
|
|
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",
|
|
@@ -47,8 +47,8 @@
|
|
|
47
47
|
"@types/node": "^22.13.14",
|
|
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",
|