@ztimson/momentum 0.20.0 → 0.27.1

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 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 server backend for single page applications such as angular, react, svelte or vue. This enables rapid development of the client front-end application or website.
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
- - WIP: Admin Panel
49
- - Use the web UI to manage server features while you build your front end
50
- - White labeled so it can use it as a content management system
51
- - View the source code for real examples of how to use the server API
52
- - [Client Library](https://git.zakscode.com/ztimson/momentum/wiki/Client)
53
- - TypeScript, ESM & UMD compatible client library for native JavaScript environments
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 & save user data
56
- - Custom password strength rules
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
- - User groups
59
- - Permissions for all modules
60
- - Custom permissions
61
- - Optionally allow public registration
62
+ - Optional public registration form
63
+ - OAuth support for custom applications
64
+ - Custom password strength rules
65
+ - Two-Factor Authentication
62
66
  - Data
63
- - Generic collection/do`cument database accessible via REST
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
- - Metadata such as created & modified by is tracked
66
- - Uses MongoDB
67
- - Email
68
- - Supports SMTP
69
- - HTML email templates
70
- - Send emails using post requests
71
- - WIP: Handle newsletter subscriptions
72
- - WIP: Send newsletters via post request
73
- - [File Storage](https://git.zakscode.com/ztimson/momentum/wiki/Storage)
74
- - Upload files using file input field
75
- - Navigate storage via API
76
- - Automatically track metadata
77
- - Granular, file level, permissions
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
- - Volumize or extend the momentum docker image to include your static website in `/app/public`
81
- - Enable the single page application redirects with the environment variable: `NOT_FOUND_REDIRECT=TRUE`
82
- - [Variables](https://git.zakscode.com/ztimson/momentum/wiki/Variables)
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
- - Granular, variable level, permissions
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
  [![Docker](https://img.shields.io/badge/Docker-384d54?style=for-the-badge&logo=docker)](https://docker.com/)
@@ -117,6 +129,7 @@ Features include:
117
129
  </summary>
118
130
 
119
131
  #### Prerequisites
132
+ - [Docker](https://docs.docker.com/install/)
120
133
  - [Node.js](https://nodejs.org/en/download)
121
134
 
122
135
  #### Instructions
@@ -130,6 +143,6 @@ Features include:
130
143
  </details>
131
144
 
132
145
  ## License
133
- Copyright © 2023 Zakary Timson | Available under MIT Licensing
146
+ Copyright © 2024 Zakary Timson | All Rights Reserved
134
147
 
135
148
  See the [license](./LICENSE) for more information.
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: {
@@ -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,62 +1,50 @@
1
1
  import { BehaviorSubject } from 'rxjs';
2
2
  import { Api } from './api';
3
- import { Meta } from './core';
4
- import { TypedEmitter, TypedEvents } from '@ztimson/utils';
5
-
6
- export type Group = Meta & {
7
- name: string;
8
- description?: string;
9
- notes?: string;
10
- users: string[];
11
- permissions: string[];
12
- extra: any;
13
- };
14
- export type User = Meta & {
15
- username: string;
16
- name: string;
17
- email: string;
18
- image?: string;
19
- disabled?: boolean;
20
- groups?: string[];
21
- permissions?: string[];
22
- notes?: string;
23
- extra: any;
24
- lastLogin?: number | null;
25
- };
3
+ import { TypedEmitter, type TypedEvents } from '@ztimson/utils';
4
+ import type { User } from './users';
26
5
  export type AuthEvents = TypedEvents & {
27
6
  USER: (user: User | null) => any;
28
7
  LOGIN: (user: User) => any;
29
8
  LOGOUT: () => any;
30
9
  REGISTER: (user: Partial<User>) => any;
31
- RESET_REQUEST: (email: string) => any;
32
- RESET_COMPLETE: (token: string) => any;
10
+ SESSION_EXPIRED: () => any;
33
11
  };
34
12
  export type AuthOptions = {
35
13
  loginUi?: string;
36
14
  persist?: boolean;
37
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
+ }
38
24
  export declare class Auth extends TypedEmitter<AuthEvents> {
39
25
  private readonly opts?;
40
26
  private readonly api;
41
27
  private readonly storageKey;
28
+ totp: Totp;
42
29
  $user: BehaviorSubject<User | null | undefined>;
43
30
  get user(): User | null | undefined;
44
31
  set user(user: User | null | undefined);
45
32
  constructor(api: Api | string, opts?: AuthOptions | undefined);
46
33
  knownHost(host?: string): Promise<void>;
47
- login(username: string, password: string): Promise<User | null>;
34
+ login(username: string, password: string, totp?: string): Promise<User | null>;
48
35
  loginRedirect(host?: string): Promise<string>;
49
36
  logout(): void;
50
- register(user: Partial<User> & {
37
+ register(u: Partial<User> & {
51
38
  username: string;
52
39
  password: string;
53
- }): Promise<void>;
40
+ }): Promise<User>;
54
41
  reset(password: string, token?: string): Promise<void>;
55
42
  reset(email: string): Promise<void>;
56
- whoAmI(token?: string, set?: boolean): Promise<{
43
+ session(token?: string, set?: boolean): Promise<{
57
44
  token: string;
58
45
  user: User;
59
46
  permissions: string[];
60
47
  } | null>;
48
+ updatePassword(username: string, password: string, oldPassword?: string): Promise<void>;
61
49
  }
62
50
  //# sourceMappingURL=auth.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
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
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
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
@@ -1,6 +1,5 @@
1
1
  import { Api } from './api';
2
- import { TypedEmitter, TypedEvents } from '@ztimson/utils';
3
-
2
+ import { TypedEmitter, type TypedEvents } from '@ztimson/utils';
4
3
  export type MailTemplate = {
5
4
  template: string;
6
5
  data?: any;
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,7 +1,14 @@
1
1
  import { Api } from './api';
2
- import { Group } from './auth';
3
- import { TypedEmitter, TypedEvents } from '@ztimson/utils';
4
-
2
+ import { TypedEmitter, type TypedEvents } from '@ztimson/utils';
3
+ import type { Meta } from './core';
4
+ export type Group = Meta & {
5
+ name: string;
6
+ description?: string;
7
+ notes?: string;
8
+ users: string[];
9
+ permissions: string[];
10
+ custom: any;
11
+ };
5
12
  export type GroupEvents = TypedEvents & {
6
13
  LIST: (users: Group[]) => any;
7
14
  CREATE: (user: Group) => any;
@@ -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,KAAK,KAAK,EAAC,MAAM,QAAQ,CAAC;AAClC,OAAO,EAAC,YAAY,EAAE,KAAK,WAAW,EAAC,MAAM,gBAAgB,CAAC;AAE9D,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"}
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"}