@ztimson/momentum 0.50.6 → 0.51.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.
- package/dist/auth.d.ts +32 -5
- package/dist/auth.d.ts.map +1 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/index.cjs +133 -81
- package/dist/index.mjs +133 -81
- package/dist/static.d.ts +2 -5
- package/dist/static.d.ts.map +1 -1
- package/dist/storage.d.ts +2 -1
- package/dist/storage.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/auth.d.ts
CHANGED
|
@@ -1,13 +1,41 @@
|
|
|
1
1
|
import { Api } from './api';
|
|
2
2
|
import { PathEvent, PathEventEmitter } from '@ztimson/utils';
|
|
3
|
+
import { Meta } from './core';
|
|
3
4
|
import { User } from './users';
|
|
4
5
|
export type AuthOptions = {
|
|
5
6
|
/** Path to login page */
|
|
6
7
|
loginUrl?: string;
|
|
7
8
|
};
|
|
9
|
+
export type UserToken = Meta & {
|
|
10
|
+
name: string;
|
|
11
|
+
owner: string;
|
|
12
|
+
token: string;
|
|
13
|
+
expire: null | Date;
|
|
14
|
+
};
|
|
15
|
+
export declare class Token extends PathEventEmitter {
|
|
16
|
+
private api;
|
|
17
|
+
constructor(api: Api);
|
|
18
|
+
all(username: string): Promise<UserToken[]>;
|
|
19
|
+
create(token: {
|
|
20
|
+
name: string;
|
|
21
|
+
owner: string;
|
|
22
|
+
expire: null | Date;
|
|
23
|
+
}): Promise<UserToken>;
|
|
24
|
+
delete(id: string): Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
export declare class Totp {
|
|
27
|
+
private api;
|
|
28
|
+
constructor(api: Api);
|
|
29
|
+
disable(username: string): import('@ztimson/utils').PromiseProgress<void>;
|
|
30
|
+
enable: (username: string) => import('@ztimson/utils').PromiseProgress<void>;
|
|
31
|
+
reset(username: string): import('@ztimson/utils').PromiseProgress<void>;
|
|
32
|
+
setup(username: string, method?: string, totp?: string): import('@ztimson/utils').PromiseProgress<void>;
|
|
33
|
+
}
|
|
8
34
|
export declare class Auth extends PathEventEmitter {
|
|
9
35
|
private readonly opts;
|
|
10
36
|
private readonly api;
|
|
37
|
+
token: Token;
|
|
38
|
+
totp: Totp;
|
|
11
39
|
private _permissions;
|
|
12
40
|
get permissions(): string[];
|
|
13
41
|
set permissions(perms: string[]);
|
|
@@ -21,7 +49,10 @@ export declare class Auth extends PathEventEmitter {
|
|
|
21
49
|
hasFatal: (...events: (string | PathEvent)[]) => void;
|
|
22
50
|
hasAllFatal: (...events: (string | PathEvent)[]) => void;
|
|
23
51
|
knownHost(host?: string): Promise<void>;
|
|
24
|
-
login(username: string, password: string,
|
|
52
|
+
login(username: string, password: string, opts?: {
|
|
53
|
+
totp?: string;
|
|
54
|
+
expire?: number | Date | null;
|
|
55
|
+
}): Promise<User | null>;
|
|
25
56
|
loginRedirect(host?: string): Promise<string>;
|
|
26
57
|
logout(): void;
|
|
27
58
|
register(u: Partial<User> & {
|
|
@@ -36,9 +67,5 @@ export declare class Auth extends PathEventEmitter {
|
|
|
36
67
|
permissions: string[];
|
|
37
68
|
} | null>;
|
|
38
69
|
updatePassword(username: string, password: string, oldPassword?: string): Promise<void>;
|
|
39
|
-
disableTotp(username: string): import('@ztimson/utils').PromiseProgress<void>;
|
|
40
|
-
enableTotp: (username: string) => import('@ztimson/utils').PromiseProgress<void>;
|
|
41
|
-
resetTotp(username: string): import('@ztimson/utils').PromiseProgress<void>;
|
|
42
|
-
setupTotp(username: string, method?: string, totp?: string): import('@ztimson/utils').PromiseProgress<void>;
|
|
43
70
|
}
|
|
44
71
|
//# sourceMappingURL=auth.d.ts.map
|
package/dist/auth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,GAAG,EAAC,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAiB,SAAS,EAAE,gBAAgB,EAAM,MAAM,gBAAgB,CAAC;AAChF,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,SAAS,CAAC;AAElC,MAAM,MAAM,WAAW,GAAG;IACzB,yBAAyB;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB,CAAA;AAED,qBAAa,IAAK,SAAQ,gBAAgB;
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,gBAAgB,EAAM,MAAM,gBAAgB,CAAC;AACnE,OAAO,EAAC,GAAG,EAAC,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAC,QAAQ,EAAC,MAAM,YAAY,CAAC;AAEpC,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,KAAK,GAAG,KAAK,GAAG,OAAO,GAAG,SAAS,CAAC;AAEnF,qBAAa,MAAO,SAAQ,gBAAgB;IAqC/B,OAAO,CAAC,GAAG;IAAO,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAnCvD,IAAI,MAAM,YAAyD;IAEnE,OAAO,CAAC,cAAc,CAAS;IAC/B,IAAI,aAAa,IACkB,OAAO,CADS;IACnD,OAAO,KAAK,aAAa,QAGxB;IAED,OAAO,CAAC,SAAS,CAAC,CAAW;IAC7B,IAAI,QAAQ,IAAI,QAAQ,CAWvB;IAED,IAAI,gBAAgB,IAAI,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAGvD;IAED,OAAO,CAAC,IAAI,CAAC,CAAU;IACvB,IAAI,GAAG,IAAI,OAAO,CAIjB;gBAEmB,GAAG,EAAE,GAAG,EAAmB,QAAQ,EAAE,QAAQ;IAK3D,MAAM,CAAC,MAAM,UAAQ,EAAE,SAAS,UAAO;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,gBAAgB,EAAM,MAAM,gBAAgB,CAAC;AACnE,OAAO,EAAC,GAAG,EAAC,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAC,QAAQ,EAAC,MAAM,YAAY,CAAC;AAEpC,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,KAAK,GAAG,KAAK,GAAG,OAAO,GAAG,SAAS,CAAC;AAEnF,qBAAa,MAAO,SAAQ,gBAAgB;IAqC/B,OAAO,CAAC,GAAG;IAAO,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAnCvD,IAAI,MAAM,YAAyD;IAEnE,OAAO,CAAC,cAAc,CAAS;IAC/B,IAAI,aAAa,IACkB,OAAO,CADS;IACnD,OAAO,KAAK,aAAa,QAGxB;IAED,OAAO,CAAC,SAAS,CAAC,CAAW;IAC7B,IAAI,QAAQ,IAAI,QAAQ,CAWvB;IAED,IAAI,gBAAgB,IAAI,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAGvD;IAED,OAAO,CAAC,IAAI,CAAC,CAAU;IACvB,IAAI,GAAG,IAAI,OAAO,CAIjB;gBAEmB,GAAG,EAAE,GAAG,EAAmB,QAAQ,EAAE,QAAQ;IAK3D,MAAM,CAAC,MAAM,UAAQ,EAAE,SAAS,UAAO;IAqH7C,SAAS,CAAC,QAAQ,CAAC,EAAE,SAAS,GAAG,KAAK;IAoIhC,mBAAmB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAa7C,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC;CAO3C"}
|
package/dist/index.cjs
CHANGED
|
@@ -1128,10 +1128,51 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
1128
1128
|
});
|
|
1129
1129
|
}
|
|
1130
1130
|
}
|
|
1131
|
+
class Token extends PathEventEmitter {
|
|
1132
|
+
constructor(api) {
|
|
1133
|
+
super();
|
|
1134
|
+
this.api = api;
|
|
1135
|
+
}
|
|
1136
|
+
all(username) {
|
|
1137
|
+
return this.api.request({ url: "/" + PES`api/auth/tokens/${username}` }).then((resp) => {
|
|
1138
|
+
this.emit(PES`token/${username}:r`, resp);
|
|
1139
|
+
return resp;
|
|
1140
|
+
});
|
|
1141
|
+
}
|
|
1142
|
+
create(token) {
|
|
1143
|
+
return this.api.request({ url: "/" + PES`api/auth/tokens/${token.owner}`, body: token }).then((resp) => {
|
|
1144
|
+
this.emit(PES`token/${token.owner}:c`, token);
|
|
1145
|
+
return resp;
|
|
1146
|
+
});
|
|
1147
|
+
}
|
|
1148
|
+
delete(id) {
|
|
1149
|
+
return this.api.request({ url: "/" + PES`api/auth/tokens/${id}`, method: "DELETE" }).then(() => this.emit(PES`token/${id}:d`, id));
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
class Totp {
|
|
1153
|
+
constructor(api) {
|
|
1154
|
+
__publicField(this, "enable", this.reset);
|
|
1155
|
+
this.api = api;
|
|
1156
|
+
}
|
|
1157
|
+
disable(username) {
|
|
1158
|
+
return this.api.request({ url: "/" + PES`api/auth/totp/${username}`, method: "DELETE" });
|
|
1159
|
+
}
|
|
1160
|
+
reset(username) {
|
|
1161
|
+
return this.api.request({ url: "/" + PES`api/auth/totp/${username}`, method: "POST" });
|
|
1162
|
+
}
|
|
1163
|
+
setup(username, method = "app", totp) {
|
|
1164
|
+
return this.api.request({ url: "/" + PES`api/auth/totp/${username}`, body: clean({
|
|
1165
|
+
method,
|
|
1166
|
+
totp
|
|
1167
|
+
}) });
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1131
1170
|
class Auth extends PathEventEmitter {
|
|
1132
1171
|
constructor(api, opts = {}) {
|
|
1133
1172
|
super();
|
|
1134
1173
|
__publicField(this, "api");
|
|
1174
|
+
__publicField(this, "token");
|
|
1175
|
+
__publicField(this, "totp");
|
|
1135
1176
|
__publicField(this, "_permissions", []);
|
|
1136
1177
|
__publicField(this, "_user");
|
|
1137
1178
|
// Permission helpers
|
|
@@ -1140,9 +1181,11 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
1140
1181
|
__publicField(this, "hasAll", (...events) => PathEvent.hasAll(this.permissions, ...events));
|
|
1141
1182
|
__publicField(this, "hasFatal", (...events) => PathEvent.hasFatal(this.permissions, ...events));
|
|
1142
1183
|
__publicField(this, "hasAllFatal", (...events) => PathEvent.hasAllFatal(this.permissions, ...events));
|
|
1143
|
-
__publicField(this, "enableTotp", this.resetTotp);
|
|
1144
1184
|
this.opts = opts;
|
|
1145
1185
|
this.api = typeof api == "string" ? new Api(api) : api;
|
|
1186
|
+
this.token = new Token(this.api);
|
|
1187
|
+
this.totp = new Totp(this.api);
|
|
1188
|
+
this.relayEvents(this.token);
|
|
1146
1189
|
this.opts = {
|
|
1147
1190
|
loginUrl: this.api.url + "/ui/#/login",
|
|
1148
1191
|
...this.opts
|
|
@@ -1185,17 +1228,17 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
1185
1228
|
if (host.startsWith("/")) return Promise.resolve();
|
|
1186
1229
|
return this.api.request({ url: `/api/auth/known-host?host=${encodeURI(new URL(host).origin)}` });
|
|
1187
1230
|
}
|
|
1188
|
-
login(username, password,
|
|
1231
|
+
login(username, password, opts) {
|
|
1189
1232
|
if (!username || !password) throw new Error("Cannot login, missing username or password");
|
|
1190
1233
|
return this.api.request({
|
|
1191
1234
|
url: "/api/auth/login",
|
|
1192
1235
|
headers: { Authorization: void 0 },
|
|
1193
1236
|
method: "POST",
|
|
1194
|
-
body: {
|
|
1237
|
+
body: clean({
|
|
1195
1238
|
username: username.trim(),
|
|
1196
1239
|
password: password.trim(),
|
|
1197
|
-
|
|
1198
|
-
}
|
|
1240
|
+
...opts
|
|
1241
|
+
}, true)
|
|
1199
1242
|
}).then(async (resp) => {
|
|
1200
1243
|
this.api.token = (resp == null ? void 0 : resp.token) || null;
|
|
1201
1244
|
const user = await this.once("auth/user");
|
|
@@ -1271,19 +1314,6 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
1271
1314
|
if (resp == null ? void 0 : resp.token) this.api.token = resp.token;
|
|
1272
1315
|
});
|
|
1273
1316
|
}
|
|
1274
|
-
// TOTP ============================================================================================================
|
|
1275
|
-
disableTotp(username) {
|
|
1276
|
-
return this.api.request({ url: `/api/auth/totp/${username}`, method: "DELETE" });
|
|
1277
|
-
}
|
|
1278
|
-
resetTotp(username) {
|
|
1279
|
-
return this.api.request({ url: `/api/auth/totp/${username}`, method: "POST" });
|
|
1280
|
-
}
|
|
1281
|
-
setupTotp(username, method = "app", totp) {
|
|
1282
|
-
return this.api.request({ url: `/api/auth/totp/${username}`, body: clean({
|
|
1283
|
-
method,
|
|
1284
|
-
totp
|
|
1285
|
-
}) });
|
|
1286
|
-
}
|
|
1287
1317
|
}
|
|
1288
1318
|
class Client extends PathEventEmitter {
|
|
1289
1319
|
constructor(api, settings) {
|
|
@@ -1320,11 +1350,14 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
1320
1350
|
get pushSubscription() {
|
|
1321
1351
|
var _a;
|
|
1322
1352
|
if (!((_a = navigator.serviceWorker) == null ? void 0 : _a.controller)) return Promise.resolve(null);
|
|
1323
|
-
return navigator.serviceWorker.ready.then((sw) =>
|
|
1353
|
+
return navigator.serviceWorker.ready.then((sw) => {
|
|
1354
|
+
var _a2;
|
|
1355
|
+
return (_a2 = sw == null ? void 0 : sw.pushManager) == null ? void 0 : _a2.getSubscription();
|
|
1356
|
+
});
|
|
1324
1357
|
}
|
|
1325
1358
|
get pwa() {
|
|
1326
1359
|
if (this._pwa == null)
|
|
1327
|
-
this._pwa =
|
|
1360
|
+
this._pwa = matchMedia("(display-mode: standalone)").matches || (navigator == null ? void 0 : navigator.standalone) || document.referrer.includes("android-app://");
|
|
1328
1361
|
return this._pwa;
|
|
1329
1362
|
}
|
|
1330
1363
|
async inject(reload = false, firstLoad = true) {
|
|
@@ -1332,6 +1365,50 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
1332
1365
|
let settings = this.settings.cache;
|
|
1333
1366
|
if (firstLoad) this.settings.all(false, reload).then(() => this.inject(false, false)).catch(() => {
|
|
1334
1367
|
});
|
|
1368
|
+
if (settings["title"] && !document.head.querySelector('meta[property="og:title"]')) {
|
|
1369
|
+
const meta = document.createElement("meta");
|
|
1370
|
+
meta.setAttribute("property", "og:title");
|
|
1371
|
+
meta.content = settings["title"];
|
|
1372
|
+
document.head.append(meta);
|
|
1373
|
+
}
|
|
1374
|
+
if (!document.querySelector('meta[property="og:type"]')) {
|
|
1375
|
+
const meta = document.createElement("meta");
|
|
1376
|
+
meta.setAttribute("property", "og:type");
|
|
1377
|
+
meta.content = "article";
|
|
1378
|
+
document.head.append(meta);
|
|
1379
|
+
}
|
|
1380
|
+
if (settings["public_url"] && !document.querySelector('meta[property="og:url"]')) {
|
|
1381
|
+
const meta = document.createElement("meta");
|
|
1382
|
+
meta.setAttribute("property", "og:url");
|
|
1383
|
+
meta.content = settings["public_url"];
|
|
1384
|
+
document.head.append(meta);
|
|
1385
|
+
}
|
|
1386
|
+
if (settings["description"]) {
|
|
1387
|
+
if (!document.querySelector('meta[property="og:description"]')) {
|
|
1388
|
+
const meta = document.createElement("meta");
|
|
1389
|
+
meta.setAttribute("property", "og:description");
|
|
1390
|
+
meta.content = settings["description"];
|
|
1391
|
+
document.head.append(meta);
|
|
1392
|
+
}
|
|
1393
|
+
if (!document.querySelector('meta[property="description"]')) {
|
|
1394
|
+
const meta = document.createElement("meta");
|
|
1395
|
+
meta.setAttribute("property", "description");
|
|
1396
|
+
meta.content = settings["description"];
|
|
1397
|
+
document.head.append(meta);
|
|
1398
|
+
}
|
|
1399
|
+
if (!document.querySelector('meta[property="twitter:card"]')) {
|
|
1400
|
+
const meta = document.createElement("meta");
|
|
1401
|
+
meta.setAttribute("property", "twitter:card");
|
|
1402
|
+
meta.content = settings["description"];
|
|
1403
|
+
document.head.append(meta);
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
if (settings["public_url"] && !document.querySelector('meta[property="og:image"]')) {
|
|
1407
|
+
const meta = document.createElement("meta");
|
|
1408
|
+
meta.setAttribute("property", "og:image");
|
|
1409
|
+
meta.content = settings["public_url"] + "/favicon.ico";
|
|
1410
|
+
document.head.append(meta);
|
|
1411
|
+
}
|
|
1335
1412
|
if (!document.querySelector('meta[name="mobile-web-app-capable"]')) {
|
|
1336
1413
|
const meta = document.createElement("meta");
|
|
1337
1414
|
meta.name = "mobile-web-app-capable";
|
|
@@ -1344,46 +1421,41 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
1344
1421
|
meta.content = "default";
|
|
1345
1422
|
document.head.append(meta);
|
|
1346
1423
|
}
|
|
1347
|
-
if (!document.querySelector('meta[name="apple-mobile-web-app-title"]')) {
|
|
1424
|
+
if (settings["title"] && !document.querySelector('meta[name="apple-mobile-web-app-title"]')) {
|
|
1348
1425
|
const meta = document.createElement("meta");
|
|
1349
1426
|
meta.name = "apple-mobile-web-app-title";
|
|
1350
1427
|
meta.content = settings["title"];
|
|
1351
1428
|
document.head.append(meta);
|
|
1352
1429
|
}
|
|
1353
|
-
if (!document.querySelector('link[rel="apple-touch-icon"]')) {
|
|
1430
|
+
if (settings["public_url"] && !document.querySelector('link[rel="apple-touch-icon"]')) {
|
|
1354
1431
|
const meta = document.createElement("link");
|
|
1355
1432
|
meta.rel = "apple-touch-icon";
|
|
1356
|
-
meta.href = settings["
|
|
1433
|
+
meta.href = settings["public_url"] + "/favicon.ico";
|
|
1357
1434
|
document.head.append(meta);
|
|
1358
1435
|
}
|
|
1359
|
-
if (!document.querySelector('link[rel="apple-touch-startup-image"]')) {
|
|
1436
|
+
if (settings["public_url"] && !document.querySelector('link[rel="apple-touch-startup-image"]')) {
|
|
1360
1437
|
const meta = document.createElement("link");
|
|
1361
1438
|
meta.rel = "apple-touch-startup-image";
|
|
1362
|
-
meta.href = settings["
|
|
1439
|
+
meta.href = settings["public_url"] + "/favicon.ico";
|
|
1363
1440
|
document.head.append(meta);
|
|
1364
1441
|
}
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
if (settings["
|
|
1368
|
-
|
|
1369
|
-
if (settings["description"])
|
|
1370
|
-
window.document.querySelectorAll(".momentum-description").forEach((el) => el.innerText = settings["description"]);
|
|
1371
|
-
if (settings.version)
|
|
1372
|
-
window.document.querySelectorAll(".momentum-version").forEach((el) => el.innerText = settings["version"]);
|
|
1373
|
-
if (settings["logo"]) {
|
|
1374
|
-
window.document.querySelectorAll(".momentum-logo").forEach((el) => el.src = settings["logo"]);
|
|
1375
|
-
}
|
|
1442
|
+
if (settings["title"]) document.querySelectorAll(".momentum-title").forEach((el) => el.innerText = settings["title"]);
|
|
1443
|
+
if (settings["description"]) document.querySelectorAll(".momentum-description").forEach((el) => el.innerText = settings["description"]);
|
|
1444
|
+
if (settings["version"]) document.querySelectorAll(".momentum-version").forEach((el) => el.innerText = settings["version"]);
|
|
1445
|
+
if (settings["logo"]) document.querySelectorAll(".momentum-logo").forEach((el) => el.src = settings["logo"]);
|
|
1376
1446
|
if (settings["theme"]) {
|
|
1447
|
+
document.body.classList.add(((_a = settings["theme"]) == null ? void 0 : _a.darkMode) ? "theme-dark" : "theme-light");
|
|
1448
|
+
document.body.classList.remove(((_b = settings["theme"]) == null ? void 0 : _b.darkMode) ? "theme-light" : "theme-dark");
|
|
1377
1449
|
document.body.style.setProperty("--theme-backdrop", (_c = settings["theme"]) == null ? void 0 : _c.background);
|
|
1378
1450
|
document.body.style.setProperty("--theme-primary", (_d = settings["theme"]) == null ? void 0 : _d.primary);
|
|
1379
1451
|
document.body.style.setProperty("--theme-accent", (_e = settings["theme"]) == null ? void 0 : _e.accent);
|
|
1380
1452
|
document.body.style.setProperty("--theme-contrast", blackOrWhite((_f = settings["theme"]) == null ? void 0 : _f.background));
|
|
1381
1453
|
}
|
|
1382
1454
|
if (settings["pwa"]) {
|
|
1383
|
-
const link =
|
|
1455
|
+
const link = document.createElement("link");
|
|
1384
1456
|
link.setAttribute("rel", "manifest");
|
|
1385
1457
|
link.setAttribute("href", this.settings.api.url + "/manifest.json");
|
|
1386
|
-
|
|
1458
|
+
document.head.append(link);
|
|
1387
1459
|
setTimeout(() => {
|
|
1388
1460
|
const dismissed = !!localStorage.getItem("momentum:install-prompt");
|
|
1389
1461
|
if (!dismissed && !this.pwa && this.mobile) this.pwaPrompt();
|
|
@@ -1956,60 +2028,61 @@ ${log}`;
|
|
|
1956
2028
|
__publicField(_Socket, "pollingSpeed", 3e4);
|
|
1957
2029
|
let Socket = _Socket;
|
|
1958
2030
|
let Storage$1 = class Storage extends PathEventEmitter {
|
|
1959
|
-
constructor(api) {
|
|
2031
|
+
constructor(api, path = "storage") {
|
|
1960
2032
|
super();
|
|
1961
2033
|
__publicField(this, "api");
|
|
2034
|
+
this.path = path;
|
|
1962
2035
|
this.api = typeof api == "string" ? new Api(api) : api;
|
|
1963
2036
|
}
|
|
1964
2037
|
copy(source, destination) {
|
|
1965
2038
|
if (!source || !destination) throw new Error("Cannot copy file or folder, missing source or destination");
|
|
1966
|
-
return this.api.request({ url: "/api/" + PES
|
|
1967
|
-
this.emit(PES
|
|
2039
|
+
return this.api.request({ url: "/api/" + PES`${this.path}/${destination}`, body: { from: source } }).then((response) => {
|
|
2040
|
+
this.emit(PES`${this.path}/${destination}:c`, response);
|
|
1968
2041
|
return response;
|
|
1969
2042
|
});
|
|
1970
2043
|
}
|
|
1971
2044
|
delete(path) {
|
|
1972
2045
|
if (!path) throw new Error("Cannot delete file or folder, missing path");
|
|
1973
|
-
return this.api.request({ url: "/api/" + PES
|
|
1974
|
-
this.emit(PES
|
|
2046
|
+
return this.api.request({ url: "/api/" + PES`${this.path}/${path}`, method: "DELETE" }).then(() => {
|
|
2047
|
+
this.emit(PES`${this.path}/${path}:d`, path);
|
|
1975
2048
|
});
|
|
1976
2049
|
}
|
|
1977
2050
|
download(path, opts = {}) {
|
|
1978
2051
|
if (!path) throw new Error("Cannot download file, missing path");
|
|
1979
|
-
return this.api.request({ ...opts, url: "/api/" + PES
|
|
2052
|
+
return this.api.request({ ...opts, url: "/api/" + PES`${this.path}/${path}`, decode: false }).then(async (response) => {
|
|
1980
2053
|
const blob = await response.blob();
|
|
1981
2054
|
const name = opts.downloadAs || path.split("/").pop();
|
|
1982
|
-
this.emit(PES
|
|
2055
|
+
this.emit(PES`${this.path}/${path}:r`, blob);
|
|
1983
2056
|
downloadFile(blob, name);
|
|
1984
2057
|
return response;
|
|
1985
2058
|
});
|
|
1986
2059
|
}
|
|
1987
2060
|
list(path) {
|
|
1988
2061
|
if (!path) path = "/";
|
|
1989
|
-
return this.api.request({ url: "/api/" + PES
|
|
1990
|
-
this.emit(PES
|
|
2062
|
+
return this.api.request({ url: "/api/" + PES`${this.path}/${path}` + "?list" }).then((resp) => {
|
|
2063
|
+
this.emit(PES`${this.path}/${path}:r`, resp);
|
|
1991
2064
|
return resp;
|
|
1992
2065
|
});
|
|
1993
2066
|
}
|
|
1994
2067
|
open(path, target = "_blank") {
|
|
1995
2068
|
if (!path) throw new Error("Cannot download file, missing path");
|
|
1996
|
-
const link = `${this.api.url}/api/` + PES
|
|
2069
|
+
const link = `${this.api.url}/api/` + PES`${this.path}/${path}` + (this.api.token ? `?token=${this.api.token}` : "");
|
|
1997
2070
|
if (!target) return link;
|
|
1998
|
-
this.emit(PES
|
|
2071
|
+
this.emit(PES`${this.path}/${path}:r`, path);
|
|
1999
2072
|
return window.open(link, target);
|
|
2000
2073
|
}
|
|
2001
2074
|
mkdir(path) {
|
|
2002
2075
|
if (!path) throw new Error("Cannot make directory, missing path");
|
|
2003
|
-
return this.api.request({ url: "/api/" + PES
|
|
2004
|
-
this.emit(PES
|
|
2076
|
+
return this.api.request({ url: "/api/" + PES`${this.path}/${path}`, body: { directory: true } }).then((resp) => {
|
|
2077
|
+
this.emit(PES`${this.path}/${path}:c`, resp);
|
|
2005
2078
|
return resp;
|
|
2006
2079
|
});
|
|
2007
2080
|
}
|
|
2008
2081
|
move(source, destination) {
|
|
2009
2082
|
if (!source || !destination) throw new Error("Cannot move file or folder, missing source or destination");
|
|
2010
2083
|
if (source == destination) return this.list(destination);
|
|
2011
|
-
return this.api.request({ url: "/api/" + PES
|
|
2012
|
-
this.emit(PES
|
|
2084
|
+
return this.api.request({ url: "/api/" + PES`${this.path}/${source}`, method: "PATCH", body: { move: destination } }).then((response) => {
|
|
2085
|
+
this.emit(PES`${this.path}/${source}:u`, response);
|
|
2013
2086
|
return response;
|
|
2014
2087
|
});
|
|
2015
2088
|
}
|
|
@@ -2019,13 +2092,13 @@ ${log}`;
|
|
|
2019
2092
|
if (!files || Array.isArray(files) && !files.length) return [];
|
|
2020
2093
|
const path = (opts && typeof opts == "object" ? opts == null ? void 0 : opts.path : opts) || "/";
|
|
2021
2094
|
return uploadWithProgress({
|
|
2022
|
-
url: `${this.api.url}/api/` + PES
|
|
2095
|
+
url: `${this.api.url}/api/` + PES`${this.path}/${path}`,
|
|
2023
2096
|
files: makeArray(files),
|
|
2024
2097
|
headers: this.api.headers
|
|
2025
2098
|
}).onProgress((p) => {
|
|
2026
2099
|
prog(p);
|
|
2027
2100
|
}).then((resp) => {
|
|
2028
|
-
this.emit(PES
|
|
2101
|
+
this.emit(PES`${this.path}/${path}:c`, resp);
|
|
2029
2102
|
res(resp);
|
|
2030
2103
|
}).catch((err) => rej(err));
|
|
2031
2104
|
});
|
|
@@ -2140,32 +2213,9 @@ ${log}`;
|
|
|
2140
2213
|
});
|
|
2141
2214
|
}
|
|
2142
2215
|
}
|
|
2143
|
-
class Static extends
|
|
2216
|
+
class Static extends Storage$1 {
|
|
2144
2217
|
constructor(api) {
|
|
2145
|
-
super();
|
|
2146
|
-
__publicField(this, "api");
|
|
2147
|
-
this.api = typeof api == "string" ? new Api(api) : api;
|
|
2148
|
-
}
|
|
2149
|
-
delete(path) {
|
|
2150
|
-
if (!path) throw new Error("Cannot delete static asset, missing path");
|
|
2151
|
-
return this.api.request({ url: `/api/` + PES`static/${path}`, method: "DELETE" }).then(() => {
|
|
2152
|
-
this.emit(PES`static/${path}:d`, path);
|
|
2153
|
-
});
|
|
2154
|
-
}
|
|
2155
|
-
upload(files, path = "/") {
|
|
2156
|
-
if (!files) throw new Error("Cannot upload static assets, missing file");
|
|
2157
|
-
return new PromiseProgress(async (res, rej, prog) => {
|
|
2158
|
-
return uploadWithProgress({
|
|
2159
|
-
url: this.api.url + "/api/" + PES`static/${path}`,
|
|
2160
|
-
files: makeArray(files),
|
|
2161
|
-
headers: this.api.headers
|
|
2162
|
-
}).onProgress((p) => {
|
|
2163
|
-
prog(p);
|
|
2164
|
-
}).then((resp) => {
|
|
2165
|
-
this.emit(PES`static/${path}:c`, resp);
|
|
2166
|
-
res(resp);
|
|
2167
|
-
}).catch((err) => rej(err));
|
|
2168
|
-
});
|
|
2218
|
+
super(api, "static");
|
|
2169
2219
|
}
|
|
2170
2220
|
}
|
|
2171
2221
|
class Momentum extends PathEventEmitter {
|
|
@@ -2194,7 +2244,7 @@ ${log}`;
|
|
|
2194
2244
|
this.actions = new Actions(this.api);
|
|
2195
2245
|
this.ai = new Ai(this.api);
|
|
2196
2246
|
this.analytics = new Analytics(this.api);
|
|
2197
|
-
this.auth = new Auth(this.api,
|
|
2247
|
+
this.auth = new Auth(this.api, opts);
|
|
2198
2248
|
this.data = new Data(this.api);
|
|
2199
2249
|
this.email = new Email(this.api);
|
|
2200
2250
|
this.forms = new Forms(this.api);
|
|
@@ -2260,6 +2310,8 @@ ${log}`;
|
|
|
2260
2310
|
exports2.Socket = Socket;
|
|
2261
2311
|
exports2.Static = Static;
|
|
2262
2312
|
exports2.Storage = Storage$1;
|
|
2313
|
+
exports2.Token = Token;
|
|
2314
|
+
exports2.Totp = Totp;
|
|
2263
2315
|
exports2.Users = Users;
|
|
2264
2316
|
Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
|
|
2265
2317
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -1124,10 +1124,51 @@ class Analytics extends PathEventEmitter {
|
|
|
1124
1124
|
});
|
|
1125
1125
|
}
|
|
1126
1126
|
}
|
|
1127
|
+
class Token extends PathEventEmitter {
|
|
1128
|
+
constructor(api) {
|
|
1129
|
+
super();
|
|
1130
|
+
this.api = api;
|
|
1131
|
+
}
|
|
1132
|
+
all(username) {
|
|
1133
|
+
return this.api.request({ url: "/" + PES`api/auth/tokens/${username}` }).then((resp) => {
|
|
1134
|
+
this.emit(PES`token/${username}:r`, resp);
|
|
1135
|
+
return resp;
|
|
1136
|
+
});
|
|
1137
|
+
}
|
|
1138
|
+
create(token) {
|
|
1139
|
+
return this.api.request({ url: "/" + PES`api/auth/tokens/${token.owner}`, body: token }).then((resp) => {
|
|
1140
|
+
this.emit(PES`token/${token.owner}:c`, token);
|
|
1141
|
+
return resp;
|
|
1142
|
+
});
|
|
1143
|
+
}
|
|
1144
|
+
delete(id) {
|
|
1145
|
+
return this.api.request({ url: "/" + PES`api/auth/tokens/${id}`, method: "DELETE" }).then(() => this.emit(PES`token/${id}:d`, id));
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
class Totp {
|
|
1149
|
+
constructor(api) {
|
|
1150
|
+
__publicField(this, "enable", this.reset);
|
|
1151
|
+
this.api = api;
|
|
1152
|
+
}
|
|
1153
|
+
disable(username) {
|
|
1154
|
+
return this.api.request({ url: "/" + PES`api/auth/totp/${username}`, method: "DELETE" });
|
|
1155
|
+
}
|
|
1156
|
+
reset(username) {
|
|
1157
|
+
return this.api.request({ url: "/" + PES`api/auth/totp/${username}`, method: "POST" });
|
|
1158
|
+
}
|
|
1159
|
+
setup(username, method = "app", totp) {
|
|
1160
|
+
return this.api.request({ url: "/" + PES`api/auth/totp/${username}`, body: clean({
|
|
1161
|
+
method,
|
|
1162
|
+
totp
|
|
1163
|
+
}) });
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1127
1166
|
class Auth extends PathEventEmitter {
|
|
1128
1167
|
constructor(api, opts = {}) {
|
|
1129
1168
|
super();
|
|
1130
1169
|
__publicField(this, "api");
|
|
1170
|
+
__publicField(this, "token");
|
|
1171
|
+
__publicField(this, "totp");
|
|
1131
1172
|
__publicField(this, "_permissions", []);
|
|
1132
1173
|
__publicField(this, "_user");
|
|
1133
1174
|
// Permission helpers
|
|
@@ -1136,9 +1177,11 @@ class Auth extends PathEventEmitter {
|
|
|
1136
1177
|
__publicField(this, "hasAll", (...events) => PathEvent.hasAll(this.permissions, ...events));
|
|
1137
1178
|
__publicField(this, "hasFatal", (...events) => PathEvent.hasFatal(this.permissions, ...events));
|
|
1138
1179
|
__publicField(this, "hasAllFatal", (...events) => PathEvent.hasAllFatal(this.permissions, ...events));
|
|
1139
|
-
__publicField(this, "enableTotp", this.resetTotp);
|
|
1140
1180
|
this.opts = opts;
|
|
1141
1181
|
this.api = typeof api == "string" ? new Api(api) : api;
|
|
1182
|
+
this.token = new Token(this.api);
|
|
1183
|
+
this.totp = new Totp(this.api);
|
|
1184
|
+
this.relayEvents(this.token);
|
|
1142
1185
|
this.opts = {
|
|
1143
1186
|
loginUrl: this.api.url + "/ui/#/login",
|
|
1144
1187
|
...this.opts
|
|
@@ -1181,17 +1224,17 @@ class Auth extends PathEventEmitter {
|
|
|
1181
1224
|
if (host.startsWith("/")) return Promise.resolve();
|
|
1182
1225
|
return this.api.request({ url: `/api/auth/known-host?host=${encodeURI(new URL(host).origin)}` });
|
|
1183
1226
|
}
|
|
1184
|
-
login(username, password,
|
|
1227
|
+
login(username, password, opts) {
|
|
1185
1228
|
if (!username || !password) throw new Error("Cannot login, missing username or password");
|
|
1186
1229
|
return this.api.request({
|
|
1187
1230
|
url: "/api/auth/login",
|
|
1188
1231
|
headers: { Authorization: void 0 },
|
|
1189
1232
|
method: "POST",
|
|
1190
|
-
body: {
|
|
1233
|
+
body: clean({
|
|
1191
1234
|
username: username.trim(),
|
|
1192
1235
|
password: password.trim(),
|
|
1193
|
-
|
|
1194
|
-
}
|
|
1236
|
+
...opts
|
|
1237
|
+
}, true)
|
|
1195
1238
|
}).then(async (resp) => {
|
|
1196
1239
|
this.api.token = (resp == null ? void 0 : resp.token) || null;
|
|
1197
1240
|
const user = await this.once("auth/user");
|
|
@@ -1267,19 +1310,6 @@ class Auth extends PathEventEmitter {
|
|
|
1267
1310
|
if (resp == null ? void 0 : resp.token) this.api.token = resp.token;
|
|
1268
1311
|
});
|
|
1269
1312
|
}
|
|
1270
|
-
// TOTP ============================================================================================================
|
|
1271
|
-
disableTotp(username) {
|
|
1272
|
-
return this.api.request({ url: `/api/auth/totp/${username}`, method: "DELETE" });
|
|
1273
|
-
}
|
|
1274
|
-
resetTotp(username) {
|
|
1275
|
-
return this.api.request({ url: `/api/auth/totp/${username}`, method: "POST" });
|
|
1276
|
-
}
|
|
1277
|
-
setupTotp(username, method = "app", totp) {
|
|
1278
|
-
return this.api.request({ url: `/api/auth/totp/${username}`, body: clean({
|
|
1279
|
-
method,
|
|
1280
|
-
totp
|
|
1281
|
-
}) });
|
|
1282
|
-
}
|
|
1283
1313
|
}
|
|
1284
1314
|
class Client extends PathEventEmitter {
|
|
1285
1315
|
constructor(api, settings) {
|
|
@@ -1316,11 +1346,14 @@ class Client extends PathEventEmitter {
|
|
|
1316
1346
|
get pushSubscription() {
|
|
1317
1347
|
var _a;
|
|
1318
1348
|
if (!((_a = navigator.serviceWorker) == null ? void 0 : _a.controller)) return Promise.resolve(null);
|
|
1319
|
-
return navigator.serviceWorker.ready.then((sw) =>
|
|
1349
|
+
return navigator.serviceWorker.ready.then((sw) => {
|
|
1350
|
+
var _a2;
|
|
1351
|
+
return (_a2 = sw == null ? void 0 : sw.pushManager) == null ? void 0 : _a2.getSubscription();
|
|
1352
|
+
});
|
|
1320
1353
|
}
|
|
1321
1354
|
get pwa() {
|
|
1322
1355
|
if (this._pwa == null)
|
|
1323
|
-
this._pwa =
|
|
1356
|
+
this._pwa = matchMedia("(display-mode: standalone)").matches || (navigator == null ? void 0 : navigator.standalone) || document.referrer.includes("android-app://");
|
|
1324
1357
|
return this._pwa;
|
|
1325
1358
|
}
|
|
1326
1359
|
async inject(reload = false, firstLoad = true) {
|
|
@@ -1328,6 +1361,50 @@ class Client extends PathEventEmitter {
|
|
|
1328
1361
|
let settings = this.settings.cache;
|
|
1329
1362
|
if (firstLoad) this.settings.all(false, reload).then(() => this.inject(false, false)).catch(() => {
|
|
1330
1363
|
});
|
|
1364
|
+
if (settings["title"] && !document.head.querySelector('meta[property="og:title"]')) {
|
|
1365
|
+
const meta = document.createElement("meta");
|
|
1366
|
+
meta.setAttribute("property", "og:title");
|
|
1367
|
+
meta.content = settings["title"];
|
|
1368
|
+
document.head.append(meta);
|
|
1369
|
+
}
|
|
1370
|
+
if (!document.querySelector('meta[property="og:type"]')) {
|
|
1371
|
+
const meta = document.createElement("meta");
|
|
1372
|
+
meta.setAttribute("property", "og:type");
|
|
1373
|
+
meta.content = "article";
|
|
1374
|
+
document.head.append(meta);
|
|
1375
|
+
}
|
|
1376
|
+
if (settings["public_url"] && !document.querySelector('meta[property="og:url"]')) {
|
|
1377
|
+
const meta = document.createElement("meta");
|
|
1378
|
+
meta.setAttribute("property", "og:url");
|
|
1379
|
+
meta.content = settings["public_url"];
|
|
1380
|
+
document.head.append(meta);
|
|
1381
|
+
}
|
|
1382
|
+
if (settings["description"]) {
|
|
1383
|
+
if (!document.querySelector('meta[property="og:description"]')) {
|
|
1384
|
+
const meta = document.createElement("meta");
|
|
1385
|
+
meta.setAttribute("property", "og:description");
|
|
1386
|
+
meta.content = settings["description"];
|
|
1387
|
+
document.head.append(meta);
|
|
1388
|
+
}
|
|
1389
|
+
if (!document.querySelector('meta[property="description"]')) {
|
|
1390
|
+
const meta = document.createElement("meta");
|
|
1391
|
+
meta.setAttribute("property", "description");
|
|
1392
|
+
meta.content = settings["description"];
|
|
1393
|
+
document.head.append(meta);
|
|
1394
|
+
}
|
|
1395
|
+
if (!document.querySelector('meta[property="twitter:card"]')) {
|
|
1396
|
+
const meta = document.createElement("meta");
|
|
1397
|
+
meta.setAttribute("property", "twitter:card");
|
|
1398
|
+
meta.content = settings["description"];
|
|
1399
|
+
document.head.append(meta);
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
if (settings["public_url"] && !document.querySelector('meta[property="og:image"]')) {
|
|
1403
|
+
const meta = document.createElement("meta");
|
|
1404
|
+
meta.setAttribute("property", "og:image");
|
|
1405
|
+
meta.content = settings["public_url"] + "/favicon.ico";
|
|
1406
|
+
document.head.append(meta);
|
|
1407
|
+
}
|
|
1331
1408
|
if (!document.querySelector('meta[name="mobile-web-app-capable"]')) {
|
|
1332
1409
|
const meta = document.createElement("meta");
|
|
1333
1410
|
meta.name = "mobile-web-app-capable";
|
|
@@ -1340,46 +1417,41 @@ class Client extends PathEventEmitter {
|
|
|
1340
1417
|
meta.content = "default";
|
|
1341
1418
|
document.head.append(meta);
|
|
1342
1419
|
}
|
|
1343
|
-
if (!document.querySelector('meta[name="apple-mobile-web-app-title"]')) {
|
|
1420
|
+
if (settings["title"] && !document.querySelector('meta[name="apple-mobile-web-app-title"]')) {
|
|
1344
1421
|
const meta = document.createElement("meta");
|
|
1345
1422
|
meta.name = "apple-mobile-web-app-title";
|
|
1346
1423
|
meta.content = settings["title"];
|
|
1347
1424
|
document.head.append(meta);
|
|
1348
1425
|
}
|
|
1349
|
-
if (!document.querySelector('link[rel="apple-touch-icon"]')) {
|
|
1426
|
+
if (settings["public_url"] && !document.querySelector('link[rel="apple-touch-icon"]')) {
|
|
1350
1427
|
const meta = document.createElement("link");
|
|
1351
1428
|
meta.rel = "apple-touch-icon";
|
|
1352
|
-
meta.href = settings["
|
|
1429
|
+
meta.href = settings["public_url"] + "/favicon.ico";
|
|
1353
1430
|
document.head.append(meta);
|
|
1354
1431
|
}
|
|
1355
|
-
if (!document.querySelector('link[rel="apple-touch-startup-image"]')) {
|
|
1432
|
+
if (settings["public_url"] && !document.querySelector('link[rel="apple-touch-startup-image"]')) {
|
|
1356
1433
|
const meta = document.createElement("link");
|
|
1357
1434
|
meta.rel = "apple-touch-startup-image";
|
|
1358
|
-
meta.href = settings["
|
|
1435
|
+
meta.href = settings["public_url"] + "/favicon.ico";
|
|
1359
1436
|
document.head.append(meta);
|
|
1360
1437
|
}
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
if (settings["
|
|
1364
|
-
|
|
1365
|
-
if (settings["description"])
|
|
1366
|
-
window.document.querySelectorAll(".momentum-description").forEach((el) => el.innerText = settings["description"]);
|
|
1367
|
-
if (settings.version)
|
|
1368
|
-
window.document.querySelectorAll(".momentum-version").forEach((el) => el.innerText = settings["version"]);
|
|
1369
|
-
if (settings["logo"]) {
|
|
1370
|
-
window.document.querySelectorAll(".momentum-logo").forEach((el) => el.src = settings["logo"]);
|
|
1371
|
-
}
|
|
1438
|
+
if (settings["title"]) document.querySelectorAll(".momentum-title").forEach((el) => el.innerText = settings["title"]);
|
|
1439
|
+
if (settings["description"]) document.querySelectorAll(".momentum-description").forEach((el) => el.innerText = settings["description"]);
|
|
1440
|
+
if (settings["version"]) document.querySelectorAll(".momentum-version").forEach((el) => el.innerText = settings["version"]);
|
|
1441
|
+
if (settings["logo"]) document.querySelectorAll(".momentum-logo").forEach((el) => el.src = settings["logo"]);
|
|
1372
1442
|
if (settings["theme"]) {
|
|
1443
|
+
document.body.classList.add(((_a = settings["theme"]) == null ? void 0 : _a.darkMode) ? "theme-dark" : "theme-light");
|
|
1444
|
+
document.body.classList.remove(((_b = settings["theme"]) == null ? void 0 : _b.darkMode) ? "theme-light" : "theme-dark");
|
|
1373
1445
|
document.body.style.setProperty("--theme-backdrop", (_c = settings["theme"]) == null ? void 0 : _c.background);
|
|
1374
1446
|
document.body.style.setProperty("--theme-primary", (_d = settings["theme"]) == null ? void 0 : _d.primary);
|
|
1375
1447
|
document.body.style.setProperty("--theme-accent", (_e = settings["theme"]) == null ? void 0 : _e.accent);
|
|
1376
1448
|
document.body.style.setProperty("--theme-contrast", blackOrWhite((_f = settings["theme"]) == null ? void 0 : _f.background));
|
|
1377
1449
|
}
|
|
1378
1450
|
if (settings["pwa"]) {
|
|
1379
|
-
const link =
|
|
1451
|
+
const link = document.createElement("link");
|
|
1380
1452
|
link.setAttribute("rel", "manifest");
|
|
1381
1453
|
link.setAttribute("href", this.settings.api.url + "/manifest.json");
|
|
1382
|
-
|
|
1454
|
+
document.head.append(link);
|
|
1383
1455
|
setTimeout(() => {
|
|
1384
1456
|
const dismissed = !!localStorage.getItem("momentum:install-prompt");
|
|
1385
1457
|
if (!dismissed && !this.pwa && this.mobile) this.pwaPrompt();
|
|
@@ -1952,60 +2024,61 @@ const _Socket = class _Socket {
|
|
|
1952
2024
|
__publicField(_Socket, "pollingSpeed", 3e4);
|
|
1953
2025
|
let Socket = _Socket;
|
|
1954
2026
|
let Storage$1 = class Storage2 extends PathEventEmitter {
|
|
1955
|
-
constructor(api) {
|
|
2027
|
+
constructor(api, path = "storage") {
|
|
1956
2028
|
super();
|
|
1957
2029
|
__publicField(this, "api");
|
|
2030
|
+
this.path = path;
|
|
1958
2031
|
this.api = typeof api == "string" ? new Api(api) : api;
|
|
1959
2032
|
}
|
|
1960
2033
|
copy(source, destination) {
|
|
1961
2034
|
if (!source || !destination) throw new Error("Cannot copy file or folder, missing source or destination");
|
|
1962
|
-
return this.api.request({ url: "/api/" + PES
|
|
1963
|
-
this.emit(PES
|
|
2035
|
+
return this.api.request({ url: "/api/" + PES`${this.path}/${destination}`, body: { from: source } }).then((response) => {
|
|
2036
|
+
this.emit(PES`${this.path}/${destination}:c`, response);
|
|
1964
2037
|
return response;
|
|
1965
2038
|
});
|
|
1966
2039
|
}
|
|
1967
2040
|
delete(path) {
|
|
1968
2041
|
if (!path) throw new Error("Cannot delete file or folder, missing path");
|
|
1969
|
-
return this.api.request({ url: "/api/" + PES
|
|
1970
|
-
this.emit(PES
|
|
2042
|
+
return this.api.request({ url: "/api/" + PES`${this.path}/${path}`, method: "DELETE" }).then(() => {
|
|
2043
|
+
this.emit(PES`${this.path}/${path}:d`, path);
|
|
1971
2044
|
});
|
|
1972
2045
|
}
|
|
1973
2046
|
download(path, opts = {}) {
|
|
1974
2047
|
if (!path) throw new Error("Cannot download file, missing path");
|
|
1975
|
-
return this.api.request({ ...opts, url: "/api/" + PES
|
|
2048
|
+
return this.api.request({ ...opts, url: "/api/" + PES`${this.path}/${path}`, decode: false }).then(async (response) => {
|
|
1976
2049
|
const blob = await response.blob();
|
|
1977
2050
|
const name = opts.downloadAs || path.split("/").pop();
|
|
1978
|
-
this.emit(PES
|
|
2051
|
+
this.emit(PES`${this.path}/${path}:r`, blob);
|
|
1979
2052
|
downloadFile(blob, name);
|
|
1980
2053
|
return response;
|
|
1981
2054
|
});
|
|
1982
2055
|
}
|
|
1983
2056
|
list(path) {
|
|
1984
2057
|
if (!path) path = "/";
|
|
1985
|
-
return this.api.request({ url: "/api/" + PES
|
|
1986
|
-
this.emit(PES
|
|
2058
|
+
return this.api.request({ url: "/api/" + PES`${this.path}/${path}` + "?list" }).then((resp) => {
|
|
2059
|
+
this.emit(PES`${this.path}/${path}:r`, resp);
|
|
1987
2060
|
return resp;
|
|
1988
2061
|
});
|
|
1989
2062
|
}
|
|
1990
2063
|
open(path, target = "_blank") {
|
|
1991
2064
|
if (!path) throw new Error("Cannot download file, missing path");
|
|
1992
|
-
const link = `${this.api.url}/api/` + PES
|
|
2065
|
+
const link = `${this.api.url}/api/` + PES`${this.path}/${path}` + (this.api.token ? `?token=${this.api.token}` : "");
|
|
1993
2066
|
if (!target) return link;
|
|
1994
|
-
this.emit(PES
|
|
2067
|
+
this.emit(PES`${this.path}/${path}:r`, path);
|
|
1995
2068
|
return window.open(link, target);
|
|
1996
2069
|
}
|
|
1997
2070
|
mkdir(path) {
|
|
1998
2071
|
if (!path) throw new Error("Cannot make directory, missing path");
|
|
1999
|
-
return this.api.request({ url: "/api/" + PES
|
|
2000
|
-
this.emit(PES
|
|
2072
|
+
return this.api.request({ url: "/api/" + PES`${this.path}/${path}`, body: { directory: true } }).then((resp) => {
|
|
2073
|
+
this.emit(PES`${this.path}/${path}:c`, resp);
|
|
2001
2074
|
return resp;
|
|
2002
2075
|
});
|
|
2003
2076
|
}
|
|
2004
2077
|
move(source, destination) {
|
|
2005
2078
|
if (!source || !destination) throw new Error("Cannot move file or folder, missing source or destination");
|
|
2006
2079
|
if (source == destination) return this.list(destination);
|
|
2007
|
-
return this.api.request({ url: "/api/" + PES
|
|
2008
|
-
this.emit(PES
|
|
2080
|
+
return this.api.request({ url: "/api/" + PES`${this.path}/${source}`, method: "PATCH", body: { move: destination } }).then((response) => {
|
|
2081
|
+
this.emit(PES`${this.path}/${source}:u`, response);
|
|
2009
2082
|
return response;
|
|
2010
2083
|
});
|
|
2011
2084
|
}
|
|
@@ -2015,13 +2088,13 @@ let Storage$1 = class Storage2 extends PathEventEmitter {
|
|
|
2015
2088
|
if (!files || Array.isArray(files) && !files.length) return [];
|
|
2016
2089
|
const path = (opts && typeof opts == "object" ? opts == null ? void 0 : opts.path : opts) || "/";
|
|
2017
2090
|
return uploadWithProgress({
|
|
2018
|
-
url: `${this.api.url}/api/` + PES
|
|
2091
|
+
url: `${this.api.url}/api/` + PES`${this.path}/${path}`,
|
|
2019
2092
|
files: makeArray(files),
|
|
2020
2093
|
headers: this.api.headers
|
|
2021
2094
|
}).onProgress((p) => {
|
|
2022
2095
|
prog(p);
|
|
2023
2096
|
}).then((resp) => {
|
|
2024
|
-
this.emit(PES
|
|
2097
|
+
this.emit(PES`${this.path}/${path}:c`, resp);
|
|
2025
2098
|
res(resp);
|
|
2026
2099
|
}).catch((err) => rej(err));
|
|
2027
2100
|
});
|
|
@@ -2136,32 +2209,9 @@ class Settings extends PathEventEmitter {
|
|
|
2136
2209
|
});
|
|
2137
2210
|
}
|
|
2138
2211
|
}
|
|
2139
|
-
class Static extends
|
|
2212
|
+
class Static extends Storage$1 {
|
|
2140
2213
|
constructor(api) {
|
|
2141
|
-
super();
|
|
2142
|
-
__publicField(this, "api");
|
|
2143
|
-
this.api = typeof api == "string" ? new Api(api) : api;
|
|
2144
|
-
}
|
|
2145
|
-
delete(path) {
|
|
2146
|
-
if (!path) throw new Error("Cannot delete static asset, missing path");
|
|
2147
|
-
return this.api.request({ url: `/api/` + PES`static/${path}`, method: "DELETE" }).then(() => {
|
|
2148
|
-
this.emit(PES`static/${path}:d`, path);
|
|
2149
|
-
});
|
|
2150
|
-
}
|
|
2151
|
-
upload(files, path = "/") {
|
|
2152
|
-
if (!files) throw new Error("Cannot upload static assets, missing file");
|
|
2153
|
-
return new PromiseProgress(async (res, rej, prog) => {
|
|
2154
|
-
return uploadWithProgress({
|
|
2155
|
-
url: this.api.url + "/api/" + PES`static/${path}`,
|
|
2156
|
-
files: makeArray(files),
|
|
2157
|
-
headers: this.api.headers
|
|
2158
|
-
}).onProgress((p) => {
|
|
2159
|
-
prog(p);
|
|
2160
|
-
}).then((resp) => {
|
|
2161
|
-
this.emit(PES`static/${path}:c`, resp);
|
|
2162
|
-
res(resp);
|
|
2163
|
-
}).catch((err) => rej(err));
|
|
2164
|
-
});
|
|
2214
|
+
super(api, "static");
|
|
2165
2215
|
}
|
|
2166
2216
|
}
|
|
2167
2217
|
class Momentum extends PathEventEmitter {
|
|
@@ -2190,7 +2240,7 @@ class Momentum extends PathEventEmitter {
|
|
|
2190
2240
|
this.actions = new Actions(this.api);
|
|
2191
2241
|
this.ai = new Ai(this.api);
|
|
2192
2242
|
this.analytics = new Analytics(this.api);
|
|
2193
|
-
this.auth = new Auth(this.api,
|
|
2243
|
+
this.auth = new Auth(this.api, opts);
|
|
2194
2244
|
this.data = new Data(this.api);
|
|
2195
2245
|
this.email = new Email(this.api);
|
|
2196
2246
|
this.forms = new Forms(this.api);
|
|
@@ -2257,5 +2307,7 @@ export {
|
|
|
2257
2307
|
Socket,
|
|
2258
2308
|
Static,
|
|
2259
2309
|
Storage$1 as Storage,
|
|
2310
|
+
Token,
|
|
2311
|
+
Totp,
|
|
2260
2312
|
Users
|
|
2261
2313
|
};
|
package/dist/static.d.ts
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import { Api } from './api';
|
|
2
|
-
import {
|
|
3
|
-
export declare class Static extends
|
|
4
|
-
private readonly api;
|
|
2
|
+
import { Storage } from './storage';
|
|
3
|
+
export declare class Static extends Storage {
|
|
5
4
|
constructor(api: Api | string);
|
|
6
|
-
delete(path: string): Promise<void>;
|
|
7
|
-
upload(files: File | File[], path?: string): PromiseProgress<string[]>;
|
|
8
5
|
}
|
|
9
6
|
//# sourceMappingURL=static.d.ts.map
|
package/dist/static.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"static.d.ts","sourceRoot":"","sources":["../src/static.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,GAAG,EAAC,MAAM,OAAO,CAAC;AAC1B,OAAO,
|
|
1
|
+
{"version":3,"file":"static.d.ts","sourceRoot":"","sources":["../src/static.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,GAAG,EAAC,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAC;AAElC,qBAAa,MAAO,SAAQ,OAAO;gBACtB,GAAG,EAAE,GAAG,GAAG,MAAM;CAG7B"}
|
package/dist/storage.d.ts
CHANGED
|
@@ -16,8 +16,9 @@ export type FileMeta = Meta & {
|
|
|
16
16
|
missing?: boolean;
|
|
17
17
|
};
|
|
18
18
|
export declare class Storage extends PathEventEmitter {
|
|
19
|
+
private readonly path;
|
|
19
20
|
readonly api: Api;
|
|
20
|
-
constructor(api: Api | string);
|
|
21
|
+
constructor(api: Api | string, path?: string);
|
|
21
22
|
copy(source: string, destination: string): Promise<DirMeta | FileMeta>;
|
|
22
23
|
delete(path: string): Promise<void>;
|
|
23
24
|
download(path: string, opts?: HttpRequestOptions & {
|
package/dist/storage.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,GAAG,EAAC,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAC,KAAK,IAAI,EAAC,MAAM,QAAQ,CAAC;AACjC,OAAO,EACN,eAAe,EACf,kBAAkB,EAKlB,gBAAgB,EAChB,MAAM,gBAAgB,CAAC;AAExB,MAAM,MAAM,OAAO,GAAG;IACrB,QAAQ,EAAE,CAAC,OAAO,GAAG,QAAQ,CAAC,EAAE,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACb,CAAA;AAED,MAAM,MAAM,QAAQ,GAAG,IAAI,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB,CAAA;AAED,qBAAa,OAAQ,SAAQ,gBAAgB;
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,GAAG,EAAC,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAC,KAAK,IAAI,EAAC,MAAM,QAAQ,CAAC;AACjC,OAAO,EACN,eAAe,EACf,kBAAkB,EAKlB,gBAAgB,EAChB,MAAM,gBAAgB,CAAC;AAExB,MAAM,MAAM,OAAO,GAAG;IACrB,QAAQ,EAAE,CAAC,OAAO,GAAG,QAAQ,CAAC,EAAE,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACb,CAAA;AAED,MAAM,MAAM,QAAQ,GAAG,IAAI,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB,CAAA;AAED,qBAAa,OAAQ,SAAQ,gBAAgB;IAGb,OAAO,CAAC,QAAQ,CAAC,IAAI;IAFpD,QAAQ,CAAC,GAAG,EAAG,GAAG,CAAC;gBAEP,GAAG,EAAE,GAAG,GAAG,MAAM,EAAmB,IAAI,GAAE,MAAkB;IAKxE,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,QAAQ,CAAC;IAQtE,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOnC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,kBAAkB,GAAG;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAM,GAAG,eAAe,CAAC,IAAI,CAAC;IAWtG,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,QAAQ,CAAC;IAQhD,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,GAAG,MAAM;IACzC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,IAAI;IAS9D,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAQrC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,QAAQ,CAAC;IAStE,MAAM,CAAC,KAAK,CAAC,EAAE,IAAI,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAC,GAAG,eAAe,CAAC,QAAQ,EAAE,CAAC;CAiBvI"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ztimson/momentum",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.51.0",
|
|
4
4
|
"description": "Client library for momentum",
|
|
5
5
|
"keywords": ["Momentum"],
|
|
6
6
|
"author": "Zak Timson <zaktimson@gmail.com>",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"postbuild": "node -e \"const fs=require('fs');fs.cpSync('dist/index.mjs','../server/public/momentum.mjs');fs.cpSync('dist/index.cjs','../server/public/momentum.js')\""
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@ztimson/utils": "0.23.
|
|
27
|
+
"@ztimson/utils": "0.23.8",
|
|
28
28
|
"var-persist": "^1.0.1"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|