@appsemble/utils 0.20.28 → 0.20.29
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 +4 -4
- package/api/components/schemas/AppDefinition.js +1 -0
- package/api/components/schemas/LoopPageActionsDefinition.d.ts +2 -0
- package/api/components/schemas/LoopPageActionsDefinition.js +24 -0
- package/api/components/schemas/LoopPageDefinition.d.ts +1 -0
- package/api/components/schemas/LoopPageDefinition.js +38 -0
- package/api/components/schemas/ObjectRemapperDefinition.js +4 -0
- package/api/components/schemas/index.d.ts +2 -0
- package/api/components/schemas/index.js +2 -0
- package/appMessages.js +4 -1
- package/iterApp.js +3 -0
- package/package.json +2 -2
- package/remap.d.ts +3 -0
- package/remap.js +3 -0
- package/validation.js +7 -7
- package/validation.test.js +1 -1
- package/api/components/index.js.map +0 -1
- package/api/components/index.ts +0 -15
- package/api/components/parameters/$filter.js.map +0 -1
- package/api/components/parameters/$filter.ts +0 -12
- package/api/components/parameters/$orderby.js.map +0 -1
- package/api/components/parameters/$orderby.ts +0 -12
- package/api/components/parameters/$select.js.map +0 -1
- package/api/components/parameters/$select.ts +0 -15
- package/api/components/parameters/$team.js.map +0 -1
- package/api/components/parameters/$team.ts +0 -11
- package/api/components/parameters/$top.js.map +0 -1
- package/api/components/parameters/$top.ts +0 -9
- package/api/components/parameters/appId.js.map +0 -1
- package/api/components/parameters/appId.ts +0 -9
- package/api/components/parameters/appOAuth2SecretId.js.map +0 -1
- package/api/components/parameters/appOAuth2SecretId.ts +0 -9
- package/api/components/parameters/appSamlSecretId.js.map +0 -1
- package/api/components/parameters/appSamlSecretId.ts +0 -12
- package/api/components/parameters/assetId.js.map +0 -1
- package/api/components/parameters/assetId.ts +0 -9
- package/api/components/parameters/blockId.js.map +0 -1
- package/api/components/parameters/blockId.ts +0 -15
- package/api/components/parameters/blockVersion.js.map +0 -1
- package/api/components/parameters/blockVersion.ts +0 -9
- package/api/components/parameters/endpoint.js.map +0 -1
- package/api/components/parameters/endpoint.ts +0 -9
- package/api/components/parameters/index.js.map +0 -1
- package/api/components/parameters/index.ts +0 -18
- package/api/components/parameters/language.js.map +0 -1
- package/api/components/parameters/language.ts +0 -9
- package/api/components/parameters/organizationId.js.map +0 -1
- package/api/components/parameters/organizationId.ts +0 -9
- package/api/components/parameters/resourceId.js.map +0 -1
- package/api/components/parameters/resourceId.ts +0 -9
- package/api/components/parameters/resourceType.js.map +0 -1
- package/api/components/parameters/resourceType.ts +0 -11
- package/api/components/parameters/screenshotId.js.map +0 -1
- package/api/components/parameters/screenshotId.ts +0 -9
- package/api/components/parameters/view.js.map +0 -1
- package/api/components/parameters/view.ts +0 -8
- package/api/components/requestBodies/index.js.map +0 -1
- package/api/components/requestBodies/index.ts +0 -3
- package/api/components/requestBodies/oauth2Consent.js.map +0 -1
- package/api/components/requestBodies/oauth2Consent.ts +0 -31
- package/api/components/requestBodies/resource.js.map +0 -1
- package/api/components/requestBodies/resource.ts +0 -31
- package/api/components/requestBodies/user.js.map +0 -1
- package/api/components/requestBodies/user.ts +0 -12
- package/api/components/responses/app.js.map +0 -1
- package/api/components/responses/app.ts +0 -12
- package/api/components/responses/blockVersion.js.map +0 -1
- package/api/components/responses/blockVersion.ts +0 -12
- package/api/components/responses/default.js.map +0 -1
- package/api/components/responses/default.ts +0 -10
- package/api/components/responses/index.js.map +0 -1
- package/api/components/responses/index.ts +0 -8
- package/api/components/responses/invite.js.map +0 -1
- package/api/components/responses/invite.ts +0 -12
- package/api/components/responses/oauth2AuthorizationCode.js.map +0 -1
- package/api/components/responses/oauth2AuthorizationCode.ts +0 -12
- package/api/components/responses/organization.js.map +0 -1
- package/api/components/responses/organization.ts +0 -12
- package/api/components/responses/resource.js.map +0 -1
- package/api/components/responses/resource.ts +0 -17
- package/api/components/responses/subscriptions.js.map +0 -1
- package/api/components/responses/subscriptions.ts +0 -16
- package/api/components/schemas/ActionDefinition.js.map +0 -1
- package/api/components/schemas/ActionDefinition.ts +0 -82
- package/api/components/schemas/AnalyticsActionDefinition.js.map +0 -1
- package/api/components/schemas/AnalyticsActionDefinition.ts +0 -25
- package/api/components/schemas/App.js.map +0 -1
- package/api/components/schemas/App.ts +0 -107
- package/api/components/schemas/AppAccount.js.map +0 -1
- package/api/components/schemas/AppAccount.ts +0 -39
- package/api/components/schemas/AppDefinition.js.map +0 -1
- package/api/components/schemas/AppDefinition.ts +0 -112
- package/api/components/schemas/AppLayoutDefinition.js.map +0 -1
- package/api/components/schemas/AppLayoutDefinition.ts +0 -39
- package/api/components/schemas/AppMessages.js.map +0 -1
- package/api/components/schemas/AppMessages.ts +0 -17
- package/api/components/schemas/AppOAuth2Secret.js.map +0 -1
- package/api/components/schemas/AppOAuth2Secret.ts +0 -65
- package/api/components/schemas/AppsembleMessages.js.map +0 -1
- package/api/components/schemas/AppsembleMessages.ts +0 -41
- package/api/components/schemas/Asset.js.map +0 -1
- package/api/components/schemas/Asset.ts +0 -33
- package/api/components/schemas/BaseActionDefinition.js.map +0 -1
- package/api/components/schemas/BaseActionDefinition.ts +0 -11
- package/api/components/schemas/BaseJSONSchema.js.map +0 -1
- package/api/components/schemas/BaseJSONSchema.ts +0 -25
- package/api/components/schemas/BasePageDefinition.js.map +0 -1
- package/api/components/schemas/BasePageDefinition.ts +0 -89
- package/api/components/schemas/BlockDefinition.js.map +0 -1
- package/api/components/schemas/BlockDefinition.ts +0 -86
- package/api/components/schemas/BlockVersion.js.map +0 -1
- package/api/components/schemas/BlockVersion.ts +0 -162
- package/api/components/schemas/ConditionActionDefinition.js.map +0 -1
- package/api/components/schemas/ConditionActionDefinition.ts +0 -30
- package/api/components/schemas/CronDefinition.js.map +0 -1
- package/api/components/schemas/CronDefinition.ts +0 -21
- package/api/components/schemas/CustomFontDefinition.js.map +0 -1
- package/api/components/schemas/CustomFontDefinition.ts +0 -21
- package/api/components/schemas/DialogActionDefinition.js.map +0 -1
- package/api/components/schemas/DialogActionDefinition.ts +0 -42
- package/api/components/schemas/DialogErrorActionDefinition.js.map +0 -1
- package/api/components/schemas/DialogErrorActionDefinition.ts +0 -17
- package/api/components/schemas/DialogOkActionDefinition.js.map +0 -1
- package/api/components/schemas/DialogOkActionDefinition.ts +0 -17
- package/api/components/schemas/DownloadActionDefinition.js.map +0 -1
- package/api/components/schemas/DownloadActionDefinition.ts +0 -19
- package/api/components/schemas/EachActionDefinition.js.map +0 -1
- package/api/components/schemas/EachActionDefinition.ts +0 -22
- package/api/components/schemas/EmailActionDefinition.js.map +0 -1
- package/api/components/schemas/EmailActionDefinition.ts +0 -58
- package/api/components/schemas/Error.js.map +0 -1
- package/api/components/schemas/Error.ts +0 -25
- package/api/components/schemas/EventActionDefinition.js.map +0 -1
- package/api/components/schemas/EventActionDefinition.ts +0 -28
- package/api/components/schemas/EventsDefinition.js.map +0 -1
- package/api/components/schemas/EventsDefinition.ts +0 -30
- package/api/components/schemas/FlowBackActionDefinition.js.map +0 -1
- package/api/components/schemas/FlowBackActionDefinition.ts +0 -16
- package/api/components/schemas/FlowFinishActionDefinition.js.map +0 -1
- package/api/components/schemas/FlowFinishActionDefinition.ts +0 -16
- package/api/components/schemas/FlowNextActionDefinition.js.map +0 -1
- package/api/components/schemas/FlowNextActionDefinition.ts +0 -17
- package/api/components/schemas/FlowPageActionsDefinition.js.map +0 -1
- package/api/components/schemas/FlowPageActionsDefinition.ts +0 -20
- package/api/components/schemas/FlowPageDefinition.js.map +0 -1
- package/api/components/schemas/FlowPageDefinition.ts +0 -37
- package/api/components/schemas/FlowToActionDefinition.js.map +0 -1
- package/api/components/schemas/FlowToActionDefinition.ts +0 -21
- package/api/components/schemas/GoogleFontDefinition.js.map +0 -1
- package/api/components/schemas/GoogleFontDefinition.ts +0 -24
- package/api/components/schemas/Health.js.map +0 -1
- package/api/components/schemas/Health.ts +0 -14
- package/api/components/schemas/JSONPointer.js.map +0 -1
- package/api/components/schemas/JSONPointer.ts +0 -20
- package/api/components/schemas/JSONSchema.js.map +0 -1
- package/api/components/schemas/JSONSchema.ts +0 -21
- package/api/components/schemas/JSONSchemaAnyOf.js.map +0 -1
- package/api/components/schemas/JSONSchemaAnyOf.ts +0 -27
- package/api/components/schemas/JSONSchemaArray.js.map +0 -1
- package/api/components/schemas/JSONSchemaArray.ts +0 -47
- package/api/components/schemas/JSONSchemaBoolean.js.map +0 -1
- package/api/components/schemas/JSONSchemaBoolean.ts +0 -37
- package/api/components/schemas/JSONSchemaConst.js.map +0 -1
- package/api/components/schemas/JSONSchemaConst.ts +0 -16
- package/api/components/schemas/JSONSchemaEnum.js.map +0 -1
- package/api/components/schemas/JSONSchemaEnum.ts +0 -36
- package/api/components/schemas/JSONSchemaInteger.js.map +0 -1
- package/api/components/schemas/JSONSchemaInteger.ts +0 -55
- package/api/components/schemas/JSONSchemaMultiType.js.map +0 -1
- package/api/components/schemas/JSONSchemaMultiType.ts +0 -48
- package/api/components/schemas/JSONSchemaNot.js.map +0 -1
- package/api/components/schemas/JSONSchemaNot.ts +0 -23
- package/api/components/schemas/JSONSchemaNull.js.map +0 -1
- package/api/components/schemas/JSONSchemaNull.ts +0 -16
- package/api/components/schemas/JSONSchemaNumber.js.map +0 -1
- package/api/components/schemas/JSONSchemaNumber.ts +0 -66
- package/api/components/schemas/JSONSchemaObject.js.map +0 -1
- package/api/components/schemas/JSONSchemaObject.ts +0 -74
- package/api/components/schemas/JSONSchemaOneOf.js.map +0 -1
- package/api/components/schemas/JSONSchemaOneOf.ts +0 -25
- package/api/components/schemas/JSONSchemaRemapper.js.map +0 -1
- package/api/components/schemas/JSONSchemaRemapper.ts +0 -19
- package/api/components/schemas/JSONSchemaRoot.js.map +0 -1
- package/api/components/schemas/JSONSchemaRoot.ts +0 -23
- package/api/components/schemas/JSONSchemaString.js.map +0 -1
- package/api/components/schemas/JSONSchemaString.ts +0 -116
- package/api/components/schemas/LinkActionDefinition.js.map +0 -1
- package/api/components/schemas/LinkActionDefinition.ts +0 -28
- package/api/components/schemas/LinkBackActionDefinition.js.map +0 -1
- package/api/components/schemas/LinkBackActionDefinition.ts +0 -14
- package/api/components/schemas/LinkNextActionDefinition.js.map +0 -1
- package/api/components/schemas/LinkNextActionDefinition.ts +0 -14
- package/api/components/schemas/LogActionDefinition.js.map +0 -1
- package/api/components/schemas/LogActionDefinition.ts +0 -22
- package/api/components/schemas/Member.js.map +0 -1
- package/api/components/schemas/Member.ts +0 -31
- package/api/components/schemas/MessageActionDefinition.js.map +0 -1
- package/api/components/schemas/MessageActionDefinition.ts +0 -36
- package/api/components/schemas/NoopActionDefinition.js.map +0 -1
- package/api/components/schemas/NoopActionDefinition.ts +0 -17
- package/api/components/schemas/NotificationHookDataDefinition.js.map +0 -1
- package/api/components/schemas/NotificationHookDataDefinition.ts +0 -25
- package/api/components/schemas/NotificationHookDefinition.js.map +0 -1
- package/api/components/schemas/NotificationHookDefinition.ts +0 -33
- package/api/components/schemas/OAuth2AuthorizationCode.js.map +0 -1
- package/api/components/schemas/OAuth2AuthorizationCode.ts +0 -15
- package/api/components/schemas/OAuth2ClientCredentials.js.map +0 -1
- package/api/components/schemas/OAuth2ClientCredentials.ts +0 -39
- package/api/components/schemas/ObjectRemapperDefinition.js.map +0 -1
- package/api/components/schemas/ObjectRemapperDefinition.ts +0 -453
- package/api/components/schemas/Organization.js.map +0 -1
- package/api/components/schemas/Organization.ts +0 -40
- package/api/components/schemas/PageDefinition.js.map +0 -1
- package/api/components/schemas/PageDefinition.ts +0 -23
- package/api/components/schemas/Rating.js.map +0 -1
- package/api/components/schemas/Rating.ts +0 -25
- package/api/components/schemas/RemapperDefinition.js.map +0 -1
- package/api/components/schemas/RemapperDefinition.ts +0 -35
- package/api/components/schemas/RequestActionDefinition.js.map +0 -1
- package/api/components/schemas/RequestActionDefinition.ts +0 -60
- package/api/components/schemas/Resource.js.map +0 -1
- package/api/components/schemas/Resource.ts +0 -20
- package/api/components/schemas/ResourceCountActionDefinition.js.map +0 -1
- package/api/components/schemas/ResourceCountActionDefinition.ts +0 -23
- package/api/components/schemas/ResourceCreateActionDefinition.js.map +0 -1
- package/api/components/schemas/ResourceCreateActionDefinition.ts +0 -22
- package/api/components/schemas/ResourceDefinition.js.map +0 -1
- package/api/components/schemas/ResourceDefinition.ts +0 -229
- package/api/components/schemas/ResourceDeleteActionDefinition.js.map +0 -1
- package/api/components/schemas/ResourceDeleteActionDefinition.ts +0 -22
- package/api/components/schemas/ResourceGetActionDefinition.js.map +0 -1
- package/api/components/schemas/ResourceGetActionDefinition.ts +0 -26
- package/api/components/schemas/ResourceHistoryDefinition.js.map +0 -1
- package/api/components/schemas/ResourceHistoryDefinition.ts +0 -15
- package/api/components/schemas/ResourceHooksDefinition.js.map +0 -1
- package/api/components/schemas/ResourceHooksDefinition.ts +0 -11
- package/api/components/schemas/ResourceQueryActionDefinition.js.map +0 -1
- package/api/components/schemas/ResourceQueryActionDefinition.ts +0 -26
- package/api/components/schemas/ResourceSubscription.js.map +0 -1
- package/api/components/schemas/ResourceSubscription.ts +0 -42
- package/api/components/schemas/ResourceSubscriptionStatusActionDefinition.js.map +0 -1
- package/api/components/schemas/ResourceSubscriptionStatusActionDefinition.ts +0 -23
- package/api/components/schemas/ResourceSubscriptionSubscribeActionDefinition.js.map +0 -1
- package/api/components/schemas/ResourceSubscriptionSubscribeActionDefinition.ts +0 -25
- package/api/components/schemas/ResourceSubscriptionToggleActionDefinition.js.map +0 -1
- package/api/components/schemas/ResourceSubscriptionToggleActionDefinition.ts +0 -22
- package/api/components/schemas/ResourceSubscriptionUnsubscribeActionDefinition.js.map +0 -1
- package/api/components/schemas/ResourceSubscriptionUnsubscribeActionDefinition.ts +0 -25
- package/api/components/schemas/ResourceUpdateActionDefinition.js.map +0 -1
- package/api/components/schemas/ResourceUpdateActionDefinition.ts +0 -22
- package/api/components/schemas/ResourceViewDefinition.js.map +0 -1
- package/api/components/schemas/ResourceViewDefinition.ts +0 -26
- package/api/components/schemas/SSLSecret.js.map +0 -1
- package/api/components/schemas/SSLSecret.ts +0 -17
- package/api/components/schemas/SSOConfiguration.js.map +0 -1
- package/api/components/schemas/SSOConfiguration.ts +0 -22
- package/api/components/schemas/SecurityDefaultDefinition.js.map +0 -1
- package/api/components/schemas/SecurityDefaultDefinition.ts +0 -29
- package/api/components/schemas/SecurityDefinition.js.map +0 -1
- package/api/components/schemas/SecurityDefinition.ts +0 -21
- package/api/components/schemas/SecurityRoleDefinition.js.map +0 -1
- package/api/components/schemas/SecurityRoleDefinition.ts +0 -29
- package/api/components/schemas/ShareActionDefinition.js.map +0 -1
- package/api/components/schemas/ShareActionDefinition.ts +0 -30
- package/api/components/schemas/StaticActionDefinition.js.map +0 -1
- package/api/components/schemas/StaticActionDefinition.ts +0 -20
- package/api/components/schemas/StorageAppendActionDefinition.js.map +0 -1
- package/api/components/schemas/StorageAppendActionDefinition.ts +0 -43
- package/api/components/schemas/StorageDeleteActionDefinition.js.map +0 -1
- package/api/components/schemas/StorageDeleteActionDefinition.ts +0 -31
- package/api/components/schemas/StorageReadActionDefinition.js.map +0 -1
- package/api/components/schemas/StorageReadActionDefinition.ts +0 -32
- package/api/components/schemas/StorageSubtractActionDefinition.js.map +0 -1
- package/api/components/schemas/StorageSubtractActionDefinition.ts +0 -35
- package/api/components/schemas/StorageUpdateActionDefinition.js.map +0 -1
- package/api/components/schemas/StorageUpdateActionDefinition.ts +0 -46
- package/api/components/schemas/StorageWriteActionDefinition.js.map +0 -1
- package/api/components/schemas/StorageWriteActionDefinition.ts +0 -42
- package/api/components/schemas/SubPage.js.map +0 -1
- package/api/components/schemas/SubPage.ts +0 -24
- package/api/components/schemas/TabsPageDefinition.js.map +0 -1
- package/api/components/schemas/TabsPageDefinition.ts +0 -22
- package/api/components/schemas/TeamInviteActionDefinition.js.map +0 -1
- package/api/components/schemas/TeamInviteActionDefinition.ts +0 -27
- package/api/components/schemas/TeamJoinActionDefinition.js.map +0 -1
- package/api/components/schemas/TeamJoinActionDefinition.ts +0 -14
- package/api/components/schemas/TeamListActionDefinition.js.map +0 -1
- package/api/components/schemas/TeamListActionDefinition.ts +0 -14
- package/api/components/schemas/TeamsDefinition.js.map +0 -1
- package/api/components/schemas/TeamsDefinition.ts +0 -30
- package/api/components/schemas/Theme.js.map +0 -1
- package/api/components/schemas/Theme.ts +0 -82
- package/api/components/schemas/ThrowActionDefinition.js.map +0 -1
- package/api/components/schemas/ThrowActionDefinition.ts +0 -17
- package/api/components/schemas/User.js.map +0 -1
- package/api/components/schemas/User.ts +0 -30
- package/api/components/schemas/UserEmail.js.map +0 -1
- package/api/components/schemas/UserEmail.ts +0 -24
- package/api/components/schemas/UserLoginActionDefinition.js.map +0 -1
- package/api/components/schemas/UserLoginActionDefinition.ts +0 -22
- package/api/components/schemas/UserRegisterActionDefinition.js.map +0 -1
- package/api/components/schemas/UserRegisterActionDefinition.ts +0 -33
- package/api/components/schemas/UserUpdateActionDefinition.js.map +0 -1
- package/api/components/schemas/UserUpdateActionDefinition.ts +0 -33
- package/api/components/schemas/index.js.map +0 -1
- package/api/components/schemas/index.ts +0 -108
- package/api/components/schemas/utils.js.map +0 -1
- package/api/components/schemas/utils.ts +0 -43
- package/api/components/securitySchemes/app.js.map +0 -1
- package/api/components/securitySchemes/app.ts +0 -33
- package/api/components/securitySchemes/basic.js.map +0 -1
- package/api/components/securitySchemes/basic.ts +0 -7
- package/api/components/securitySchemes/cli.js.map +0 -1
- package/api/components/securitySchemes/cli.test.js.map +0 -1
- package/api/components/securitySchemes/cli.test.ts +0 -6
- package/api/components/securitySchemes/cli.ts +0 -25
- package/api/components/securitySchemes/index.js.map +0 -1
- package/api/components/securitySchemes/index.ts +0 -4
- package/api/components/securitySchemes/studio.js.map +0 -1
- package/api/components/securitySchemes/studio.ts +0 -8
- package/api/index.js.map +0 -1
- package/api/index.test.js.map +0 -1
- package/api/index.test.ts +0 -196
- package/api/index.ts +0 -44
- package/api/paths/action.js.map +0 -1
- package/api/paths/action.ts +0 -55
- package/api/paths/appMessages.js.map +0 -1
- package/api/paths/appMessages.ts +0 -104
- package/api/paths/appOAuth2Secrets.js.map +0 -1
- package/api/paths/appOAuth2Secrets.ts +0 -152
- package/api/paths/appSSLSecrets.js.map +0 -1
- package/api/paths/appSSLSecrets.ts +0 -40
- package/api/paths/appSamlSecrets.js.map +0 -1
- package/api/paths/appSamlSecrets.ts +0 -85
- package/api/paths/apps.js.map +0 -1
- package/api/paths/apps.ts +0 -1394
- package/api/paths/appsembleMessages.js.map +0 -1
- package/api/paths/appsembleMessages.ts +0 -49
- package/api/paths/assets.js.map +0 -1
- package/api/paths/assets.ts +0 -139
- package/api/paths/blocks.js.map +0 -1
- package/api/paths/blocks.ts +0 -184
- package/api/paths/emails.js.map +0 -1
- package/api/paths/emails.ts +0 -164
- package/api/paths/health.js.map +0 -1
- package/api/paths/health.ts +0 -75
- package/api/paths/index.js.map +0 -1
- package/api/paths/index.ts +0 -45
- package/api/paths/invite.js.map +0 -1
- package/api/paths/invite.ts +0 -26
- package/api/paths/oauth2ClientCredentials.js.map +0 -1
- package/api/paths/oauth2ClientCredentials.ts +0 -79
- package/api/paths/oauth2Login.js.map +0 -1
- package/api/paths/oauth2Login.ts +0 -120
- package/api/paths/oauth2Provider.js.map +0 -1
- package/api/paths/oauth2Provider.ts +0 -73
- package/api/paths/organizations.js.map +0 -1
- package/api/paths/organizations.ts +0 -471
- package/api/paths/resourceHistory.js.map +0 -1
- package/api/paths/resourceHistory.ts +0 -32
- package/api/paths/resources.js.map +0 -1
- package/api/paths/resources.ts +0 -305
- package/api/paths/saml.js.map +0 -1
- package/api/paths/saml.ts +0 -127
- package/api/paths/templates.js.map +0 -1
- package/api/paths/templates.ts +0 -85
- package/api/paths/user.js.map +0 -1
- package/api/paths/user.ts +0 -481
- package/api/schema-tests/AppDefinition/invalid/additional-property.yaml +0 -11
- package/api/schema-tests/AppDefinition/invalid/empty-pages.yaml +0 -4
- package/api/schema-tests/AppDefinition/invalid/missing-default-page.yaml +0 -7
- package/api/schema-tests/AppDefinition/invalid/missing-name.yaml +0 -7
- package/api/schema-tests/AppDefinition/invalid/missing-pages.yaml +0 -2
- package/api/schema-tests/AppDefinition/valid/all-properties.yaml +0 -114
- package/api/schema-tests/AppDefinition/valid/minimal.yaml +0 -9
- package/api/schema-tests/FlowPageDefinition/invalid/missing-subPages.yaml +0 -2
- package/api/schema-tests/FlowPageDefinition/valid/flow.yaml +0 -15
- package/api/schema-tests/PageDefinition/invalid/additional-properties.yaml +0 -5
- package/api/schema-tests/PageDefinition/invalid/missing-blocks.yaml +0 -1
- package/api/schema-tests/PageDefinition/invalid/missing-name.yaml +0 -3
- package/api/schema-tests/PageDefinition/valid/all-properties.yaml +0 -15
- package/api/schema-tests/PageDefinition/valid/minimal.yaml +0 -5
- package/api/schema-tests/TabsPageDefinition/invalid/missing-subPages.yaml +0 -2
- package/api/schema-tests/TabsPageDefinition/valid/tabs.yaml +0 -7
- package/api/tags/app.js.map +0 -1
- package/api/tags/app.ts +0 -6
- package/api/tags/appMember.js.map +0 -1
- package/api/tags/appMember.ts +0 -6
- package/api/tags/asset.js.map +0 -1
- package/api/tags/asset.ts +0 -6
- package/api/tags/auth.js.map +0 -1
- package/api/tags/auth.ts +0 -6
- package/api/tags/index.js.map +0 -1
- package/api/tags/index.ts +0 -9
- package/api/tags/language.js.map +0 -1
- package/api/tags/language.ts +0 -6
- package/api/tags/organization.js.map +0 -1
- package/api/tags/organization.ts +0 -6
- package/api/tags/resource.js.map +0 -1
- package/api/tags/resource.ts +0 -6
- package/api/tags/template.js.map +0 -1
- package/api/tags/template.ts +0 -6
- package/api/tags/user.js.map +0 -1
- package/api/tags/user.ts +0 -6
- package/appMessages.js.map +0 -1
- package/appMessages.test.js.map +0 -1
- package/appMessages.test.ts +0 -432
- package/appMessages.ts +0 -145
- package/appSecurity.js.map +0 -1
- package/appSecurity.test.js.map +0 -1
- package/appSecurity.test.ts +0 -141
- package/appSecurity.ts +0 -48
- package/blockUtils.js.map +0 -1
- package/blockUtils.test.js.map +0 -1
- package/blockUtils.test.ts +0 -94
- package/blockUtils.ts +0 -76
- package/changed/added/.gitkeep +0 -0
- package/changed/changed/.gitkeep +0 -0
- package/changed/deprecated/.gitkeep +0 -0
- package/changed/fixed/.gitkeep +0 -0
- package/changed/removed/.gitkeep +0 -0
- package/changed/security/.gitkeep +0 -0
- package/checkAppRole.js.map +0 -1
- package/checkAppRole.ts +0 -49
- package/compare.js.map +0 -1
- package/compare.ts +0 -10
- package/constants/Permission.js.map +0 -1
- package/constants/Permission.ts +0 -95
- package/constants/asciiLogo.js.map +0 -1
- package/constants/asciiLogo.ts +0 -8
- package/constants/baseTheme.js.map +0 -1
- package/constants/baseTheme.ts +0 -17
- package/constants/date.js.map +0 -1
- package/constants/date.ts +0 -20
- package/constants/fonts.js.map +0 -1
- package/constants/fonts.ts +0 -1291
- package/constants/index.js.map +0 -1
- package/constants/index.ts +0 -9
- package/constants/locale.js.map +0 -1
- package/constants/locale.ts +0 -4
- package/constants/patterns.js.map +0 -1
- package/constants/patterns.test.js.map +0 -1
- package/constants/patterns.test.ts +0 -100
- package/constants/patterns.ts +0 -48
- package/constants/roles.js.map +0 -1
- package/constants/roles.ts +0 -49
- package/constants/scopes.js.map +0 -1
- package/constants/scopes.ts +0 -13
- package/convertToCsv.js.map +0 -1
- package/convertToCsv.test.js.map +0 -1
- package/convertToCsv.test.ts +0 -73
- package/convertToCsv.ts +0 -65
- package/formatRequestAction.js.map +0 -1
- package/formatRequestAction.ts +0 -16
- package/has.js.map +0 -1
- package/has.test.js.map +0 -1
- package/has.test.ts +0 -19
- package/has.ts +0 -10
- package/i18n.js.map +0 -1
- package/i18n.test.js.map +0 -1
- package/i18n.test.ts +0 -81
- package/i18n.ts +0 -55
- package/ics.js.map +0 -1
- package/ics.ts +0 -44
- package/index.js.map +0 -1
- package/index.ts +0 -29
- package/intl-messageformat.js.map +0 -1
- package/intl-messageformat.ts +0 -6
- package/iterApp.js.map +0 -1
- package/iterApp.test.js.map +0 -1
- package/iterApp.test.ts +0 -512
- package/iterApp.ts +0 -174
- package/jest.config.js +0 -3
- package/jsonschema.js.map +0 -1
- package/jsonschema.test.js.map +0 -1
- package/jsonschema.test.ts +0 -320
- package/jsonschema.ts +0 -222
- package/langmap.js.map +0 -1
- package/langmap.ts +0 -23
- package/mapValues.js.map +0 -1
- package/mapValues.test.js.map +0 -1
- package/mapValues.test.ts +0 -15
- package/mapValues.ts +0 -10
- package/miscellaneous.js.map +0 -1
- package/miscellaneous.test.js.map +0 -1
- package/miscellaneous.test.ts +0 -82
- package/miscellaneous.ts +0 -71
- package/noop.js.map +0 -1
- package/noop.ts +0 -5
- package/normalize.js.map +0 -1
- package/normalize.test.js.map +0 -1
- package/normalize.test.ts +0 -24
- package/normalize.ts +0 -23
- package/objectCache.js.map +0 -1
- package/objectCache.test.js.map +0 -1
- package/objectCache.test.ts +0 -19
- package/objectCache.ts +0 -22
- package/pem.js.map +0 -1
- package/pem.ts +0 -11
- package/prefix.js.map +0 -1
- package/prefix.test.js.map +0 -1
- package/prefix.test.ts +0 -11
- package/prefix.ts +0 -10
- package/remap.js.map +0 -1
- package/remap.test.js.map +0 -1
- package/remap.test.ts +0 -1039
- package/remap.ts +0 -455
- package/string.js.map +0 -1
- package/string.test.js.map +0 -1
- package/string.test.ts +0 -29
- package/string.ts +0 -31
- package/theme.js.map +0 -1
- package/theme.test.js.map +0 -1
- package/theme.test.ts +0 -99
- package/theme.ts +0 -38
- package/tsconfig.json +0 -6
- package/types.js.map +0 -1
- package/types.ts +0 -6
- package/validateStyle.js.map +0 -1
- package/validateStyle.test.js.map +0 -1
- package/validateStyle.test.ts +0 -14
- package/validateStyle.ts +0 -19
- package/validation.js.map +0 -1
- package/validation.test.js.map +0 -1
- package/validation.test.ts +0 -1915
- package/validation.ts +0 -767
package/validation.ts
DELETED
|
@@ -1,767 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AppDefinition,
|
|
3
|
-
BlockManifest,
|
|
4
|
-
ResourceGetActionDefinition,
|
|
5
|
-
RoleDefinition,
|
|
6
|
-
} from '@appsemble/types';
|
|
7
|
-
import cronParser from 'cron-parser';
|
|
8
|
-
import { Schema, ValidationError, Validator, ValidatorResult } from 'jsonschema';
|
|
9
|
-
import languageTags from 'language-tags';
|
|
10
|
-
import { Promisable } from 'type-fest';
|
|
11
|
-
|
|
12
|
-
import { getAppBlocks, IdentifiableBlock, normalizeBlockName } from './blockUtils.js';
|
|
13
|
-
import { has } from './has.js';
|
|
14
|
-
import { partialNormalized } from './index.js';
|
|
15
|
-
import { iterApp, Prefix } from './iterApp.js';
|
|
16
|
-
|
|
17
|
-
type Report = (instance: unknown, message: string, path: (number | string)[]) => void;
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Check whether or not the given link represents a link related to the Appsemble core.
|
|
21
|
-
*
|
|
22
|
-
* @param link The link to check
|
|
23
|
-
* @returns Whether or not the given link represents a link related to the Appsemble core.
|
|
24
|
-
*/
|
|
25
|
-
export function isAppLink(link: string[] | string): boolean {
|
|
26
|
-
return link === '/Login' || link === '/Settings';
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function validateJSONSchema(schema: Schema, prefix: Prefix, report: Report): void {
|
|
30
|
-
if (schema.type === 'object') {
|
|
31
|
-
if ('properties' in schema) {
|
|
32
|
-
if (Array.isArray(schema.required)) {
|
|
33
|
-
for (const [index, name] of schema.required.entries()) {
|
|
34
|
-
if (!has(schema.properties, name)) {
|
|
35
|
-
report(name, 'is not defined in properties', [...prefix, 'required', index]);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
for (const [key, propertySchema] of Object.entries(schema.properties)) {
|
|
40
|
-
validateJSONSchema(propertySchema, [...prefix, 'properties', key], report);
|
|
41
|
-
}
|
|
42
|
-
} else {
|
|
43
|
-
report(schema, 'is missing properties', prefix);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function validateResourceSchemas(definition: AppDefinition, report: Report): void {
|
|
49
|
-
if (!definition.resources) {
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
for (const [resourceName, resource] of Object.entries(definition.resources)) {
|
|
54
|
-
// Handled by schema validation
|
|
55
|
-
if (!resource?.schema) {
|
|
56
|
-
continue;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const { schema } = resource;
|
|
60
|
-
const prefix = ['resources', resourceName, 'schema'];
|
|
61
|
-
|
|
62
|
-
validateJSONSchema(schema, prefix, report);
|
|
63
|
-
if (!('type' in schema)) {
|
|
64
|
-
report(schema, 'must define type object', prefix);
|
|
65
|
-
} else if (schema.type !== 'object') {
|
|
66
|
-
report(schema.type, 'must define type object', [...prefix, 'type']);
|
|
67
|
-
}
|
|
68
|
-
if ('properties' in schema) {
|
|
69
|
-
for (const [propertyName, propertySchema] of Object.entries(schema.properties)) {
|
|
70
|
-
if (propertyName === 'id') {
|
|
71
|
-
for (const [validatorKey, value] of Object.entries(propertySchema)) {
|
|
72
|
-
if (validatorKey === 'description' || validatorKey === 'title') {
|
|
73
|
-
continue;
|
|
74
|
-
}
|
|
75
|
-
if (validatorKey === 'type') {
|
|
76
|
-
if (value !== 'integer' && value !== 'number') {
|
|
77
|
-
report(value, 'must be integer', [
|
|
78
|
-
...prefix,
|
|
79
|
-
'properties',
|
|
80
|
-
propertyName,
|
|
81
|
-
validatorKey,
|
|
82
|
-
]);
|
|
83
|
-
}
|
|
84
|
-
continue;
|
|
85
|
-
}
|
|
86
|
-
report(value, 'does not support custom validators', [
|
|
87
|
-
...prefix,
|
|
88
|
-
'properties',
|
|
89
|
-
propertyName,
|
|
90
|
-
validatorKey,
|
|
91
|
-
]);
|
|
92
|
-
}
|
|
93
|
-
} else if (propertyName === '$created' || propertyName === '$updated') {
|
|
94
|
-
for (const [validatorKey, value] of Object.entries(propertySchema)) {
|
|
95
|
-
if (validatorKey === 'description' || validatorKey === 'title') {
|
|
96
|
-
continue;
|
|
97
|
-
}
|
|
98
|
-
if (validatorKey === 'type') {
|
|
99
|
-
if (value !== 'string') {
|
|
100
|
-
report(value, 'must be string', [
|
|
101
|
-
...prefix,
|
|
102
|
-
'properties',
|
|
103
|
-
propertyName,
|
|
104
|
-
validatorKey,
|
|
105
|
-
]);
|
|
106
|
-
}
|
|
107
|
-
continue;
|
|
108
|
-
}
|
|
109
|
-
if (validatorKey === 'format') {
|
|
110
|
-
if (value !== 'date-time') {
|
|
111
|
-
report(value, 'must be date-time', [
|
|
112
|
-
...prefix,
|
|
113
|
-
'properties',
|
|
114
|
-
propertyName,
|
|
115
|
-
validatorKey,
|
|
116
|
-
]);
|
|
117
|
-
}
|
|
118
|
-
continue;
|
|
119
|
-
}
|
|
120
|
-
report(value, 'does not support custom validators', [
|
|
121
|
-
...prefix,
|
|
122
|
-
'properties',
|
|
123
|
-
propertyName,
|
|
124
|
-
validatorKey,
|
|
125
|
-
]);
|
|
126
|
-
}
|
|
127
|
-
} else if (propertyName.startsWith('$')) {
|
|
128
|
-
report(propertySchema, 'may not start with $', [...prefix, 'properties', propertyName]);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function validateBlocks(
|
|
136
|
-
definition: AppDefinition,
|
|
137
|
-
blockVersions: Map<string, Map<string, BlockManifest>>,
|
|
138
|
-
report: Report,
|
|
139
|
-
): void {
|
|
140
|
-
iterApp(definition, {
|
|
141
|
-
onBlock(block, path) {
|
|
142
|
-
const type = normalizeBlockName(block.type);
|
|
143
|
-
const versions = blockVersions.get(type);
|
|
144
|
-
if (!versions) {
|
|
145
|
-
report(block.type, 'is not a known block type', [...path, 'type']);
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
const actionParameters = new Set<string>();
|
|
149
|
-
const version = versions.get(block.version);
|
|
150
|
-
if (!version) {
|
|
151
|
-
report(block.version, 'is not a known version for this block type', [...path, 'version']);
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (version.parameters) {
|
|
156
|
-
const validator = new Validator();
|
|
157
|
-
|
|
158
|
-
validator.customFormats.fontawesome = () => true;
|
|
159
|
-
validator.customFormats.remapper = () => true;
|
|
160
|
-
validator.customFormats.action = (property) => {
|
|
161
|
-
actionParameters.add(property);
|
|
162
|
-
return has(block.actions, property);
|
|
163
|
-
};
|
|
164
|
-
validator.customFormats['event-listener'] = (property) =>
|
|
165
|
-
has(block.events?.listen, property);
|
|
166
|
-
validator.customFormats['event-emitter'] = (property) => has(block.events?.emit, property);
|
|
167
|
-
const result = validator.validate(block.parameters || {}, version.parameters, {
|
|
168
|
-
nestedErrors: true,
|
|
169
|
-
});
|
|
170
|
-
if ('parameters' in block) {
|
|
171
|
-
for (const error of result.errors) {
|
|
172
|
-
report(error.instance, error.message, [...path, 'parameters', ...error.path]);
|
|
173
|
-
}
|
|
174
|
-
} else if (!result.valid) {
|
|
175
|
-
report(block, 'requires property "parameters"', path);
|
|
176
|
-
}
|
|
177
|
-
} else if (block.parameters) {
|
|
178
|
-
report(block.parameters, 'is not allowed on this block type', [...path, 'parameters']);
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
if (block.actions) {
|
|
182
|
-
if (version.actions) {
|
|
183
|
-
for (const [key, action] of Object.entries(block.actions)) {
|
|
184
|
-
if (version.actions.$any) {
|
|
185
|
-
if (actionParameters.has(key)) {
|
|
186
|
-
continue;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
if (!has(version.actions, key) && !version.wildcardActions) {
|
|
190
|
-
report(action, 'is unused', [...path, 'actions', key]);
|
|
191
|
-
}
|
|
192
|
-
} else if (!has(version.actions, key)) {
|
|
193
|
-
report(action, 'is an unknown action for this block', [...path, 'actions', key]);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
} else {
|
|
197
|
-
report(block.actions, 'is not allowed on this block', [...path, 'actions']);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
if (!block.events) {
|
|
202
|
-
return;
|
|
203
|
-
}
|
|
204
|
-
if (block.events.emit) {
|
|
205
|
-
for (const [key, value] of Object.entries(block.events.emit)) {
|
|
206
|
-
if (!version.events?.emit?.$any && !has(version.events?.emit, key)) {
|
|
207
|
-
report(value, 'is an unknown event emitter', [...path, 'events', 'emit', key]);
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
if (block.events.listen) {
|
|
212
|
-
for (const [key, value] of Object.entries(block.events.listen)) {
|
|
213
|
-
if (!version.events?.listen?.$any && !has(version.events?.listen, key)) {
|
|
214
|
-
report(value, 'is an unknown event listener', [...path, 'events', 'listen', key]);
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
},
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
function checkCyclicRoleInheritance(
|
|
223
|
-
roles: Record<string, RoleDefinition>,
|
|
224
|
-
name: string,
|
|
225
|
-
report: Report,
|
|
226
|
-
): void {
|
|
227
|
-
let lastchecked: string;
|
|
228
|
-
const stack: string[] = [];
|
|
229
|
-
|
|
230
|
-
const checkRoleRecursively = (role: string): boolean => {
|
|
231
|
-
lastchecked = role;
|
|
232
|
-
if (stack.includes(role)) {
|
|
233
|
-
return true;
|
|
234
|
-
}
|
|
235
|
-
stack.push(role);
|
|
236
|
-
return roles[role]?.inherits?.some(checkRoleRecursively);
|
|
237
|
-
};
|
|
238
|
-
|
|
239
|
-
const duplicate = checkRoleRecursively(name);
|
|
240
|
-
if (duplicate && lastchecked === name) {
|
|
241
|
-
report(roles[name], 'cyclicly inherits itself', ['security', 'roles', name]);
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
* Validate security related definitions within the app definition.
|
|
247
|
-
*
|
|
248
|
-
* @param definition The definition of the app
|
|
249
|
-
* @param report A function used to report a value.
|
|
250
|
-
*/
|
|
251
|
-
function validateSecurity(definition: AppDefinition, report: Report): void {
|
|
252
|
-
const { security } = definition;
|
|
253
|
-
const defaultAllow = ['$none', '$public', '$team:member', '$team:manager'];
|
|
254
|
-
if (!security) {
|
|
255
|
-
return;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
const checkRoleExists = (name: string, path: Prefix, allow = defaultAllow): boolean => {
|
|
259
|
-
if (!has(security.roles, name) && !allow.includes(name)) {
|
|
260
|
-
report(name, 'does not exist in this app’s roles', path);
|
|
261
|
-
return false;
|
|
262
|
-
}
|
|
263
|
-
return true;
|
|
264
|
-
};
|
|
265
|
-
|
|
266
|
-
const checkRoles = (object: { roles?: string[] }, path: Prefix, allow = defaultAllow): void => {
|
|
267
|
-
if (!object?.roles) {
|
|
268
|
-
return;
|
|
269
|
-
}
|
|
270
|
-
for (const [index, role] of object.roles.entries()) {
|
|
271
|
-
checkRoleExists(role, [...path, 'roles', index], allow);
|
|
272
|
-
}
|
|
273
|
-
};
|
|
274
|
-
|
|
275
|
-
checkRoleExists(security.default.role, ['security', 'default', 'role']);
|
|
276
|
-
checkRoles(definition, []);
|
|
277
|
-
if (definition.resources) {
|
|
278
|
-
for (const [resourceName, resource] of Object.entries(definition.resources)) {
|
|
279
|
-
checkRoles(resource, ['resources', resourceName], [...defaultAllow, '$author']);
|
|
280
|
-
checkRoles(
|
|
281
|
-
resource.count,
|
|
282
|
-
['resources', resourceName, 'count'],
|
|
283
|
-
[...defaultAllow, '$author'],
|
|
284
|
-
);
|
|
285
|
-
checkRoles(resource.create, ['resources', resourceName, 'create']);
|
|
286
|
-
checkRoles(
|
|
287
|
-
resource.delete,
|
|
288
|
-
['resources', resourceName, 'delete'],
|
|
289
|
-
[...defaultAllow, '$author'],
|
|
290
|
-
);
|
|
291
|
-
checkRoles(resource.get, ['resources', resourceName, 'get'], [...defaultAllow, '$author']);
|
|
292
|
-
checkRoles(
|
|
293
|
-
resource.query,
|
|
294
|
-
['resources', resourceName, 'query'],
|
|
295
|
-
[...defaultAllow, '$author'],
|
|
296
|
-
);
|
|
297
|
-
checkRoles(
|
|
298
|
-
resource.update,
|
|
299
|
-
['resources', resourceName, 'update'],
|
|
300
|
-
[...defaultAllow, '$author'],
|
|
301
|
-
);
|
|
302
|
-
|
|
303
|
-
if (resource.views) {
|
|
304
|
-
for (const [viewName, view] of Object.entries(resource.views)) {
|
|
305
|
-
checkRoles(
|
|
306
|
-
view,
|
|
307
|
-
['resources', resourceName, 'views', viewName],
|
|
308
|
-
[...defaultAllow, '$author'],
|
|
309
|
-
);
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
iterApp(definition, { onBlock: checkRoles, onPage: checkRoles });
|
|
315
|
-
|
|
316
|
-
for (const [name, role] of Object.entries(security.roles)) {
|
|
317
|
-
if (!role?.inherits) {
|
|
318
|
-
continue;
|
|
319
|
-
}
|
|
320
|
-
let found = false;
|
|
321
|
-
for (const [index, inheritee] of role.inherits.entries()) {
|
|
322
|
-
found ||= checkRoleExists(inheritee, ['security', 'roles', name, 'inherits', index]);
|
|
323
|
-
}
|
|
324
|
-
if (found) {
|
|
325
|
-
checkCyclicRoleInheritance(security.roles, name, report);
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
/**
|
|
331
|
-
* Validates the hooks in resource definition to ensure its properties are valid.
|
|
332
|
-
*
|
|
333
|
-
* @param definition The definition of the app
|
|
334
|
-
* @param report A function used to report a value.
|
|
335
|
-
*/
|
|
336
|
-
function validateHooks(definition: AppDefinition, report: Report): void {
|
|
337
|
-
if (!definition.resources) {
|
|
338
|
-
return;
|
|
339
|
-
}
|
|
340
|
-
const actionTypes = ['create', 'update', 'delete'] as const;
|
|
341
|
-
for (const [resourceKey, resource] of Object.entries(definition.resources)) {
|
|
342
|
-
for (const actionType of actionTypes) {
|
|
343
|
-
if (!has(resource, actionType)) {
|
|
344
|
-
continue;
|
|
345
|
-
}
|
|
346
|
-
const tos = resource[actionType].hooks?.notification?.to;
|
|
347
|
-
if (tos) {
|
|
348
|
-
for (const [index, to] of tos.entries()) {
|
|
349
|
-
if (to !== '$author' && !has(definition.security?.roles, to)) {
|
|
350
|
-
report(to, 'is an unknown role', [
|
|
351
|
-
'resources',
|
|
352
|
-
resourceKey,
|
|
353
|
-
actionType,
|
|
354
|
-
'hooks',
|
|
355
|
-
'notifications',
|
|
356
|
-
'to',
|
|
357
|
-
index,
|
|
358
|
-
]);
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
function validateResourceReferences(definition: AppDefinition, report: Report): void {
|
|
367
|
-
if (!definition.resources) {
|
|
368
|
-
return;
|
|
369
|
-
}
|
|
370
|
-
for (const [resourceType, resource] of Object.entries(definition.resources)) {
|
|
371
|
-
if (!resource.references) {
|
|
372
|
-
continue;
|
|
373
|
-
}
|
|
374
|
-
for (const [field, reference] of Object.entries(resource.references)) {
|
|
375
|
-
if (!has(definition.resources, reference.resource)) {
|
|
376
|
-
report(reference.resource, 'is not an existing resource', [
|
|
377
|
-
'resources',
|
|
378
|
-
resourceType,
|
|
379
|
-
'references',
|
|
380
|
-
field,
|
|
381
|
-
'resource',
|
|
382
|
-
]);
|
|
383
|
-
continue;
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
if (!has(resource.schema.properties, field)) {
|
|
387
|
-
report(field, 'does not exist on this resource', [
|
|
388
|
-
'resources',
|
|
389
|
-
resourceType,
|
|
390
|
-
'references',
|
|
391
|
-
field,
|
|
392
|
-
]);
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
function validateLanguage({ defaultLanguage }: AppDefinition, report: Report): void {
|
|
399
|
-
if (defaultLanguage != null && !languageTags.check(defaultLanguage)) {
|
|
400
|
-
report(defaultLanguage, 'is not a valid language code', ['defaultLanguage']);
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
function validateDefaultPage({ defaultPage, pages }: AppDefinition, report: Report): void {
|
|
405
|
-
const page = pages?.find((p) => p.name === defaultPage);
|
|
406
|
-
|
|
407
|
-
if (!page) {
|
|
408
|
-
report(defaultPage, 'does not refer to an existing page', ['defaultPage']);
|
|
409
|
-
return;
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
if (page.parameters) {
|
|
413
|
-
report(defaultPage, 'may not specify parameters', ['defaultPage']);
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
function validateCronJobs({ cron }: AppDefinition, report: Report): void {
|
|
418
|
-
if (!cron) {
|
|
419
|
-
return;
|
|
420
|
-
}
|
|
421
|
-
for (const [id, job] of Object.entries(cron)) {
|
|
422
|
-
if (typeof job?.schedule !== 'string') {
|
|
423
|
-
continue;
|
|
424
|
-
}
|
|
425
|
-
try {
|
|
426
|
-
cronParser.parseExpression(job.schedule);
|
|
427
|
-
} catch {
|
|
428
|
-
report(job.schedule, 'contains an invalid expression', ['cron', id, 'schedule']);
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
function validateActions(definition: AppDefinition, report: Report): void {
|
|
434
|
-
const urlRegex = new RegExp(`^${partialNormalized.source}:`);
|
|
435
|
-
|
|
436
|
-
iterApp(definition, {
|
|
437
|
-
onAction(action, path) {
|
|
438
|
-
if (action.type.startsWith('user.') && !definition.security) {
|
|
439
|
-
report(
|
|
440
|
-
action.type,
|
|
441
|
-
'refers to a user action but the app doesn’t have a security definition',
|
|
442
|
-
[...path, 'type'],
|
|
443
|
-
);
|
|
444
|
-
return;
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
if (action.type.startsWith('resource.')) {
|
|
448
|
-
// All of the actions starting with `resource.` contain a property called `resource`.
|
|
449
|
-
const { resource: resourceName, view } = action as ResourceGetActionDefinition;
|
|
450
|
-
const resource = definition.resources?.[resourceName];
|
|
451
|
-
|
|
452
|
-
if (!resource) {
|
|
453
|
-
report(action.type, 'refers to a resource that doesn’t exist', [...path, 'resource']);
|
|
454
|
-
return;
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
if (!action.type.startsWith('resource.subscription.')) {
|
|
458
|
-
const type = action.type.split('.')[1] as
|
|
459
|
-
| 'count'
|
|
460
|
-
| 'create'
|
|
461
|
-
| 'delete'
|
|
462
|
-
| 'get'
|
|
463
|
-
| 'query'
|
|
464
|
-
| 'update';
|
|
465
|
-
const roles = resource?.[type]?.roles ?? resource?.roles;
|
|
466
|
-
if (!roles) {
|
|
467
|
-
report(action.type, 'refers to a resource action that is currently set to private', [
|
|
468
|
-
...path,
|
|
469
|
-
'resource',
|
|
470
|
-
]);
|
|
471
|
-
return;
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
if (roles && !roles.length && !definition.security) {
|
|
475
|
-
report(
|
|
476
|
-
action.type,
|
|
477
|
-
'refers to a resource action that is accessible when logged in, but the app has no security definitions',
|
|
478
|
-
[...path, 'resource'],
|
|
479
|
-
);
|
|
480
|
-
return;
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
if ((type === 'get' || type === 'query') && view) {
|
|
484
|
-
if (!resource.views?.[view]) {
|
|
485
|
-
report(action.type, 'refers to a view that doesn’t exist', [...path, 'view']);
|
|
486
|
-
return;
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
const viewRoles = resource?.views?.[view].roles;
|
|
490
|
-
if (!viewRoles?.length) {
|
|
491
|
-
report(action.type, 'refers to a resource view that is currently set to private', [
|
|
492
|
-
...path,
|
|
493
|
-
'view',
|
|
494
|
-
]);
|
|
495
|
-
return;
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
if (viewRoles && !viewRoles.length && !definition.security) {
|
|
499
|
-
report(
|
|
500
|
-
action.type,
|
|
501
|
-
'refers to a resource action that is accessible when logged in, but the app has no security definitions',
|
|
502
|
-
[...path, 'view'],
|
|
503
|
-
);
|
|
504
|
-
return;
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
if (action.type.startsWith('flow.')) {
|
|
511
|
-
const page = definition.pages?.[Number(path[1])];
|
|
512
|
-
if (page?.type !== 'flow') {
|
|
513
|
-
report(action.type, 'flow actions can only be used on pages with the type ‘flow’', [
|
|
514
|
-
...path,
|
|
515
|
-
'type',
|
|
516
|
-
]);
|
|
517
|
-
return;
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
if (action.type === 'flow.cancel' && !page.actions?.onFlowCancel) {
|
|
521
|
-
report(action.type, 'was defined but ‘onFlowCancel’ page action wasn’t defined', [
|
|
522
|
-
...path,
|
|
523
|
-
'type',
|
|
524
|
-
]);
|
|
525
|
-
return;
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
if (action.type === 'flow.finish' && !page.actions?.onFlowFinish) {
|
|
529
|
-
report(action.type, 'was defined but ‘onFlowFinish’ page action wasn’t defined', [
|
|
530
|
-
...path,
|
|
531
|
-
'type',
|
|
532
|
-
]);
|
|
533
|
-
return;
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
if (action.type === 'flow.back' && path[3] === 0) {
|
|
537
|
-
report(action.type, 'is not allowed on the first step in the flow', [...path, 'type']);
|
|
538
|
-
return;
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
if (
|
|
542
|
-
action.type === 'flow.next' &&
|
|
543
|
-
Number(path[3]) === page.steps.length - 1 &&
|
|
544
|
-
!page.actions?.onFlowFinish
|
|
545
|
-
) {
|
|
546
|
-
report(
|
|
547
|
-
action.type,
|
|
548
|
-
'was defined on the last step but ‘onFlowFinish’ page action wasn’t defined',
|
|
549
|
-
[...path, 'type'],
|
|
550
|
-
);
|
|
551
|
-
return;
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
if (action.type === 'flow.to' && !page.steps.some((step) => step.name === action.step)) {
|
|
555
|
-
report(action.type, 'refers to a step that doesn’t exist', [...path, 'step']);
|
|
556
|
-
return;
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
if (action.type === 'link') {
|
|
561
|
-
const { to } = action;
|
|
562
|
-
if (typeof to === 'string' && urlRegex.test(to)) {
|
|
563
|
-
return;
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
if (isAppLink(to)) {
|
|
567
|
-
return;
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
const [toBase, toSub] = [].concat(to);
|
|
571
|
-
const toPage = definition.pages.find(({ name }) => name === toBase);
|
|
572
|
-
|
|
573
|
-
if (!toPage) {
|
|
574
|
-
report(to, 'refers to a page that doesn’t exist', [...path, 'to']);
|
|
575
|
-
return;
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
if (toPage.type !== 'tabs' && toSub) {
|
|
579
|
-
report(toSub, 'refers to a sub page on a page that isn’t of type ‘tabs’ or ‘flow’', [
|
|
580
|
-
...path,
|
|
581
|
-
'to',
|
|
582
|
-
1,
|
|
583
|
-
]);
|
|
584
|
-
return;
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
if (toPage.type === 'tabs' && toSub) {
|
|
588
|
-
const subPage = toPage.tabs.find(({ name }) => name === toSub);
|
|
589
|
-
if (!subPage) {
|
|
590
|
-
report(toSub, 'refers to a tab that doesn’t exist', [...path, 'to', 1]);
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
},
|
|
595
|
-
});
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
function validateEvents(
|
|
599
|
-
definition: AppDefinition,
|
|
600
|
-
blockVersions: Map<string, Map<string, BlockManifest>>,
|
|
601
|
-
report: Report,
|
|
602
|
-
): void {
|
|
603
|
-
const indexMap = new Map<
|
|
604
|
-
number,
|
|
605
|
-
{
|
|
606
|
-
emitters: Map<string, Prefix[]>;
|
|
607
|
-
listeners: Map<string, Prefix[]>;
|
|
608
|
-
}
|
|
609
|
-
>();
|
|
610
|
-
|
|
611
|
-
function collect(prefix: Prefix, name: string, isEmitter: boolean): void {
|
|
612
|
-
const [firstKey, pageIndex] = prefix;
|
|
613
|
-
|
|
614
|
-
// Ignore anything not part of a page. For example cron actions never support events.
|
|
615
|
-
if (firstKey !== 'pages') {
|
|
616
|
-
return;
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
if (typeof pageIndex !== 'number') {
|
|
620
|
-
return;
|
|
621
|
-
}
|
|
622
|
-
if (!indexMap.has(pageIndex)) {
|
|
623
|
-
indexMap.set(pageIndex, { emitters: new Map(), listeners: new Map() });
|
|
624
|
-
}
|
|
625
|
-
const { emitters, listeners } = indexMap.get(pageIndex)!;
|
|
626
|
-
const context = isEmitter ? emitters : listeners;
|
|
627
|
-
if (!context.has(name)) {
|
|
628
|
-
context.set(name, []);
|
|
629
|
-
}
|
|
630
|
-
const prefixes = context.get(name)!;
|
|
631
|
-
prefixes.push(prefix);
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
iterApp(definition, {
|
|
635
|
-
onAction(action, path) {
|
|
636
|
-
if (action.type === 'dialog') {
|
|
637
|
-
for (const block of action.blocks) {
|
|
638
|
-
const versions = blockVersions.get(normalizeBlockName(block.type));
|
|
639
|
-
const version = versions.get(block.version);
|
|
640
|
-
if (version.layout === 'float') {
|
|
641
|
-
report(
|
|
642
|
-
block.version,
|
|
643
|
-
'block with layout type: "'
|
|
644
|
-
.concat(version.layout)
|
|
645
|
-
.concat('" is not allowed in a dialog action'),
|
|
646
|
-
[...path, 'type'],
|
|
647
|
-
);
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
if (block.layout === 'float') {
|
|
651
|
-
report(
|
|
652
|
-
block,
|
|
653
|
-
'block with layout type: "'
|
|
654
|
-
.concat(block.layout)
|
|
655
|
-
.concat('" is not allowed in a dialog action'),
|
|
656
|
-
[...path, 'type'],
|
|
657
|
-
);
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
|
-
return;
|
|
661
|
-
}
|
|
662
|
-
if (action.type !== 'event') {
|
|
663
|
-
return;
|
|
664
|
-
}
|
|
665
|
-
|
|
666
|
-
collect([...path, 'event'], action.event, true);
|
|
667
|
-
if ('waitFor' in action) {
|
|
668
|
-
collect([...path, 'waitFor'], action.waitFor, false);
|
|
669
|
-
}
|
|
670
|
-
},
|
|
671
|
-
|
|
672
|
-
onBlock(block, path) {
|
|
673
|
-
if (!block.events) {
|
|
674
|
-
return;
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
if (block.events.emit) {
|
|
678
|
-
for (const [prefix, name] of Object.entries(block.events.emit)) {
|
|
679
|
-
collect([...path, 'events', 'emit', prefix], name, true);
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
|
|
683
|
-
if (block.events.listen) {
|
|
684
|
-
for (const [prefix, name] of Object.entries(block.events.listen)) {
|
|
685
|
-
collect([...path, 'events', 'listen', prefix], name, false);
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
},
|
|
689
|
-
});
|
|
690
|
-
|
|
691
|
-
for (const { emitters, listeners } of indexMap.values()) {
|
|
692
|
-
for (const [name, prefixes] of listeners.entries()) {
|
|
693
|
-
if (!emitters.has(name)) {
|
|
694
|
-
for (const prefix of prefixes) {
|
|
695
|
-
report(name, 'does not match any event emitters', prefix);
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
for (const [name, prefixes] of emitters.entries()) {
|
|
700
|
-
if (!listeners.has(name)) {
|
|
701
|
-
for (const prefix of prefixes) {
|
|
702
|
-
report(name, 'does not match any event listeners', prefix);
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
export type BlockVersionsGetter = (blockMap: IdentifiableBlock[]) => Promisable<BlockManifest[]>;
|
|
710
|
-
|
|
711
|
-
/**
|
|
712
|
-
* Validate an app definition.
|
|
713
|
-
*
|
|
714
|
-
* This check various conditions which can’t be validated using basic JSON schema validation.
|
|
715
|
-
*
|
|
716
|
-
* @param definition The app validation to check.
|
|
717
|
-
* @param getBlockVersions A function for getting block manifests from block versions.
|
|
718
|
-
* @param validatorResult If specified, error messages will be applied to this existing validator
|
|
719
|
-
* result.
|
|
720
|
-
* @returns A validator result which contains all app validation violations.
|
|
721
|
-
*/
|
|
722
|
-
export async function validateAppDefinition(
|
|
723
|
-
definition: AppDefinition,
|
|
724
|
-
getBlockVersions: BlockVersionsGetter,
|
|
725
|
-
validatorResult?: ValidatorResult,
|
|
726
|
-
): Promise<ValidatorResult> {
|
|
727
|
-
let result = validatorResult;
|
|
728
|
-
if (!result) {
|
|
729
|
-
const validator = new Validator();
|
|
730
|
-
result = validator.validate(definition, {});
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
if (!definition) {
|
|
734
|
-
return result;
|
|
735
|
-
}
|
|
736
|
-
const blocks = getAppBlocks(definition);
|
|
737
|
-
const blockVersions = await getBlockVersions(blocks);
|
|
738
|
-
|
|
739
|
-
const blockVersionMap = new Map<string, Map<string, BlockManifest>>();
|
|
740
|
-
for (const version of blockVersions) {
|
|
741
|
-
if (!blockVersionMap.has(version.name)) {
|
|
742
|
-
blockVersionMap.set(version.name, new Map());
|
|
743
|
-
}
|
|
744
|
-
blockVersionMap.get(version.name).set(version.version, version);
|
|
745
|
-
}
|
|
746
|
-
|
|
747
|
-
const report: Report = (instance, message, path) => {
|
|
748
|
-
result.errors.push(new ValidationError(message, instance, undefined, path));
|
|
749
|
-
};
|
|
750
|
-
|
|
751
|
-
try {
|
|
752
|
-
validateCronJobs(definition, report);
|
|
753
|
-
validateDefaultPage(definition, report);
|
|
754
|
-
validateHooks(definition, report);
|
|
755
|
-
validateLanguage(definition, report);
|
|
756
|
-
validateResourceReferences(definition, report);
|
|
757
|
-
validateResourceSchemas(definition, report);
|
|
758
|
-
validateSecurity(definition, report);
|
|
759
|
-
validateBlocks(definition, blockVersionMap, report);
|
|
760
|
-
validateActions(definition, report);
|
|
761
|
-
validateEvents(definition, blockVersionMap, report);
|
|
762
|
-
} catch (error) {
|
|
763
|
-
report(null, `Unexpected error: ${error instanceof Error ? error.message : error}`, []);
|
|
764
|
-
}
|
|
765
|
-
|
|
766
|
-
return result;
|
|
767
|
-
}
|