libmodulor 0.24.0 → 0.25.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 +17 -0
- package/README.md +1 -1
- package/dist/esm/apps/Helper/src/lib/project.js +6 -6
- package/dist/esm/dt/Validation.d.ts +2 -2
- package/dist/esm/dt/base/TBase.d.ts +2 -0
- package/dist/esm/dt/base/TBase.js +3 -0
- package/dist/esm/dt/base/TObject.d.ts +6 -4
- package/dist/esm/dt/base/TObject.js +4 -5
- package/dist/esm/dt/base/TString.d.ts +2 -1
- package/dist/esm/dt/base/TString.js +22 -0
- package/dist/esm/dt/final/TFile.d.ts +13 -4
- package/dist/esm/dt/final/TFile.js +70 -8
- package/dist/esm/dt/final/TFileExtension.d.ts +1 -1
- package/dist/esm/dt/final/TFileMimeType.d.ts +2 -6
- package/dist/esm/dt/final/TFileMimeType.js +0 -6
- package/dist/esm/dt/final/TFilePath.d.ts +7 -0
- package/dist/esm/dt/final/TFilePath.js +5 -1
- package/dist/esm/dt/index.d.ts +1 -1
- package/dist/esm/i18n/WordingManager.d.ts +2 -1
- package/dist/esm/i18n/WordingManager.js +23 -2
- package/dist/esm/i18n/locales/de.js +8 -0
- package/dist/esm/i18n/locales/en.js +8 -0
- package/dist/esm/i18n/locales/es.js +8 -0
- package/dist/esm/i18n/locales/fr.js +8 -0
- package/dist/esm/i18n/types.d.ts +2 -2
- package/dist/esm/std/FSManager.d.ts +7 -5
- package/dist/esm/std/FSManager.js +5 -6
- package/dist/esm/std/FormDataBuilder.d.ts +2 -1
- package/dist/esm/std/impl/NodeFSManager.js +3 -2
- package/dist/esm/target/lib/react/StyleContextProvider.d.ts +1 -0
- package/dist/esm/target/lib/react/form.d.ts +1 -1
- package/dist/esm/target/lib/react/form.js +1 -0
- package/dist/esm/target/lib/react/useAction.d.ts +1 -1
- package/dist/esm/target/lib/react/useAction.js +13 -12
- package/dist/esm/target/lib/server-express/funcs.js +2 -1
- package/dist/esm/target/lib/web/input.d.ts +1 -0
- package/dist/esm/target/lib/web/input.js +5 -1
- package/dist/esm/target/react-native-pure/UCFormField.js +2 -1
- package/dist/esm/target/react-native-pure/UCFormFieldControl.js +6 -4
- package/dist/esm/target/react-native-pure/UCFormFieldErr.d.ts +1 -1
- package/dist/esm/target/react-native-pure/UCFormFieldErr.js +4 -1
- package/dist/esm/target/react-native-pure/UCFormFieldHelp.d.ts +4 -0
- package/dist/esm/target/react-native-pure/UCFormFieldHelp.js +15 -0
- package/dist/esm/target/react-web-pure/UCFormField.js +2 -1
- package/dist/esm/target/react-web-pure/UCFormFieldErr.d.ts +1 -1
- package/dist/esm/target/react-web-pure/UCFormFieldErr.js +4 -1
- package/dist/esm/target/react-web-pure/UCFormFieldHelp.d.ts +4 -0
- package/dist/esm/target/react-web-pure/UCFormFieldHelp.js +14 -0
- package/dist/esm/testing/impl/SimpleAppDocsEmitter/SimpleAppDocsEmitter.d.ts +7 -0
- package/dist/esm/testing/impl/SimpleAppDocsEmitter/SimpleAppDocsEmitter.js +59 -0
- package/dist/esm/testing/impl/SimpleAppDocsEmitter/markdown.d.ts +2 -0
- package/dist/esm/testing/impl/SimpleAppDocsEmitter/markdown.js +10 -0
- package/dist/esm/testing/impl/SimpleAppDocsEmitter/sequence-diagram.d.ts +2 -0
- package/dist/esm/testing/impl/SimpleAppDocsEmitter/sequence-diagram.js +92 -0
- package/dist/esm/testing/impl/SimpleAppDocsEmitter/tech-summary.d.ts +2 -0
- package/dist/esm/testing/impl/SimpleAppDocsEmitter/tech-summary.js +27 -0
- package/dist/esm/testing/impl/SimpleAppDocsEmitter/uc-summary.d.ts +2 -0
- package/dist/esm/testing/impl/SimpleAppDocsEmitter/uc-summary.js +63 -0
- package/dist/esm/testing/impl/newNodeAppTester.js +1 -1
- package/dist/esm/testing/uc-input.js +5 -2
- package/dist/esm/uc/exec.d.ts +42 -21
- package/dist/esm/uc/exec.js +48 -13
- package/dist/esm/uc/input-field.d.ts +6 -4
- package/dist/esm/uc/input-field.js +4 -5
- package/dist/esm/uc/side-effect.d.ts +10 -8
- package/dist/esm/uc/side-effect.js +5 -6
- package/dist/esm/uc/workers/UCInputFilesProcessor.js +3 -3
- package/dist/esm/uc/workers/UCInputValidator.js +2 -1
- package/dist/esm/uc/workers/UCOutputFilesProcessor.js +1 -1
- package/dist/esm/utils/bundling/webpack/loader.js +1 -1
- package/dist/esm/utils/index.d.ts +1 -1
- package/dist/esm/utils/types/utility-types.d.ts +4 -0
- package/package.json +16 -14
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
})(FSManagerItemInfoType || (FSManagerItemInfoType = {}));
|
|
1
|
+
export const FSManagerItemInfoType = {
|
|
2
|
+
DIR: 'DIR',
|
|
3
|
+
FILE: 'FILE',
|
|
4
|
+
OTHER: 'OTHER',
|
|
5
|
+
};
|
|
@@ -94,15 +94,16 @@ let NodeFSManager = class NodeFSManager {
|
|
|
94
94
|
}
|
|
95
95
|
switch (source) {
|
|
96
96
|
case 'path': {
|
|
97
|
-
const { base: name, mimeType: type } = await this.info(path);
|
|
97
|
+
const { base: name, mimeType: type, size, } = await this.info(path);
|
|
98
98
|
if (!type) {
|
|
99
99
|
return [];
|
|
100
100
|
}
|
|
101
101
|
return [
|
|
102
102
|
{
|
|
103
103
|
name,
|
|
104
|
-
|
|
104
|
+
size,
|
|
105
105
|
type,
|
|
106
|
+
uri: path,
|
|
106
107
|
},
|
|
107
108
|
];
|
|
108
109
|
}
|
|
@@ -18,6 +18,7 @@ export interface StyleContextT {
|
|
|
18
18
|
formField?: StyleDef | undefined;
|
|
19
19
|
formFieldControl?: Record<SelectiveStyleDefKey, StyleDef | undefined>;
|
|
20
20
|
formFieldDesc?: StyleDef | undefined;
|
|
21
|
+
formFieldHelp?: StyleDef | undefined;
|
|
21
22
|
formFieldErr?: StyleDef | undefined;
|
|
22
23
|
formFieldLabel?: StyleDef | undefined;
|
|
23
24
|
formSubmitControl?: StyleDef | undefined;
|
|
@@ -18,7 +18,7 @@ export interface UCFormFieldErrProps {
|
|
|
18
18
|
export interface UCFormFieldLabelProps<T extends DataType> {
|
|
19
19
|
f: UCInputField<T>;
|
|
20
20
|
}
|
|
21
|
-
export declare const UC_FORM_FIELD_ELEMENTS: readonly ["control", "desc", "err", "label"];
|
|
21
|
+
export declare const UC_FORM_FIELD_ELEMENTS: readonly ["control", "desc", "err", "help", "label"];
|
|
22
22
|
export type UCFormFieldElement = (typeof UC_FORM_FIELD_ELEMENTS)[number];
|
|
23
23
|
export type UCFormFieldProps<T extends DataType> = Omit<UCFormFieldControlProps<T>, 'onChange'> & {
|
|
24
24
|
only?: UCFormFieldElement[];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ErrorMessage, UIntDuration } from '../../../dt/index.js';
|
|
2
|
-
import
|
|
2
|
+
import { UCExecRes, UCExecState } from '../../../uc/index.js';
|
|
3
3
|
export type UseActionAction = () => Promise<void>;
|
|
4
4
|
export type UseActionConfirm = () => Promise<boolean>;
|
|
5
5
|
export type UseActionExec = () => Promise<UCExecRes>;
|
|
@@ -1,54 +1,55 @@
|
|
|
1
1
|
import { useEffect, useState } from 'react';
|
|
2
|
+
import { UCExecRes, UCExecState } from '../../../uc/index.js';
|
|
2
3
|
import { sleep } from '../../../utils/index.js';
|
|
3
4
|
export function useAction({ action, autoExec = false, confirm, onError, onInit, onStart, sleepInMs, }) {
|
|
4
5
|
const [errMsg, setErrMsg] = useState(null);
|
|
5
6
|
const [execRes, setExecRes] = useState(null);
|
|
6
|
-
const [execState, setExecState] = useState(onInit ?
|
|
7
|
+
const [execState, setExecState] = useState(onInit ? UCExecState.INITIALIZING : UCExecState.IDLE);
|
|
7
8
|
// biome-ignore lint/correctness/useExhaustiveDependencies : must run only once
|
|
8
9
|
useEffect(() => {
|
|
9
10
|
(async () => {
|
|
10
|
-
if (execState ===
|
|
11
|
+
if (execState === UCExecState.INITIALIZING) {
|
|
11
12
|
await onInit?.();
|
|
12
13
|
}
|
|
13
14
|
if (autoExec) {
|
|
14
15
|
await exec();
|
|
15
16
|
}
|
|
16
17
|
else {
|
|
17
|
-
setExecState(
|
|
18
|
+
setExecState(UCExecState.IDLE);
|
|
18
19
|
}
|
|
19
20
|
})();
|
|
20
21
|
}, []);
|
|
21
22
|
const exec = async () => {
|
|
22
23
|
setErrMsg(null);
|
|
23
24
|
setExecRes(null);
|
|
24
|
-
setExecState(
|
|
25
|
+
setExecState(UCExecState.SUBMITTING);
|
|
25
26
|
await onStart?.();
|
|
26
27
|
const confirmed = confirm ? await confirm?.() : true;
|
|
27
28
|
if (!confirmed) {
|
|
28
|
-
setExecState(
|
|
29
|
-
setExecRes(
|
|
30
|
-
return
|
|
29
|
+
setExecState(UCExecState.IDLE);
|
|
30
|
+
setExecRes(UCExecRes.ABORTED);
|
|
31
|
+
return UCExecRes.ABORTED;
|
|
31
32
|
}
|
|
32
33
|
if (sleepInMs !== undefined) {
|
|
33
34
|
await sleep(sleepInMs);
|
|
34
35
|
}
|
|
35
36
|
try {
|
|
36
37
|
await action();
|
|
37
|
-
setExecRes(
|
|
38
|
-
return
|
|
38
|
+
setExecRes(UCExecRes.SUCCEEDED);
|
|
39
|
+
return UCExecRes.SUCCEEDED;
|
|
39
40
|
}
|
|
40
41
|
catch (err) {
|
|
41
|
-
setExecRes(
|
|
42
|
+
setExecRes(UCExecRes.FAILED);
|
|
42
43
|
if (onError) {
|
|
43
44
|
await onError?.(err);
|
|
44
45
|
}
|
|
45
46
|
else {
|
|
46
47
|
setErrMsg(err.message);
|
|
47
48
|
}
|
|
48
|
-
return
|
|
49
|
+
return UCExecRes.FAILED;
|
|
49
50
|
}
|
|
50
51
|
finally {
|
|
51
|
-
setExecState(
|
|
52
|
+
setExecState(UCExecState.IDLE);
|
|
52
53
|
}
|
|
53
54
|
};
|
|
54
55
|
return { errMsg, exec, execRes, execState };
|
|
@@ -97,8 +97,9 @@ export function mountHandler(contract, express, handler) {
|
|
|
97
97
|
export function toFile(f) {
|
|
98
98
|
return {
|
|
99
99
|
name: f.name,
|
|
100
|
-
|
|
100
|
+
size: f.size,
|
|
101
101
|
type: f.mimetype,
|
|
102
|
+
uri: f.tempFilePath,
|
|
102
103
|
};
|
|
103
104
|
}
|
|
104
105
|
export function toReq(req) {
|
|
@@ -34,6 +34,7 @@ export interface HTMLInputDef {
|
|
|
34
34
|
* @see node_modules/@types/react/index.d.ts `InputHTMLAttributes`
|
|
35
35
|
*/
|
|
36
36
|
spec?: {
|
|
37
|
+
accept?: string | undefined;
|
|
37
38
|
'aria-errormessage'?: string | undefined;
|
|
38
39
|
'aria-invalid'?: boolean | undefined;
|
|
39
40
|
disabled?: boolean | undefined;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TBoolean, TNumber, TString, } from '../../../dt/index.js';
|
|
1
|
+
import { TBoolean, TFile, TNumber, TString, } from '../../../dt/index.js';
|
|
2
2
|
import { ucifHint, ucifId, ucifIsMandatory, } from '../../../uc/index.js';
|
|
3
3
|
export function htmlInputDef(field, disabled, errMsg) {
|
|
4
4
|
const def = {
|
|
@@ -34,6 +34,10 @@ export function htmlInputDef(field, disabled, errMsg) {
|
|
|
34
34
|
else if (fType instanceof TBoolean) {
|
|
35
35
|
def.internal.checked = fType.getInitialValue() === true;
|
|
36
36
|
}
|
|
37
|
+
else if (fType instanceof TFile) {
|
|
38
|
+
const constraints = fType.getFileConstraints();
|
|
39
|
+
def.spec.accept = constraints.accept.join(',');
|
|
40
|
+
}
|
|
37
41
|
if (!(fType instanceof TBoolean)) {
|
|
38
42
|
def.internal.value = fType.getInitialValue()?.toString() || '';
|
|
39
43
|
}
|
|
@@ -7,6 +7,7 @@ import { useStyleContext } from '../lib/react/StyleContextProvider.js';
|
|
|
7
7
|
import { UCFormFieldControl } from './UCFormFieldControl.js';
|
|
8
8
|
import { UCFormFieldDesc } from './UCFormFieldDesc.js';
|
|
9
9
|
import { UCFormFieldErr } from './UCFormFieldErr.js';
|
|
10
|
+
import { UCFormFieldHelp } from './UCFormFieldHelp.js';
|
|
10
11
|
import { UCFormFieldLabel } from './UCFormFieldLabel.js';
|
|
11
12
|
export function UCFormField({ disabled, execState, f, only, }) {
|
|
12
13
|
const { i18nManager } = useDIContext();
|
|
@@ -16,5 +17,5 @@ export function UCFormField({ disabled, execState, f, only, }) {
|
|
|
16
17
|
setErrMsg(validateFormField(i18nManager, f));
|
|
17
18
|
};
|
|
18
19
|
const elements = only ?? UC_FORM_FIELD_ELEMENTS;
|
|
19
|
-
return (_jsxs(View, { style: formField?.style, children: [elements.includes('label') && _jsx(UCFormFieldLabel, { f: f }), elements.includes('control') && (_jsx(UCFormFieldControl, { disabled: disabled, execState: execState, f: f, onChange: onChange })), elements.includes('
|
|
20
|
+
return (_jsxs(View, { style: formField?.style, children: [elements.includes('label') && _jsx(UCFormFieldLabel, { f: f }), elements.includes('control') && (_jsx(UCFormFieldControl, { disabled: disabled, execState: execState, f: f, onChange: onChange })), elements.includes('desc') && _jsx(UCFormFieldDesc, { f: f }), elements.includes('help') && _jsx(UCFormFieldHelp, { f: f }), elements.includes('err') && _jsx(UCFormFieldErr, { errMsg: errMsg })] }));
|
|
20
21
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useState } from 'react';
|
|
3
3
|
import { FlatList, Pressable, StyleSheet, Switch, Text, TextInput, } from 'react-native';
|
|
4
|
-
import { TBoolean } from '../../dt/index.js';
|
|
4
|
+
import { TBoolean, TFile } from '../../dt/index.js';
|
|
5
5
|
import { ucifRepeatability } from '../../uc/index.js';
|
|
6
6
|
import { isBlank } from '../../utils/index.js';
|
|
7
7
|
import { styleDef, useStyleContext, } from '../lib/react/StyleContextProvider.js';
|
|
@@ -11,7 +11,7 @@ const MULTIPLE_VALUES_SEPARATOR = ',';
|
|
|
11
11
|
export function UCFormFieldControl({ disabled, errMsg = null, execState, f, onChange: onChangeBase, }) {
|
|
12
12
|
const { colors, formFieldControl, renderFormFieldControl } = useStyleContext();
|
|
13
13
|
const [internalValue, setInternalValue] = useState(f.getValue());
|
|
14
|
-
// biome-ignore lint/correctness/useExhaustiveDependencies:
|
|
14
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: It is actually necessary because only `f` or `f.getValue` does not trigger the effect
|
|
15
15
|
useEffect(() => {
|
|
16
16
|
setInternalValue(f.getValue());
|
|
17
17
|
}, [f.getValue()]);
|
|
@@ -25,6 +25,10 @@ export function UCFormFieldControl({ disabled, errMsg = null, execState, f, onCh
|
|
|
25
25
|
if (component) {
|
|
26
26
|
return component;
|
|
27
27
|
}
|
|
28
|
+
const { type } = f.def;
|
|
29
|
+
if (type instanceof TFile) {
|
|
30
|
+
return (_jsx(Text, { style: { color: 'red' }, children: "Generic file picker not available in RN" }));
|
|
31
|
+
}
|
|
28
32
|
const onChangeText = (value) => {
|
|
29
33
|
const [isRepeatable] = ucifRepeatability(f.def);
|
|
30
34
|
if (isRepeatable && typeof value === 'string') {
|
|
@@ -58,7 +62,6 @@ export function UCFormFieldControl({ disabled, errMsg = null, execState, f, onCh
|
|
|
58
62
|
setInternalValue(value);
|
|
59
63
|
};
|
|
60
64
|
const attrs = rnInputDef(f, disabled, errMsg);
|
|
61
|
-
const { type } = f.def;
|
|
62
65
|
const options = type.getOptions();
|
|
63
66
|
if (options) {
|
|
64
67
|
// TODO : Handle type.hasStrictOptions() => display an input text alongside the options
|
|
@@ -72,7 +75,6 @@ export function UCFormFieldControl({ disabled, errMsg = null, execState, f, onCh
|
|
|
72
75
|
},
|
|
73
76
|
], children: _jsx(Text, { children: item.label }) })), showsHorizontalScrollIndicator: false, style: styles.select }));
|
|
74
77
|
}
|
|
75
|
-
// TODO : Implement picker for TFile (requires a dependency...)
|
|
76
78
|
if (type instanceof TBoolean) {
|
|
77
79
|
const { style } = styleDef(formFieldControl, 'Switch');
|
|
78
80
|
return (_jsx(Switch, { disabled: !attrs.spec?.editable, onValueChange: onValueChange, style: style, trackColor: { true: colors?.primary }, value: internalValue }));
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { ReactElement } from 'react';
|
|
2
2
|
import type { UCFormFieldErrProps } from '../lib/react/form.js';
|
|
3
|
-
export declare function UCFormFieldErr({ errMsg }: UCFormFieldErrProps): ReactElement;
|
|
3
|
+
export declare function UCFormFieldErr({ errMsg, }: UCFormFieldErrProps): ReactElement | null;
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { Text } from 'react-native';
|
|
3
3
|
import { useStyleContext } from '../lib/react/StyleContextProvider.js';
|
|
4
|
-
export function UCFormFieldErr({ errMsg }) {
|
|
4
|
+
export function UCFormFieldErr({ errMsg, }) {
|
|
5
5
|
const { formFieldErr } = useStyleContext();
|
|
6
|
+
if (!errMsg) {
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
6
9
|
return _jsx(Text, { style: formFieldErr?.style, children: errMsg });
|
|
7
10
|
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ReactElement } from 'react';
|
|
2
|
+
import type { DataType } from '../../dt/index.js';
|
|
3
|
+
import type { UCFormFieldDescProps } from '../lib/react/form.js';
|
|
4
|
+
export declare function UCFormFieldHelp<T extends DataType>({ f, }: UCFormFieldDescProps<T>): ReactElement | null;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Text } from 'react-native';
|
|
3
|
+
import { useDIContext } from '../../index.react.js';
|
|
4
|
+
import { useStyleContext } from '../lib/react/StyleContextProvider.js';
|
|
5
|
+
export function UCFormFieldHelp({ f, }) {
|
|
6
|
+
const { wordingManager } = useDIContext();
|
|
7
|
+
const { formFieldHelp } = useStyleContext();
|
|
8
|
+
const { def: { type }, } = f;
|
|
9
|
+
const parts = wordingManager.dtConstr(type);
|
|
10
|
+
if (!parts) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
const text = parts.join(' - ');
|
|
14
|
+
return _jsx(Text, { style: formFieldHelp?.style, children: text });
|
|
15
|
+
}
|
|
@@ -6,6 +6,7 @@ import { useStyleContext } from '../lib/react/StyleContextProvider.js';
|
|
|
6
6
|
import { UCFormFieldControl } from './UCFormFieldControl.js';
|
|
7
7
|
import { UCFormFieldDesc } from './UCFormFieldDesc.js';
|
|
8
8
|
import { UCFormFieldErr } from './UCFormFieldErr.js';
|
|
9
|
+
import { UCFormFieldHelp } from './UCFormFieldHelp.js';
|
|
9
10
|
import { UCFormFieldLabel } from './UCFormFieldLabel.js';
|
|
10
11
|
export function UCFormField({ disabled, execState, f, only, }) {
|
|
11
12
|
const { i18nManager } = useDIContext();
|
|
@@ -15,5 +16,5 @@ export function UCFormField({ disabled, execState, f, only, }) {
|
|
|
15
16
|
setErrMsg(validateFormField(i18nManager, f));
|
|
16
17
|
};
|
|
17
18
|
const elements = only ?? UC_FORM_FIELD_ELEMENTS;
|
|
18
|
-
return (_jsxs("div", { className: formField?.className, style: formField?.style, children: [elements.includes('label') && _jsx(UCFormFieldLabel, { f: f }), elements.includes('control') && (_jsx(UCFormFieldControl, { disabled: disabled, execState: execState, f: f, onChange: onChange })), elements.includes('
|
|
19
|
+
return (_jsxs("div", { className: formField?.className, style: formField?.style, children: [elements.includes('label') && _jsx(UCFormFieldLabel, { f: f }), elements.includes('control') && (_jsx(UCFormFieldControl, { disabled: disabled, execState: execState, f: f, onChange: onChange })), elements.includes('desc') && _jsx(UCFormFieldDesc, { f: f }), elements.includes('help') && _jsx(UCFormFieldHelp, { f: f }), elements.includes('err') && _jsx(UCFormFieldErr, { errMsg: errMsg })] }));
|
|
19
20
|
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { ReactElement } from 'react';
|
|
2
2
|
import type { UCFormFieldErrProps } from '../lib/react/form.js';
|
|
3
|
-
export declare function UCFormFieldErr({ errMsg }: UCFormFieldErrProps): ReactElement;
|
|
3
|
+
export declare function UCFormFieldErr({ errMsg, }: UCFormFieldErrProps): ReactElement | null;
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useStyleContext } from '../lib/react/StyleContextProvider.js';
|
|
3
|
-
export function UCFormFieldErr({ errMsg }) {
|
|
3
|
+
export function UCFormFieldErr({ errMsg, }) {
|
|
4
4
|
const { formFieldErr } = useStyleContext();
|
|
5
|
+
if (!errMsg) {
|
|
6
|
+
return null;
|
|
7
|
+
}
|
|
5
8
|
return (_jsx("div", { className: formFieldErr?.className, style: formFieldErr?.style, children: errMsg }));
|
|
6
9
|
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ReactElement } from 'react';
|
|
2
|
+
import type { DataType } from '../../dt/index.js';
|
|
3
|
+
import type { UCFormFieldDescProps } from '../lib/react/form.js';
|
|
4
|
+
export declare function UCFormFieldHelp<T extends DataType>({ f, }: UCFormFieldDescProps<T>): ReactElement | null;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useDIContext } from '../../index.react.js';
|
|
3
|
+
import { useStyleContext } from '../lib/react/StyleContextProvider.js';
|
|
4
|
+
export function UCFormFieldHelp({ f, }) {
|
|
5
|
+
const { wordingManager } = useDIContext();
|
|
6
|
+
const { formFieldHelp } = useStyleContext();
|
|
7
|
+
const { def: { type }, } = f;
|
|
8
|
+
const parts = wordingManager.dtConstr(type);
|
|
9
|
+
if (!parts) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
const text = parts.join(' - ');
|
|
13
|
+
return (_jsx("div", { className: formFieldHelp?.className, style: formFieldHelp?.style, children: text }));
|
|
14
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { FSManager } from '../../../std/index.js';
|
|
2
|
+
import type { AppDocsEmitter, Input, Output } from '../../workers/AppDocsEmitter.js';
|
|
3
|
+
export declare class SimpleAppDocsEmitter implements AppDocsEmitter {
|
|
4
|
+
private fsManager;
|
|
5
|
+
constructor(fsManager: FSManager);
|
|
6
|
+
exec({ appPath, ucDefSourcesCheckerOutput, }: Input): Promise<Output>;
|
|
7
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
11
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
|
+
};
|
|
13
|
+
import { inject, injectable } from 'inversify';
|
|
14
|
+
import { APP_DOCS_FILE_NAME } from '../../../convention.js';
|
|
15
|
+
import { techSummary } from './tech-summary.js';
|
|
16
|
+
import { ucSummary } from './uc-summary.js';
|
|
17
|
+
let SimpleAppDocsEmitter = class SimpleAppDocsEmitter {
|
|
18
|
+
fsManager;
|
|
19
|
+
constructor(fsManager) {
|
|
20
|
+
this.fsManager = fsManager;
|
|
21
|
+
}
|
|
22
|
+
async exec({ appPath, ucDefSourcesCheckerOutput, }) {
|
|
23
|
+
const outPath = this.fsManager.path(appPath, APP_DOCS_FILE_NAME);
|
|
24
|
+
const tpl = template(ucDefSourcesCheckerOutput.items);
|
|
25
|
+
await this.fsManager.touch(outPath, tpl);
|
|
26
|
+
return {
|
|
27
|
+
outPath,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
SimpleAppDocsEmitter = __decorate([
|
|
32
|
+
injectable(),
|
|
33
|
+
__param(0, inject('FSManager')),
|
|
34
|
+
__metadata("design:paramtypes", [Object])
|
|
35
|
+
], SimpleAppDocsEmitter);
|
|
36
|
+
export { SimpleAppDocsEmitter };
|
|
37
|
+
// For now, we can have it here. When it becomes harder to maintain, we can introduce some kind of template engine.
|
|
38
|
+
// Be aware that this will introduce complexities on building the lib.
|
|
39
|
+
// We'll need to include these templates in the build and make them accessible via package.json "exports" or any other mechanism.
|
|
40
|
+
// Hence the choice to keep it simple for now.
|
|
41
|
+
// Defined it as function in case we need to pass args.
|
|
42
|
+
// Using --- for the comment to make it compatible with pandoc
|
|
43
|
+
// See https://stackoverflow.com/a/4829998/1259118
|
|
44
|
+
const template = (items) => `<!---
|
|
45
|
+
All this code has been auto generated.
|
|
46
|
+
DO NOT EDIT.
|
|
47
|
+
Or be prepared to see all your changes erased at the next generation.
|
|
48
|
+
-->
|
|
49
|
+
|
|
50
|
+
# App
|
|
51
|
+
|
|
52
|
+
## Use Cases
|
|
53
|
+
|
|
54
|
+
${items.map(ucSummary).join('\n\n')}
|
|
55
|
+
|
|
56
|
+
## Technical Summary
|
|
57
|
+
|
|
58
|
+
${techSummary(items)}
|
|
59
|
+
`;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { UC_MAIN_STEP_PREFIX_REGULAR } from '../../../convention.js';
|
|
2
|
+
const CHECK_POLICY = '🔐 Check policy';
|
|
3
|
+
const CHECK_POLICY_COND = 'when any validation fails';
|
|
4
|
+
const CHECK_POLICY_COND_ACTION = 'show failure';
|
|
5
|
+
const CLIENT_CONFIRM_N_COND = 'when does not confirm';
|
|
6
|
+
const CLIENT_CONFIRM_N_COND_ACTION = 'stop everything';
|
|
7
|
+
const CLIENT_CONFIRM_Q = '❓ Sure';
|
|
8
|
+
const CLIENT_CONFIRM_Y = 'Yes';
|
|
9
|
+
const FILL = '✏️ Fill';
|
|
10
|
+
const LB = '<br/>';
|
|
11
|
+
const OK = '👍 OK';
|
|
12
|
+
const SEND = '📤 Send';
|
|
13
|
+
const SUBMIT = '↩️ Submit';
|
|
14
|
+
const TRIGGER = '⤴️ Trigger';
|
|
15
|
+
export function ucSequenceDiagram(item) {
|
|
16
|
+
// Debugger : https://mermaid.live/edit
|
|
17
|
+
// Messages : https://mermaid.js.org/syntax/sequenceDiagram.html#messages
|
|
18
|
+
const client = 'Client';
|
|
19
|
+
const server = 'Server';
|
|
20
|
+
const user = 'User';
|
|
21
|
+
const lines = [`actor ${user}`];
|
|
22
|
+
const { ioIFields, ioOPI0Fields, ioOPI1Fields, lifecycleClientPolicy, lifecycleClientSteps, lifecycleServerPolicy, lifecycleServerSteps, metadataSensitive, } = item;
|
|
23
|
+
let req = TRIGGER;
|
|
24
|
+
if (ioIFields && ioIFields.length > 0) {
|
|
25
|
+
// TODO : Include only fields to fill manually ?
|
|
26
|
+
// Not sure though, as for CLI for example (i.e. noContext), one needs to provide all of them
|
|
27
|
+
req = `${FILL}${LB}${fields(item.ioIFields)}`;
|
|
28
|
+
}
|
|
29
|
+
lines.push(`${user}->>+${client}: ${req}`);
|
|
30
|
+
lines.push(`${user}->>${client}: ${SUBMIT}`);
|
|
31
|
+
if (metadataSensitive?.value) {
|
|
32
|
+
lines.push(...clientConfirm(client, user));
|
|
33
|
+
}
|
|
34
|
+
if (lifecycleClientPolicy) {
|
|
35
|
+
lines.push(...policy(client, user, lifecycleClientPolicy));
|
|
36
|
+
}
|
|
37
|
+
if (lifecycleClientSteps) {
|
|
38
|
+
lines.push(...mainSteps(client, lifecycleClientSteps));
|
|
39
|
+
}
|
|
40
|
+
// This is an approximation. Might need to improve it.
|
|
41
|
+
const hasServer = item.lifecycleServerPolicy?.value;
|
|
42
|
+
if (hasServer) {
|
|
43
|
+
req = SEND;
|
|
44
|
+
if (ioIFields && ioIFields.length > 0) {
|
|
45
|
+
req = `${req}${LB}${fields(item.ioIFields)}`;
|
|
46
|
+
}
|
|
47
|
+
lines.push(`${client}->>+${server}: ${req}`);
|
|
48
|
+
if (lifecycleServerPolicy) {
|
|
49
|
+
lines.push(...policy(server, user, lifecycleServerPolicy));
|
|
50
|
+
}
|
|
51
|
+
if (lifecycleServerSteps) {
|
|
52
|
+
lines.push(...mainSteps(server, lifecycleServerSteps));
|
|
53
|
+
}
|
|
54
|
+
let res = '';
|
|
55
|
+
if (ioOPI0Fields && ioOPI0Fields.length > 0) {
|
|
56
|
+
res += `${res}${LB}${fields(item.ioOPI0Fields)}`;
|
|
57
|
+
}
|
|
58
|
+
if (ioOPI1Fields && ioOPI1Fields?.length > 0) {
|
|
59
|
+
res += `${res}${LB}${fields(item.ioOPI1Fields)}`;
|
|
60
|
+
}
|
|
61
|
+
lines.push(`${server}-->>-${client}: ${OK}${res}`);
|
|
62
|
+
}
|
|
63
|
+
lines.push(`${client}-->>-${user}: ${OK}`);
|
|
64
|
+
return `\`\`\`mermaid
|
|
65
|
+
sequenceDiagram
|
|
66
|
+
${lines.join('\n ')}
|
|
67
|
+
\`\`\``;
|
|
68
|
+
}
|
|
69
|
+
function clientConfirm(participant, caller) {
|
|
70
|
+
return [
|
|
71
|
+
`${participant}->>${caller}: ${CLIENT_CONFIRM_Q}`,
|
|
72
|
+
`${caller}->>${participant}: ${CLIENT_CONFIRM_Y}`,
|
|
73
|
+
`break ${CLIENT_CONFIRM_N_COND}`,
|
|
74
|
+
` ${participant}-->${caller}: ${CLIENT_CONFIRM_N_COND_ACTION}`,
|
|
75
|
+
'end',
|
|
76
|
+
];
|
|
77
|
+
}
|
|
78
|
+
function fields(fields) {
|
|
79
|
+
return (fields?.map((f) => `${f.value.name}: ${f.value.dataType}`).join(LB) ||
|
|
80
|
+
'');
|
|
81
|
+
}
|
|
82
|
+
function mainSteps(participant, field) {
|
|
83
|
+
return field.map((f) => `${participant}->>${participant}: ${f.value.replace(UC_MAIN_STEP_PREFIX_REGULAR, '').trim()}`);
|
|
84
|
+
}
|
|
85
|
+
function policy(participant, caller, lifecyclePolicyField) {
|
|
86
|
+
return [
|
|
87
|
+
`${participant}->>${participant}: ${CHECK_POLICY} "${lifecyclePolicyField.value}"`,
|
|
88
|
+
`break ${CHECK_POLICY_COND}`,
|
|
89
|
+
` ${participant}-->${caller}: ${CHECK_POLICY_COND_ACTION}`,
|
|
90
|
+
'end',
|
|
91
|
+
];
|
|
92
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { OUTPUT_ITEM_FIELDS, } from '../../UCDefASTParser.js';
|
|
2
|
+
import { thead } from './markdown.js';
|
|
3
|
+
export function techSummary(items) {
|
|
4
|
+
return `${thead(OUTPUT_ITEM_FIELDS)}
|
|
5
|
+
${items
|
|
6
|
+
.map((item, idx) => ['', idx + 1, ...OUTPUT_ITEM_FIELDS.map((f) => val(item[f])), ''].join('|'))
|
|
7
|
+
.join('\n')}`;
|
|
8
|
+
}
|
|
9
|
+
function val(value) {
|
|
10
|
+
if (!value) {
|
|
11
|
+
return '';
|
|
12
|
+
}
|
|
13
|
+
const values = Array.isArray(value) ? value : [value];
|
|
14
|
+
// NOTE : <br> won't work for every markdown renderer.
|
|
15
|
+
// See https://stackoverflow.com/questions/11700487/how-do-i-add-a-newline-in-a-markdown-table
|
|
16
|
+
return values.map(fmtVal).join('<br>');
|
|
17
|
+
}
|
|
18
|
+
function fmtVal(field) {
|
|
19
|
+
const { err, value } = field;
|
|
20
|
+
let res = (typeof value === 'string' ? value : value.raw) ?? '';
|
|
21
|
+
if (err) {
|
|
22
|
+
res += `❌ ${err}`;
|
|
23
|
+
}
|
|
24
|
+
res = res.replace(/[\u00A0-\u9999<>&]/g, (i) => `&#${i.charCodeAt(0)};`); // TS generics considered as HTML
|
|
25
|
+
res = res.replaceAll('|', '\\|'); // TS intersection vs Markdown table column
|
|
26
|
+
return res;
|
|
27
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { humanize } from '../../../utils/index.js';
|
|
2
|
+
import { pre, thead } from './markdown.js';
|
|
3
|
+
import { ucSequenceDiagram } from './sequence-diagram.js';
|
|
4
|
+
export function ucSummary(item) {
|
|
5
|
+
return `### ${item.metadataName?.value}
|
|
6
|
+
|
|
7
|
+
${lifecycle(item)}
|
|
8
|
+
|
|
9
|
+
${fields(item)}
|
|
10
|
+
|
|
11
|
+
#### Sequence Diagram
|
|
12
|
+
|
|
13
|
+
${ucSequenceDiagram(item)}`;
|
|
14
|
+
}
|
|
15
|
+
const UC_FIELDS_TABLES_COLS = ['name', 'humanized', 'dataType'];
|
|
16
|
+
function fields(item) {
|
|
17
|
+
const { ioIFields, ioOPI0Fields, ioOPI1Fields } = item;
|
|
18
|
+
return `#### Input (I)
|
|
19
|
+
|
|
20
|
+
${ucFieldsTable(ioIFields)}
|
|
21
|
+
|
|
22
|
+
#### Output (O)
|
|
23
|
+
|
|
24
|
+
##### Part 0 (OPI0)
|
|
25
|
+
|
|
26
|
+
${ucFieldsTable(ioOPI0Fields)}
|
|
27
|
+
|
|
28
|
+
##### Part 1 (OPI1)
|
|
29
|
+
|
|
30
|
+
${ucFieldsTable(ioOPI1Fields)}`;
|
|
31
|
+
}
|
|
32
|
+
function ucFieldsTable(fields) {
|
|
33
|
+
if (!fields || fields.length === 0) {
|
|
34
|
+
return 'None';
|
|
35
|
+
}
|
|
36
|
+
return `${thead(UC_FIELDS_TABLES_COLS)}
|
|
37
|
+
${fields
|
|
38
|
+
?.map(({ value: { dataType, name } }, idx) => [
|
|
39
|
+
'',
|
|
40
|
+
idx + 1,
|
|
41
|
+
pre(name),
|
|
42
|
+
name ? humanize(name) : '',
|
|
43
|
+
pre(dataType),
|
|
44
|
+
'',
|
|
45
|
+
].join('|'))
|
|
46
|
+
.join('\n')}`;
|
|
47
|
+
}
|
|
48
|
+
function lifecycle(item) {
|
|
49
|
+
const { lifecycleClientPolicy, lifecycleServerPolicy } = item;
|
|
50
|
+
return `- **Type** : ${pre(lifecycleType(item))}
|
|
51
|
+
- **Client Policy** : ${pre(lifecycleClientPolicy?.value)}
|
|
52
|
+
- **Server Policy** : ${pre(lifecycleServerPolicy?.value)}`;
|
|
53
|
+
}
|
|
54
|
+
function lifecycleType(item) {
|
|
55
|
+
const { lifecycleClientPolicy, lifecycleServerPolicy } = item;
|
|
56
|
+
if (lifecycleClientPolicy && lifecycleServerPolicy) {
|
|
57
|
+
return 'Client / Server';
|
|
58
|
+
}
|
|
59
|
+
if (lifecycleClientPolicy) {
|
|
60
|
+
return 'Client only';
|
|
61
|
+
}
|
|
62
|
+
return 'Server only';
|
|
63
|
+
}
|
|
@@ -10,7 +10,7 @@ import { bindNodeCore } from '../../utils/ioc/bindNodeCore.js';
|
|
|
10
10
|
import { bindServer } from '../../utils/ioc/bindServer.js';
|
|
11
11
|
import { AppTester } from '../AppTester.js';
|
|
12
12
|
import { optsAllSet } from '../opts.js';
|
|
13
|
-
import { SimpleAppDocsEmitter } from './SimpleAppDocsEmitter.js';
|
|
13
|
+
import { SimpleAppDocsEmitter } from './SimpleAppDocsEmitter/SimpleAppDocsEmitter.js';
|
|
14
14
|
import { TypeScriptLibUCDefASTParser } from './TypeScriptLibUCDefASTParser.js';
|
|
15
15
|
export async function newNodeAppTester(serverPortRangeStart, idx, args) {
|
|
16
16
|
const { configurator } = args;
|