@appsemble/utils 0.28.9 → 0.28.11

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.28.9/config/assets/logo.svg) Appsemble Utilities
1
+ # ![](https://gitlab.com/appsemble/appsemble/-/raw/0.28.11/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.28.9/pipeline.svg)](https://gitlab.com/appsemble/appsemble/-/releases/0.28.9)
6
+ [![GitLab CI](https://gitlab.com/appsemble/appsemble/badges/0.28.11/pipeline.svg)](https://gitlab.com/appsemble/appsemble/-/releases/0.28.11)
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.28.9/LICENSE.md) ©
29
+ [LGPL-3.0-only](https://gitlab.com/appsemble/appsemble/-/blob/0.28.11/LICENSE.md) ©
30
30
  [Appsemble](https://appsemble.com)
@@ -5,10 +5,8 @@ export const SubPage = {
5
5
  additionalProperties: false,
6
6
  properties: {
7
7
  name: {
8
- type: 'string',
8
+ $ref: '#/components/schemas/RemapperDefinition',
9
9
  description: 'The name of the sub page.',
10
- minLength: 1,
11
- maxLength: 50,
12
10
  },
13
11
  roles: {
14
12
  type: 'array',
@@ -0,0 +1,2 @@
1
+ import { type OpenAPIV3 } from 'openapi-types';
2
+ export declare const TabsPageActionsDefinition: OpenAPIV3.NonArraySchemaObject;
@@ -0,0 +1,12 @@
1
+ export const TabsPageActionsDefinition = {
2
+ type: 'object',
3
+ description: 'Action fired on page events',
4
+ additionalProperties: false,
5
+ properties: {
6
+ onLoad: {
7
+ $ref: '#/components/schemas/ActionDefinition',
8
+ description: '',
9
+ },
10
+ },
11
+ };
12
+ //# sourceMappingURL=TabsPageActionsDefinition.js.map
@@ -3,7 +3,14 @@ import { extendJSONSchema } from './utils.js';
3
3
  export const TabsPageDefinition = extendJSONSchema(BasePageDefinition, {
4
4
  type: 'object',
5
5
  description: 'This describes what a page will look like in the app.',
6
- required: ['type', 'tabs'],
6
+ oneOf: [
7
+ {
8
+ required: ['type', 'tabs'],
9
+ },
10
+ {
11
+ required: ['type', 'definition'],
12
+ },
13
+ ],
7
14
  additionalProperties: true,
8
15
  properties: {
9
16
  type: {
@@ -17,6 +24,23 @@ export const TabsPageDefinition = extendJSONSchema(BasePageDefinition, {
17
24
  $ref: '#/components/schemas/SubPage',
18
25
  },
19
26
  },
27
+ definition: {
28
+ type: 'object',
29
+ additionalProperties: false,
30
+ description: 'Generate tabs dynamically',
31
+ required: ['events', 'foreach'],
32
+ properties: {
33
+ events: {
34
+ $ref: '#/components/schemas/EventsDefinition',
35
+ },
36
+ foreach: {
37
+ $ref: '#/components/schemas/SubPage',
38
+ },
39
+ },
40
+ },
41
+ actions: {
42
+ $ref: '#/components/schemas/TabsPageActionsDefinition',
43
+ },
20
44
  },
21
45
  });
22
46
  //# sourceMappingURL=TabsPageDefinition.js.map
@@ -129,5 +129,6 @@ export * from './UserQueryActionDefinition.js';
129
129
  export * from './UserRemoveActionDefinition.js';
130
130
  export * from './LoopPageDefinition.js';
131
131
  export * from './LoopPageActionsDefinition.js';
132
+ export * from './TabsPageActionsDefinition.js';
132
133
  export * from './UsersDefinition.js';
133
134
  export * from './UserPropertyDefinition.js';
@@ -129,6 +129,7 @@ export * from './UserQueryActionDefinition.js';
129
129
  export * from './UserRemoveActionDefinition.js';
130
130
  export * from './LoopPageDefinition.js';
131
131
  export * from './LoopPageActionsDefinition.js';
132
+ export * from './TabsPageActionsDefinition.js';
132
133
  export * from './UsersDefinition.js';
133
134
  export * from './UserPropertyDefinition.js';
134
135
  //# sourceMappingURL=index.js.map
package/api/index.test.js CHANGED
@@ -66,6 +66,7 @@ describe('schemas', () => {
66
66
  it.each(entries.filter(([, schema]) => schema.type === 'object'))('%s', (path, schema) => {
67
67
  // Action descriptions are defined on the type property.
68
68
  const descriptionSchema = path.endsWith('ActionDefinition') ? schema.properties.type : schema;
69
+ const isTabsPageDefinition = path.endsWith('TabsPageDefinition');
69
70
  expect(schema).not.toHaveProperty('additionalItems');
70
71
  expect(schema).toHaveProperty('additionalProperties');
71
72
  expect(schema).not.toHaveProperty('allOf');
@@ -85,7 +86,10 @@ describe('schemas', () => {
85
86
  expect(schema).not.toHaveProperty('minItems');
86
87
  expect(schema).not.toHaveProperty('minLength');
87
88
  expect(schema).not.toHaveProperty('multipleOf');
88
- expect(schema).not.toHaveProperty('oneOf');
89
+ if (!isTabsPageDefinition) {
90
+ // eslint-disable-next-line vitest/no-conditional-expect
91
+ expect(schema).not.toHaveProperty('oneOf');
92
+ }
89
93
  expect(schema).not.toHaveProperty('then');
90
94
  expect(schema).not.toHaveProperty('uniqueItems');
91
95
  if (schema.required && !schema.additionalProperties) {
package/appMessages.js CHANGED
@@ -93,14 +93,16 @@ export function extractAppMessages(app, onBlock) {
93
93
  var _a, _b;
94
94
  const prefix = `pages.${normalize(page.name)}`;
95
95
  messages.app[prefix] = page.name;
96
- if (page.type === 'tabs') {
96
+ if (page.type === 'tabs' && Array.isArray(page.tabs)) {
97
97
  for (const [index, tab] of page.tabs.entries()) {
98
- messages.app[`${prefix}.tabs.${index}`] = (_a = tab.name) !== null && _a !== void 0 ? _a : '';
98
+ messages.app[`${prefix}.tabs.${index}`] =
99
+ (_a = (typeof tab.name === 'string' ? tab.name : '')) !== null && _a !== void 0 ? _a : '';
99
100
  }
100
101
  }
101
102
  if (page.type === 'flow') {
102
103
  for (const [index, step] of page.steps.entries()) {
103
- messages.app[`${prefix}.steps.${index}`] = (_b = step.name) !== null && _b !== void 0 ? _b : '';
104
+ messages.app[`${prefix}.steps.${index}`] =
105
+ (_b = (typeof step.name === 'string' ? step.name : '')) !== null && _b !== void 0 ? _b : '';
104
106
  }
105
107
  }
106
108
  if (page.type === 'loop') {
package/examples.js CHANGED
@@ -598,6 +598,12 @@ export const examples = {
598
598
  result: {},
599
599
  skip: true,
600
600
  },
601
+ 'tab.name': {
602
+ input: null,
603
+ remapper: {},
604
+ result: {},
605
+ skip: true,
606
+ },
601
607
  'string.case': {
602
608
  input: 'Patrick',
603
609
  remapper: {
package/iterApp.js CHANGED
@@ -102,7 +102,14 @@ export function iterPage(page, callbacks, prefix = []) {
102
102
  return (result ||
103
103
  (page.type === 'flow'
104
104
  ? page.steps.some((step, index) => iterBlockList(step.blocks, callbacks, [...prefix, 'steps', index, 'blocks']))
105
- : page.tabs.some((tab, index) => iterBlockList(tab.blocks, callbacks, [...prefix, 'tabs', index, 'blocks']))));
105
+ : page.tabs
106
+ ? page.tabs.some((tab, index) => iterBlockList(tab.blocks, callbacks, [...prefix, 'tabs', index, 'blocks']))
107
+ : iterBlockList(page.definition.foreach.blocks, callbacks, [
108
+ ...prefix,
109
+ 'tabs',
110
+ 0,
111
+ 'blocks',
112
+ ])));
106
113
  }
107
114
  if (page.type === 'loop') {
108
115
  let result = false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appsemble/utils",
3
- "version": "0.28.9",
3
+ "version": "0.28.11",
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.28.9",
40
+ "@appsemble/types": "0.28.11",
41
41
  "axios": "^1.0.0",
42
42
  "cron-parser": "^4.0.0",
43
43
  "date-fns": "^2.0.0",
@@ -90,6 +90,30 @@ Result:
90
90
  "title": "Most influential bands of all time",
91
91
  "content": ...
92
92
  }
93
+ \`\`\`
94
+ `,
95
+ },
96
+ 'tab.name': {
97
+ enum: [null],
98
+ description: `
99
+
100
+ Returns the name of the current tab in a \`tabs\` page.
101
+
102
+ \`\`\`yaml
103
+ name: Example Page A
104
+ type: tabs
105
+ tabs:
106
+ - name: Tab2
107
+ blocks:
108
+ - type: action-button
109
+ version: "0.27.12"
110
+ parameters:
111
+ icon: chevron-right
112
+ actions:
113
+ onClick:
114
+ type: log
115
+ remapBefore:
116
+ { tab.name: null }
93
117
  \`\`\`
94
118
  `,
95
119
  },
package/remap.d.ts CHANGED
@@ -68,6 +68,9 @@ interface InternalContext extends RemapperContext {
68
68
  stepRef?: {
69
69
  current: Record<string, any>;
70
70
  };
71
+ tabRef?: {
72
+ current: Record<string, any>;
73
+ };
71
74
  }
72
75
  export declare function remap(remapper: Remapper, input: unknown, context: InternalContext | RemapperContext): unknown;
73
76
  export {};
package/remap.js CHANGED
@@ -107,6 +107,9 @@ const mapperImplementations = {
107
107
  step(mapper, input, context) {
108
108
  return context.stepRef.current[mapper];
109
109
  },
110
+ 'tab.name'(mapper, input, context) {
111
+ return context.tabRef.current.name;
112
+ },
110
113
  gt: ([left, right], input, context) => remap(left, input, context) > remap(right, input, context),
111
114
  lt: ([left, right], input, context) => remap(left, input, context) < remap(right, input, context),
112
115
  ics(mappers, input, context) {
package/validation.js CHANGED
@@ -619,7 +619,7 @@ function validateActions(definition, report) {
619
619
  ]);
620
620
  return;
621
621
  }
622
- if (toPage.type === 'tabs' && toSub) {
622
+ if (toPage.type === 'tabs' && toSub && Array.isArray(toPage.tabs)) {
623
623
  const subPage = toPage.tabs.find(({ name }) => name === toSub);
624
624
  if (!subPage) {
625
625
  report(toSub, 'refers to a tab that doesn’t exist', [...path, 'to', 1]);
@@ -705,6 +705,21 @@ function validateEvents(definition, blockVersions, report) {
705
705
  collect([...path, 'waitFor'], action.waitFor, false);
706
706
  }
707
707
  },
708
+ onPage(page, path) {
709
+ if (!(page.type === 'tabs') || page.tabs) {
710
+ return;
711
+ }
712
+ if (page.definition.events.emit) {
713
+ for (const [prefix, name] of Object.entries(page.definition.events.emit)) {
714
+ collect([...path, 'events', 'emit', prefix], name, true);
715
+ }
716
+ }
717
+ if (page.definition.events.listen) {
718
+ for (const [prefix, name] of Object.entries(page.definition.events.listen)) {
719
+ collect([...path, 'events', 'listen', prefix], name, false);
720
+ }
721
+ }
722
+ },
708
723
  onBlock(block, path) {
709
724
  if (!block.events) {
710
725
  return;