@appsemble/utils 0.27.11 → 0.28.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/README.md CHANGED
@@ -1,9 +1,9 @@
1
- # ![](https://gitlab.com/appsemble/appsemble/-/raw/0.27.11/config/assets/logo.svg) Appsemble Utilities
1
+ # ![](https://gitlab.com/appsemble/appsemble/-/raw/0.28.0/config/assets/logo.svg) Appsemble Utilities
2
2
 
3
3
  > Internal utility functions used across multiple Appsemble projects.
4
4
 
5
5
  [![npm](https://img.shields.io/npm/v/@appsemble/utils)](https://www.npmjs.com/package/@appsemble/utils)
6
- [![GitLab CI](https://gitlab.com/appsemble/appsemble/badges/0.27.11/pipeline.svg)](https://gitlab.com/appsemble/appsemble/-/releases/0.27.11)
6
+ [![GitLab CI](https://gitlab.com/appsemble/appsemble/badges/0.28.0/pipeline.svg)](https://gitlab.com/appsemble/appsemble/-/releases/0.28.0)
7
7
  [![Prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://prettier.io)
8
8
 
9
9
  ## Table of Contents
@@ -26,5 +26,5 @@ not guaranteed.
26
26
 
27
27
  ## License
28
28
 
29
- [LGPL-3.0-only](https://gitlab.com/appsemble/appsemble/-/blob/0.27.11/LICENSE.md) ©
29
+ [LGPL-3.0-only](https://gitlab.com/appsemble/appsemble/-/blob/0.28.0/LICENSE.md) ©
30
30
  [Appsemble](https://appsemble.com)
@@ -0,0 +1,2 @@
1
+ import { type OpenAPIV3 } from 'openapi-types';
2
+ export declare const appPath: OpenAPIV3.ParameterObject;
@@ -0,0 +1,8 @@
1
+ export const appPath = {
2
+ name: 'appPath',
3
+ in: 'path',
4
+ description: 'The app-path of the app on which to perform an operation',
5
+ required: true,
6
+ schema: { $ref: '#/components/schemas/App/properties/path' },
7
+ };
8
+ //# sourceMappingURL=appPath.js.map
@@ -0,0 +1,2 @@
1
+ import { type OpenAPIV3 } from 'openapi-types';
2
+ export declare const appVariableId: OpenAPIV3.ParameterObject;
@@ -0,0 +1,8 @@
1
+ export const appVariableId = {
2
+ name: 'appVariableId',
3
+ in: 'path',
4
+ description: 'The id of the app variable on which to perform an operation',
5
+ required: true,
6
+ schema: { type: 'string' },
7
+ };
8
+ //# sourceMappingURL=appVariableId.js.map
@@ -5,6 +5,7 @@ export * from './$team.js';
5
5
  export * from './$top.js';
6
6
  export * from './$skip.js';
7
7
  export * from './appId.js';
8
+ export * from './appPath.js';
8
9
  export * from './appOAuth2SecretId.js';
9
10
  export * from './appSamlSecretId.js';
10
11
  export * from './assetId.js';
@@ -18,6 +19,7 @@ export * from './resourceType.js';
18
19
  export * from './screenshotId.js';
19
20
  export * from './readmeId.js';
20
21
  export * from './appServiceId.js';
22
+ export * from './appVariableId.js';
21
23
  export * from './view.js';
22
24
  export * from './trainingId.js';
23
25
  export * from './trainingBlockId.js';
@@ -5,6 +5,7 @@ export * from './$team.js';
5
5
  export * from './$top.js';
6
6
  export * from './$skip.js';
7
7
  export * from './appId.js';
8
+ export * from './appPath.js';
8
9
  export * from './appOAuth2SecretId.js';
9
10
  export * from './appSamlSecretId.js';
10
11
  export * from './assetId.js';
@@ -18,6 +19,7 @@ export * from './resourceType.js';
18
19
  export * from './screenshotId.js';
19
20
  export * from './readmeId.js';
20
21
  export * from './appServiceId.js';
22
+ export * from './appVariableId.js';
21
23
  export * from './view.js';
22
24
  export * from './trainingId.js';
23
25
  export * from './trainingBlockId.js';
@@ -0,0 +1,2 @@
1
+ import { type OpenAPIV3 } from 'openapi-types';
2
+ export declare const AppVariable: OpenAPIV3.NonArraySchemaObject;
@@ -0,0 +1,22 @@
1
+ export const AppVariable = {
2
+ type: 'object',
3
+ description: 'App variable',
4
+ required: ['name'],
5
+ additionalProperties: false,
6
+ properties: {
7
+ id: {
8
+ type: 'number',
9
+ description: 'An autogenerated ID.',
10
+ readOnly: true,
11
+ },
12
+ name: {
13
+ type: 'string',
14
+ description: 'The name of the variable, that will be accessible from clients.',
15
+ },
16
+ value: {
17
+ description: 'The value of the variable.',
18
+ anyOf: [{ type: 'string' }, { type: 'boolean' }, { type: 'number' }],
19
+ },
20
+ },
21
+ };
22
+ //# sourceMappingURL=AppVariable.js.map
@@ -12,6 +12,7 @@ export * from './AppMessages.js';
12
12
  export * from './AppOAuth2Secret.js';
13
13
  export * from './AppsembleMessages.js';
14
14
  export * from './AppServiceSecret.js';
15
+ export * from './AppVariable.js';
15
16
  export * from './ArrayRemapperDefinition.js';
16
17
  export * from './Asset.js';
17
18
  export * from './BlockDefinition.js';
@@ -12,6 +12,7 @@ export * from './AppMessages.js';
12
12
  export * from './AppOAuth2Secret.js';
13
13
  export * from './AppsembleMessages.js';
14
14
  export * from './AppServiceSecret.js';
15
+ export * from './AppVariable.js';
15
16
  export * from './ArrayRemapperDefinition.js';
16
17
  export * from './Asset.js';
17
18
  export * from './BlockDefinition.js';
@@ -11,7 +11,7 @@ export const paths = {
11
11
  },
12
12
  },
13
13
  },
14
- security: [{ studio: [] }],
14
+ security: [{ studio: [] }, { cli: ['apps:write'] }],
15
15
  responses: {
16
16
  201: {
17
17
  description: 'A list of the OAuth2 secrets for the app.',
@@ -41,6 +41,16 @@ export const paths = {
41
41
  },
42
42
  },
43
43
  },
44
+ delete: {
45
+ tags: ['secret'],
46
+ operationId: 'deleteAppOAuth2Secrets',
47
+ security: [{ studio: [] }, { cli: ['apps:write'] }],
48
+ responses: {
49
+ 204: {
50
+ description: 'The deleted app OAuth2 secrets.',
51
+ },
52
+ },
53
+ },
44
54
  },
45
55
  '/api/apps/{appId}/secrets/oauth2/{appOAuth2SecretId}': {
46
56
  parameters: [
@@ -32,7 +32,7 @@ export const paths = {
32
32
  $ref: '#/components/schemas/SSLSecret',
33
33
  },
34
34
  },
35
- security: [{ studio: [] }],
35
+ security: [{ studio: [] }, { cli: ['apps:write'] }],
36
36
  },
37
37
  },
38
38
  };
@@ -11,7 +11,7 @@ export const paths = {
11
11
  },
12
12
  },
13
13
  },
14
- security: [{ studio: [] }],
14
+ security: [{ studio: [] }, { cli: ['apps:write'] }],
15
15
  responses: {
16
16
  201: {
17
17
  description: 'A list of the SAML secrets for the app.',
@@ -41,6 +41,16 @@ export const paths = {
41
41
  },
42
42
  },
43
43
  },
44
+ delete: {
45
+ tags: ['secret'],
46
+ operationId: 'deleteAppSamlSecrets',
47
+ security: [{ studio: [] }, { cli: ['apps:write'] }],
48
+ responses: {
49
+ 204: {
50
+ description: 'The deleted app saml secrets.',
51
+ },
52
+ },
53
+ },
44
54
  },
45
55
  '/api/apps/{appId}/secrets/saml/{appSamlSecretId}': {
46
56
  parameters: [
@@ -28,7 +28,7 @@ export const paths = {
28
28
  },
29
29
  },
30
30
  },
31
- security: [{ studio: [] }],
31
+ security: [{ studio: [] }, { cli: ['apps:write'] }],
32
32
  responses: {
33
33
  200: {
34
34
  description: 'The app SCIM configuration',
@@ -3,7 +3,7 @@ export const paths = {
3
3
  parameters: [{ $ref: '#/components/parameters/appId' }],
4
4
  post: {
5
5
  tags: ['secret'],
6
- operationId: 'addAppServiceSecret',
6
+ operationId: 'createAppServiceSecret',
7
7
  requestBody: {
8
8
  content: {
9
9
  'application/json': {
@@ -11,7 +11,7 @@ export const paths = {
11
11
  },
12
12
  },
13
13
  },
14
- security: [{ studio: [] }],
14
+ security: [{ studio: [] }, { cli: ['apps:write'] }],
15
15
  responses: {
16
16
  201: {
17
17
  description: 'The created app service secret.',
@@ -41,6 +41,16 @@ export const paths = {
41
41
  },
42
42
  },
43
43
  },
44
+ delete: {
45
+ tags: ['secret'],
46
+ operationId: 'deleteAppServiceSecrets',
47
+ security: [{ studio: [] }, { cli: ['apps:write'] }],
48
+ responses: {
49
+ 204: {
50
+ description: 'The deleted app service secrets.',
51
+ },
52
+ },
53
+ },
44
54
  },
45
55
  '/api/apps/{appId}/secrets/service/{appServiceId}': {
46
56
  parameters: [
@@ -0,0 +1,2 @@
1
+ import { type OpenAPIV3 } from 'openapi-types';
2
+ export declare const paths: OpenAPIV3.PathsObject;
@@ -0,0 +1,93 @@
1
+ export const paths = {
2
+ '/api/apps/{appId}/variables': {
3
+ parameters: [{ $ref: '#/components/parameters/appId' }],
4
+ post: {
5
+ tags: ['variable'],
6
+ operationId: 'createAppVariable',
7
+ requestBody: {
8
+ content: {
9
+ 'application/json': {
10
+ schema: { $ref: '#/components/schemas/AppVariable' },
11
+ },
12
+ },
13
+ },
14
+ security: [{ studio: [] }, { cli: ['apps:write'] }],
15
+ responses: {
16
+ 201: {
17
+ description: 'The created app variable.',
18
+ content: {
19
+ 'application/json': {
20
+ schema: { $ref: '#/components/schemas/AppVariable' },
21
+ },
22
+ },
23
+ },
24
+ },
25
+ },
26
+ get: {
27
+ tags: ['variable'],
28
+ operationId: 'getAppVariables',
29
+ responses: {
30
+ 200: {
31
+ description: 'The list of app variables.',
32
+ content: {
33
+ 'application/json': {
34
+ schema: {
35
+ type: 'array',
36
+ items: { $ref: '#/components/schemas/AppVariable' },
37
+ },
38
+ },
39
+ },
40
+ },
41
+ },
42
+ },
43
+ delete: {
44
+ tags: ['variable'],
45
+ operationId: 'deleteAppVariables',
46
+ security: [{ studio: [] }, { cli: ['apps:write'] }],
47
+ responses: {
48
+ 204: {
49
+ description: 'The deleted app variables.',
50
+ },
51
+ },
52
+ },
53
+ },
54
+ '/api/apps/{appId}/variables/{appVariableId}': {
55
+ parameters: [
56
+ { $ref: '#/components/parameters/appId' },
57
+ { $ref: '#/components/parameters/appVariableId' },
58
+ ],
59
+ put: {
60
+ tags: ['secret'],
61
+ operationId: 'updateAppVariable',
62
+ requestBody: {
63
+ content: {
64
+ 'application/json': {
65
+ schema: { $ref: '#/components/schemas/AppVariable' },
66
+ },
67
+ },
68
+ },
69
+ security: [{ studio: [] }],
70
+ responses: {
71
+ 200: {
72
+ description: 'The updated app variable.',
73
+ content: {
74
+ 'application/json': {
75
+ schema: { $ref: '#/components/schemas/AppVariable' },
76
+ },
77
+ },
78
+ },
79
+ },
80
+ },
81
+ delete: {
82
+ tags: ['secret'],
83
+ operationId: 'deleteAppVariable',
84
+ security: [{ studio: [] }],
85
+ responses: {
86
+ 204: {
87
+ description: 'The deleted app variable.',
88
+ },
89
+ },
90
+ },
91
+ },
92
+ };
93
+ //# sourceMappingURL=appVariables.js.map
package/api/paths/apps.js CHANGED
@@ -142,6 +142,28 @@ export const paths = {
142
142
  security: [{ studio: [] }, {}],
143
143
  },
144
144
  },
145
+ '/api/apps/path/{appPath}': {
146
+ parameters: [{ $ref: '#/components/parameters/appPath' }],
147
+ get: {
148
+ tags: ['app', 'app-path'],
149
+ parameters: [
150
+ {
151
+ name: 'language',
152
+ schema: { type: 'string' },
153
+ description: 'The language to include the translations of, if available',
154
+ in: 'query',
155
+ },
156
+ ],
157
+ description: 'Get an app by app-path',
158
+ operationId: 'getAppByPath',
159
+ responses: {
160
+ 200: {
161
+ description: 'The app that matches the given app path.',
162
+ $ref: '#/components/responses/app',
163
+ },
164
+ },
165
+ },
166
+ },
145
167
  '/api/apps/{appId}': {
146
168
  parameters: [{ $ref: '#/components/parameters/appId' }],
147
169
  get: {
@@ -340,7 +362,7 @@ export const paths = {
340
362
  parameters: [{ $ref: '#/components/parameters/appId' }],
341
363
  get: {
342
364
  tags: ['app', 'export', 'zip'],
343
- description: 'Export the app',
365
+ description: 'Export an app as a zip file',
344
366
  operationId: 'exportApp',
345
367
  parameters: [
346
368
  {
@@ -10,6 +10,7 @@ import { paths as appScimSecrets } from './appScimSecrets.js';
10
10
  import { paths as appsembleMessages } from './appsembleMessages.js';
11
11
  import { paths as appServiceSecrets } from './appServiceSecrets.js';
12
12
  import { paths as appSSLSecrets } from './appSSLSecrets.js';
13
+ import { paths as appVariables } from './appVariables.js';
13
14
  import { paths as assets } from './assets.js';
14
15
  import { paths as blocks } from './blocks.js';
15
16
  import { paths as emails } from './emails.js';
@@ -33,6 +34,7 @@ export const paths = {
33
34
  ...scimEndpoints,
34
35
  ...appsembleMessages,
35
36
  ...appSSLSecrets,
37
+ ...appVariables,
36
38
  ...appCollections,
37
39
  ...appQuotas,
38
40
  ...assets,
@@ -68,6 +68,14 @@ export const paths = {
68
68
  type: 'boolean',
69
69
  description: 'Include example assets.',
70
70
  },
71
+ variables: {
72
+ type: 'boolean',
73
+ description: 'Include example variables.',
74
+ },
75
+ secrets: {
76
+ type: 'boolean',
77
+ description: 'Include example secrets.',
78
+ },
71
79
  visibility: {
72
80
  $ref: '#/components/schemas/App/properties/visibility',
73
81
  },
package/examples.js CHANGED
@@ -279,6 +279,12 @@ export const examples = {
279
279
  result: {},
280
280
  skip: true,
281
281
  },
282
+ variable: {
283
+ input: null,
284
+ remapper: {},
285
+ result: {},
286
+ skip: true,
287
+ },
282
288
  'date.add': {
283
289
  input: '2023-06-30T14:50:19.601Z',
284
290
  remapper: [
@@ -649,6 +655,7 @@ export function schemaExample(remapper, options) {
649
655
  export function createExampleContext(url, lang, userInfo, history) {
650
656
  return {
651
657
  getMessage: ({ defaultMessage }) => new IntlMessageFormat(defaultMessage, lang, undefined),
658
+ getVariable: () => null,
652
659
  url: String(url),
653
660
  appUrl: `${url.protocol}//example-app.example-organization.${url.host}`,
654
661
  userInfo: userInfo !== null && userInfo !== void 0 ? userInfo : {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appsemble/utils",
3
- "version": "0.27.11",
3
+ "version": "0.28.0",
4
4
  "description": "Utility functions used in Appsemble internally",
5
5
  "keywords": [
6
6
  "app",
@@ -37,7 +37,7 @@
37
37
  "test": "vitest"
38
38
  },
39
39
  "dependencies": {
40
- "@appsemble/types": "0.27.11",
40
+ "@appsemble/types": "0.28.0",
41
41
  "axios": "^1.0.0",
42
42
  "cron-parser": "^4.0.0",
43
43
  "date-fns": "^2.0.0",
@@ -0,0 +1,2 @@
1
+ import { type OpenAPIV3 } from 'openapi-types';
2
+ export declare const configRemappers: Record<string, OpenAPIV3.ReferenceObject | OpenAPIV3.SchemaObject>;
@@ -0,0 +1,7 @@
1
+ export const configRemappers = {
2
+ variable: {
3
+ type: 'string',
4
+ description: 'Get a predefined app variable by name',
5
+ },
6
+ };
7
+ //# sourceMappingURL=config.js.map
@@ -203,6 +203,12 @@ The result of the final page’s log would then be:
203
203
  { type: 'string' },
204
204
  { type: 'integer' },
205
205
  { type: 'array', minItems: 1, items: { anyOf: [{ type: 'string' }, { type: 'integer' }] } },
206
+ {
207
+ type: 'array',
208
+ minItems: 1,
209
+ items: { $ref: '#/components/schemas/ObjectRemapperDefinition' },
210
+ },
211
+ { $ref: '#/components/schemas/ObjectRemapperDefinition' },
206
212
  ],
207
213
  description: `Gets the chosen property from an object.
208
214
 
@@ -26,7 +26,12 @@ ${schemaExample('date.add')}
26
26
  `,
27
27
  },
28
28
  'date.format': {
29
- enum: ['string', null],
29
+ oneOf: [
30
+ { enum: [null] },
31
+ {
32
+ type: 'string',
33
+ },
34
+ ],
30
35
  description: `Format a date according to the RFC3339 format.
31
36
 
32
37
  Here is an example of a RFC3339 complicit date:
@@ -7,3 +7,4 @@ export * from './objects.js';
7
7
  export * from './randoms.js';
8
8
  export * from './strings.js';
9
9
  export * from './unsorted.js';
10
+ export * from './config.js';
@@ -7,4 +7,5 @@ export * from './objects.js';
7
7
  export * from './randoms.js';
8
8
  export * from './strings.js';
9
9
  export * from './unsorted.js';
10
+ export * from './config.js';
10
11
  //# sourceMappingURL=index.js.map
package/remap.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type AppMember, type Remapper, type UserInfo } from '@appsemble/types';
1
+ import { type AppMember, type Remapper, type UserInfo, type ValueFromProcess } from '@appsemble/types';
2
2
  import { type IntlMessageFormat } from 'intl-messageformat';
3
3
  export interface IntlMessage {
4
4
  id?: string;
@@ -11,6 +11,7 @@ export interface IntlMessage {
11
11
  * @returns A message format instance.
12
12
  */
13
13
  export type MessageGetter = (msg: IntlMessage) => IntlMessageFormat;
14
+ export type AppConfigEntryGetter = (name: string) => ValueFromProcess;
14
15
  export interface RemapperContext {
15
16
  /**
16
17
  * The id of the app whose context the remapper is run in.
@@ -28,6 +29,10 @@ export interface RemapperContext {
28
29
  * @see MessageGetter
29
30
  */
30
31
  getMessage: MessageGetter;
32
+ /**
33
+ * @see VariableGetter
34
+ */
35
+ getVariable: AppConfigEntryGetter;
31
36
  /**
32
37
  * The history stack containing the states before an action was called.
33
38
  */
package/remap.js CHANGED
@@ -84,6 +84,12 @@ const mapperImplementations = {
84
84
  }
85
85
  return result !== null && result !== void 0 ? result : null;
86
86
  },
87
+ variable(name, input, context) {
88
+ if (context.getVariable) {
89
+ return context.getVariable(name);
90
+ }
91
+ return { variable: name };
92
+ },
87
93
  equals(mappers, input, context) {
88
94
  if (mappers.length <= 1) {
89
95
  return true;
@@ -239,13 +245,45 @@ const mapperImplementations = {
239
245
  return Array.isArray(input) ? input.filter((value, i) => !indices.has(i)) : [];
240
246
  },
241
247
  static: (input) => input,
242
- prop(prop, obj) {
248
+ prop(prop, obj, context) {
243
249
  let result = obj;
244
- for (const p of [prop].flat()) {
245
- if (result == null) {
250
+ if (result == null) {
251
+ return result;
252
+ }
253
+ if (Array.isArray(prop)) {
254
+ if (prop.every((item) => typeof item === 'number' || typeof item === 'string')) {
255
+ // This runs if the provided value is an array of property names or indexes
256
+ for (const p of [prop].flat()) {
257
+ result = result[p];
258
+ }
259
+ }
260
+ else if (prop.every((item) => typeof item === 'object' && !Array.isArray(item))) {
261
+ // This runs if the provided value is an array of remappers
262
+ const remapped = remap(prop, obj, context);
263
+ if (typeof remapped === 'number' || typeof remapped === 'string') {
264
+ result = result[remapped];
265
+ }
266
+ else {
267
+ console.error(`Invalid remapper ${JSON.stringify(prop)}`);
268
+ }
269
+ }
270
+ }
271
+ else if (typeof prop === 'object') {
272
+ if (prop == null) {
273
+ result = result.null;
246
274
  return result;
247
275
  }
248
- result = result[p];
276
+ // This runs if the provided value is a remapper
277
+ const remapped = remap(prop, result, context);
278
+ if (typeof remapped === 'number' || typeof remapped === 'string') {
279
+ result = result[remapped];
280
+ }
281
+ else {
282
+ console.error(`Invalid remapper ${JSON.stringify(prop)}`);
283
+ }
284
+ }
285
+ else if (typeof prop === 'number' || typeof prop === 'string') {
286
+ result = result[prop];
249
287
  }
250
288
  return result;
251
289
  },
package/remap.test.js CHANGED
@@ -3,9 +3,10 @@ import { beforeEach, describe, expect, it, vi } from 'vitest';
3
3
  import { createExampleContext, examples } from './examples.js';
4
4
  import { remap } from './remap.js';
5
5
  function runTests(tests) {
6
- it.each(Object.entries(tests))('should %s', (name, { context, expected, history, input, mappers, messages, userInfo }) => {
6
+ it.each(Object.entries(tests))('should %s', (name, { context, expected, history, input, mappers, messages, userInfo, variables }) => {
7
7
  const result = remap(mappers, input, {
8
8
  getMessage: ({ defaultMessage, id }) => { var _a, _b; return new IntlMessageFormat((_b = (_a = messages === null || messages === void 0 ? void 0 : messages.messageIds) === null || _a === void 0 ? void 0 : _a[id]) !== null && _b !== void 0 ? _b : defaultMessage); },
9
+ getVariable: (variableName) => { var _a; return (_a = variables.find((variable) => variable.name === variableName)) === null || _a === void 0 ? void 0 : _a.value; },
9
10
  url: 'https://example.com/en/example',
10
11
  appUrl: 'https://example.com',
11
12
  userInfo,
@@ -120,6 +121,22 @@ describe('context', () => {
120
121
  },
121
122
  });
122
123
  });
124
+ describe('variable', () => {
125
+ runTests({
126
+ 'get a variable': {
127
+ input: {},
128
+ mappers: { variable: 'my-variable' },
129
+ expected: 'my-variable-value',
130
+ variables: [{ id: 0, name: 'my-variable', value: 'my-variable-value' }],
131
+ },
132
+ 'get an undefined variable': {
133
+ input: {},
134
+ mappers: { variable: 'my-variable' },
135
+ expected: undefined,
136
+ variables: [],
137
+ },
138
+ });
139
+ });
123
140
  describe('date.now', () => {
124
141
  beforeEach(() => {
125
142
  vi.useFakeTimers({ now: 0 });
@@ -210,7 +227,7 @@ describe('log', () => {
210
227
  vi.spyOn(console, 'warn').mockImplementation(null);
211
228
  });
212
229
  function runLogTests(tests) {
213
- it.each(Object.entries(tests))('should %s', (name, { context, expected: expectedInput, history, input, mappers, messages, userInfo }) => {
230
+ it.each(Object.entries(tests))('should %s', (name, { context, expected: expectedInput, history, input, mappers, messages, userInfo, variables, }) => {
214
231
  const expected = JSON.stringify({
215
232
  input: expectedInput,
216
233
  context: {
@@ -228,6 +245,7 @@ describe('log', () => {
228
245
  }, null, 2);
229
246
  remap(mappers, input, {
230
247
  getMessage: ({ defaultMessage, id }) => { var _a, _b; return new IntlMessageFormat((_b = (_a = messages === null || messages === void 0 ? void 0 : messages.messageIds) === null || _a === void 0 ? void 0 : _a[id]) !== null && _b !== void 0 ? _b : defaultMessage); },
248
+ getVariable: (variableName) => variables.find((variable) => variable.name === variableName).value,
231
249
  url: 'https://example.com/en/example',
232
250
  appUrl: 'https://example.com',
233
251
  userInfo,
@@ -870,6 +888,24 @@ describe('prop', () => {
870
888
  mappers: [{ prop: 'names' }, { prop: 0 }],
871
889
  expected: 'foo',
872
890
  },
891
+ 'handle a single remapper': {
892
+ input: { en: 'English', nl: 'Dutch' },
893
+ mappers: [{ prop: { app: 'locale' } }],
894
+ expected: 'English',
895
+ },
896
+ 'handle an array of remappers': {
897
+ input: { address: { town: 'Bikini Bottom' } },
898
+ mappers: [{ prop: [{ 'object.from': { prop: 'address' } }, { prop: 'prop' }] }],
899
+ expected: { town: 'Bikini Bottom' },
900
+ },
901
+ 'handle an array of remappers with numbers': {
902
+ input: { languages: ['English', 'Dutch'] },
903
+ mappers: [
904
+ { prop: [{ 'object.from': { prop: 'languages' } }, { prop: 'prop' }] },
905
+ { prop: 0 },
906
+ ],
907
+ expected: 'English',
908
+ },
873
909
  'handle null': {
874
910
  input: { name: 'Spongebob' },
875
911
  mappers: { prop: null },