libmodulor 0.4.0 → 0.5.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 +18 -1
- package/README.md +3 -3
- package/dist/esm/app/workers/AppSrcFilePathBuilder.d.ts +16 -0
- package/dist/esm/app/workers/AppSrcFilePathBuilder.js +6 -4
- package/dist/esm/apps/Helper/index.js +1 -0
- package/dist/esm/apps/Helper/src/ucds/GenerateAppsTestsUCD.js +3 -2
- package/dist/esm/bundlers/vite/StripUCDLifecycleServerPlugin.js +3 -0
- package/dist/esm/convention.d.ts +1 -0
- package/dist/esm/convention.js +17 -4
- package/dist/esm/dt/Validation.d.ts +8 -0
- package/dist/esm/dt/Validation.js +8 -0
- package/dist/esm/dt/base/TBase.d.ts +2 -1
- package/dist/esm/dt/base/TBoolean.js +2 -0
- package/dist/esm/dt/base/TInt.js +3 -0
- package/dist/esm/dt/base/TNumber.js +2 -0
- package/dist/esm/dt/base/TObject.d.ts +15 -0
- package/dist/esm/dt/base/TObject.js +14 -0
- package/dist/esm/dt/base/TString.js +1 -1
- package/dist/esm/dt/final/TAmount.js +1 -0
- package/dist/esm/dt/final/TCountryISO3166Alpha2.js +1 -0
- package/dist/esm/dt/final/TCurrencyISO4217.js +1 -0
- package/dist/esm/dt/final/TDateTimeFormat.js +1 -0
- package/dist/esm/dt/final/TEmail.js +2 -0
- package/dist/esm/dt/final/TEmoji.js +4 -0
- package/dist/esm/dt/final/TFile.js +3 -0
- package/dist/esm/dt/final/THostAddress.js +2 -0
- package/dist/esm/dt/final/TIPv6.js +1 -0
- package/dist/esm/dt/final/TJWT.js +8 -0
- package/dist/esm/dt/final/TPercentage.js +5 -0
- package/dist/esm/dt/final/TSQLQuery.js +1 -0
- package/dist/esm/dt/final/TSSHPrivateKey.js +3 -1
- package/dist/esm/dt/final/TSemVerVersion.js +1 -0
- package/dist/esm/dt/final/TShellCommand.js +1 -0
- package/dist/esm/dt/final/TURL.js +2 -0
- package/dist/esm/dt/final/TUUID.js +1 -0
- package/dist/esm/dt/final/TYesNo.js +1 -1
- package/dist/esm/i18n/WordingManager.d.ts +16 -0
- package/dist/esm/i18n/types.d.ts +5 -0
- package/dist/esm/icon/Icon.d.ts +7 -0
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/index.js +4 -0
- package/dist/esm/product/manifest.d.ts +15 -0
- package/dist/esm/products/Helper/index.js +3 -0
- package/dist/esm/products/Helper/manifest.d.ts +6 -1
- package/dist/esm/std/BufferManager.d.ts +18 -0
- package/dist/esm/std/ClockManager.d.ts +5 -0
- package/dist/esm/std/EnvironmentManager.d.ts +10 -0
- package/dist/esm/std/HTTPAPICaller.d.ts +6 -0
- package/dist/esm/std/I18nManager.d.ts +26 -0
- package/dist/esm/std/JWTManager.d.ts +26 -0
- package/dist/esm/std/JobManager.d.ts +6 -0
- package/dist/esm/std/LLMManager.d.ts +25 -0
- package/dist/esm/std/LLMManager.js +1 -0
- package/dist/esm/std/PromptManager.d.ts +8 -0
- package/dist/esm/std/SettingsManager.d.ts +19 -0
- package/dist/esm/std/SettingsManager.js +9 -0
- package/dist/esm/std/impl/ConsoleLogger.js +7 -1
- package/dist/esm/std/impl/FakeEmailManager.js +1 -0
- package/dist/esm/std/impl/FakeJobManager.js +1 -0
- package/dist/esm/std/impl/FetchHTTPAPICallExecutor.d.ts +9 -0
- package/dist/esm/std/impl/FetchHTTPAPICallExecutor.js +11 -0
- package/dist/esm/std/impl/MistralAILLMManager.d.ts +17 -0
- package/dist/esm/std/impl/MistralAILLMManager.js +56 -0
- package/dist/esm/std/impl/NodeCryptoManager.js +6 -1
- package/dist/esm/std/impl/NodeDeterministicCryptoManager.d.ts +14 -0
- package/dist/esm/std/impl/NodeDeterministicCryptoManager.js +17 -3
- package/dist/esm/std/impl/NodeFSManager.js +10 -0
- package/dist/esm/std/impl/NodeHTTPAPICallExecutorAgentBuilder.js +2 -0
- package/dist/esm/std/impl/NodePromptManager.js +3 -0
- package/dist/esm/std/impl/OllamaLLMManager.d.ts +20 -0
- package/dist/esm/std/impl/OllamaLLMManager.js +56 -0
- package/dist/esm/std/impl/OpenAILLMManager.d.ts +17 -0
- package/dist/esm/std/impl/OpenAILLMManager.js +51 -0
- package/dist/esm/std/impl/SimpleHTTPAPICaller.js +14 -0
- package/dist/esm/std/impl/SimpleMapI18nManager.js +4 -2
- package/dist/esm/std/impl/StdDateClockManager.js +3 -0
- package/dist/esm/std/impl/UCDataStoreExternalResourceManager.js +3 -0
- package/dist/esm/std/impl/WebCryptoManager.js +9 -0
- package/dist/esm/std/index.d.ts +1 -0
- package/dist/esm/std/index.js +1 -0
- package/dist/esm/target/lib/cli/renderer.js +3 -0
- package/dist/esm/target/lib/client/consts.d.ts +3 -0
- package/dist/esm/target/lib/client/consts.js +3 -0
- package/dist/esm/target/lib/mcp-server/MCPServerBooter.js +1 -0
- package/dist/esm/target/lib/react/UCContainer.js +1 -0
- package/dist/esm/target/lib/react/UCPanel.js +4 -0
- package/dist/esm/target/lib/react/useUC.d.ts +8 -0
- package/dist/esm/target/lib/react/useUC.js +22 -0
- package/dist/esm/target/lib/react/useUCOR.d.ts +15 -0
- package/dist/esm/target/lib/react/useUCOR.js +45 -0
- package/dist/esm/target/lib/rn/input.d.ts +7 -0
- package/dist/esm/target/lib/rn/input.js +2 -0
- package/dist/esm/target/lib/server/AuthenticationChecker.js +2 -1
- package/dist/esm/target/lib/server/BasicAuthenticationChecker.js +1 -0
- package/dist/esm/target/lib/server/CSPDirectivesBuilder.js +13 -0
- package/dist/esm/target/lib/server/CustomerFacingErrorBuilder.js +3 -0
- package/dist/esm/target/lib/server/PrivateApiKeyAuthenticationChecker.js +1 -0
- package/dist/esm/target/lib/server/PublicApiKeyChecker.js +1 -1
- package/dist/esm/target/lib/server/RequestChecker.js +5 -4
- package/dist/esm/target/lib/server/RequestHandler.d.ts +5 -0
- package/dist/esm/target/lib/server/RequestLogger.js +5 -0
- package/dist/esm/target/lib/server/ServerManager.d.ts +19 -0
- package/dist/esm/target/lib/server/consts.d.ts +3 -0
- package/dist/esm/target/lib/server/consts.js +3 -0
- package/dist/esm/target/lib/web/input.d.ts +21 -0
- package/dist/esm/target/lib/web/input.js +4 -0
- package/dist/esm/target/node-core-cli/NodeCoreCLIManager.js +2 -2
- package/dist/esm/target/node-express-server/NodeExpressServerManager.js +5 -0
- package/dist/esm/target/node-express-server/lib/AuthCookieCreator.js +1 -1
- package/dist/esm/target/node-express-server/middlewares/AuthenticationCheckerMiddlewareBuilder.js +1 -0
- package/dist/esm/target/node-express-server/middlewares/PublicApiKeyCheckerMiddlewareBuilder.js +1 -0
- package/dist/esm/target/node-express-server/middlewares/RequestCheckerMiddlewareBuilder.js +1 -0
- package/dist/esm/target/node-express-server/middlewares/RequestHandlerMiddlewareBuilder.js +8 -0
- package/dist/esm/target/node-express-server/middlewares/RequestLoggerMiddlewareBuilder.js +1 -0
- package/dist/esm/target/node-mcp-server/NodeLocalStdioMCPServerManager.d.ts +10 -0
- package/dist/esm/target/node-mcp-server/NodeLocalStdioMCPServerManager.js +14 -0
- package/dist/esm/target/react-native-pure/UCFormFieldControl.js +1 -0
- package/dist/esm/testing/AppTester.d.ts +4 -0
- package/dist/esm/testing/AppTester.js +16 -0
- package/dist/esm/testing/AppTesterConfigurator.d.ts +68 -0
- package/dist/esm/testing/UCDataStoreTester.d.ts +9 -0
- package/dist/esm/testing/UCDataStoreTester.js +13 -0
- package/dist/esm/testing/impl/SimpleAppDocsEmitter.js +22 -2
- package/dist/esm/testing/impl/SimpleAppTesterConfigurator.js +1 -0
- package/dist/esm/testing/impl/SimpleHTMLAppTestReportEmitter.js +9 -3
- package/dist/esm/testing/impl/TypeScriptLibUCDefASTParser.js +12 -4
- package/dist/esm/testing/impl/VitestAppTestSuiteEmitter.js +6 -0
- package/dist/esm/testing/opts.d.ts +38 -0
- package/dist/esm/testing/opts.js +1 -1
- package/dist/esm/testing/uc-input.js +2 -0
- package/dist/esm/testing/workers/AppTesterCtxInitializer.js +7 -0
- package/dist/esm/testing/workers/UCExecutor.js +1 -0
- package/dist/esm/testing/workers/checkers/AppIndexChecker.js +1 -0
- package/dist/esm/testing/workers/checkers/UCDefSourcesChecker.js +4 -0
- package/dist/esm/uc/UC.js +19 -1
- package/dist/esm/uc/UCInputField.d.ts +28 -0
- package/dist/esm/uc/UCInputField.js +42 -0
- package/dist/esm/uc/data.d.ts +3 -0
- package/dist/esm/uc/def.d.ts +7 -0
- package/dist/esm/uc/exec.d.ts +39 -0
- package/dist/esm/uc/exec.js +29 -0
- package/dist/esm/uc/ext.d.ts +30 -1
- package/dist/esm/uc/helpers/UCOutputBuilder.js +5 -0
- package/dist/esm/uc/helpers/UCOutputReader.js +3 -1
- package/dist/esm/uc/impl/HTTPUCTransporter.js +4 -0
- package/dist/esm/uc/impl/InMemoryUCDataStore.js +7 -0
- package/dist/esm/uc/impl/KnexUCDataStore.d.ts +4 -0
- package/dist/esm/uc/impl/KnexUCDataStore.js +14 -0
- package/dist/esm/uc/impl/SimpleUCManager.js +6 -0
- package/dist/esm/uc/input-field.d.ts +60 -0
- package/dist/esm/uc/input-field.js +33 -0
- package/dist/esm/uc/input.d.ts +24 -0
- package/dist/esm/uc/lifecycle/client/IdleClientMain.js +1 -0
- package/dist/esm/uc/lifecycle/server/IdleServerMain.js +2 -0
- package/dist/esm/uc/manager.d.ts +11 -0
- package/dist/esm/uc/metadata.d.ts +10 -0
- package/dist/esm/uc/opi-layout.d.ts +3 -0
- package/dist/esm/uc/opi.d.ts +8 -0
- package/dist/esm/uc/output-field.d.ts +9 -0
- package/dist/esm/uc/output-part.d.ts +22 -0
- package/dist/esm/uc/output.d.ts +3 -0
- package/dist/esm/uc/policies/RoleRegularUCPolicy.js +1 -0
- package/dist/esm/uc/policies/funcs.js +1 -0
- package/dist/esm/uc/policy.d.ts +22 -0
- package/dist/esm/uc/sec.d.ts +9 -0
- package/dist/esm/uc/server.d.ts +10 -0
- package/dist/esm/uc/settings.d.ts +25 -0
- package/dist/esm/uc/side-effect.d.ts +16 -0
- package/dist/esm/uc/side-effect.js +16 -0
- package/dist/esm/uc/utils/rInput.d.ts +12 -0
- package/dist/esm/uc/utils/rInput.js +2 -0
- package/dist/esm/uc/utils/rVal.d.ts +25 -0
- package/dist/esm/uc/utils/rVal.js +27 -0
- package/dist/esm/uc/utils/recIs.d.ts +9 -0
- package/dist/esm/uc/utils/recIs.js +12 -1
- package/dist/esm/uc/utils/stripUCDLifecycleServer.d.ts +13 -0
- package/dist/esm/uc/utils/stripUCDLifecycleServer.js +17 -0
- package/dist/esm/uc/utils/ucifcoIsForArray.d.ts +6 -0
- package/dist/esm/uc/utils/ucifcoIsForArray.js +6 -0
- package/dist/esm/uc/workers/SimpleAggregateFinder.d.ts +12 -0
- package/dist/esm/uc/workers/SimpleAggregateFinder.js +12 -0
- package/dist/esm/uc/workers/UCBuilder.d.ts +7 -0
- package/dist/esm/uc/workers/UCBuilder.js +7 -0
- package/dist/esm/uc/workers/UCExecChecker.js +2 -0
- package/dist/esm/uc/workers/UCInputFilesProcessor.js +10 -4
- package/dist/esm/uc/workers/UCOutputFilesProcessor.js +6 -2
- package/dist/esm/utils/async/sleep.d.ts +10 -0
- package/dist/esm/utils/async/sleep.js +10 -0
- package/dist/esm/utils/http/appendData.js +5 -1
- package/dist/esm/utils/ioc/ContainerPrinter.js +2 -0
- package/dist/esm/utils/ioc/bindCommon.js +4 -0
- package/dist/esm/utils/ioc/bindNodeCLI.js +2 -0
- package/dist/esm/utils/ioc/bindNodeCore.js +1 -0
- package/dist/esm/utils/ioc/bindProduct.js +2 -0
- package/dist/esm/utils/ioc/bindRN.js +1 -0
- package/dist/esm/utils/ioc/bindServer.js +1 -0
- package/dist/esm/utils/ioc/bindWeb.js +2 -0
- package/dist/esm/utils/ioc/container.js +6 -0
- package/dist/esm/utils/numbers/units.js +3 -0
- package/dist/esm/utils/types/funcs.d.ts +35 -0
- package/dist/esm/utils/types/funcs.js +35 -0
- package/dist/esm/utils/types/utility-types.d.ts +17 -0
- package/dist/esm/utils/types/utility-types.js +1 -0
- package/package.json +9 -9
package/dist/esm/uc/ext.d.ts
CHANGED
|
@@ -5,12 +5,41 @@ import type { UCMountingPoint } from './utils/ucMountingPoint.js';
|
|
|
5
5
|
export type UCHTTPMountingPoint = `/${URLPath}`;
|
|
6
6
|
export interface UCExt<OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined> {
|
|
7
7
|
cmd?: {
|
|
8
|
+
/**
|
|
9
|
+
* The command on which the use case is mounted at
|
|
10
|
+
*
|
|
11
|
+
* By default, it's mounted at `${fqucn}`.
|
|
12
|
+
*/
|
|
8
13
|
mountAt?: UCMountingPoint;
|
|
9
14
|
};
|
|
10
15
|
http?: {
|
|
16
|
+
/**
|
|
17
|
+
* The verb on which the use case is mounted at
|
|
18
|
+
*
|
|
19
|
+
* By default, it's computed from the {@link UCMetadata.action} with some specific heuristics.
|
|
20
|
+
*
|
|
21
|
+
* For instance, you can set `POST` even for a `List` use case, which usually defaults to `GET`.
|
|
22
|
+
* This can be useful in case you want the input to "travel" through the body of the request, and not the query params.
|
|
23
|
+
*/
|
|
11
24
|
method?: HTTPMethod;
|
|
25
|
+
/**
|
|
26
|
+
* The path on which the use case should mounted at
|
|
27
|
+
*
|
|
28
|
+
* By default, it's mounted at `/api/v1/${fqucn}`.
|
|
29
|
+
*/
|
|
12
30
|
mountAt?: UCHTTPMountingPoint;
|
|
31
|
+
/**
|
|
32
|
+
* The path on which the use case should also mounted at
|
|
33
|
+
*
|
|
34
|
+
* This is typically used when the mounting point is changed and you want to maintain a "legacy" endpoint for clients having
|
|
35
|
+
* a different release cycle than the server (e.g. a mobile app), who are still calling the old endpoint.
|
|
36
|
+
*/
|
|
13
37
|
mountAlsoAt?: UCHTTPMountingPoint[];
|
|
14
|
-
|
|
38
|
+
/**
|
|
39
|
+
* Transform the output received to fit with some specific cases where the endpoint is expected to respect a certain contract
|
|
40
|
+
* @param output
|
|
41
|
+
* @returns
|
|
42
|
+
*/
|
|
43
|
+
transform?: (output: UCOutput<OPI0, OPI1>) => object;
|
|
15
44
|
};
|
|
16
45
|
}
|
|
@@ -19,13 +19,17 @@ export class UCOutputBuilder {
|
|
|
19
19
|
}
|
|
20
20
|
addAll1(items) {
|
|
21
21
|
this.init1IfNecessary();
|
|
22
|
+
// biome-ignore lint/style/noNonNullAssertion: set in the call above
|
|
22
23
|
this.output.parts._1.items.push(...items);
|
|
24
|
+
// biome-ignore lint/style/noNonNullAssertion: set in the call above
|
|
23
25
|
this.output.parts._1.total += items.length;
|
|
24
26
|
return this;
|
|
25
27
|
}
|
|
26
28
|
add1(item) {
|
|
27
29
|
this.init1IfNecessary();
|
|
30
|
+
// biome-ignore lint/style/noNonNullAssertion: set in the call above
|
|
28
31
|
this.output.parts._1.items.push(item);
|
|
32
|
+
// biome-ignore lint/style/noNonNullAssertion: set in the call above
|
|
29
33
|
this.output.parts._1.total += 1;
|
|
30
34
|
return this;
|
|
31
35
|
}
|
|
@@ -34,6 +38,7 @@ export class UCOutputBuilder {
|
|
|
34
38
|
}
|
|
35
39
|
count1() {
|
|
36
40
|
this.init1IfNecessary();
|
|
41
|
+
// biome-ignore lint/style/noNonNullAssertion: set in the call above
|
|
37
42
|
return this.output.parts._1.total;
|
|
38
43
|
}
|
|
39
44
|
has(predicate) {
|
|
@@ -75,7 +75,9 @@ export class UCOutputReader {
|
|
|
75
75
|
total = part.total;
|
|
76
76
|
}
|
|
77
77
|
return {
|
|
78
|
-
fields: allFieldsKeys.map((fieldKey) =>
|
|
78
|
+
fields: allFieldsKeys.map((fieldKey) =>
|
|
79
|
+
// biome-ignore lint/suspicious/noExplicitAny: can be anything
|
|
80
|
+
new UCOutputField(fieldKey, allFields[fieldKey])),
|
|
79
81
|
idx,
|
|
80
82
|
items,
|
|
81
83
|
key,
|
|
@@ -40,6 +40,7 @@ let HTTPUCTransporter = class HTTPUCTransporter {
|
|
|
40
40
|
const publicApiKeyCheckType = sec?.publicApiKeyCheckType ?? DEFAULT_UC_SEC_PAKCT;
|
|
41
41
|
switch (publicApiKeyCheckType) {
|
|
42
42
|
case 'off':
|
|
43
|
+
// Nothing to do
|
|
43
44
|
break;
|
|
44
45
|
case 'on': {
|
|
45
46
|
const publicApiKey = await this.serverClientManager.publicApiKey();
|
|
@@ -102,6 +103,9 @@ let HTTPUCTransporter = class HTTPUCTransporter {
|
|
|
102
103
|
},
|
|
103
104
|
urlBuilder: async () => `${baseURL}${path}`,
|
|
104
105
|
});
|
|
106
|
+
// In case of 204, we get an empty object.
|
|
107
|
+
// Even though it makes deserializing easier, this is not considered a valid output.
|
|
108
|
+
// So we handle the case here.
|
|
105
109
|
if (!res || Object.keys(res).length === 0) {
|
|
106
110
|
return;
|
|
107
111
|
}
|
|
@@ -19,6 +19,7 @@ function predicate(key, filter) {
|
|
|
19
19
|
return (r) => r[key] === filter;
|
|
20
20
|
}
|
|
21
21
|
let InMemoryUCDataStore = class InMemoryUCDataStore {
|
|
22
|
+
// biome-ignore lint/suspicious/noExplicitAny: can be anything
|
|
22
23
|
entries;
|
|
23
24
|
tx;
|
|
24
25
|
constructor() {
|
|
@@ -46,10 +47,13 @@ let InMemoryUCDataStore = class InMemoryUCDataStore {
|
|
|
46
47
|
};
|
|
47
48
|
}
|
|
48
49
|
async install() {
|
|
50
|
+
// Nothing to do
|
|
49
51
|
}
|
|
50
52
|
async read(opts) {
|
|
51
53
|
let items = this
|
|
52
54
|
.entries;
|
|
55
|
+
// Filter
|
|
56
|
+
// Of course it handles only simple cases (eq X, is null, in) with the AND operator
|
|
53
57
|
if (opts?.filters) {
|
|
54
58
|
const { aggregateId, appName, name, organizationId, userId } = opts.filters;
|
|
55
59
|
if (aggregateId !== undefined) {
|
|
@@ -68,6 +72,8 @@ let InMemoryUCDataStore = class InMemoryUCDataStore {
|
|
|
68
72
|
items = items.filter(predicate('userId', userId));
|
|
69
73
|
}
|
|
70
74
|
}
|
|
75
|
+
// Sort
|
|
76
|
+
// => No need, we are processing them by order of insertion in the Map
|
|
71
77
|
return {
|
|
72
78
|
records: items,
|
|
73
79
|
};
|
|
@@ -79,6 +85,7 @@ let InMemoryUCDataStore = class InMemoryUCDataStore {
|
|
|
79
85
|
return [];
|
|
80
86
|
}
|
|
81
87
|
async testKey() {
|
|
88
|
+
// Nothing to do
|
|
82
89
|
}
|
|
83
90
|
async write(record) {
|
|
84
91
|
this.writeBulk([record]);
|
|
@@ -5,6 +5,10 @@ import type { UCDataStore, UCDataStoreReadOpts, UCDataStoreReadProjectionOpts, U
|
|
|
5
5
|
import type { UCData } from '../data.js';
|
|
6
6
|
import type { UCInput } from '../input.js';
|
|
7
7
|
import type { UCSettings } from '../settings.js';
|
|
8
|
+
/**
|
|
9
|
+
* @see https://knexjs.org/guide/#configuration-options
|
|
10
|
+
* @see https://knexjs.org/guide/#pool
|
|
11
|
+
*/
|
|
8
12
|
export interface KnexUCDataStoreSettings extends Settings {
|
|
9
13
|
knex_uc_data_store_conn_string: `postgresql://${string}`;
|
|
10
14
|
knex_uc_data_store_file_path: FilePath | ':memory:';
|
|
@@ -58,6 +58,7 @@ let KnexUCDataStore = class KnexUCDataStore {
|
|
|
58
58
|
}
|
|
59
59
|
async read(opts) {
|
|
60
60
|
const query = this.client(this.s().uc_data_store_ucs_dataset_name);
|
|
61
|
+
// Filter
|
|
61
62
|
if (opts?.filters) {
|
|
62
63
|
const { aggregateId, appName, idWithinInput, name, organizationId, userId, } = opts.filters;
|
|
63
64
|
this.filter(query, aggregateId, 'aggregateId');
|
|
@@ -67,10 +68,17 @@ let KnexUCDataStore = class KnexUCDataStore {
|
|
|
67
68
|
this.filter(query, userId, 'userId');
|
|
68
69
|
if (idWithinInput !== undefined) {
|
|
69
70
|
for (const [k, v] of Object.entries(idWithinInput)) {
|
|
71
|
+
// Not comfortable with the key here but it seems to escape correctly :
|
|
72
|
+
// select * from "d2efe54a-ce85-437c-958e-440f54c0743d"
|
|
73
|
+
// where jsonb_path_query_first("input", ?) #>> '{}' = ?
|
|
74
|
+
// and "name" = ?
|
|
75
|
+
// and "organization_id" = ?
|
|
76
|
+
// order by "created_at" asc
|
|
70
77
|
query.whereJsonPath('input', `$.${k}`, '=', v);
|
|
71
78
|
}
|
|
72
79
|
}
|
|
73
80
|
}
|
|
81
|
+
// Sort
|
|
74
82
|
query.orderBy('created_at', 'asc');
|
|
75
83
|
const records = (await query).map((r) => this.mapRowToRecord(r));
|
|
76
84
|
return {
|
|
@@ -79,11 +87,13 @@ let KnexUCDataStore = class KnexUCDataStore {
|
|
|
79
87
|
}
|
|
80
88
|
async readProjection(name, opts) {
|
|
81
89
|
const query = this.client(name);
|
|
90
|
+
// Sort
|
|
82
91
|
if (opts?.orderBy) {
|
|
83
92
|
for (const [k, v] of Object.entries(opts.orderBy)) {
|
|
84
93
|
query.orderBy(k, v);
|
|
85
94
|
}
|
|
86
95
|
}
|
|
96
|
+
// Paginate
|
|
87
97
|
if (opts?.limit) {
|
|
88
98
|
query.limit(opts.limit);
|
|
89
99
|
}
|
|
@@ -201,9 +211,13 @@ let KnexUCDataStore = class KnexUCDataStore {
|
|
|
201
211
|
};
|
|
202
212
|
}
|
|
203
213
|
parseJSONColIfNecessary(value) {
|
|
214
|
+
// In some DBs, the json type is returned as string (e.g. sqlite3)
|
|
204
215
|
return typeof value === 'string' ? JSON.parse(value) : value;
|
|
205
216
|
}
|
|
217
|
+
//#region migrations
|
|
206
218
|
async migration001CreateMainTable() {
|
|
219
|
+
// Using hasTable and then createTable because createTableIfNotExists has been deprecated
|
|
220
|
+
// See https://github.com/knex/knex/issues/1303#issuecomment-594489136
|
|
207
221
|
const exists = await this.client.schema.hasTable(this.s().uc_data_store_ucs_dataset_name);
|
|
208
222
|
if (exists) {
|
|
209
223
|
return;
|
|
@@ -29,6 +29,7 @@ let SimpleUCManager = class SimpleUCManager {
|
|
|
29
29
|
ucInputValidator;
|
|
30
30
|
ucInitProvider;
|
|
31
31
|
ucMainProvider;
|
|
32
|
+
// WARNING : This property makes this class "thread unsafe". Be careful how you inject it into your components.
|
|
32
33
|
tx;
|
|
33
34
|
constructor(ucClientConfirmManager, clockManager, cryptoManager, logger, ucDataStore, ucExecChecker, ucInputFilesProcessor, ucInputValidator, ucInitProvider, ucMainProvider) {
|
|
34
35
|
this.ucClientConfirmManager = ucClientConfirmManager;
|
|
@@ -64,6 +65,7 @@ let SimpleUCManager = class SimpleUCManager {
|
|
|
64
65
|
if (!client) {
|
|
65
66
|
throw new Error(`The use case ${metadata.name} has no client lifecycle`);
|
|
66
67
|
}
|
|
68
|
+
// Always check the right to execute, even if done when displaying the control
|
|
67
69
|
const { allowed } = await this.ucExecChecker.exec({
|
|
68
70
|
lifecycle: 'client',
|
|
69
71
|
uc,
|
|
@@ -72,6 +74,9 @@ let SimpleUCManager = class SimpleUCManager {
|
|
|
72
74
|
throw new ForbiddenError();
|
|
73
75
|
}
|
|
74
76
|
this.ucInputValidator.exec({ uc });
|
|
77
|
+
// Process the file client side only if it is not sent to the server
|
|
78
|
+
// Be careful with some edge cases where the file needs to be uploaded somewhere else.
|
|
79
|
+
// Note that we cannot check server !== true because in some cases, the server is not stripped (e.g. tests, node cli client, etc.).
|
|
75
80
|
if (server === undefined) {
|
|
76
81
|
await this.ucInputFilesProcessor.exec({ uc });
|
|
77
82
|
}
|
|
@@ -85,6 +90,7 @@ let SimpleUCManager = class SimpleUCManager {
|
|
|
85
90
|
if (typeof server !== 'object') {
|
|
86
91
|
throw new Error(`The use case ${metadata.name} has no server lifecycle`);
|
|
87
92
|
}
|
|
93
|
+
// Always check the right to execute, even if done when displaying the control
|
|
88
94
|
const { allowed } = await this.ucExecChecker.exec({
|
|
89
95
|
lifecycle: 'server',
|
|
90
96
|
uc,
|
|
@@ -2,30 +2,90 @@ import type { DataType, TBase, UIntQuantity } from '../dt/index.js';
|
|
|
2
2
|
import type { UCFieldKey } from './def.js';
|
|
3
3
|
import type { Value } from './value.js';
|
|
4
4
|
export declare enum UCInputFieldChangeOperator {
|
|
5
|
+
/**
|
|
6
|
+
* Considering the cardinality of the field (min > 1), add a new value
|
|
7
|
+
*/
|
|
5
8
|
ADD = "ADD",
|
|
9
|
+
/**
|
|
10
|
+
* Considering the cardinality of the field (min > 1), remove a value
|
|
11
|
+
*/
|
|
6
12
|
REMOVE = "REMOVE",
|
|
13
|
+
/**
|
|
14
|
+
* Reset the value of the field
|
|
15
|
+
*/
|
|
7
16
|
RESET = "RESET",
|
|
17
|
+
/**
|
|
18
|
+
* Considering the cardinality of the field (max <= 1), set the value
|
|
19
|
+
*/
|
|
8
20
|
SET = "SET"
|
|
9
21
|
}
|
|
10
22
|
export declare enum UCInputFieldFillingMode {
|
|
23
|
+
/**
|
|
24
|
+
* Set programmatically on behalf of the user (e.g. a foreign key id for a given object)
|
|
25
|
+
*/
|
|
11
26
|
AUTO_PRE = "AUTO_PRE",
|
|
27
|
+
/**
|
|
28
|
+
* Set manually by the user (e.g. a form field, a cli flag, etc.)
|
|
29
|
+
*/
|
|
12
30
|
MANUAL = "MANUAL"
|
|
13
31
|
}
|
|
14
32
|
export interface UCInputFieldDefCardinality {
|
|
15
33
|
max?: UIntQuantity;
|
|
16
34
|
min?: UIntQuantity;
|
|
17
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Definition of a use case input field
|
|
38
|
+
*/
|
|
18
39
|
export interface UCInputFieldDef<T extends DataType> {
|
|
40
|
+
/**
|
|
41
|
+
* A field can have 0, 1 or n values. This field defines the rules.
|
|
42
|
+
*
|
|
43
|
+
* @defaultValue { max: 1, min: 1 } => the user must absolutely provide one value only
|
|
44
|
+
*
|
|
45
|
+
* @example { max: 5, min: 0 } => the user must provide at most 5 values or none
|
|
46
|
+
* @example { min: 0 } => the user must provide 0 values or none
|
|
47
|
+
*/
|
|
19
48
|
cardinality?: UCInputFieldDefCardinality;
|
|
49
|
+
/**
|
|
50
|
+
* @defaultValue {@link UCInputFieldFillingMode.MANUAL}
|
|
51
|
+
*/
|
|
20
52
|
fillingMode?: UCInputFieldFillingMode;
|
|
53
|
+
/**
|
|
54
|
+
* @defaultValue false
|
|
55
|
+
*/
|
|
21
56
|
readOnly?: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Some types are automatically considered sensitive (e.g. {@link Password}).
|
|
59
|
+
*
|
|
60
|
+
* But you can force the behavior with this setting for any other type of field.
|
|
61
|
+
*
|
|
62
|
+
* @defaultValue false
|
|
63
|
+
*/
|
|
22
64
|
sensitive?: boolean;
|
|
65
|
+
/**
|
|
66
|
+
* When you persist a use case, all the input fields are automatically persisted as well.
|
|
67
|
+
*
|
|
68
|
+
* Sometimes this is not wanted. Setting the field as transient will exclude it from being persisted.
|
|
69
|
+
*
|
|
70
|
+
* @defaultValue false
|
|
71
|
+
*/
|
|
23
72
|
transient?: boolean;
|
|
24
73
|
type: TBase<T>;
|
|
25
74
|
}
|
|
26
75
|
export type UCInputFieldValue<T extends DataType> = Value<T>;
|
|
27
76
|
export declare function ucifExamples<T extends DataType>(def: UCInputFieldDef<T>): T[] | undefined;
|
|
28
77
|
export declare function ucifHint<T extends DataType>(def: UCInputFieldDef<T>): string | undefined;
|
|
78
|
+
/**
|
|
79
|
+
* The unique id associated to this field
|
|
80
|
+
*
|
|
81
|
+
* By default it would return `inputfield-myField`.
|
|
82
|
+
* If you have the same field multiple times in one context (e.g. a web page), pass a unique element to the `prefix`.
|
|
83
|
+
* For example `uc1-inputfield-myField` and `uc2-inputfield-myField`
|
|
84
|
+
*
|
|
85
|
+
* @param prefix
|
|
86
|
+
* @param separator
|
|
87
|
+
* @returns
|
|
88
|
+
*/
|
|
29
89
|
export declare function ucifId(key: UCFieldKey, prefix?: string, separator?: string): string;
|
|
30
90
|
export declare function ucifIsMandatory<T extends DataType>(def: UCInputFieldDef<T>): boolean;
|
|
31
91
|
export declare function ucifRepeatability<T extends DataType>(def: UCInputFieldDef<T>): [boolean, UIntQuantity];
|
|
@@ -1,21 +1,41 @@
|
|
|
1
1
|
export var UCInputFieldChangeOperator;
|
|
2
2
|
(function (UCInputFieldChangeOperator) {
|
|
3
|
+
/**
|
|
4
|
+
* Considering the cardinality of the field (min > 1), add a new value
|
|
5
|
+
*/
|
|
3
6
|
UCInputFieldChangeOperator["ADD"] = "ADD";
|
|
7
|
+
/**
|
|
8
|
+
* Considering the cardinality of the field (min > 1), remove a value
|
|
9
|
+
*/
|
|
4
10
|
UCInputFieldChangeOperator["REMOVE"] = "REMOVE";
|
|
11
|
+
/**
|
|
12
|
+
* Reset the value of the field
|
|
13
|
+
*/
|
|
5
14
|
UCInputFieldChangeOperator["RESET"] = "RESET";
|
|
15
|
+
/**
|
|
16
|
+
* Considering the cardinality of the field (max <= 1), set the value
|
|
17
|
+
*/
|
|
6
18
|
UCInputFieldChangeOperator["SET"] = "SET";
|
|
7
19
|
})(UCInputFieldChangeOperator || (UCInputFieldChangeOperator = {}));
|
|
8
20
|
export var UCInputFieldFillingMode;
|
|
9
21
|
(function (UCInputFieldFillingMode) {
|
|
22
|
+
/**
|
|
23
|
+
* Set programmatically on behalf of the user (e.g. a foreign key id for a given object)
|
|
24
|
+
*/
|
|
10
25
|
UCInputFieldFillingMode["AUTO_PRE"] = "AUTO_PRE";
|
|
26
|
+
/**
|
|
27
|
+
* Set manually by the user (e.g. a form field, a cli flag, etc.)
|
|
28
|
+
*/
|
|
11
29
|
UCInputFieldFillingMode["MANUAL"] = "MANUAL";
|
|
12
30
|
})(UCInputFieldFillingMode || (UCInputFieldFillingMode = {}));
|
|
13
31
|
export function ucifExamples(def) {
|
|
14
32
|
const { type } = def;
|
|
15
33
|
const examples = type.getExamples();
|
|
34
|
+
// Leaving the value `undefined` means you want the default value
|
|
16
35
|
if (examples === undefined) {
|
|
17
36
|
return [type.example()];
|
|
18
37
|
}
|
|
38
|
+
// Setting the examples to `[]` means you don't want them
|
|
19
39
|
if (examples.length === 0) {
|
|
20
40
|
return undefined;
|
|
21
41
|
}
|
|
@@ -37,6 +57,17 @@ export function ucifHint(def) {
|
|
|
37
57
|
}
|
|
38
58
|
return examples.join(', ');
|
|
39
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* The unique id associated to this field
|
|
62
|
+
*
|
|
63
|
+
* By default it would return `inputfield-myField`.
|
|
64
|
+
* If you have the same field multiple times in one context (e.g. a web page), pass a unique element to the `prefix`.
|
|
65
|
+
* For example `uc1-inputfield-myField` and `uc2-inputfield-myField`
|
|
66
|
+
*
|
|
67
|
+
* @param prefix
|
|
68
|
+
* @param separator
|
|
69
|
+
* @returns
|
|
70
|
+
*/
|
|
40
71
|
export function ucifId(key, prefix = 'inputfield', separator = '-') {
|
|
41
72
|
return `${prefix}${separator}${key}`;
|
|
42
73
|
}
|
|
@@ -60,12 +91,14 @@ export function ucifIsSensitive(def) {
|
|
|
60
91
|
}
|
|
61
92
|
export function ucifMustBeFilledManually(def, opts) {
|
|
62
93
|
const { fillingMode } = def;
|
|
94
|
+
// If there is no mode, we consider it as UCInputFieldFillingMode.MANUAL
|
|
63
95
|
if (!fillingMode) {
|
|
64
96
|
return true;
|
|
65
97
|
}
|
|
66
98
|
const fillingModes = [
|
|
67
99
|
UCInputFieldFillingMode.MANUAL,
|
|
68
100
|
];
|
|
101
|
+
// If there is no context, it means that the field cannot be set via UCInputFieldFillingMode.AUTO_PRE (e.g. in CLI target)
|
|
69
102
|
if (opts?.noContext) {
|
|
70
103
|
fillingModes.push(UCInputFieldFillingMode.AUTO_PRE);
|
|
71
104
|
}
|
package/dist/esm/uc/input.d.ts
CHANGED
|
@@ -1,11 +1,35 @@
|
|
|
1
1
|
import type { StringKeys } from '../utils/index.js';
|
|
2
2
|
import type { UCInputFieldDef } from './input-field.js';
|
|
3
|
+
/**
|
|
4
|
+
* Base interface all the use case input interfaces must extend
|
|
5
|
+
*/
|
|
3
6
|
export interface UCInput {
|
|
4
7
|
}
|
|
8
|
+
/**
|
|
9
|
+
* Definition of a use case input
|
|
10
|
+
*/
|
|
5
11
|
export interface UCInputDef<I extends UCInput> {
|
|
12
|
+
/**
|
|
13
|
+
* This is useful when you want to render a given field only after its dependent fields have been set.
|
|
14
|
+
*/
|
|
6
15
|
dependencies?: Partial<Record<StringKeys<I>, StringKeys<I>[]>>;
|
|
16
|
+
/**
|
|
17
|
+
* It must follow strictly the shape of the corresponding {@link UCInput} with fields sorted alphabetically.
|
|
18
|
+
*/
|
|
7
19
|
fields: Record<StringKeys<I>, UCInputFieldDef<any>>;
|
|
20
|
+
/**
|
|
21
|
+
* By default, the fields are displayed in the same order as in {@link fields} (i.e. alphabetically).
|
|
22
|
+
*
|
|
23
|
+
* You can customize this by specifying the desired order here.
|
|
24
|
+
*
|
|
25
|
+
* For example, when rendering a form, this is used.
|
|
26
|
+
*/
|
|
8
27
|
order?: StringKeys<I>[];
|
|
28
|
+
/**
|
|
29
|
+
* Cross-field validation rules
|
|
30
|
+
*
|
|
31
|
+
* For example, if you want the user to provide `a` OR `b` but not both.
|
|
32
|
+
*/
|
|
9
33
|
validation?: {
|
|
10
34
|
or?: StringKeys<I>[];
|
|
11
35
|
};
|
|
@@ -7,6 +7,8 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
import { injectable } from 'inversify';
|
|
8
8
|
let IdleServerMain = class IdleServerMain {
|
|
9
9
|
async exec(_props) {
|
|
10
|
+
// Right now it's the same as IdleClientMain, but it's better to have 2 impls in case they need to diverge
|
|
11
|
+
// NOOP
|
|
10
12
|
}
|
|
11
13
|
};
|
|
12
14
|
IdleServerMain = __decorate([
|
package/dist/esm/uc/manager.d.ts
CHANGED
|
@@ -8,8 +8,19 @@ import type { UCInput } from './input.js';
|
|
|
8
8
|
import type { UCOPIBase } from './opi.js';
|
|
9
9
|
import type { UCOutputOrNothing } from './output.js';
|
|
10
10
|
export interface UCManagerPersistOpts {
|
|
11
|
+
/**
|
|
12
|
+
* In case the use case relates to an existing aggregate, pass its `aggregateId` in this field.
|
|
13
|
+
* This is typically used in a `Delete` use case in order to link it to the `Create` one executed in the past.
|
|
14
|
+
*/
|
|
11
15
|
aggregateId?: UUID;
|
|
16
|
+
/**
|
|
17
|
+
* @defaultValue {@link UCExecMode.USER}
|
|
18
|
+
*/
|
|
12
19
|
executionMode?: UCExecMode;
|
|
20
|
+
/**
|
|
21
|
+
* In case the use case is performed by an anonymous user or a user outside the organization, pass the actual `organizationId` in this field.
|
|
22
|
+
* This is typically used in a use case where someone anonymous posts something for a specific organization in a multi-tenant architecture.
|
|
23
|
+
*/
|
|
13
24
|
organizationId?: UUID;
|
|
14
25
|
}
|
|
15
26
|
export interface UCManager {
|
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
import type { AppName } from '../app/index.js';
|
|
2
2
|
import type { IconCode } from '../icon/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* The type of action the use case performs
|
|
5
|
+
*
|
|
6
|
+
* This impacts the HTTP verb used in the transport layer for example.
|
|
7
|
+
*/
|
|
3
8
|
export type UCAction = 'Create' | 'Delete' | 'List' | 'Search' | 'Update' | 'View';
|
|
4
9
|
export type UCName = Capitalize<string>;
|
|
5
10
|
export type FQUCNameSeparator = '_';
|
|
11
|
+
/**
|
|
12
|
+
* Fully qualified use case name
|
|
13
|
+
*
|
|
14
|
+
* It's made with the {@link AppName} and the {@link UCName} linked by {@link FQUCNameSeparator}.
|
|
15
|
+
*/
|
|
6
16
|
export type FQUCName = `${AppName}${FQUCNameSeparator}${UCName}`;
|
|
7
17
|
export interface UCMetadata {
|
|
8
18
|
action: UCAction;
|
|
@@ -7,6 +7,9 @@ export interface UCOPILayoutContext {
|
|
|
7
7
|
availableWidthInPx: UIntQuantity;
|
|
8
8
|
target: 'cli' | 'mobile' | 'web';
|
|
9
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* @alpha This feature is not fully ready yet.
|
|
12
|
+
*/
|
|
10
13
|
export type UCOPILayout<OPI extends UCOPIBase, LT extends UCOPILayoutType = UCOPILayoutType, LI extends UCOPILayoutInput = UCOPILayoutInput> = {
|
|
11
14
|
get: (item: OPI, context: UCOPILayoutContext) => LI;
|
|
12
15
|
type: LT;
|
package/dist/esm/uc/opi.d.ts
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import type { DataType, UUID } from '../dt/index.js';
|
|
2
2
|
import type { Value } from './value.js';
|
|
3
|
+
/**
|
|
4
|
+
* Base interface all the use case OPI interfaces must extend
|
|
5
|
+
*/
|
|
3
6
|
export interface UCOPIBase {
|
|
4
7
|
id: UUID;
|
|
5
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* A value returned as part of an OPI
|
|
11
|
+
*
|
|
12
|
+
* Unlike {@link UCInputFieldValue}, it cannot be `undefined` because it is not serializable in JSON.
|
|
13
|
+
*/
|
|
6
14
|
export type UCOPIValue<T extends DataType> = Exclude<Value<T>, undefined>;
|
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
import type { DataType, TBase } from '../dt/index.js';
|
|
2
2
|
import type { StringKeys } from '../utils/index.js';
|
|
3
3
|
import type { UCOPIBase } from './opi.js';
|
|
4
|
+
/**
|
|
5
|
+
* Definition of a use case output field
|
|
6
|
+
*/
|
|
4
7
|
export interface UCOutputFieldDef<OPI extends UCOPIBase, T extends DataType> {
|
|
8
|
+
/**
|
|
9
|
+
* Indicates another field of the output this field can potentially link to (in the `<a></a>` way).
|
|
10
|
+
*/
|
|
5
11
|
linksTo?: StringKeys<OPI>;
|
|
12
|
+
/**
|
|
13
|
+
* The aggregation method to use to present the summary of this field across all the corresponding items.
|
|
14
|
+
*/
|
|
6
15
|
totalType?: 'sum';
|
|
7
16
|
type: TBase<T>;
|
|
8
17
|
}
|
|
@@ -6,14 +6,36 @@ import type { UCOPILayout } from './opi-layout.js';
|
|
|
6
6
|
import type { UCOPIBase } from './opi.js';
|
|
7
7
|
import type { UCOutputFieldDef } from './output-field.js';
|
|
8
8
|
export interface UCOutputPart<OPI extends UCOPIBase> {
|
|
9
|
+
/**
|
|
10
|
+
* The items making the part
|
|
11
|
+
*/
|
|
9
12
|
items: OPI[];
|
|
13
|
+
/**
|
|
14
|
+
* Pagination to pass to the next call of the use case.
|
|
15
|
+
*/
|
|
10
16
|
pagination?: ListInput;
|
|
17
|
+
/**
|
|
18
|
+
* The total number of items regardless pagination.
|
|
19
|
+
*/
|
|
11
20
|
total: UIntQuantity;
|
|
12
21
|
}
|
|
13
22
|
export type UCOutputPartDefFields<OPI extends UCOPIBase> = Record<StringKeys<OPI>, UCOutputFieldDef<OPI, any>>;
|
|
23
|
+
/**
|
|
24
|
+
* Definition of a use case output part
|
|
25
|
+
*/
|
|
14
26
|
export interface UCOutputPartDef<OPI extends UCOPIBase> {
|
|
27
|
+
/**
|
|
28
|
+
* It must follow strictly the shape of the corresponding {@link UCOPIBase} with fields sorted alphabetically.
|
|
29
|
+
*/
|
|
15
30
|
fields: Omit<UCOutputPartDefFields<OPI>, 'id'>;
|
|
16
31
|
layout?: UCOPILayout<OPI>;
|
|
32
|
+
/**
|
|
33
|
+
* By default, the fields are displayed in the same order as in {@link fields} (i.e. alphabetically).
|
|
34
|
+
*
|
|
35
|
+
* You can customize this by specifying the desired order here.
|
|
36
|
+
*
|
|
37
|
+
* For example, when rendering a card with the data, this is used.
|
|
38
|
+
*/
|
|
17
39
|
order?: StringKeys<OPI>[];
|
|
18
40
|
related?: {
|
|
19
41
|
global: UCDef<any, any, any>[];
|
package/dist/esm/uc/output.d.ts
CHANGED
|
@@ -10,6 +10,9 @@ export interface UCOutput<OPI0 extends UCOPIBase | undefined = undefined, OPI1 e
|
|
|
10
10
|
};
|
|
11
11
|
}
|
|
12
12
|
export type UCOutputOrNothing<OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined> = UCOutput<OPI0, OPI1> | void;
|
|
13
|
+
/**
|
|
14
|
+
* Definition of a use case output
|
|
15
|
+
*/
|
|
13
16
|
export interface UCOutputDef<OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined> {
|
|
14
17
|
parts?: {
|
|
15
18
|
_0: UCOutputPartDef<NonNullable<OPI0>>;
|
package/dist/esm/uc/policy.d.ts
CHANGED
|
@@ -8,6 +8,28 @@ export interface UCPolicyInput<I extends UCInput | undefined = undefined, OPI0 e
|
|
|
8
8
|
export interface UCPolicyOutput {
|
|
9
9
|
allowed: boolean;
|
|
10
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* The policy defines the type(s) of user(s) who can perform the use case
|
|
13
|
+
*
|
|
14
|
+
* It corresponds more or less to RBAC (Resource Based Access Control).
|
|
15
|
+
*
|
|
16
|
+
* At this moment, for simplicity, ABAC (Attribute Based Access Control) must be done in the `main` of a use case.
|
|
17
|
+
* For example, if you have to check that a user must be the owner of a resource.
|
|
18
|
+
*
|
|
19
|
+
* The main reason for this choice at this moment, is to avoid "double-fetching" in the `policy` and in `main`.
|
|
20
|
+
* 1. Fetch the resource (e.g. by id) to check if the user is the owner => Accept
|
|
21
|
+
* 2. Fetch the resource again to perform actions on it
|
|
22
|
+
*
|
|
23
|
+
* A good solution for this would be to pass the resources fetched from the `policy` to `main` but that is,
|
|
24
|
+
* at least for the moment, out of scope.
|
|
25
|
+
*/
|
|
11
26
|
export interface UCPolicy<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined> extends Worker<UCPolicyInput<I, OPI0, OPI1>, Promise<UCPolicyOutput>> {
|
|
27
|
+
/**
|
|
28
|
+
* Determines whether the policy check can be executed before checking the auth
|
|
29
|
+
*
|
|
30
|
+
* For example, for {@link NobodyUCPolicy}, we know that there is no need to check the auth,
|
|
31
|
+
* as the policy will always return false. The same goes for {@link EverybodyUCPolicy} but
|
|
32
|
+
* in the opposite way.
|
|
33
|
+
*/
|
|
12
34
|
canBeExecutedPreAuth(): Promise<boolean>;
|
|
13
35
|
}
|
package/dist/esm/uc/sec.d.ts
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
export type UCSecAuthType = 'apiKey' | 'basic' | 'jwt';
|
|
2
2
|
export type UCSecPublicApiKeyCheckType = 'off' | 'on';
|
|
3
|
+
/**
|
|
4
|
+
* Definition of the security scheme of a use case
|
|
5
|
+
*/
|
|
3
6
|
export interface UCSec {
|
|
7
|
+
/**
|
|
8
|
+
* @defaultValue {@link DEFAULT_UC_SEC_AT}
|
|
9
|
+
*/
|
|
4
10
|
authType?: UCSecAuthType;
|
|
11
|
+
/**
|
|
12
|
+
* @defaultValue {@link DEFAULT_UC_SEC_PAKCT}
|
|
13
|
+
*/
|
|
5
14
|
publicApiKeyCheckType?: UCSecPublicApiKeyCheckType;
|
|
6
15
|
}
|