@ankhorage/contracts 7.6.0 → 7.7.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 +6 -0
- package/README.md +1 -1
- package/dist/appManifest/deploy.d.ts.map +1 -1
- package/dist/appManifest/deploy.js +8 -2
- package/dist/appManifest/deploy.js.map +1 -1
- package/dist/deploy.d.ts +13 -0
- package/dist/deploy.d.ts.map +1 -1
- package/dist/deploy.js +8 -0
- package/dist/deploy.js.map +1 -1
- package/package.json +1 -1
- package/src/appManifest/deploy.ts +9 -2
- package/src/deploy.test.ts +56 -3
- package/src/deploy.ts +15 -0
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
# CONTRACTS
|
|
5
5
|
|
|
6
|
-
         
|
|
7
7
|
|
|
8
8
|
Serializable app, action, theme, auth, and secret-store contracts for Ankhorage.
|
|
9
9
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/appManifest/deploy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,iBAAiB,EAIlB,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/appManifest/deploy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,iBAAiB,EAIlB,MAAM,WAAW,CAAC;AAWnB,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,iBAAiB,CAE9E"}
|
|
@@ -3,8 +3,9 @@ const DEPLOY_KEYS = new Set(['targets']);
|
|
|
3
3
|
const TARGET_KEYS = new Set(['web', 'android', 'ios']);
|
|
4
4
|
const PROVIDER_KEYS = new Set(['build', 'publish']);
|
|
5
5
|
const WEB_KEYS = new Set(['enabled', 'providers']);
|
|
6
|
-
const ANDROID_KEYS = new Set(['enabled', 'package', 'providers']);
|
|
7
|
-
const IOS_KEYS = new Set(['enabled', 'bundleIdentifier', 'providers']);
|
|
6
|
+
const ANDROID_KEYS = new Set(['enabled', 'package', 'scheme', 'providers']);
|
|
7
|
+
const IOS_KEYS = new Set(['enabled', 'bundleIdentifier', 'scheme', 'providers']);
|
|
8
|
+
const URI_SCHEME_PATTERN = /^[A-Za-z][A-Za-z0-9+.-]*$/u;
|
|
8
9
|
export function isAppDeployManifest(value) {
|
|
9
10
|
return isRecord(value) && hasOnlyKeys(value, DEPLOY_KEYS) && isAppDeployTargets(value.targets);
|
|
10
11
|
}
|
|
@@ -26,6 +27,7 @@ function isAndroidTarget(value) {
|
|
|
26
27
|
hasOnlyKeys(value, ANDROID_KEYS) &&
|
|
27
28
|
typeof value.enabled === 'boolean' &&
|
|
28
29
|
isNonEmptyString(value.package) &&
|
|
30
|
+
isOptionalScheme(value.scheme) &&
|
|
29
31
|
isOptionalProviders(value.providers));
|
|
30
32
|
}
|
|
31
33
|
function isIosTarget(value) {
|
|
@@ -33,8 +35,12 @@ function isIosTarget(value) {
|
|
|
33
35
|
hasOnlyKeys(value, IOS_KEYS) &&
|
|
34
36
|
typeof value.enabled === 'boolean' &&
|
|
35
37
|
isNonEmptyString(value.bundleIdentifier) &&
|
|
38
|
+
isOptionalScheme(value.scheme) &&
|
|
36
39
|
isOptionalProviders(value.providers));
|
|
37
40
|
}
|
|
41
|
+
function isOptionalScheme(value) {
|
|
42
|
+
return value === undefined || (typeof value === 'string' && URI_SCHEME_PATTERN.test(value));
|
|
43
|
+
}
|
|
38
44
|
function isOptionalProviders(value) {
|
|
39
45
|
return value === undefined || isProviderSelection(value);
|
|
40
46
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deploy.js","sourceRoot":"","sources":["../../src/appManifest/deploy.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpC,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;AACzC,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;AACvD,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;AACpD,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC;AACnD,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,CAAC,SAAS,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"deploy.js","sourceRoot":"","sources":["../../src/appManifest/deploy.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AppDeployAndroidTargetConfig,\n AppDeployIosTargetConfig,\n AppDeployManifest,\n AppDeployProviderSelection,\n AppDeployTargets,\n AppDeployWebTargetConfig,\n} from '../deploy';\nimport { isRecord } from './shared';\n\nconst DEPLOY_KEYS = new Set(['targets']);\nconst TARGET_KEYS = new Set(['web', 'android', 'ios']);\nconst PROVIDER_KEYS = new Set(['build', 'publish']);\nconst WEB_KEYS = new Set(['enabled', 'providers']);\nconst ANDROID_KEYS = new Set(['enabled', 'package', 'scheme', 'providers']);\nconst IOS_KEYS = new Set(['enabled', 'bundleIdentifier', 'scheme', 'providers']);\nconst URI_SCHEME_PATTERN = /^[A-Za-z][A-Za-z0-9+.-]*$/u;\n\nexport function isAppDeployManifest(value: unknown): value is AppDeployManifest {\n return isRecord(value) && hasOnlyKeys(value, DEPLOY_KEYS) && isAppDeployTargets(value.targets);\n}\n\nfunction isAppDeployTargets(value: unknown): value is AppDeployTargets {\n return (\n isRecord(value) &&\n hasOnlyKeys(value, TARGET_KEYS) &&\n (value.web === undefined || isWebTarget(value.web)) &&\n (value.android === undefined || isAndroidTarget(value.android)) &&\n (value.ios === undefined || isIosTarget(value.ios))\n );\n}\n\nfunction isWebTarget(value: unknown): value is AppDeployWebTargetConfig {\n return (\n isRecord(value) &&\n hasOnlyKeys(value, WEB_KEYS) &&\n typeof value.enabled === 'boolean' &&\n isOptionalProviders(value.providers)\n );\n}\n\nfunction isAndroidTarget(value: unknown): value is AppDeployAndroidTargetConfig {\n return (\n isRecord(value) &&\n hasOnlyKeys(value, ANDROID_KEYS) &&\n typeof value.enabled === 'boolean' &&\n isNonEmptyString(value.package) &&\n isOptionalScheme(value.scheme) &&\n isOptionalProviders(value.providers)\n );\n}\n\nfunction isIosTarget(value: unknown): value is AppDeployIosTargetConfig {\n return (\n isRecord(value) &&\n hasOnlyKeys(value, IOS_KEYS) &&\n typeof value.enabled === 'boolean' &&\n isNonEmptyString(value.bundleIdentifier) &&\n isOptionalScheme(value.scheme) &&\n isOptionalProviders(value.providers)\n );\n}\n\nfunction isOptionalScheme(value: unknown): value is string | undefined {\n return value === undefined || (typeof value === 'string' && URI_SCHEME_PATTERN.test(value));\n}\n\nfunction isOptionalProviders(value: unknown): value is AppDeployProviderSelection | undefined {\n return value === undefined || isProviderSelection(value);\n}\n\nfunction isProviderSelection(value: unknown): value is AppDeployProviderSelection {\n return (\n isRecord(value) &&\n hasOnlyKeys(value, PROVIDER_KEYS) &&\n (value.build === undefined || isNonEmptyString(value.build)) &&\n (value.publish === undefined || isNonEmptyString(value.publish))\n );\n}\n\nfunction isNonEmptyString(value: unknown): value is string {\n return typeof value === 'string' && value.trim().length > 0;\n}\n\nfunction hasOnlyKeys(value: Record<string, unknown>, allowed: ReadonlySet<string>): boolean {\n return Object.keys(value).every((key) => allowed.has(key));\n}\n"]}
|
package/dist/deploy.d.ts
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
export declare const APP_DEPLOY_TARGET_IDS: readonly ["web", "android", "ios"];
|
|
2
2
|
export type AppDeployTargetId = (typeof APP_DEPLOY_TARGET_IDS)[number];
|
|
3
|
+
/**
|
|
4
|
+
* Logical application environments shared across platform-specific planning.
|
|
5
|
+
*
|
|
6
|
+
* `local` maps to local Web, iOS development, and Android debug execution.
|
|
7
|
+
* Environment-specific endpoints, signing material, and credentials are owned
|
|
8
|
+
* by their dedicated deployment/infra configuration rather than this identity contract.
|
|
9
|
+
*/
|
|
10
|
+
export declare const APP_DEPLOY_ENVIRONMENT_IDS: readonly ["local", "preview", "production"];
|
|
11
|
+
export type AppDeployEnvironmentId = (typeof APP_DEPLOY_ENVIRONMENT_IDS)[number];
|
|
3
12
|
export interface AppDeployProviderSelection {
|
|
4
13
|
readonly build?: string;
|
|
5
14
|
readonly publish?: string;
|
|
@@ -11,11 +20,15 @@ export interface AppDeployWebTargetConfig {
|
|
|
11
20
|
export interface AppDeployAndroidTargetConfig {
|
|
12
21
|
readonly enabled: boolean;
|
|
13
22
|
readonly package: string;
|
|
23
|
+
/** Stable application URI scheme used for target-aware deep links such as OAuth callbacks. */
|
|
24
|
+
readonly scheme?: string;
|
|
14
25
|
readonly providers?: AppDeployProviderSelection;
|
|
15
26
|
}
|
|
16
27
|
export interface AppDeployIosTargetConfig {
|
|
17
28
|
readonly enabled: boolean;
|
|
18
29
|
readonly bundleIdentifier: string;
|
|
30
|
+
/** Stable application URI scheme used for target-aware deep links such as OAuth callbacks. */
|
|
31
|
+
readonly scheme?: string;
|
|
19
32
|
readonly providers?: AppDeployProviderSelection;
|
|
20
33
|
}
|
|
21
34
|
export interface AppDeployTargets {
|
package/dist/deploy.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../src/deploy.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,qBAAqB,oCAAqC,CAAC;AAExE,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvE,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,SAAS,CAAC,EAAE,0BAA0B,CAAC;CACjD;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,CAAC,EAAE,0BAA0B,CAAC;CACjD;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,SAAS,CAAC,EAAE,0BAA0B,CAAC;CACjD;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,GAAG,CAAC,EAAE,wBAAwB,CAAC;IACxC,QAAQ,CAAC,OAAO,CAAC,EAAE,4BAA4B,CAAC;IAChD,QAAQ,CAAC,GAAG,CAAC,EAAE,wBAAwB,CAAC;CACzC;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAC;CACpC;AAED,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../src/deploy.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,qBAAqB,oCAAqC,CAAC;AAExE,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvE;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,6CAA8C,CAAC;AAEtF,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,0BAA0B,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjF,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,SAAS,CAAC,EAAE,0BAA0B,CAAC;CACjD;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,8FAA8F;IAC9F,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,CAAC,EAAE,0BAA0B,CAAC;CACjD;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,8FAA8F;IAC9F,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,CAAC,EAAE,0BAA0B,CAAC;CACjD;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,GAAG,CAAC,EAAE,wBAAwB,CAAC;IACxC,QAAQ,CAAC,OAAO,CAAC,EAAE,4BAA4B,CAAC;IAChD,QAAQ,CAAC,GAAG,CAAC,EAAE,wBAAwB,CAAC;CACzC;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAC;CACpC;AAED,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/deploy.js
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
1
|
export const APP_DEPLOY_TARGET_IDS = ['web', 'android', 'ios'];
|
|
2
|
+
/**
|
|
3
|
+
* Logical application environments shared across platform-specific planning.
|
|
4
|
+
*
|
|
5
|
+
* `local` maps to local Web, iOS development, and Android debug execution.
|
|
6
|
+
* Environment-specific endpoints, signing material, and credentials are owned
|
|
7
|
+
* by their dedicated deployment/infra configuration rather than this identity contract.
|
|
8
|
+
*/
|
|
9
|
+
export const APP_DEPLOY_ENVIRONMENT_IDS = ['local', 'preview', 'production'];
|
|
2
10
|
export { isAppDeployManifest } from './appManifest/deploy';
|
|
3
11
|
//# sourceMappingURL=deploy.js.map
|
package/dist/deploy.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deploy.js","sourceRoot":"","sources":["../src/deploy.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,CAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"deploy.js","sourceRoot":"","sources":["../src/deploy.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,CAAU,CAAC;AAIxE;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,OAAO,EAAE,SAAS,EAAE,YAAY,CAAU,CAAC;AAwCtF,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC","sourcesContent":["export const APP_DEPLOY_TARGET_IDS = ['web', 'android', 'ios'] as const;\n\nexport type AppDeployTargetId = (typeof APP_DEPLOY_TARGET_IDS)[number];\n\n/**\n * Logical application environments shared across platform-specific planning.\n *\n * `local` maps to local Web, iOS development, and Android debug execution.\n * Environment-specific endpoints, signing material, and credentials are owned\n * by their dedicated deployment/infra configuration rather than this identity contract.\n */\nexport const APP_DEPLOY_ENVIRONMENT_IDS = ['local', 'preview', 'production'] as const;\n\nexport type AppDeployEnvironmentId = (typeof APP_DEPLOY_ENVIRONMENT_IDS)[number];\n\nexport interface AppDeployProviderSelection {\n readonly build?: string;\n readonly publish?: string;\n}\n\nexport interface AppDeployWebTargetConfig {\n readonly enabled: boolean;\n readonly providers?: AppDeployProviderSelection;\n}\n\nexport interface AppDeployAndroidTargetConfig {\n readonly enabled: boolean;\n readonly package: string;\n /** Stable application URI scheme used for target-aware deep links such as OAuth callbacks. */\n readonly scheme?: string;\n readonly providers?: AppDeployProviderSelection;\n}\n\nexport interface AppDeployIosTargetConfig {\n readonly enabled: boolean;\n readonly bundleIdentifier: string;\n /** Stable application URI scheme used for target-aware deep links such as OAuth callbacks. */\n readonly scheme?: string;\n readonly providers?: AppDeployProviderSelection;\n}\n\nexport interface AppDeployTargets {\n readonly web?: AppDeployWebTargetConfig;\n readonly android?: AppDeployAndroidTargetConfig;\n readonly ios?: AppDeployIosTargetConfig;\n}\n\nexport interface AppDeployManifest {\n readonly targets: AppDeployTargets;\n}\n\nexport { isAppDeployManifest } from './appManifest/deploy';\n"]}
|
package/package.json
CHANGED
|
@@ -12,8 +12,9 @@ const DEPLOY_KEYS = new Set(['targets']);
|
|
|
12
12
|
const TARGET_KEYS = new Set(['web', 'android', 'ios']);
|
|
13
13
|
const PROVIDER_KEYS = new Set(['build', 'publish']);
|
|
14
14
|
const WEB_KEYS = new Set(['enabled', 'providers']);
|
|
15
|
-
const ANDROID_KEYS = new Set(['enabled', 'package', 'providers']);
|
|
16
|
-
const IOS_KEYS = new Set(['enabled', 'bundleIdentifier', 'providers']);
|
|
15
|
+
const ANDROID_KEYS = new Set(['enabled', 'package', 'scheme', 'providers']);
|
|
16
|
+
const IOS_KEYS = new Set(['enabled', 'bundleIdentifier', 'scheme', 'providers']);
|
|
17
|
+
const URI_SCHEME_PATTERN = /^[A-Za-z][A-Za-z0-9+.-]*$/u;
|
|
17
18
|
|
|
18
19
|
export function isAppDeployManifest(value: unknown): value is AppDeployManifest {
|
|
19
20
|
return isRecord(value) && hasOnlyKeys(value, DEPLOY_KEYS) && isAppDeployTargets(value.targets);
|
|
@@ -44,6 +45,7 @@ function isAndroidTarget(value: unknown): value is AppDeployAndroidTargetConfig
|
|
|
44
45
|
hasOnlyKeys(value, ANDROID_KEYS) &&
|
|
45
46
|
typeof value.enabled === 'boolean' &&
|
|
46
47
|
isNonEmptyString(value.package) &&
|
|
48
|
+
isOptionalScheme(value.scheme) &&
|
|
47
49
|
isOptionalProviders(value.providers)
|
|
48
50
|
);
|
|
49
51
|
}
|
|
@@ -54,10 +56,15 @@ function isIosTarget(value: unknown): value is AppDeployIosTargetConfig {
|
|
|
54
56
|
hasOnlyKeys(value, IOS_KEYS) &&
|
|
55
57
|
typeof value.enabled === 'boolean' &&
|
|
56
58
|
isNonEmptyString(value.bundleIdentifier) &&
|
|
59
|
+
isOptionalScheme(value.scheme) &&
|
|
57
60
|
isOptionalProviders(value.providers)
|
|
58
61
|
);
|
|
59
62
|
}
|
|
60
63
|
|
|
64
|
+
function isOptionalScheme(value: unknown): value is string | undefined {
|
|
65
|
+
return value === undefined || (typeof value === 'string' && URI_SCHEME_PATTERN.test(value));
|
|
66
|
+
}
|
|
67
|
+
|
|
61
68
|
function isOptionalProviders(value: unknown): value is AppDeployProviderSelection | undefined {
|
|
62
69
|
return value === undefined || isProviderSelection(value);
|
|
63
70
|
}
|
package/src/deploy.test.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { join } from 'node:path';
|
|
|
4
4
|
import { describe, expect, it } from 'bun:test';
|
|
5
5
|
|
|
6
6
|
import { isAppManifest } from './appManifest';
|
|
7
|
-
import { APP_DEPLOY_TARGET_IDS, isAppDeployManifest } from './deploy';
|
|
7
|
+
import { APP_DEPLOY_ENVIRONMENT_IDS, APP_DEPLOY_TARGET_IDS, isAppDeployManifest } from './deploy';
|
|
8
8
|
import { DEPLOYMENT_TARGETS } from './types';
|
|
9
9
|
|
|
10
10
|
function createManifest(deploy?: unknown): Record<string, unknown> {
|
|
@@ -39,18 +39,24 @@ describe('app deployment contracts', () => {
|
|
|
39
39
|
expect(DEPLOYMENT_TARGETS).toEqual(['minikube']);
|
|
40
40
|
});
|
|
41
41
|
|
|
42
|
-
it('
|
|
42
|
+
it('defines one logical environment vocabulary across platform-specific execution', () => {
|
|
43
|
+
expect(APP_DEPLOY_ENVIRONMENT_IDS).toEqual(['local', 'preview', 'production']);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('accepts canonical web, Android, and iOS desired state with stable native schemes', () => {
|
|
43
47
|
const deploy = {
|
|
44
48
|
targets: {
|
|
45
49
|
web: { enabled: true, providers: { publish: 'eas' } },
|
|
46
50
|
android: {
|
|
47
51
|
enabled: true,
|
|
48
52
|
package: 'com.example.app',
|
|
53
|
+
scheme: 'example-app',
|
|
49
54
|
providers: { build: 'eas', publish: 'google-play' },
|
|
50
55
|
},
|
|
51
56
|
ios: {
|
|
52
57
|
enabled: false,
|
|
53
58
|
bundleIdentifier: 'com.example.app',
|
|
59
|
+
scheme: 'example-app',
|
|
54
60
|
providers: { build: 'eas', publish: 'app-store-connect' },
|
|
55
61
|
},
|
|
56
62
|
},
|
|
@@ -60,6 +66,40 @@ describe('app deployment contracts', () => {
|
|
|
60
66
|
expect(isAppManifest(createManifest(deploy))).toBe(true);
|
|
61
67
|
});
|
|
62
68
|
|
|
69
|
+
it('keeps native schemes optional for existing deployment manifests', () => {
|
|
70
|
+
expect(
|
|
71
|
+
isAppDeployManifest({
|
|
72
|
+
targets: {
|
|
73
|
+
android: { enabled: true, package: 'com.example.app' },
|
|
74
|
+
ios: { enabled: true, bundleIdentifier: 'com.example.app' },
|
|
75
|
+
},
|
|
76
|
+
}),
|
|
77
|
+
).toBe(true);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('accepts every supported platform combination', () => {
|
|
81
|
+
const web = { enabled: true };
|
|
82
|
+
const android = { enabled: true, package: 'com.example.app', scheme: 'example-app' };
|
|
83
|
+
const ios = {
|
|
84
|
+
enabled: true,
|
|
85
|
+
bundleIdentifier: 'com.example.app',
|
|
86
|
+
scheme: 'example-app',
|
|
87
|
+
};
|
|
88
|
+
const combinations = [
|
|
89
|
+
{ web },
|
|
90
|
+
{ android },
|
|
91
|
+
{ ios },
|
|
92
|
+
{ web, android },
|
|
93
|
+
{ web, ios },
|
|
94
|
+
{ android, ios },
|
|
95
|
+
{ web, android, ios },
|
|
96
|
+
];
|
|
97
|
+
|
|
98
|
+
for (const targets of combinations) {
|
|
99
|
+
expect(isAppDeployManifest({ targets })).toBe(true);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
|
|
63
103
|
it('keeps deployment optional and accepts an empty target registry structurally', () => {
|
|
64
104
|
expect(isAppManifest(createManifest())).toBe(true);
|
|
65
105
|
expect(isAppDeployManifest({ targets: {} })).toBe(true);
|
|
@@ -86,7 +126,14 @@ describe('app deployment contracts', () => {
|
|
|
86
126
|
{ targets: { desktop: { enabled: true } } },
|
|
87
127
|
{ targets: { web: { enabled: 'yes' } } },
|
|
88
128
|
{ targets: { android: { enabled: true, package: '' } } },
|
|
129
|
+
{ targets: { android: { enabled: true, package: 'com.example.app', scheme: '' } } },
|
|
130
|
+
{ targets: { android: { enabled: true, package: 'com.example.app', scheme: '9app' } } },
|
|
89
131
|
{ targets: { ios: { enabled: true, bundleIdentifier: ' ' } } },
|
|
132
|
+
{
|
|
133
|
+
targets: {
|
|
134
|
+
ios: { enabled: true, bundleIdentifier: 'com.example.app', scheme: 'bad scheme' },
|
|
135
|
+
},
|
|
136
|
+
},
|
|
90
137
|
{ targets: { web: { enabled: true, providers: { publish: '' } } } },
|
|
91
138
|
{ targets: { web: { enabled: true, providerConfig: { region: 'eu' } } } },
|
|
92
139
|
{ targets: { web: { enabled: true, credentials: { token: 'secret' } } } },
|
|
@@ -102,7 +149,13 @@ describe('app deployment contracts', () => {
|
|
|
102
149
|
expect(
|
|
103
150
|
isAppManifest(
|
|
104
151
|
createManifest({
|
|
105
|
-
targets: {
|
|
152
|
+
targets: {
|
|
153
|
+
android: {
|
|
154
|
+
enabled: true,
|
|
155
|
+
package: 'com.example.app',
|
|
156
|
+
credentials: {},
|
|
157
|
+
},
|
|
158
|
+
},
|
|
106
159
|
}),
|
|
107
160
|
),
|
|
108
161
|
).toBe(false);
|
package/src/deploy.ts
CHANGED
|
@@ -2,6 +2,17 @@ export const APP_DEPLOY_TARGET_IDS = ['web', 'android', 'ios'] as const;
|
|
|
2
2
|
|
|
3
3
|
export type AppDeployTargetId = (typeof APP_DEPLOY_TARGET_IDS)[number];
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Logical application environments shared across platform-specific planning.
|
|
7
|
+
*
|
|
8
|
+
* `local` maps to local Web, iOS development, and Android debug execution.
|
|
9
|
+
* Environment-specific endpoints, signing material, and credentials are owned
|
|
10
|
+
* by their dedicated deployment/infra configuration rather than this identity contract.
|
|
11
|
+
*/
|
|
12
|
+
export const APP_DEPLOY_ENVIRONMENT_IDS = ['local', 'preview', 'production'] as const;
|
|
13
|
+
|
|
14
|
+
export type AppDeployEnvironmentId = (typeof APP_DEPLOY_ENVIRONMENT_IDS)[number];
|
|
15
|
+
|
|
5
16
|
export interface AppDeployProviderSelection {
|
|
6
17
|
readonly build?: string;
|
|
7
18
|
readonly publish?: string;
|
|
@@ -15,12 +26,16 @@ export interface AppDeployWebTargetConfig {
|
|
|
15
26
|
export interface AppDeployAndroidTargetConfig {
|
|
16
27
|
readonly enabled: boolean;
|
|
17
28
|
readonly package: string;
|
|
29
|
+
/** Stable application URI scheme used for target-aware deep links such as OAuth callbacks. */
|
|
30
|
+
readonly scheme?: string;
|
|
18
31
|
readonly providers?: AppDeployProviderSelection;
|
|
19
32
|
}
|
|
20
33
|
|
|
21
34
|
export interface AppDeployIosTargetConfig {
|
|
22
35
|
readonly enabled: boolean;
|
|
23
36
|
readonly bundleIdentifier: string;
|
|
37
|
+
/** Stable application URI scheme used for target-aware deep links such as OAuth callbacks. */
|
|
38
|
+
readonly scheme?: string;
|
|
24
39
|
readonly providers?: AppDeployProviderSelection;
|
|
25
40
|
}
|
|
26
41
|
|