@ankhorage/contracts 14.0.0 → 16.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +37 -0
- package/README.md +10 -2
- package/dist/appManifest/apis.d.ts +1 -0
- package/dist/appManifest/apis.d.ts.map +1 -1
- package/dist/appManifest/apis.js +17 -14
- package/dist/appManifest/apis.js.map +1 -1
- package/dist/appManifest/bindings.d.ts +3 -0
- package/dist/appManifest/bindings.d.ts.map +1 -1
- package/dist/appManifest/bindings.js +17 -1
- package/dist/appManifest/bindings.js.map +1 -1
- package/dist/appManifest/constants.d.ts +18 -0
- package/dist/appManifest/constants.d.ts.map +1 -0
- package/dist/appManifest/constants.js +18 -0
- package/dist/appManifest/constants.js.map +1 -0
- package/dist/appManifest/data.d.ts +4 -0
- package/dist/appManifest/data.d.ts.map +1 -1
- package/dist/appManifest/data.js +22 -3
- package/dist/appManifest/data.js.map +1 -1
- package/dist/appManifest/dataSources.d.ts +1 -0
- package/dist/appManifest/dataSources.d.ts.map +1 -1
- package/dist/appManifest/dataSources.js +7 -6
- package/dist/appManifest/dataSources.js.map +1 -1
- package/dist/appManifest/deploy.d.ts +1 -0
- package/dist/appManifest/deploy.d.ts.map +1 -1
- package/dist/appManifest/deploy.js +16 -13
- package/dist/appManifest/deploy.js.map +1 -1
- package/dist/appManifest/icon.d.ts.map +1 -1
- package/dist/appManifest/icon.js +2 -1
- package/dist/appManifest/icon.js.map +1 -1
- package/dist/appManifest/isAppManifest.d.ts +4 -0
- package/dist/appManifest/isAppManifest.d.ts.map +1 -0
- package/dist/appManifest/isAppManifest.js +69 -0
- package/dist/appManifest/isAppManifest.js.map +1 -0
- package/dist/appManifest/isAppStateSpec.d.ts +4 -0
- package/dist/appManifest/isAppStateSpec.d.ts.map +1 -0
- package/dist/appManifest/isAppStateSpec.js +9 -0
- package/dist/appManifest/isAppStateSpec.js.map +1 -0
- package/dist/appManifest/isManifestValue.d.ts +3 -0
- package/dist/appManifest/isManifestValue.d.ts.map +1 -0
- package/dist/appManifest/isManifestValue.js +15 -0
- package/dist/appManifest/isManifestValue.js.map +1 -0
- package/dist/appManifest/media.d.ts +1 -0
- package/dist/appManifest/media.d.ts.map +1 -1
- package/dist/appManifest/media.js +10 -8
- package/dist/appManifest/media.js.map +1 -1
- package/dist/appManifest/navigator.d.ts.map +1 -1
- package/dist/appManifest/navigator.js +7 -6
- package/dist/appManifest/navigator.js.map +1 -1
- package/dist/appManifest/navigatorOptions.d.ts +0 -2
- package/dist/appManifest/navigatorOptions.d.ts.map +1 -1
- package/dist/appManifest/navigatorOptions.js +8 -12
- package/dist/appManifest/navigatorOptions.js.map +1 -1
- package/dist/appManifest/parseAppManifest.d.ts +10 -0
- package/dist/appManifest/parseAppManifest.d.ts.map +1 -0
- package/dist/appManifest/parseAppManifest.js +14 -0
- package/dist/appManifest/parseAppManifest.js.map +1 -0
- package/dist/appManifest/screens.d.ts +4 -0
- package/dist/appManifest/screens.d.ts.map +1 -1
- package/dist/appManifest/screens.js +14 -2
- package/dist/appManifest/screens.js.map +1 -1
- package/dist/appManifest.d.ts +3 -18
- package/dist/appManifest.d.ts.map +1 -1
- package/dist/appManifest.js +2 -80
- package/dist/appManifest.js.map +1 -1
- package/dist/auth.d.ts +3 -2
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js.map +1 -1
- package/dist/deploy.d.ts +0 -9
- package/dist/deploy.d.ts.map +1 -1
- package/dist/deploy.js +0 -8
- package/dist/deploy.js.map +1 -1
- package/dist/environments.d.ts +4 -0
- package/dist/environments.d.ts.map +1 -0
- package/dist/environments.js +3 -0
- package/dist/environments.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/infra/constants.d.ts +91 -0
- package/dist/infra/constants.d.ts.map +1 -0
- package/dist/infra/constants.js +91 -0
- package/dist/infra/constants.js.map +1 -0
- package/dist/infra/infraFields.d.ts +12 -0
- package/dist/infra/infraFields.d.ts.map +1 -0
- package/dist/infra/infraFields.js +14 -0
- package/dist/infra/infraFields.js.map +1 -0
- package/dist/infra/isInfraAdapterDescriptor.d.ts +4 -0
- package/dist/infra/isInfraAdapterDescriptor.d.ts.map +1 -0
- package/dist/infra/isInfraAdapterDescriptor.js +31 -0
- package/dist/infra/isInfraAdapterDescriptor.js.map +1 -0
- package/dist/infra/isInfraAuthSpec.d.ts +4 -0
- package/dist/infra/isInfraAuthSpec.d.ts.map +1 -0
- package/dist/infra/isInfraAuthSpec.js +75 -0
- package/dist/infra/isInfraAuthSpec.js.map +1 -0
- package/dist/infra/isInfraCredentialRef.d.ts +3 -0
- package/dist/infra/isInfraCredentialRef.d.ts.map +1 -0
- package/dist/infra/isInfraCredentialRef.js +10 -0
- package/dist/infra/isInfraCredentialRef.js.map +1 -0
- package/dist/infra/isInfraDeploymentSpec.d.ts +4 -0
- package/dist/infra/isInfraDeploymentSpec.d.ts.map +1 -0
- package/dist/infra/isInfraDeploymentSpec.js +66 -0
- package/dist/infra/isInfraDeploymentSpec.js.map +1 -0
- package/dist/infra/isInfraEnvironmentSpec.d.ts +4 -0
- package/dist/infra/isInfraEnvironmentSpec.d.ts.map +1 -0
- package/dist/infra/isInfraEnvironmentSpec.js +82 -0
- package/dist/infra/isInfraEnvironmentSpec.js.map +1 -0
- package/dist/infra/isInfraManifest.d.ts +4 -0
- package/dist/infra/isInfraManifest.d.ts.map +1 -0
- package/dist/infra/isInfraManifest.js +23 -0
- package/dist/infra/isInfraManifest.js.map +1 -0
- package/dist/infra/isInfraShape.d.ts +3 -0
- package/dist/infra/isInfraShape.d.ts.map +1 -0
- package/dist/infra/isInfraShape.js +10 -0
- package/dist/infra/isInfraShape.js.map +1 -0
- package/dist/infra/isInfraWorkloadHealth.d.ts +3 -0
- package/dist/infra/isInfraWorkloadHealth.d.ts.map +1 -0
- package/dist/infra/isInfraWorkloadHealth.js +37 -0
- package/dist/infra/isInfraWorkloadHealth.js.map +1 -0
- package/dist/infra/isInfraWorkloadSpec.d.ts +4 -0
- package/dist/infra/isInfraWorkloadSpec.d.ts.map +1 -0
- package/dist/infra/isInfraWorkloadSpec.js +70 -0
- package/dist/infra/isInfraWorkloadSpec.js.map +1 -0
- package/dist/infra/isInfraWorkloadValue.d.ts +3 -0
- package/dist/infra/isInfraWorkloadValue.d.ts.map +1 -0
- package/dist/infra/isInfraWorkloadValue.js +40 -0
- package/dist/infra/isInfraWorkloadValue.js.map +1 -0
- package/dist/infra/parseInfraManifest.d.ts +5 -0
- package/dist/infra/parseInfraManifest.d.ts.map +1 -0
- package/dist/infra/parseInfraManifest.js +17 -0
- package/dist/infra/parseInfraManifest.js.map +1 -0
- package/dist/infra/validateInfraAdapterSelection.d.ts +6 -0
- package/dist/infra/validateInfraAdapterSelection.d.ts.map +1 -0
- package/dist/infra/validateInfraAdapterSelection.js +36 -0
- package/dist/infra/validateInfraAdapterSelection.js.map +1 -0
- package/dist/infra.d.ts +16 -0
- package/dist/infra.d.ts.map +1 -0
- package/dist/infra.js +11 -0
- package/dist/infra.js.map +1 -0
- package/dist/media.d.ts +7 -6
- package/dist/media.d.ts.map +1 -1
- package/dist/media.js +5 -5
- package/dist/media.js.map +1 -1
- package/dist/state.d.ts +5 -0
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js.map +1 -1
- package/dist/types/appManifest.d.ts +9 -0
- package/dist/types/appManifest.d.ts.map +1 -0
- package/dist/types/appManifest.js +2 -0
- package/dist/types/appManifest.js.map +1 -0
- package/dist/types/infraAdapters.d.ts +87 -0
- package/dist/types/infraAdapters.d.ts.map +1 -0
- package/dist/types/infraAdapters.js +2 -0
- package/dist/types/infraAdapters.js.map +1 -0
- package/dist/types/infraLifecycle.d.ts +107 -0
- package/dist/types/infraLifecycle.d.ts.map +1 -0
- package/dist/types/infraLifecycle.js +2 -0
- package/dist/types/infraLifecycle.js.map +1 -0
- package/dist/types/infraManifest.d.ts +142 -0
- package/dist/types/infraManifest.d.ts.map +1 -0
- package/dist/types/infraManifest.js +2 -0
- package/dist/types/infraManifest.js.map +1 -0
- package/dist/types/infraSecrets.d.ts +15 -0
- package/dist/types/infraSecrets.d.ts.map +1 -0
- package/dist/types/infraSecrets.js +2 -0
- package/dist/types/infraSecrets.js.map +1 -0
- package/dist/types/infraValidation.d.ts +5 -0
- package/dist/types/infraValidation.d.ts.map +1 -0
- package/dist/types/infraValidation.js +2 -0
- package/dist/types/infraValidation.js.map +1 -0
- package/dist/types/infraWorkload.d.ts +70 -0
- package/dist/types/infraWorkload.d.ts.map +1 -0
- package/dist/types/infraWorkload.js +2 -0
- package/dist/types/infraWorkload.js.map +1 -0
- package/dist/types.d.ts +7 -70
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +0 -9
- package/dist/types.js.map +1 -1
- package/package.json +11 -2
- package/src/appManifest/apis.ts +18 -16
- package/src/appManifest/bindings.ts +18 -1
- package/src/appManifest/constants.ts +19 -0
- package/src/appManifest/data.ts +23 -9
- package/src/appManifest/dataSources.ts +8 -7
- package/src/appManifest/deploy.ts +17 -15
- package/src/appManifest/icon.ts +3 -1
- package/src/appManifest/isAppManifest.ts +95 -0
- package/src/appManifest/isAppStateSpec.ts +13 -0
- package/src/appManifest/isManifestValue.ts +19 -0
- package/src/appManifest/media.ts +11 -10
- package/src/appManifest/navigator.ts +7 -6
- package/src/appManifest/navigatorOptions.ts +9 -16
- package/src/appManifest/parseAppManifest.ts +15 -0
- package/src/appManifest/screens.ts +14 -2
- package/src/appManifest.test.ts +9 -5
- package/src/appManifest.ts +3 -107
- package/src/auth-flow-contract.test.ts +6 -10
- package/src/auth-oauth.test.ts +2 -2
- package/src/auth.ts +3 -2
- package/src/bindings.test.ts +5 -0
- package/src/contracts.test.ts +21 -19
- package/src/deploy.test.ts +13 -5
- package/src/deploy.ts +0 -11
- package/src/environments.ts +4 -0
- package/src/index.ts +2 -1
- package/src/infra/constants.ts +91 -0
- package/src/infra/infraFields.ts +20 -0
- package/src/infra/isInfraAdapterDescriptor.ts +37 -0
- package/src/infra/isInfraAuthSpec.ts +98 -0
- package/src/infra/isInfraCredentialRef.ts +11 -0
- package/src/infra/isInfraDeploymentSpec.ts +75 -0
- package/src/infra/isInfraEnvironmentSpec.ts +95 -0
- package/src/infra/isInfraManifest.ts +29 -0
- package/src/infra/isInfraShape.ts +16 -0
- package/src/infra/isInfraWorkloadHealth.ts +38 -0
- package/src/infra/isInfraWorkloadSpec.ts +87 -0
- package/src/infra/isInfraWorkloadValue.ts +41 -0
- package/src/infra/parseInfraManifest.ts +20 -0
- package/src/infra/validateInfraAdapterSelection.ts +42 -0
- package/src/infra-types.test.ts +93 -0
- package/src/infra-workload.test.ts +186 -0
- package/src/infra.test.ts +268 -0
- package/src/infra.ts +15 -0
- package/src/media.ts +12 -11
- package/src/profile-contract.test.ts +2 -3
- package/src/secrets.test.ts +19 -13
- package/src/state.ts +6 -0
- package/src/types/appManifest.ts +5 -0
- package/src/types/infraAdapters.ts +150 -0
- package/src/types/infraLifecycle.ts +105 -0
- package/src/types/infraManifest.ts +130 -0
- package/src/types/infraSecrets.ts +16 -0
- package/src/types/infraValidation.ts +2 -0
- package/src/types/infraWorkload.ts +64 -0
- package/src/types.ts +7 -87
- package/dist/appManifest/infra.d.ts +0 -2
- package/dist/appManifest/infra.d.ts.map +0 -1
- package/dist/appManifest/infra.js +0 -130
- package/dist/appManifest/infra.js.map +0 -1
- package/dist/appManifest/shared.d.ts +0 -8
- package/dist/appManifest/shared.d.ts.map +0 -1
- package/dist/appManifest/shared.js +0 -31
- package/dist/appManifest/shared.js.map +0 -1
- package/dist/secretManifest.d.ts +0 -11
- package/dist/secretManifest.d.ts.map +0 -1
- package/dist/secretManifest.js +0 -2
- package/dist/secretManifest.js.map +0 -1
- package/src/appManifest/infra.ts +0 -190
- package/src/appManifest/shared.ts +0 -40
- package/src/secretManifest.ts +0 -12
package/src/appManifest/apis.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { hasOnlyKeys, isRecord } from '@ankhorage/utility/object';
|
|
2
|
+
import { isNonEmptyString, isOptionalString } from '@ankhorage/utility/string';
|
|
3
|
+
|
|
1
4
|
import type { ApiDefinition, ApiDefinitionList } from '../data';
|
|
2
5
|
import { isCredentialRef, isDataEndpointRegistry, isDataSchemaRegistry } from './data';
|
|
3
|
-
import { isManifestValue
|
|
6
|
+
import { isManifestValue } from './isManifestValue';
|
|
4
7
|
|
|
5
8
|
const API_BASE_KEYS = [
|
|
6
9
|
'id',
|
|
@@ -13,18 +16,20 @@ const API_BASE_KEYS = [
|
|
|
13
16
|
'schemas',
|
|
14
17
|
'metadata',
|
|
15
18
|
] as const;
|
|
16
|
-
const EXTERNAL_REST_KEYS =
|
|
17
|
-
const EXTERNAL_GRAPHQL_KEYS =
|
|
18
|
-
const INTERNAL_REST_KEYS =
|
|
19
|
-
const OPEN_API_KEYS =
|
|
20
|
-
const INTROSPECTION_KEYS =
|
|
19
|
+
const EXTERNAL_REST_KEYS = [...API_BASE_KEYS, 'baseUrl', 'openApi'] as const;
|
|
20
|
+
const EXTERNAL_GRAPHQL_KEYS = [...API_BASE_KEYS, 'endpointUrl', 'introspection'] as const;
|
|
21
|
+
const INTERNAL_REST_KEYS = [...API_BASE_KEYS, 'basePath'] as const;
|
|
22
|
+
const OPEN_API_KEYS = ['url', 'documentId', 'version'] as const;
|
|
23
|
+
const INTROSPECTION_KEYS = ['enabled', 'schemaVersion'] as const;
|
|
21
24
|
|
|
25
|
+
/*** Validate API definitions and require unique API identities. */
|
|
22
26
|
export function isApiDefinitionList(value: unknown): value is ApiDefinitionList {
|
|
23
27
|
if (!Array.isArray(value) || !value.every(isApiDefinition)) return false;
|
|
24
28
|
const ids = value.map((api) => api.id);
|
|
25
29
|
return new Set(ids).size === ids.length;
|
|
26
30
|
}
|
|
27
31
|
|
|
32
|
+
/*** Validate one API definition against its origin and protocol branch. */
|
|
28
33
|
function isApiDefinition(value: unknown): value is ApiDefinition {
|
|
29
34
|
if (!isApiBaseDefinition(value)) return false;
|
|
30
35
|
if (value.origin === 'external' && value.protocol === 'rest') return isExternalRestApi(value);
|
|
@@ -35,14 +40,14 @@ function isApiDefinition(value: unknown): value is ApiDefinition {
|
|
|
35
40
|
return false;
|
|
36
41
|
}
|
|
37
42
|
|
|
43
|
+
/*** Validate common API identity, endpoint, schema and authored metadata fields. */
|
|
38
44
|
function isApiBaseDefinition(value: unknown): value is Record<string, unknown> {
|
|
39
45
|
return (
|
|
40
46
|
isRecord(value) &&
|
|
41
47
|
isNonEmptyString(value.id) &&
|
|
42
48
|
(value.origin === 'external' || value.origin === 'internal') &&
|
|
43
49
|
(value.protocol === 'graphql' || value.protocol === 'rest') &&
|
|
44
|
-
|
|
45
|
-
isOptionalString(value.description) &&
|
|
50
|
+
[value.name, value.description].every(isOptionalString) &&
|
|
46
51
|
(value.credential === undefined || isCredentialRef(value.credential)) &&
|
|
47
52
|
isDataEndpointRegistry(value.endpoints) &&
|
|
48
53
|
(value.schemas === undefined || isDataSchemaRegistry(value.schemas)) &&
|
|
@@ -50,6 +55,7 @@ function isApiBaseDefinition(value: unknown): value is Record<string, unknown> {
|
|
|
50
55
|
);
|
|
51
56
|
}
|
|
52
57
|
|
|
58
|
+
/*** Validate external REST endpoint and optional OpenAPI metadata. */
|
|
53
59
|
function isExternalRestApi(value: Record<string, unknown>): boolean {
|
|
54
60
|
return (
|
|
55
61
|
hasOnlyKeys(value, EXTERNAL_REST_KEYS) &&
|
|
@@ -58,6 +64,7 @@ function isExternalRestApi(value: Record<string, unknown>): boolean {
|
|
|
58
64
|
);
|
|
59
65
|
}
|
|
60
66
|
|
|
67
|
+
/*** Validate external GraphQL endpoint and optional introspection metadata. */
|
|
61
68
|
function isExternalGraphQlApi(value: Record<string, unknown>): boolean {
|
|
62
69
|
return (
|
|
63
70
|
hasOnlyKeys(value, EXTERNAL_GRAPHQL_KEYS) &&
|
|
@@ -66,10 +73,12 @@ function isExternalGraphQlApi(value: Record<string, unknown>): boolean {
|
|
|
66
73
|
);
|
|
67
74
|
}
|
|
68
75
|
|
|
76
|
+
/*** Validate the supported internal REST API configuration. */
|
|
69
77
|
function isInternalRestApi(value: Record<string, unknown>): boolean {
|
|
70
78
|
return hasOnlyKeys(value, INTERNAL_REST_KEYS) && isNonEmptyString(value.basePath);
|
|
71
79
|
}
|
|
72
80
|
|
|
81
|
+
/*** Validate optional OpenAPI document location and version fields. */
|
|
73
82
|
function isOpenApiDocumentRef(value: unknown): boolean {
|
|
74
83
|
return (
|
|
75
84
|
isRecord(value) &&
|
|
@@ -80,6 +89,7 @@ function isOpenApiDocumentRef(value: unknown): boolean {
|
|
|
80
89
|
);
|
|
81
90
|
}
|
|
82
91
|
|
|
92
|
+
/*** Validate explicit GraphQL introspection settings. */
|
|
83
93
|
function isGraphQlIntrospection(value: unknown): boolean {
|
|
84
94
|
return (
|
|
85
95
|
isRecord(value) &&
|
|
@@ -88,11 +98,3 @@ function isGraphQlIntrospection(value: unknown): boolean {
|
|
|
88
98
|
isOptionalString(value.schemaVersion)
|
|
89
99
|
);
|
|
90
100
|
}
|
|
91
|
-
|
|
92
|
-
function isNonEmptyString(value: unknown): value is string {
|
|
93
|
-
return typeof value === 'string' && value.trim().length > 0;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
function hasOnlyKeys(value: Record<string, unknown>, allowed: ReadonlySet<string>): boolean {
|
|
97
|
-
return Object.keys(value).every((key) => allowed.has(key));
|
|
98
|
-
}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isRecord } from '@ankhorage/utility/object';
|
|
2
|
+
import { isOptionalString } from '@ankhorage/utility/string';
|
|
2
3
|
|
|
4
|
+
import { isManifestValue } from './isManifestValue';
|
|
5
|
+
|
|
6
|
+
/*** Validate every component binding in the authored registry. */
|
|
3
7
|
export function isComponentDataBindingRegistry(value: unknown): boolean {
|
|
4
8
|
return isRecord(value) && Object.values(value).every(isComponentDataBinding);
|
|
5
9
|
}
|
|
6
10
|
|
|
11
|
+
/*** Validate literal, operation and path-based binding sources. */
|
|
7
12
|
export function isBindingValueSource(value: unknown): boolean {
|
|
8
13
|
return (
|
|
9
14
|
isRecord(value) &&
|
|
@@ -17,6 +22,7 @@ export function isBindingValueSource(value: unknown): boolean {
|
|
|
17
22
|
);
|
|
18
23
|
}
|
|
19
24
|
|
|
25
|
+
/*** Validate a screen operation loader and its optional input mapping. */
|
|
20
26
|
export function isScreenDataLoaderDefinition(value: unknown): boolean {
|
|
21
27
|
return (
|
|
22
28
|
isRecord(value) &&
|
|
@@ -27,6 +33,7 @@ export function isScreenDataLoaderDefinition(value: unknown): boolean {
|
|
|
27
33
|
);
|
|
28
34
|
}
|
|
29
35
|
|
|
36
|
+
/*** Validate component identity and its property and event bindings. */
|
|
30
37
|
function isComponentDataBinding(value: unknown): boolean {
|
|
31
38
|
return (
|
|
32
39
|
isRecord(value) &&
|
|
@@ -42,6 +49,7 @@ function isComponentDataBinding(value: unknown): boolean {
|
|
|
42
49
|
);
|
|
43
50
|
}
|
|
44
51
|
|
|
52
|
+
/*** Validate a property binding with optional transforms and fallback behavior. */
|
|
45
53
|
function isPropBinding(value: unknown): boolean {
|
|
46
54
|
return (
|
|
47
55
|
isRecord(value) &&
|
|
@@ -54,6 +62,7 @@ function isPropBinding(value: unknown): boolean {
|
|
|
54
62
|
);
|
|
55
63
|
}
|
|
56
64
|
|
|
65
|
+
/*** Validate an event binding and its declared target. */
|
|
57
66
|
function isEventBinding(value: unknown): boolean {
|
|
58
67
|
return (
|
|
59
68
|
isRecord(value) &&
|
|
@@ -63,6 +72,7 @@ function isEventBinding(value: unknown): boolean {
|
|
|
63
72
|
);
|
|
64
73
|
}
|
|
65
74
|
|
|
75
|
+
/*** Validate the selected operation or action event target. */
|
|
66
76
|
function isEventBindingTarget(value: unknown): boolean {
|
|
67
77
|
return (
|
|
68
78
|
isRecord(value) &&
|
|
@@ -71,6 +81,7 @@ function isEventBindingTarget(value: unknown): boolean {
|
|
|
71
81
|
);
|
|
72
82
|
}
|
|
73
83
|
|
|
84
|
+
/*** Validate a binding condition and its source value. */
|
|
74
85
|
function isBindingCondition(value: unknown): boolean {
|
|
75
86
|
return (
|
|
76
87
|
isRecord(value) &&
|
|
@@ -80,6 +91,7 @@ function isBindingCondition(value: unknown): boolean {
|
|
|
80
91
|
);
|
|
81
92
|
}
|
|
82
93
|
|
|
94
|
+
/*** Validate API and operation identities with an optional endpoint reference. */
|
|
83
95
|
function isBindingOperationRef(value: unknown): boolean {
|
|
84
96
|
return (
|
|
85
97
|
isRecord(value) &&
|
|
@@ -89,6 +101,7 @@ function isBindingOperationRef(value: unknown): boolean {
|
|
|
89
101
|
);
|
|
90
102
|
}
|
|
91
103
|
|
|
104
|
+
/*** Validate authored binding fallback values. */
|
|
92
105
|
function isBindingFallback(value: unknown): boolean {
|
|
93
106
|
return (
|
|
94
107
|
isRecord(value) &&
|
|
@@ -97,6 +110,7 @@ function isBindingFallback(value: unknown): boolean {
|
|
|
97
110
|
);
|
|
98
111
|
}
|
|
99
112
|
|
|
113
|
+
/*** Validate loading, empty and error binding behavior. */
|
|
100
114
|
function isBindingLifecycleBehavior(value: unknown): boolean {
|
|
101
115
|
return (
|
|
102
116
|
isRecord(value) &&
|
|
@@ -107,6 +121,7 @@ function isBindingLifecycleBehavior(value: unknown): boolean {
|
|
|
107
121
|
);
|
|
108
122
|
}
|
|
109
123
|
|
|
124
|
+
/*** Validate optional ordered binding transformations. */
|
|
110
125
|
function isOptionalBindingTransforms(value: unknown): boolean {
|
|
111
126
|
return (
|
|
112
127
|
value === undefined ||
|
|
@@ -115,10 +130,12 @@ function isOptionalBindingTransforms(value: unknown): boolean {
|
|
|
115
130
|
);
|
|
116
131
|
}
|
|
117
132
|
|
|
133
|
+
/*** Validate every value in an operation input mapping. */
|
|
118
134
|
function isBindingInputMap(value: unknown): boolean {
|
|
119
135
|
return isRecord(value) && Object.values(value).every(isBindingInputValue);
|
|
120
136
|
}
|
|
121
137
|
|
|
138
|
+
/*** Validate recursive array, object, literal and source operation inputs. */
|
|
122
139
|
function isBindingInputValue(value: unknown): boolean {
|
|
123
140
|
return (
|
|
124
141
|
isRecord(value) &&
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { AppManifest } from '../types';
|
|
2
|
+
|
|
3
|
+
export const APP_MANIFEST_KEY_POLICY = {
|
|
4
|
+
metadata: 'required',
|
|
5
|
+
themes: 'required',
|
|
6
|
+
activeThemeId: 'required',
|
|
7
|
+
activeThemeMode: 'optional',
|
|
8
|
+
splashScreen: 'optional',
|
|
9
|
+
media: 'optional',
|
|
10
|
+
deploy: 'optional',
|
|
11
|
+
state: 'optional',
|
|
12
|
+
infra: 'required',
|
|
13
|
+
navigator: 'required',
|
|
14
|
+
screens: 'required',
|
|
15
|
+
dataSources: 'optional',
|
|
16
|
+
dataBindings: 'optional',
|
|
17
|
+
repository: 'optional',
|
|
18
|
+
settings: 'required',
|
|
19
|
+
} as const satisfies Record<keyof AppManifest, 'optional' | 'required'>;
|
package/src/appManifest/data.ts
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
isStringArray,
|
|
7
|
-
} from './shared';
|
|
1
|
+
import { isStringArray } from '@ankhorage/utility/array';
|
|
2
|
+
import { isRecord } from '@ankhorage/utility/object';
|
|
3
|
+
import { isOptionalString } from '@ankhorage/utility/string';
|
|
4
|
+
|
|
5
|
+
import { isManifestValue } from './isManifestValue';
|
|
8
6
|
|
|
9
7
|
const DATA_SCHEMA_TYPES = new Set([
|
|
10
8
|
'array',
|
|
@@ -18,14 +16,17 @@ const DATA_SCHEMA_TYPES = new Set([
|
|
|
18
16
|
const OPERATION_INTENTS = new Set(['action', 'create', 'delete', 'read', 'update']);
|
|
19
17
|
const PARAMETER_LOCATIONS = new Set(['body', 'cookie', 'header', 'path', 'query']);
|
|
20
18
|
|
|
19
|
+
/*** Validate every endpoint in the data endpoint registry. */
|
|
21
20
|
export function isDataEndpointRegistry(value: unknown): boolean {
|
|
22
21
|
return isRecord(value) && Object.values(value).every(isDataEndpointConfig);
|
|
23
22
|
}
|
|
24
23
|
|
|
24
|
+
/*** Validate every schema in the data schema registry. */
|
|
25
25
|
export function isDataSchemaRegistry(value: unknown): boolean {
|
|
26
26
|
return isRecord(value) && Object.values(value).every(isDataSchema);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
/*** Validate credential identity and optional descriptive metadata. */
|
|
29
30
|
export function isCredentialRef(value: unknown): boolean {
|
|
30
31
|
return (
|
|
31
32
|
isRecord(value) &&
|
|
@@ -36,6 +37,7 @@ export function isCredentialRef(value: unknown): boolean {
|
|
|
36
37
|
);
|
|
37
38
|
}
|
|
38
39
|
|
|
40
|
+
/*** Validate an adapter reference and its optional authored configuration. */
|
|
39
41
|
export function isAdapterRef(value: unknown): boolean {
|
|
40
42
|
return (
|
|
41
43
|
isRecord(value) &&
|
|
@@ -47,6 +49,7 @@ export function isAdapterRef(value: unknown): boolean {
|
|
|
47
49
|
);
|
|
48
50
|
}
|
|
49
51
|
|
|
52
|
+
/*** Validate endpoint identity, operations and optional connection metadata. */
|
|
50
53
|
function isDataEndpointConfig(value: unknown): boolean {
|
|
51
54
|
return (
|
|
52
55
|
isRecord(value) &&
|
|
@@ -63,6 +66,7 @@ function isDataEndpointConfig(value: unknown): boolean {
|
|
|
63
66
|
);
|
|
64
67
|
}
|
|
65
68
|
|
|
69
|
+
/*** Validate operation protocol, intent, request and response configuration. */
|
|
66
70
|
function isDataOperationConfig(value: unknown): boolean {
|
|
67
71
|
return (
|
|
68
72
|
isRecord(value) &&
|
|
@@ -83,6 +87,7 @@ function isDataOperationConfig(value: unknown): boolean {
|
|
|
83
87
|
);
|
|
84
88
|
}
|
|
85
89
|
|
|
90
|
+
/*** Validate request schema, parameters and optional content type. */
|
|
86
91
|
function isDataOperationRequest(value: unknown): boolean {
|
|
87
92
|
return (
|
|
88
93
|
isRecord(value) &&
|
|
@@ -93,6 +98,7 @@ function isDataOperationRequest(value: unknown): boolean {
|
|
|
93
98
|
);
|
|
94
99
|
}
|
|
95
100
|
|
|
101
|
+
/*** Validate parameter identity, location, schema and optional default value. */
|
|
96
102
|
function isDataOperationParameter(value: unknown): boolean {
|
|
97
103
|
return (
|
|
98
104
|
isRecord(value) &&
|
|
@@ -100,12 +106,13 @@ function isDataOperationParameter(value: unknown): boolean {
|
|
|
100
106
|
typeof value.name === 'string' &&
|
|
101
107
|
typeof value.location === 'string' &&
|
|
102
108
|
PARAMETER_LOCATIONS.has(value.location) &&
|
|
103
|
-
|
|
109
|
+
(value.required === undefined || typeof value.required === 'boolean') &&
|
|
104
110
|
isOptionalString(value.description) &&
|
|
105
111
|
(value.default === undefined || isManifestValue(value.default))
|
|
106
112
|
);
|
|
107
113
|
}
|
|
108
114
|
|
|
115
|
+
/*** Validate response status, schema and optional descriptive metadata. */
|
|
109
116
|
function isDataOperationResponse(value: unknown): boolean {
|
|
110
117
|
return (
|
|
111
118
|
isRecord(value) &&
|
|
@@ -118,6 +125,7 @@ function isDataOperationResponse(value: unknown): boolean {
|
|
|
118
125
|
);
|
|
119
126
|
}
|
|
120
127
|
|
|
128
|
+
/*** Validate inline schema and schema-reference fields. */
|
|
121
129
|
function isDataSchemaSlot(value: Record<string, unknown>): boolean {
|
|
122
130
|
return (
|
|
123
131
|
(value.schema === undefined || isDataSchema(value.schema)) &&
|
|
@@ -125,6 +133,7 @@ function isDataSchemaSlot(value: Record<string, unknown>): boolean {
|
|
|
125
133
|
);
|
|
126
134
|
}
|
|
127
135
|
|
|
136
|
+
/*** Validate supported schema types, constraints and compositions. */
|
|
128
137
|
function isDataSchema(value: unknown): boolean {
|
|
129
138
|
if (!isRecord(value) || !isDataSchemaType(value.type)) return false;
|
|
130
139
|
if (!isOptionalSchemaScalars(value)) return false;
|
|
@@ -132,6 +141,7 @@ function isDataSchema(value: unknown): boolean {
|
|
|
132
141
|
return isOptionalSchemaComposition(value);
|
|
133
142
|
}
|
|
134
143
|
|
|
144
|
+
/*** Validate a supported schema type or an array of supported types. */
|
|
135
145
|
function isDataSchemaType(value: unknown): boolean {
|
|
136
146
|
if (value === undefined) return true;
|
|
137
147
|
if (typeof value === 'string') return DATA_SCHEMA_TYPES.has(value);
|
|
@@ -141,12 +151,13 @@ function isDataSchemaType(value: unknown): boolean {
|
|
|
141
151
|
);
|
|
142
152
|
}
|
|
143
153
|
|
|
154
|
+
/*** Validate optional scalar schema constraints. */
|
|
144
155
|
function isOptionalSchemaScalars(value: Record<string, unknown>): boolean {
|
|
145
156
|
return (
|
|
146
157
|
isOptionalString(value.title) &&
|
|
147
158
|
isOptionalString(value.description) &&
|
|
148
159
|
isOptionalString(value.format) &&
|
|
149
|
-
|
|
160
|
+
(value.nullable === undefined || typeof value.nullable === 'boolean') &&
|
|
150
161
|
(value.const === undefined || isManifestValue(value.const)) &&
|
|
151
162
|
(value.default === undefined || isManifestValue(value.default)) &&
|
|
152
163
|
(value.enum === undefined ||
|
|
@@ -155,6 +166,7 @@ function isOptionalSchemaScalars(value: Record<string, unknown>): boolean {
|
|
|
155
166
|
);
|
|
156
167
|
}
|
|
157
168
|
|
|
169
|
+
/*** Validate optional schema properties, items and required fields. */
|
|
158
170
|
function isOptionalSchemaCollections(value: Record<string, unknown>): boolean {
|
|
159
171
|
return (
|
|
160
172
|
(value.required === undefined || isStringArray(value.required)) &&
|
|
@@ -167,6 +179,7 @@ function isOptionalSchemaCollections(value: Record<string, unknown>): boolean {
|
|
|
167
179
|
);
|
|
168
180
|
}
|
|
169
181
|
|
|
182
|
+
/*** Validate optional schema alternatives and intersections. */
|
|
170
183
|
function isOptionalSchemaComposition(value: Record<string, unknown>): boolean {
|
|
171
184
|
return ['allOf', 'anyOf', 'oneOf'].every((key) => {
|
|
172
185
|
const entry = value[key];
|
|
@@ -174,6 +187,7 @@ function isOptionalSchemaComposition(value: Record<string, unknown>): boolean {
|
|
|
174
187
|
});
|
|
175
188
|
}
|
|
176
189
|
|
|
190
|
+
/*** Validate a named schema reference. */
|
|
177
191
|
function isDataSchemaRef(value: unknown): boolean {
|
|
178
192
|
return isRecord(value) && typeof value.id === 'string';
|
|
179
193
|
}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
+
import { hasOnlyKeys, isRecord } from '@ankhorage/utility/object';
|
|
2
|
+
import { isOptionalString } from '@ankhorage/utility/string';
|
|
3
|
+
|
|
1
4
|
import {
|
|
2
5
|
isAdapterRef,
|
|
3
6
|
isCredentialRef,
|
|
4
7
|
isDataEndpointRegistry,
|
|
5
8
|
isDataSchemaRegistry,
|
|
6
9
|
} from './data';
|
|
7
|
-
import { isManifestValue
|
|
10
|
+
import { isManifestValue } from './isManifestValue';
|
|
8
11
|
|
|
9
|
-
const DATABASE_SOURCE_KEYS =
|
|
12
|
+
const DATABASE_SOURCE_KEYS = [
|
|
10
13
|
'id',
|
|
11
14
|
'kind',
|
|
12
15
|
'name',
|
|
@@ -16,8 +19,9 @@ const DATABASE_SOURCE_KEYS = new Set([
|
|
|
16
19
|
'endpoints',
|
|
17
20
|
'schemas',
|
|
18
21
|
'metadata',
|
|
19
|
-
]
|
|
22
|
+
] as const;
|
|
20
23
|
|
|
24
|
+
/*** Validate the supported data-source entries in the registry. */
|
|
21
25
|
export function isDataSourceRegistry(value: unknown): boolean {
|
|
22
26
|
return (
|
|
23
27
|
isRecord(value) &&
|
|
@@ -25,6 +29,7 @@ export function isDataSourceRegistry(value: unknown): boolean {
|
|
|
25
29
|
);
|
|
26
30
|
}
|
|
27
31
|
|
|
32
|
+
/*** Validate database adapter identity and supported configuration fields. */
|
|
28
33
|
function isDatabaseDataSource(value: unknown): value is Record<string, unknown> {
|
|
29
34
|
return (
|
|
30
35
|
isRecord(value) &&
|
|
@@ -42,7 +47,3 @@ function isDatabaseDataSource(value: unknown): value is Record<string, unknown>
|
|
|
42
47
|
(value.metadata === undefined || isManifestValue(value.metadata))
|
|
43
48
|
);
|
|
44
49
|
}
|
|
45
|
-
|
|
46
|
-
function hasOnlyKeys(value: Record<string, unknown>, allowed: ReadonlySet<string>): boolean {
|
|
47
|
-
return Object.keys(value).every((key) => allowed.has(key));
|
|
48
|
-
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { hasOnlyKeys, isRecord } from '@ankhorage/utility/object';
|
|
2
|
+
import { isNonEmptyString } from '@ankhorage/utility/string';
|
|
3
|
+
|
|
1
4
|
import type {
|
|
2
5
|
AppDeployAndroidTargetConfig,
|
|
3
6
|
AppDeployIosTargetConfig,
|
|
@@ -6,20 +9,21 @@ import type {
|
|
|
6
9
|
AppDeployTargets,
|
|
7
10
|
AppDeployWebTargetConfig,
|
|
8
11
|
} from '../deploy';
|
|
9
|
-
import { isRecord } from './shared';
|
|
10
12
|
|
|
11
|
-
const DEPLOY_KEYS =
|
|
12
|
-
const TARGET_KEYS =
|
|
13
|
-
const PROVIDER_KEYS =
|
|
14
|
-
const WEB_KEYS =
|
|
15
|
-
const ANDROID_KEYS =
|
|
16
|
-
const IOS_KEYS =
|
|
13
|
+
const DEPLOY_KEYS = ['targets'] as const;
|
|
14
|
+
const TARGET_KEYS = ['web', 'android', 'ios'] as const;
|
|
15
|
+
const PROVIDER_KEYS = ['build', 'publish'] as const;
|
|
16
|
+
const WEB_KEYS = ['enabled', 'providers'] as const;
|
|
17
|
+
const ANDROID_KEYS = ['enabled', 'package', 'scheme', 'providers'] as const;
|
|
18
|
+
const IOS_KEYS = ['enabled', 'bundleIdentifier', 'scheme', 'providers'] as const;
|
|
17
19
|
const URI_SCHEME_PATTERN = /^[A-Za-z][A-Za-z0-9+.-]*$/u;
|
|
18
20
|
|
|
21
|
+
/*** Validate authored application deployment configuration. */
|
|
19
22
|
export function isAppDeployManifest(value: unknown): value is AppDeployManifest {
|
|
20
23
|
return isRecord(value) && hasOnlyKeys(value, DEPLOY_KEYS) && isAppDeployTargets(value.targets);
|
|
21
24
|
}
|
|
22
25
|
|
|
26
|
+
/*** Validate the optional web, Android and iOS deployment targets. */
|
|
23
27
|
function isAppDeployTargets(value: unknown): value is AppDeployTargets {
|
|
24
28
|
return (
|
|
25
29
|
isRecord(value) &&
|
|
@@ -30,6 +34,7 @@ function isAppDeployTargets(value: unknown): value is AppDeployTargets {
|
|
|
30
34
|
);
|
|
31
35
|
}
|
|
32
36
|
|
|
37
|
+
/*** Validate web deployment identity and provider selection. */
|
|
33
38
|
function isWebTarget(value: unknown): value is AppDeployWebTargetConfig {
|
|
34
39
|
return (
|
|
35
40
|
isRecord(value) &&
|
|
@@ -39,6 +44,7 @@ function isWebTarget(value: unknown): value is AppDeployWebTargetConfig {
|
|
|
39
44
|
);
|
|
40
45
|
}
|
|
41
46
|
|
|
47
|
+
/*** Validate Android deployment identity, scheme and provider selection. */
|
|
42
48
|
function isAndroidTarget(value: unknown): value is AppDeployAndroidTargetConfig {
|
|
43
49
|
return (
|
|
44
50
|
isRecord(value) &&
|
|
@@ -50,6 +56,7 @@ function isAndroidTarget(value: unknown): value is AppDeployAndroidTargetConfig
|
|
|
50
56
|
);
|
|
51
57
|
}
|
|
52
58
|
|
|
59
|
+
/*** Validate iOS deployment identity, scheme and provider selection. */
|
|
53
60
|
function isIosTarget(value: unknown): value is AppDeployIosTargetConfig {
|
|
54
61
|
return (
|
|
55
62
|
isRecord(value) &&
|
|
@@ -61,14 +68,17 @@ function isIosTarget(value: unknown): value is AppDeployIosTargetConfig {
|
|
|
61
68
|
);
|
|
62
69
|
}
|
|
63
70
|
|
|
71
|
+
/*** Accept an omitted scheme or a non-empty authored scheme. */
|
|
64
72
|
function isOptionalScheme(value: unknown): value is string | undefined {
|
|
65
73
|
return value === undefined || (typeof value === 'string' && URI_SCHEME_PATTERN.test(value));
|
|
66
74
|
}
|
|
67
75
|
|
|
76
|
+
/*** Accept omitted deployment providers or a valid provider selection. */
|
|
68
77
|
function isOptionalProviders(value: unknown): value is AppDeployProviderSelection | undefined {
|
|
69
78
|
return value === undefined || isProviderSelection(value);
|
|
70
79
|
}
|
|
71
80
|
|
|
81
|
+
/*** Validate deployment provider identities and supported selection keys. */
|
|
72
82
|
function isProviderSelection(value: unknown): value is AppDeployProviderSelection {
|
|
73
83
|
return (
|
|
74
84
|
isRecord(value) &&
|
|
@@ -77,11 +87,3 @@ function isProviderSelection(value: unknown): value is AppDeployProviderSelectio
|
|
|
77
87
|
(value.publish === undefined || isNonEmptyString(value.publish))
|
|
78
88
|
);
|
|
79
89
|
}
|
|
80
|
-
|
|
81
|
-
function isNonEmptyString(value: unknown): value is string {
|
|
82
|
-
return typeof value === 'string' && value.trim().length > 0;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function hasOnlyKeys(value: Record<string, unknown>, allowed: ReadonlySet<string>): boolean {
|
|
86
|
-
return Object.keys(value).every((key) => allowed.has(key));
|
|
87
|
-
}
|
package/src/appManifest/icon.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { isRecord } from '@ankhorage/utility/object';
|
|
2
|
+
import { isOptionalString } from '@ankhorage/utility/string';
|
|
3
|
+
|
|
1
4
|
import { isMediaAssetReference } from '../media';
|
|
2
|
-
import { isOptionalString, isRecord } from './shared';
|
|
3
5
|
|
|
4
6
|
/*** Validate a serializable icon as either a named font glyph or an SVG media reference. */
|
|
5
7
|
export function isIconSpec(value: unknown): boolean {
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { isStringArray } from '@ankhorage/utility/array';
|
|
2
|
+
import { isRecord } from '@ankhorage/utility/object';
|
|
3
|
+
|
|
4
|
+
import { isInfraManifest } from '../infra/isInfraManifest';
|
|
5
|
+
import type { AppManifest } from '../types';
|
|
6
|
+
import { isComponentDataBindingRegistry } from './bindings';
|
|
7
|
+
import { APP_MANIFEST_KEY_POLICY } from './constants';
|
|
8
|
+
import { isDataSourceRegistry } from './dataSources';
|
|
9
|
+
import { isAppDeployManifest } from './deploy';
|
|
10
|
+
import { isAppStateSpec } from './isAppStateSpec';
|
|
11
|
+
import { isMediaManifest } from './media';
|
|
12
|
+
import {
|
|
13
|
+
isAppNavigatorManifest,
|
|
14
|
+
isManifestMetadata,
|
|
15
|
+
isScreenRegistry,
|
|
16
|
+
isSplashScreenSpec,
|
|
17
|
+
isThemeConfig,
|
|
18
|
+
} from './screens';
|
|
19
|
+
|
|
20
|
+
/*** Return whether an unknown value satisfies the canonical AppManifest shape. */
|
|
21
|
+
export function isAppManifest(value: unknown): value is AppManifest {
|
|
22
|
+
return (
|
|
23
|
+
isRecord(value) &&
|
|
24
|
+
hasRequiredManifestKeys(value) &&
|
|
25
|
+
!('generatedApis' in value) &&
|
|
26
|
+
isManifestMetadata(value.metadata) &&
|
|
27
|
+
isPresentation(value) &&
|
|
28
|
+
isOptionalCapabilities(value) &&
|
|
29
|
+
isInfraManifest(value.infra) &&
|
|
30
|
+
isAppNavigatorManifest(value.navigator) &&
|
|
31
|
+
isScreenRegistry(value.screens) &&
|
|
32
|
+
isAppSettings(value.settings)
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/*** Validate the canonical application manifest field policy. */
|
|
37
|
+
function hasRequiredManifestKeys(value: Record<string, unknown>): boolean {
|
|
38
|
+
return Object.entries(APP_MANIFEST_KEY_POLICY).every(
|
|
39
|
+
([key, policy]) => policy === 'optional' || key in value,
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/*** Validate the canonical application manifest field policy. */
|
|
44
|
+
function isActiveThemeMode(value: unknown): boolean {
|
|
45
|
+
return value === undefined || value === 'dark' || value === 'light';
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/*** Validate the canonical application manifest field policy. */
|
|
49
|
+
function isRepositoryManifest(value: unknown): boolean {
|
|
50
|
+
return (
|
|
51
|
+
isRecord(value) &&
|
|
52
|
+
value.provider === 'github' &&
|
|
53
|
+
typeof value.owner === 'string' &&
|
|
54
|
+
value.owner.length > 0 &&
|
|
55
|
+
typeof value.name === 'string' &&
|
|
56
|
+
value.name.length > 0 &&
|
|
57
|
+
typeof value.url === 'string' &&
|
|
58
|
+
value.url.length > 0 &&
|
|
59
|
+
value.defaultBranch === 'main'
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/*** Validate the canonical application manifest field policy. */
|
|
64
|
+
function isAppSettings(value: unknown): boolean {
|
|
65
|
+
return (
|
|
66
|
+
isRecord(value) &&
|
|
67
|
+
!('apiBaseUrl' in value) &&
|
|
68
|
+
isRecord(value.localization) &&
|
|
69
|
+
typeof value.localization.defaultLocale === 'string' &&
|
|
70
|
+
isStringArray(value.localization.locales)
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/*** Validate authored appearance as one cohesive manifest concern. */
|
|
75
|
+
function isPresentation(value: Record<string, unknown>): boolean {
|
|
76
|
+
return (
|
|
77
|
+
Array.isArray(value.themes) &&
|
|
78
|
+
value.themes.every(isThemeConfig) &&
|
|
79
|
+
typeof value.activeThemeId === 'string' &&
|
|
80
|
+
isActiveThemeMode(value.activeThemeMode) &&
|
|
81
|
+
(value.splashScreen === undefined || isSplashScreenSpec(value.splashScreen)) &&
|
|
82
|
+
(value.media === undefined || isMediaManifest(value.media))
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/*** Validate independently optional application capability selections. */
|
|
87
|
+
function isOptionalCapabilities(value: Record<string, unknown>): boolean {
|
|
88
|
+
return (
|
|
89
|
+
(value.deploy === undefined || isAppDeployManifest(value.deploy)) &&
|
|
90
|
+
(value.state === undefined || isAppStateSpec(value.state)) &&
|
|
91
|
+
(value.dataSources === undefined || isDataSourceRegistry(value.dataSources)) &&
|
|
92
|
+
(value.dataBindings === undefined || isComponentDataBindingRegistry(value.dataBindings)) &&
|
|
93
|
+
(value.repository === undefined || isRepositoryManifest(value.repository))
|
|
94
|
+
);
|
|
95
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { isRecord } from '@ankhorage/utility/object';
|
|
2
|
+
|
|
3
|
+
import type { AppStateSpec } from '../state';
|
|
4
|
+
|
|
5
|
+
/*** Application state cannot claim persistence unsupported by the selected Legend adapter. */
|
|
6
|
+
export function isAppStateSpec(value: unknown): value is AppStateSpec {
|
|
7
|
+
return (
|
|
8
|
+
isRecord(value) &&
|
|
9
|
+
value.provider === 'legend' &&
|
|
10
|
+
(value.persistence === undefined || value.persistence === false) &&
|
|
11
|
+
Object.keys(value).every((key) => key === 'provider' || key === 'persistence')
|
|
12
|
+
);
|
|
13
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { isRecord } from '@ankhorage/utility/object';
|
|
2
|
+
|
|
3
|
+
/*** Validate the existing recursive ManifestValue domain used by authored bindings and API metadata. */
|
|
4
|
+
export function isManifestValue(value: unknown): boolean {
|
|
5
|
+
if (
|
|
6
|
+
value === null ||
|
|
7
|
+
typeof value === 'string' ||
|
|
8
|
+
typeof value === 'number' ||
|
|
9
|
+
typeof value === 'boolean'
|
|
10
|
+
) {
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (Array.isArray(value)) {
|
|
15
|
+
return value.every(isManifestValue);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return isRecord(value) && Object.values(value).every(isManifestValue);
|
|
19
|
+
}
|