@equinor/fusion-framework-vite-plugin-spa 1.1.3 → 1.2.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 +60 -0
- package/README.md +74 -31
- package/dist/esm/html/bootstrap.js +93 -6
- package/dist/esm/html/bootstrap.js.map +1 -1
- package/dist/esm/html/register-service-worker.js +54 -11
- package/dist/esm/html/register-service-worker.js.map +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/html/bootstrap.js +4342 -981
- package/dist/html/bootstrap.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/html/index.html.d.ts +1 -1
- package/dist/types/html/register-service-worker.d.ts +2 -1
- package/dist/types/types.d.ts +4 -0
- package/dist/types/version.d.ts +1 -1
- package/package.json +6 -5
- package/src/html/bootstrap.ts +115 -12
- package/src/html/register-service-worker.ts +87 -35
- package/src/types.ts +5 -0
- package/src/version.ts +1 -1
- package/tsconfig.json +3 -0
|
@@ -15,5 +15,5 @@
|
|
|
15
15
|
* @constant
|
|
16
16
|
* @type {string}
|
|
17
17
|
*/
|
|
18
|
-
export declare const html = "\n <!DOCTYPE html>\n <html>\n <head>\n <title>%FUSION_SPA_TITLE%</title>\n <meta name=\"mode\" content=\"%MODE%\">\n <meta name=\"fusion-spa-plugin-version\" content=\"1.
|
|
18
|
+
export declare const html = "\n <!DOCTYPE html>\n <html>\n <head>\n <title>%FUSION_SPA_TITLE%</title>\n <meta name=\"mode\" content=\"%MODE%\">\n <meta name=\"fusion-spa-plugin-version\" content=\"1.2.0\">\n <link rel=\"stylesheet\" href=\"https://cdn.eds.equinor.com/font/equinor-font.css\" />\n <script type=\"module\" src=\"%FUSION_SPA_BOOTSTRAP%\"></script>\n <script>\n // suppress console error for custom elements already defined. \n // WebComponents should be added by the portal, but not removed from application\n const _customElementsDefine = window.customElements.define;\n window.customElements.define = (name, cl, conf) => {\n if (!customElements.get(name)) {\n _customElementsDefine.call(window.customElements, name, cl, conf);\n }\n };\n </script>\n <style>\n html, body {\n margin: 0;\n padding: 0;\n height: 100%;\n font-family: 'EquinorFont', sans-serif;\n }\n </style>\n </head>\n <body></body>\n </html>\n";
|
|
19
19
|
export default html;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { ModulesInstance } from '@equinor/fusion-framework-module';
|
|
2
2
|
import type { MsalModule } from '@equinor/fusion-framework-module-msal';
|
|
3
|
-
|
|
3
|
+
import { type TelemetryModule } from '@equinor/fusion-framework-module-telemetry';
|
|
4
|
+
export declare function registerServiceWorker(framework: ModulesInstance<[MsalModule, TelemetryModule]>): Promise<void>;
|
package/dist/types/types.d.ts
CHANGED
|
@@ -13,10 +13,14 @@ export type FusionTemplateEnv = {
|
|
|
13
13
|
title: string;
|
|
14
14
|
/** Template bootstrap file path */
|
|
15
15
|
bootstrap: string;
|
|
16
|
+
telemetry?: {
|
|
17
|
+
consoleLevel?: number;
|
|
18
|
+
};
|
|
16
19
|
/** Id of the portal to load */
|
|
17
20
|
portal: {
|
|
18
21
|
id: string;
|
|
19
22
|
tag?: string;
|
|
23
|
+
proxy?: boolean;
|
|
20
24
|
};
|
|
21
25
|
/** Service discovery configuration */
|
|
22
26
|
serviceDiscovery: {
|
package/dist/types/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "1.
|
|
1
|
+
export declare const version = "1.2.0";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@equinor/fusion-framework-vite-plugin-spa",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Vite plugin for SPA development",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "dist/types/index.d.ts",
|
|
@@ -46,11 +46,12 @@
|
|
|
46
46
|
"@types/lodash.mergewith": "^4.6.2",
|
|
47
47
|
"rollup": "^4.39.0",
|
|
48
48
|
"typescript": "^5.8.2",
|
|
49
|
-
"vite": "^7.1.
|
|
50
|
-
"@equinor/fusion-framework-module
|
|
51
|
-
"@equinor/fusion-framework-module": "5.0.2",
|
|
49
|
+
"vite": "^7.1.9",
|
|
50
|
+
"@equinor/fusion-framework-module": "5.0.3",
|
|
52
51
|
"@equinor/fusion-framework-module-msal": "5.0.1",
|
|
53
|
-
"@equinor/fusion-framework-module-
|
|
52
|
+
"@equinor/fusion-framework-module-http": "7.0.2",
|
|
53
|
+
"@equinor/fusion-framework-module-telemetry": "4.2.0",
|
|
54
|
+
"@equinor/fusion-framework-module-service-discovery": "9.0.2"
|
|
54
55
|
},
|
|
55
56
|
"scripts": {
|
|
56
57
|
"build": "tsc -b",
|
package/src/html/bootstrap.ts
CHANGED
|
@@ -6,8 +6,18 @@ import {
|
|
|
6
6
|
enableServiceDiscovery,
|
|
7
7
|
type ServiceDiscoveryModule,
|
|
8
8
|
} from '@equinor/fusion-framework-module-service-discovery';
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
enableTelemetry,
|
|
12
|
+
TelemetryLevel,
|
|
13
|
+
type TelemetryModule,
|
|
14
|
+
} from '@equinor/fusion-framework-module-telemetry';
|
|
15
|
+
import { ConsoleAdapter } from '@equinor/fusion-framework-module-telemetry/console-adapter';
|
|
16
|
+
|
|
9
17
|
import { registerServiceWorker } from './register-service-worker.js';
|
|
10
18
|
|
|
19
|
+
import { version } from '../version.js';
|
|
20
|
+
|
|
11
21
|
// @todo - add type for portal manifest when available
|
|
12
22
|
type PortalManifest = {
|
|
13
23
|
build: {
|
|
@@ -23,8 +33,6 @@ const importWithoutVite = <T>(path: string): Promise<T> => import(/* @vite-ignor
|
|
|
23
33
|
// Create Fusion Framework configurator
|
|
24
34
|
const configurator = new ModulesConfigurator();
|
|
25
35
|
|
|
26
|
-
configurator.logger.level = import.meta.env.FUSION_SPA_LOG_LEVEL ?? 1;
|
|
27
|
-
|
|
28
36
|
const serviceDiscoveryUrl = new URL(
|
|
29
37
|
import.meta.env.FUSION_SPA_SERVICE_DISCOVERY_URL,
|
|
30
38
|
import.meta.env.FUSION_SPA_SERVICE_DISCOVERY_URL.startsWith('http')
|
|
@@ -56,12 +64,65 @@ enableMSAL(configurator, (builder) => {
|
|
|
56
64
|
builder.setRequiresAuth(Boolean(import.meta.env.FUSION_SPA_MSAL_REQUIRES_AUTH));
|
|
57
65
|
});
|
|
58
66
|
|
|
67
|
+
enableTelemetry(configurator, {
|
|
68
|
+
attachConfiguratorEvents: true,
|
|
69
|
+
configure: (builder) => {
|
|
70
|
+
const consoleLevel = Number(
|
|
71
|
+
import.meta.env.FUSION_SPA_TELEMETRY_CONSOLE_LEVEL ?? TelemetryLevel.Information,
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
if (Number.isNaN(consoleLevel)) {
|
|
75
|
+
// If environment variable is set but invalid, log all telemetry
|
|
76
|
+
builder.setAdapter(new ConsoleAdapter());
|
|
77
|
+
} else {
|
|
78
|
+
builder.setAdapter(
|
|
79
|
+
new ConsoleAdapter({
|
|
80
|
+
filter: (item) => item.level >= consoleLevel,
|
|
81
|
+
}),
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
builder.setMetadata(({ modules }) => {
|
|
85
|
+
const metadata = {
|
|
86
|
+
fusion: {
|
|
87
|
+
spa: {
|
|
88
|
+
version,
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
// biome-ignore lint/suspicious/noExplicitAny: we need to use any here to allow dynamic properties
|
|
92
|
+
} as Record<string, any>;
|
|
93
|
+
if (modules?.auth) {
|
|
94
|
+
metadata.fusion.user = {
|
|
95
|
+
id: modules.auth.defaultAccount?.homeAccountId,
|
|
96
|
+
name: modules.auth.defaultAccount?.name,
|
|
97
|
+
email: modules.auth.defaultAccount?.username,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
return metadata;
|
|
101
|
+
});
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
|
|
59
105
|
(async () => {
|
|
60
106
|
// initialize the framework - this will create the framework instance and configure the modules
|
|
61
|
-
const ref =
|
|
107
|
+
const ref =
|
|
108
|
+
await configurator.initialize<
|
|
109
|
+
[ServiceDiscoveryModule, HttpModule, MsalModule, TelemetryModule]
|
|
110
|
+
>();
|
|
111
|
+
|
|
112
|
+
const telemetry = ref.telemetry;
|
|
62
113
|
|
|
63
114
|
// attach service discovery to the framework - append auth token to configured endpoints
|
|
64
|
-
|
|
115
|
+
using measurement = telemetry.measure({
|
|
116
|
+
name: 'bootstrap',
|
|
117
|
+
level: TelemetryLevel.Information,
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
await measurement.clone().resolve(registerServiceWorker(ref), {
|
|
121
|
+
data: {
|
|
122
|
+
level: TelemetryLevel.Debug,
|
|
123
|
+
name: 'bootstrap::registerServiceWorker',
|
|
124
|
+
},
|
|
125
|
+
});
|
|
65
126
|
|
|
66
127
|
// create a client for the portal service - this is used to fetch the portal manifest
|
|
67
128
|
const portalClient = await ref.serviceDiscovery.createClient('portal-config');
|
|
@@ -69,25 +130,67 @@ enableMSAL(configurator, (builder) => {
|
|
|
69
130
|
// fetch the portal manifest - this is used to load the portal template
|
|
70
131
|
const portalId = import.meta.env.FUSION_SPA_PORTAL_ID;
|
|
71
132
|
const portalTag = import.meta.env.FUSION_SPA_PORTAL_TAG ?? 'latest';
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
133
|
+
const portalProxy = import.meta.env.FUSION_SPA_PORTAL_PROXY ?? false;
|
|
134
|
+
const portal_manifest = await measurement
|
|
135
|
+
.clone()
|
|
136
|
+
.resolve(portalClient.json<PortalManifest>(`/portals/${portalId}@${portalTag}`), {
|
|
137
|
+
data: (manifest: PortalManifest) => ({
|
|
138
|
+
name: 'bootstrap::loadPortalManifest',
|
|
139
|
+
level: TelemetryLevel.Debug,
|
|
140
|
+
properties: {
|
|
141
|
+
portalId,
|
|
142
|
+
portalTag,
|
|
143
|
+
templateEntry: manifest.build.templateEntry,
|
|
144
|
+
manifestVersion: manifest.build.config?.version,
|
|
145
|
+
assetPath: manifest.build.assetPath,
|
|
146
|
+
},
|
|
147
|
+
}),
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
const portal_config = await measurement
|
|
151
|
+
.clone()
|
|
152
|
+
.resolve(portalClient.json(`/portals/${portalId}@${portalTag}/config`), {
|
|
153
|
+
data: {
|
|
154
|
+
name: 'bootstrap::loadPortalConfig',
|
|
155
|
+
level: TelemetryLevel.Debug,
|
|
156
|
+
properties: {
|
|
157
|
+
portalId,
|
|
158
|
+
portalTag,
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
});
|
|
77
162
|
|
|
78
163
|
// create a entrypoint for the portal - this is used to render the portal
|
|
79
164
|
const el = document.createElement('div');
|
|
80
165
|
document.body.innerHTML = '';
|
|
81
166
|
document.body.appendChild(el);
|
|
82
167
|
|
|
83
|
-
const portalEntryPoint = [
|
|
168
|
+
const portalEntryPoint = [
|
|
169
|
+
portalProxy ? '/portal-proxy' : '',
|
|
170
|
+
portal_manifest.build.assetPath,
|
|
171
|
+
portal_manifest.build.templateEntry,
|
|
172
|
+
]
|
|
84
173
|
.filter(Boolean)
|
|
85
174
|
.join('/');
|
|
86
175
|
|
|
87
176
|
// @todo: should test if the entrypoint is external or internal
|
|
88
177
|
// @todo: add proper return type
|
|
89
|
-
const { render } =
|
|
90
|
-
|
|
178
|
+
const { render } = await measurement
|
|
179
|
+
.clone()
|
|
180
|
+
.resolve(
|
|
181
|
+
importWithoutVite<Promise<{ render: (...args: unknown[]) => void }>>(portalEntryPoint),
|
|
182
|
+
{
|
|
183
|
+
data: {
|
|
184
|
+
name: 'bootstrap::loadPortalSourceCode',
|
|
185
|
+
level: TelemetryLevel.Debug,
|
|
186
|
+
properties: {
|
|
187
|
+
portalId,
|
|
188
|
+
portalTag,
|
|
189
|
+
entryPoint: portalEntryPoint,
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
);
|
|
91
194
|
|
|
92
195
|
// render the portal - this will load the portal template and render it
|
|
93
196
|
render(el, { ref, manifest: portal_manifest, config: portal_config });
|
|
@@ -1,16 +1,30 @@
|
|
|
1
1
|
import type { ModulesInstance } from '@equinor/fusion-framework-module';
|
|
2
2
|
import type { MsalModule } from '@equinor/fusion-framework-module-msal';
|
|
3
|
+
import { TelemetryLevel, type TelemetryModule } from '@equinor/fusion-framework-module-telemetry';
|
|
3
4
|
|
|
4
|
-
export async function registerServiceWorker(
|
|
5
|
+
export async function registerServiceWorker(
|
|
6
|
+
framework: ModulesInstance<[MsalModule, TelemetryModule]>,
|
|
7
|
+
) {
|
|
8
|
+
const telemetry = framework.telemetry;
|
|
5
9
|
if ('serviceWorker' in navigator === false) {
|
|
6
|
-
|
|
7
|
-
|
|
10
|
+
const exception = new Error('Service workers are not supported in this browser.');
|
|
11
|
+
exception.name = 'ServiceWorkerNotSupported';
|
|
12
|
+
telemetry.trackException({
|
|
13
|
+
name: `registerServiceWorker.${exception.name}`,
|
|
14
|
+
exception,
|
|
15
|
+
});
|
|
16
|
+
throw exception;
|
|
8
17
|
}
|
|
9
18
|
|
|
10
19
|
const resourceConfigs = import.meta.env.FUSION_SPA_SERVICE_WORKER_RESOURCES;
|
|
11
20
|
if (!resourceConfigs) {
|
|
12
|
-
|
|
13
|
-
|
|
21
|
+
const exception = new Error('Service worker config is not defined.');
|
|
22
|
+
exception.name = 'ServiceWorkerConfigNotDefined';
|
|
23
|
+
telemetry.trackException({
|
|
24
|
+
name: `registerServiceWorker.${exception.name}`,
|
|
25
|
+
exception,
|
|
26
|
+
});
|
|
27
|
+
throw exception;
|
|
14
28
|
}
|
|
15
29
|
|
|
16
30
|
/**
|
|
@@ -34,14 +48,19 @@ export async function registerServiceWorker(framework: ModulesInstance<[MsalModu
|
|
|
34
48
|
// extract scopes from the event data
|
|
35
49
|
const scopes = event.data.scopes as string[];
|
|
36
50
|
if (!scopes || !Array.isArray(scopes)) {
|
|
37
|
-
|
|
51
|
+
const error = new Error('Invalid scopes provided');
|
|
52
|
+
error.name = 'InvalidScopesProvided';
|
|
53
|
+
throw error;
|
|
38
54
|
}
|
|
39
55
|
|
|
40
56
|
// request a token from the MSAL module
|
|
41
57
|
const token = await framework.auth.acquireToken({ scopes });
|
|
42
58
|
|
|
43
59
|
if (!token) {
|
|
44
|
-
|
|
60
|
+
const error = new Error('Failed to acquire token');
|
|
61
|
+
error.name = 'FailedToAcquireToken';
|
|
62
|
+
|
|
63
|
+
throw error;
|
|
45
64
|
}
|
|
46
65
|
|
|
47
66
|
// send the token back to the service worker
|
|
@@ -50,6 +69,11 @@ export async function registerServiceWorker(framework: ModulesInstance<[MsalModu
|
|
|
50
69
|
expiresOn: token.expiresOn?.getTime(),
|
|
51
70
|
});
|
|
52
71
|
} catch (error) {
|
|
72
|
+
const exception = error as Error;
|
|
73
|
+
telemetry.trackException({
|
|
74
|
+
name: `serviceWorker.onMessage.${exception.name}`,
|
|
75
|
+
exception,
|
|
76
|
+
});
|
|
53
77
|
event.ports[0].postMessage({
|
|
54
78
|
error: (error as Error).message,
|
|
55
79
|
});
|
|
@@ -57,14 +81,26 @@ export async function registerServiceWorker(framework: ModulesInstance<[MsalModu
|
|
|
57
81
|
}
|
|
58
82
|
});
|
|
59
83
|
|
|
60
|
-
// register the service worker
|
|
84
|
+
// register the service worker with telemetry
|
|
61
85
|
// updateViaCache: 'none' ensures the service worker script is always fetched fresh
|
|
62
86
|
// This is important during development to pick up code changes
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
updateViaCache: 'none',
|
|
87
|
+
using measurement = telemetry.measure({
|
|
88
|
+
name: 'registerServiceWorker',
|
|
89
|
+
level: TelemetryLevel.Information,
|
|
67
90
|
});
|
|
91
|
+
const registration = await measurement.clone().resolve(
|
|
92
|
+
navigator.serviceWorker.register('/@fusion-spa-sw.js', {
|
|
93
|
+
type: 'module',
|
|
94
|
+
scope: '/',
|
|
95
|
+
updateViaCache: 'none',
|
|
96
|
+
}),
|
|
97
|
+
{
|
|
98
|
+
data: {
|
|
99
|
+
name: 'registerServiceWorker.register',
|
|
100
|
+
level: TelemetryLevel.Debug,
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
);
|
|
68
104
|
|
|
69
105
|
// Handle service worker updates/installations
|
|
70
106
|
// If there's a service worker waiting or installing, send config when it activates
|
|
@@ -88,7 +124,12 @@ export async function registerServiceWorker(framework: ModulesInstance<[MsalModu
|
|
|
88
124
|
});
|
|
89
125
|
|
|
90
126
|
// wait for the service worker to be ready
|
|
91
|
-
const readyRegistration = await navigator.serviceWorker.ready
|
|
127
|
+
const readyRegistration = await measurement.clone().resolve(navigator.serviceWorker.ready, {
|
|
128
|
+
data: {
|
|
129
|
+
name: 'registerServiceWorker.ready',
|
|
130
|
+
level: TelemetryLevel.Debug,
|
|
131
|
+
},
|
|
132
|
+
});
|
|
92
133
|
|
|
93
134
|
// ensure we have an active service worker before sending config
|
|
94
135
|
const activeWorker = readyRegistration.active;
|
|
@@ -100,27 +141,35 @@ export async function registerServiceWorker(framework: ModulesInstance<[MsalModu
|
|
|
100
141
|
// CRITICAL: Wait for the service worker to become the controller
|
|
101
142
|
// This ensures the service worker can intercept fetch requests
|
|
102
143
|
if (!navigator.serviceWorker.controller) {
|
|
103
|
-
await
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
144
|
+
await measurement.clone().resolve(
|
|
145
|
+
new Promise<void>((resolve) => {
|
|
146
|
+
let checkInterval: NodeJS.Timeout;
|
|
147
|
+
|
|
148
|
+
const finish = () => {
|
|
149
|
+
clearInterval(checkInterval);
|
|
150
|
+
navigator.serviceWorker.removeEventListener('controllerchange', onControllerChange);
|
|
151
|
+
resolve();
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
const onControllerChange = () => finish();
|
|
155
|
+
|
|
156
|
+
// If controllerchange fires, the service worker has taken control
|
|
157
|
+
navigator.serviceWorker.addEventListener('controllerchange', onControllerChange);
|
|
158
|
+
|
|
159
|
+
// Polling fallback and timeout to prevent infinite waiting
|
|
160
|
+
checkInterval = setInterval(() => {
|
|
161
|
+
if (navigator.serviceWorker.controller) finish();
|
|
162
|
+
}, 200);
|
|
163
|
+
|
|
164
|
+
setTimeout(finish, 5000);
|
|
165
|
+
}),
|
|
166
|
+
{
|
|
167
|
+
data: {
|
|
168
|
+
name: 'registerServiceWorker.controllerWait',
|
|
169
|
+
level: TelemetryLevel.Debug,
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
);
|
|
124
173
|
}
|
|
125
174
|
|
|
126
175
|
// send the config to the active service worker
|
|
@@ -131,6 +180,9 @@ export async function registerServiceWorker(framework: ModulesInstance<[MsalModu
|
|
|
131
180
|
sendConfigToServiceWorker(navigator.serviceWorker.controller);
|
|
132
181
|
}
|
|
133
182
|
} catch (error) {
|
|
134
|
-
|
|
183
|
+
telemetry.trackException({
|
|
184
|
+
name: `registerServiceWorker.${(error as Error).name}`,
|
|
185
|
+
exception: error as Error,
|
|
186
|
+
});
|
|
135
187
|
}
|
|
136
188
|
}
|
package/src/types.ts
CHANGED
|
@@ -17,10 +17,15 @@ export type FusionTemplateEnv = {
|
|
|
17
17
|
/** Template bootstrap file path */
|
|
18
18
|
bootstrap: string;
|
|
19
19
|
|
|
20
|
+
telemetry?: {
|
|
21
|
+
consoleLevel?: number;
|
|
22
|
+
};
|
|
23
|
+
|
|
20
24
|
/** Id of the portal to load */
|
|
21
25
|
portal: {
|
|
22
26
|
id: string;
|
|
23
27
|
tag?: string;
|
|
28
|
+
proxy?: boolean;
|
|
24
29
|
};
|
|
25
30
|
|
|
26
31
|
/** Service discovery configuration */
|
package/src/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Generated by genversion.
|
|
2
|
-
export const version = '1.
|
|
2
|
+
export const version = '1.2.0';
|