@equinor/fusion-framework-module-app 7.0.4-next.1 → 7.1.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 +85 -12
- package/dist/esm/AppClient.js +33 -4
- package/dist/esm/AppClient.js.map +1 -1
- package/dist/esm/AppModuleProvider.js +15 -5
- package/dist/esm/AppModuleProvider.js.map +1 -1
- package/dist/esm/app/App.js +6 -2
- package/dist/esm/app/App.js.map +1 -1
- package/dist/esm/app/actions.js +1 -1
- package/dist/esm/app/actions.js.map +1 -1
- package/dist/esm/app/flows.js +2 -2
- package/dist/esm/app/flows.js.map +1 -1
- package/dist/esm/errors.js +33 -0
- package/dist/esm/errors.js.map +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/esm/version.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/AppClient.d.ts +15 -2
- package/dist/types/AppModuleProvider.d.ts +4 -3
- package/dist/types/app/App.d.ts +1 -0
- package/dist/types/app/actions.d.ts +8 -2
- package/dist/types/app/create-reducer.d.ts +4 -1
- package/dist/types/app/types.d.ts +1 -0
- package/dist/types/errors.d.ts +20 -0
- package/dist/types/types.d.ts +7 -0
- package/dist/types/version.d.ts +1 -1
- package/package.json +8 -8
- package/src/AppClient.ts +57 -9
- package/src/AppModuleProvider.ts +29 -8
- package/src/app/App.ts +6 -2
- package/src/app/actions.ts +1 -1
- package/src/app/flows.ts +2 -2
- package/src/app/types.ts +1 -0
- package/src/errors.ts +45 -0
- package/src/types.ts +8 -0
- package/src/version.ts +1 -1
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
import { type Observable, type ObservableInput } from 'rxjs';
|
|
2
2
|
import { type IHttpClient } from '@equinor/fusion-framework-module-http';
|
|
3
|
-
import type { AppConfig, AppManifest, AppSettings, ConfigEnvironment } from './types';
|
|
3
|
+
import type { AppBuildManifest, AppConfig, AppManifest, AppSettings, ConfigEnvironment } from './types';
|
|
4
4
|
export interface IAppClient extends Disposable {
|
|
5
5
|
/**
|
|
6
|
-
* Fetch app manifest by appKey
|
|
6
|
+
* Fetch app manifest by appKey and tag
|
|
7
7
|
*/
|
|
8
8
|
getAppManifest: (args: {
|
|
9
9
|
appKey: string;
|
|
10
|
+
tag?: string;
|
|
10
11
|
}) => ObservableInput<AppManifest>;
|
|
12
|
+
/**
|
|
13
|
+
* Fetch app build manifest by appKey and tag
|
|
14
|
+
*/
|
|
15
|
+
getAppBuild: (args: {
|
|
16
|
+
appKey: string;
|
|
17
|
+
tag?: string;
|
|
18
|
+
}) => ObservableInput<AppBuildManifest>;
|
|
11
19
|
/**
|
|
12
20
|
* Fetch all app manifests
|
|
13
21
|
*/
|
|
@@ -44,8 +52,13 @@ export interface IAppClient extends Disposable {
|
|
|
44
52
|
export declare class AppClient implements IAppClient {
|
|
45
53
|
#private;
|
|
46
54
|
constructor(client: IHttpClient);
|
|
55
|
+
getAppBuild(args: {
|
|
56
|
+
appKey: string;
|
|
57
|
+
tag?: string;
|
|
58
|
+
}): Observable<AppBuildManifest>;
|
|
47
59
|
getAppManifest(args: {
|
|
48
60
|
appKey: string;
|
|
61
|
+
tag?: string;
|
|
49
62
|
}): Observable<AppManifest>;
|
|
50
63
|
getAppManifests(args: {
|
|
51
64
|
filterByCurrentUser?: boolean;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type Observable } from 'rxjs';
|
|
2
2
|
import type { ModuleType } from '@equinor/fusion-framework-module';
|
|
3
3
|
import type { EventModule } from '@equinor/fusion-framework-module-event';
|
|
4
|
-
import type { AppConfig, AppManifest, AppSettings, ConfigEnvironment, CurrentApp } from './types';
|
|
4
|
+
import type { AppConfig, AppManifest, AppReference, AppSettings, ConfigEnvironment, CurrentApp } from './types';
|
|
5
5
|
import { App, type IApp } from './app/App';
|
|
6
6
|
import type { AppModuleConfig } from './AppConfigurator';
|
|
7
7
|
import type { AppBundleStateInitial } from './app/types';
|
|
@@ -29,8 +29,9 @@ export declare class AppModuleProvider {
|
|
|
29
29
|
/**
|
|
30
30
|
* fetch an application by key
|
|
31
31
|
* @param appKey - application key
|
|
32
|
+
* @param tag - application tag (optional)
|
|
32
33
|
*/
|
|
33
|
-
getAppManifest(appKey: string): Observable<AppManifest>;
|
|
34
|
+
getAppManifest(appKey: string, tag?: string): Observable<AppManifest>;
|
|
34
35
|
getAppManifests(filter?: {
|
|
35
36
|
filterByCurrentUser: boolean;
|
|
36
37
|
}): Observable<AppManifest[]>;
|
|
@@ -59,7 +60,7 @@ export declare class AppModuleProvider {
|
|
|
59
60
|
* set the current application, will internally resolve manifest
|
|
60
61
|
* @param appKey - application key
|
|
61
62
|
*/
|
|
62
|
-
setCurrentApp(appKeyOrApp: string | IApp): void;
|
|
63
|
+
setCurrentApp(appKeyOrApp: string | IApp | AppReference): void;
|
|
63
64
|
clearCurrentApp(): void;
|
|
64
65
|
get assetUri(): string;
|
|
65
66
|
/**
|
package/dist/types/app/App.d.ts
CHANGED
|
@@ -196,6 +196,7 @@ export declare class App<TEnv extends ConfigEnvironment = ConfigEnvironment, TMo
|
|
|
196
196
|
get status$(): Observable<AppBundleState['status']>;
|
|
197
197
|
get state(): Readonly<AppBundleState>;
|
|
198
198
|
get appKey(): string;
|
|
199
|
+
get tag(): string | undefined;
|
|
199
200
|
get manifest(): Readonly<AppManifest> | undefined;
|
|
200
201
|
get manifestAsync(): Promise<Readonly<AppManifest>>;
|
|
201
202
|
get config(): AppConfig<TEnv> | undefined;
|
|
@@ -6,7 +6,10 @@ declare const createActions: () => {
|
|
|
6
6
|
created: number;
|
|
7
7
|
update: boolean | undefined;
|
|
8
8
|
}>;
|
|
9
|
-
fetchManifest: import("@equinor/fusion-observable").ActionCreatorWithPreparedPayload<[key: string,
|
|
9
|
+
fetchManifest: import("@equinor/fusion-observable").ActionCreatorWithPreparedPayload<[key: string, tag?: string | undefined, update?: boolean | undefined], {
|
|
10
|
+
key: string;
|
|
11
|
+
tag: string | undefined;
|
|
12
|
+
}, "fetch_manifest::request", never, {
|
|
10
13
|
update: boolean | undefined;
|
|
11
14
|
}> & {
|
|
12
15
|
success: import("@equinor/fusion-observable").ActionCreatorWithPreparedPayload<[manifest: AppManifest], AppManifest, "fetch_manifest::success", never, never>;
|
|
@@ -54,7 +57,10 @@ export declare const actions: {
|
|
|
54
57
|
created: number;
|
|
55
58
|
update: boolean | undefined;
|
|
56
59
|
}>;
|
|
57
|
-
fetchManifest: import("@equinor/fusion-observable").ActionCreatorWithPreparedPayload<[key: string,
|
|
60
|
+
fetchManifest: import("@equinor/fusion-observable").ActionCreatorWithPreparedPayload<[key: string, tag?: string | undefined, update?: boolean | undefined], {
|
|
61
|
+
key: string;
|
|
62
|
+
tag: string | undefined;
|
|
63
|
+
}, "fetch_manifest::request", never, {
|
|
58
64
|
update: boolean | undefined;
|
|
59
65
|
}> & {
|
|
60
66
|
success: import("@equinor/fusion-observable").ActionCreatorWithPreparedPayload<[manifest: AppManifest], AppManifest, "fetch_manifest::success", never, never>;
|
|
@@ -2,7 +2,10 @@ import type { AppBundleState, AppBundleStateInitial } from './types';
|
|
|
2
2
|
export declare const createReducer: (value: AppBundleStateInitial) => import("@equinor/fusion-observable").ReducerWithInitialState<AppBundleState, import("@equinor/fusion-observable").PayloadAction<import("..").AppManifest, "set_manifest", {
|
|
3
3
|
created: number;
|
|
4
4
|
update: boolean | undefined;
|
|
5
|
-
}, never> | import("@equinor/fusion-observable").PayloadAction<
|
|
5
|
+
}, never> | import("@equinor/fusion-observable").PayloadAction<{
|
|
6
|
+
key: string;
|
|
7
|
+
tag: string | undefined;
|
|
8
|
+
}, "fetch_manifest::request", {
|
|
6
9
|
update: boolean | undefined;
|
|
7
10
|
}, never> | {
|
|
8
11
|
payload: import("..").AppConfig<import("../AppConfig").ConfigEnvironment>;
|
|
@@ -17,6 +17,7 @@ import type { Actions } from './actions';
|
|
|
17
17
|
*/
|
|
18
18
|
export type AppBundleState<TConfig extends ConfigEnvironment = ConfigEnvironment, TModules = any> = {
|
|
19
19
|
appKey: string;
|
|
20
|
+
tag?: string;
|
|
20
21
|
status: Set<ActionBaseType<Actions>>;
|
|
21
22
|
manifest?: AppManifest;
|
|
22
23
|
config?: AppConfig<TConfig>;
|
package/dist/types/errors.d.ts
CHANGED
|
@@ -39,6 +39,26 @@ export declare class AppConfigError extends Error {
|
|
|
39
39
|
*/
|
|
40
40
|
constructor(type: AppErrorType, message?: string, options?: ErrorOptions);
|
|
41
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Represents an error that occurs in the application build.
|
|
44
|
+
*/
|
|
45
|
+
export declare class AppBuildError extends Error {
|
|
46
|
+
readonly type: AppErrorType;
|
|
47
|
+
/**
|
|
48
|
+
* Creates an instance of `AppBuildError` based on the HTTP response status.
|
|
49
|
+
* @param response The HTTP response.
|
|
50
|
+
* @param options Additional error options.
|
|
51
|
+
* @returns An instance of `AppBuildError` based on the HTTP response status.
|
|
52
|
+
*/
|
|
53
|
+
static fromHttpResponse(response: Response, options?: ErrorOptions): AppBuildError;
|
|
54
|
+
/**
|
|
55
|
+
* Creates an instance of `AppBuildError`.
|
|
56
|
+
* @param type The type of the application error.
|
|
57
|
+
* @param message The error message.
|
|
58
|
+
* @param options Additional error options.
|
|
59
|
+
*/
|
|
60
|
+
constructor(type: AppErrorType, message?: string, options?: ErrorOptions);
|
|
61
|
+
}
|
|
42
62
|
/**
|
|
43
63
|
* Represents an error that occurs while fetching application settings.
|
|
44
64
|
*/
|
package/dist/types/types.d.ts
CHANGED
|
@@ -14,6 +14,13 @@ export type AppEnv<TEnv extends ConfigEnvironment = ConfigEnvironment, TProps =
|
|
|
14
14
|
config?: AppConfig<TEnv>;
|
|
15
15
|
props?: TProps;
|
|
16
16
|
};
|
|
17
|
+
/**
|
|
18
|
+
* Reference to an app, used to fetch app manifest from app service
|
|
19
|
+
*/
|
|
20
|
+
export type AppReference = {
|
|
21
|
+
appKey: string;
|
|
22
|
+
tag?: string;
|
|
23
|
+
};
|
|
17
24
|
export type ModuleDeps = [HttpModule, ServiceDiscoveryModule, EventModule];
|
|
18
25
|
export interface AppSettings {
|
|
19
26
|
[key: string]: unknown;
|
package/dist/types/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "7.0
|
|
1
|
+
export declare const version = "7.1.0";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@equinor/fusion-framework-module-app",
|
|
3
|
-
"version": "7.0
|
|
3
|
+
"version": "7.1.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/esm/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -61,16 +61,16 @@
|
|
|
61
61
|
"rxjs": "^7.8.1",
|
|
62
62
|
"uuid": "^13.0.0",
|
|
63
63
|
"zod": "^4.1.8",
|
|
64
|
-
"@equinor/fusion-query": "^6.0.
|
|
65
|
-
"@equinor/fusion-observable": "^8.5.
|
|
64
|
+
"@equinor/fusion-query": "^6.0.1",
|
|
65
|
+
"@equinor/fusion-observable": "^8.5.6"
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
68
|
"typescript": "^5.8.2",
|
|
69
|
-
"@equinor/fusion-framework-module
|
|
70
|
-
"@equinor/fusion-framework-module": "^
|
|
71
|
-
"@equinor/fusion-framework-module-http": "^7.0.
|
|
72
|
-
"@equinor/fusion-framework-module-msal": "^
|
|
73
|
-
"@equinor/fusion-framework-module-service-discovery": "^9.0.
|
|
69
|
+
"@equinor/fusion-framework-module": "^5.0.5",
|
|
70
|
+
"@equinor/fusion-framework-module-event": "^4.4.0",
|
|
71
|
+
"@equinor/fusion-framework-module-http": "^7.0.4",
|
|
72
|
+
"@equinor/fusion-framework-module-msal": "^5.1.2",
|
|
73
|
+
"@equinor/fusion-framework-module-service-discovery": "^9.0.4"
|
|
74
74
|
},
|
|
75
75
|
"scripts": {
|
|
76
76
|
"build": "tsc -b"
|
package/src/AppClient.ts
CHANGED
|
@@ -10,17 +10,28 @@ import {
|
|
|
10
10
|
} from '@equinor/fusion-framework-module-http';
|
|
11
11
|
import { jsonSelector } from '@equinor/fusion-framework-module-http/selectors';
|
|
12
12
|
|
|
13
|
-
import { ApiApplicationSchema } from './schemas';
|
|
13
|
+
import { ApiApplicationBuildSchema, ApiApplicationSchema } from './schemas';
|
|
14
14
|
|
|
15
|
-
import type {
|
|
16
|
-
|
|
15
|
+
import type {
|
|
16
|
+
AppBuildManifest,
|
|
17
|
+
AppConfig,
|
|
18
|
+
AppManifest,
|
|
19
|
+
AppSettings,
|
|
20
|
+
ConfigEnvironment,
|
|
21
|
+
} from './types';
|
|
22
|
+
import { AppBuildError, AppConfigError, AppManifestError, AppSettingsError } from './errors';
|
|
17
23
|
import { AppConfigSelector } from './AppClient.Selectors';
|
|
18
24
|
|
|
19
25
|
export interface IAppClient extends Disposable {
|
|
20
26
|
/**
|
|
21
|
-
* Fetch app manifest by appKey
|
|
27
|
+
* Fetch app manifest by appKey and tag
|
|
22
28
|
*/
|
|
23
|
-
getAppManifest: (args: { appKey: string }) => ObservableInput<AppManifest>;
|
|
29
|
+
getAppManifest: (args: { appKey: string; tag?: string }) => ObservableInput<AppManifest>;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Fetch app build manifest by appKey and tag
|
|
33
|
+
*/
|
|
34
|
+
getAppBuild: (args: { appKey: string; tag?: string }) => ObservableInput<AppBuildManifest>;
|
|
24
35
|
|
|
25
36
|
/**
|
|
26
37
|
* Fetch all app manifests
|
|
@@ -81,6 +92,7 @@ export class AppClient implements IAppClient {
|
|
|
81
92
|
#manifest: Query<AppManifest, { appKey: string }>;
|
|
82
93
|
#manifests: Query<AppManifest[], { filterByCurrentUser?: boolean } | undefined>;
|
|
83
94
|
#config: Query<AppConfig, { appKey: string; tag?: string }>;
|
|
95
|
+
#build: Query<AppBuildManifest, { appKey: string; tag?: string }>;
|
|
84
96
|
#settings: Query<AppSettings, { appKey: string; settings?: AppSettings }>;
|
|
85
97
|
#client: IHttpClient;
|
|
86
98
|
|
|
@@ -88,10 +100,28 @@ export class AppClient implements IAppClient {
|
|
|
88
100
|
this.#client = client;
|
|
89
101
|
|
|
90
102
|
const expire = 1 * 60 * 1000;
|
|
91
|
-
|
|
103
|
+
|
|
104
|
+
this.#build = new Query<AppBuildManifest, { appKey: string; tag?: string }>({
|
|
92
105
|
client: {
|
|
93
|
-
fn: ({ appKey }) => {
|
|
94
|
-
return client.json(`/
|
|
106
|
+
fn: ({ appKey, tag }) => {
|
|
107
|
+
return client.json(`/apps/${appKey}/builds/${tag}`, {
|
|
108
|
+
headers: {
|
|
109
|
+
'Api-Version': '1.0',
|
|
110
|
+
},
|
|
111
|
+
selector: async (res: Response) =>
|
|
112
|
+
ApiApplicationBuildSchema.parse(await jsonSelector(res)) as AppBuildManifest,
|
|
113
|
+
});
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
queueOperator: 'merge',
|
|
117
|
+
key: ({ appKey, tag }) => `${appKey}@${tag}`,
|
|
118
|
+
expire,
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
this.#manifest = new Query<AppManifest, { appKey: string; tag?: string }>({
|
|
122
|
+
client: {
|
|
123
|
+
fn: ({ appKey, tag }) => {
|
|
124
|
+
return client.json$(tag ? `/apps/${appKey}@${tag}` : `/persons/me/apps/${appKey}`, {
|
|
95
125
|
headers: {
|
|
96
126
|
'Api-Version': '1.0',
|
|
97
127
|
},
|
|
@@ -156,7 +186,24 @@ export class AppClient implements IAppClient {
|
|
|
156
186
|
});
|
|
157
187
|
}
|
|
158
188
|
|
|
159
|
-
|
|
189
|
+
getAppBuild(args: { appKey: string; tag?: string }): Observable<AppBuildManifest> {
|
|
190
|
+
return this.#build.query(args).pipe(
|
|
191
|
+
map((res) => res.value as AppBuildManifest),
|
|
192
|
+
catchError((err) => {
|
|
193
|
+
const cause = err?.cause || err;
|
|
194
|
+
|
|
195
|
+
if (cause instanceof AppBuildError) {
|
|
196
|
+
throw cause;
|
|
197
|
+
}
|
|
198
|
+
if (cause instanceof HttpJsonResponseError || cause instanceof HttpResponseError) {
|
|
199
|
+
throw AppBuildError.fromHttpResponse(cause.response, { cause });
|
|
200
|
+
}
|
|
201
|
+
throw new AppBuildError('unknown', 'failed to load build', { cause });
|
|
202
|
+
}),
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
getAppManifest(args: { appKey: string; tag?: string }): Observable<AppManifest> {
|
|
160
207
|
return this.#manifest.query(args).pipe(
|
|
161
208
|
queryValue,
|
|
162
209
|
catchError((err) => {
|
|
@@ -251,6 +298,7 @@ export class AppClient implements IAppClient {
|
|
|
251
298
|
this.#manifests.complete();
|
|
252
299
|
this.#config.complete();
|
|
253
300
|
this.#settings.complete();
|
|
301
|
+
this.#build.complete();
|
|
254
302
|
}
|
|
255
303
|
}
|
|
256
304
|
|
package/src/AppModuleProvider.ts
CHANGED
|
@@ -12,7 +12,14 @@ import {
|
|
|
12
12
|
import type { ModuleType } from '@equinor/fusion-framework-module';
|
|
13
13
|
import type { EventModule } from '@equinor/fusion-framework-module-event';
|
|
14
14
|
|
|
15
|
-
import type {
|
|
15
|
+
import type {
|
|
16
|
+
AppConfig,
|
|
17
|
+
AppManifest,
|
|
18
|
+
AppReference,
|
|
19
|
+
AppSettings,
|
|
20
|
+
ConfigEnvironment,
|
|
21
|
+
CurrentApp,
|
|
22
|
+
} from './types';
|
|
16
23
|
|
|
17
24
|
import { App, filterEmpty, type IApp } from './app/App';
|
|
18
25
|
import type { AppModuleConfig } from './AppConfigurator';
|
|
@@ -103,9 +110,10 @@ export class AppModuleProvider {
|
|
|
103
110
|
/**
|
|
104
111
|
* fetch an application by key
|
|
105
112
|
* @param appKey - application key
|
|
113
|
+
* @param tag - application tag (optional)
|
|
106
114
|
*/
|
|
107
|
-
public getAppManifest(appKey: string): Observable<AppManifest> {
|
|
108
|
-
return from(this.#appClient.getAppManifest({ appKey }));
|
|
115
|
+
public getAppManifest(appKey: string, tag?: string): Observable<AppManifest> {
|
|
116
|
+
return from(this.#appClient.getAppManifest({ appKey, tag }));
|
|
109
117
|
}
|
|
110
118
|
|
|
111
119
|
public getAppManifests(filter?: { filterByCurrentUser: boolean }): Observable<AppManifest[]> {
|
|
@@ -152,10 +160,23 @@ export class AppModuleProvider {
|
|
|
152
160
|
* set the current application, will internally resolve manifest
|
|
153
161
|
* @param appKey - application key
|
|
154
162
|
*/
|
|
155
|
-
public setCurrentApp(appKeyOrApp: string | IApp): void {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
163
|
+
public setCurrentApp(appKeyOrApp: string | IApp | AppReference): void {
|
|
164
|
+
if (typeof appKeyOrApp === 'string') {
|
|
165
|
+
const newApp = new App({ appKey: appKeyOrApp }, { provider: this, event: this.#event });
|
|
166
|
+
this.#current$.next(newApp as CurrentApp);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (appKeyOrApp.appKey && 'tag' in appKeyOrApp) {
|
|
171
|
+
const newApp = new App(
|
|
172
|
+
{ appKey: appKeyOrApp.appKey, tag: appKeyOrApp.tag },
|
|
173
|
+
{ provider: this, event: this.#event },
|
|
174
|
+
);
|
|
175
|
+
this.#current$.next(newApp as CurrentApp);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
this.#current$.next(appKeyOrApp as CurrentApp);
|
|
159
180
|
}
|
|
160
181
|
|
|
161
182
|
public clearCurrentApp(): void {
|
|
@@ -171,7 +192,7 @@ export class AppModuleProvider {
|
|
|
171
192
|
* @deprecated
|
|
172
193
|
*/
|
|
173
194
|
public createApp(value: AppBundleStateInitial): App {
|
|
174
|
-
console.warn();
|
|
195
|
+
console.warn('AppModuleProvider.createApp is deprecated and should not be used.');
|
|
175
196
|
return new App(value, { provider: this, event: this.#event });
|
|
176
197
|
}
|
|
177
198
|
|
package/src/app/App.ts
CHANGED
|
@@ -311,6 +311,9 @@ export class App<
|
|
|
311
311
|
get appKey(): string {
|
|
312
312
|
return this.#state.value.appKey;
|
|
313
313
|
}
|
|
314
|
+
get tag(): string | undefined {
|
|
315
|
+
return this.#state.value.tag;
|
|
316
|
+
}
|
|
314
317
|
|
|
315
318
|
get manifest(): Readonly<AppManifest> | undefined {
|
|
316
319
|
return this.state.manifest;
|
|
@@ -564,7 +567,8 @@ export class App<
|
|
|
564
567
|
}),
|
|
565
568
|
error: (err) => {
|
|
566
569
|
// emit error and complete the stream
|
|
567
|
-
subscriber.error(err)
|
|
570
|
+
subscriber.error(err);
|
|
571
|
+
this.#state.next(actions.initialize.failure(err));
|
|
568
572
|
},
|
|
569
573
|
complete: () => {
|
|
570
574
|
// dispatch initialize success action to indicate that the application has been initialized
|
|
@@ -586,7 +590,7 @@ export class App<
|
|
|
586
590
|
}
|
|
587
591
|
|
|
588
592
|
public loadManifest(update?: boolean) {
|
|
589
|
-
this.#state.next(actions.fetchManifest(this.appKey, update));
|
|
593
|
+
this.#state.next(actions.fetchManifest(this.appKey, this.tag, update));
|
|
590
594
|
}
|
|
591
595
|
|
|
592
596
|
public updateManifest(manifest: AppManifest, replace?: false) {
|
package/src/app/actions.ts
CHANGED
|
@@ -25,7 +25,7 @@ const createActions = () => ({
|
|
|
25
25
|
|
|
26
26
|
fetchManifest: createAsyncAction(
|
|
27
27
|
'fetch_manifest',
|
|
28
|
-
(key: string, update?: boolean) => ({ payload: key, meta: { update } }),
|
|
28
|
+
(key: string, tag?: string, update?: boolean) => ({ payload: { key, tag }, meta: { update } }),
|
|
29
29
|
(manifest: AppManifest) => ({ payload: manifest }),
|
|
30
30
|
(error: unknown) => ({ payload: error }),
|
|
31
31
|
),
|
package/src/app/flows.ts
CHANGED
|
@@ -24,12 +24,12 @@ export const handleFetchManifest =
|
|
|
24
24
|
// when request is received, abort any ongoing request and start new
|
|
25
25
|
switchMap((action) => {
|
|
26
26
|
const {
|
|
27
|
-
payload:
|
|
27
|
+
payload: { key, tag },
|
|
28
28
|
meta: { update },
|
|
29
29
|
} = action;
|
|
30
30
|
|
|
31
31
|
// fetch manifest from provider
|
|
32
|
-
const subject = from(provider.getAppManifest(
|
|
32
|
+
const subject = from(provider.getAppManifest(key, tag)).pipe(
|
|
33
33
|
// filter out null values
|
|
34
34
|
filter((x) => !!x),
|
|
35
35
|
// allow multiple subscriptions
|
package/src/app/types.ts
CHANGED
package/src/errors.ts
CHANGED
|
@@ -90,6 +90,51 @@ export class AppConfigError extends Error {
|
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
/**
|
|
94
|
+
* Represents an error that occurs in the application build.
|
|
95
|
+
*/
|
|
96
|
+
export class AppBuildError extends Error {
|
|
97
|
+
/**
|
|
98
|
+
* Creates an instance of `AppBuildError` based on the HTTP response status.
|
|
99
|
+
* @param response The HTTP response.
|
|
100
|
+
* @param options Additional error options.
|
|
101
|
+
* @returns An instance of `AppBuildError` based on the HTTP response status.
|
|
102
|
+
*/
|
|
103
|
+
static fromHttpResponse(response: Response, options?: ErrorOptions): AppBuildError {
|
|
104
|
+
switch (response.status) {
|
|
105
|
+
case 401:
|
|
106
|
+
return new AppBuildError(
|
|
107
|
+
'unauthorized',
|
|
108
|
+
'failed to load application build metadata, request not authorized',
|
|
109
|
+
options,
|
|
110
|
+
);
|
|
111
|
+
case 404:
|
|
112
|
+
return new AppBuildError('not_found', 'application build metadata not found', options);
|
|
113
|
+
case 410:
|
|
114
|
+
return new AppBuildError('deleted', 'application build deleted', options);
|
|
115
|
+
}
|
|
116
|
+
return new AppBuildError(
|
|
117
|
+
'unknown',
|
|
118
|
+
`failed to load application build, status code ${response.status}`,
|
|
119
|
+
options,
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Creates an instance of `AppBuildError`.
|
|
125
|
+
* @param type The type of the application error.
|
|
126
|
+
* @param message The error message.
|
|
127
|
+
* @param options Additional error options.
|
|
128
|
+
*/
|
|
129
|
+
constructor(
|
|
130
|
+
public readonly type: AppErrorType,
|
|
131
|
+
message?: string,
|
|
132
|
+
options?: ErrorOptions,
|
|
133
|
+
) {
|
|
134
|
+
super(message, options);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
93
138
|
/**
|
|
94
139
|
* Represents an error that occurs while fetching application settings.
|
|
95
140
|
*/
|
package/src/types.ts
CHANGED
|
@@ -20,6 +20,14 @@ export type AppEnv<TEnv extends ConfigEnvironment = ConfigEnvironment, TProps =
|
|
|
20
20
|
props?: TProps;
|
|
21
21
|
};
|
|
22
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Reference to an app, used to fetch app manifest from app service
|
|
25
|
+
*/
|
|
26
|
+
export type AppReference = {
|
|
27
|
+
appKey: string;
|
|
28
|
+
tag?: string; // defaults to 'latest'
|
|
29
|
+
};
|
|
30
|
+
|
|
23
31
|
// TODO: change to module-services when new app service is created
|
|
24
32
|
export type ModuleDeps = [HttpModule, ServiceDiscoveryModule, EventModule];
|
|
25
33
|
|
package/src/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Generated by genversion.
|
|
2
|
-
export const version = '7.0
|
|
2
|
+
export const version = '7.1.0';
|