@ztimson/momentum 0.21.0 → 0.27.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/README.md +44 -32
- package/dist/actions.d.ts +1 -2
- package/dist/actions.js +70 -0
- package/dist/api.d.ts +1 -2
- package/dist/api.js +40 -0
- package/dist/auth.d.ts +16 -9
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +164 -0
- package/dist/core.js +2 -0
- package/dist/data.d.ts +2 -3
- package/dist/data.js +48 -0
- package/dist/email.d.ts +1 -2
- package/dist/email.js +22 -0
- package/dist/groups.d.ts +3 -4
- package/dist/groups.d.ts.map +1 -1
- package/dist/groups.js +51 -0
- package/dist/index.js +31 -0
- package/dist/index.mjs +1 -0
- package/dist/logger.d.ts +0 -1
- package/dist/logger.js +59 -0
- package/dist/momentum.d.ts +9 -10
- package/dist/momentum.js +74 -0
- package/dist/pdf.d.ts +7 -13
- package/dist/pdf.d.ts.map +1 -1
- package/dist/pdf.js +34 -0
- package/dist/settings.d.ts +1 -2
- package/dist/settings.js +48 -0
- package/dist/sockets.d.ts +0 -1
- package/dist/sockets.js +54 -0
- package/dist/static.d.ts +2 -3
- package/dist/static.js +33 -0
- package/dist/storage.d.ts +2 -3
- package/dist/storage.js +99 -0
- package/dist/users.d.ts +10 -8
- package/dist/users.d.ts.map +1 -1
- package/dist/users.js +76 -0
- package/package.json +13 -16
- package/dist/momentum.cjs +0 -4
- package/dist/momentum.cjs.map +0 -1
- package/dist/momentum.mjs +0 -1307
- package/dist/momentum.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -42,47 +42,59 @@
|
|
|
42
42
|
|
|
43
43
|
Momentum is a self-hosted server development platform. What does that mean? Think something similar to [Firebase](https://firebase.google.com) but you are in full control of your data & services.
|
|
44
44
|
|
|
45
|
-
It was developed as a generic
|
|
45
|
+
It was developed as a generic backend to add functionality to single page applications such as angular, react, svelte or vue. Momentum comes with a client library to make integration extremely easy.
|
|
46
|
+
|
|
47
|
+
Momentum also comes with a management interface to allow easy administration of momentum without having to build anything.
|
|
46
48
|
|
|
47
49
|
Features include:
|
|
48
|
-
-
|
|
49
|
-
-
|
|
50
|
-
-
|
|
51
|
-
-
|
|
52
|
-
|
|
53
|
-
-
|
|
50
|
+
- Actions
|
|
51
|
+
- Write server side code to create custom functionality
|
|
52
|
+
- Writen with javascript & the momentum client library to minimize the learning curve
|
|
53
|
+
- Custom library and can be installed & accessed from actions using Docker & NPM
|
|
54
|
+
- Trigger actions including CRONs, RESTFUL requests & system events
|
|
55
|
+
- Extremely fast
|
|
54
56
|
- Authentication
|
|
55
|
-
- Manage users
|
|
56
|
-
-
|
|
57
|
+
- Manage users with custom values
|
|
58
|
+
- Manage groups with cascading permissions & custom values
|
|
59
|
+
- Token management for 3rd party applications
|
|
60
|
+
- Full permission system which supports custom values
|
|
57
61
|
- Account validation & reset emails
|
|
58
|
-
-
|
|
59
|
-
-
|
|
60
|
-
- Custom
|
|
61
|
-
-
|
|
62
|
+
- Optional public registration form
|
|
63
|
+
- OAuth support for custom applications
|
|
64
|
+
- Custom password strength rules
|
|
65
|
+
- Two-Factor Authentication
|
|
62
66
|
- Data
|
|
63
|
-
-
|
|
67
|
+
- Edit database like an Excel table
|
|
68
|
+
- Create custom forms & reports to interact with data
|
|
69
|
+
- Interact with data through the REST API
|
|
64
70
|
- Granular collection & document level permissions
|
|
65
|
-
-
|
|
66
|
-
-
|
|
67
|
-
-
|
|
68
|
-
-
|
|
69
|
-
-
|
|
70
|
-
-
|
|
71
|
-
|
|
72
|
-
-
|
|
73
|
-
|
|
74
|
-
- Upload files
|
|
75
|
-
-
|
|
76
|
-
-
|
|
77
|
-
|
|
78
|
-
- [Static File Server](https://git.zakscode.com/ztimson/momentum/wiki/Static)
|
|
71
|
+
- Automatic metadata tracking
|
|
72
|
+
- Easy import/export to CSV, Excel & JSON
|
|
73
|
+
- Logs
|
|
74
|
+
- Save & view server logs through the UI for easy debugging
|
|
75
|
+
- Submit client logs to momentum to aid in remote debugging
|
|
76
|
+
- Client logs come with device information such as user agent & screen size
|
|
77
|
+
- Storage
|
|
78
|
+
- Storage anything with momentum storage
|
|
79
|
+
- Built in filebrowser
|
|
80
|
+
- Upload & download files with the API
|
|
81
|
+
- Full file permissions
|
|
82
|
+
- Automatic metadata tracking
|
|
83
|
+
- Static File Server
|
|
79
84
|
- Host your single page application using Momentum for easy hosting
|
|
80
|
-
-
|
|
81
|
-
|
|
82
|
-
|
|
85
|
+
- Configurable routing
|
|
86
|
+
- Settings
|
|
87
|
+
- Full theming & white label support
|
|
83
88
|
- Manage the server through variables which can be changed at runtime
|
|
84
89
|
- Create & use custom variables for your application
|
|
85
|
-
|
|
90
|
+
- Miscellaneous
|
|
91
|
+
- Automatically turn website into Progressive Web App
|
|
92
|
+
- Caching & offline support built into the client library
|
|
93
|
+
- Socket support to keep all clients in sync automatically
|
|
94
|
+
- Generate PDFs from templates, HTML or links
|
|
95
|
+
- SMTP support to send emails from templates
|
|
96
|
+
- Twilio support to manage texts & calls
|
|
97
|
+
- Stripe support to handle payments & subscriptions
|
|
86
98
|
|
|
87
99
|
### Built With
|
|
88
100
|
[](https://docker.com/)
|
package/dist/actions.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { Api } from './api';
|
|
2
|
-
import { RequestOptions, TypedEmitter, TypedEvents } from '@ztimson/utils';
|
|
2
|
+
import { RequestOptions, TypedEmitter, type TypedEvents } from '@ztimson/utils';
|
|
3
3
|
import { BehaviorSubject } from 'rxjs';
|
|
4
4
|
import { Meta } from './core';
|
|
5
|
-
|
|
6
5
|
export type Action = Meta & {
|
|
7
6
|
name: string;
|
|
8
7
|
trigger: {
|
package/dist/actions.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Actions = exports.ActionType = void 0;
|
|
4
|
+
const api_1 = require("./api");
|
|
5
|
+
const utils_1 = require("@ztimson/utils");
|
|
6
|
+
const rxjs_1 = require("rxjs");
|
|
7
|
+
var ActionType;
|
|
8
|
+
(function (ActionType) {
|
|
9
|
+
ActionType[ActionType["CRON"] = 0] = "CRON";
|
|
10
|
+
ActionType[ActionType["EVENT"] = 1] = "EVENT";
|
|
11
|
+
ActionType[ActionType["DELETE"] = 2] = "DELETE";
|
|
12
|
+
ActionType[ActionType["GET"] = 3] = "GET";
|
|
13
|
+
ActionType[ActionType["PATCH"] = 4] = "PATCH";
|
|
14
|
+
ActionType[ActionType["POST"] = 5] = "POST";
|
|
15
|
+
ActionType[ActionType["PUT"] = 6] = "PUT";
|
|
16
|
+
})(ActionType || (exports.ActionType = ActionType = {}));
|
|
17
|
+
class Actions extends utils_1.TypedEmitter {
|
|
18
|
+
api;
|
|
19
|
+
$cache = new rxjs_1.BehaviorSubject([]);
|
|
20
|
+
get cache() { return this.$cache.value; }
|
|
21
|
+
set cache(val) { this.$cache.next(val); }
|
|
22
|
+
constructor(api) {
|
|
23
|
+
super();
|
|
24
|
+
this.api = typeof api == 'string' ? new api_1.Api(api) : api;
|
|
25
|
+
}
|
|
26
|
+
delete(id) {
|
|
27
|
+
return this.api.request({ url: `/api/actions/${id}`, method: 'DELETE' }).then(() => {
|
|
28
|
+
this.cache = this.cache.filter(a => a._id != id);
|
|
29
|
+
this.emit('DELETE', id);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
list() {
|
|
33
|
+
return this.api.request({ url: `/api/actions` }).then(resp => {
|
|
34
|
+
this.cache = resp;
|
|
35
|
+
this.emit('LIST', resp);
|
|
36
|
+
return resp;
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
read(id, reload = false) {
|
|
40
|
+
const cached = this.cache.find(a => a._id == id);
|
|
41
|
+
if (!reload && cached)
|
|
42
|
+
return Promise.resolve(cached);
|
|
43
|
+
return this.api.request({ url: `/api/actions/${id}` }).then(action => {
|
|
44
|
+
if (action)
|
|
45
|
+
this.cache = this.cache.filter(a => a._id != id).concat([action]);
|
|
46
|
+
this.emit('READ', action);
|
|
47
|
+
return action;
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
run(path, opts = {}) {
|
|
51
|
+
return this.api.request({ url: (`/api/actions/run/` + path).replaceAll('//', '/'), ...opts });
|
|
52
|
+
}
|
|
53
|
+
runById(action, opts = {}) {
|
|
54
|
+
const id = typeof action == 'string' ? action : action._id;
|
|
55
|
+
return this.api.request({ url: '/api/actions/run-by-id/' + id, method: 'POST', ...opts });
|
|
56
|
+
}
|
|
57
|
+
update(action) {
|
|
58
|
+
return this.api.request({
|
|
59
|
+
url: `/api/actions${action._id ? `/${action._id}` : ''}`,
|
|
60
|
+
method: 'POST',
|
|
61
|
+
body: action
|
|
62
|
+
}).then(action => {
|
|
63
|
+
if (action)
|
|
64
|
+
this.cache = this.cache.filter(a => a._id != action._id).concat([action]);
|
|
65
|
+
this.emit('UPDATE', action);
|
|
66
|
+
return action;
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
exports.Actions = Actions;
|
package/dist/api.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { TypedEvents, RequestOptions, XHR, XhrOptions } from '@ztimson/utils';
|
|
2
|
-
|
|
1
|
+
import { type TypedEvents, type RequestOptions, XHR, type XhrOptions } from '@ztimson/utils';
|
|
3
2
|
export type ApiEvents = TypedEvents & {
|
|
4
3
|
REQUEST: (request: Promise<any>, options: RequestOptions) => any;
|
|
5
4
|
RESPONSE: (response: any, options: RequestOptions) => any;
|
package/dist/api.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Api = void 0;
|
|
4
|
+
const utils_1 = require("@ztimson/utils");
|
|
5
|
+
class Api extends utils_1.XHR {
|
|
6
|
+
url;
|
|
7
|
+
opts;
|
|
8
|
+
emitter = new utils_1.TypedEmitter();
|
|
9
|
+
_token = null;
|
|
10
|
+
get token() { return this._token; }
|
|
11
|
+
set token(token) {
|
|
12
|
+
if (token == this._token)
|
|
13
|
+
return;
|
|
14
|
+
this._token = token;
|
|
15
|
+
this.headers['Authorization'] = token ? `Bearer ${token}` : undefined;
|
|
16
|
+
this.emit('TOKEN', token);
|
|
17
|
+
}
|
|
18
|
+
constructor(url = location.origin, opts = {}) {
|
|
19
|
+
opts.url = url;
|
|
20
|
+
super(opts);
|
|
21
|
+
this.url = url;
|
|
22
|
+
this.opts = opts;
|
|
23
|
+
}
|
|
24
|
+
emit = this.emitter.emit.bind(this.emitter);
|
|
25
|
+
off = this.emitter.off.bind(this.emitter);
|
|
26
|
+
on = this.emitter.on.bind(this.emitter);
|
|
27
|
+
once = this.emitter.once.bind(this.emitter);
|
|
28
|
+
request(options) {
|
|
29
|
+
const req = super.request(options).then(resp => {
|
|
30
|
+
this.emit('RESPONSE', resp, options);
|
|
31
|
+
return resp;
|
|
32
|
+
}).catch(err => {
|
|
33
|
+
this.emit('REJECTED', err, options);
|
|
34
|
+
throw err;
|
|
35
|
+
});
|
|
36
|
+
this.emit('REQUEST', req, options);
|
|
37
|
+
return req;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.Api = Api;
|
package/dist/auth.d.ts
CHANGED
|
@@ -1,43 +1,50 @@
|
|
|
1
1
|
import { BehaviorSubject } from 'rxjs';
|
|
2
2
|
import { Api } from './api';
|
|
3
|
-
import { TypedEmitter, TypedEvents } from '@ztimson/utils';
|
|
4
|
-
import { User } from './users';
|
|
5
|
-
|
|
3
|
+
import { TypedEmitter, type TypedEvents } from '@ztimson/utils';
|
|
4
|
+
import type { User } from './users';
|
|
6
5
|
export type AuthEvents = TypedEvents & {
|
|
7
6
|
USER: (user: User | null) => any;
|
|
8
7
|
LOGIN: (user: User) => any;
|
|
9
8
|
LOGOUT: () => any;
|
|
10
9
|
REGISTER: (user: Partial<User>) => any;
|
|
11
|
-
RESET_REQUEST: (email: string) => any;
|
|
12
|
-
RESET_COMPLETE: (token: string) => any;
|
|
13
10
|
SESSION_EXPIRED: () => any;
|
|
14
11
|
};
|
|
15
12
|
export type AuthOptions = {
|
|
16
13
|
loginUi?: string;
|
|
17
14
|
persist?: boolean;
|
|
18
15
|
};
|
|
16
|
+
export declare class Totp {
|
|
17
|
+
private api;
|
|
18
|
+
constructor(api: Api);
|
|
19
|
+
disable(username: string): Promise<void>;
|
|
20
|
+
enable: (username: string) => Promise<void>;
|
|
21
|
+
reset(username: string): Promise<void>;
|
|
22
|
+
setup(username: string, method?: string, totp?: string): Promise<void>;
|
|
23
|
+
}
|
|
19
24
|
export declare class Auth extends TypedEmitter<AuthEvents> {
|
|
20
25
|
private readonly opts?;
|
|
21
26
|
private readonly api;
|
|
22
27
|
private readonly storageKey;
|
|
28
|
+
totp: Totp;
|
|
23
29
|
$user: BehaviorSubject<User | null | undefined>;
|
|
24
30
|
get user(): User | null | undefined;
|
|
25
31
|
set user(user: User | null | undefined);
|
|
26
32
|
constructor(api: Api | string, opts?: AuthOptions | undefined);
|
|
27
33
|
knownHost(host?: string): Promise<void>;
|
|
28
|
-
login(username: string, password: string): Promise<User | null>;
|
|
34
|
+
login(username: string, password: string, totp?: string): Promise<User | null>;
|
|
29
35
|
loginRedirect(host?: string): Promise<string>;
|
|
30
36
|
logout(): void;
|
|
31
|
-
register(
|
|
37
|
+
register(u: Partial<User> & {
|
|
32
38
|
username: string;
|
|
33
39
|
password: string;
|
|
34
|
-
}): Promise<
|
|
40
|
+
}): Promise<User>;
|
|
35
41
|
reset(password: string, token?: string): Promise<void>;
|
|
36
42
|
reset(email: string): Promise<void>;
|
|
37
|
-
|
|
43
|
+
session(token?: string, set?: boolean): Promise<{
|
|
38
44
|
token: string;
|
|
39
45
|
user: User;
|
|
40
46
|
permissions: string[];
|
|
41
47
|
} | null>;
|
|
48
|
+
updatePassword(username: string, password: string, oldPassword?: string): Promise<void>;
|
|
42
49
|
}
|
|
43
50
|
//# 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,eAAe,EAAC,MAAM,MAAM,CAAC;AACrC,OAAO,EAAC,GAAG,EAAC,MAAM,OAAO,CAAC;AAC1B,OAAO,
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAC,MAAM,MAAM,CAAC;AACrC,OAAO,EAAC,GAAG,EAAC,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAiB,YAAY,EAAE,KAAK,WAAW,EAAC,MAAM,gBAAgB,CAAC;AAC9E,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,SAAS,CAAC;AAElC,MAAM,MAAM,UAAU,GAAG,WAAW,GAAG;IACtC,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,KAAK,GAAG,CAAC;IACjC,KAAK,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,GAAG,CAAC;IAC3B,MAAM,EAAE,MAAM,GAAG,CAAC;IAClB,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC;IACvC,eAAe,EAAE,MAAM,GAAG,CAAC;CAC3B,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB,CAAA;AAED,qBAAa,IAAI;IACJ,OAAO,CAAC,GAAG;gBAAH,GAAG,EAAE,GAAG;IAE5B,OAAO,CAAC,QAAQ,EAAE,MAAM;IAIxB,MAAM,aAEU,MAAM,mBAFF;IAEpB,KAAK,CAAC,QAAQ,EAAE,MAAM;IAItB,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,SAAQ,EAAE,IAAI,CAAC,EAAE,MAAM;CAMrD;AAED,qBAAa,IAAK,SAAQ,YAAY,CAAC,UAAU,CAAC;IAgBlB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;IAfrD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAO;IAC3B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAU;IAErC,IAAI,EAAG,IAAI,CAAC;IAEZ,KAAK,2CAA0D;IAC/D,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,SAAS,CAA6B;IAChE,IAAI,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,SAAS,EAMrC;gBAEW,GAAG,EAAE,GAAG,GAAG,MAAM,EAAmB,IAAI,CAAC,EAAE,WAAW,YAAA;IAqClE,SAAS,CAAC,IAAI,GAAE,MAAwB,GAAG,OAAO,CAAC,IAAI,CAAC;IAKxD,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAe9E,aAAa,CAAC,IAAI,GAAE,MAAwB,GAAG,OAAO,CAAC,MAAM,CAAC;IAa9D,MAAM,IAAI,IAAI;IAMR,QAAQ,CAAC,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAOtF,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IACtD,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAY7B,OAAO,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,UAAQ,GAAG,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,IAAI,CAAC;QAAC,WAAW,EAAE,MAAM,EAAE,CAAA;KAAC,GAAG,IAAI,CAAC;IAexG,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAQ7F"}
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Auth = exports.Totp = void 0;
|
|
4
|
+
const rxjs_1 = require("rxjs");
|
|
5
|
+
const api_1 = require("./api");
|
|
6
|
+
const utils_1 = require("@ztimson/utils");
|
|
7
|
+
class Totp {
|
|
8
|
+
api;
|
|
9
|
+
constructor(api) {
|
|
10
|
+
this.api = api;
|
|
11
|
+
}
|
|
12
|
+
disable(username) {
|
|
13
|
+
return this.api.request({ url: `/api/auth/totp/${username}`, method: 'DELETE' });
|
|
14
|
+
}
|
|
15
|
+
enable = this.reset;
|
|
16
|
+
reset(username) {
|
|
17
|
+
return this.api.request({ url: `/api/auth/totp/${username}`, method: 'POST' });
|
|
18
|
+
}
|
|
19
|
+
setup(username, method = 'app', totp) {
|
|
20
|
+
return this.api.request({ url: `/api/auth/totp/${username}`, body: (0, utils_1.clean)({
|
|
21
|
+
method,
|
|
22
|
+
totp
|
|
23
|
+
}) });
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.Totp = Totp;
|
|
27
|
+
class Auth extends utils_1.TypedEmitter {
|
|
28
|
+
opts;
|
|
29
|
+
api;
|
|
30
|
+
storageKey;
|
|
31
|
+
totp;
|
|
32
|
+
$user = new rxjs_1.BehaviorSubject(undefined);
|
|
33
|
+
get user() { return this.$user.value; }
|
|
34
|
+
set user(user) {
|
|
35
|
+
if (!(0, utils_1.isEqual)(this.user, user)) {
|
|
36
|
+
const u = user ? user : null;
|
|
37
|
+
this.$user.next(u);
|
|
38
|
+
this.emit('USER', u);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
constructor(api, opts) {
|
|
42
|
+
super();
|
|
43
|
+
this.opts = opts;
|
|
44
|
+
this.api = typeof api == 'string' ? new api_1.Api(api) : api;
|
|
45
|
+
this.totp = new Totp(this.api);
|
|
46
|
+
if (!this.opts?.loginUi)
|
|
47
|
+
this.opts = { ...this.opts, loginUi: this.api.url + '/ui/login' };
|
|
48
|
+
this.storageKey = `momentum:${new URL(this.api.url).host}`;
|
|
49
|
+
this.api.addInterceptor((resp, next) => {
|
|
50
|
+
const blacklist = [
|
|
51
|
+
'/api/auth/login',
|
|
52
|
+
'/api/auth/password',
|
|
53
|
+
'/api/auth/totp'
|
|
54
|
+
];
|
|
55
|
+
if (resp.status == 401 && !blacklist.find(url => resp.url.includes(url)))
|
|
56
|
+
this.emit('SESSION_EXPIRED');
|
|
57
|
+
next();
|
|
58
|
+
});
|
|
59
|
+
this.api.on('TOKEN', token => {
|
|
60
|
+
if (this.opts?.persist) {
|
|
61
|
+
if (token)
|
|
62
|
+
localStorage.setItem(this.storageKey, token);
|
|
63
|
+
else
|
|
64
|
+
localStorage.removeItem(this.storageKey);
|
|
65
|
+
}
|
|
66
|
+
if (token)
|
|
67
|
+
this.session(token, true).catch(() => { });
|
|
68
|
+
else
|
|
69
|
+
this.user = null;
|
|
70
|
+
});
|
|
71
|
+
if (opts?.persist) {
|
|
72
|
+
const token = localStorage.getItem(this.storageKey);
|
|
73
|
+
if (token)
|
|
74
|
+
this.api.token = token;
|
|
75
|
+
else
|
|
76
|
+
this.user = null;
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
this.user = null;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
knownHost(host = location.origin) {
|
|
83
|
+
if (host.startsWith('/'))
|
|
84
|
+
return Promise.resolve();
|
|
85
|
+
return this.api.request({ url: `/api/auth/known-host?host=${encodeURI(new URL(host).origin)}` });
|
|
86
|
+
}
|
|
87
|
+
login(username, password, totp) {
|
|
88
|
+
return this.api.request({
|
|
89
|
+
url: '/api/auth/login',
|
|
90
|
+
headers: { Authorization: undefined },
|
|
91
|
+
body: {
|
|
92
|
+
username: username.trim(),
|
|
93
|
+
password: password.trim(),
|
|
94
|
+
totp,
|
|
95
|
+
}
|
|
96
|
+
}).then(async (resp) => {
|
|
97
|
+
this.api.token = resp.token;
|
|
98
|
+
return await this.once('USER');
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
loginRedirect(host = location.origin) {
|
|
102
|
+
return new Promise((res, rej) => {
|
|
103
|
+
const win = window.open(encodeURI(`${this.opts?.loginUi}?redirect=postmessage&host=${host}`), '_blank');
|
|
104
|
+
if (!win)
|
|
105
|
+
return rej('Unable to open login');
|
|
106
|
+
win.addEventListener('message', (event) => {
|
|
107
|
+
if (!event?.data?.token)
|
|
108
|
+
return rej('Unknown response from login');
|
|
109
|
+
this.api.token = event.data.token;
|
|
110
|
+
res(event.data.token);
|
|
111
|
+
win.close();
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
logout() {
|
|
116
|
+
this.api.token = null;
|
|
117
|
+
this.user = null;
|
|
118
|
+
this.emit('LOGOUT');
|
|
119
|
+
}
|
|
120
|
+
async register(u) {
|
|
121
|
+
const user = await this.api.request({ url: '/api/auth/register', body: { ...u } });
|
|
122
|
+
if (user.image.startsWith('/'))
|
|
123
|
+
user.image = `${this.api.url}${user.image}?token=${this.api.token}`;
|
|
124
|
+
this.emit('REGISTER', user);
|
|
125
|
+
return user;
|
|
126
|
+
}
|
|
127
|
+
reset(emailOrPass, token) {
|
|
128
|
+
return this.api.request({
|
|
129
|
+
url: '/api/auth/reset',
|
|
130
|
+
headers: { 'Authorization': token ? `Bearer ${token}` : undefined },
|
|
131
|
+
body: {
|
|
132
|
+
email: token ? undefined : emailOrPass,
|
|
133
|
+
password: token ? emailOrPass : undefined,
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
async session(token, set = false) {
|
|
138
|
+
if (!token)
|
|
139
|
+
token = this.api.token;
|
|
140
|
+
const user = await this.api.request({
|
|
141
|
+
url: '/api/auth/session',
|
|
142
|
+
headers: token ? { 'Authorization': `Bearer ${token}` } : undefined
|
|
143
|
+
});
|
|
144
|
+
if (set) {
|
|
145
|
+
this.api.token = token;
|
|
146
|
+
if (user?.user)
|
|
147
|
+
user.user.image = `${this.api.url}${user.user.image}?token=${this.api.token}`;
|
|
148
|
+
this.user = user?.user || null;
|
|
149
|
+
if (user)
|
|
150
|
+
this.emit('LOGIN', user.user);
|
|
151
|
+
}
|
|
152
|
+
return user;
|
|
153
|
+
}
|
|
154
|
+
async updatePassword(username, password, oldPassword) {
|
|
155
|
+
return this.api.request({
|
|
156
|
+
url: '/api/auth/password',
|
|
157
|
+
body: { username, password, oldPassword }
|
|
158
|
+
}).then(resp => {
|
|
159
|
+
if (resp?.token)
|
|
160
|
+
this.api.token = resp.token;
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
exports.Auth = Auth;
|
package/dist/core.js
ADDED
package/dist/data.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Api } from './api';
|
|
2
|
-
import { Meta } from './core';
|
|
3
|
-
import { TypedEmitter, TypedEvents } from '@ztimson/utils';
|
|
4
|
-
|
|
2
|
+
import { type Meta } from './core';
|
|
3
|
+
import { TypedEmitter, type TypedEvents } from '@ztimson/utils';
|
|
5
4
|
export type DataEvents = TypedEvents & {
|
|
6
5
|
DELETE: (collection: string, document: string) => any;
|
|
7
6
|
GET: (collection: string, documents: any) => any;
|
package/dist/data.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Data = void 0;
|
|
4
|
+
const api_1 = require("./api");
|
|
5
|
+
const utils_1 = require("@ztimson/utils");
|
|
6
|
+
class Data extends utils_1.TypedEmitter {
|
|
7
|
+
api;
|
|
8
|
+
constructor(api) {
|
|
9
|
+
super();
|
|
10
|
+
this.api = typeof api == 'string' ? new api_1.Api(api) : api;
|
|
11
|
+
}
|
|
12
|
+
delete(collection, document) {
|
|
13
|
+
return this.api.request({
|
|
14
|
+
url: `/api/data/${collection}/${document}`,
|
|
15
|
+
method: 'DELETE'
|
|
16
|
+
}).then(() => this.emit('DELETE', collection, document));
|
|
17
|
+
}
|
|
18
|
+
get(collection, document) {
|
|
19
|
+
return this.api.request({ url: `/api/data/${collection}${document ? `/${document}` : ''}` }).then(resp => {
|
|
20
|
+
this.emit('GET', collection, resp);
|
|
21
|
+
return resp;
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
raw(collection, operand, query, options) {
|
|
25
|
+
return this.api.request({
|
|
26
|
+
url: `/api/data/${collection}`,
|
|
27
|
+
body: {
|
|
28
|
+
operand,
|
|
29
|
+
query,
|
|
30
|
+
options,
|
|
31
|
+
}
|
|
32
|
+
}).then(resp => {
|
|
33
|
+
this.emit('RAW', collection, resp);
|
|
34
|
+
return resp;
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
set(collection, document, append = false) {
|
|
38
|
+
return this.api.request({
|
|
39
|
+
url: `/api/data/${collection}/${document._id || ''}`,
|
|
40
|
+
method: append ? 'PATCH' : 'POST',
|
|
41
|
+
body: document
|
|
42
|
+
}).then(resp => {
|
|
43
|
+
this.emit('SET', collection, document);
|
|
44
|
+
return resp;
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
exports.Data = Data;
|
package/dist/email.d.ts
CHANGED
package/dist/email.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Email = void 0;
|
|
4
|
+
const api_1 = require("./api");
|
|
5
|
+
const utils_1 = require("@ztimson/utils");
|
|
6
|
+
class Email extends utils_1.TypedEmitter {
|
|
7
|
+
api;
|
|
8
|
+
constructor(api) {
|
|
9
|
+
super();
|
|
10
|
+
this.api = typeof api == 'string' ? new api_1.Api(api) : api;
|
|
11
|
+
}
|
|
12
|
+
send(email) {
|
|
13
|
+
let url = '/api/email';
|
|
14
|
+
if (typeof email.body == 'object')
|
|
15
|
+
url += `/${email.body.template}`;
|
|
16
|
+
return this.api.request({ url, body: email }).then(resp => {
|
|
17
|
+
this.emit('SENT', email);
|
|
18
|
+
return resp;
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.Email = Email;
|
package/dist/groups.d.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { Api } from './api';
|
|
2
|
-
import { TypedEmitter, TypedEvents } from '@ztimson/utils';
|
|
3
|
-
import { Meta } from './core';
|
|
4
|
-
|
|
2
|
+
import { TypedEmitter, type TypedEvents } from '@ztimson/utils';
|
|
3
|
+
import type { Meta } from './core';
|
|
5
4
|
export type Group = Meta & {
|
|
6
5
|
name: string;
|
|
7
6
|
description?: string;
|
|
8
7
|
notes?: string;
|
|
9
8
|
users: string[];
|
|
10
9
|
permissions: string[];
|
|
11
|
-
|
|
10
|
+
custom: any;
|
|
12
11
|
};
|
|
13
12
|
export type GroupEvents = TypedEvents & {
|
|
14
13
|
LIST: (users: Group[]) => any;
|
package/dist/groups.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"groups.d.ts","sourceRoot":"","sources":["../src/groups.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,GAAG,EAAC,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAC,YAAY,EAAE,KAAK,WAAW,EAAC,MAAM,gBAAgB,CAAC;AAC9D,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,QAAQ,CAAC;AAEjC,MAAM,MAAM,KAAK,GAAG,IAAI,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,
|
|
1
|
+
{"version":3,"file":"groups.d.ts","sourceRoot":"","sources":["../src/groups.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,GAAG,EAAC,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAC,YAAY,EAAE,KAAK,WAAW,EAAC,MAAM,gBAAgB,CAAC;AAC9D,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,QAAQ,CAAC;AAEjC,MAAM,MAAM,KAAK,GAAG,IAAI,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,MAAM,EAAE,GAAG,CAAC;CACZ,CAAA;AAED,MAAM,MAAM,WAAW,GAAG,WAAW,GAAG;IACvC,IAAI,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,GAAG,CAAC;IAC9B,MAAM,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,GAAG,CAAC;IAC7B,IAAI,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,GAAG,CAAC;IAC3B,MAAM,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,GAAG,CAAC;IAC7B,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,GAAG,CAAC;CAC9B,CAAC;AAEF,qBAAa,MAAO,SAAQ,YAAY,CAAC,WAAW,CAAC;IACpD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAO;gBAEf,GAAG,EAAE,GAAG,GAAG,MAAM;IAK7B,MAAM,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;IAWpC,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;IAOxB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAOlC,MAAM,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;IAWpC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAMnC"}
|
package/dist/groups.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Groups = void 0;
|
|
4
|
+
const api_1 = require("./api");
|
|
5
|
+
const utils_1 = require("@ztimson/utils");
|
|
6
|
+
class Groups extends utils_1.TypedEmitter {
|
|
7
|
+
api;
|
|
8
|
+
constructor(api) {
|
|
9
|
+
super();
|
|
10
|
+
this.api = typeof api == 'string' ? new api_1.Api(api) : api;
|
|
11
|
+
}
|
|
12
|
+
create(group) {
|
|
13
|
+
return this.api.request({
|
|
14
|
+
url: `/api/groups/${group.name}`,
|
|
15
|
+
method: 'POST',
|
|
16
|
+
body: group
|
|
17
|
+
}).then(resp => {
|
|
18
|
+
this.emit('CREATE', resp);
|
|
19
|
+
return resp;
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
list() {
|
|
23
|
+
return this.api.request({ url: `/api/groups` }).then(resp => {
|
|
24
|
+
this.emit('LIST', resp);
|
|
25
|
+
return resp;
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
read(name) {
|
|
29
|
+
return this.api.request({ url: `/api/groups/${name}` }).then(resp => {
|
|
30
|
+
this.emit('READ', resp);
|
|
31
|
+
return resp;
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
update(group) {
|
|
35
|
+
return this.api.request({
|
|
36
|
+
url: `/api/groups/${group.name}`,
|
|
37
|
+
method: 'PATCH',
|
|
38
|
+
body: group
|
|
39
|
+
}).then(resp => {
|
|
40
|
+
this.emit('UPDATE', resp);
|
|
41
|
+
return resp;
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
delete(name) {
|
|
45
|
+
return this.api.request({
|
|
46
|
+
url: `/api/groups/${name}`,
|
|
47
|
+
method: 'DELETE'
|
|
48
|
+
}).then(() => this.emit('DELETE', name));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.Groups = Groups;
|