@itrocks/framework 0.2.1 → 0.2.3
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 +251 -0
- package/cjs/dependencies.js +29 -13
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -7,3 +7,254 @@
|
|
|
7
7
|
# it.rocks framework
|
|
8
8
|
|
|
9
9
|
RAD framework for intuitive web application development, blending data and domain-driven design with modular architecture.
|
|
10
|
+
|
|
11
|
+
*This documentation was written by an artificial intelligence and may contain errors or approximations.
|
|
12
|
+
It has not yet been fully reviewed by a human. If anything seems unclear or incomplete,
|
|
13
|
+
please feel free to contact the author of this package.*
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm i @itrocks/framework
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
In a typical it.rocks application you install the framework together with
|
|
22
|
+
the modules that provide your domain model, actions and UI pieces. The
|
|
23
|
+
framework itself focuses on wiring everything together.
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
Importing `@itrocks/framework` has two main effects:
|
|
28
|
+
|
|
29
|
+
- it boots the framework at runtime (composition of modules, configuration
|
|
30
|
+
loading, HTTP server and main loop),
|
|
31
|
+
- it exposes enhanced reflection helpers `ReflectClass` and
|
|
32
|
+
`ReflectProperty` that integrate with the rest of the it.rocks
|
|
33
|
+
ecosystem.
|
|
34
|
+
|
|
35
|
+
Most of the time you do **not** import low‑level files from this package
|
|
36
|
+
directly. Instead you:
|
|
37
|
+
|
|
38
|
+
1. Start your application by importing the compiled entry point
|
|
39
|
+
`@itrocks/framework/cjs/framework.js` (or the plain `@itrocks/framework`
|
|
40
|
+
export from Node when appropriate).
|
|
41
|
+
2. Use `ReflectClass` / `ReflectProperty` from `@itrocks/framework` when you
|
|
42
|
+
need reflection that understands it.rocks‑specific concepts such as
|
|
43
|
+
`uses` and HTML transformers.
|
|
44
|
+
|
|
45
|
+
### Minimal bootstrap example
|
|
46
|
+
|
|
47
|
+
The simplest way to start an it.rocks application is to import the
|
|
48
|
+
framework once at startup. It will:
|
|
49
|
+
|
|
50
|
+
- scan configuration files (`config.yaml`, `local.yaml`) of your
|
|
51
|
+
application and its dependencies,
|
|
52
|
+
- compose all registered modules (actions, routes, templates, stores,
|
|
53
|
+
transformers, …),
|
|
54
|
+
- build the default action workflow,
|
|
55
|
+
- bind framework dependencies,
|
|
56
|
+
- run the main server loop.
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
// index.ts
|
|
60
|
+
import '@itrocks/framework'
|
|
61
|
+
|
|
62
|
+
// Import your application modules so that their configuration, actions
|
|
63
|
+
// and templates are discovered during composition.
|
|
64
|
+
import '@itrocks/home'
|
|
65
|
+
import './src/domain'
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
When this file is executed with Node (after TypeScript compilation), the
|
|
69
|
+
framework starts automatically and exposes your routes and actions.
|
|
70
|
+
|
|
71
|
+
### Using framework reflection helpers
|
|
72
|
+
|
|
73
|
+
`ReflectClass` and `ReflectProperty` behave like their counterparts from
|
|
74
|
+
`@itrocks/reflect`, but they add framework‑level knowledge:
|
|
75
|
+
|
|
76
|
+
- `ReflectClass` understands mixins declared through `@itrocks/uses` and
|
|
77
|
+
merges their property types,
|
|
78
|
+
- `ReflectProperty` is able to render property values using
|
|
79
|
+
transformers from `@itrocks/transformer` and
|
|
80
|
+
`@itrocks/core-transformers`.
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
import type { ObjectType } from '@itrocks/class-type'
|
|
84
|
+
import { ReflectClass } from '@itrocks/framework'
|
|
85
|
+
import { EmailAddress, emailAddressOf } from '@itrocks/email-address'
|
|
86
|
+
|
|
87
|
+
class User {
|
|
88
|
+
@EmailAddress()
|
|
89
|
+
email = ''
|
|
90
|
+
|
|
91
|
+
name = ''
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async function renderUserSummary(user: User) {
|
|
95
|
+
const reflectClass = new ReflectClass<User>(User as ObjectType<User>)
|
|
96
|
+
const properties = reflectClass.properties
|
|
97
|
+
|
|
98
|
+
const result: Record<string, string> = {}
|
|
99
|
+
|
|
100
|
+
for (const property of properties) {
|
|
101
|
+
const isEmail = emailAddressOf(User, property.name as keyof User)
|
|
102
|
+
const value = await property.output()
|
|
103
|
+
|
|
104
|
+
result[property.name] = isEmail ? `<a href="mailto:${value}">${value}</a>` : String(value ?? '')
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return result
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
In this example:
|
|
112
|
+
|
|
113
|
+
- `ReflectClass` gives you `ReflectProperty` instances rather than the
|
|
114
|
+
bare properties from `@itrocks/reflect`,
|
|
115
|
+
- each `ReflectProperty` can render its value using configured
|
|
116
|
+
transformers (`property.output()`),
|
|
117
|
+
- you can combine metadata from other packages (like
|
|
118
|
+
`@itrocks/email-address`) to build higher‑level behaviour.
|
|
119
|
+
|
|
120
|
+
## API
|
|
121
|
+
|
|
122
|
+
`@itrocks/framework` exposes two main public symbols and the side‑effect
|
|
123
|
+
of bootstrapping the framework when its main module is imported.
|
|
124
|
+
|
|
125
|
+
### Framework bootstrap (side‑effect of importing `@itrocks/framework`)
|
|
126
|
+
|
|
127
|
+
When the compiled JavaScript entry point (`cjs/framework.js`) is loaded,
|
|
128
|
+
the following steps are executed:
|
|
129
|
+
|
|
130
|
+
1. `scanConfigFiles()` from `@itrocks/config` is called to build the
|
|
131
|
+
global `config` object from all discovered `config.yaml` / `local.yaml`
|
|
132
|
+
files.
|
|
133
|
+
2. The application composition is built with `compose()` from
|
|
134
|
+
`@itrocks/compose`, wiring stores, actions, routes, templates and other
|
|
135
|
+
components declared by installed modules.
|
|
136
|
+
3. `build()` from `@itrocks/default-action-workflow` is invoked to
|
|
137
|
+
register the default actions workflow (list/new/delete, login/signup,
|
|
138
|
+
output/edit/print/delete, …).
|
|
139
|
+
4. `bind()` from the local `dependencies` module wires framework
|
|
140
|
+
dependencies (such as HTTP server, logging and storage bindings).
|
|
141
|
+
5. `run()` from the local `main` module starts the framework main loop
|
|
142
|
+
(HTTP server and request handling in a typical application).
|
|
143
|
+
|
|
144
|
+
You normally do not call any of these functions directly. Importing the
|
|
145
|
+
module once at startup is enough to run your application, provided that
|
|
146
|
+
you have configured your routes and modules.
|
|
147
|
+
|
|
148
|
+
### `class ReflectClass<T extends object = object> extends RC<T>`
|
|
149
|
+
|
|
150
|
+
Enhanced reflection class that extends
|
|
151
|
+
`@itrocks/reflect:ReflectClass<T>` and adds framework‑specific
|
|
152
|
+
behaviour.
|
|
153
|
+
|
|
154
|
+
Typical usage:
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
import { ReflectClass } from '@itrocks/framework'
|
|
158
|
+
|
|
159
|
+
const reflectClass = new ReflectClass(SomeDomainClass)
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
#### Methods and properties
|
|
163
|
+
|
|
164
|
+
- `inheritedPropertyTypes(propertyTypes: PropertyTypes): void`
|
|
165
|
+
|
|
166
|
+
Extends the base implementation by also merging property types coming
|
|
167
|
+
from classes declared in the `uses` of the current type (via
|
|
168
|
+
`@itrocks/uses`). This lets you treat mixin properties as if they were
|
|
169
|
+
declared directly on the class.
|
|
170
|
+
|
|
171
|
+
- `get parent(): ReflectClass | undefined`
|
|
172
|
+
|
|
173
|
+
Returns the parent `ReflectClass` if the current type inherits from
|
|
174
|
+
another class. The parent is wrapped so that it also benefits from the
|
|
175
|
+
framework‑specific methods.
|
|
176
|
+
|
|
177
|
+
- `get properties(): Iterable<ReflectProperty<T>>`
|
|
178
|
+
|
|
179
|
+
Returns an iterable collection of `ReflectProperty<T>` instances, one
|
|
180
|
+
for each property of the reflected class. All of them are upgraded to
|
|
181
|
+
the `ReflectProperty` defined by this package.
|
|
182
|
+
|
|
183
|
+
- `property(name: KeyOf<T>): ReflectProperty<T>`
|
|
184
|
+
|
|
185
|
+
Returns a single `ReflectProperty<T>` instance for the given property
|
|
186
|
+
name. This is the preferred way to work with properties when you want
|
|
187
|
+
to use framework helpers like `output()` and `edit()`.
|
|
188
|
+
|
|
189
|
+
- `get uses(): Type[]`
|
|
190
|
+
|
|
191
|
+
Returns the list of mixin classes attached to the current type through
|
|
192
|
+
`@itrocks/uses`. The result is cached on the instance.
|
|
193
|
+
|
|
194
|
+
### `class ReflectProperty<T extends object> extends RP<T>`
|
|
195
|
+
|
|
196
|
+
Enhanced property reflection class that extends
|
|
197
|
+
`@itrocks/reflect:ReflectProperty<T>` and knows how to call transformers
|
|
198
|
+
from `@itrocks/transformer` / `@itrocks/core-transformers` in the
|
|
199
|
+
context of the framework.
|
|
200
|
+
|
|
201
|
+
Typical usage:
|
|
202
|
+
|
|
203
|
+
```ts
|
|
204
|
+
import { ReflectClass } from '@itrocks/framework'
|
|
205
|
+
|
|
206
|
+
async function renderProperty(object: any, name: string) {
|
|
207
|
+
const reflectClass = new ReflectClass(object.constructor)
|
|
208
|
+
const reflectProperty = reflectClass.property(name as never)
|
|
209
|
+
return await reflectProperty.output()
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
#### Properties
|
|
214
|
+
|
|
215
|
+
- `get class: ReflectClass<T>`
|
|
216
|
+
|
|
217
|
+
Returns the owning `ReflectClass` instance, upgraded from the base
|
|
218
|
+
implementation so that it always exposes the framework‑aware
|
|
219
|
+
`ReflectClass`.
|
|
220
|
+
|
|
221
|
+
#### Methods
|
|
222
|
+
|
|
223
|
+
- `async edit(format: string = HTML): Promise<any>`
|
|
224
|
+
|
|
225
|
+
Applies the `EDIT` transformer chain to the property and returns the
|
|
226
|
+
result, usually an HTML fragment representing an input field or an
|
|
227
|
+
editable widget. You can change the `format` to use an alternative
|
|
228
|
+
representation if you have registered other transformers.
|
|
229
|
+
|
|
230
|
+
- `async output(format: string = HTML, askFor?: HtmlContainer): Promise<any>`
|
|
231
|
+
|
|
232
|
+
Applies the `OUTPUT` transformer chain to the property and returns the
|
|
233
|
+
result (often an HTML fragment for display). The optional `askFor`
|
|
234
|
+
`HtmlContainer` lets you drive how the output is wrapped.
|
|
235
|
+
|
|
236
|
+
- `async outputMandatoryContainer(format: string = HTML): Promise<any>`
|
|
237
|
+
|
|
238
|
+
Convenience wrapper around `output()` that always wraps the result in
|
|
239
|
+
a mandatory `HtmlContainer`.
|
|
240
|
+
|
|
241
|
+
- `async outputOptionalContainer(format: string = HTML): Promise<any>`
|
|
242
|
+
|
|
243
|
+
Convenience wrapper around `output()` that wraps the result in an
|
|
244
|
+
optional `HtmlContainer`.
|
|
245
|
+
|
|
246
|
+
## Typical use cases
|
|
247
|
+
|
|
248
|
+
- Quickly bootstrap a full it.rocks web application by importing the
|
|
249
|
+
framework once at startup; it takes care of configuration loading,
|
|
250
|
+
module composition and action workflow wiring.
|
|
251
|
+
- Integrate multiple it.rocks modules (actions, routes, templates,
|
|
252
|
+
storage, translations, UI components, …) without writing plumbing
|
|
253
|
+
code.
|
|
254
|
+
- Use `ReflectClass` / `ReflectProperty` when you need to:
|
|
255
|
+
- inspect domain models and their properties (including mixins),
|
|
256
|
+
- generate forms and views using the configured transformers,
|
|
257
|
+
- render property values consistently across your application.
|
|
258
|
+
- Build higher‑level tooling (CRUD generators, admin dashboards,
|
|
259
|
+
documentation tools) on top of the reflection API exposed by the
|
|
260
|
+
framework.
|
package/cjs/dependencies.js
CHANGED
|
@@ -6,6 +6,8 @@ const lazy_loading_1 = require("@itrocks/lazy-loading");
|
|
|
6
6
|
const action_1 = require("@itrocks/action");
|
|
7
7
|
const app_dir_1 = require("@itrocks/app-dir");
|
|
8
8
|
const class_file_1 = require("@itrocks/class-file");
|
|
9
|
+
const class_type_1 = require("@itrocks/class-type");
|
|
10
|
+
const class_type_2 = require("@itrocks/class-type");
|
|
9
11
|
const class_view_1 = require("@itrocks/class-view");
|
|
10
12
|
const class_view_2 = require("@itrocks/class-view");
|
|
11
13
|
const collection_1 = require("@itrocks/collection");
|
|
@@ -16,7 +18,6 @@ const core_transformers_2 = require("@itrocks/core-transformers");
|
|
|
16
18
|
const file_1 = require("@itrocks/file");
|
|
17
19
|
const lazy_loading_2 = require("@itrocks/lazy-loading");
|
|
18
20
|
const list_properties_1 = require("@itrocks/list-properties");
|
|
19
|
-
const menu_1 = require("@itrocks/menu");
|
|
20
21
|
const mysql_1 = require("@itrocks/mysql");
|
|
21
22
|
const password_1 = require("@itrocks/password");
|
|
22
23
|
const transformers_1 = require("@itrocks/password/transformers");
|
|
@@ -42,7 +43,6 @@ const translate_1 = require("@itrocks/translate");
|
|
|
42
43
|
const date_fns_1 = require("date-fns");
|
|
43
44
|
const node_path_1 = require("node:path");
|
|
44
45
|
const node_path_2 = require("node:path");
|
|
45
|
-
const menu = new menu_1.Menu(config_1.config.menu);
|
|
46
46
|
async function propertyOutput(object, property) {
|
|
47
47
|
return (0, transformer_1.applyTransformer)(await object[property], object, property, transformer_2.HTML, transformer_3.OUTPUT);
|
|
48
48
|
}
|
|
@@ -109,20 +109,36 @@ function bind() {
|
|
|
109
109
|
(0, translate_1.trLoad)((0, node_path_1.join)(app_dir_1.appDir, 'app', 'fr-FR.csv')).catch();
|
|
110
110
|
(0, translate_1.trLoad)((0, node_path_1.join)(app_dir_1.appDir, 'fr-FR.csv')).catch();
|
|
111
111
|
action_1.Action.prototype.htmlTemplateResponse = async function (data, request, templateFile, statusCode = 200, headers = {}) {
|
|
112
|
-
const containerData =
|
|
113
|
-
action: request.action,
|
|
114
|
-
favicon: config_1.config.container?.favicon ?? (0, node_path_2.normalize)((0, node_path_1.join)(__dirname, '../favicon.ico')),
|
|
115
|
-
manifest: config_1.config.container?.manifest ? [config_1.config.container.manifest] : [],
|
|
116
|
-
menu,
|
|
117
|
-
request,
|
|
118
|
-
scripts: config_1.config.container?.scripts,
|
|
119
|
-
session: request.request.session,
|
|
120
|
-
styleSheets: config_1.config.container?.styleSheets,
|
|
121
|
-
};
|
|
122
|
-
Object.assign(containerData, this);
|
|
112
|
+
const containerData = Object.assign(defaultContainerData(request), this);
|
|
123
113
|
const contained = !request.request.headers['xhr-info'] && config_1.config.container?.file;
|
|
124
114
|
const template = new template_insight_1.Template(data, containerData);
|
|
125
115
|
return this.htmlResponse(await template.parseFile(templateFile, contained && (0, node_path_1.join)(app_dir_1.appDir, config_1.config.container.file)), statusCode, headers);
|
|
126
116
|
};
|
|
127
117
|
}
|
|
118
|
+
function configContainerData() {
|
|
119
|
+
const configContainerData = config_1.config.container?.data ?? {};
|
|
120
|
+
for (const [name, value] of Object.entries(configContainerData)) {
|
|
121
|
+
if ((typeof value === 'string') && '@.'.includes(value[0])) {
|
|
122
|
+
const exported = value.includes(':')
|
|
123
|
+
? require(value.split(':')[0])[value.split(':')[1]]
|
|
124
|
+
: (require(value).default ?? Object.values(require(value))[0]);
|
|
125
|
+
configContainerData[name] =
|
|
126
|
+
(0, class_type_1.isAnyFunction)(exported) ? exported(config_1.config[name]) :
|
|
127
|
+
(0, class_type_2.isAnyType)(exported) ? new exported(config_1.config[name]) :
|
|
128
|
+
exported;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return configContainerData;
|
|
132
|
+
}
|
|
133
|
+
function defaultContainerData(request) {
|
|
134
|
+
return Object.assign({
|
|
135
|
+
action: request.action,
|
|
136
|
+
favicon: config_1.config.container?.favicon ?? (0, node_path_2.normalize)((0, node_path_1.join)(__dirname, '../favicon.ico')),
|
|
137
|
+
manifest: config_1.config.container?.manifest ? [config_1.config.container.manifest] : [],
|
|
138
|
+
request,
|
|
139
|
+
scripts: config_1.config.container?.scripts,
|
|
140
|
+
session: request.request.session,
|
|
141
|
+
styleSheets: config_1.config.container?.styleSheets,
|
|
142
|
+
}, configContainerData());
|
|
143
|
+
}
|
|
128
144
|
//# sourceMappingURL=dependencies.js.map
|
package/package.json
CHANGED
|
@@ -76,8 +76,12 @@
|
|
|
76
76
|
"business",
|
|
77
77
|
"domain",
|
|
78
78
|
"driven",
|
|
79
|
+
"dynamics",
|
|
79
80
|
"framework",
|
|
80
|
-
"
|
|
81
|
+
"http",
|
|
82
|
+
"itrocks",
|
|
83
|
+
"it.rocks",
|
|
84
|
+
"package"
|
|
81
85
|
],
|
|
82
86
|
"license": "ISC",
|
|
83
87
|
"name": "@itrocks/framework",
|
|
@@ -91,5 +95,5 @@
|
|
|
91
95
|
"build:front": "tsc -p src/front/tsconfig.json && sed -i 's#../../##g' *.js *.d.ts"
|
|
92
96
|
},
|
|
93
97
|
"types": "./cjs/framework.d.ts",
|
|
94
|
-
"version": "0.2.
|
|
98
|
+
"version": "0.2.3"
|
|
95
99
|
}
|