@ankhorage/contracts 1.18.3 → 1.19.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.
- package/CHANGELOG.md +12 -0
- package/README.md +86 -0
- package/dist/cli.d.ts +23 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +2 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/package.json +12 -1
- package/src/cli.test.ts +88 -0
- package/src/cli.ts +27 -0
- package/src/contracts.test.ts +22 -1
- package/src/index.ts +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @ankhorage/contracts
|
|
2
2
|
|
|
3
|
+
## 1.19.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 37105b0: Add published ankh package metadata and document capability naming conventions.
|
|
8
|
+
|
|
9
|
+
## 1.19.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- b618979: Add `@ankhorage/contracts/cli` metadata contracts for Ankh package discovery.
|
|
14
|
+
|
|
3
15
|
## 1.18.3
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -22,6 +22,7 @@ Shared public contracts for Ankhorage packages and standalone provider packages.
|
|
|
22
22
|
```ts
|
|
23
23
|
import type { AppManifest } from '@ankhorage/contracts';
|
|
24
24
|
import type { AuthAdapter } from '@ankhorage/contracts/auth';
|
|
25
|
+
import type { AnkhCommandProviderManifest, AnkhPackageMetadata } from '@ankhorage/contracts/cli';
|
|
25
26
|
import type { DbAdapter } from '@ankhorage/contracts/db';
|
|
26
27
|
import type { StorageAdapter } from '@ankhorage/contracts/storage';
|
|
27
28
|
```
|
|
@@ -71,6 +72,91 @@ export function createSupabaseAuthAdapter(): AuthAdapter {
|
|
|
71
72
|
}
|
|
72
73
|
```
|
|
73
74
|
|
|
75
|
+
## CLI discovery contracts
|
|
76
|
+
|
|
77
|
+
`@ankhorage/contracts/cli` contains metadata-only discovery contracts for Ankh
|
|
78
|
+
packages and command providers.
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
import type { AnkhCommandProviderManifest, AnkhPackageMetadata } from '@ankhorage/contracts/cli';
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Provider packages expose `package.json.ankh` metadata using a package-relative
|
|
85
|
+
provider module path:
|
|
86
|
+
|
|
87
|
+
```json
|
|
88
|
+
{
|
|
89
|
+
"ankh": {
|
|
90
|
+
"category": "infra",
|
|
91
|
+
"provider": "./dist/ankh.provider.js",
|
|
92
|
+
"capabilities": ["infra.up", "infra.status"]
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Metadata-only packages use `null` for `provider`:
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"ankh": {
|
|
102
|
+
"category": "contracts",
|
|
103
|
+
"provider": null,
|
|
104
|
+
"capabilities": ["contracts.cli"]
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
`@ankhorage/contracts` now publishes this metadata shape directly from its own
|
|
110
|
+
`package.json`:
|
|
111
|
+
|
|
112
|
+
```json
|
|
113
|
+
{
|
|
114
|
+
"ankh": {
|
|
115
|
+
"category": "contracts",
|
|
116
|
+
"provider": null,
|
|
117
|
+
"capabilities": ["contracts.cli"]
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Command descriptor paths are relative to the provider category:
|
|
123
|
+
|
|
124
|
+
- `category: "infra"` with `path: ["up"]` maps to `ankh infra up`
|
|
125
|
+
- `category: "dev"` with `path: ["android", "scan"]` maps to `ankh dev android scan`
|
|
126
|
+
|
|
127
|
+
This subpath contains contracts only. It must not depend on `commander`,
|
|
128
|
+
`@ankhorage/ankh`, provider implementations, or runtime CLI execution logic.
|
|
129
|
+
|
|
130
|
+
Capability names are dot-separated package metadata identifiers.
|
|
131
|
+
|
|
132
|
+
Preferred forms:
|
|
133
|
+
|
|
134
|
+
- `<category>.<action>` for simple capabilities
|
|
135
|
+
- `<category>.<resource>.<action>` for nested or domain-specific capabilities
|
|
136
|
+
|
|
137
|
+
Valid examples:
|
|
138
|
+
|
|
139
|
+
- `infra.up`
|
|
140
|
+
- `templates.create`
|
|
141
|
+
- `contracts.cli`
|
|
142
|
+
- `board.web.import`
|
|
143
|
+
- `doctor.repo.validate`
|
|
144
|
+
- `dev.android.rebuild`
|
|
145
|
+
- `expoRuntime.plan`
|
|
146
|
+
|
|
147
|
+
Invalid examples:
|
|
148
|
+
|
|
149
|
+
- `infra`
|
|
150
|
+
- `infra-up`
|
|
151
|
+
- `.status`
|
|
152
|
+
- `infra.`
|
|
153
|
+
- `infra..up`
|
|
154
|
+
|
|
155
|
+
`AnkhCapabilityId` remains intentionally broad at the TypeScript level so
|
|
156
|
+
packages can publish stable serializable metadata without embedding policy
|
|
157
|
+
validation logic here. Stricter validation belongs later in
|
|
158
|
+
`@ankhorage/doctor`.
|
|
159
|
+
|
|
74
160
|
## Profile contract
|
|
75
161
|
|
|
76
162
|
Auth providers own identity records. App-facing profile data should be modeled separately, usually in an app table such as `profiles`.
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export type AnkhCommandCategory = string;
|
|
2
|
+
export type AnkhProviderReference = `./${string}`;
|
|
3
|
+
export type AnkhCapabilityId = `${string}.${string}`;
|
|
4
|
+
export interface AnkhCommandDescriptor {
|
|
5
|
+
readonly path: readonly [string, ...string[]];
|
|
6
|
+
readonly summary: string;
|
|
7
|
+
readonly capability: AnkhCapabilityId;
|
|
8
|
+
readonly aliases?: readonly string[];
|
|
9
|
+
readonly examples?: readonly string[];
|
|
10
|
+
}
|
|
11
|
+
export interface AnkhCommandProviderManifest {
|
|
12
|
+
readonly id: string;
|
|
13
|
+
readonly category: AnkhCommandCategory;
|
|
14
|
+
readonly version: string;
|
|
15
|
+
readonly capabilities: readonly AnkhCapabilityId[];
|
|
16
|
+
readonly commands: readonly AnkhCommandDescriptor[];
|
|
17
|
+
}
|
|
18
|
+
export interface AnkhPackageMetadata {
|
|
19
|
+
readonly category: AnkhCommandCategory;
|
|
20
|
+
readonly provider: AnkhProviderReference | null;
|
|
21
|
+
readonly capabilities: readonly AnkhCapabilityId[];
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC;AAEzC,MAAM,MAAM,qBAAqB,GAAG,KAAK,MAAM,EAAE,CAAC;AAElD,MAAM,MAAM,gBAAgB,GAAG,GAAG,MAAM,IAAI,MAAM,EAAE,CAAC;AAErD,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;IAC9C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC;IACtC,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACvC;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,YAAY,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACnD,QAAQ,CAAC,QAAQ,EAAE,SAAS,qBAAqB,EAAE,CAAC;CACrD;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC;IACvC,QAAQ,CAAC,QAAQ,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAChD,QAAQ,CAAC,YAAY,EAAE,SAAS,gBAAgB,EAAE,CAAC;CACpD"}
|
package/dist/cli.js
ADDED
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"","sourcesContent":["export type AnkhCommandCategory = string;\n\nexport type AnkhProviderReference = `./${string}`;\n\nexport type AnkhCapabilityId = `${string}.${string}`;\n\nexport interface AnkhCommandDescriptor {\n readonly path: readonly [string, ...string[]];\n readonly summary: string;\n readonly capability: AnkhCapabilityId;\n readonly aliases?: readonly string[];\n readonly examples?: readonly string[];\n}\n\nexport interface AnkhCommandProviderManifest {\n readonly id: string;\n readonly category: AnkhCommandCategory;\n readonly version: string;\n readonly capabilities: readonly AnkhCapabilityId[];\n readonly commands: readonly AnkhCommandDescriptor[];\n}\n\nexport interface AnkhPackageMetadata {\n readonly category: AnkhCommandCategory;\n readonly provider: AnkhProviderReference | null;\n readonly capabilities: readonly AnkhCapabilityId[];\n}\n"]}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,QAAQ,CAAC;AACvB,cAAc,MAAM,CAAC;AACrB,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,MAAM,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,OAAO,CAAC;AACtB,cAAc,QAAQ,CAAC;AACvB,cAAc,MAAM,CAAC;AACrB,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,MAAM,CAAC"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,QAAQ,CAAC;AACvB,cAAc,MAAM,CAAC;AACrB,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,MAAM,CAAC","sourcesContent":["export * from './auth';\nexport * from './bindings';\nexport * from './data';\nexport * from './db';\nexport * from './nutrition';\nexport * from './requirements';\nexport * from './state';\nexport * from './storage';\nexport * from './types';\nexport * from './ui';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,OAAO,CAAC;AACtB,cAAc,QAAQ,CAAC;AACvB,cAAc,MAAM,CAAC;AACrB,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,MAAM,CAAC","sourcesContent":["export * from './auth';\nexport * from './bindings';\nexport * from './cli';\nexport * from './data';\nexport * from './db';\nexport * from './nutrition';\nexport * from './requirements';\nexport * from './state';\nexport * from './storage';\nexport * from './types';\nexport * from './ui';\n"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ankhorage/contracts",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.19.1",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
|
+
"ankh": {
|
|
6
|
+
"category": "contracts",
|
|
7
|
+
"provider": null,
|
|
8
|
+
"capabilities": [
|
|
9
|
+
"contracts.cli"
|
|
10
|
+
]
|
|
11
|
+
},
|
|
5
12
|
"dependencies": {
|
|
6
13
|
"@ankhorage/color-theory": "^0.0.7"
|
|
7
14
|
},
|
|
@@ -25,6 +32,10 @@
|
|
|
25
32
|
"types": "./dist/bindings.d.ts",
|
|
26
33
|
"default": "./dist/bindings.js"
|
|
27
34
|
},
|
|
35
|
+
"./cli": {
|
|
36
|
+
"types": "./dist/cli.d.ts",
|
|
37
|
+
"default": "./dist/cli.js"
|
|
38
|
+
},
|
|
28
39
|
"./data": {
|
|
29
40
|
"types": "./dist/data/index.d.ts",
|
|
30
41
|
"default": "./dist/data/index.js"
|
package/src/cli.test.ts
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { describe, expect, it } from 'bun:test';
|
|
2
|
+
|
|
3
|
+
import type {
|
|
4
|
+
AnkhCapabilityId,
|
|
5
|
+
AnkhCommandDescriptor,
|
|
6
|
+
AnkhCommandProviderManifest,
|
|
7
|
+
AnkhPackageMetadata,
|
|
8
|
+
} from './index';
|
|
9
|
+
|
|
10
|
+
describe('cli contracts', () => {
|
|
11
|
+
it('accepts provider package metadata and provider manifests', () => {
|
|
12
|
+
const packageMetadata = {
|
|
13
|
+
category: 'infra',
|
|
14
|
+
provider: './dist/ankh.provider.js',
|
|
15
|
+
capabilities: ['infra.up', 'infra.status'],
|
|
16
|
+
} as const satisfies AnkhPackageMetadata;
|
|
17
|
+
|
|
18
|
+
const upCommand = {
|
|
19
|
+
path: ['up'],
|
|
20
|
+
summary: 'Bring project infrastructure up',
|
|
21
|
+
capability: 'infra.up',
|
|
22
|
+
aliases: ['start'],
|
|
23
|
+
examples: ['ankh infra up shop'],
|
|
24
|
+
} as const satisfies AnkhCommandDescriptor;
|
|
25
|
+
|
|
26
|
+
const manifest = {
|
|
27
|
+
id: '@ankhorage/infra',
|
|
28
|
+
category: 'infra',
|
|
29
|
+
version: '1.0.0',
|
|
30
|
+
capabilities: ['infra.up', 'infra.status'],
|
|
31
|
+
commands: [upCommand],
|
|
32
|
+
} as const satisfies AnkhCommandProviderManifest;
|
|
33
|
+
|
|
34
|
+
expect(JSON.parse(JSON.stringify(packageMetadata))).toEqual(packageMetadata);
|
|
35
|
+
expect(JSON.parse(JSON.stringify(manifest))).toEqual(manifest);
|
|
36
|
+
expect(manifest.id).toBe('@ankhorage/infra');
|
|
37
|
+
expect(manifest.category).toBe('infra');
|
|
38
|
+
expect(manifest.commands[0].path).toEqual(['up']);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('accepts metadata-only packages without a provider module', () => {
|
|
42
|
+
const packageMetadata = {
|
|
43
|
+
category: 'contracts',
|
|
44
|
+
provider: null,
|
|
45
|
+
capabilities: ['contracts.cli'],
|
|
46
|
+
} as const satisfies AnkhPackageMetadata;
|
|
47
|
+
|
|
48
|
+
expect(JSON.parse(JSON.stringify(packageMetadata))).toEqual(packageMetadata);
|
|
49
|
+
expect(packageMetadata.provider).toBeNull();
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('keeps command paths relative to the provider category', () => {
|
|
53
|
+
const androidScanCommand = {
|
|
54
|
+
path: ['android', 'scan'],
|
|
55
|
+
summary: 'Scan an Android target',
|
|
56
|
+
capability: 'dev.android.scan',
|
|
57
|
+
examples: ['ankh dev android scan'],
|
|
58
|
+
} as const satisfies AnkhCommandDescriptor;
|
|
59
|
+
|
|
60
|
+
const manifest = {
|
|
61
|
+
id: '@ankhorage/dev',
|
|
62
|
+
category: 'dev',
|
|
63
|
+
version: '1.0.0',
|
|
64
|
+
capabilities: ['dev.android.scan'],
|
|
65
|
+
commands: [androidScanCommand],
|
|
66
|
+
} as const satisfies AnkhCommandProviderManifest;
|
|
67
|
+
|
|
68
|
+
expect(manifest.category).toBe('dev');
|
|
69
|
+
expect(manifest.commands[0].path).toEqual(['android', 'scan']);
|
|
70
|
+
expect(manifest.commands[0].path[0]).not.toBe(manifest.category);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('accepts dot-separated capability ids for discovery metadata', () => {
|
|
74
|
+
const capabilities = [
|
|
75
|
+
'infra.up',
|
|
76
|
+
'templates.list',
|
|
77
|
+
'board.web.import',
|
|
78
|
+
'contracts.cli',
|
|
79
|
+
] as const satisfies readonly AnkhCapabilityId[];
|
|
80
|
+
|
|
81
|
+
expect(capabilities).toEqual([
|
|
82
|
+
'infra.up',
|
|
83
|
+
'templates.list',
|
|
84
|
+
'board.web.import',
|
|
85
|
+
'contracts.cli',
|
|
86
|
+
]);
|
|
87
|
+
});
|
|
88
|
+
});
|
package/src/cli.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export type AnkhCommandCategory = string;
|
|
2
|
+
|
|
3
|
+
export type AnkhProviderReference = `./${string}`;
|
|
4
|
+
|
|
5
|
+
export type AnkhCapabilityId = `${string}.${string}`;
|
|
6
|
+
|
|
7
|
+
export interface AnkhCommandDescriptor {
|
|
8
|
+
readonly path: readonly [string, ...string[]];
|
|
9
|
+
readonly summary: string;
|
|
10
|
+
readonly capability: AnkhCapabilityId;
|
|
11
|
+
readonly aliases?: readonly string[];
|
|
12
|
+
readonly examples?: readonly string[];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface AnkhCommandProviderManifest {
|
|
16
|
+
readonly id: string;
|
|
17
|
+
readonly category: AnkhCommandCategory;
|
|
18
|
+
readonly version: string;
|
|
19
|
+
readonly capabilities: readonly AnkhCapabilityId[];
|
|
20
|
+
readonly commands: readonly AnkhCommandDescriptor[];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface AnkhPackageMetadata {
|
|
24
|
+
readonly category: AnkhCommandCategory;
|
|
25
|
+
readonly provider: AnkhProviderReference | null;
|
|
26
|
+
readonly capabilities: readonly AnkhCapabilityId[];
|
|
27
|
+
}
|
package/src/contracts.test.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { COLOR_HARMONIES } from '@ankhorage/color-theory';
|
|
|
5
5
|
import { describe, expect, it } from 'bun:test';
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
|
+
type AnkhPackageMetadata,
|
|
8
9
|
APP_CATEGORIES,
|
|
9
10
|
type AppCategory,
|
|
10
11
|
type AppManifest,
|
|
@@ -56,6 +57,26 @@ async function collectTypeScriptFiles(directory: string): Promise<string[]> {
|
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
describe('contracts', () => {
|
|
60
|
+
it('exports the cli subpath for Ankh discovery contracts', async () => {
|
|
61
|
+
const expectedAnkhMetadata = {
|
|
62
|
+
category: 'contracts',
|
|
63
|
+
provider: null,
|
|
64
|
+
capabilities: ['contracts.cli'],
|
|
65
|
+
} as const satisfies AnkhPackageMetadata;
|
|
66
|
+
|
|
67
|
+
const packageJson = JSON.parse(await readFile(join(process.cwd(), 'package.json'), 'utf8')) as {
|
|
68
|
+
ankh?: unknown;
|
|
69
|
+
exports?: Record<string, { default?: string; types?: string }>;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
expect(packageJson.exports?.['./cli']).toEqual({
|
|
73
|
+
types: './dist/cli.d.ts',
|
|
74
|
+
default: './dist/cli.js',
|
|
75
|
+
});
|
|
76
|
+
expect(packageJson.ankh).toEqual(expectedAnkhMetadata);
|
|
77
|
+
expect(JSON.parse(JSON.stringify(expectedAnkhMetadata))).toEqual(expectedAnkhMetadata);
|
|
78
|
+
});
|
|
79
|
+
|
|
59
80
|
it('exports stable platform constants', () => {
|
|
60
81
|
expect(NAVIGATOR_TYPES).toEqual(['stack', 'tabs', 'drawer']);
|
|
61
82
|
expect(APP_CATEGORIES).toEqual([
|
|
@@ -213,7 +234,7 @@ describe('contracts', () => {
|
|
|
213
234
|
|
|
214
235
|
it('ThemeModeConfig.harmony accepts all ColorHarmony values', () => {
|
|
215
236
|
for (const harmony of COLOR_HARMONIES) {
|
|
216
|
-
const config
|
|
237
|
+
const config = { primaryColor: '#ff0000', harmony } satisfies ThemeModeConfig;
|
|
217
238
|
expect(config.harmony).toBe(harmony);
|
|
218
239
|
}
|
|
219
240
|
});
|