@appsemble/utils 0.24.9 → 0.24.12

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/miscellaneous.js CHANGED
@@ -30,6 +30,9 @@ export function stripNullValues(value, { depth = Number.POSITIVE_INFINITY, ...op
30
30
  if (typeof value !== 'object') {
31
31
  return value;
32
32
  }
33
+ if (value instanceof Blob) {
34
+ return value;
35
+ }
33
36
  if (depth <= 0) {
34
37
  return value;
35
38
  }
@@ -36,6 +36,18 @@ describe('stripNullValues', () => {
36
36
  const input = [, undefined, null];
37
37
  expect(stripNullValues(input)).toStrictEqual([]);
38
38
  });
39
+ it('should not remove Blob values', () => {
40
+ const blob = new Blob([], { type: 'image/jpeg' });
41
+ const input = {
42
+ foo: null,
43
+ bar: blob,
44
+ baz: 'hello',
45
+ };
46
+ expect(stripNullValues(input)).toStrictEqual({
47
+ bar: blob,
48
+ baz: 'hello',
49
+ });
50
+ });
39
51
  it('should remove undefined, and null values from objects', () => {
40
52
  const input = {
41
53
  foo: null,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appsemble/utils",
3
- "version": "0.24.9",
3
+ "version": "0.24.12",
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.24.9",
40
+ "@appsemble/types": "0.24.12",
41
41
  "axios": "^1.0.0",
42
42
  "cron-parser": "^4.0.0",
43
43
  "date-fns": "^2.0.0",
@@ -361,6 +361,32 @@ Example:
361
361
  "sub": "5c6270e2-ad31-414f-bcab-6752a2c4dcfd",
362
362
  "properties": {}
363
363
  }
364
+ \`\`\`
365
+ `,
366
+ },
367
+ appMember: {
368
+ enum: ['userId', 'memberId', 'name', 'primary_email', 'role'],
369
+ description: `
370
+ > **Note:** For this remapper to work, the user that activated the remapper has to be logged in to
371
+ > the app
372
+
373
+ Provides some fields of the appMember object.
374
+
375
+ - \`userId\`: The id of the user to which the appMember object belongs.
376
+ - \`memberId\`: The id of the appMember object itself. This value should be used when fetching resources created by the current user.
377
+ - \`primary_email\`: User’s **primary** email address.
378
+ - \`name\`: The user’s name.
379
+ - \`role\`: User's role in the context of the app.
380
+ Example:
381
+
382
+ \`\`\`json
383
+ {
384
+ "memberId": "1f433c7a-54ea-466e-89f7-5dbb8f324b12",
385
+ "name": "Test User"
386
+ "primaryEmail": "example@hotmail.nl",
387
+ "role": "Medewerker",
388
+ "userId": "5c6270e2-ad31-414f-bcab-6752a2c4dcfd"
389
+ }
364
390
  \`\`\`
365
391
  `,
366
392
  },
package/remap.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type Remapper, type UserInfo } from '@appsemble/types';
1
+ import { type AppMember, type Remapper, type UserInfo } from '@appsemble/types';
2
2
  import { type IntlMessageFormat } from 'intl-messageformat';
3
3
  export interface IntlMessage {
4
4
  id?: string;
@@ -48,6 +48,10 @@ export interface RemapperContext {
48
48
  * A custom context passed to the remap function.
49
49
  */
50
50
  context: Record<string, any>;
51
+ /**
52
+ * The appMember object for the current user in the app.
53
+ */
54
+ appMember: AppMember;
51
55
  }
52
56
  interface InternalContext extends RemapperContext {
53
57
  root?: unknown;
package/remap.js CHANGED
@@ -347,5 +347,6 @@ const mapperImplementations = {
347
347
  return message.format() || `{${messageId}}`;
348
348
  },
349
349
  user: (property, input, context) => { var _a; return (_a = context.userInfo) === null || _a === void 0 ? void 0 : _a[property]; },
350
+ appMember: (property, input, context) => { var _a, _b; return (_b = (_a = context.userInfo) === null || _a === void 0 ? void 0 : _a.appMember) === null || _b === void 0 ? void 0 : _b[property]; },
350
351
  };
351
352
  //# sourceMappingURL=remap.js.map
package/remap.test.js CHANGED
@@ -13,6 +13,7 @@ function runTests(tests) {
13
13
  appId: 6789,
14
14
  locale: 'en',
15
15
  pageData: { hello: 'Page data' },
16
+ appMember: userInfo === null || userInfo === void 0 ? void 0 : userInfo.appMember,
16
17
  });
17
18
  expect(result).toStrictEqual(expected);
18
19
  });
@@ -234,6 +235,7 @@ describe('log', () => {
234
235
  appId: 6789,
235
236
  locale: 'en',
236
237
  pageData: { hello: 'Page data' },
238
+ appMember: userInfo === null || userInfo === void 0 ? void 0 : userInfo.appMember,
237
239
  });
238
240
  expect(console[mappers.log]).toHaveBeenCalledWith(expected);
239
241
  });
package/validation.js CHANGED
@@ -76,6 +76,19 @@ function validateResourceSchemas(definition, report) {
76
76
  }
77
77
  const { schema } = resource;
78
78
  const prefix = ['resources', resourceName, 'schema'];
79
+ const reservedKeywords = new Set([
80
+ 'created',
81
+ 'updated',
82
+ 'author',
83
+ 'editor',
84
+ 'seed',
85
+ 'ephemeral',
86
+ 'clonable',
87
+ 'expires',
88
+ ]);
89
+ if (reservedKeywords.has(resourceName)) {
90
+ report(schema, 'is a reserved keyword', ['resources', resourceName]);
91
+ }
79
92
  validateJSONSchema(schema, prefix, report);
80
93
  if (!('type' in schema)) {
81
94
  report(schema, 'must define type object', prefix);
@@ -866,6 +866,96 @@ describe('validateAppDefinition', () => {
866
866
  new ValidationError('does not exist in this app’s roles', 'Unknown', undefined, ['roles', 0]),
867
867
  ]);
868
868
  });
869
+ it('should validate resource types against reserved keywords', async () => {
870
+ const app = {
871
+ name: 'Test app',
872
+ defaultPage: 'Test Page',
873
+ pages: [
874
+ {
875
+ name: 'Test Page',
876
+ blocks: [],
877
+ },
878
+ ],
879
+ resources: {
880
+ created: {
881
+ schema: {
882
+ type: 'object',
883
+ properties: {
884
+ name: { type: 'string' },
885
+ },
886
+ },
887
+ },
888
+ updated: {
889
+ schema: {
890
+ type: 'object',
891
+ properties: {
892
+ name: { type: 'string' },
893
+ },
894
+ },
895
+ },
896
+ author: {
897
+ schema: {
898
+ type: 'object',
899
+ properties: {
900
+ name: { type: 'string' },
901
+ },
902
+ },
903
+ },
904
+ editor: {
905
+ schema: {
906
+ type: 'object',
907
+ properties: {
908
+ name: { type: 'string' },
909
+ },
910
+ },
911
+ },
912
+ seed: {
913
+ schema: {
914
+ type: 'object',
915
+ properties: {
916
+ name: { type: 'string' },
917
+ },
918
+ },
919
+ },
920
+ ephemeral: {
921
+ schema: {
922
+ type: 'object',
923
+ properties: {
924
+ name: { type: 'string' },
925
+ },
926
+ },
927
+ },
928
+ clonable: {
929
+ schema: {
930
+ type: 'object',
931
+ properties: {
932
+ name: { type: 'string' },
933
+ },
934
+ },
935
+ },
936
+ expires: {
937
+ schema: {
938
+ type: 'object',
939
+ properties: {
940
+ name: { type: 'string' },
941
+ },
942
+ },
943
+ },
944
+ },
945
+ };
946
+ const result = await validateAppDefinition(app, () => []);
947
+ expect(result.valid).toBe(false);
948
+ expect(result.errors).toStrictEqual([
949
+ new ValidationError('is a reserved keyword', { type: 'object', properties: { name: { type: 'string' } } }, undefined, ['resources', 'created']),
950
+ new ValidationError('is a reserved keyword', { type: 'object', properties: { name: { type: 'string' } } }, undefined, ['resources', 'updated']),
951
+ new ValidationError('is a reserved keyword', { type: 'object', properties: { name: { type: 'string' } } }, undefined, ['resources', 'author']),
952
+ new ValidationError('is a reserved keyword', { type: 'object', properties: { name: { type: 'string' } } }, undefined, ['resources', 'editor']),
953
+ new ValidationError('is a reserved keyword', { type: 'object', properties: { name: { type: 'string' } } }, undefined, ['resources', 'seed']),
954
+ new ValidationError('is a reserved keyword', { type: 'object', properties: { name: { type: 'string' } } }, undefined, ['resources', 'ephemeral']),
955
+ new ValidationError('is a reserved keyword', { type: 'object', properties: { name: { type: 'string' } } }, undefined, ['resources', 'clonable']),
956
+ new ValidationError('is a reserved keyword', { type: 'object', properties: { name: { type: 'string' } } }, undefined, ['resources', 'expires']),
957
+ ]);
958
+ });
869
959
  it('should validate the resource roles exist', async () => {
870
960
  const app = createTestApp();
871
961
  app.resources.person.roles = ['Unknown'];