@appsemble/utils 0.27.12 → 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.12/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.12/pipeline.svg)](https://gitlab.com/appsemble/appsemble/-/releases/0.27.12)
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.12/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
@@ -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';
@@ -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';
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
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appsemble/utils",
3
- "version": "0.27.12",
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.12",
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",
@@ -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:
package/remap.js CHANGED
@@ -245,13 +245,45 @@ const mapperImplementations = {
245
245
  return Array.isArray(input) ? input.filter((value, i) => !indices.has(i)) : [];
246
246
  },
247
247
  static: (input) => input,
248
- prop(prop, obj) {
248
+ prop(prop, obj, context) {
249
249
  let result = obj;
250
- for (const p of [prop].flat()) {
251
- 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;
252
274
  return result;
253
275
  }
254
- 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];
255
287
  }
256
288
  return result;
257
289
  },
package/remap.test.js CHANGED
@@ -888,6 +888,24 @@ describe('prop', () => {
888
888
  mappers: [{ prop: 'names' }, { prop: 0 }],
889
889
  expected: 'foo',
890
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
+ },
891
909
  'handle null': {
892
910
  input: { name: 'Spongebob' },
893
911
  mappers: { prop: null },