@ti-engine/web-framework 1.20.0 → 1.21.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/CHANGELOG.md +43 -0
- package/bin/localization/web-server-labels.json +161 -1
- package/bin/static/fragments/components/component-sidebar.html +25 -0
- package/bin/static/fragments/frame-about.html +96 -0
- package/bin/static/fragments/frame-profile.html +103 -3
- package/bin/static/scripts/ti-framework.css +139 -0
- package/bin/static/scripts/ti-framework.js +316 -0
- package/bin/web-app-manager.js +235 -2
- package/components/application-info.js +190 -0
- package/components/definitions.types.js +65 -0
- package/package.json +5 -1
- package/types/bin/web-app-manager.d.ts +95 -1
- package/types/bin/web-server.d.ts +1 -0
- package/types/components/application-info.d.ts +53 -0
- package/types/components/definitions.types.d.ts +166 -0
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The ti-engine is an open source, free to use—both for personal and commercial projects—framework for the creation of microservice-based solutions using node.js.
|
|
3
|
+
* Copyright © 2021-2026 Boris Kostadinov <kostadinov.boris@gmail.com>
|
|
4
|
+
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
5
|
+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
6
|
+
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
"use strict";
|
|
10
|
+
|
|
11
|
+
const path = require( "node:path" );
|
|
12
|
+
const fs = require( "node:fs" );
|
|
13
|
+
|
|
14
|
+
/** @import { TiApplicationInfo } from "#definitions" */
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Matches the leading npm scope of a package name (`@ti-engine/competence` → `competence`).
|
|
18
|
+
*
|
|
19
|
+
* @type {RegExp}
|
|
20
|
+
*/
|
|
21
|
+
const RE_PACKAGE_SCOPE = /^@[^/]+\//;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Matches the first character that can open the contact suffix of a `package.json` author string — the `<` of the
|
|
25
|
+
* e-mail or the `(` of the homepage.
|
|
26
|
+
*
|
|
27
|
+
* @type {RegExp}
|
|
28
|
+
*/
|
|
29
|
+
const RE_AUTHOR_CONTACT_START = /[<(]/;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Turns an npm package name into a human-readable display name — the scope is dropped and each dash/underscore
|
|
33
|
+
* separated word is capitalized (`@ti-engine/web-framework` → `Web Framework`). Used only when neither the manifest
|
|
34
|
+
* nor the environment supplies an explicit display name.
|
|
35
|
+
*
|
|
36
|
+
* @method
|
|
37
|
+
* @param {string} packageName
|
|
38
|
+
* @returns {string}
|
|
39
|
+
* @private
|
|
40
|
+
*/
|
|
41
|
+
function toDisplayName( packageName ) {
|
|
42
|
+
const bare = String( packageName || "" ).replace( RE_PACKAGE_SCOPE, "" ).trim();
|
|
43
|
+
if ( !bare ) {
|
|
44
|
+
return "";
|
|
45
|
+
}
|
|
46
|
+
return bare
|
|
47
|
+
.split( /[-_.\s]+/ )
|
|
48
|
+
.filter( ( word ) => word.length > 0 )
|
|
49
|
+
.map( ( word ) => word.charAt( 0 ).toUpperCase() + word.slice( 1 ) )
|
|
50
|
+
.join( " " );
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Reduces a `package.json` author entry — either the string form or the object form — to a bare display name,
|
|
55
|
+
* dropping the e-mail address and homepage that npm allows to be inlined in the string form.
|
|
56
|
+
* <br/>
|
|
57
|
+
* NOTE: npm's string form is `Name <email> (url)`, where both bracketed parts are optional **suffixes** — they are
|
|
58
|
+
* never embedded inside the name. So the name is simply everything before the first `<` or `(`. This deliberately
|
|
59
|
+
* does NOT globally remove `<…>` spans: a replace of that shape reads as an attempt to strip HTML tags, which
|
|
60
|
+
* CodeQL flags as an incomplete multi-character sanitizer (`js/incomplete-multi-character-sanitization`, high) —
|
|
61
|
+
* correctly, since one pass over `<<a>b>` leaves a stray `<`. Truncating at the delimiter matches the actual
|
|
62
|
+
* grammar and cannot leave a partial span behind.
|
|
63
|
+
*
|
|
64
|
+
* @method
|
|
65
|
+
* @param {string|Object} author
|
|
66
|
+
* @returns {string}
|
|
67
|
+
* @private
|
|
68
|
+
*/
|
|
69
|
+
function toAuthorName( author ) {
|
|
70
|
+
if ( author && typeof author === "object" ) {
|
|
71
|
+
return String( author.name || "" ).trim();
|
|
72
|
+
}
|
|
73
|
+
const declared = String( author || "" );
|
|
74
|
+
const contactStart = declared.search( RE_AUTHOR_CONTACT_START );
|
|
75
|
+
return ( contactStart === -1 ? declared : declared.slice( 0, contactStart ) ).trim();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Reduces a `package.json` repository entry — either the string shorthand or the object form — to a plain URL,
|
|
80
|
+
* stripping the `git+` prefix and `.git` suffix npm accepts so the result is browser-openable.
|
|
81
|
+
*
|
|
82
|
+
* @method
|
|
83
|
+
* @param {string|Object} repository
|
|
84
|
+
* @returns {string}
|
|
85
|
+
* @private
|
|
86
|
+
*/
|
|
87
|
+
function toRepositoryUrl( repository ) {
|
|
88
|
+
const raw = ( repository && typeof repository === "object" ) ? repository.url : repository;
|
|
89
|
+
const url = String( raw || "" ).trim();
|
|
90
|
+
if ( !url ) {
|
|
91
|
+
return "";
|
|
92
|
+
}
|
|
93
|
+
return url.replace( /^git\+/, "" ).replace( /\.git$/, "" );
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Returns the trimmed string value of `value`, or `fallback` when it is absent or blank. Keeps the builder below
|
|
98
|
+
* free of repeated `String( … ).trim() || …` noise while treating a whitespace-only manifest field as absent.
|
|
99
|
+
*
|
|
100
|
+
* @method
|
|
101
|
+
* @param {*} value
|
|
102
|
+
* @param {string} [fallback=""]
|
|
103
|
+
* @returns {string}
|
|
104
|
+
* @private
|
|
105
|
+
*/
|
|
106
|
+
function text( value, fallback = "" ) {
|
|
107
|
+
const resolved = String( value === undefined || value === null ? "" : value ).trim();
|
|
108
|
+
return resolved || fallback;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Builds the normalized application-information descriptor that backs the framework "About" screen.
|
|
113
|
+
* <br/>
|
|
114
|
+
* The function is PURE — everything it needs is injected — so the whole resolution order (manifest → environment
|
|
115
|
+
* override) is unit-testable without touching the filesystem or `process.env`. The impure half, reading the
|
|
116
|
+
* consuming application's manifest, is {@link readApplicationManifest}.
|
|
117
|
+
* <br/>
|
|
118
|
+
* Resolution order for the three overridable fields is manifest first, environment last:
|
|
119
|
+
* - `TI_WEB_APP_NAME` overrides `manifest.displayName` / a display name derived from `manifest.name`;
|
|
120
|
+
* - `TI_WEB_APP_VERSION` overrides `manifest.version`;
|
|
121
|
+
* - `TI_WEB_APP_RELEASE_DATE` overrides `manifest.releaseDate`.
|
|
122
|
+
* <br/>
|
|
123
|
+
* The environment wins because it is how a container image stamps facts that its baked-in manifest cannot know —
|
|
124
|
+
* most importantly the build/release date, for which `package.json` has no standard field at all.
|
|
125
|
+
*
|
|
126
|
+
* @method
|
|
127
|
+
* @param {Object} [options]
|
|
128
|
+
* @param {Object} [options.manifest] A `package.json`-shaped object for the consuming application.
|
|
129
|
+
* @param {Object} [options.env] The environment source (injectable for testing).
|
|
130
|
+
* @param {Array<{name: string, version: string}>} [options.components] Framework component versions to list.
|
|
131
|
+
* @param {Object} [options.runtime] Runtime facts (node/platform/instance). Included verbatim when present; the
|
|
132
|
+
* caller decides whether the current session is allowed to see them.
|
|
133
|
+
* @returns {TiApplicationInfo}
|
|
134
|
+
* @public
|
|
135
|
+
*/
|
|
136
|
+
function buildApplicationInfo( options = {} ) {
|
|
137
|
+
const manifest = ( options.manifest && typeof options.manifest === "object" ) ? options.manifest : {};
|
|
138
|
+
const env = ( options.env && typeof options.env === "object" ) ? options.env : {};
|
|
139
|
+
|
|
140
|
+
const packageName = text( manifest.name );
|
|
141
|
+
const name = text( env.TI_WEB_APP_NAME, text( manifest.displayName, toDisplayName( packageName ) ) );
|
|
142
|
+
const author = toAuthorName( manifest.author );
|
|
143
|
+
const homepage = text( manifest.homepage, toRepositoryUrl( manifest.repository ) );
|
|
144
|
+
|
|
145
|
+
const components = ( Array.isArray( options.components ) ? options.components : [] )
|
|
146
|
+
.map( ( component ) => ( {
|
|
147
|
+
name: text( component && component.name ),
|
|
148
|
+
version: text( component && component.version )
|
|
149
|
+
} ) )
|
|
150
|
+
.filter( ( component ) => component.name.length > 0 );
|
|
151
|
+
|
|
152
|
+
return {
|
|
153
|
+
name: name,
|
|
154
|
+
packageName: packageName,
|
|
155
|
+
version: text( env.TI_WEB_APP_VERSION, text( manifest.version ) ),
|
|
156
|
+
releaseDate: text( env.TI_WEB_APP_RELEASE_DATE, text( manifest.releaseDate ) ),
|
|
157
|
+
description: text( manifest.description ),
|
|
158
|
+
license: text( manifest.license ),
|
|
159
|
+
homepage: homepage,
|
|
160
|
+
author: author,
|
|
161
|
+
components: components,
|
|
162
|
+
runtime: ( options.runtime && typeof options.runtime === "object" ) ? { ...options.runtime } : null,
|
|
163
|
+
sections: []
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Reads the consuming application's `package.json`. This is the one impure function in this module.
|
|
169
|
+
* <br/>
|
|
170
|
+
* NOTE: A missing or malformed manifest resolves to an empty object rather than throwing — an informational screen
|
|
171
|
+
* must never be the reason a request fails, and {@link buildApplicationInfo} produces a usable (if sparse)
|
|
172
|
+
* descriptor from `{}`.
|
|
173
|
+
*
|
|
174
|
+
* @method
|
|
175
|
+
* @param {string} [directory=process.cwd()] The directory holding the manifest.
|
|
176
|
+
* @returns {Object}
|
|
177
|
+
* @public
|
|
178
|
+
*/
|
|
179
|
+
function readApplicationManifest( directory = process.cwd() ) {
|
|
180
|
+
try {
|
|
181
|
+
const manifestPath = path.join( directory, "package.json" );
|
|
182
|
+
const contents = fs.readFileSync( manifestPath, "utf8" );
|
|
183
|
+
const parsed = JSON.parse( contents );
|
|
184
|
+
return ( parsed && typeof parsed === "object" ) ? parsed : {};
|
|
185
|
+
} catch {
|
|
186
|
+
return {};
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
module.exports = { buildApplicationInfo, readApplicationManifest };
|
|
@@ -26,3 +26,68 @@
|
|
|
26
26
|
* @property {(callback: TiSessionCallback) => TiSession} destroy
|
|
27
27
|
* @property {(callback?: TiSessionCallback) => TiSession} save
|
|
28
28
|
*/
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* One label/value pair inside a {@link TiInfoSection}. Both strings are display-ready — already localized and
|
|
32
|
+
* already formatted by the server, since that is where the session language and the label catalogue live. The
|
|
33
|
+
* three flags are purely presentational; an empty `value` renders the screen's placeholder.
|
|
34
|
+
*
|
|
35
|
+
* @typedef {Object} TiInfoItem
|
|
36
|
+
* @property {string} label
|
|
37
|
+
* @property {string} [value]
|
|
38
|
+
* @property {string} [href] Renders the value as a link to this target. Only `http:`, `https:` and `mailto:` are
|
|
39
|
+
* honoured — any other scheme is dropped client-side and the item degrades to plain text.
|
|
40
|
+
* @property {boolean} [wide] Span the full width of the section grid instead of one column.
|
|
41
|
+
* @property {boolean} [mono] Render the value in the monospaced face (IDs, versions, hashes).
|
|
42
|
+
* @property {boolean} [muted] Render the value as a dimmed hint rather than primary text.
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* A titled group of label/value pairs. The framework's Profile and About screens render an array of these
|
|
47
|
+
* generically, so an application contributes content without contributing layout.
|
|
48
|
+
*
|
|
49
|
+
* @typedef {Object} TiInfoSection
|
|
50
|
+
* @property {string} title
|
|
51
|
+
* @property {string} [description] Optional intro line under the section title.
|
|
52
|
+
* @property {string} [icon] Optional `ti-icon` variant name for the section head.
|
|
53
|
+
* @property {boolean} [wide] Claim the full row of the two-up section grid instead of one column.
|
|
54
|
+
* @property {TiInfoItem[]} items A section with no items is dropped rather than rendered empty.
|
|
55
|
+
*/
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* The identity header of the Profile screen — the avatar/name block and the pills beside it.
|
|
59
|
+
*
|
|
60
|
+
* @typedef {Object} TiProfileIdentity
|
|
61
|
+
* @property {string} name
|
|
62
|
+
* @property {string} [subtitle] Meta line under the name (e.g. `role family · specialization · unit`).
|
|
63
|
+
* @property {string} [caption] Secondary line under the subtitle (e.g. the corporate e-mail).
|
|
64
|
+
* @property {string} [avatarSeed] Stable seed for the deterministic avatar colour; defaults to the name.
|
|
65
|
+
* @property {{text: string, tone?: string}} [badge] Small qualifier rendered inside the meta line.
|
|
66
|
+
* @property {Array<{text: string, tone?: string, dot?: boolean, mono?: boolean}>} [tags] Pills beside the name.
|
|
67
|
+
*/
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* The descriptor backing the framework Profile screen.
|
|
71
|
+
*
|
|
72
|
+
* @typedef {Object} TiProfileInfo
|
|
73
|
+
* @property {TiProfileIdentity} identity
|
|
74
|
+
* @property {TiInfoSection[]} sections
|
|
75
|
+
*/
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* The descriptor backing the framework About screen. Produced by `buildApplicationInfo` and optionally extended by
|
|
79
|
+
* the application through {@link TiWebAppManager#getApplicationInfo}.
|
|
80
|
+
*
|
|
81
|
+
* @typedef {Object} TiApplicationInfo
|
|
82
|
+
* @property {string} name Display name of the application.
|
|
83
|
+
* @property {string} packageName The npm package name it was resolved from.
|
|
84
|
+
* @property {string} version
|
|
85
|
+
* @property {string} releaseDate
|
|
86
|
+
* @property {string} description
|
|
87
|
+
* @property {string} license
|
|
88
|
+
* @property {string} homepage
|
|
89
|
+
* @property {string} author
|
|
90
|
+
* @property {Array<{name: string, version: string}>} components Framework component versions.
|
|
91
|
+
* @property {Object|null} runtime Runtime facts (node/platform/instance), or `null` when withheld.
|
|
92
|
+
* @property {TiInfoSection[]} sections Application-contributed extra sections.
|
|
93
|
+
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ti-engine/web-framework",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.21.0",
|
|
4
4
|
"description": "A web-framework based on the ti-engine. It provides a customizable ready-to-use web-server microservice and a set of tools for creating web applications. NOTICE: This is still a work in progress and the full architecture, design, and functionality are not available!",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ti-engine",
|
|
@@ -37,6 +37,10 @@
|
|
|
37
37
|
"types": "./types/components/admin-config-handlers.d.ts",
|
|
38
38
|
"default": "./components/admin-config-handlers.js"
|
|
39
39
|
},
|
|
40
|
+
"#application-info": {
|
|
41
|
+
"types": "./types/components/application-info.d.ts",
|
|
42
|
+
"default": "./components/application-info.js"
|
|
43
|
+
},
|
|
40
44
|
"#auth-manager": {
|
|
41
45
|
"types": "./types/components/auth-manager.d.ts",
|
|
42
46
|
"default": "./components/auth-manager.js"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export = TiWebAppManager;
|
|
2
|
-
import type { TiSession } from "#definitions";
|
|
2
|
+
import type { TiApplicationInfo, TiInfoSection, TiProfileInfo, TiSession } from "#definitions";
|
|
3
3
|
/**
|
|
4
4
|
* Gates the login-page authentication markup to the effective enabled methods. The login fragment delimits blocks
|
|
5
5
|
* with HTML-comment markers: `<!--ti-auth-method:METHOD-->…<!--/ti-auth-method-->` around each method's control
|
|
@@ -160,6 +160,100 @@ declare class TiWebAppManager {
|
|
|
160
160
|
* @public
|
|
161
161
|
*/
|
|
162
162
|
processDataRequest(session: TiSession, view: string, options?: Object): Promise<Object>;
|
|
163
|
+
/**
|
|
164
|
+
* Returns the configuration for the shared UI components the application shell renders — currently the sidebar
|
|
165
|
+
* user flyout menu. Shipped as part of the `config` data payload and merged into the `tiComponentsConfig`
|
|
166
|
+
* Alpine store on the client.
|
|
167
|
+
* <br/>
|
|
168
|
+
* The default menu links the two screens the framework itself provides (Profile and About) plus sign-out, so a
|
|
169
|
+
* consuming application gets a working user menu without configuring one. Override to replace it; a subclass
|
|
170
|
+
* that supplies its own `componentsConfig` naturally supersedes this.
|
|
171
|
+
*
|
|
172
|
+
* @method
|
|
173
|
+
* @param {TiSession} session
|
|
174
|
+
* @returns {Object}
|
|
175
|
+
* @virtual
|
|
176
|
+
* @public
|
|
177
|
+
*/
|
|
178
|
+
buildComponentsConfig(session: TiSession): Object;
|
|
179
|
+
/**
|
|
180
|
+
* Returns the descriptor rendered by the "Profile" screen — the identity header plus an ordered list of titled
|
|
181
|
+
* label/value sections. Every string in it is display-ready: the server resolves labels and formats values,
|
|
182
|
+
* because this is where the session language and the label catalogue are (see {@link resolveLabel}).
|
|
183
|
+
* <br/>
|
|
184
|
+
* The default implementation reports what the framework itself knows about the session user — name, username,
|
|
185
|
+
* e-mail, language and roles. Override in subclasses to show application-owned data instead; the screen, its
|
|
186
|
+
* Alpine component and its styling are inherited unchanged, so an override only decides the content.
|
|
187
|
+
* <br/>
|
|
188
|
+
* NOTE: The descriptor is always about the SESSION user. There is deliberately no "whose profile" parameter —
|
|
189
|
+
* viewing another person's record belongs to an application screen that carries its own scoping rules.
|
|
190
|
+
*
|
|
191
|
+
* @method
|
|
192
|
+
* @param {TiSession} session
|
|
193
|
+
* @returns {Promise<TiProfileInfo>}
|
|
194
|
+
* @exception {TiException.E_SEC_UNAUTHORIZED_ACCESS} (401) When the session carries no user.
|
|
195
|
+
* @virtual
|
|
196
|
+
* @public
|
|
197
|
+
*/
|
|
198
|
+
getProfileInfo(session: TiSession): Promise<TiProfileInfo>;
|
|
199
|
+
/**
|
|
200
|
+
* Returns the descriptor rendered by the "About" screen — the application's own identity (name, version,
|
|
201
|
+
* release date, description, license, homepage) plus the ti-engine component versions it runs on, and any
|
|
202
|
+
* extra sections the application contributes.
|
|
203
|
+
* <br/>
|
|
204
|
+
* The baseline is resolved once from the consuming application's `package.json`, overridable through
|
|
205
|
+
* `TI_WEB_APP_NAME` / `TI_WEB_APP_VERSION` / `TI_WEB_APP_RELEASE_DATE` (see `#application-info`), and cached —
|
|
206
|
+
* the manifest cannot change while the process runs.
|
|
207
|
+
* <br/>
|
|
208
|
+
* NOTE: Runtime facts (node version, platform, instance identity) are attached only for an `admin` session.
|
|
209
|
+
* They are operational detail that helps support and means nothing to an ordinary user, so they are not handed
|
|
210
|
+
* to every signed-in visitor. Override in subclasses to append application-specific sections; call `super` and
|
|
211
|
+
* extend the result rather than rebuilding it.
|
|
212
|
+
*
|
|
213
|
+
* @method
|
|
214
|
+
* @param {TiSession} session
|
|
215
|
+
* @returns {Promise<TiApplicationInfo>}
|
|
216
|
+
* @virtual
|
|
217
|
+
* @public
|
|
218
|
+
*/
|
|
219
|
+
getApplicationInfo(session: TiSession): Promise<TiApplicationInfo>;
|
|
220
|
+
/**
|
|
221
|
+
* Builds the identity header of the Profile screen from the session user. Kept separate from
|
|
222
|
+
* {@link TiWebAppManager#getProfileInfo} so a subclass that replaces the sections can still reuse — or fall
|
|
223
|
+
* back to — the framework's identity block when the application has no richer identity to show.
|
|
224
|
+
*
|
|
225
|
+
* @method
|
|
226
|
+
* @param {TiSession} session
|
|
227
|
+
* @returns {Object}
|
|
228
|
+
* @public
|
|
229
|
+
*/
|
|
230
|
+
buildSessionIdentity(session: TiSession): Object;
|
|
231
|
+
/**
|
|
232
|
+
* Builds the framework's account-level Profile sections from the session user. A subclass showing richer
|
|
233
|
+
* application data can append these so the account facts remain visible alongside it.
|
|
234
|
+
*
|
|
235
|
+
* @method
|
|
236
|
+
* @param {TiSession} session
|
|
237
|
+
* @returns {TiInfoSection[]}
|
|
238
|
+
* @public
|
|
239
|
+
*/
|
|
240
|
+
buildAccountSections(session: TiSession): TiInfoSection[];
|
|
241
|
+
/**
|
|
242
|
+
* Resolves the versions of the ti-engine packages the running application is built on, for the About screen.
|
|
243
|
+
* <br/>
|
|
244
|
+
* NOTE: `@ti-engine/core` does not expose `./package.json` through its exports map, so its manifest is located
|
|
245
|
+
* by walking up from a module it *does* export. A package that cannot be resolved is simply omitted — an
|
|
246
|
+
* informational screen must never be the reason a request fails.
|
|
247
|
+
*
|
|
248
|
+
* @method
|
|
249
|
+
* @static
|
|
250
|
+
* @returns {Array<{name: string, version: string}>}
|
|
251
|
+
* @public
|
|
252
|
+
*/
|
|
253
|
+
static resolveFrameworkComponents(): Array<{
|
|
254
|
+
name: string;
|
|
255
|
+
version: string;
|
|
256
|
+
}>;
|
|
163
257
|
/**
|
|
164
258
|
* Used to process an application service request.
|
|
165
259
|
*
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
declare const _exports: {
|
|
2
|
+
buildApplicationInfo: typeof buildApplicationInfo;
|
|
3
|
+
readApplicationManifest: typeof readApplicationManifest;
|
|
4
|
+
};
|
|
5
|
+
export = _exports;
|
|
6
|
+
import type { TiApplicationInfo } from "#definitions";
|
|
7
|
+
/**
|
|
8
|
+
* Builds the normalized application-information descriptor that backs the framework "About" screen.
|
|
9
|
+
* <br/>
|
|
10
|
+
* The function is PURE — everything it needs is injected — so the whole resolution order (manifest → environment
|
|
11
|
+
* override) is unit-testable without touching the filesystem or `process.env`. The impure half, reading the
|
|
12
|
+
* consuming application's manifest, is {@link readApplicationManifest}.
|
|
13
|
+
* <br/>
|
|
14
|
+
* Resolution order for the three overridable fields is manifest first, environment last:
|
|
15
|
+
* - `TI_WEB_APP_NAME` overrides `manifest.displayName` / a display name derived from `manifest.name`;
|
|
16
|
+
* - `TI_WEB_APP_VERSION` overrides `manifest.version`;
|
|
17
|
+
* - `TI_WEB_APP_RELEASE_DATE` overrides `manifest.releaseDate`.
|
|
18
|
+
* <br/>
|
|
19
|
+
* The environment wins because it is how a container image stamps facts that its baked-in manifest cannot know —
|
|
20
|
+
* most importantly the build/release date, for which `package.json` has no standard field at all.
|
|
21
|
+
*
|
|
22
|
+
* @method
|
|
23
|
+
* @param {Object} [options]
|
|
24
|
+
* @param {Object} [options.manifest] A `package.json`-shaped object for the consuming application.
|
|
25
|
+
* @param {Object} [options.env] The environment source (injectable for testing).
|
|
26
|
+
* @param {Array<{name: string, version: string}>} [options.components] Framework component versions to list.
|
|
27
|
+
* @param {Object} [options.runtime] Runtime facts (node/platform/instance). Included verbatim when present; the
|
|
28
|
+
* caller decides whether the current session is allowed to see them.
|
|
29
|
+
* @returns {TiApplicationInfo}
|
|
30
|
+
* @public
|
|
31
|
+
*/
|
|
32
|
+
declare function buildApplicationInfo(options?: {
|
|
33
|
+
manifest?: Object;
|
|
34
|
+
env?: Object;
|
|
35
|
+
components?: Array<{
|
|
36
|
+
name: string;
|
|
37
|
+
version: string;
|
|
38
|
+
}>;
|
|
39
|
+
runtime?: Object;
|
|
40
|
+
}): TiApplicationInfo;
|
|
41
|
+
/**
|
|
42
|
+
* Reads the consuming application's `package.json`. This is the one impure function in this module.
|
|
43
|
+
* <br/>
|
|
44
|
+
* NOTE: A missing or malformed manifest resolves to an empty object rather than throwing — an informational screen
|
|
45
|
+
* must never be the reason a request fails, and {@link buildApplicationInfo} produces a usable (if sparse)
|
|
46
|
+
* descriptor from `{}`.
|
|
47
|
+
*
|
|
48
|
+
* @method
|
|
49
|
+
* @param {string} [directory=process.cwd()] The directory holding the manifest.
|
|
50
|
+
* @returns {Object}
|
|
51
|
+
* @public
|
|
52
|
+
*/
|
|
53
|
+
declare function readApplicationManifest(directory?: string): Object;
|
|
@@ -11,6 +11,112 @@ export type TiSession = {
|
|
|
11
11
|
destroy: (callback: TiSessionCallback) => TiSession;
|
|
12
12
|
save: (callback?: TiSessionCallback) => TiSession;
|
|
13
13
|
};
|
|
14
|
+
export type TiInfoItem = {
|
|
15
|
+
label: string;
|
|
16
|
+
value?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Renders the value as a link to this target. Only `http:`, `https:` and `mailto:` are
|
|
19
|
+
* honoured — any other scheme is dropped client-side and the item degrades to plain text.
|
|
20
|
+
*/
|
|
21
|
+
href?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Span the full width of the section grid instead of one column.
|
|
24
|
+
*/
|
|
25
|
+
wide?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Render the value in the monospaced face (IDs, versions, hashes).
|
|
28
|
+
*/
|
|
29
|
+
mono?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Render the value as a dimmed hint rather than primary text.
|
|
32
|
+
*/
|
|
33
|
+
muted?: boolean;
|
|
34
|
+
};
|
|
35
|
+
export type TiInfoSection = {
|
|
36
|
+
title: string;
|
|
37
|
+
/**
|
|
38
|
+
* Optional intro line under the section title.
|
|
39
|
+
*/
|
|
40
|
+
description?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Optional `ti-icon` variant name for the section head.
|
|
43
|
+
*/
|
|
44
|
+
icon?: string;
|
|
45
|
+
/**
|
|
46
|
+
* Claim the full row of the two-up section grid instead of one column.
|
|
47
|
+
*/
|
|
48
|
+
wide?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* A section with no items is dropped rather than rendered empty.
|
|
51
|
+
*/
|
|
52
|
+
items: TiInfoItem[];
|
|
53
|
+
};
|
|
54
|
+
export type TiProfileIdentity = {
|
|
55
|
+
name: string;
|
|
56
|
+
/**
|
|
57
|
+
* Meta line under the name (e.g. `role family · specialization · unit`).
|
|
58
|
+
*/
|
|
59
|
+
subtitle?: string;
|
|
60
|
+
/**
|
|
61
|
+
* Secondary line under the subtitle (e.g. the corporate e-mail).
|
|
62
|
+
*/
|
|
63
|
+
caption?: string;
|
|
64
|
+
/**
|
|
65
|
+
* Stable seed for the deterministic avatar colour; defaults to the name.
|
|
66
|
+
*/
|
|
67
|
+
avatarSeed?: string;
|
|
68
|
+
/**
|
|
69
|
+
* Small qualifier rendered inside the meta line.
|
|
70
|
+
*/
|
|
71
|
+
badge?: {
|
|
72
|
+
text: string;
|
|
73
|
+
tone?: string;
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Pills beside the name.
|
|
77
|
+
*/
|
|
78
|
+
tags?: Array<{
|
|
79
|
+
text: string;
|
|
80
|
+
tone?: string;
|
|
81
|
+
dot?: boolean;
|
|
82
|
+
mono?: boolean;
|
|
83
|
+
}>;
|
|
84
|
+
};
|
|
85
|
+
export type TiProfileInfo = {
|
|
86
|
+
identity: TiProfileIdentity;
|
|
87
|
+
sections: TiInfoSection[];
|
|
88
|
+
};
|
|
89
|
+
export type TiApplicationInfo = {
|
|
90
|
+
/**
|
|
91
|
+
* Display name of the application.
|
|
92
|
+
*/
|
|
93
|
+
name: string;
|
|
94
|
+
/**
|
|
95
|
+
* The npm package name it was resolved from.
|
|
96
|
+
*/
|
|
97
|
+
packageName: string;
|
|
98
|
+
version: string;
|
|
99
|
+
releaseDate: string;
|
|
100
|
+
description: string;
|
|
101
|
+
license: string;
|
|
102
|
+
homepage: string;
|
|
103
|
+
author: string;
|
|
104
|
+
/**
|
|
105
|
+
* Framework component versions.
|
|
106
|
+
*/
|
|
107
|
+
components: Array<{
|
|
108
|
+
name: string;
|
|
109
|
+
version: string;
|
|
110
|
+
}>;
|
|
111
|
+
/**
|
|
112
|
+
* Runtime facts (node/platform/instance), or `null` when withheld.
|
|
113
|
+
*/
|
|
114
|
+
runtime: Object | null;
|
|
115
|
+
/**
|
|
116
|
+
* Application-contributed extra sections.
|
|
117
|
+
*/
|
|
118
|
+
sections: TiInfoSection[];
|
|
119
|
+
};
|
|
14
120
|
/** @import { TiLocalizationLanguage } from "@ti-engine/core/localization" */
|
|
15
121
|
/**
|
|
16
122
|
* @callback TiSessionCallback
|
|
@@ -29,3 +135,63 @@ export type TiSession = {
|
|
|
29
135
|
* @property {(callback: TiSessionCallback) => TiSession} destroy
|
|
30
136
|
* @property {(callback?: TiSessionCallback) => TiSession} save
|
|
31
137
|
*/
|
|
138
|
+
/**
|
|
139
|
+
* One label/value pair inside a {@link TiInfoSection}. Both strings are display-ready — already localized and
|
|
140
|
+
* already formatted by the server, since that is where the session language and the label catalogue live. The
|
|
141
|
+
* three flags are purely presentational; an empty `value` renders the screen's placeholder.
|
|
142
|
+
*
|
|
143
|
+
* @typedef {Object} TiInfoItem
|
|
144
|
+
* @property {string} label
|
|
145
|
+
* @property {string} [value]
|
|
146
|
+
* @property {string} [href] Renders the value as a link to this target. Only `http:`, `https:` and `mailto:` are
|
|
147
|
+
* honoured — any other scheme is dropped client-side and the item degrades to plain text.
|
|
148
|
+
* @property {boolean} [wide] Span the full width of the section grid instead of one column.
|
|
149
|
+
* @property {boolean} [mono] Render the value in the monospaced face (IDs, versions, hashes).
|
|
150
|
+
* @property {boolean} [muted] Render the value as a dimmed hint rather than primary text.
|
|
151
|
+
*/
|
|
152
|
+
/**
|
|
153
|
+
* A titled group of label/value pairs. The framework's Profile and About screens render an array of these
|
|
154
|
+
* generically, so an application contributes content without contributing layout.
|
|
155
|
+
*
|
|
156
|
+
* @typedef {Object} TiInfoSection
|
|
157
|
+
* @property {string} title
|
|
158
|
+
* @property {string} [description] Optional intro line under the section title.
|
|
159
|
+
* @property {string} [icon] Optional `ti-icon` variant name for the section head.
|
|
160
|
+
* @property {boolean} [wide] Claim the full row of the two-up section grid instead of one column.
|
|
161
|
+
* @property {TiInfoItem[]} items A section with no items is dropped rather than rendered empty.
|
|
162
|
+
*/
|
|
163
|
+
/**
|
|
164
|
+
* The identity header of the Profile screen — the avatar/name block and the pills beside it.
|
|
165
|
+
*
|
|
166
|
+
* @typedef {Object} TiProfileIdentity
|
|
167
|
+
* @property {string} name
|
|
168
|
+
* @property {string} [subtitle] Meta line under the name (e.g. `role family · specialization · unit`).
|
|
169
|
+
* @property {string} [caption] Secondary line under the subtitle (e.g. the corporate e-mail).
|
|
170
|
+
* @property {string} [avatarSeed] Stable seed for the deterministic avatar colour; defaults to the name.
|
|
171
|
+
* @property {{text: string, tone?: string}} [badge] Small qualifier rendered inside the meta line.
|
|
172
|
+
* @property {Array<{text: string, tone?: string, dot?: boolean, mono?: boolean}>} [tags] Pills beside the name.
|
|
173
|
+
*/
|
|
174
|
+
/**
|
|
175
|
+
* The descriptor backing the framework Profile screen.
|
|
176
|
+
*
|
|
177
|
+
* @typedef {Object} TiProfileInfo
|
|
178
|
+
* @property {TiProfileIdentity} identity
|
|
179
|
+
* @property {TiInfoSection[]} sections
|
|
180
|
+
*/
|
|
181
|
+
/**
|
|
182
|
+
* The descriptor backing the framework About screen. Produced by `buildApplicationInfo` and optionally extended by
|
|
183
|
+
* the application through {@link TiWebAppManager#getApplicationInfo}.
|
|
184
|
+
*
|
|
185
|
+
* @typedef {Object} TiApplicationInfo
|
|
186
|
+
* @property {string} name Display name of the application.
|
|
187
|
+
* @property {string} packageName The npm package name it was resolved from.
|
|
188
|
+
* @property {string} version
|
|
189
|
+
* @property {string} releaseDate
|
|
190
|
+
* @property {string} description
|
|
191
|
+
* @property {string} license
|
|
192
|
+
* @property {string} homepage
|
|
193
|
+
* @property {string} author
|
|
194
|
+
* @property {Array<{name: string, version: string}>} components Framework component versions.
|
|
195
|
+
* @property {Object|null} runtime Runtime facts (node/platform/instance), or `null` when withheld.
|
|
196
|
+
* @property {TiInfoSection[]} sections Application-contributed extra sections.
|
|
197
|
+
*/
|