@openmrs/esm-config 3.4.1-pre.96 → 4.0.0-pre.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +10 -10
- package/.turbo/turbo-lint.log +2 -0
- package/.turbo/turbo-test.log +14 -0
- package/.turbo/turbo-typescript.log +2 -0
- package/dist/__mocks__/openmrs-esm-state.mock.d.ts +12 -0
- package/dist/openmrs-esm-module-config.js +1 -1
- package/dist/openmrs-esm-module-config.js.map +1 -1
- package/dist/src/index.d.ts +7 -0
- package/dist/src/module-config/module-config.d.ts +57 -0
- package/dist/src/module-config/module-config.test.d.ts +1 -0
- package/dist/src/module-config/state.d.ts +109 -0
- package/dist/src/navigation/interpolate-string.d.ts +34 -0
- package/dist/src/navigation/interpolate-string.test.d.ts +1 -0
- package/dist/src/navigation/navigate.d.ts +26 -0
- package/dist/src/navigation/navigate.test.d.ts +1 -0
- package/dist/src/public.d.ts +7 -0
- package/dist/src/types.d.ts +49 -0
- package/dist/src/validators/type-validators.d.ts +6 -0
- package/dist/src/validators/type-validators.test.d.ts +1 -0
- package/dist/src/validators/validator.d.ts +24 -0
- package/dist/src/validators/validators.d.ts +32 -0
- package/dist/src/validators/validators.test.d.ts +1 -0
- package/jest.config.js +4 -0
- package/package.json +6 -6
- package/src/navigation/interpolate-string.test.ts +3 -3
- package/src/navigation/interpolate-string.ts +10 -2
- package/src/navigation/navigate.ts +10 -4
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Config, ConfigObject, ConfigSchema } from "../types";
|
|
2
|
+
/**
|
|
3
|
+
* This defines a configuration schema for a module. The schema tells the
|
|
4
|
+
* configuration system how the module can be configured. It specifies
|
|
5
|
+
* what makes configuration valid or invalid.
|
|
6
|
+
*
|
|
7
|
+
* See [Configuration System](http://o3-dev.docs.openmrs.org/#/main/config)
|
|
8
|
+
* for more information about defining a config schema.
|
|
9
|
+
*
|
|
10
|
+
* @param moduleName Name of the module the schema is being defined for. Generally
|
|
11
|
+
* should be the one in which the `defineConfigSchema` call takes place.
|
|
12
|
+
* @param schema The config schema for the module
|
|
13
|
+
*/
|
|
14
|
+
export declare function defineConfigSchema(moduleName: string, schema: ConfigSchema): void;
|
|
15
|
+
/**
|
|
16
|
+
* This defines a configuration schema for an extension. When a schema is defined
|
|
17
|
+
* for an extension, that extension will receive the configuration corresponding
|
|
18
|
+
* to that schema, rather than the configuration corresponding to the module
|
|
19
|
+
* in which it is defined.
|
|
20
|
+
*
|
|
21
|
+
* The schema tells the configuration system how the module can be configured.
|
|
22
|
+
* It specifies what makes configuration valid or invalid.
|
|
23
|
+
*
|
|
24
|
+
* See [Configuration System](http://o3-dev.docs.openmrs.org/#/main/config)
|
|
25
|
+
* for more information about defining a config schema.
|
|
26
|
+
*
|
|
27
|
+
* @param extensionName Name of the extension the schema is being defined for.
|
|
28
|
+
* Should match the `name` of one of the `extensions` entries being returned
|
|
29
|
+
* by `setupOpenMRS`.
|
|
30
|
+
* @param schema The config schema for the extension
|
|
31
|
+
*/
|
|
32
|
+
export declare function defineExtensionConfigSchema(extensionName: string, schema: ConfigSchema): void;
|
|
33
|
+
export declare function provide(config: Config, sourceName?: string): void;
|
|
34
|
+
/**
|
|
35
|
+
* A promise-based way to access the config as soon as it is fully loaded.
|
|
36
|
+
* If it is already loaded, resolves the config in its present state.
|
|
37
|
+
*
|
|
38
|
+
* In general you should use the Unistore-based API provided by
|
|
39
|
+
* `getConfigStore`, which allows creating a subscription so that you always
|
|
40
|
+
* have the latest config. If using React, just use `useConfig`.
|
|
41
|
+
*
|
|
42
|
+
* This is a useful function if you need to get the config in the course
|
|
43
|
+
* of the execution of a function.
|
|
44
|
+
*
|
|
45
|
+
* @param moduleName The name of the module for which to look up the config
|
|
46
|
+
*/
|
|
47
|
+
export declare function getConfig(moduleName: string): Promise<Config>;
|
|
48
|
+
/**
|
|
49
|
+
* Validate and interpolate defaults for `providedConfig` according to `schema`
|
|
50
|
+
*
|
|
51
|
+
* @param schema a configuration schema
|
|
52
|
+
* @param providedConfig an object of config values (without the top-level module name)
|
|
53
|
+
* @param keyPathContext a dot-deparated string which helps the user figure out where
|
|
54
|
+
* the provided config came from
|
|
55
|
+
* @internal
|
|
56
|
+
*/
|
|
57
|
+
export declare function processConfig(schema: ConfigSchema, providedConfig: ConfigObject, keyPathContext: string, devDefaultsAreOn?: boolean): Config;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { Config, ConfigObject, ConfigSchema, ExtensionSlotConfigObject, ProvidedConfig } from "../types";
|
|
2
|
+
/**
|
|
3
|
+
* Internal store
|
|
4
|
+
* A store of the inputs and internal state
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
7
|
+
export interface ConfigInternalStore {
|
|
8
|
+
/** Configs added using the `provide` function */
|
|
9
|
+
providedConfigs: Array<ProvidedConfig>;
|
|
10
|
+
/** An object with module names for keys and schemas for values */
|
|
11
|
+
schemas: Record<string, ConfigSchema>;
|
|
12
|
+
/** Whether to use dev defaults or not */
|
|
13
|
+
devDefaultsAreOn: boolean;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* @internal
|
|
17
|
+
*/
|
|
18
|
+
export declare const configInternalStore: import("unistore").Store<ConfigInternalStore>;
|
|
19
|
+
/**
|
|
20
|
+
* Temporary config
|
|
21
|
+
* LocalStorage-based config used by the implementer tools
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
24
|
+
export interface TemporaryConfigStore {
|
|
25
|
+
config: Config;
|
|
26
|
+
}
|
|
27
|
+
/** @internal */
|
|
28
|
+
export declare const temporaryConfigStore: import("unistore").Store<TemporaryConfigStore>;
|
|
29
|
+
/**
|
|
30
|
+
* Config-side extension store
|
|
31
|
+
* Just what esm-config needs to know about extension state. This
|
|
32
|
+
* is to avoid having esm-config depend on esm-extensions, which would
|
|
33
|
+
* create a circular dependency.
|
|
34
|
+
* @internal
|
|
35
|
+
*/
|
|
36
|
+
export interface ConfigExtensionStore {
|
|
37
|
+
mountedExtensions: Array<ConfigExtensionStoreElement>;
|
|
38
|
+
}
|
|
39
|
+
/** @internal */
|
|
40
|
+
export interface ConfigExtensionStoreElement {
|
|
41
|
+
slotModuleName: string;
|
|
42
|
+
extensionModuleName: string;
|
|
43
|
+
slotName: string;
|
|
44
|
+
extensionId: string;
|
|
45
|
+
}
|
|
46
|
+
/** @internal */
|
|
47
|
+
export declare const configExtensionStore: import("unistore").Store<ConfigExtensionStore>;
|
|
48
|
+
/**
|
|
49
|
+
* Output configs
|
|
50
|
+
*
|
|
51
|
+
* Each module has its own stores for its config and its extension slots' configs.
|
|
52
|
+
* @internal
|
|
53
|
+
*/
|
|
54
|
+
export interface ConfigStore {
|
|
55
|
+
config: ConfigObject | null;
|
|
56
|
+
loaded: boolean;
|
|
57
|
+
}
|
|
58
|
+
/** @internal */
|
|
59
|
+
export declare function getConfigStore(moduleName: string): import("unistore").Store<ConfigStore>;
|
|
60
|
+
/**
|
|
61
|
+
* Configuration for all the specific extension slots
|
|
62
|
+
* @internal
|
|
63
|
+
*/
|
|
64
|
+
export interface ExtensionSlotsConfigStore {
|
|
65
|
+
slots: {
|
|
66
|
+
[slotName: string]: {
|
|
67
|
+
config: ExtensionSlotConfigObject;
|
|
68
|
+
loaded: boolean;
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/** @internal */
|
|
73
|
+
export declare function getExtensionSlotsConfigStore(): import("unistore").Store<ExtensionSlotsConfigStore>;
|
|
74
|
+
/** @internal */
|
|
75
|
+
export declare function getExtensionSlotConfig(slotName: string): {
|
|
76
|
+
config: ExtensionSlotConfigObject;
|
|
77
|
+
loaded: boolean;
|
|
78
|
+
};
|
|
79
|
+
/** @internal */
|
|
80
|
+
export declare function getExtensionSlotConfigFromStore(state: ExtensionSlotsConfigStore, slotName: string): {
|
|
81
|
+
config: ExtensionSlotConfigObject;
|
|
82
|
+
loaded: boolean;
|
|
83
|
+
};
|
|
84
|
+
/** @internal */
|
|
85
|
+
export interface ExtensionsConfigStore {
|
|
86
|
+
configs: {
|
|
87
|
+
[slotName: string]: {
|
|
88
|
+
[extensionId: string]: ConfigStore;
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* One store for all the extensions
|
|
94
|
+
* @internal
|
|
95
|
+
*/
|
|
96
|
+
export declare function getExtensionsConfigStore(): import("unistore").Store<ExtensionsConfigStore>;
|
|
97
|
+
/** @internal */
|
|
98
|
+
export declare function getExtensionConfig(slotName: string, extensionId: string): ConfigStore;
|
|
99
|
+
/** @internal */
|
|
100
|
+
export declare function getExtensionConfigFromStore(state: ExtensionsConfigStore, slotName: string, extensionId: string): ConfigStore;
|
|
101
|
+
/**
|
|
102
|
+
* A store of the implementer tools output config
|
|
103
|
+
* @internal
|
|
104
|
+
*/
|
|
105
|
+
export interface ImplementerToolsConfigStore {
|
|
106
|
+
config: Config;
|
|
107
|
+
}
|
|
108
|
+
/** @internal */
|
|
109
|
+
export declare const implementerToolsConfigStore: import("unistore").Store<ImplementerToolsConfigStore>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** @module @category Navigation */
|
|
2
|
+
/**
|
|
3
|
+
* Interpolates a string with openmrsBase and openmrsSpaBase.
|
|
4
|
+
*
|
|
5
|
+
* Useful for accepting `${openmrsBase}` or `${openmrsSpaBase}` template
|
|
6
|
+
* parameters in configurable URLs.
|
|
7
|
+
*
|
|
8
|
+
* @param template A string to interpolate
|
|
9
|
+
* @param additionalParams Additional values to interpolate into the string template
|
|
10
|
+
*/
|
|
11
|
+
export declare function interpolateUrl(template: string, additionalParams?: {
|
|
12
|
+
[key: string]: string;
|
|
13
|
+
}): string;
|
|
14
|
+
/**
|
|
15
|
+
* Interpolates values of `params` into the `template` string.
|
|
16
|
+
*
|
|
17
|
+
* Useful for additional template parameters in URLs.
|
|
18
|
+
*
|
|
19
|
+
* Example usage:
|
|
20
|
+
* ```js
|
|
21
|
+
* navigate({
|
|
22
|
+
* to: interpolateString(
|
|
23
|
+
* config.links.patientChart,
|
|
24
|
+
* { patientUuid: patient.uuid }
|
|
25
|
+
* )
|
|
26
|
+
* });
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @param template With optional params wrapped in `${ }`
|
|
30
|
+
* @param params Values to interpolate into the string template
|
|
31
|
+
*/
|
|
32
|
+
export declare function interpolateString(template: string, params: {
|
|
33
|
+
[key: string]: string;
|
|
34
|
+
}): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export declare type TemplateParams = {
|
|
2
|
+
[key: string]: string;
|
|
3
|
+
};
|
|
4
|
+
export interface NavigateOptions {
|
|
5
|
+
to: string;
|
|
6
|
+
templateParams?: TemplateParams;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Calls `location.assign` for non-SPA paths and [navigateToUrl](https://single-spa.js.org/docs/api/#navigatetourl) for SPA paths
|
|
10
|
+
*
|
|
11
|
+
* Example usage:
|
|
12
|
+
* ```js
|
|
13
|
+
* const config = useConfig();
|
|
14
|
+
* const submitHandler = () => {
|
|
15
|
+
* navigate({ to: config.links.submitSuccess });
|
|
16
|
+
* };
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* @param to The target path or URL. Supports templating with 'openmrsBase', 'openmrsSpaBase',
|
|
20
|
+
* and any additional template parameters defined in `templateParams`.
|
|
21
|
+
* For example, `${openmrsSpaBase}/home` will resolve to `/openmrs/spa/home`
|
|
22
|
+
* for implementations using the standard OpenMRS and SPA base paths.
|
|
23
|
+
* If `templateParams` contains `{ foo: "bar" }`, then the URL `${openmrsBase}/${foo}`
|
|
24
|
+
* will become `/openmrs/bar`.
|
|
25
|
+
*/
|
|
26
|
+
export declare function navigate({ to, templateParams }: NavigateOptions): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from "./types";
|
|
2
|
+
export * from "./navigation/interpolate-string";
|
|
3
|
+
export * from "./navigation/navigate";
|
|
4
|
+
export * from "./validators/validator";
|
|
5
|
+
export * from "./validators/validators";
|
|
6
|
+
export { defineConfigSchema, defineExtensionConfigSchema, provide, getConfig, } from "./module-config/module-config";
|
|
7
|
+
export { getConfigStore, ConfigStore } from "./module-config/state";
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export declare enum Type {
|
|
2
|
+
Array = "Array",
|
|
3
|
+
Boolean = "Boolean",
|
|
4
|
+
ConceptUuid = "ConceptUuid",
|
|
5
|
+
Number = "Number",
|
|
6
|
+
Object = "Object",
|
|
7
|
+
String = "String",
|
|
8
|
+
UUID = "UUID",
|
|
9
|
+
PersonAttributeTypeUuid = "PersonAttributeTypeUuid",
|
|
10
|
+
PatientIdentifierTypeUuid = "PatientIdentifierTypeUuid"
|
|
11
|
+
}
|
|
12
|
+
export interface ConfigSchema {
|
|
13
|
+
[key: string]: ConfigSchema | ConfigValue;
|
|
14
|
+
_type?: Type;
|
|
15
|
+
_validators?: Array<Validator>;
|
|
16
|
+
_elements?: ConfigSchema;
|
|
17
|
+
}
|
|
18
|
+
export interface Config extends Object {
|
|
19
|
+
[moduleName: string]: {
|
|
20
|
+
[key: string]: any;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export interface ConfigObject extends Object {
|
|
24
|
+
[key: string]: any;
|
|
25
|
+
}
|
|
26
|
+
export declare type ConfigValue = string | number | boolean | void | Array<any> | object;
|
|
27
|
+
export interface ExtensionSlotConfig {
|
|
28
|
+
add?: Array<string>;
|
|
29
|
+
remove?: Array<string>;
|
|
30
|
+
order?: Array<string>;
|
|
31
|
+
configure?: ExtensionSlotConfigureValueObject;
|
|
32
|
+
}
|
|
33
|
+
export interface ExtensionSlotConfigureValueObject {
|
|
34
|
+
[key: string]: object;
|
|
35
|
+
}
|
|
36
|
+
export interface ExtensionSlotConfigObject {
|
|
37
|
+
/** Additional extension IDs to assign to this slot, in addition to those `attach`ed in code. */
|
|
38
|
+
add?: Array<string>;
|
|
39
|
+
/** Extension IDs which were `attach`ed to the slot but which should not be assigned. */
|
|
40
|
+
remove?: Array<string>;
|
|
41
|
+
/** Overrides the default ordering of extensions. */
|
|
42
|
+
order?: Array<string>;
|
|
43
|
+
}
|
|
44
|
+
export declare type ProvidedConfig = {
|
|
45
|
+
source: string;
|
|
46
|
+
config: Config;
|
|
47
|
+
};
|
|
48
|
+
export declare type ValidatorFunction = (value: any) => boolean;
|
|
49
|
+
export declare type Validator = (value: any) => void | string;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const isArray: import("..").Validator;
|
|
2
|
+
export declare const isBoolean: import("..").Validator;
|
|
3
|
+
export declare const isNumber: import("..").Validator;
|
|
4
|
+
export declare const isString: import("..").Validator;
|
|
5
|
+
export declare const isObject: import("..").Validator;
|
|
6
|
+
export declare const isUuid: import("..").Validator;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** @module @category Config Validation */
|
|
2
|
+
import { Validator, ValidatorFunction } from "../types";
|
|
3
|
+
/**
|
|
4
|
+
* Constructs a custom validator.
|
|
5
|
+
*
|
|
6
|
+
* ### Example
|
|
7
|
+
*
|
|
8
|
+
* ```typescript
|
|
9
|
+
* {
|
|
10
|
+
* foo: {
|
|
11
|
+
* _default: 0,
|
|
12
|
+
* _validators: [
|
|
13
|
+
* validator(val => val >= 0, "Must not be negative.")
|
|
14
|
+
* ]
|
|
15
|
+
* }
|
|
16
|
+
* }
|
|
17
|
+
* ```
|
|
18
|
+
* @param validationFunction Takes the configured value as input. Returns true
|
|
19
|
+
* if it is valid, false otherwise.
|
|
20
|
+
* @param message A string message that explains why the value is invalid. Can
|
|
21
|
+
* also be a function that takes the value as input and returns a string.
|
|
22
|
+
* @returns A validator ready for use in a config schema
|
|
23
|
+
*/
|
|
24
|
+
export declare function validator(validationFunction: ValidatorFunction, message: string | ((value: any) => string)): Validator;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verifies that the value is between the provided minimum and maximum
|
|
3
|
+
*
|
|
4
|
+
* @param min Minimum acceptable value
|
|
5
|
+
* @param max Maximum acceptable value
|
|
6
|
+
*/
|
|
7
|
+
export declare const inRange: (min: number, max: number) => import("..").Validator;
|
|
8
|
+
/**
|
|
9
|
+
* Verifies that a string contains only the default URL template
|
|
10
|
+
* parameters, plus any specified in `allowedTemplateParameters`.
|
|
11
|
+
*
|
|
12
|
+
* @param allowedTemplateParameters To be added to `openmrsBase` and `openmrsSpaBase`
|
|
13
|
+
* @category Navigation
|
|
14
|
+
*/
|
|
15
|
+
export declare const isUrlWithTemplateParameters: (allowedTemplateParameters: string[]) => import("..").Validator;
|
|
16
|
+
/**
|
|
17
|
+
* Verifies that a string contains only the default URL template parameters.
|
|
18
|
+
*
|
|
19
|
+
* @category Navigation
|
|
20
|
+
*/
|
|
21
|
+
export declare const isUrl: import("..").Validator;
|
|
22
|
+
/**
|
|
23
|
+
* Verifies that the value is one of the allowed options.
|
|
24
|
+
* @param allowedValues The list of allowable values
|
|
25
|
+
*/
|
|
26
|
+
export declare const oneOf: (allowedValues: Array<any>) => import("..").Validator;
|
|
27
|
+
export declare const validators: {
|
|
28
|
+
inRange: (min: number, max: number) => import("..").Validator;
|
|
29
|
+
isUrl: import("..").Validator;
|
|
30
|
+
isUrlWithTemplateParameters: (allowedTemplateParameters: string[]) => import("..").Validator;
|
|
31
|
+
oneOf: (allowedValues: Array<any>) => import("..").Validator;
|
|
32
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/jest.config.js
CHANGED
|
@@ -8,4 +8,8 @@ module.exports = {
|
|
|
8
8
|
"@openmrs/esm-globals": "<rootDir>/__mocks__/openmrs-esm-globals.mock.tsx",
|
|
9
9
|
"@openmrs/esm-state": "<rootDir>/__mocks__/openmrs-esm-state.mock.tsx",
|
|
10
10
|
},
|
|
11
|
+
testEnvironment: "jsdom",
|
|
12
|
+
testEnvironmentOptions: {
|
|
13
|
+
url: "http://localhost/",
|
|
14
|
+
},
|
|
11
15
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openmrs/esm-config",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0-pre.1",
|
|
4
4
|
"license": "MPL-2.0",
|
|
5
5
|
"description": "A configuration library for the OpenMRS Single-Spa framework.",
|
|
6
6
|
"browser": "dist/openmrs-esm-module-config.js",
|
|
@@ -39,18 +39,18 @@
|
|
|
39
39
|
"ramda": "^0.26.1"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
|
-
"@openmrs/esm-globals": "
|
|
43
|
-
"@openmrs/esm-state": "
|
|
42
|
+
"@openmrs/esm-globals": "4.x",
|
|
43
|
+
"@openmrs/esm-state": "4.x",
|
|
44
44
|
"single-spa": "5.x",
|
|
45
45
|
"systemjs": "6.x"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@openmrs/esm-globals": "^
|
|
49
|
-
"@openmrs/esm-state": "^
|
|
48
|
+
"@openmrs/esm-globals": "^4.0.0-pre.1",
|
|
49
|
+
"@openmrs/esm-state": "^4.0.0-pre.1",
|
|
50
50
|
"@types/ramda": "^0.26.44",
|
|
51
51
|
"@types/systemjs": "^6.1.0",
|
|
52
52
|
"babel-plugin-ramda": "^2.0.0",
|
|
53
53
|
"single-spa": "^5.9.2"
|
|
54
54
|
},
|
|
55
|
-
"gitHead": "
|
|
55
|
+
"gitHead": "9f58b801f07526083a9edc1cc5a1e58660d71eb0"
|
|
56
56
|
}
|
|
@@ -15,14 +15,14 @@ describe("interpolateUrl", () => {
|
|
|
15
15
|
describe("interpolateString", () => {
|
|
16
16
|
it("interpolates template elements", () => {
|
|
17
17
|
const result = interpolateString("test ${one} ${two} 3", {
|
|
18
|
-
one: 1,
|
|
19
|
-
two: 2,
|
|
18
|
+
one: "1",
|
|
19
|
+
two: "2",
|
|
20
20
|
});
|
|
21
21
|
expect(result).toBe("test 1 2 3");
|
|
22
22
|
});
|
|
23
23
|
|
|
24
24
|
it("tolerates extra parameters", () => {
|
|
25
|
-
const result = interpolateString("test ok", { one: 1, two: 2 });
|
|
25
|
+
const result = interpolateString("test ok", { one: "1", two: "2" });
|
|
26
26
|
expect(result).toBe("test ok");
|
|
27
27
|
});
|
|
28
28
|
});
|
|
@@ -11,12 +11,17 @@ function trimTrailingSlash(str: string) {
|
|
|
11
11
|
* parameters in configurable URLs.
|
|
12
12
|
*
|
|
13
13
|
* @param template A string to interpolate
|
|
14
|
+
* @param additionalParams Additional values to interpolate into the string template
|
|
14
15
|
*/
|
|
15
|
-
export function interpolateUrl(
|
|
16
|
+
export function interpolateUrl(
|
|
17
|
+
template: string,
|
|
18
|
+
additionalParams?: { [key: string]: string }
|
|
19
|
+
): string {
|
|
16
20
|
const openmrsSpaBase = trimTrailingSlash(window.getOpenmrsSpaBase());
|
|
17
21
|
return interpolateString(template, {
|
|
18
22
|
openmrsBase: window.openmrsBase,
|
|
19
23
|
openmrsSpaBase: openmrsSpaBase,
|
|
24
|
+
...additionalParams,
|
|
20
25
|
}).replace(/^\/\//, "/"); // remove extra initial slash if present
|
|
21
26
|
}
|
|
22
27
|
|
|
@@ -38,7 +43,10 @@ export function interpolateUrl(template: string): string {
|
|
|
38
43
|
* @param template With optional params wrapped in `${ }`
|
|
39
44
|
* @param params Values to interpolate into the string template
|
|
40
45
|
*/
|
|
41
|
-
export function interpolateString(
|
|
46
|
+
export function interpolateString(
|
|
47
|
+
template: string,
|
|
48
|
+
params: { [key: string]: string }
|
|
49
|
+
): string {
|
|
42
50
|
const names = Object.keys(params);
|
|
43
51
|
return names.reduce(
|
|
44
52
|
(prev, curr) => prev.split("${" + curr + "}").join(params[curr]),
|
|
@@ -7,8 +7,11 @@ function trimTrailingSlash(str: string) {
|
|
|
7
7
|
return str.replace(/\/$/, "");
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
+
export type TemplateParams = { [key: string]: string };
|
|
11
|
+
|
|
10
12
|
export interface NavigateOptions {
|
|
11
13
|
to: string;
|
|
14
|
+
templateParams?: TemplateParams;
|
|
12
15
|
}
|
|
13
16
|
|
|
14
17
|
/**
|
|
@@ -16,19 +19,22 @@ export interface NavigateOptions {
|
|
|
16
19
|
*
|
|
17
20
|
* Example usage:
|
|
18
21
|
* ```js
|
|
19
|
-
* const config =
|
|
22
|
+
* const config = useConfig();
|
|
20
23
|
* const submitHandler = () => {
|
|
21
24
|
* navigate({ to: config.links.submitSuccess });
|
|
22
25
|
* };
|
|
23
26
|
* ```
|
|
24
27
|
*
|
|
25
|
-
* @param to The target path or URL. Supports templating with 'openmrsBase'
|
|
28
|
+
* @param to The target path or URL. Supports templating with 'openmrsBase', 'openmrsSpaBase',
|
|
29
|
+
* and any additional template parameters defined in `templateParams`.
|
|
26
30
|
* For example, `${openmrsSpaBase}/home` will resolve to `/openmrs/spa/home`
|
|
27
31
|
* for implementations using the standard OpenMRS and SPA base paths.
|
|
32
|
+
* If `templateParams` contains `{ foo: "bar" }`, then the URL `${openmrsBase}/${foo}`
|
|
33
|
+
* will become `/openmrs/bar`.
|
|
28
34
|
*/
|
|
29
|
-
export function navigate({ to }: NavigateOptions): void {
|
|
35
|
+
export function navigate({ to, templateParams }: NavigateOptions): void {
|
|
30
36
|
const openmrsSpaBase = trimTrailingSlash(window.getOpenmrsSpaBase());
|
|
31
|
-
const target = interpolateUrl(to);
|
|
37
|
+
const target = interpolateUrl(to, templateParams);
|
|
32
38
|
const isSpaPath = target.startsWith(openmrsSpaBase);
|
|
33
39
|
|
|
34
40
|
if (isSpaPath) {
|