@ti-engine/web-framework 1.19.1 → 1.20.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/CHANGELOG.md +29 -0
- package/bin/web-app-manager.js +3 -6
- package/bin/web-server.js +8 -9
- package/components/admin-config-handlers.js +3 -0
- package/components/auth-manager.js +3 -7
- package/components/authorization.js +2 -2
- package/components/config-change-notifier.js +4 -4
- package/components/config-registry.js +3 -6
- package/components/config-service.js +9 -6
- package/components/config-store.js +1 -3
- package/components/definitions.types.js +5 -3
- package/components/session-store.js +9 -6
- package/components/user.js +2 -0
- package/components/web-handlers.js +7 -4
- package/package.json +84 -21
- package/types/bin/web-app-manager.d.ts +194 -0
- package/types/bin/web-server.d.ts +374 -0
- package/types/components/admin-config-handlers.d.ts +11 -0
- package/types/components/auth-manager.d.ts +125 -0
- package/types/components/authorization.d.ts +54 -0
- package/types/components/config-change-notifier.d.ts +73 -0
- package/types/components/config-registry.d.ts +149 -0
- package/types/components/config-service.d.ts +218 -0
- package/types/components/config-store.d.ts +128 -0
- package/types/components/definitions.types.d.ts +31 -0
- package/types/components/session-store.d.ts +56 -0
- package/types/components/user.d.ts +83 -0
- package/types/components/web-config-env.d.ts +17 -0
- package/types/components/web-handlers.d.ts +23 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
export = ConfigStore;
|
|
2
|
+
/**
|
|
3
|
+
* A versioned, change-set-aware configuration store backed by the common memory cache (RedisJSON).
|
|
4
|
+
* <br/>
|
|
5
|
+
* Each editable configuration is a *document* identified by a `configKey`. Every committed edit:
|
|
6
|
+
* - bumps the document's monotonic `version`,
|
|
7
|
+
* - writes a full **snapshot** to history (enabling restore),
|
|
8
|
+
* - and is correlated with the other documents written in the same logical edit via a shared **change-set** id,
|
|
9
|
+
* so a multi-document edit (and its restore) is treated as one unit even though storage is per-document.
|
|
10
|
+
* <br/>
|
|
11
|
+
* Optimistic locking: callers pass the `expectedVersion` they edited from; the save is rejected if any document
|
|
12
|
+
* moved on in the meantime. This component is storage-only — schema/semantic validation is a separate pipeline
|
|
13
|
+
* that must run *before* {@link ConfigStore#saveChangeSet}.
|
|
14
|
+
* <br/>
|
|
15
|
+
* NOTE: true cross-document atomicity is not provided (the cache exposes per-key commands only). All locks are
|
|
16
|
+
* checked *before* any write, so the common conflict case is safe; a mid-write process failure can leave a
|
|
17
|
+
* partially-applied change-set, detectable via the change-set record. Hardening (a Lua/MULTI write) is deferred.
|
|
18
|
+
*
|
|
19
|
+
* @class ConfigStore
|
|
20
|
+
* @public
|
|
21
|
+
*/
|
|
22
|
+
declare class ConfigStore {
|
|
23
|
+
#private;
|
|
24
|
+
/**
|
|
25
|
+
* Returns the current envelope `{ value, version, updatedAt, updatedBy, changeSetID }` for a configuration
|
|
26
|
+
* document, or `null` if it has never been written.
|
|
27
|
+
*
|
|
28
|
+
* @method
|
|
29
|
+
* @param {string} configKey
|
|
30
|
+
* @returns {Promise<Object|null>}
|
|
31
|
+
* @public
|
|
32
|
+
*/
|
|
33
|
+
getCurrent(configKey: string): Promise<Object | null>;
|
|
34
|
+
/**
|
|
35
|
+
* Writes the default value as version 1 only if the document does not yet exist (idempotent bootstrap).
|
|
36
|
+
* Resolves with the current envelope either way.
|
|
37
|
+
*
|
|
38
|
+
* @method
|
|
39
|
+
* @param {string} configKey
|
|
40
|
+
* @param {Object} defaultValue
|
|
41
|
+
* @returns {Promise<Object>}
|
|
42
|
+
* @public
|
|
43
|
+
*/
|
|
44
|
+
seedIfEmpty(configKey: string, defaultValue: Object): Promise<Object>;
|
|
45
|
+
/**
|
|
46
|
+
* Commits an edit spanning one or more documents as a single change-set. All optimistic-lock checks run before
|
|
47
|
+
* any write. Each edit: `{ configKey, value, expectedVersion }`.
|
|
48
|
+
*
|
|
49
|
+
* @method
|
|
50
|
+
* @param {Array<{configKey: string, value: Object, expectedVersion: number}>} edits
|
|
51
|
+
* @param {Object} meta
|
|
52
|
+
* @param {string} meta.adminID
|
|
53
|
+
* @param {string} [meta.note]
|
|
54
|
+
* @returns {Promise<{changeSetID: string, versions: Object<string, number>}>}
|
|
55
|
+
* @throws {TiException.E_WEB_INVALID_REQUEST_PARAMETERS} On bad input or a version conflict (see `details`).
|
|
56
|
+
* @public
|
|
57
|
+
*/
|
|
58
|
+
saveChangeSet(edits: Array<{
|
|
59
|
+
configKey: string;
|
|
60
|
+
value: Object;
|
|
61
|
+
expectedVersion: number;
|
|
62
|
+
}>, meta: {
|
|
63
|
+
adminID: string;
|
|
64
|
+
note?: string;
|
|
65
|
+
}): Promise<{
|
|
66
|
+
changeSetID: string;
|
|
67
|
+
versions: Record<string, number>;
|
|
68
|
+
}>;
|
|
69
|
+
/**
|
|
70
|
+
* Returns all history entries for a document, ascending by version.
|
|
71
|
+
*
|
|
72
|
+
* @method
|
|
73
|
+
* @param {string} configKey
|
|
74
|
+
* @returns {Promise<Array<Object>>}
|
|
75
|
+
* @public
|
|
76
|
+
*/
|
|
77
|
+
listHistory(configKey: string): Promise<Array<Object>>;
|
|
78
|
+
/**
|
|
79
|
+
* Returns a single history snapshot entry for a document version, or `null`.
|
|
80
|
+
*
|
|
81
|
+
* @method
|
|
82
|
+
* @param {string} configKey
|
|
83
|
+
* @param {number} version
|
|
84
|
+
* @returns {Promise<Object|null>}
|
|
85
|
+
* @public
|
|
86
|
+
*/
|
|
87
|
+
getVersion(configKey: string, version: number): Promise<Object | null>;
|
|
88
|
+
/**
|
|
89
|
+
* Returns a change-set record by id, or `null`.
|
|
90
|
+
*
|
|
91
|
+
* @method
|
|
92
|
+
* @param {string} changeSetID
|
|
93
|
+
* @returns {Promise<Object|null>}
|
|
94
|
+
* @public
|
|
95
|
+
*/
|
|
96
|
+
getChangeSet(changeSetID: string): Promise<Object | null>;
|
|
97
|
+
/**
|
|
98
|
+
* Returns every change-set record, most-recent first (the cross-document audit feed).
|
|
99
|
+
*
|
|
100
|
+
* @method
|
|
101
|
+
* @returns {Promise<Array<Object>>}
|
|
102
|
+
* @public
|
|
103
|
+
*/
|
|
104
|
+
listChangeSets(): Promise<Array<Object>>;
|
|
105
|
+
/**
|
|
106
|
+
* Restores every document in a prior change-set to that change-set's snapshot, committing it as a *new*
|
|
107
|
+
* change-set (restore is never destructive — it moves forward to a past state).
|
|
108
|
+
*
|
|
109
|
+
* @method
|
|
110
|
+
* @param {string} changeSetID
|
|
111
|
+
* @param {Object} meta
|
|
112
|
+
* @param {string} meta.adminID
|
|
113
|
+
* @param {string} [meta.note]
|
|
114
|
+
* @returns {Promise<{changeSetID: string, versions: Object<string, number>}>}
|
|
115
|
+
* @public
|
|
116
|
+
*/
|
|
117
|
+
restoreChangeSet(changeSetID: string, meta: {
|
|
118
|
+
adminID: string;
|
|
119
|
+
note?: string;
|
|
120
|
+
}): Promise<{
|
|
121
|
+
changeSetID: string;
|
|
122
|
+
versions: Record<string, number>;
|
|
123
|
+
}>;
|
|
124
|
+
}
|
|
125
|
+
declare namespace ConfigStore {
|
|
126
|
+
var _a: Readonly<ConfigStore>;
|
|
127
|
+
export { _a as instance };
|
|
128
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { TiLocalizationLanguage } from "@ti-engine/core/localization";
|
|
2
|
+
export type TiSessionCallback = (error?: Error | null) => void;
|
|
3
|
+
export type TiSession = {
|
|
4
|
+
id: string;
|
|
5
|
+
user?: Object;
|
|
6
|
+
language?: TiLocalizationLanguage;
|
|
7
|
+
cookie?: Object;
|
|
8
|
+
oidc?: Object;
|
|
9
|
+
csrfToken?: string;
|
|
10
|
+
regenerate: (callback: TiSessionCallback) => TiSession;
|
|
11
|
+
destroy: (callback: TiSessionCallback) => TiSession;
|
|
12
|
+
save: (callback?: TiSessionCallback) => TiSession;
|
|
13
|
+
};
|
|
14
|
+
/** @import { TiLocalizationLanguage } from "@ti-engine/core/localization" */
|
|
15
|
+
/**
|
|
16
|
+
* @callback TiSessionCallback
|
|
17
|
+
* @param {Error|null} [error]
|
|
18
|
+
* @returns {void}
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* @typedef {Object} TiSession
|
|
22
|
+
* @property {string} id
|
|
23
|
+
* @property {Object} [user]
|
|
24
|
+
* @property {TiLocalizationLanguage} [language]
|
|
25
|
+
* @property {Object} [cookie]
|
|
26
|
+
* @property {Object} [oidc]
|
|
27
|
+
* @property {string} [csrfToken]
|
|
28
|
+
* @property {(callback: TiSessionCallback) => TiSession} regenerate
|
|
29
|
+
* @property {(callback: TiSessionCallback) => TiSession} destroy
|
|
30
|
+
* @property {(callback?: TiSessionCallback) => TiSession} save
|
|
31
|
+
*/
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export = SessionStore;
|
|
2
|
+
import session = require("express-session");
|
|
3
|
+
import type { SessionData } from "express-session";
|
|
4
|
+
import type { TiException } from "@ti-engine/core/exceptions";
|
|
5
|
+
/**
|
|
6
|
+
* A session store for the web server using the standard 'cache' module of the ti-engine.
|
|
7
|
+
* <br/>
|
|
8
|
+
* NOTE: This implementation is compatible with the 'express-session' module.
|
|
9
|
+
*
|
|
10
|
+
* @class SessionStore
|
|
11
|
+
* @public
|
|
12
|
+
*/
|
|
13
|
+
declare class SessionStore extends session.Store {
|
|
14
|
+
/**
|
|
15
|
+
* @constructor
|
|
16
|
+
*/
|
|
17
|
+
constructor();
|
|
18
|
+
/**
|
|
19
|
+
* Used to store a user session in the cache.
|
|
20
|
+
*
|
|
21
|
+
* @method
|
|
22
|
+
* @param {string} sessionID
|
|
23
|
+
* @param {SessionData} session
|
|
24
|
+
* @param {(error?: Error|TiException|null) => void} callback
|
|
25
|
+
* @public
|
|
26
|
+
*/
|
|
27
|
+
set(sessionID: string, session: SessionData, callback: (error?: Error | TiException | null) => void): void;
|
|
28
|
+
/**
|
|
29
|
+
* Used to retrieve a user session from the cache.
|
|
30
|
+
*
|
|
31
|
+
* @method
|
|
32
|
+
* @param {string} sessionID
|
|
33
|
+
* @param {(error?: Error|TiException|null, session?: SessionData|null) => void} callback
|
|
34
|
+
* @public
|
|
35
|
+
*/
|
|
36
|
+
get(sessionID: string, callback: (error?: Error | TiException | null, session?: SessionData | null) => void): void;
|
|
37
|
+
/**
|
|
38
|
+
* Used to remove a user session from the cache.
|
|
39
|
+
*
|
|
40
|
+
* @method
|
|
41
|
+
* @param {string} sessionID
|
|
42
|
+
* @param {(error?: Error|TiException|null) => void} callback
|
|
43
|
+
* @public
|
|
44
|
+
*/
|
|
45
|
+
destroy(sessionID: string, callback: (error?: Error | TiException | null) => void): void;
|
|
46
|
+
/**
|
|
47
|
+
* Used to update the expiration time of a user session in the cache.
|
|
48
|
+
*
|
|
49
|
+
* @method
|
|
50
|
+
* @param {string} sessionID
|
|
51
|
+
* @param {SessionData} session
|
|
52
|
+
* @param {(error?: Error|TiException|null) => void} callback
|
|
53
|
+
* @public
|
|
54
|
+
*/
|
|
55
|
+
touch(sessionID: string, session: SessionData, callback: (error?: Error | TiException | null) => void): void;
|
|
56
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
export = User;
|
|
2
|
+
import type { TiLocalizationLanguage } from "@ti-engine/core/localization";
|
|
3
|
+
/** @import { TiLocalizationLanguage } from "@ti-engine/core/localization" */
|
|
4
|
+
/**
|
|
5
|
+
* Represents a user in the system.
|
|
6
|
+
*
|
|
7
|
+
* @class User
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
declare class User {
|
|
11
|
+
#private;
|
|
12
|
+
/**
|
|
13
|
+
* @constructor
|
|
14
|
+
* @param {Object} userData
|
|
15
|
+
* @param {string} userData.userID
|
|
16
|
+
* @param {string} [userData.username]
|
|
17
|
+
* @param {string} [userData.email]
|
|
18
|
+
* @param {string} [userData.name]
|
|
19
|
+
* @param {TiLocalizationLanguage} [userData.language]
|
|
20
|
+
* @param {string[]} [userData.roles]
|
|
21
|
+
* @param {string[]} [userData.permissions]
|
|
22
|
+
* @param {Object} [userData.details]
|
|
23
|
+
*/
|
|
24
|
+
constructor(userData?: {
|
|
25
|
+
userID: string;
|
|
26
|
+
username?: string;
|
|
27
|
+
email?: string;
|
|
28
|
+
name?: string;
|
|
29
|
+
language?: TiLocalizationLanguage;
|
|
30
|
+
roles?: string[];
|
|
31
|
+
permissions?: string[];
|
|
32
|
+
details?: Object;
|
|
33
|
+
});
|
|
34
|
+
/**
|
|
35
|
+
* @property
|
|
36
|
+
* @returns {string}
|
|
37
|
+
* @public
|
|
38
|
+
*/
|
|
39
|
+
get userID(): string;
|
|
40
|
+
/**
|
|
41
|
+
* @property
|
|
42
|
+
* @returns {string}
|
|
43
|
+
* @public
|
|
44
|
+
*/
|
|
45
|
+
get username(): string;
|
|
46
|
+
/**
|
|
47
|
+
* @property
|
|
48
|
+
* @returns {string}
|
|
49
|
+
* @public
|
|
50
|
+
*/
|
|
51
|
+
get email(): string;
|
|
52
|
+
/**
|
|
53
|
+
* @property
|
|
54
|
+
* @returns {string}
|
|
55
|
+
* @public
|
|
56
|
+
*/
|
|
57
|
+
get name(): string;
|
|
58
|
+
/**
|
|
59
|
+
* @property
|
|
60
|
+
* @returns {TiLocalizationLanguage}
|
|
61
|
+
* @public
|
|
62
|
+
*/
|
|
63
|
+
get language(): TiLocalizationLanguage;
|
|
64
|
+
/**
|
|
65
|
+
* @method
|
|
66
|
+
* @returns {*}
|
|
67
|
+
* @public
|
|
68
|
+
*/
|
|
69
|
+
getDetail(key: any): any;
|
|
70
|
+
/**
|
|
71
|
+
* @method
|
|
72
|
+
* @param {string} key
|
|
73
|
+
* @param {*} value
|
|
74
|
+
* @public
|
|
75
|
+
*/
|
|
76
|
+
setDetail(key: string, value: any): void;
|
|
77
|
+
/**
|
|
78
|
+
* @method
|
|
79
|
+
* @returns {Object}
|
|
80
|
+
* @public
|
|
81
|
+
*/
|
|
82
|
+
asJSON(): Object;
|
|
83
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export = applyWebConfigEnvOverrides;
|
|
2
|
+
/**
|
|
3
|
+
* Applies TI_WEB_* environment-variable overrides onto an (already-merged) web server configuration object.
|
|
4
|
+
* Each override is applied ONLY when its environment variable is defined, so an absent variable leaves the
|
|
5
|
+
* configured/default value untouched (fully backward compatible). This gives ti-engine web servers 12-factor,
|
|
6
|
+
* container-friendly control over network binding, TLS, the session cookie secret, the enabled authentication
|
|
7
|
+
* methods, the admin allowlist, the trusted request origins, and the `/static` cache policy without editing config files. Note `TI_WEB_AUTH_METHODS`,
|
|
8
|
+
* `TI_WEB_AUTH_ADMINS`, `TI_WEB_TRUSTED_ORIGINS`, and `TI_WEB_STATIC_IMMUTABLE_PATHS` fully REPLACE their config arrays (`auth.enabledMethods` / `auth.admins` / `trustedOrigins` / `staticCache.immutablePaths`) rather than
|
|
9
|
+
* merging — the config-file merge is by-index and cannot cleanly override an array.
|
|
10
|
+
*
|
|
11
|
+
* @method
|
|
12
|
+
* @param {Object} config The web server configuration to augment (mutated in place and returned).
|
|
13
|
+
* @param {Object} [env=process.env] The environment source (injectable for testing).
|
|
14
|
+
* @returns {Object} The same config object, with any present overrides applied.
|
|
15
|
+
* @public
|
|
16
|
+
*/
|
|
17
|
+
declare function applyWebConfigEnvOverrides(config: Object, env?: Object): Object;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export declare var onShutDownHandler: (instance: TiWebServer) => ExpressHandler;
|
|
2
|
+
export declare var resourceProtectionHandler: (instance: TiWebServer) => ExpressHandler;
|
|
3
|
+
export declare var authenticationHandler: (instance: TiWebServer) => ExpressHandler;
|
|
4
|
+
export declare var authorizedOAuth2CallbackHandler: (instance: TiWebServer, authMethod: TiAuthMethod) => ExpressHandler;
|
|
5
|
+
export declare var logoutHandler: () => ExpressHandler;
|
|
6
|
+
export declare var healthHandler: () => ExpressHandler;
|
|
7
|
+
export declare var userInformationHandler: () => ExpressHandler;
|
|
8
|
+
export declare var httpRedirectHandler: (instance: TiWebServer) => ExpressHandler;
|
|
9
|
+
export declare var serviceCallHandler: (instance: TiWebServer) => ExpressHandler;
|
|
10
|
+
export declare var invalidRouteHandler: () => ExpressHandler;
|
|
11
|
+
export declare var defaultErrorHandler: () => ExpressErrorHandler;
|
|
12
|
+
export declare var nonceGenerationHandler: () => ExpressHandler;
|
|
13
|
+
export declare var cspHeaderHandler: () => ExpressHandler;
|
|
14
|
+
export declare var webAppHandler: (instance: TiWebServer) => ExpressHandler;
|
|
15
|
+
export declare var originRefererValidationHandler: (instance: any) => ExpressHandler;
|
|
16
|
+
export declare var csrfInitHandler: (instance: TiWebServer) => ExpressHandler;
|
|
17
|
+
export declare var csrfProtectionHandler: () => ExpressHandler;
|
|
18
|
+
import type { TiAuthMethod } from "#auth-manager";
|
|
19
|
+
import type TiWebServer from "#web-server";
|
|
20
|
+
export type ExpressRequest = import("express").Request;
|
|
21
|
+
export type ExpressResponse = import("express").Response;
|
|
22
|
+
export type ExpressHandler = (request: ExpressRequest, response: ExpressResponse, next: (error: Error | null) => void) => void;
|
|
23
|
+
export type ExpressErrorHandler = (error: Error, request: ExpressRequest, response: ExpressResponse, next: (error: Error | null) => void) => void;
|