@ankhorage/contracts 7.9.0 → 8.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +1 -1
  3. package/dist/appManifest/apis.d.ts +3 -0
  4. package/dist/appManifest/apis.d.ts.map +1 -0
  5. package/dist/appManifest/apis.js +81 -0
  6. package/dist/appManifest/apis.js.map +1 -0
  7. package/dist/appManifest/bindings.js +1 -1
  8. package/dist/appManifest/bindings.js.map +1 -1
  9. package/dist/appManifest/data.d.ts +5 -0
  10. package/dist/appManifest/data.d.ts.map +1 -0
  11. package/dist/appManifest/data.js +140 -0
  12. package/dist/appManifest/data.js.map +1 -0
  13. package/dist/appManifest/dataSources.d.ts.map +1 -1
  14. package/dist/appManifest/dataSources.js +23 -120
  15. package/dist/appManifest/dataSources.js.map +1 -1
  16. package/dist/appManifest/infra.d.ts.map +1 -1
  17. package/dist/appManifest/infra.js +2 -0
  18. package/dist/appManifest/infra.js.map +1 -1
  19. package/dist/appManifest.d.ts.map +1 -1
  20. package/dist/appManifest.js +4 -6
  21. package/dist/appManifest.js.map +1 -1
  22. package/dist/bindings.d.ts +2 -2
  23. package/dist/bindings.d.ts.map +1 -1
  24. package/dist/bindings.js.map +1 -1
  25. package/dist/data/apis.d.ts +42 -38
  26. package/dist/data/apis.d.ts.map +1 -1
  27. package/dist/data/apis.js +1 -7
  28. package/dist/data/apis.js.map +1 -1
  29. package/dist/data/diagnostics.d.ts +3 -2
  30. package/dist/data/diagnostics.d.ts.map +1 -1
  31. package/dist/data/diagnostics.js.map +1 -1
  32. package/dist/data/ids.d.ts +1 -0
  33. package/dist/data/ids.d.ts.map +1 -1
  34. package/dist/data/ids.js.map +1 -1
  35. package/dist/data/sources.d.ts +5 -42
  36. package/dist/data/sources.d.ts.map +1 -1
  37. package/dist/data/sources.js.map +1 -1
  38. package/dist/requirements.d.ts +1 -1
  39. package/dist/requirements.d.ts.map +1 -1
  40. package/dist/requirements.js +1 -0
  41. package/dist/requirements.js.map +1 -1
  42. package/dist/types.d.ts +2 -3
  43. package/dist/types.d.ts.map +1 -1
  44. package/dist/types.js.map +1 -1
  45. package/package.json +1 -1
  46. package/src/appManifest/apis.ts +98 -0
  47. package/src/appManifest/bindings.ts +1 -1
  48. package/src/appManifest/data.ts +179 -0
  49. package/src/appManifest/dataSources.ts +30 -157
  50. package/src/appManifest/infra.ts +2 -0
  51. package/src/appManifest.test.ts +96 -40
  52. package/src/appManifest.ts +4 -6
  53. package/src/bindings.test.ts +36 -43
  54. package/src/bindings.ts +2 -2
  55. package/src/data/apis.test.ts +55 -45
  56. package/src/data/apis.ts +49 -46
  57. package/src/data/data.test.ts +19 -160
  58. package/src/data/diagnostics.ts +3 -1
  59. package/src/data/ids.ts +1 -0
  60. package/src/data/sources.ts +5 -53
  61. package/src/requirements.test.ts +23 -0
  62. package/src/requirements.ts +1 -0
  63. package/src/types.ts +2 -3
  64. package/dist/appManifest/generatedApis.d.ts +0 -2
  65. package/dist/appManifest/generatedApis.d.ts.map +0 -1
  66. package/dist/appManifest/generatedApis.js +0 -87
  67. package/dist/appManifest/generatedApis.js.map +0 -1
  68. package/src/appManifest/generatedApis.ts +0 -122
@@ -1,160 +1,13 @@
1
1
  import { describe, expect, it } from 'bun:test';
2
2
 
3
- import type {
4
- DatabaseDataSourceConfig,
5
- DataSourceConfig,
6
- DataSourceDiagnostic,
7
- ExternalGraphQlApiDataSourceConfig,
8
- ExternalRestApiDataSourceConfig,
9
- GeneratedRestApiDataSourceConfig,
10
- } from './index';
3
+ import type { DatabaseDataSourceConfig, DataSourceConfig, DataSourceDiagnostic } from './index';
11
4
 
12
5
  function assertSerializable<TValue>(value: TValue): void {
13
6
  expect(JSON.parse(JSON.stringify(value))).toEqual(value);
14
7
  }
15
8
 
16
9
  describe('data source contracts', () => {
17
- it('serializes an external REST API with manual operations', () => {
18
- const source: ExternalRestApiDataSourceConfig = {
19
- id: 'cms-rest',
20
- kind: 'api',
21
- origin: 'external',
22
- protocol: 'rest',
23
- name: 'CMS REST API',
24
- baseUrl: 'https://cms.example.com',
25
- credential: {
26
- id: 'cms-api-key',
27
- kind: 'apiKey',
28
- label: 'CMS API key',
29
- },
30
- endpoints: {
31
- posts: {
32
- id: 'posts',
33
- kind: 'http',
34
- path: '/posts',
35
- operations: {
36
- 'posts.list': {
37
- id: 'posts.list',
38
- endpointId: 'posts',
39
- protocol: 'http',
40
- intent: 'read',
41
- method: 'GET',
42
- path: '/posts',
43
- },
44
- },
45
- },
46
- },
47
- };
48
-
49
- assertSerializable(source);
50
- expect(source.endpoints.posts?.operations['posts.list']?.intent).toBe('read');
51
- });
52
-
53
- it('models OpenAPI as optional metadata on an external REST API', () => {
54
- const source: ExternalRestApiDataSourceConfig = {
55
- id: 'shop-api',
56
- kind: 'api',
57
- origin: 'external',
58
- protocol: 'rest',
59
- name: 'Shop API',
60
- baseUrl: 'https://shop.example.com/api',
61
- openApi: {
62
- url: 'https://shop.example.com/openapi.json',
63
- version: '2026-08-06',
64
- },
65
- endpoints: {},
66
- };
67
-
68
- assertSerializable(source);
69
- expect(source.openApi?.url).toContain('openapi.json');
70
- expect(source.kind).toBe('api');
71
- });
72
-
73
- it('serializes an external GraphQL API independently of origin', () => {
74
- const source: ExternalGraphQlApiDataSourceConfig = {
75
- id: 'content-graphql',
76
- kind: 'api',
77
- origin: 'external',
78
- protocol: 'graphql',
79
- endpointUrl: 'https://content.example.com/graphql',
80
- introspection: {
81
- enabled: true,
82
- schemaVersion: '2026-08-06',
83
- },
84
- endpoints: {
85
- graphql: {
86
- id: 'graphql',
87
- kind: 'graphql',
88
- operations: {
89
- PostsQuery: {
90
- id: 'PostsQuery',
91
- endpointId: 'graphql',
92
- protocol: 'graphql',
93
- intent: 'read',
94
- },
95
- },
96
- },
97
- },
98
- };
99
-
100
- assertSerializable(source);
101
- expect(source.protocol).toBe('graphql');
102
- expect(source.endpoints.graphql?.operations.PostsQuery?.intent).toBe('read');
103
- });
104
-
105
- it('serializes a normalized generated REST API projection', () => {
106
- const source: GeneratedRestApiDataSourceConfig = {
107
- id: 'catalog-api',
108
- kind: 'api',
109
- origin: 'generated',
110
- protocol: 'rest',
111
- generatedApiId: 'catalog-api',
112
- name: 'Catalog API',
113
- adapter: {
114
- id: 'primary-db',
115
- kind: 'database',
116
- packageName: '@ankhorage/supabase-db',
117
- },
118
- schemas: {
119
- products: {
120
- type: 'object',
121
- required: ['id', 'name'],
122
- properties: {
123
- id: { type: 'string', format: 'uuid' },
124
- name: { type: 'string' },
125
- },
126
- },
127
- },
128
- endpoints: {
129
- products: {
130
- id: 'products',
131
- kind: 'database',
132
- path: '/products',
133
- operations: {
134
- 'products.list': {
135
- id: 'products.list',
136
- endpointId: 'products',
137
- protocol: 'database',
138
- intent: 'read',
139
- },
140
- 'products.create': {
141
- id: 'products.create',
142
- endpointId: 'products',
143
- protocol: 'database',
144
- intent: 'create',
145
- },
146
- },
147
- },
148
- },
149
- };
150
-
151
- assertSerializable(source);
152
- expect(source.adapter.kind).toBe('database');
153
- expect(source.origin).toBe('generated');
154
- expect(source.endpoints.products?.operations['products.create']?.intent).toBe('create');
155
- });
156
-
157
- it('keeps database sources separate from API origin and protocol', () => {
10
+ it('keeps database sources separate from canonical APIs', () => {
158
11
  const source: DatabaseDataSourceConfig = {
159
12
  id: 'primary-db',
160
13
  kind: 'database',
@@ -164,27 +17,33 @@ describe('data source contracts', () => {
164
17
 
165
18
  assertSerializable(source);
166
19
  expect(source.kind).toBe('database');
20
+ expect('origin' in source).toBe(false);
21
+ expect('protocol' in source).toBe(false);
167
22
  });
168
23
 
169
- it('accepts a provider-neutral source union and diagnostics', () => {
24
+ it('keeps the data-source union database-specific', () => {
170
25
  const source: DataSourceConfig = {
171
- id: 'public-api',
172
- kind: 'api',
173
- origin: 'external',
174
- protocol: 'rest',
175
- baseUrl: 'https://public.example.com',
26
+ id: 'primary-db',
27
+ kind: 'database',
28
+ adapter: { id: 'database-adapter', kind: 'database' },
176
29
  endpoints: {},
177
30
  };
31
+
32
+ assertSerializable(source);
33
+ expect(source.adapter.kind).toBe('database');
34
+ });
35
+
36
+ it('supports API identity on shared data diagnostics', () => {
178
37
  const diagnostic: DataSourceDiagnostic = {
179
38
  code: 'missing-operation',
180
39
  severity: 'error',
181
40
  message: 'Operation not found.',
182
- dataSourceId: 'public-api',
183
- endpointId: 'posts',
184
- operationId: 'posts.list',
41
+ apiId: 'nutrition',
42
+ endpointId: 'products',
43
+ operationId: 'products.list',
185
44
  };
186
45
 
187
- assertSerializable({ source, diagnostic });
188
- expect(diagnostic.code).toBe('missing-operation');
46
+ assertSerializable(diagnostic);
47
+ expect(diagnostic.apiId).toBe('nutrition');
189
48
  });
190
49
  });
@@ -1,4 +1,4 @@
1
- import type { DataSourceId, EndpointId, OperationId } from './ids';
1
+ import type { ApiId, DataSourceId, EndpointId, OperationId } from './ids';
2
2
 
3
3
  export type DataDiagnosticSeverity = 'error' | 'info' | 'warning';
4
4
 
@@ -7,6 +7,7 @@ export type DataDiagnosticCode =
7
7
  | 'duplicate-operation-id'
8
8
  | 'invalid-config'
9
9
  | 'missing-adapter'
10
+ | 'missing-api'
10
11
  | 'missing-credential'
11
12
  | 'missing-data-source'
12
13
  | 'missing-endpoint'
@@ -22,6 +23,7 @@ export interface DataSourceDiagnostic {
22
23
  readonly code: DataDiagnosticCode;
23
24
  readonly message: string;
24
25
  readonly severity: DataDiagnosticSeverity;
26
+ readonly apiId?: ApiId;
25
27
  readonly dataSourceId?: DataSourceId;
26
28
  readonly endpointId?: EndpointId;
27
29
  readonly operationId?: OperationId;
package/src/data/ids.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export type ApiId = string;
1
2
  export type DataSourceId = string;
2
3
  export type EndpointId = string;
3
4
  export type OperationId = string;
@@ -4,67 +4,19 @@ import type { CredentialRef, DatabaseAdapterRef } from './refs';
4
4
  import type { DataSchemaRegistry } from './schemas';
5
5
  import type { DataContractValue } from './values';
6
6
 
7
- export type DataSourceKind = 'api' | 'database';
8
- export type ApiOrigin = 'external' | 'generated';
9
- export type ApiProtocol = 'graphql' | 'rest';
7
+ export type DataSourceKind = 'database';
10
8
 
11
- export interface DataSourceBaseConfig {
9
+ export interface DatabaseDataSourceConfig {
12
10
  readonly id: DataSourceId;
13
- readonly kind: DataSourceKind;
11
+ readonly kind: 'database';
14
12
  readonly name?: string;
15
13
  readonly description?: string;
16
14
  readonly credential?: CredentialRef;
15
+ readonly adapter: DatabaseAdapterRef;
17
16
  readonly endpoints: DataEndpointRegistry;
18
17
  readonly schemas?: DataSchemaRegistry;
19
18
  readonly metadata?: DataContractValue;
20
19
  }
21
20
 
22
- export interface ApiDataSourceBaseConfig extends DataSourceBaseConfig {
23
- readonly kind: 'api';
24
- readonly origin: ApiOrigin;
25
- readonly protocol: ApiProtocol;
26
- }
27
-
28
- export interface OpenApiDocumentRef {
29
- readonly url?: string;
30
- readonly documentId?: string;
31
- readonly version?: string;
32
- }
33
-
34
- export interface ExternalRestApiDataSourceConfig extends ApiDataSourceBaseConfig {
35
- readonly origin: 'external';
36
- readonly protocol: 'rest';
37
- readonly baseUrl: string;
38
- readonly openApi?: OpenApiDocumentRef;
39
- }
40
-
41
- export interface ExternalGraphQlApiDataSourceConfig extends ApiDataSourceBaseConfig {
42
- readonly origin: 'external';
43
- readonly protocol: 'graphql';
44
- readonly endpointUrl: string;
45
- readonly introspection?: {
46
- readonly enabled: boolean;
47
- readonly schemaVersion?: string;
48
- };
49
- }
50
-
51
- export interface GeneratedRestApiDataSourceConfig extends ApiDataSourceBaseConfig {
52
- readonly origin: 'generated';
53
- readonly protocol: 'rest';
54
- readonly generatedApiId: string;
55
- readonly adapter: DatabaseAdapterRef;
56
- }
57
-
58
- export type ApiDataSourceConfig =
59
- | ExternalGraphQlApiDataSourceConfig
60
- | ExternalRestApiDataSourceConfig
61
- | GeneratedRestApiDataSourceConfig;
62
-
63
- export interface DatabaseDataSourceConfig extends DataSourceBaseConfig {
64
- readonly kind: 'database';
65
- readonly adapter: DatabaseAdapterRef;
66
- }
67
-
68
- export type DataSourceConfig = ApiDataSourceConfig | DatabaseDataSourceConfig;
69
-
21
+ export type DataSourceConfig = DatabaseDataSourceConfig;
70
22
  export type DataSourceRegistry = Readonly<Record<DataSourceId, DataSourceConfig>>;
@@ -0,0 +1,23 @@
1
+ import { describe, expect, it } from 'bun:test';
2
+
3
+ import {
4
+ ANKHORAGE_CAPABILITY_NAMES,
5
+ type AnkhorageCapabilityName,
6
+ type ComponentRequirements,
7
+ type ScreenRequirements,
8
+ } from './index';
9
+
10
+ describe('platform requirements', () => {
11
+ it('exports ebookReader as the canonical reader capability', () => {
12
+ const capability: AnkhorageCapabilityName = 'ebookReader';
13
+ const componentRequirements: ComponentRequirements = {
14
+ capabilities: [{ capability }],
15
+ };
16
+ const screenRequirements: ScreenRequirements = {
17
+ capabilities: [{ capability }],
18
+ };
19
+
20
+ expect(ANKHORAGE_CAPABILITY_NAMES).toContain(capability);
21
+ expect(componentRequirements).toEqual(screenRequirements);
22
+ });
23
+ });
@@ -14,6 +14,7 @@ export type AnkhoragePermissionName = (typeof ANKHORAGE_PERMISSION_NAMES)[number
14
14
  export const ANKHORAGE_CAPABILITY_NAMES = [
15
15
  'barcodeScanner',
16
16
  'cameraPreview',
17
+ 'ebookReader',
17
18
  'mediaPicker',
18
19
  'filePicker',
19
20
  'location',
package/src/types.ts CHANGED
@@ -6,7 +6,7 @@ import type {
6
6
  ComponentDataBindingRegistry,
7
7
  ScreenDataLoaderDefinition,
8
8
  } from './bindings';
9
- import type { DataSourceRegistry, GeneratedApiRegistry } from './data';
9
+ import type { ApiDefinitionList, DataSourceRegistry } from './data';
10
10
  import type { AppDeployManifest } from './deploy';
11
11
  import type { MediaManifest } from './media';
12
12
  import type { ScreenRequirements } from './requirements';
@@ -374,12 +374,12 @@ export interface InfraManifest {
374
374
  storage?: StorageSpec;
375
375
  state?: StateSpec;
376
376
  networking?: NetworkingSpec;
377
+ apis?: ApiDefinitionList;
377
378
  modules: string[];
378
379
  modulesConfig?: Record<string, unknown>;
379
380
  }
380
381
 
381
382
  export interface AppSettings {
382
- apiBaseUrl?: string;
383
383
  localization: {
384
384
  defaultLocale: string;
385
385
  locales: string[];
@@ -407,7 +407,6 @@ export interface AppManifest {
407
407
  infra: InfraManifest;
408
408
  navigator: NavigatorSpec;
409
409
  screens: Record<string, ScreenSpec>;
410
- generatedApis?: GeneratedApiRegistry;
411
410
  dataSources?: DataSourceRegistry;
412
411
  dataBindings?: ComponentDataBindingRegistry;
413
412
  settings: AppSettings;
@@ -1,2 +0,0 @@
1
- export declare function isGeneratedApiRegistry(value: unknown): boolean;
2
- //# sourceMappingURL=generatedApis.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"generatedApis.d.ts","sourceRoot":"","sources":["../../src/appManifest/generatedApis.ts"],"names":[],"mappings":"AAQA,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAE9D"}
@@ -1,87 +0,0 @@
1
- import { isManifestValue, isOptionalBoolean, isOptionalString, isRecord, isStringArray, } from './shared';
2
- export function isGeneratedApiRegistry(value) {
3
- return isRecord(value) && Object.values(value).every(isGeneratedApiDefinition);
4
- }
5
- function isGeneratedApiDefinition(value) {
6
- return (isRecord(value) &&
7
- typeof value.id === 'string' &&
8
- value.protocol === 'rest' &&
9
- isOptionalString(value.name) &&
10
- isOptionalString(value.description) &&
11
- typeof value.basePath === 'string' &&
12
- isDatabaseAdapterRef(value.database) &&
13
- Array.isArray(value.resources) &&
14
- value.resources.every(isGeneratedApiResourceDefinition) &&
15
- (value.auth === undefined || isGeneratedApiAuthRequirement(value.auth)) &&
16
- (value.metadata === undefined || isManifestValue(value.metadata)));
17
- }
18
- function isDatabaseAdapterRef(value) {
19
- return isRecord(value) && value.kind === 'database' && isAdapterRef(value);
20
- }
21
- function isGeneratedApiAuthRequirement(value) {
22
- return (isRecord(value) &&
23
- isOptionalBoolean(value.required) &&
24
- (value.roles === undefined || isStringArray(value.roles)) &&
25
- (value.permissions === undefined || isStringArray(value.permissions)) &&
26
- isOptionalString(value.policy) &&
27
- (value.metadata === undefined || isManifestValue(value.metadata)));
28
- }
29
- function isGeneratedApiResourceDefinition(value) {
30
- return (isRecord(value) &&
31
- typeof value.id === 'string' &&
32
- isOptionalString(value.name) &&
33
- isOptionalString(value.description) &&
34
- typeof value.path === 'string' &&
35
- isDbCollectionDefinition(value.collection) &&
36
- Array.isArray(value.operations) &&
37
- value.operations.every(isGeneratedApiCrudOperation) &&
38
- (value.seed === undefined || isSeedRecords(value.seed)) &&
39
- (value.policies === undefined ||
40
- (Array.isArray(value.policies) && value.policies.every(isGeneratedApiPolicyRef))) &&
41
- (value.metadata === undefined || isManifestValue(value.metadata)));
42
- }
43
- function isSeedRecords(value) {
44
- return (Array.isArray(value) &&
45
- value.every((record) => isRecord(record) && Object.values(record).every(isManifestValue)));
46
- }
47
- function isGeneratedApiCrudOperation(value) {
48
- return ['create', 'delete', 'list', 'read', 'update'].includes(String(value));
49
- }
50
- function isGeneratedApiPolicyRef(value) {
51
- return (isRecord(value) &&
52
- typeof value.id === 'string' &&
53
- (value.operation === undefined || isGeneratedApiCrudOperation(value.operation)));
54
- }
55
- function isDbCollectionDefinition(value) {
56
- return (isRecord(value) &&
57
- typeof value.name === 'string' &&
58
- isOptionalString(value.schema) &&
59
- Array.isArray(value.fields) &&
60
- value.fields.every(isDbFieldDefinition) &&
61
- isOptionalString(value.primaryKey));
62
- }
63
- function isDbFieldDefinition(value) {
64
- return (isRecord(value) &&
65
- typeof value.name === 'string' &&
66
- typeof value.type === 'string' &&
67
- ['text', 'number', 'boolean', 'datetime', 'json', 'uuid'].includes(value.type) &&
68
- isOptionalBoolean(value.required) &&
69
- isOptionalBoolean(value.unique) &&
70
- isDbDefaultValue(value.defaultValue));
71
- }
72
- function isDbDefaultValue(value) {
73
- return (value === undefined ||
74
- value === null ||
75
- typeof value === 'boolean' ||
76
- typeof value === 'number' ||
77
- typeof value === 'string');
78
- }
79
- function isAdapterRef(value) {
80
- return (isRecord(value) &&
81
- typeof value.id === 'string' &&
82
- typeof value.kind === 'string' &&
83
- isOptionalString(value.packageName) &&
84
- isOptionalString(value.exportName) &&
85
- (value.config === undefined || isManifestValue(value.config)));
86
- }
87
- //# sourceMappingURL=generatedApis.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"generatedApis.js","sourceRoot":"","sources":["../../src/appManifest/generatedApis.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n isManifestValue,\n isOptionalBoolean,\n isOptionalString,\n isRecord,\n isStringArray,\n} from './shared';\n\nexport function isGeneratedApiRegistry(value: unknown): boolean {\n return isRecord(value) && Object.values(value).every(isGeneratedApiDefinition);\n}\n\nfunction isGeneratedApiDefinition(value: unknown): boolean {\n return (\n isRecord(value) &&\n typeof value.id === 'string' &&\n value.protocol === 'rest' &&\n isOptionalString(value.name) &&\n isOptionalString(value.description) &&\n typeof value.basePath === 'string' &&\n isDatabaseAdapterRef(value.database) &&\n Array.isArray(value.resources) &&\n value.resources.every(isGeneratedApiResourceDefinition) &&\n (value.auth === undefined || isGeneratedApiAuthRequirement(value.auth)) &&\n (value.metadata === undefined || isManifestValue(value.metadata))\n );\n}\n\nfunction isDatabaseAdapterRef(value: unknown): boolean {\n return isRecord(value) && value.kind === 'database' && isAdapterRef(value);\n}\n\nfunction isGeneratedApiAuthRequirement(value: unknown): boolean {\n return (\n isRecord(value) &&\n isOptionalBoolean(value.required) &&\n (value.roles === undefined || isStringArray(value.roles)) &&\n (value.permissions === undefined || isStringArray(value.permissions)) &&\n isOptionalString(value.policy) &&\n (value.metadata === undefined || isManifestValue(value.metadata))\n );\n}\n\nfunction isGeneratedApiResourceDefinition(value: unknown): boolean {\n return (\n isRecord(value) &&\n typeof value.id === 'string' &&\n isOptionalString(value.name) &&\n isOptionalString(value.description) &&\n typeof value.path === 'string' &&\n isDbCollectionDefinition(value.collection) &&\n Array.isArray(value.operations) &&\n value.operations.every(isGeneratedApiCrudOperation) &&\n (value.seed === undefined || isSeedRecords(value.seed)) &&\n (value.policies === undefined ||\n (Array.isArray(value.policies) && value.policies.every(isGeneratedApiPolicyRef))) &&\n (value.metadata === undefined || isManifestValue(value.metadata))\n );\n}\n\nfunction isSeedRecords(value: unknown): boolean {\n return (\n Array.isArray(value) &&\n value.every((record) => isRecord(record) && Object.values(record).every(isManifestValue))\n );\n}\n\nfunction isGeneratedApiCrudOperation(value: unknown): boolean {\n return ['create', 'delete', 'list', 'read', 'update'].includes(String(value));\n}\n\nfunction isGeneratedApiPolicyRef(value: unknown): boolean {\n return (\n isRecord(value) &&\n typeof value.id === 'string' &&\n (value.operation === undefined || isGeneratedApiCrudOperation(value.operation))\n );\n}\n\nfunction isDbCollectionDefinition(value: unknown): boolean {\n return (\n isRecord(value) &&\n typeof value.name === 'string' &&\n isOptionalString(value.schema) &&\n Array.isArray(value.fields) &&\n value.fields.every(isDbFieldDefinition) &&\n isOptionalString(value.primaryKey)\n );\n}\n\nfunction isDbFieldDefinition(value: unknown): boolean {\n return (\n isRecord(value) &&\n typeof value.name === 'string' &&\n typeof value.type === 'string' &&\n ['text', 'number', 'boolean', 'datetime', 'json', 'uuid'].includes(value.type) &&\n isOptionalBoolean(value.required) &&\n isOptionalBoolean(value.unique) &&\n isDbDefaultValue(value.defaultValue)\n );\n}\n\nfunction isDbDefaultValue(value: unknown): boolean {\n return (\n value === undefined ||\n value === null ||\n typeof value === 'boolean' ||\n typeof value === 'number' ||\n typeof value === 'string'\n );\n}\n\nfunction isAdapterRef(value: unknown): boolean {\n return (\n isRecord(value) &&\n typeof value.id === 'string' &&\n typeof value.kind === 'string' &&\n isOptionalString(value.packageName) &&\n isOptionalString(value.exportName) &&\n (value.config === undefined || isManifestValue(value.config))\n );\n}\n"]}
@@ -1,122 +0,0 @@
1
- import {
2
- isManifestValue,
3
- isOptionalBoolean,
4
- isOptionalString,
5
- isRecord,
6
- isStringArray,
7
- } from './shared';
8
-
9
- export function isGeneratedApiRegistry(value: unknown): boolean {
10
- return isRecord(value) && Object.values(value).every(isGeneratedApiDefinition);
11
- }
12
-
13
- function isGeneratedApiDefinition(value: unknown): boolean {
14
- return (
15
- isRecord(value) &&
16
- typeof value.id === 'string' &&
17
- value.protocol === 'rest' &&
18
- isOptionalString(value.name) &&
19
- isOptionalString(value.description) &&
20
- typeof value.basePath === 'string' &&
21
- isDatabaseAdapterRef(value.database) &&
22
- Array.isArray(value.resources) &&
23
- value.resources.every(isGeneratedApiResourceDefinition) &&
24
- (value.auth === undefined || isGeneratedApiAuthRequirement(value.auth)) &&
25
- (value.metadata === undefined || isManifestValue(value.metadata))
26
- );
27
- }
28
-
29
- function isDatabaseAdapterRef(value: unknown): boolean {
30
- return isRecord(value) && value.kind === 'database' && isAdapterRef(value);
31
- }
32
-
33
- function isGeneratedApiAuthRequirement(value: unknown): boolean {
34
- return (
35
- isRecord(value) &&
36
- isOptionalBoolean(value.required) &&
37
- (value.roles === undefined || isStringArray(value.roles)) &&
38
- (value.permissions === undefined || isStringArray(value.permissions)) &&
39
- isOptionalString(value.policy) &&
40
- (value.metadata === undefined || isManifestValue(value.metadata))
41
- );
42
- }
43
-
44
- function isGeneratedApiResourceDefinition(value: unknown): boolean {
45
- return (
46
- isRecord(value) &&
47
- typeof value.id === 'string' &&
48
- isOptionalString(value.name) &&
49
- isOptionalString(value.description) &&
50
- typeof value.path === 'string' &&
51
- isDbCollectionDefinition(value.collection) &&
52
- Array.isArray(value.operations) &&
53
- value.operations.every(isGeneratedApiCrudOperation) &&
54
- (value.seed === undefined || isSeedRecords(value.seed)) &&
55
- (value.policies === undefined ||
56
- (Array.isArray(value.policies) && value.policies.every(isGeneratedApiPolicyRef))) &&
57
- (value.metadata === undefined || isManifestValue(value.metadata))
58
- );
59
- }
60
-
61
- function isSeedRecords(value: unknown): boolean {
62
- return (
63
- Array.isArray(value) &&
64
- value.every((record) => isRecord(record) && Object.values(record).every(isManifestValue))
65
- );
66
- }
67
-
68
- function isGeneratedApiCrudOperation(value: unknown): boolean {
69
- return ['create', 'delete', 'list', 'read', 'update'].includes(String(value));
70
- }
71
-
72
- function isGeneratedApiPolicyRef(value: unknown): boolean {
73
- return (
74
- isRecord(value) &&
75
- typeof value.id === 'string' &&
76
- (value.operation === undefined || isGeneratedApiCrudOperation(value.operation))
77
- );
78
- }
79
-
80
- function isDbCollectionDefinition(value: unknown): boolean {
81
- return (
82
- isRecord(value) &&
83
- typeof value.name === 'string' &&
84
- isOptionalString(value.schema) &&
85
- Array.isArray(value.fields) &&
86
- value.fields.every(isDbFieldDefinition) &&
87
- isOptionalString(value.primaryKey)
88
- );
89
- }
90
-
91
- function isDbFieldDefinition(value: unknown): boolean {
92
- return (
93
- isRecord(value) &&
94
- typeof value.name === 'string' &&
95
- typeof value.type === 'string' &&
96
- ['text', 'number', 'boolean', 'datetime', 'json', 'uuid'].includes(value.type) &&
97
- isOptionalBoolean(value.required) &&
98
- isOptionalBoolean(value.unique) &&
99
- isDbDefaultValue(value.defaultValue)
100
- );
101
- }
102
-
103
- function isDbDefaultValue(value: unknown): boolean {
104
- return (
105
- value === undefined ||
106
- value === null ||
107
- typeof value === 'boolean' ||
108
- typeof value === 'number' ||
109
- typeof value === 'string'
110
- );
111
- }
112
-
113
- function isAdapterRef(value: unknown): boolean {
114
- return (
115
- isRecord(value) &&
116
- typeof value.id === 'string' &&
117
- typeof value.kind === 'string' &&
118
- isOptionalString(value.packageName) &&
119
- isOptionalString(value.exportName) &&
120
- (value.config === undefined || isManifestValue(value.config))
121
- );
122
- }