@appsemble/utils 0.30.14-test.6 → 0.32.1-test.14

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.
Files changed (171) hide show
  1. package/README.md +3 -3
  2. package/allActions.js +5 -3
  3. package/api/components/parameters/$orderby.js +2 -2
  4. package/api/components/parameters/index.d.ts +2 -1
  5. package/api/components/parameters/index.js +2 -1
  6. package/api/components/parameters/webhookName.d.ts +2 -0
  7. package/api/components/parameters/webhookName.js +10 -0
  8. package/api/components/parameters/webhookSecretId.d.ts +2 -0
  9. package/api/components/parameters/webhookSecretId.js +8 -0
  10. package/api/components/schemas/ActionDefinition.js +3 -0
  11. package/api/components/schemas/App.js +8 -0
  12. package/api/components/schemas/AppDefinition.js +6 -0
  13. package/api/components/schemas/AppLayoutDefinition.js +8 -0
  14. package/api/components/schemas/AppServiceSecret.js +5 -0
  15. package/api/components/schemas/AppWebhookSecret.d.ts +2 -0
  16. package/api/components/schemas/AppWebhookSecret.js +25 -0
  17. package/api/components/schemas/DialogOkActionDefinition.js +1 -1
  18. package/api/components/schemas/FilterParametersDefinition.d.ts +2 -0
  19. package/api/components/schemas/FilterParametersDefinition.js +15 -0
  20. package/api/components/schemas/FlowCancelActionDefinition.js +1 -1
  21. package/api/components/schemas/FlowFinishActionDefinition.js +1 -1
  22. package/api/components/schemas/GroupMemberDeleteActionDefinition.js +1 -1
  23. package/api/components/schemas/ResourceDefinition.js +5 -0
  24. package/api/components/schemas/ResourceDeleteAllActionDefinition.d.ts +1 -0
  25. package/api/components/schemas/ResourceDeleteAllActionDefinition.js +21 -0
  26. package/api/components/schemas/ResourceDeleteBulkActionDefinition.d.ts +1 -0
  27. package/api/components/schemas/ResourceDeleteBulkActionDefinition.js +18 -0
  28. package/api/components/schemas/ResourceGetActionDefinition.js +3 -0
  29. package/api/components/schemas/ResourcePatchActionDefinition.js +3 -0
  30. package/api/components/schemas/ResourceSubscriptionStatusActionDefinition.js +1 -0
  31. package/api/components/schemas/ResourceSubscriptionSubscribeActionDefinition.js +1 -0
  32. package/api/components/schemas/ResourceSubscriptionToggleActionDefinition.js +1 -0
  33. package/api/components/schemas/ResourceSubscriptionUnsubscribeActionDefinition.js +1 -0
  34. package/api/components/schemas/ResourceUpdatePositionsActionDefinition.d.ts +1 -0
  35. package/api/components/schemas/ResourceUpdatePositionsActionDefinition.js +21 -0
  36. package/api/components/schemas/SecurityCronDefinition.d.ts +2 -0
  37. package/api/components/schemas/SecurityCronDefinition.js +26 -0
  38. package/api/components/schemas/SecurityDefinition.js +1 -0
  39. package/api/components/schemas/StorageSubtractActionDefinition.js +2 -2
  40. package/api/components/schemas/Training.js +2 -25
  41. package/api/components/schemas/TrainingCompleted.d.ts +2 -0
  42. package/api/components/schemas/TrainingCompleted.js +17 -0
  43. package/api/components/schemas/WebhookDefinition.d.ts +2 -0
  44. package/api/components/schemas/WebhookDefinition.js +17 -0
  45. package/api/components/schemas/index.d.ts +8 -1
  46. package/api/components/schemas/index.js +8 -1
  47. package/api/components/schemas/utils.js +1 -1
  48. package/api/components/securitySchemes/index.d.ts +1 -0
  49. package/api/components/securitySchemes/index.js +1 -0
  50. package/api/components/securitySchemes/webhook.d.ts +2 -0
  51. package/api/components/securitySchemes/webhook.js +6 -0
  52. package/api/paths/apps/appId/resources/resourceType/resourceId/positions.js +54 -0
  53. package/api/paths/apps/appId/secrets/webhook/secretId.js +61 -0
  54. package/api/paths/apps/appId/secrets/webhook.js +44 -0
  55. package/api/paths/apps/appId/webhooks/webhookName.js +35 -0
  56. package/api/paths/apps/appId.js +6 -0
  57. package/api/paths/auth/email/patchPassword.js +30 -0
  58. package/api/paths/index.d.ts +7 -5
  59. package/api/paths/index.js +16 -12
  60. package/api/paths/trainings/completeTraining.js +18 -0
  61. package/api/paths/trainings/completedTrainings.d.ts +2 -0
  62. package/api/paths/trainings/completedTrainings.js +21 -0
  63. package/api/paths/trainings/trainingIds.d.ts +2 -0
  64. package/api/paths/trainings/trainingIds.js +20 -0
  65. package/api/tags/index.js +4 -4
  66. package/appMessages.js +1 -1
  67. package/assets.js +1 -1
  68. package/authorization.d.ts +1 -1
  69. package/authorization.js +1 -1
  70. package/blockUtils.d.ts +1 -1
  71. package/blockUtils.js +1 -0
  72. package/convertToCsv.js +2 -0
  73. package/examples.js +214 -4
  74. package/formatRequestAction.js +2 -2
  75. package/has.d.ts +1 -1
  76. package/has.js +1 -1
  77. package/i18n.js +6 -8
  78. package/ics.js +1 -1
  79. package/iterApp.js +3 -3
  80. package/jsonschema.js +16 -3
  81. package/package.json +15 -11
  82. package/reference-schemas/actions/appMember.d.ts +2 -0
  83. package/reference-schemas/actions/appMember.js +21 -0
  84. package/reference-schemas/actions/flow.d.ts +2 -0
  85. package/reference-schemas/actions/flow.js +13 -0
  86. package/reference-schemas/actions/group.d.ts +2 -0
  87. package/reference-schemas/actions/group.js +13 -0
  88. package/reference-schemas/actions/index.d.ts +7 -0
  89. package/reference-schemas/actions/index.js +8 -0
  90. package/reference-schemas/actions/link.d.ts +2 -0
  91. package/reference-schemas/actions/link.js +9 -0
  92. package/reference-schemas/actions/miscellaneous.d.ts +2 -0
  93. package/reference-schemas/actions/miscellaneous.js +41 -0
  94. package/reference-schemas/actions/resources.d.ts +2 -0
  95. package/reference-schemas/actions/resources.js +19 -0
  96. package/reference-schemas/actions/storage.d.ts +2 -0
  97. package/reference-schemas/actions/storage.js +15 -0
  98. package/reference-schemas/remappers/conditionals.js +39 -0
  99. package/reference-schemas/remappers/data.js +26 -2
  100. package/reference-schemas/remappers/index.d.ts +1 -0
  101. package/reference-schemas/remappers/index.js +1 -0
  102. package/reference-schemas/remappers/objects.js +32 -0
  103. package/reference-schemas/remappers/odata.d.ts +2 -0
  104. package/reference-schemas/remappers/odata.js +95 -0
  105. package/reference-schemas/remappers/strings.js +33 -0
  106. package/reference-schemas/remappers/unsorted.js +9 -0
  107. package/remap.d.ts +2 -0
  108. package/remap.js +192 -15
  109. package/serializeResource.d.ts +7 -0
  110. package/serializeResource.js +7 -0
  111. package/serverActions.d.ts +1 -1
  112. package/serverActions.js +2 -0
  113. package/theme.js +5 -1
  114. package/validateStyle.js +2 -0
  115. package/validation.js +52 -16
  116. package/api/components/parameters/trainingBlockId.d.ts +0 -2
  117. package/api/components/parameters/trainingBlockId.js +0 -8
  118. package/api/components/schemas/TrainingBlock.d.ts +0 -2
  119. package/api/components/schemas/TrainingBlock.js +0 -38
  120. package/api/components/securitySchemes/cli.test.d.ts +0 -1
  121. package/api/components/securitySchemes/cli.test.js +0 -7
  122. package/api/index.test.d.ts +0 -1
  123. package/api/index.test.js +0 -180
  124. package/api/paths/trainingBlocks/trainingBlockId.js +0 -41
  125. package/api/paths/trainings/trainingId/blocks.js +0 -51
  126. package/api/paths/trainings/trainingId/users/current.js +0 -62
  127. package/api/paths/trainings/trainingId/users.js +0 -25
  128. package/api/paths/trainings/trainingId.js +0 -85
  129. package/api/paths/trainings.js +0 -44
  130. package/appMessages.test.d.ts +0 -1
  131. package/appMessages.test.js +0 -409
  132. package/blockUtils.test.d.ts +0 -1
  133. package/blockUtils.test.js +0 -77
  134. package/constants/patterns.test.d.ts +0 -1
  135. package/constants/patterns.test.js +0 -83
  136. package/convertToCsv.test.d.ts +0 -1
  137. package/convertToCsv.test.js +0 -55
  138. package/has.test.d.ts +0 -1
  139. package/has.test.js +0 -17
  140. package/i18n.test.d.ts +0 -1
  141. package/i18n.test.js +0 -76
  142. package/iterApp.test.d.ts +0 -1
  143. package/iterApp.test.js +0 -439
  144. package/jsonschema.test.d.ts +0 -1
  145. package/jsonschema.test.js +0 -256
  146. package/mapValues.test.d.ts +0 -1
  147. package/mapValues.test.js +0 -16
  148. package/miscellaneous.test.d.ts +0 -1
  149. package/miscellaneous.test.js +0 -87
  150. package/normalize.test.d.ts +0 -1
  151. package/normalize.test.js +0 -23
  152. package/objectCache.test.d.ts +0 -1
  153. package/objectCache.test.js +0 -20
  154. package/prefix.test.d.ts +0 -1
  155. package/prefix.test.js +0 -11
  156. package/remap.test.d.ts +0 -1
  157. package/remap.test.js +0 -1387
  158. package/string.test.d.ts +0 -1
  159. package/string.test.js +0 -27
  160. package/theme.test.d.ts +0 -1
  161. package/theme.test.js +0 -91
  162. package/validateStyle.test.d.ts +0 -1
  163. package/validateStyle.test.js +0 -13
  164. package/validation.test.d.ts +0 -1
  165. package/validation.test.js +0 -3121
  166. /package/api/paths/{trainingBlocks/trainingBlockId.d.ts → apps/appId/resources/resourceType/resourceId/positions.d.ts} +0 -0
  167. /package/api/paths/{trainings/trainingId.d.ts → apps/appId/secrets/webhook/secretId.d.ts} +0 -0
  168. /package/api/paths/{trainings.d.ts → apps/appId/secrets/webhook.d.ts} +0 -0
  169. /package/api/paths/{trainings/trainingId/blocks.d.ts → apps/appId/webhooks/webhookName.d.ts} +0 -0
  170. /package/api/paths/{trainings/trainingId/users.d.ts → auth/email/patchPassword.d.ts} +0 -0
  171. /package/api/paths/trainings/{trainingId/users/current.d.ts → completeTraining.d.ts} +0 -0
package/remap.js CHANGED
@@ -1,5 +1,7 @@
1
+ import { filter, literalValues, param } from '@odata/parser';
1
2
  import { addMilliseconds, format, parse, parseISO } from 'date-fns';
2
3
  import equal from 'fast-deep-equal';
4
+ import { XMLParser } from 'fast-xml-parser';
3
5
  import { createEvent } from 'ics';
4
6
  import parseDuration from 'parse-duration';
5
7
  import { has } from './has.js';
@@ -13,6 +15,15 @@ class RemapperError extends TypeError {
13
15
  this.remapper = remapper;
14
16
  }
15
17
  }
18
+ function isPlainObject(value) {
19
+ return value != null && typeof value === 'object' && !Array.isArray(value);
20
+ }
21
+ function isEqualArray(a, b) {
22
+ if (a.length !== b.length) {
23
+ return false;
24
+ }
25
+ return a.every((val, i) => val === b[i]);
26
+ }
16
27
  export function remap(remapper, input, context) {
17
28
  if (typeof remapper === 'string' ||
18
29
  typeof remapper === 'number' ||
@@ -104,14 +115,32 @@ const mapperImplementations = {
104
115
  const [firstValue, ...otherValues] = mappers.map((mapper) => remap(mapper, input, context));
105
116
  return !otherValues.some((value) => equal(firstValue, value));
106
117
  },
118
+ or(mappers, input, context) {
119
+ const values = mappers.map((mapper) => Boolean(remap(mapper, input, context)));
120
+ return values.length > 0 ? values.includes(true) : true;
121
+ },
122
+ and(mappers, input, context) {
123
+ const values = mappers.map((mapper) => remap(mapper, input, context));
124
+ return values.every(Boolean);
125
+ },
107
126
  step(mapper, input, context) {
127
+ // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
128
+ // @ts-ignore 18048 variable is possibly undefined (strictNullChecks)
108
129
  return context.stepRef.current[mapper];
109
130
  },
110
131
  'tab.name'(mapper, input, context) {
132
+ // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
133
+ // @ts-ignore 18048 variable is possibly undefined (strictNullChecks)
111
134
  return context.tabRef.current.name;
112
135
  },
113
- gt: ([left, right], input, context) => remap(left, input, context) > remap(right, input, context),
114
- lt: ([left, right], input, context) => remap(left, input, context) < remap(right, input, context),
136
+ gt: ([left, right], input, context) =>
137
+ // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
138
+ // @ts-ignore Messed up - 2571 Object is of type 'unknown'.
139
+ remap(left, input, context) > remap(right, input, context),
140
+ lt: ([left, right], input, context) =>
141
+ // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
142
+ // @ts-ignore Messed up - 2571 Object is of type 'unknown'.
143
+ remap(left, input, context) < remap(right, input, context),
115
144
  ics(mappers, input, context) {
116
145
  let event;
117
146
  const mappedStart = remap(mappers.start, input, context);
@@ -127,10 +156,10 @@ const mapperImplementations = {
127
156
  startInputType: 'utc',
128
157
  startOutputType: 'utc',
129
158
  title: remap(mappers.title, input, context),
130
- description: remap(mappers.description, input, context),
131
- url: remap(mappers.url, input, context),
132
- location: remap(mappers.location, input, context),
133
- geo: processLocation(remap(mappers.coordinates, input, context)),
159
+ description: remap(mappers.description ?? null, input, context),
160
+ url: remap(mappers.url ?? null, input, context),
161
+ location: remap(mappers.location ?? null, input, context),
162
+ geo: processLocation(remap(mappers.coordinates ?? null, input, context)),
134
163
  productId: context.appUrl,
135
164
  };
136
165
  if ('end' in mappers) {
@@ -166,14 +195,15 @@ const mapperImplementations = {
166
195
  return remap(condition ? mappers.then : mappers.else, input, context);
167
196
  },
168
197
  match(mappers, input, context) {
169
- return (remap(mappers.find((mapper) => remap(mapper.case, input, context))?.value, input, context) ??
170
- null);
198
+ return (remap(mappers.find((mapper) => remap(mapper.case, input, context))?.value ?? null, input, context) ?? null);
171
199
  },
172
200
  'object.from': (mappers, input, context) => mapValues(mappers, (mapper) => remap(mapper, input, context)),
173
201
  'object.assign': (mappers, input, context) => ({
174
202
  ...input,
175
203
  ...mapValues(mappers, (mapper) => remap(mapper, input, context)),
176
204
  }),
205
+ // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
206
+ // @ts-ignore 2322 ... is not assignable to type (strictNullChecks)
177
207
  'object.omit'(keys, input) {
178
208
  const result = { ...input };
179
209
  for (const key of keys) {
@@ -194,6 +224,54 @@ const mapperImplementations = {
194
224
  }
195
225
  return result;
196
226
  },
227
+ 'object.compare'([remapper1, remapper2], input, context) {
228
+ const remapped1 = remap(remapper1, input, context);
229
+ const remapped2 = remap(remapper2, input, context);
230
+ function deepDiff(obj1, obj2, path = []) {
231
+ const diffs = [];
232
+ const keys = new Set([...Object.keys(obj1 || {}), ...Object.keys(obj2 || {})]);
233
+ for (const key of keys) {
234
+ const val1 = obj1?.[key];
235
+ const val2 = obj2?.[key];
236
+ const currentPath = [...path, key];
237
+ if (isPlainObject(val1) && isPlainObject(val2)) {
238
+ diffs.push(...deepDiff(val1, val2, currentPath));
239
+ }
240
+ else if (Array.isArray(val1) && Array.isArray(val2)) {
241
+ if (!isEqualArray(val1, val2)) {
242
+ diffs.push({ path: currentPath, type: 'changed', from: val1, to: val2 });
243
+ }
244
+ }
245
+ else if (!(key in obj1)) {
246
+ diffs.push({ path: currentPath, type: 'added', value: val2 });
247
+ }
248
+ else if (!(key in obj2)) {
249
+ diffs.push({ path: currentPath, type: 'removed', value: val1 });
250
+ }
251
+ else if (val1 !== val2) {
252
+ diffs.push({ path: currentPath, type: 'changed', from: val1, to: val2 });
253
+ }
254
+ }
255
+ return diffs;
256
+ }
257
+ if (!isPlainObject(remapped1) || !isPlainObject(remapped2)) {
258
+ return [];
259
+ }
260
+ return deepDiff(remapped1, remapped2);
261
+ },
262
+ 'object.explode'(property, input) {
263
+ if (!isPlainObject(input)) {
264
+ return [];
265
+ }
266
+ const { [property]: arrayValue, ...rest } = input;
267
+ if (!Array.isArray(arrayValue)) {
268
+ return [];
269
+ }
270
+ return arrayValue.map((item) => ({
271
+ ...rest,
272
+ ...item,
273
+ }));
274
+ },
197
275
  type(args, input) {
198
276
  // eslint-disable-next-line eqeqeq
199
277
  if (input === null) {
@@ -204,9 +282,17 @@ const mapperImplementations = {
204
282
  }
205
283
  return typeof input;
206
284
  },
285
+ // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
286
+ // @ts-ignore 2322 ... is not assignable to type (strictNullChecks)
207
287
  'array.map': (mapper, input, context) => input?.map((item, index) => remap(mapper, item, {
208
288
  ...context,
209
- array: { index, length: input.length, item },
289
+ array: {
290
+ index,
291
+ length: input.length,
292
+ item,
293
+ prevItem: input[index - 1],
294
+ nextItem: input[index + 1],
295
+ },
210
296
  })) ?? [],
211
297
  'array.unique'(mapper, input, context) {
212
298
  if (!Array.isArray(input)) {
@@ -216,7 +302,13 @@ const mapperImplementations = {
216
302
  ? item
217
303
  : remap(mapper, item, {
218
304
  ...context,
219
- array: { index, length: input.length, item },
305
+ array: {
306
+ index,
307
+ length: input.length,
308
+ item,
309
+ prevItem: input[index - 1],
310
+ nextItem: input[index + 1],
311
+ },
220
312
  }));
221
313
  return input.filter((value, index) => {
222
314
  for (let i = 0; i < index; i += 1) {
@@ -227,7 +319,11 @@ const mapperImplementations = {
227
319
  return true;
228
320
  });
229
321
  },
322
+ // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
323
+ // @ts-ignore 2322 ... is not assignable to type (strictNullChecks)
230
324
  array: (prop, input, context) => context.array?.[prop],
325
+ // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
326
+ // @ts-ignore 2322 ... is not assignable to type (strictNullChecks)
231
327
  'array.filter'(mapper, input, context) {
232
328
  if (!Array.isArray(input)) {
233
329
  console.error(`${input} is not an array!`);
@@ -236,11 +332,19 @@ const mapperImplementations = {
236
332
  return input?.filter((item, index) => {
237
333
  const remapped = remap(mapper, item, {
238
334
  ...context,
239
- array: { index, length: input.length, item },
335
+ array: {
336
+ index,
337
+ length: input.length,
338
+ item,
339
+ prevItem: input[index - 1],
340
+ nextItem: input[index + 1],
341
+ },
240
342
  });
241
343
  return remapped;
242
344
  });
243
345
  },
346
+ // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
347
+ // @ts-ignore 2322 ... is not assignable to type (strictNullChecks)
244
348
  'array.find'(mapper, input, context) {
245
349
  if (!Array.isArray(input)) {
246
350
  console.error(`${input} is not an array!`);
@@ -337,6 +441,8 @@ const mapperImplementations = {
337
441
  }
338
442
  return remapped;
339
443
  },
444
+ // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
445
+ // @ts-ignore 2322 ... is not assignable to type (strictNullChecks)
340
446
  'date.parse': (fmt, input) => (fmt ? parse(input, fmt, new Date()) : parseISO(input)),
341
447
  'date.now': () => new Date(),
342
448
  'date.add'(time, input) {
@@ -355,6 +461,8 @@ const mapperImplementations = {
355
461
  return args ? format(date, args) : date.toJSON();
356
462
  },
357
463
  'null.strip': (args, input) => stripNullValues(input, args || {}),
464
+ // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
465
+ // @ts-ignore 2322 ... is not assignable to type (strictNullChecks)
358
466
  'random.choice': (args, input) => Array.isArray(input) ? input[Math.floor(Math.random() * input.length)] : input,
359
467
  'random.integer'(args) {
360
468
  const min = Math.min(...args);
@@ -375,14 +483,19 @@ const mapperImplementations = {
375
483
  return result.join('');
376
484
  },
377
485
  root: (args, input, context) => context.root,
486
+ // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
487
+ // @ts-ignore 2322 ... is not assignable to type (strictNullChecks)
488
+ len: (args, input) => input?.length,
378
489
  history: (index, input, context) => context.history?.[index],
379
- 'from.history': ({ index, props }, input, context) => mapValues(props, (mapper) => remap(mapper, context.history[index], context)),
490
+ 'from.history': ({ index, props }, input, context) => mapValues(props, (mapper) => remap(mapper, context.history?.[index], context)),
380
491
  'assign.history': ({ index, props }, input, context) => ({
381
492
  ...input,
382
- ...mapValues(props, (mapper) => remap(mapper, context.history[index], context)),
493
+ ...mapValues(props, (mapper) => remap(mapper, context.history?.[index], context)),
383
494
  }),
495
+ // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
496
+ // @ts-ignore 2322 ... is not assignable to type (strictNullChecks)
384
497
  'omit.history'({ index, keys }, input, context) {
385
- const result = { ...context.history[index] };
498
+ const result = { ...context.history?.[index] };
386
499
  for (const key of keys) {
387
500
  if (Array.isArray(key)) {
388
501
  let acc = result;
@@ -410,13 +523,45 @@ const mapperImplementations = {
410
523
  }
411
524
  return input;
412
525
  },
526
+ // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
527
+ // @ts-ignore 2322 ... is not assignable to type (strictNullChecks)
528
+ 'string.startsWith'(substring, input) {
529
+ if (typeof substring === 'string') {
530
+ return input.startsWith(substring);
531
+ }
532
+ if (substring.strict || substring.strict === undefined) {
533
+ return input.startsWith(substring.substring);
534
+ }
535
+ return input.toLowerCase().startsWith(substring.substring.toLowerCase());
536
+ },
537
+ // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
538
+ // @ts-ignore 2322 ... is not assignable to type (strictNullChecks)
539
+ 'string.endsWith'(substring, input) {
540
+ if (typeof substring === 'string') {
541
+ return input.endsWith(substring);
542
+ }
543
+ if (substring.strict || substring.strict === undefined) {
544
+ return input.endsWith(substring.substring);
545
+ }
546
+ return input.toLowerCase().endsWith(substring.substring.toLowerCase());
547
+ },
548
+ // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
549
+ // @ts-ignore 2322 null is not assignable to type (strictNullChecks)
550
+ slice(sliceIndex, input) {
551
+ try {
552
+ return Array.isArray(sliceIndex) ? input.slice(...sliceIndex) : input.slice(sliceIndex);
553
+ }
554
+ catch {
555
+ return null;
556
+ }
557
+ },
413
558
  log(level, input, context) {
414
559
  console[level ?? 'info'](JSON.stringify({ input, context }, null, 2));
415
560
  return input;
416
561
  },
417
562
  'string.format'({ messageId, template, values }, input, context) {
418
563
  try {
419
- const remappedMessageId = remap(messageId, input, context);
564
+ const remappedMessageId = remap(messageId ?? null, input, context);
420
565
  const message = context.getMessage({ id: remappedMessageId, defaultMessage: template });
421
566
  return message.format(values ? mapValues(values, (val) => remap(val, input, context)) : undefined);
422
567
  }
@@ -448,5 +593,37 @@ const mapperImplementations = {
448
593
  const url = `http://${containerName}.${namespace}.svc.cluster.local/${endpoint}`;
449
594
  return url;
450
595
  },
596
+ 'filter.from'(values, input, context) {
597
+ let result = filter();
598
+ for (const [field, { comparator, type, value }] of Object.entries(values)) {
599
+ const remapped = remap(value, input, context);
600
+ const remappedDefined = remapped === undefined ? null : remapped;
601
+ const literal = type === 'String' && value != null
602
+ ? literalValues[type](remappedDefined.replaceAll("'", "''").replaceAll('\\', '\\\\'))
603
+ : literalValues[type === 'Number' ? 'Decimal' : type](remappedDefined);
604
+ result = result.field(field)[comparator](literal);
605
+ }
606
+ return String(param().filter(result)).replace(/^\$filter=/, '');
607
+ },
608
+ 'order.from'(values) {
609
+ return String(param().orderby(Object.entries(values).map(([key, order]) => ({ field: key, order })))).replace('$orderby=', '');
610
+ },
611
+ 'xml.parse'(value, input, context) {
612
+ const parser = new XMLParser({
613
+ ignoreAttributes: false,
614
+ attributeNamePrefix: '',
615
+ });
616
+ try {
617
+ return parser.parse(remap(value, input, context) || '');
618
+ }
619
+ catch (error) {
620
+ console.error(error);
621
+ return {};
622
+ }
623
+ },
624
+ defined(value, input, context) {
625
+ const remapped = remap(value, input, context);
626
+ return remapped !== undefined && remapped != null;
627
+ },
451
628
  };
452
629
  //# sourceMappingURL=remap.js.map
@@ -1,2 +1,9 @@
1
1
  import { type JsonValue } from 'type-fest';
2
+ /**
3
+ * Works on a resource on the client, for example passed from the form block
4
+ *
5
+ * @param data The resource to be serialized, optionally containing asset blobs
6
+ * @returns A FormData instance containing the resource and an array of the assets
7
+ * referenced from the resource
8
+ */
2
9
  export declare function serializeResource(data: any): FormData | JsonValue;
@@ -1,4 +1,11 @@
1
1
  import { mapValues } from './mapValues.js';
2
+ /**
3
+ * Works on a resource on the client, for example passed from the form block
4
+ *
5
+ * @param data The resource to be serialized, optionally containing asset blobs
6
+ * @returns A FormData instance containing the resource and an array of the assets
7
+ * referenced from the resource
8
+ */
2
9
  export function serializeResource(data) {
3
10
  const assets = [];
4
11
  const extractAssets = (value) => {
@@ -1,2 +1,2 @@
1
- export declare const serverActions: Set<"log" | "condition" | "each" | "email" | "noop" | "notify" | "static" | "throw" | "request" | "resource.create" | "resource.delete" | "resource.get" | "resource.patch" | "resource.query" | "resource.update">;
1
+ export declare const serverActions: Set<"log" | "condition" | "each" | "email" | "noop" | "notify" | "static" | "throw" | "request" | "resource.create" | "resource.delete" | "resource.delete.all" | "resource.delete.bulk" | "resource.get" | "resource.patch" | "resource.query" | "resource.update">;
2
2
  export type ServerActionName = typeof serverActions extends Set<infer T> ? T : never;
package/serverActions.js CHANGED
@@ -13,6 +13,8 @@ export const serverActions = new Set([
13
13
  'resource.patch',
14
14
  'resource.update',
15
15
  'resource.delete',
16
+ 'resource.delete.all',
17
+ 'resource.delete.bulk',
16
18
  'static',
17
19
  ]);
18
20
  //# sourceMappingURL=serverActions.js.map
package/theme.js CHANGED
@@ -19,7 +19,11 @@ export function mergeThemes(...themes) {
19
19
  */
20
20
  export function createThemeURL(theme) {
21
21
  const { font, ...rest } = theme;
22
- const params = new URLSearchParams({ ...rest, fontFamily: font.family, fontSource: font.source });
22
+ const params = new URLSearchParams({
23
+ ...rest,
24
+ fontFamily: font.family,
25
+ fontSource: font.source ?? '',
26
+ });
23
27
  // Sort for cacheability.
24
28
  params.sort();
25
29
  return `/bulma/0.9.3/bulma.min.css?${params}`;
package/validateStyle.js CHANGED
@@ -7,6 +7,8 @@ export class StyleValidationError extends Error {
7
7
  }
8
8
  export function validateStyle(css) {
9
9
  if (!css) {
10
+ // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
11
+ // @ts-ignore 2322 null is not assignable to type (strictNullChecks)
10
12
  return null;
11
13
  }
12
14
  try {
package/validation.js CHANGED
@@ -32,7 +32,7 @@ function validateJSONSchema(schema, prefix, report) {
32
32
  }
33
33
  }
34
34
  }
35
- for (const [key, propertySchema] of Object.entries(schema.properties)) {
35
+ for (const [key, propertySchema] of Object.entries(schema.properties ?? {})) {
36
36
  validateJSONSchema(propertySchema, [...prefix, 'properties', key], report);
37
37
  }
38
38
  }
@@ -87,7 +87,7 @@ function validateMembersSchema(definition, report) {
87
87
  if (!('type' in schema) && !('enum' in schema)) {
88
88
  report(schema, 'must define type or enum', prefix);
89
89
  }
90
- if ('reference' in propertyDefinition) {
90
+ if ('reference' in propertyDefinition && propertyDefinition.reference) {
91
91
  const { resource: resourceName } = propertyDefinition.reference;
92
92
  const resourceDefinition = definition.resources?.[resourceName];
93
93
  if (!resourceDefinition) {
@@ -134,7 +134,7 @@ function validateResourceSchemas(definition, report) {
134
134
  report(schema.type, 'must define type object', [...prefix, 'type']);
135
135
  }
136
136
  if ('properties' in schema) {
137
- for (const [propertyName, propertySchema] of Object.entries(schema.properties)) {
137
+ for (const [propertyName, propertySchema] of Object.entries(schema.properties ?? {})) {
138
138
  if (propertyName === 'id') {
139
139
  for (const [validatorKey, value] of Object.entries(propertySchema)) {
140
140
  if (validatorKey === 'description' || validatorKey === 'title') {
@@ -365,7 +365,7 @@ function validatePermissions(appDefinition, permissions, inheritedPermissions, p
365
365
  if (resourceViewPermissionPattern.test(permission)) {
366
366
  const [, resourceName, , resourceView] = permission.split(':');
367
367
  if (resourceName === 'all') {
368
- for (const [rName, resourceDefinition] of Object.entries(appDefinition.resources)) {
368
+ for (const [rName, resourceDefinition] of Object.entries(appDefinition.resources ?? {})) {
369
369
  if (!resourceDefinition.views?.[resourceView]) {
370
370
  report(appDefinition, `resource ${rName} is missing a definition for the ${resourceView} view`, [...path, 'permissions', index]);
371
371
  return;
@@ -373,7 +373,7 @@ function validatePermissions(appDefinition, permissions, inheritedPermissions, p
373
373
  }
374
374
  }
375
375
  else {
376
- if (!appDefinition.resources[resourceName]?.views?.[resourceView]) {
376
+ if (!appDefinition.resources?.[resourceName]?.views?.[resourceView]) {
377
377
  report(appDefinition, `resource ${resourceName} is missing a definition for the ${resourceView} view`, [...path, 'permissions', index]);
378
378
  return;
379
379
  }
@@ -617,7 +617,7 @@ function checkCyclicRoleInheritance(roles, name, report) {
617
617
  return true;
618
618
  }
619
619
  stack.push(role);
620
- return roles[role]?.inherits?.some(checkRoleRecursively);
620
+ return Boolean(roles[role]?.inherits?.some(checkRoleRecursively));
621
621
  };
622
622
  const duplicate = checkRoleRecursively(name);
623
623
  if (duplicate && lastChecked === name) {
@@ -634,7 +634,7 @@ function validateSecurity(definition, report) {
634
634
  const { notifications, security } = definition;
635
635
  const predefinedRoles = Object.keys(PredefinedAppRole);
636
636
  const checkRoleExists = (name, path, roles = predefinedRoles) => {
637
- if (!has(security.roles, name) && !roles.includes(name)) {
637
+ if (!has(security?.roles, name) && !roles.includes(name)) {
638
638
  report(name, 'does not exist in this app’s roles', path);
639
639
  return false;
640
640
  }
@@ -654,8 +654,8 @@ function validateSecurity(definition, report) {
654
654
  }
655
655
  return;
656
656
  }
657
- if ((!security.default || !security.roles) && !security.guest) {
658
- report(definition, 'invalid security definition. Must define either guest or roles and default', ['security']);
657
+ if ((!security.default || !security.roles) && !security.guest && !security.cron) {
658
+ report(definition, 'invalid security definition. Must define either guest or cron or roles and default', ['security']);
659
659
  return;
660
660
  }
661
661
  if (security.guest) {
@@ -677,13 +677,38 @@ function validateSecurity(definition, report) {
677
677
  validatePermissions(definition, security.guest.permissions, inheritedPermissions, possibleGuestPermissions, report, ['security', 'guest']);
678
678
  }
679
679
  }
680
+ else if (security.cron) {
681
+ if (!definition.cron) {
682
+ report(definition, 'can not define cron definition without a cron job', ['security', 'cron']);
683
+ return;
684
+ }
685
+ if (security.cron.inherits && security.cron.inherits.length && !security.roles) {
686
+ report(definition, 'cron can not inherit roles if the roles property is not defined', [
687
+ 'security',
688
+ 'cron',
689
+ 'inherits',
690
+ ]);
691
+ return;
692
+ }
693
+ const inheritedPermissions = getAppRolePermissions(security, security.cron.inherits || []);
694
+ const possibleCronPermissions = getAppPossibleGuestPermissions(definition);
695
+ if (inheritedPermissions.some((ip) => !possibleCronPermissions.includes(ip))) {
696
+ report(definition, 'invalid security definition. Guest cannot inherit roles that contain own resource permissions', ['security', 'cron', 'inherits']);
697
+ return;
698
+ }
699
+ if (security.cron.permissions) {
700
+ validatePermissions(definition, security.cron.permissions, inheritedPermissions, possibleCronPermissions, report, ['security', 'cron']);
701
+ }
702
+ }
680
703
  else {
704
+ // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
705
+ // @ts-ignore 18048 variable is possibly undefined (strictNullChecks)
681
706
  checkRoleExists(security.default.role, ['security', 'default', 'role']);
682
707
  }
683
708
  if (security.roles) {
684
709
  const possibleAppPermissions = getAppPossiblePermissions(definition);
685
710
  for (const [name, role] of Object.entries(security.roles)) {
686
- if (predefinedRoles.includes(name)) {
711
+ if ([...predefinedRoles, 'cron'].includes(name)) {
687
712
  report(definition, `not allowed to overwrite role ${name}`, ['security', 'roles', name]);
688
713
  }
689
714
  const inheritedPermissions = [];
@@ -735,7 +760,7 @@ function validateHooks(definition, report) {
735
760
  if (!has(resource, actionType)) {
736
761
  continue;
737
762
  }
738
- const tos = resource[actionType].hooks?.notification?.to;
763
+ const tos = resource[actionType]?.hooks?.notification?.to;
739
764
  if (tos) {
740
765
  for (const [index, to] of tos.entries()) {
741
766
  if (to !== '$author' && !has(definition.security?.roles, to)) {
@@ -823,6 +848,10 @@ function validateActions(definition, report) {
823
848
  report(action.type, 'action type is not supported for cron jobs', [...path, 'type']);
824
849
  return;
825
850
  }
851
+ if (path[0] === 'webhooks' && !serverActions.has(action.type)) {
852
+ report(action.type, 'action type is not supported for webhooks', [...path, 'type']);
853
+ return;
854
+ }
826
855
  if (action.type.startsWith('app.member.') && !definition.security) {
827
856
  report(action.type, 'refers to an app member action but the app doesn’t have a security definition', [...path, 'type']);
828
857
  return;
@@ -943,6 +972,8 @@ function validateActions(definition, report) {
943
972
  return;
944
973
  }
945
974
  const [toBase, toSub] = [].concat(to);
975
+ // @ts-expect-error 2345 argument of type is not assignable to parameter of type
976
+ // (strictNullChecks) - Severe
946
977
  const toPage = findPageByName(definition.pages, toBase);
947
978
  if (!toPage) {
948
979
  report(to, 'refers to a page that doesn’t exist', [...path, 'to']);
@@ -1020,8 +1051,8 @@ function validateEvents(definition, blockVersions, report) {
1020
1051
  if (action.type === 'dialog') {
1021
1052
  for (const block of action.blocks) {
1022
1053
  const versions = blockVersions.get(normalizeBlockName(block.type));
1023
- const version = versions.get(block.version);
1024
- if (version.layout === 'float') {
1054
+ const version = versions?.get(block.version);
1055
+ if (version?.layout === 'float') {
1025
1056
  report(block.version, 'block with layout type: "'
1026
1057
  .concat(version.layout)
1027
1058
  .concat('" is not allowed in a dialog action'), [...path, 'type']);
@@ -1038,7 +1069,7 @@ function validateEvents(definition, blockVersions, report) {
1038
1069
  return;
1039
1070
  }
1040
1071
  collect([...path, 'event'], action.event, true);
1041
- if ('waitFor' in action) {
1072
+ if ('waitFor' in action && action.waitFor) {
1042
1073
  collect([...path, 'waitFor'], action.waitFor, false);
1043
1074
  }
1044
1075
  },
@@ -1046,12 +1077,12 @@ function validateEvents(definition, blockVersions, report) {
1046
1077
  if (!(page.type === 'tabs') || page.tabs) {
1047
1078
  return;
1048
1079
  }
1049
- if (page.definition.events.emit) {
1080
+ if (page.definition?.events.emit) {
1050
1081
  for (const [prefix, name] of Object.entries(page.definition.events.emit)) {
1051
1082
  collect([...path, 'events', 'emit', prefix], name, true);
1052
1083
  }
1053
1084
  }
1054
- if (page.definition.events.listen) {
1085
+ if (page.definition?.events.listen) {
1055
1086
  for (const [prefix, name] of Object.entries(page.definition.events.listen)) {
1056
1087
  collect([...path, 'events', 'listen', prefix], name, false);
1057
1088
  }
@@ -1078,6 +1109,8 @@ function validateEvents(definition, blockVersions, report) {
1078
1109
  listeners: new Map(),
1079
1110
  };
1080
1111
  if (indexMap.has('controller')) {
1112
+ // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
1113
+ // @ts-ignore 2322 null is not assignable to type (strictNullChecks)
1081
1114
  controllerEvents = { ...indexMap.get('controller') };
1082
1115
  }
1083
1116
  indexMap.delete('controller');
@@ -1159,6 +1192,9 @@ export async function validateAppDefinition(definition, getBlockVersions, contro
1159
1192
  result.errors.push(new ValidationError(message, instance, undefined, path));
1160
1193
  };
1161
1194
  try {
1195
+ // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
1196
+ // @ts-ignore 2345 argument of type is not assignable to parameter of type
1197
+ // (strictNullChecks)
1162
1198
  validateController(definition, controllerImplementations, report);
1163
1199
  validateCronJobs(definition, report);
1164
1200
  validateDefaultPage(definition, report);
@@ -1,2 +0,0 @@
1
- import { type OpenAPIV3 } from 'openapi-types';
2
- export declare const trainingBlockId: OpenAPIV3.ParameterObject;
@@ -1,8 +0,0 @@
1
- export const trainingBlockId = {
2
- name: 'trainingBlockId',
3
- in: 'path',
4
- description: 'Id of the trainingBlock on which the operation will be performed.',
5
- required: true,
6
- schema: { $ref: '#/components/schemas/TrainingBlock/properties/id' },
7
- };
8
- //# sourceMappingURL=trainingBlockId.js.map
@@ -1,2 +0,0 @@
1
- import { type OpenAPIV3 } from 'openapi-types';
2
- export declare const TrainingBlock: OpenAPIV3.NonArraySchemaObject;
@@ -1,38 +0,0 @@
1
- export const TrainingBlock = {
2
- type: 'object',
3
- description: '',
4
- additionalProperties: false,
5
- properties: {
6
- id: {
7
- type: 'string',
8
- description: 'The id of the Training Block, will be generated automatically by the system.',
9
- readOnly: true,
10
- },
11
- trainingId: {
12
- type: 'number',
13
- minimum: 0,
14
- description: 'Id of the parent training.',
15
- },
16
- title: {
17
- type: 'string',
18
- description: 'Title of the training block.',
19
- },
20
- documentationLink: {
21
- type: 'string',
22
- description: 'A URL pointing to a page in the documentation.',
23
- },
24
- videoLink: {
25
- type: 'string',
26
- description: 'Link of the video associated with the training block.',
27
- },
28
- exampleCode: {
29
- type: 'string',
30
- description: 'Example code for the user to be copied.',
31
- },
32
- externalResource: {
33
- type: 'string',
34
- description: 'Link to any external resource.',
35
- },
36
- },
37
- };
38
- //# sourceMappingURL=TrainingBlock.js.map
@@ -1 +0,0 @@
1
- export {};
@@ -1,7 +0,0 @@
1
- import { expect, it } from 'vitest';
2
- import { cli } from './cli.js';
3
- import { scopes } from '../../../constants/index.js';
4
- it('should match the known scopes defined in utils', () => {
5
- expect(Object.keys(cli.flows.clientCredentials.scopes)).toStrictEqual(scopes);
6
- });
7
- //# sourceMappingURL=cli.test.js.map
@@ -1 +0,0 @@
1
- export {};