@equinor/fusion-framework-cli 10.0.0-next-663bed8344cc2ca0111705b05045173328b3104d → 10.0.0-next-65f4bbf022d22b529abd095acd74ab218499fb8b
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 +10 -15
- package/bin/cli.mjs +1 -1
- package/dist/bin/build-application.js +65 -0
- package/dist/bin/build-application.js.map +1 -0
- package/dist/bin/bundle-application.js +56 -0
- package/dist/bin/bundle-application.js.map +1 -0
- package/dist/bin/create-dev-serve.js +123 -0
- package/dist/bin/create-dev-serve.js.map +1 -0
- package/dist/bin/create-export-config.js +50 -0
- package/dist/bin/create-export-config.js.map +1 -0
- package/dist/bin/create-export-manifest.js +77 -0
- package/dist/bin/create-export-manifest.js.map +1 -0
- package/dist/bin/dev-portal/AppLoader.js +77 -0
- package/dist/bin/dev-portal/AppLoader.js.map +1 -0
- package/dist/bin/dev-portal/BookMarkSideSheet.js +15 -0
- package/dist/bin/dev-portal/BookMarkSideSheet.js.map +1 -0
- package/dist/bin/dev-portal/ContextSelector/ContextSelector.js +41 -0
- package/dist/bin/dev-portal/ContextSelector/ContextSelector.js.map +1 -0
- package/dist/bin/dev-portal/ContextSelector/index.js +2 -0
- package/dist/bin/dev-portal/ContextSelector/index.js.map +1 -0
- package/dist/bin/dev-portal/ContextSelector/useContextResolver.js +171 -0
- package/dist/bin/dev-portal/ContextSelector/useContextResolver.js.map +1 -0
- package/dist/bin/dev-portal/EquinorLoader.js +14 -0
- package/dist/bin/dev-portal/EquinorLoader.js.map +1 -0
- package/dist/bin/dev-portal/ErrorViewer.js +7 -0
- package/dist/bin/dev-portal/ErrorViewer.js.map +1 -0
- package/dist/bin/dev-portal/FusionLogo.js +4 -0
- package/dist/bin/dev-portal/FusionLogo.js.map +1 -0
- package/dist/bin/dev-portal/Header.js +37 -0
- package/dist/bin/dev-portal/Header.js.map +1 -0
- package/dist/bin/dev-portal/PersonSideSheet/index.js +32 -0
- package/dist/bin/dev-portal/PersonSideSheet/index.js.map +1 -0
- package/dist/bin/dev-portal/PersonSideSheet/sheets/FeatureSheetContent.js +16 -0
- package/dist/bin/dev-portal/PersonSideSheet/sheets/FeatureSheetContent.js.map +1 -0
- package/dist/bin/dev-portal/PersonSideSheet/sheets/FeatureTogglerApp.js +16 -0
- package/dist/bin/dev-portal/PersonSideSheet/sheets/FeatureTogglerApp.js.map +1 -0
- package/dist/bin/dev-portal/PersonSideSheet/sheets/FeatureTogglerPortal.js +16 -0
- package/dist/bin/dev-portal/PersonSideSheet/sheets/FeatureTogglerPortal.js.map +1 -0
- package/dist/bin/dev-portal/PersonSideSheet/sheets/LandingSheetContent.js +19 -0
- package/dist/bin/dev-portal/PersonSideSheet/sheets/LandingSheetContent.js.map +1 -0
- package/dist/bin/dev-portal/PersonSideSheet/sheets/Styled.js +30 -0
- package/dist/bin/dev-portal/PersonSideSheet/sheets/Styled.js.map +1 -0
- package/dist/bin/dev-portal/PersonSideSheet/sheets/index.js +3 -0
- package/dist/bin/dev-portal/PersonSideSheet/sheets/index.js.map +1 -0
- package/dist/bin/dev-portal/PersonSideSheet/sheets/types.js +2 -0
- package/dist/bin/dev-portal/PersonSideSheet/sheets/types.js.map +1 -0
- package/dist/bin/dev-portal/Router.js +59 -0
- package/dist/bin/dev-portal/Router.js.map +1 -0
- package/dist/bin/dev-portal/config.js +69 -0
- package/dist/bin/dev-portal/config.js.map +1 -0
- package/dist/bin/dev-portal/main.js +13 -0
- package/dist/bin/dev-portal/main.js.map +1 -0
- package/dist/bin/dev-portal/resources/fallback-photo.svg.js +3 -0
- package/dist/bin/dev-portal/resources/fallback-photo.svg.js.map +1 -0
- package/dist/bin/dev-portal/useAppContextNavigation.js +68 -0
- package/dist/bin/dev-portal/useAppContextNavigation.js.map +1 -0
- package/dist/bin/main.app.js +171 -0
- package/dist/bin/main.app.js.map +1 -0
- package/dist/bin/main.js +20 -0
- package/dist/bin/main.js.map +1 -0
- package/dist/bin/public/assets/{index-Cb85_fOB.js → index-D0eBBcR8.js} +483 -483
- package/dist/bin/public/index.html +1 -1
- package/dist/bin/publish-application.js +104 -0
- package/dist/bin/publish-application.js.map +1 -0
- package/dist/bin/tag-application.js +82 -0
- package/dist/bin/tag-application.js.map +1 -0
- package/dist/bin/upload-application.js +72 -0
- package/dist/bin/upload-application.js.map +1 -0
- package/dist/bin/upload-export-config.js +87 -0
- package/dist/bin/upload-export-config.js.map +1 -0
- package/dist/bin/utils/execute-command.js +23 -0
- package/dist/bin/utils/execute-command.js.map +1 -0
- package/dist/bin/utils/format.js +17 -0
- package/dist/bin/utils/format.js.map +1 -0
- package/dist/bin/utils/getEndpointUrl.js +49 -0
- package/dist/bin/utils/getEndpointUrl.js.map +1 -0
- package/dist/bin/utils/index.js +14 -0
- package/dist/bin/utils/index.js.map +1 -0
- package/dist/bin/utils/isAppRegistered.js +35 -0
- package/dist/bin/utils/isAppRegistered.js.map +1 -0
- package/dist/bin/utils/load-app-config.js +35 -0
- package/dist/bin/utils/load-app-config.js.map +1 -0
- package/dist/bin/utils/load-manifest.js +40 -0
- package/dist/bin/utils/load-manifest.js.map +1 -0
- package/dist/bin/utils/load-package.js +24 -0
- package/dist/bin/utils/load-package.js.map +1 -0
- package/dist/bin/utils/load-vite-config.js +54 -0
- package/dist/bin/utils/load-vite-config.js.map +1 -0
- package/dist/bin/utils/proxy-request-logger.js +34 -0
- package/dist/bin/utils/proxy-request-logger.js.map +1 -0
- package/dist/bin/utils/publishAppConfig.js +36 -0
- package/dist/bin/utils/publishAppConfig.js.map +1 -0
- package/dist/bin/utils/requireToken.js +10 -0
- package/dist/bin/utils/requireToken.js.map +1 -0
- package/dist/bin/utils/spinner.js +77 -0
- package/dist/bin/utils/spinner.js.map +1 -0
- package/dist/bin/utils/tagAppBundle.js +35 -0
- package/dist/bin/utils/tagAppBundle.js.map +1 -0
- package/dist/bin/utils/uploadAppBundle.js +54 -0
- package/dist/bin/utils/uploadAppBundle.js.map +1 -0
- package/dist/lib/app-config.js +1 -1
- package/dist/lib/app-config.js.map +1 -1
- package/dist/schemas.js +14 -0
- package/dist/schemas.js.map +1 -0
- package/dist/types/bin/build-application.d.ts +13 -0
- package/dist/types/bin/bundle-application.d.ts +4 -0
- package/dist/types/bin/create-dev-serve.d.ts +11 -0
- package/dist/types/bin/create-export-config.d.ts +13 -0
- package/dist/types/bin/create-export-manifest.d.ts +16 -0
- package/dist/types/bin/dev-portal/AppLoader.d.ts +11 -0
- package/dist/types/bin/dev-portal/BookMarkSideSheet.d.ts +6 -0
- package/dist/types/bin/dev-portal/ContextSelector/ContextSelector.d.ts +8 -0
- package/dist/types/bin/dev-portal/ContextSelector/index.d.ts +1 -0
- package/dist/types/bin/dev-portal/ContextSelector/useContextResolver.d.ts +15 -0
- package/dist/types/bin/dev-portal/EquinorLoader.d.ts +5 -0
- package/dist/types/bin/dev-portal/ErrorViewer.d.ts +4 -0
- package/dist/types/bin/dev-portal/FusionLogo.d.ts +5 -0
- package/dist/types/bin/dev-portal/Header.d.ts +3 -0
- package/dist/types/bin/dev-portal/PersonSideSheet/index.d.ts +11 -0
- package/dist/types/bin/dev-portal/PersonSideSheet/sheets/FeatureSheetContent.d.ts +6 -0
- package/dist/types/bin/dev-portal/PersonSideSheet/sheets/FeatureTogglerApp.d.ts +5 -0
- package/dist/types/bin/dev-portal/PersonSideSheet/sheets/FeatureTogglerPortal.d.ts +5 -0
- package/dist/types/bin/dev-portal/PersonSideSheet/sheets/LandingSheetContent.d.ts +5 -0
- package/dist/types/bin/dev-portal/PersonSideSheet/sheets/Styled.d.ts +6 -0
- package/dist/types/bin/dev-portal/PersonSideSheet/sheets/index.d.ts +2 -0
- package/dist/types/bin/dev-portal/PersonSideSheet/sheets/types.d.ts +5 -0
- package/dist/types/bin/dev-portal/Router.d.ts +1 -0
- package/dist/types/bin/dev-portal/config.d.ts +3 -0
- package/dist/types/bin/dev-portal/main.d.ts +1 -0
- package/dist/types/bin/dev-portal/resources/fallback-photo.svg.d.ts +2 -0
- package/dist/types/bin/dev-portal/useAppContextNavigation.d.ts +5 -0
- package/dist/types/bin/main.app.d.ts +3 -0
- package/dist/types/bin/main.d.ts +1 -0
- package/dist/types/bin/publish-application.d.ts +6 -0
- package/dist/types/bin/tag-application.d.ts +12 -0
- package/dist/types/bin/upload-application.d.ts +6 -0
- package/dist/types/bin/upload-export-config.d.ts +10 -0
- package/dist/types/bin/utils/execute-command.d.ts +8 -0
- package/dist/types/bin/utils/format.d.ts +8 -0
- package/dist/types/bin/utils/getEndpointUrl.d.ts +10 -0
- package/dist/types/bin/utils/index.d.ts +14 -0
- package/dist/types/bin/utils/isAppRegistered.d.ts +5 -0
- package/dist/types/bin/utils/load-app-config.d.ts +10 -0
- package/dist/types/bin/utils/load-manifest.d.ts +10 -0
- package/dist/types/bin/utils/load-package.d.ts +5 -0
- package/dist/types/bin/utils/load-vite-config.d.ts +10 -0
- package/dist/types/bin/utils/proxy-request-logger.d.ts +15 -0
- package/dist/types/bin/utils/publishAppConfig.d.ts +9 -0
- package/dist/types/bin/utils/requireToken.d.ts +4 -0
- package/dist/types/bin/utils/spinner.d.ts +20 -0
- package/dist/types/bin/utils/tagAppBundle.d.ts +7 -0
- package/dist/types/bin/utils/uploadAppBundle.d.ts +7 -0
- package/dist/types/{app-config.d.ts → lib/app-config.d.ts} +1 -1
- package/dist/types/{plugins → lib/plugins}/app-proxy/app-proxy-plugin.d.ts +1 -1
- package/dist/types/schemas.d.ts +30 -0
- package/dist/types/version.d.ts +1 -0
- package/dist/version.js +3 -0
- package/dist/version.js.map +1 -0
- package/package.json +20 -23
- package/dist/bin/main.mjs +0 -2003
- /package/dist/types/{app-manifest.d.ts → lib/app-manifest.d.ts} +0 -0
- /package/dist/types/{app-package.d.ts → lib/app-package.d.ts} +0 -0
- /package/dist/types/{index.d.ts → lib/index.d.ts} +0 -0
- /package/dist/types/{plugins → lib/plugins}/app-assets/app-asset-plugin.d.ts +0 -0
- /package/dist/types/{plugins → lib/plugins}/app-assets/emit-asset.d.ts +0 -0
- /package/dist/types/{plugins → lib/plugins}/app-assets/extension-filter-pattern.d.ts +0 -0
- /package/dist/types/{plugins → lib/plugins}/app-assets/index.d.ts +0 -0
- /package/dist/types/{plugins → lib/plugins}/app-assets/read-asset-content.d.ts +0 -0
- /package/dist/types/{plugins → lib/plugins}/app-assets/resolve-asset-id.d.ts +0 -0
- /package/dist/types/{plugins → lib/plugins}/app-assets/static.d.ts +0 -0
- /package/dist/types/{plugins → lib/plugins}/app-proxy/index.d.ts +0 -0
- /package/dist/types/{plugins → lib/plugins}/external-public/external-public-plugin.d.ts +0 -0
- /package/dist/types/{plugins → lib/plugins}/external-public/index.d.ts +0 -0
- /package/dist/types/{utils → lib/utils}/assert.d.ts +0 -0
- /package/dist/types/{utils → lib/utils}/config.d.ts +0 -0
- /package/dist/types/{utils → lib/utils}/expect.d.ts +0 -0
- /package/dist/types/{utils → lib/utils}/file-exists.d.ts +0 -0
- /package/dist/types/{utils → lib/utils}/ts-transpile.d.ts +0 -0
- /package/dist/types/{utils → lib/utils}/types.d.ts +0 -0
- /package/dist/types/{vite-config.d.ts → lib/vite-config.d.ts} +0 -0
- /package/dist/types/{vite-logger.d.ts → lib/vite-logger.d.ts} +0 -0
package/dist/bin/main.mjs
DELETED
|
@@ -1,2003 +0,0 @@
|
|
|
1
|
-
import { pathToFileURL, fileURLToPath } from 'node:url';
|
|
2
|
-
import path, { join, dirname, resolve, extname, relative } from 'node:path';
|
|
3
|
-
import { readPackageUp, readPackageUpSync } from 'read-package-up';
|
|
4
|
-
import { Command } from 'commander';
|
|
5
|
-
import { createFilter, createLogger, defineConfig, mergeConfig, createServer, build } from 'vite';
|
|
6
|
-
import { assert as assert$1 } from 'node:console';
|
|
7
|
-
import portFinder from 'portfinder';
|
|
8
|
-
import deepmerge from 'deepmerge/index.js';
|
|
9
|
-
import ViteRestart from 'vite-plugin-restart';
|
|
10
|
-
import nodeFs, { existsSync, readFileSync, accessSync, constants, statSync } from 'node:fs';
|
|
11
|
-
import mime from 'mime';
|
|
12
|
-
import { access, stat, mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
13
|
-
import { findUpMultiple } from 'find-up';
|
|
14
|
-
import assert, { AssertionError } from 'node:assert';
|
|
15
|
-
import tsc from 'typescript';
|
|
16
|
-
import deepMerge from 'deepmerge';
|
|
17
|
-
import { execSync } from 'node:child_process';
|
|
18
|
-
import { parse } from 'semver';
|
|
19
|
-
import { interpolateName } from 'loader-utils';
|
|
20
|
-
import { ApiAppConfigSchema } from '@equinor/fusion-framework-module-app/schemas.js';
|
|
21
|
-
import ora from 'ora';
|
|
22
|
-
import chalk from 'chalk';
|
|
23
|
-
import prettyBytes from 'pretty-bytes';
|
|
24
|
-
import viteEnv from 'vite-plugin-environment';
|
|
25
|
-
import tsconfigPaths from 'vite-tsconfig-paths';
|
|
26
|
-
import AdmZip from 'adm-zip';
|
|
27
|
-
import fetch$1 from 'node-fetch';
|
|
28
|
-
import { exit } from 'node:process';
|
|
29
|
-
import semverValid from 'semver/functions/valid.js';
|
|
30
|
-
|
|
31
|
-
/******************************************************************************
|
|
32
|
-
Copyright (c) Microsoft Corporation.
|
|
33
|
-
|
|
34
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
35
|
-
purpose with or without fee is hereby granted.
|
|
36
|
-
|
|
37
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
38
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
39
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
40
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
41
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
42
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
43
|
-
PERFORMANCE OF THIS SOFTWARE.
|
|
44
|
-
***************************************************************************** */
|
|
45
|
-
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
function __rest(s, e) {
|
|
49
|
-
var t = {};
|
|
50
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
51
|
-
t[p] = s[p];
|
|
52
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
53
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
54
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
55
|
-
t[p[i]] = s[p[i]];
|
|
56
|
-
}
|
|
57
|
-
return t;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function __awaiter(thisArg, _arguments, P, generator) {
|
|
61
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
62
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
63
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
64
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
65
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
66
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function __classPrivateFieldGet(receiver, state, kind, f) {
|
|
71
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
72
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
73
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function __classPrivateFieldSet(receiver, state, value, kind, f) {
|
|
77
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
78
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
79
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
80
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
84
|
-
var e = new Error(message);
|
|
85
|
-
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Preserve token for executing proxy assets
|
|
90
|
-
*
|
|
91
|
-
* @remarks
|
|
92
|
-
* This assumes the client will execute a api call using bearer token before
|
|
93
|
-
* acquiring a asset. By default the Framework will execute a rest call to load
|
|
94
|
-
* application manifest for resolving build assets to import.
|
|
95
|
-
*
|
|
96
|
-
* @remarks
|
|
97
|
-
* This is a quick and dirty method to authorize requests without bearer token
|
|
98
|
-
* like browser `import`.
|
|
99
|
-
* The correct way would be to have a auth controller within the dev-server,
|
|
100
|
-
* but since the token is only exposed to the plugin and the cli is a tool for local
|
|
101
|
-
* development, this should be sufficient.
|
|
102
|
-
*/
|
|
103
|
-
let __APP_API_TOKEN__ = '';
|
|
104
|
-
/**
|
|
105
|
-
* The `appProxyPlugin` function creates a Vite plugin that configures a proxy for API and bundle requests
|
|
106
|
-
* to the Fusion apps backend. It also serves the app manifest, config, and local bundles if an app is provided.
|
|
107
|
-
*
|
|
108
|
-
* @param {AppProxyPluginOptions} options - The options for configuring the app proxy plugin.
|
|
109
|
-
*
|
|
110
|
-
* @returns {Plugin} - The configured Vite plugin.
|
|
111
|
-
*
|
|
112
|
-
* @example
|
|
113
|
-
* ```typescript
|
|
114
|
-
* const plugin = appProxyPlugin({
|
|
115
|
-
* proxy: {
|
|
116
|
-
* path: '/app-proxy',
|
|
117
|
-
* target: 'https://fusion-s-apps-ci.azurewebsites.net/',
|
|
118
|
-
* onProxyReq: (proxyReq, req, res) => {
|
|
119
|
-
* proxyReq.on('response', (res) => { console.log(res.statusCode) });
|
|
120
|
-
* },
|
|
121
|
-
* },
|
|
122
|
-
* app: {
|
|
123
|
-
* key: 'my-app',
|
|
124
|
-
* version: '1.0.0',
|
|
125
|
-
* generateConfig: async () => ({}),
|
|
126
|
-
* generateManifest: async () => ({}),
|
|
127
|
-
* },
|
|
128
|
-
* });
|
|
129
|
-
*
|
|
130
|
-
* // api calls
|
|
131
|
-
* fetch('/app-proxy/apps/my-app/builds/1.0.0/config'); // will generate app config by provided function
|
|
132
|
-
* fetch('/app-proxy/apps/my-app/builds/0.0.9/config'); // will proxy to the target, since version does not match
|
|
133
|
-
* fetch('/app-proxy/apps/other-app/builds/1.0.0/config'); // will proxy to the target, since app key does not match
|
|
134
|
-
*
|
|
135
|
-
* // asset calls
|
|
136
|
-
* fetch('/app-proxy/bundles/my-app/builds/1.0.0/index.js'); // will generate bundle by provided function
|
|
137
|
-
* fetch('/app-proxy/bundles/my-app/builds/0.0.9/index.js'); // will proxy to the target, since version does not match
|
|
138
|
-
* ```
|
|
139
|
-
*
|
|
140
|
-
*/
|
|
141
|
-
const appProxyPlugin = (options) => {
|
|
142
|
-
const { proxy: { onProxyReq = () => void 0, path: proxyPath, target }, } = options;
|
|
143
|
-
return {
|
|
144
|
-
name: 'fusion:app-proxy',
|
|
145
|
-
apply: 'serve',
|
|
146
|
-
config(config) {
|
|
147
|
-
var _a;
|
|
148
|
-
(_a = config.server) !== null && _a !== void 0 ? _a : (config.server = {});
|
|
149
|
-
config.server.proxy = {
|
|
150
|
-
// proxy all api calls to the fusion apps backend
|
|
151
|
-
[proxyPath]: {
|
|
152
|
-
target,
|
|
153
|
-
changeOrigin: true,
|
|
154
|
-
secure: false,
|
|
155
|
-
rewrite: (path) => path.replace(proxyPath, ''),
|
|
156
|
-
configure: (proxy) => {
|
|
157
|
-
proxy.on('proxyReq', (proxyReq) => {
|
|
158
|
-
const token = proxyReq.getHeader('authorization');
|
|
159
|
-
if (typeof token === 'string') {
|
|
160
|
-
// preserve token for executing proxy assets
|
|
161
|
-
__APP_API_TOKEN__ = token;
|
|
162
|
-
}
|
|
163
|
-
else if (__APP_API_TOKEN__) {
|
|
164
|
-
// apply token to proxy request
|
|
165
|
-
proxyReq.setHeader('authorization', __APP_API_TOKEN__);
|
|
166
|
-
}
|
|
167
|
-
});
|
|
168
|
-
proxy.on('proxyReq', onProxyReq);
|
|
169
|
-
},
|
|
170
|
-
},
|
|
171
|
-
};
|
|
172
|
-
},
|
|
173
|
-
configureServer(server) {
|
|
174
|
-
const { app } = options;
|
|
175
|
-
// disable local assets if no app configuration provided
|
|
176
|
-
if (!app)
|
|
177
|
-
return;
|
|
178
|
-
// serve app config if request matches the current app and version
|
|
179
|
-
const configPath = `${proxyPath}/apps/${app.key}/builds/${app.version}/config`;
|
|
180
|
-
server.middlewares.use(configPath, (_req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
181
|
-
res.setHeader('content-type', 'application/json');
|
|
182
|
-
res.end(JSON.stringify(yield app.generateConfig()));
|
|
183
|
-
}));
|
|
184
|
-
// serve app manifest if request matches the current app
|
|
185
|
-
// todo this should have version
|
|
186
|
-
const manifestPath = `${proxyPath}/apps/${app.key}`;
|
|
187
|
-
server.middlewares.use(manifestPath, (_req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
188
|
-
res.setHeader('content-type', 'application/json');
|
|
189
|
-
res.end(JSON.stringify(yield app.generateManifest()));
|
|
190
|
-
}));
|
|
191
|
-
// serve local bundles if request matches the current app and version
|
|
192
|
-
const bundlePath = `${proxyPath}/bundles/apps/${app.key}/${app.version}`;
|
|
193
|
-
server.middlewares.use((req, _res, next) => __awaiter(this, void 0, void 0, function* () {
|
|
194
|
-
var _a;
|
|
195
|
-
if ((_a = req.url) === null || _a === void 0 ? void 0 : _a.match(bundlePath)) {
|
|
196
|
-
// remove proxy path from url
|
|
197
|
-
req.url = req.url.replace(bundlePath, '');
|
|
198
|
-
}
|
|
199
|
-
next();
|
|
200
|
-
}));
|
|
201
|
-
},
|
|
202
|
-
};
|
|
203
|
-
};
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Creates a plugin that serves an external public directory.
|
|
207
|
-
*
|
|
208
|
-
* This plugin is useful when you want to serve a static site from a different directory than the one where the Vite server is running.
|
|
209
|
-
* Vite`s built in `mode: 'spa'` will only look for the `index.html` file in the configured `root` directory,
|
|
210
|
-
* so this plugin is necessary to serve the `index.html` file from a different directory.
|
|
211
|
-
*
|
|
212
|
-
* @param path - The path to the external public directory.
|
|
213
|
-
* @param options - Optional filter patterns to include or exclude specific assets.
|
|
214
|
-
* @param options.include - A filter pattern to include specific assets.
|
|
215
|
-
* @param options.exclude - A filter pattern to exclude specific assets.
|
|
216
|
-
* @returns A Vite plugin object.
|
|
217
|
-
*
|
|
218
|
-
* The plugin:
|
|
219
|
-
* - Sets the `path` configuration to the provided path.
|
|
220
|
-
* - Adds a middleware to the server that serves static assets from the specified path.
|
|
221
|
-
* - Adds a middleware to the server that serves the `index.html` file from the specified path.
|
|
222
|
-
*
|
|
223
|
-
* The middleware:
|
|
224
|
-
* - Checks if the request is for a static asset and serves it from the specified path.
|
|
225
|
-
* - Reads the `index.html` file from the specified path.
|
|
226
|
-
* - Transforms the HTML using the server's `transformIndexHtml` method.
|
|
227
|
-
* - Responds with the transformed HTML, setting appropriate headers.
|
|
228
|
-
*/
|
|
229
|
-
const externalPublicPlugin = (path, options) => {
|
|
230
|
-
let viteConfig;
|
|
231
|
-
const assetFilter = createFilter(void 0 , void 0 );
|
|
232
|
-
return {
|
|
233
|
-
name: 'fusion:external-public',
|
|
234
|
-
apply: 'serve',
|
|
235
|
-
configResolved(config) {
|
|
236
|
-
viteConfig = config;
|
|
237
|
-
},
|
|
238
|
-
configureServer(server) {
|
|
239
|
-
// serve the static assets from the provided path
|
|
240
|
-
server.middlewares.use((req, res, next) => __awaiter(this, void 0, void 0, function* () {
|
|
241
|
-
var _a;
|
|
242
|
-
const [urlPath] = req.url.split('?');
|
|
243
|
-
const assetPath = join(path, urlPath);
|
|
244
|
-
if (!assetFilter(assetPath) ||
|
|
245
|
-
(
|
|
246
|
-
// skip if the request is for index.html
|
|
247
|
-
(_a = req.url) === null || _a === void 0 ? void 0 : _a.match('index.html')) ||
|
|
248
|
-
// skip if request is for a source file
|
|
249
|
-
existsSync(join(viteConfig.root, urlPath)) ||
|
|
250
|
-
// skip if asset is in publicDir
|
|
251
|
-
existsSync(join(viteConfig.publicDir, urlPath)) ||
|
|
252
|
-
// skip if asset does not exist
|
|
253
|
-
!existsSync(assetPath)) {
|
|
254
|
-
return next();
|
|
255
|
-
}
|
|
256
|
-
try {
|
|
257
|
-
const content = readFileSync(assetPath);
|
|
258
|
-
const contentType = mime.getType(assetPath) || 'application/octet-stream';
|
|
259
|
-
res.writeHead(200, Object.assign({ 'content-type': contentType, 'content-length': Buffer.byteLength(content), 'cache-control': 'no-cache' }, server.config.server.headers));
|
|
260
|
-
res.end(content);
|
|
261
|
-
}
|
|
262
|
-
catch (e) {
|
|
263
|
-
next(e);
|
|
264
|
-
}
|
|
265
|
-
}));
|
|
266
|
-
// intercept requests to serve the index.html file
|
|
267
|
-
server.middlewares.use((req, res, next) => __awaiter(this, void 0, void 0, function* () {
|
|
268
|
-
var _a;
|
|
269
|
-
if (
|
|
270
|
-
// Only accept GET or HEAD
|
|
271
|
-
(req.method !== 'GET' && req.method !== 'HEAD') ||
|
|
272
|
-
// Only accept text/html
|
|
273
|
-
!((_a = req.headers.accept) === null || _a === void 0 ? void 0 : _a.includes('text/html'))) {
|
|
274
|
-
return next();
|
|
275
|
-
}
|
|
276
|
-
try {
|
|
277
|
-
// load the raw html from provided path
|
|
278
|
-
const htmlRaw = readFileSync(join(path, 'index.html'), 'utf-8');
|
|
279
|
-
// transform the html, this is where vite plugin hooks are applied
|
|
280
|
-
const html = yield server.transformIndexHtml(req.url, htmlRaw, req.originalUrl);
|
|
281
|
-
// apply content headers and configured additional headers
|
|
282
|
-
res.writeHead(200, Object.assign({ 'content-type': 'text/html', 'content-length': Buffer.byteLength(html), 'cache-control': 'no-cache' }, server.config.server.headers));
|
|
283
|
-
// send the transformed html and end the response
|
|
284
|
-
res.end(html);
|
|
285
|
-
}
|
|
286
|
-
catch (e) {
|
|
287
|
-
next(e);
|
|
288
|
-
}
|
|
289
|
-
}));
|
|
290
|
-
},
|
|
291
|
-
};
|
|
292
|
-
};
|
|
293
|
-
|
|
294
|
-
const fileExistsSync = (file, options) => {
|
|
295
|
-
try {
|
|
296
|
-
accessSync(file, constants.F_OK);
|
|
297
|
-
return true;
|
|
298
|
-
}
|
|
299
|
-
catch (err) {
|
|
300
|
-
return false;
|
|
301
|
-
}
|
|
302
|
-
};
|
|
303
|
-
const fileExists = (file, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
304
|
-
try {
|
|
305
|
-
yield access(file, constants.F_OK);
|
|
306
|
-
return true;
|
|
307
|
-
}
|
|
308
|
-
catch (err) {
|
|
309
|
-
if (options === null || options === void 0 ? void 0 : options.assert) {
|
|
310
|
-
throw err;
|
|
311
|
-
}
|
|
312
|
-
return false;
|
|
313
|
-
}
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
const transpile = (file) => __awaiter(void 0, void 0, void 0, function* () {
|
|
317
|
-
const pkg = yield readPackageUp();
|
|
318
|
-
assert(pkg, `failed to resolve bundle package`);
|
|
319
|
-
const pkgRoot = dirname(pkg.path);
|
|
320
|
-
const sourceFile = resolve(pkgRoot, file);
|
|
321
|
-
assert(sourceFile, `failed to resolve ${file}`);
|
|
322
|
-
const cacheDir = join(pkgRoot, 'node_modules', '.cache', 'ffc');
|
|
323
|
-
const targetFile = join(cacheDir, file.replace(pkgRoot, '').replace(/.ts$/, '.mjs'));
|
|
324
|
-
if (yield fileExists(targetFile)) {
|
|
325
|
-
const sourceTouch = (yield stat(sourceFile)).mtime;
|
|
326
|
-
const targetTouch = (yield stat(targetFile)).mtime;
|
|
327
|
-
if (sourceTouch < targetTouch) {
|
|
328
|
-
return targetFile;
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
if (!existsSync(dirname(targetFile))) {
|
|
332
|
-
yield mkdir(cacheDir, { recursive: true });
|
|
333
|
-
}
|
|
334
|
-
const compilerOptions = yield loadCompilerOptions('tsconfig.json');
|
|
335
|
-
const tsContent = (yield readFile(sourceFile)).toString();
|
|
336
|
-
const jsContent = tsc.transpileModule(tsContent, { compilerOptions }).outputText;
|
|
337
|
-
assert(jsContent, `failed to transpile [${file}]`);
|
|
338
|
-
yield writeFile(targetFile, jsContent);
|
|
339
|
-
return targetFile;
|
|
340
|
-
});
|
|
341
|
-
const loadCompilerOptions = (filename) => {
|
|
342
|
-
const config = tsc.readConfigFile(filename, tsc.sys.readFile).config;
|
|
343
|
-
if (config.extends) {
|
|
344
|
-
const extended = resolve(config.extends);
|
|
345
|
-
return Object.assign(Object.assign({}, loadCompilerOptions(extended)), config.compilerOptions);
|
|
346
|
-
}
|
|
347
|
-
return config.compilerOptions;
|
|
348
|
-
};
|
|
349
|
-
|
|
350
|
-
const supportedExt = ['.ts', '.mjs', '.js', '.json'];
|
|
351
|
-
/**
|
|
352
|
-
* @param filename name if config file without extension
|
|
353
|
-
*/
|
|
354
|
-
const findConfigs = (filename, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
355
|
-
const _a = options !== null && options !== void 0 ? options : {}, { extensions } = _a, findOptions = __rest(_a, ["extensions"]);
|
|
356
|
-
extensions && assertConfigFileType(extensions);
|
|
357
|
-
return findUpMultiple((extensions !== null && extensions !== void 0 ? extensions : supportedExt).map((ext) => [filename, ext].join('')), Object.assign(Object.assign({}, findOptions), { type: 'file' }));
|
|
358
|
-
});
|
|
359
|
-
const resolveConfig = (filename, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
360
|
-
const [file] = yield findConfigs(filename, options === null || options === void 0 ? void 0 : options.find);
|
|
361
|
-
if (file) {
|
|
362
|
-
return {
|
|
363
|
-
path: file,
|
|
364
|
-
config: yield loadConfig(file),
|
|
365
|
-
};
|
|
366
|
-
}
|
|
367
|
-
});
|
|
368
|
-
function assertConfigFileType(value, message) {
|
|
369
|
-
const values = typeof value === 'string' ? [value] : value;
|
|
370
|
-
values.forEach((ext) => assert$1(supportedExt.includes(ext), new AssertionError({
|
|
371
|
-
message: 'unsupported file type',
|
|
372
|
-
actual: value,
|
|
373
|
-
expected: supportedExt.join('|'),
|
|
374
|
-
})));
|
|
375
|
-
}
|
|
376
|
-
const configExtname = (file) => {
|
|
377
|
-
const ext = extname(file);
|
|
378
|
-
assertConfigFileType(ext);
|
|
379
|
-
return ext;
|
|
380
|
-
};
|
|
381
|
-
const loadConfig = (file) => __awaiter(void 0, void 0, void 0, function* () {
|
|
382
|
-
assert$1(yield fileExists(file, { assert: true }), `failed to access file ${file}`);
|
|
383
|
-
switch (configExtname(file)) {
|
|
384
|
-
case '.ts': {
|
|
385
|
-
return loadConfig(yield transpile(file));
|
|
386
|
-
}
|
|
387
|
-
case '.mjs':
|
|
388
|
-
case '.js': {
|
|
389
|
-
const result = (yield import(String(pathToFileURL(file)))).default;
|
|
390
|
-
return typeof result === 'function' ? result : () => result;
|
|
391
|
-
}
|
|
392
|
-
case '.json': {
|
|
393
|
-
return () => __awaiter(void 0, void 0, void 0, function* () { return JSON.parse(yield readFile(file, 'utf-8')); });
|
|
394
|
-
}
|
|
395
|
-
default:
|
|
396
|
-
throw Error('unsupported file type');
|
|
397
|
-
}
|
|
398
|
-
});
|
|
399
|
-
function initiateConfig(config, ...args) {
|
|
400
|
-
return Promise.resolve(config(...args));
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
function assertObject(value, message) {
|
|
404
|
-
assert(typeof value === 'object', message);
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
/**
|
|
408
|
-
* Resolves the entry point of a given package.
|
|
409
|
-
*
|
|
410
|
-
* This function attempts to find the entry point of a package by checking several
|
|
411
|
-
* common properties in the package's `package.json` file, such as `entrypoint`, `main`,
|
|
412
|
-
* and `module`. If none of these properties are found, it defaults to checking for
|
|
413
|
-
* common entry files like `src/index.ts`, `src/index.tsx`, `src/index.js`, and `src/index.jsx`.
|
|
414
|
-
*
|
|
415
|
-
* @param pkg - The resolved application package containing the package.json and path information.
|
|
416
|
-
* @returns The relative path to the resolved entry point.
|
|
417
|
-
* @throws Will throw an error if no entry point can be resolved.
|
|
418
|
-
*/
|
|
419
|
-
const resolveEntryPoint$1 = (packageJson, pkgPath = '') => {
|
|
420
|
-
const entrypoint = [
|
|
421
|
-
packageJson.entrypoint,
|
|
422
|
-
packageJson.main,
|
|
423
|
-
packageJson.module,
|
|
424
|
-
'src/index.ts',
|
|
425
|
-
'src/index.tsx',
|
|
426
|
-
'src/index.js',
|
|
427
|
-
'src/index.jsx',
|
|
428
|
-
]
|
|
429
|
-
.filter((x) => !!x)
|
|
430
|
-
.map((x) => relative(dirname(pkgPath), x))
|
|
431
|
-
.find((entry) => existsSync(entry));
|
|
432
|
-
assert(entrypoint, 'failed to resolve entrypoint');
|
|
433
|
-
return entrypoint;
|
|
434
|
-
};
|
|
435
|
-
/**
|
|
436
|
-
* Resolves the application key from the given package.json object.
|
|
437
|
-
*
|
|
438
|
-
* @param packageJson - An object containing the 'name' property from the package.json.
|
|
439
|
-
* @returns The resolved application key, which is the package name with any leading '@' or scope removed.
|
|
440
|
-
* @throws Will throw an error if the 'name' property is not present in the packageJson.
|
|
441
|
-
*/
|
|
442
|
-
const resolveAppKey = (packageJson) => {
|
|
443
|
-
assert(packageJson.name, 'expected [name] in packageJson');
|
|
444
|
-
return packageJson.name.replace(/^@|\w.*\//gm, '');
|
|
445
|
-
};
|
|
446
|
-
/**
|
|
447
|
-
* Resolves the application package by searching for the nearest `package.json` file.
|
|
448
|
-
*
|
|
449
|
-
* @param options - Optional parameters to customize the search behavior.
|
|
450
|
-
* @returns A promise that resolves to the found package information.
|
|
451
|
-
* @throws Will throw an error if the `package.json` file is not found.
|
|
452
|
-
*/
|
|
453
|
-
const resolveAppPackage = (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
454
|
-
const result = yield readPackageUp(options);
|
|
455
|
-
if (!result) {
|
|
456
|
-
throw Error('failed to find package.json');
|
|
457
|
-
}
|
|
458
|
-
return result;
|
|
459
|
-
});
|
|
460
|
-
|
|
461
|
-
/**
|
|
462
|
-
* Cache for the content of assets.
|
|
463
|
-
*/
|
|
464
|
-
const assetsContentMap = new Map();
|
|
465
|
-
/**
|
|
466
|
-
* Reads the content of an asset synchronously.
|
|
467
|
-
*
|
|
468
|
-
* @param id - The identifier of the asset, which can include a query string.
|
|
469
|
-
* @returns The content of the asset as a Buffer if it exists, otherwise null.
|
|
470
|
-
*
|
|
471
|
-
* @remarks
|
|
472
|
-
* - If the asset content is already cached, it returns the cached content.
|
|
473
|
-
* - The function extracts the filename from the identifier by removing any query string.
|
|
474
|
-
* - If the file exists, it reads the content, caches it, and then returns it.
|
|
475
|
-
* - If the file does not exist, it logs a warning and returns null.
|
|
476
|
-
*/
|
|
477
|
-
const readAssetContentSync = (id) => {
|
|
478
|
-
// check if the asset is already loaded
|
|
479
|
-
if (assetsContentMap.has(id)) {
|
|
480
|
-
return assetsContentMap.get(id);
|
|
481
|
-
}
|
|
482
|
-
// extract the filename without query
|
|
483
|
-
const [pureId] = id.split('?');
|
|
484
|
-
// if the file exists, read, cache and return content
|
|
485
|
-
if (existsSync(pureId)) {
|
|
486
|
-
const content = readFileSync(pureId);
|
|
487
|
-
assetsContentMap.set(id, content);
|
|
488
|
-
return content;
|
|
489
|
-
}
|
|
490
|
-
return null;
|
|
491
|
-
};
|
|
492
|
-
|
|
493
|
-
/**
|
|
494
|
-
* Synchronously emits an asset file based on the provided context and options.
|
|
495
|
-
*
|
|
496
|
-
* @param context - The plugin context used for emitting the file and logging warnings.
|
|
497
|
-
* @param id - The identifier of the asset, which may include a resource query.
|
|
498
|
-
* @param options - Optional parameters for customizing the emitted asset.
|
|
499
|
-
* @param options.name - The name template for the emitted asset file. Defaults to '[name].[ext]'.
|
|
500
|
-
* @param options.outDir - The output directory where the asset will be emitted. Defaults to 'dist'.
|
|
501
|
-
* @param options.assetsDir - The directory within the output directory where assets will be stored. Defaults to 'assets'.
|
|
502
|
-
* @returns The path of the emitted asset relative to the assets directory, or null if the asset content could not be read.
|
|
503
|
-
*/
|
|
504
|
-
const emitAssetSync = (context, id, options = {}) => {
|
|
505
|
-
const { outDir = 'dist', assetsDir = 'assets', name = '[name].[ext]' } = options;
|
|
506
|
-
const [originalFileName, resourceQuery] = id.split('?');
|
|
507
|
-
// read asset content, early return if not found
|
|
508
|
-
const content = readAssetContentSync(id);
|
|
509
|
-
if (!content || content.byteLength === 0) {
|
|
510
|
-
throw new Error(`Could not read asset content for ${id}`);
|
|
511
|
-
}
|
|
512
|
-
// generate asset file name
|
|
513
|
-
const url = interpolateName({
|
|
514
|
-
resourcePath: originalFileName,
|
|
515
|
-
resourceQuery,
|
|
516
|
-
}, name, { content });
|
|
517
|
-
const assetPath = path.posix.join(assetsDir, url);
|
|
518
|
-
const fileName = assetPath.replace(`?${resourceQuery}`, '');
|
|
519
|
-
const fullName = path.join(path.isAbsolute(outDir) ? process.cwd() : '', outDir, assetPath);
|
|
520
|
-
// write asset to file
|
|
521
|
-
context.emitFile({
|
|
522
|
-
fileName,
|
|
523
|
-
name: fullName,
|
|
524
|
-
type: 'asset',
|
|
525
|
-
source: content,
|
|
526
|
-
});
|
|
527
|
-
return assetPath;
|
|
528
|
-
};
|
|
529
|
-
|
|
530
|
-
const PLUGIN_NAME = 'vite:fusion:app-assets';
|
|
531
|
-
/**
|
|
532
|
-
* General asset extensions.
|
|
533
|
-
*/
|
|
534
|
-
const ASSET_EXTENSIONS = [
|
|
535
|
-
// Images
|
|
536
|
-
...['png', 'jpg', 'jpeg', 'gif', 'svg', 'ico', 'webp'],
|
|
537
|
-
// Videos and audio
|
|
538
|
-
...['mp4', 'webm', 'mp3'],
|
|
539
|
-
// Fonts
|
|
540
|
-
...['woff2', 'woff', 'eot', 'ttf', 'otf'],
|
|
541
|
-
// Documents
|
|
542
|
-
...['pdf', 'md', 'txt'],
|
|
543
|
-
];
|
|
544
|
-
|
|
545
|
-
/**
|
|
546
|
-
* Try to resolve the assets directly based on the ID and importer.
|
|
547
|
-
*/
|
|
548
|
-
const localResolve = (id, importer) => {
|
|
549
|
-
if (path.isAbsolute(id)) {
|
|
550
|
-
return { id, external: 'absolute', resolvedBy: PLUGIN_NAME };
|
|
551
|
-
}
|
|
552
|
-
else if (id.startsWith('.')) {
|
|
553
|
-
return {
|
|
554
|
-
id: path.resolve(path.dirname(importer), id),
|
|
555
|
-
external: 'relative',
|
|
556
|
-
resolvedBy: PLUGIN_NAME,
|
|
557
|
-
};
|
|
558
|
-
}
|
|
559
|
-
return null;
|
|
560
|
-
};
|
|
561
|
-
/**
|
|
562
|
-
* Resolves the asset ID based on the provided context, ID, importer, and options.
|
|
563
|
-
*
|
|
564
|
-
* @param context - The plugin context used for resolving the ID.
|
|
565
|
-
* @param id - The asset ID to resolve.
|
|
566
|
-
* @param importer - The path of the module that is importing the asset.
|
|
567
|
-
* @param options - Optional resolution options.
|
|
568
|
-
* @returns A promise that resolves to a `PartialResolvedId` object or `null`.
|
|
569
|
-
*
|
|
570
|
-
* The function handles three cases:
|
|
571
|
-
* 1. If the ID is an absolute path, it returns an object with the ID, marked as external and resolved by the plugin.
|
|
572
|
-
* 2. If the ID is a relative path, it resolves the path relative to the importer and returns an object with the resolved ID, marked as external and resolved by the plugin.
|
|
573
|
-
* 3. For all other cases, it delegates the resolution to the context's resolve method.
|
|
574
|
-
*/
|
|
575
|
-
const resolveAssetId = (context, id, importer, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
576
|
-
const resolve = localResolve(id, importer);
|
|
577
|
-
/**
|
|
578
|
-
* Check if the asset can be resolved locally.
|
|
579
|
-
* If the asset is found, return the resolved asset.
|
|
580
|
-
*
|
|
581
|
-
* @remarks
|
|
582
|
-
* The Id alone might not be enough to resolve the asset.
|
|
583
|
-
* Rollup only gives the ID as the import from the source.
|
|
584
|
-
*
|
|
585
|
-
* For example, if the import is `import svgData from './assets/image.svg';`,
|
|
586
|
-
* the actual file is `./assets/image.svg.js`.
|
|
587
|
-
*
|
|
588
|
-
* In this we try to as the context to resolve the ID.
|
|
589
|
-
*/
|
|
590
|
-
if (resolve && nodeFs.existsSync(resolve.id)) {
|
|
591
|
-
return resolve;
|
|
592
|
-
}
|
|
593
|
-
return yield context.resolve(id, importer, options);
|
|
594
|
-
});
|
|
595
|
-
|
|
596
|
-
/**
|
|
597
|
-
* Removes the leading dot from a file extension string.
|
|
598
|
-
* `.` are a RegExp special character, so it needs to be escaped.
|
|
599
|
-
*/
|
|
600
|
-
const trimLeadingDot = (ext) => ext.replace(/^\./, '');
|
|
601
|
-
/**
|
|
602
|
-
* Creates a regular expression pattern to filter files based on their extensions.
|
|
603
|
-
*
|
|
604
|
-
* @param exts - An array of file extensions to include in the pattern.
|
|
605
|
-
* @returns A RegExp object that matches files with the specified extensions.
|
|
606
|
-
*
|
|
607
|
-
* @example
|
|
608
|
-
* ```typescript
|
|
609
|
-
* const pattern = createExtensionFilterPattern(['.js', '.ts']);
|
|
610
|
-
* console.log(pattern); // Output: /\.(js|ts)(\?.*)?$/
|
|
611
|
-
* ```
|
|
612
|
-
*/
|
|
613
|
-
const createExtensionFilterPattern = (exts) => new RegExp(`\\.(${exts.map(trimLeadingDot).join('|')})(\\?.*)?$`);
|
|
614
|
-
|
|
615
|
-
const defaultInclude = createExtensionFilterPattern(ASSET_EXTENSIONS);
|
|
616
|
-
/**
|
|
617
|
-
* A Vite plugin to handle external resources in a library build.
|
|
618
|
-
*
|
|
619
|
-
* @param options - Configuration options for the plugin.
|
|
620
|
-
* @param options.name - Optional name for the emitted assets.
|
|
621
|
-
* @param options.include - Filter pattern to include specific files.
|
|
622
|
-
* @param options.exclude - Filter pattern to exclude specific files.
|
|
623
|
-
* @returns A Vite plugin object.
|
|
624
|
-
*
|
|
625
|
-
* @remarks
|
|
626
|
-
* This plugin is intended to be used only during the Vite library build process.
|
|
627
|
-
* It resolves asset IDs, emits assets, and exports them as URLs.
|
|
628
|
-
*
|
|
629
|
-
* @example
|
|
630
|
-
* ```typescript
|
|
631
|
-
* // vite.config.ts
|
|
632
|
-
* import { ExternalAppAssetPlugin } from '@equinor/fusion-framework-cli/plugins/app-assets-plugin';
|
|
633
|
-
*
|
|
634
|
-
* export default {
|
|
635
|
-
* plugins: [
|
|
636
|
-
* ExternalAppAssetPlugin({
|
|
637
|
-
* name: 'my-asset',
|
|
638
|
-
* include: ['svg', 'png'],
|
|
639
|
-
* exclude: 'node_modules/**',
|
|
640
|
-
* }),
|
|
641
|
-
* ],
|
|
642
|
-
* };
|
|
643
|
-
* ```
|
|
644
|
-
*/
|
|
645
|
-
const AppAssetExportPlugin = (options = {}) => {
|
|
646
|
-
const { name, include = defaultInclude, exclude } = options;
|
|
647
|
-
let viteConfig;
|
|
648
|
-
const assetsPathMap = new Map();
|
|
649
|
-
const filter = createFilter(include, exclude);
|
|
650
|
-
return {
|
|
651
|
-
name: PLUGIN_NAME,
|
|
652
|
-
enforce: 'pre',
|
|
653
|
-
apply: 'build',
|
|
654
|
-
configResolved(config) {
|
|
655
|
-
viteConfig = config;
|
|
656
|
-
},
|
|
657
|
-
resolveId(source_1) {
|
|
658
|
-
return __awaiter(this, arguments, void 0, function* (source, importer = '', opts) {
|
|
659
|
-
var _a;
|
|
660
|
-
if (viteConfig.build.lib === false) {
|
|
661
|
-
this.warn(`this plugin is only for vite build lib`);
|
|
662
|
-
}
|
|
663
|
-
// skip resolves triggered by plugin self
|
|
664
|
-
if (((_a = opts.custom) === null || _a === void 0 ? void 0 : _a.caller) === PLUGIN_NAME) {
|
|
665
|
-
return null;
|
|
666
|
-
}
|
|
667
|
-
// resolve asset ID, the ID should refer to the actual asset file
|
|
668
|
-
const assetId = yield resolveAssetId(this, source, importer, Object.assign(Object.assign({}, opts), { custom: Object.assign(Object.assign({}, opts.custom), { caller: PLUGIN_NAME }) }));
|
|
669
|
-
// skip if asset is not found or filtered out
|
|
670
|
-
const { id } = assetId !== null && assetId !== void 0 ? assetId : {};
|
|
671
|
-
const shouldIncludeAsset = id && filter(id);
|
|
672
|
-
if (!shouldIncludeAsset) {
|
|
673
|
-
return null;
|
|
674
|
-
}
|
|
675
|
-
try {
|
|
676
|
-
// emit asset and index the asset path
|
|
677
|
-
const { outDir, assetsDir } = viteConfig.build;
|
|
678
|
-
const assetPath = emitAssetSync(this, id, {
|
|
679
|
-
name,
|
|
680
|
-
outDir,
|
|
681
|
-
assetsDir,
|
|
682
|
-
});
|
|
683
|
-
assetsPathMap.set(id, assetPath);
|
|
684
|
-
}
|
|
685
|
-
catch (err) {
|
|
686
|
-
this.warn(err.message);
|
|
687
|
-
return null;
|
|
688
|
-
}
|
|
689
|
-
});
|
|
690
|
-
},
|
|
691
|
-
load(id) {
|
|
692
|
-
// lookup asset path and export as URL
|
|
693
|
-
const assetPath = assetsPathMap.get(id);
|
|
694
|
-
if (assetPath) {
|
|
695
|
-
// ensure asset path is relative from the script load path
|
|
696
|
-
return `export default new URL(/* @vite-ignore */'${assetPath}', import.meta.url).href`;
|
|
697
|
-
}
|
|
698
|
-
},
|
|
699
|
-
};
|
|
700
|
-
};
|
|
701
|
-
|
|
702
|
-
/** base filename for configuration files */
|
|
703
|
-
const manifestConfigFilename = 'app.manifest.config';
|
|
704
|
-
function assertAppManifest(value) {
|
|
705
|
-
var _a;
|
|
706
|
-
assert(value, 'expected manifest');
|
|
707
|
-
assert(value.build, 'expected build');
|
|
708
|
-
assert(parse((_a = value.build) === null || _a === void 0 ? void 0 : _a.version), 'invalid version');
|
|
709
|
-
// TODO make assertions
|
|
710
|
-
}
|
|
711
|
-
/** loads manifestFn from file */
|
|
712
|
-
const loadManifest = (filename) => loadConfig(filename !== null && filename !== void 0 ? filename : manifestConfigFilename);
|
|
713
|
-
/**
|
|
714
|
-
* tries to resolve manifest
|
|
715
|
-
* @see {@link resolveConfig | resolving config}
|
|
716
|
-
*/
|
|
717
|
-
const resolveManifest = (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
718
|
-
if (options === null || options === void 0 ? void 0 : options.file) {
|
|
719
|
-
const config = yield loadManifest(options.file);
|
|
720
|
-
return {
|
|
721
|
-
config,
|
|
722
|
-
path: options.file,
|
|
723
|
-
};
|
|
724
|
-
}
|
|
725
|
-
return resolveConfig(manifestConfigFilename, { find: options });
|
|
726
|
-
});
|
|
727
|
-
const resolveGithubRepo = (pkg) => {
|
|
728
|
-
try {
|
|
729
|
-
/* get reporurl from package.json */
|
|
730
|
-
if (pkg.repository) {
|
|
731
|
-
return typeof pkg.repository === 'string' ? pkg.repository : pkg.repository.url;
|
|
732
|
-
}
|
|
733
|
-
else {
|
|
734
|
-
/* get reporurl from git command */
|
|
735
|
-
return execSync('git remote get-url origin')
|
|
736
|
-
.toString()
|
|
737
|
-
.trim()
|
|
738
|
-
.replace('git@github.com:', 'https://github.com/')
|
|
739
|
-
.replace(/.git$/, '');
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
catch (_a) {
|
|
743
|
-
return undefined;
|
|
744
|
-
}
|
|
745
|
-
};
|
|
746
|
-
const resolveGitCommitSha = () => {
|
|
747
|
-
try {
|
|
748
|
-
return execSync('git rev-parse HEAD').toString().trim();
|
|
749
|
-
}
|
|
750
|
-
catch (_a) {
|
|
751
|
-
return undefined;
|
|
752
|
-
}
|
|
753
|
-
};
|
|
754
|
-
const createManifestFromPackage = (pkg) => {
|
|
755
|
-
const { packageJson } = pkg;
|
|
756
|
-
assertObject(packageJson, 'expected packageJson');
|
|
757
|
-
assert(packageJson.name, 'expected [name] in packageJson');
|
|
758
|
-
assert(packageJson.version, 'expected [version] in packageJson');
|
|
759
|
-
const entryPoint = resolveEntryPoint$1(packageJson);
|
|
760
|
-
const manifest = {
|
|
761
|
-
appKey: resolveAppKey(pkg.packageJson),
|
|
762
|
-
displayName: packageJson.name,
|
|
763
|
-
description: packageJson.description || '',
|
|
764
|
-
keywords: packageJson.keywords,
|
|
765
|
-
type: 'standalone',
|
|
766
|
-
build: {
|
|
767
|
-
entryPoint,
|
|
768
|
-
version: packageJson.version,
|
|
769
|
-
timestamp: new Date().toISOString(),
|
|
770
|
-
githubRepo: resolveGithubRepo(packageJson),
|
|
771
|
-
commitSha: resolveGitCommitSha(),
|
|
772
|
-
annotations: packageJson.annotations,
|
|
773
|
-
projectPage: packageJson.homepage,
|
|
774
|
-
allowedExtensions: ASSET_EXTENSIONS.map(
|
|
775
|
-
// TODO: @jaysencpp, this is just 🫤, extensions should not require leading dot
|
|
776
|
-
(ext) => `.${ext}`),
|
|
777
|
-
},
|
|
778
|
-
};
|
|
779
|
-
return manifest;
|
|
780
|
-
};
|
|
781
|
-
const createManifest$1 = (env, base, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
782
|
-
const resolved = yield resolveManifest(options);
|
|
783
|
-
if (resolved) {
|
|
784
|
-
const configuredManifest = yield initiateConfig(resolved.config, env, { base });
|
|
785
|
-
const manifest = deepMerge(base, configuredManifest !== null && configuredManifest !== void 0 ? configuredManifest : {});
|
|
786
|
-
assertAppManifest(manifest);
|
|
787
|
-
return { manifest, path: resolved.path };
|
|
788
|
-
}
|
|
789
|
-
else if (options === null || options === void 0 ? void 0 : options.file) {
|
|
790
|
-
throw new AssertionError({
|
|
791
|
-
message: `Expected to load manifest from ${options.file}`,
|
|
792
|
-
expected: '<manifest>',
|
|
793
|
-
});
|
|
794
|
-
}
|
|
795
|
-
return { manifest: base };
|
|
796
|
-
});
|
|
797
|
-
|
|
798
|
-
const appConfigFilename = 'app.config';
|
|
799
|
-
const loadAppConfig$1 = (filename) => loadConfig(filename !== null && filename !== void 0 ? filename : appConfigFilename);
|
|
800
|
-
const resolveAppConfig = (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
801
|
-
if (options === null || options === void 0 ? void 0 : options.file) {
|
|
802
|
-
const config = yield loadAppConfig$1(options.file);
|
|
803
|
-
return {
|
|
804
|
-
config,
|
|
805
|
-
path: options.file,
|
|
806
|
-
};
|
|
807
|
-
}
|
|
808
|
-
return resolveConfig(appConfigFilename, { find: options });
|
|
809
|
-
});
|
|
810
|
-
const createAppConfig = (env, base, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
811
|
-
var _a;
|
|
812
|
-
const resolved = yield resolveAppConfig(options);
|
|
813
|
-
if (resolved) {
|
|
814
|
-
const configValue = (_a = (yield initiateConfig(resolved.config, env, { base }))) !== null && _a !== void 0 ? _a : {};
|
|
815
|
-
const config = ApiAppConfigSchema.parse(configValue);
|
|
816
|
-
return { config, path: resolved.path };
|
|
817
|
-
}
|
|
818
|
-
else if (options === null || options === void 0 ? void 0 : options.file) {
|
|
819
|
-
throw new AssertionError({
|
|
820
|
-
message: `Expected to load config from ${options.file}`,
|
|
821
|
-
expected: '<file>',
|
|
822
|
-
});
|
|
823
|
-
}
|
|
824
|
-
return { config: base };
|
|
825
|
-
});
|
|
826
|
-
|
|
827
|
-
var _Spinner_ora;
|
|
828
|
-
const parseArgs = (args) => args.length ? args.join(' ') : undefined;
|
|
829
|
-
const originalConsole = console;
|
|
830
|
-
class Spinner {
|
|
831
|
-
get ora() {
|
|
832
|
-
return __classPrivateFieldGet(this, _Spinner_ora, "f");
|
|
833
|
-
}
|
|
834
|
-
set attachConsole(value) {
|
|
835
|
-
if (value) {
|
|
836
|
-
console.log = this.info.bind(this);
|
|
837
|
-
console.info = this.info.bind(this);
|
|
838
|
-
}
|
|
839
|
-
else {
|
|
840
|
-
console = originalConsole;
|
|
841
|
-
}
|
|
842
|
-
}
|
|
843
|
-
static Global(options) {
|
|
844
|
-
_spinner = new Spinner(options);
|
|
845
|
-
return _spinner;
|
|
846
|
-
}
|
|
847
|
-
static Clone(spinner) {
|
|
848
|
-
const { prefixText } = spinner || _spinner;
|
|
849
|
-
return new Spinner({ prefixText });
|
|
850
|
-
}
|
|
851
|
-
static get Current() {
|
|
852
|
-
return _spinner;
|
|
853
|
-
}
|
|
854
|
-
static set Current(spinner) {
|
|
855
|
-
_spinner = spinner;
|
|
856
|
-
}
|
|
857
|
-
constructor(options) {
|
|
858
|
-
_Spinner_ora.set(this, void 0);
|
|
859
|
-
__classPrivateFieldSet(this, _Spinner_ora, ora(options), "f");
|
|
860
|
-
}
|
|
861
|
-
get prefixText() {
|
|
862
|
-
return __classPrivateFieldGet(this, _Spinner_ora, "f").prefixText;
|
|
863
|
-
}
|
|
864
|
-
info(...args) {
|
|
865
|
-
__classPrivateFieldGet(this, _Spinner_ora, "f").info(parseArgs(args));
|
|
866
|
-
}
|
|
867
|
-
succeed(...args) {
|
|
868
|
-
__classPrivateFieldGet(this, _Spinner_ora, "f").succeed(parseArgs(args));
|
|
869
|
-
}
|
|
870
|
-
start(...args) {
|
|
871
|
-
__classPrivateFieldGet(this, _Spinner_ora, "f").start(parseArgs(args));
|
|
872
|
-
}
|
|
873
|
-
fail(...args) {
|
|
874
|
-
__classPrivateFieldGet(this, _Spinner_ora, "f").fail(parseArgs(args));
|
|
875
|
-
}
|
|
876
|
-
warn(...args) {
|
|
877
|
-
__classPrivateFieldGet(this, _Spinner_ora, "f").warn(parseArgs(args));
|
|
878
|
-
}
|
|
879
|
-
clear() {
|
|
880
|
-
__classPrivateFieldGet(this, _Spinner_ora, "f").clear();
|
|
881
|
-
}
|
|
882
|
-
stop() {
|
|
883
|
-
__classPrivateFieldGet(this, _Spinner_ora, "f").stop();
|
|
884
|
-
}
|
|
885
|
-
stopAndPersist(...args) {
|
|
886
|
-
__classPrivateFieldGet(this, _Spinner_ora, "f").stopAndPersist(...args);
|
|
887
|
-
}
|
|
888
|
-
}
|
|
889
|
-
_Spinner_ora = new WeakMap();
|
|
890
|
-
let _spinner = new Spinner();
|
|
891
|
-
|
|
892
|
-
const formatPath = (path, opt) => {
|
|
893
|
-
var _a;
|
|
894
|
-
return chalk.blueBright((opt === null || opt === void 0 ? void 0 : opt.relative) ? './' + relative((_a = opt === null || opt === void 0 ? void 0 : opt.cwd) !== null && _a !== void 0 ? _a : process.cwd(), path) : path);
|
|
895
|
-
};
|
|
896
|
-
const formatByteSize = (input) => {
|
|
897
|
-
if (typeof input === 'string') {
|
|
898
|
-
return formatByteSize(statSync(input).size);
|
|
899
|
-
}
|
|
900
|
-
return chalk.yellowBright(prettyBytes(input));
|
|
901
|
-
};
|
|
902
|
-
|
|
903
|
-
const loadAppConfig = (env, pkg, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
904
|
-
const spinner = Spinner.Current;
|
|
905
|
-
try {
|
|
906
|
-
spinner.start('create application configuration');
|
|
907
|
-
spinner.info(`generating config with ${chalk.red.dim(env.command)} command in ${chalk.green.dim(env.mode)} mode`);
|
|
908
|
-
const baseAppConfig = {};
|
|
909
|
-
const appConfig = yield createAppConfig(env, baseAppConfig, { file: options === null || options === void 0 ? void 0 : options.file });
|
|
910
|
-
spinner.succeed();
|
|
911
|
-
if (appConfig.path) {
|
|
912
|
-
spinner.info(`generating config from ${formatPath(appConfig.path, { relative: true })}`);
|
|
913
|
-
}
|
|
914
|
-
else {
|
|
915
|
-
spinner.info(chalk.dim('no local application config applied, using built-in'));
|
|
916
|
-
}
|
|
917
|
-
return appConfig;
|
|
918
|
-
}
|
|
919
|
-
catch (err) {
|
|
920
|
-
spinner.fail(`failed to resolve application config ${(options === null || options === void 0 ? void 0 : options.file) ? formatPath(options === null || options === void 0 ? void 0 : options.file) : ''}`);
|
|
921
|
-
throw err;
|
|
922
|
-
}
|
|
923
|
-
});
|
|
924
|
-
|
|
925
|
-
const createViteLogger = () => {
|
|
926
|
-
const logger = createLogger();
|
|
927
|
-
const originalLogger = Object.assign({}, logger);
|
|
928
|
-
logger.error = (msg, opt) => {
|
|
929
|
-
// TODO find a way to make these assets external
|
|
930
|
-
if (msg.match(/^Pre-transform error: Failed to load url \/assets/)) {
|
|
931
|
-
return;
|
|
932
|
-
}
|
|
933
|
-
originalLogger.error(msg, opt);
|
|
934
|
-
};
|
|
935
|
-
logger.warn = (msg, options) => {
|
|
936
|
-
/** import of app file from framework */
|
|
937
|
-
if (msg.includes('import(manifest.entry)') &&
|
|
938
|
-
msg.includes('dynamic-import-vars#limitations'))
|
|
939
|
-
return;
|
|
940
|
-
originalLogger.warn(msg, options);
|
|
941
|
-
};
|
|
942
|
-
return logger;
|
|
943
|
-
};
|
|
944
|
-
|
|
945
|
-
const configFilename = 'app.vite.config';
|
|
946
|
-
const loadViteConfig$1 = (filename) => loadConfig(filename !== null && filename !== void 0 ? filename : configFilename);
|
|
947
|
-
const resolveViteConfig = (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
948
|
-
if (options === null || options === void 0 ? void 0 : options.file) {
|
|
949
|
-
const config = yield loadViteConfig$1(options.file);
|
|
950
|
-
return {
|
|
951
|
-
config,
|
|
952
|
-
path: options.file,
|
|
953
|
-
};
|
|
954
|
-
}
|
|
955
|
-
return resolveConfig(configFilename, { find: options });
|
|
956
|
-
});
|
|
957
|
-
const createAppViteConfig = (env, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
958
|
-
var _a;
|
|
959
|
-
const resolved = yield resolveViteConfig(options);
|
|
960
|
-
if (resolved) {
|
|
961
|
-
const config = (_a = (yield initiateConfig(resolved.config, env))) !== null && _a !== void 0 ? _a : {};
|
|
962
|
-
return { config, path: resolved.path };
|
|
963
|
-
}
|
|
964
|
-
else if (options === null || options === void 0 ? void 0 : options.file) {
|
|
965
|
-
throw new AssertionError({
|
|
966
|
-
message: `Expected to load config from ${options.file}`,
|
|
967
|
-
expected: '<file>',
|
|
968
|
-
});
|
|
969
|
-
}
|
|
970
|
-
});
|
|
971
|
-
const resolveEntryPoint = (cwd, dir, opt) => {
|
|
972
|
-
var _a;
|
|
973
|
-
cwd !== null && cwd !== void 0 ? cwd : (cwd = process.cwd());
|
|
974
|
-
dir !== null && dir !== void 0 ? dir : (dir = 'src');
|
|
975
|
-
const files = (_a = void 0 ) !== null && _a !== void 0 ? _a : ['index.ts', 'index.tsx', 'main.ts', 'main.tsx'];
|
|
976
|
-
return files
|
|
977
|
-
.map((file) => [dir, file].join('/'))
|
|
978
|
-
.find((file) => fileExistsSync(path.resolve(cwd, file)));
|
|
979
|
-
};
|
|
980
|
-
const createViteConfig = (env, overrides) => __awaiter(void 0, void 0, void 0, function* () {
|
|
981
|
-
var _a;
|
|
982
|
-
const { root = process.cwd() } = env;
|
|
983
|
-
const entry = String(resolveEntryPoint(root));
|
|
984
|
-
const defaultConfig = defineConfig({
|
|
985
|
-
plugins: [
|
|
986
|
-
tsconfigPaths(),
|
|
987
|
-
viteEnv({
|
|
988
|
-
NODE_ENV: env.mode,
|
|
989
|
-
FUSION_LOG_LEVEL: ((_a = process.env.FUSION_LOG_LEVEL) !== null && _a !== void 0 ? _a : env.mode === 'development') ? '3' : '1',
|
|
990
|
-
}),
|
|
991
|
-
],
|
|
992
|
-
mode: env.mode,
|
|
993
|
-
root,
|
|
994
|
-
appType: 'custom',
|
|
995
|
-
build: {
|
|
996
|
-
lib: {
|
|
997
|
-
entry,
|
|
998
|
-
fileName: 'app-bundle',
|
|
999
|
-
formats: ['es'],
|
|
1000
|
-
},
|
|
1001
|
-
rollupOptions: {
|
|
1002
|
-
output: {
|
|
1003
|
-
manualChunks: undefined,
|
|
1004
|
-
},
|
|
1005
|
-
},
|
|
1006
|
-
},
|
|
1007
|
-
customLogger: createViteLogger(),
|
|
1008
|
-
});
|
|
1009
|
-
return defaultConfig;
|
|
1010
|
-
});
|
|
1011
|
-
|
|
1012
|
-
const loadViteConfig = (env, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1013
|
-
const spinner = Spinner.Current;
|
|
1014
|
-
try {
|
|
1015
|
-
spinner.start('load local vite configuration');
|
|
1016
|
-
const appViteConfig = yield createAppViteConfig(env, {
|
|
1017
|
-
file: options === null || options === void 0 ? void 0 : options.file,
|
|
1018
|
-
});
|
|
1019
|
-
spinner.succeed();
|
|
1020
|
-
if (appViteConfig === null || appViteConfig === void 0 ? void 0 : appViteConfig.path) {
|
|
1021
|
-
spinner.info(`🛠️ ${formatPath(appViteConfig.path, { relative: true })}`);
|
|
1022
|
-
}
|
|
1023
|
-
else if (options === null || options === void 0 ? void 0 : options.file) {
|
|
1024
|
-
spinner.fail(`failed to load vite config from ${formatPath(options === null || options === void 0 ? void 0 : options.file)}`);
|
|
1025
|
-
throw new AssertionError({
|
|
1026
|
-
message: `Expected to load config from ${formatPath(options === null || options === void 0 ? void 0 : options.file)}`,
|
|
1027
|
-
expected: '<UserConfig>',
|
|
1028
|
-
});
|
|
1029
|
-
}
|
|
1030
|
-
else {
|
|
1031
|
-
spinner.info(chalk.dim(`no local vite config applied, using built-in see ${formatPath('https://vitejs.dev/config/')}`));
|
|
1032
|
-
}
|
|
1033
|
-
spinner.start('create vite configuration');
|
|
1034
|
-
const viteConfig = yield createViteConfig(env);
|
|
1035
|
-
spinner.succeed();
|
|
1036
|
-
if (appViteConfig === null || appViteConfig === void 0 ? void 0 : appViteConfig.config) {
|
|
1037
|
-
return {
|
|
1038
|
-
viteConfig: mergeConfig(viteConfig, appViteConfig.config),
|
|
1039
|
-
path: appViteConfig.path,
|
|
1040
|
-
};
|
|
1041
|
-
}
|
|
1042
|
-
else {
|
|
1043
|
-
return { viteConfig };
|
|
1044
|
-
}
|
|
1045
|
-
}
|
|
1046
|
-
catch (err) {
|
|
1047
|
-
spinner.fail();
|
|
1048
|
-
throw err;
|
|
1049
|
-
}
|
|
1050
|
-
});
|
|
1051
|
-
|
|
1052
|
-
const loadPackage = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
1053
|
-
const spinner = Spinner.Current;
|
|
1054
|
-
spinner.start('resolve application package');
|
|
1055
|
-
const pkg = yield resolveAppPackage();
|
|
1056
|
-
spinner.succeed();
|
|
1057
|
-
spinner.info('📦', chalk.yellowBright([pkg.packageJson.name, pkg.packageJson.version].join('@')));
|
|
1058
|
-
const packageDirname = dirname(pkg.path);
|
|
1059
|
-
spinner.info(`🏠 ${chalk.blueBright(packageDirname)}`);
|
|
1060
|
-
return Object.assign(Object.assign({}, pkg), { root: packageDirname });
|
|
1061
|
-
});
|
|
1062
|
-
|
|
1063
|
-
const loadAppManifest = (env, pkg, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1064
|
-
const spinner = Spinner.Clone();
|
|
1065
|
-
try {
|
|
1066
|
-
spinner.start('create application manifest');
|
|
1067
|
-
const baseManifest = yield createManifestFromPackage(pkg);
|
|
1068
|
-
spinner.info('created application manifest from package.json');
|
|
1069
|
-
// TODO - this need to come from the config
|
|
1070
|
-
if (env.command !== 'serve') {
|
|
1071
|
-
baseManifest.build.entryPoint =
|
|
1072
|
-
pkg.packageJson.type === 'module' ? 'app-bundle.js' : 'app-bundle.mjs';
|
|
1073
|
-
}
|
|
1074
|
-
spinner.info(`generating manifest with ${chalk.red.dim(env.command)} command in ${chalk.green.dim(env.mode)} mode`);
|
|
1075
|
-
const manifest = yield createManifest$1(env, baseManifest, { file: options === null || options === void 0 ? void 0 : options.file });
|
|
1076
|
-
if (manifest.path) {
|
|
1077
|
-
spinner.succeed(`Created manifest from ${formatPath(manifest.path, { relative: true })}`);
|
|
1078
|
-
}
|
|
1079
|
-
else {
|
|
1080
|
-
spinner.succeed(chalk.dim('no local manifest config applied, using default generated'));
|
|
1081
|
-
}
|
|
1082
|
-
return manifest;
|
|
1083
|
-
}
|
|
1084
|
-
catch (err) {
|
|
1085
|
-
spinner.fail(`failed to resolve manifest ${(options === null || options === void 0 ? void 0 : options.file) ? formatPath(options === null || options === void 0 ? void 0 : options.file) : ''}`);
|
|
1086
|
-
throw err;
|
|
1087
|
-
}
|
|
1088
|
-
});
|
|
1089
|
-
|
|
1090
|
-
/**
|
|
1091
|
-
* Logs the status of a proxy request using a spinner.
|
|
1092
|
-
*
|
|
1093
|
-
* @param proxyReq - The proxy request to log.
|
|
1094
|
-
*
|
|
1095
|
-
* The function attaches event listeners to the proxy request to handle
|
|
1096
|
-
* 'response' and 'error' events. It uses a spinner to indicate the status
|
|
1097
|
-
* of the request:
|
|
1098
|
-
* - On a successful response (status code < 400), the spinner succeeds.
|
|
1099
|
-
* - On a response with a status code >= 400, the spinner warns with the status message.
|
|
1100
|
-
* - On an error, the spinner fails.
|
|
1101
|
-
*/
|
|
1102
|
-
const proxyRequestLogger = (proxyReq) => {
|
|
1103
|
-
const spinner = Spinner.Clone();
|
|
1104
|
-
spinner.ora.suffixText = formatPath([proxyReq.protocol, '//', proxyReq.host, proxyReq.path].join(''));
|
|
1105
|
-
spinner.start('proxy request');
|
|
1106
|
-
proxyReq.on('response', (res) => {
|
|
1107
|
-
var _a;
|
|
1108
|
-
if (Number(res.statusCode) < 400) {
|
|
1109
|
-
spinner.succeed();
|
|
1110
|
-
}
|
|
1111
|
-
else {
|
|
1112
|
-
spinner.warn(chalk.yellow((_a = res.statusMessage) !== null && _a !== void 0 ? _a : `${res.statusCode} `));
|
|
1113
|
-
}
|
|
1114
|
-
spinner.stop();
|
|
1115
|
-
});
|
|
1116
|
-
proxyReq.on('error', () => {
|
|
1117
|
-
spinner.fail();
|
|
1118
|
-
});
|
|
1119
|
-
};
|
|
1120
|
-
|
|
1121
|
-
const createDevServer = (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1122
|
-
var _a, _b, _c, _d;
|
|
1123
|
-
const { configSourceFiles, library, port, devPortalPath } = options;
|
|
1124
|
-
const spinner = Spinner.Global({ prefixText: chalk.dim('dev-server') });
|
|
1125
|
-
const pkg = yield loadPackage();
|
|
1126
|
-
const env = {
|
|
1127
|
-
command: 'serve',
|
|
1128
|
-
mode: (_a = process.env.NODE_ENV) !== null && _a !== void 0 ? _a : 'development',
|
|
1129
|
-
root: pkg.root,
|
|
1130
|
-
};
|
|
1131
|
-
const generateManifest = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
1132
|
-
const { manifest } = yield loadAppManifest(env, pkg, {
|
|
1133
|
-
file: configSourceFiles.manifest,
|
|
1134
|
-
});
|
|
1135
|
-
const assetPath = `bundles/apps/${manifest.appKey}/${pkg.packageJson.version}`;
|
|
1136
|
-
return deepmerge(manifest, {
|
|
1137
|
-
build: {
|
|
1138
|
-
assetPath,
|
|
1139
|
-
configUrl: `${assetPath}/config`,
|
|
1140
|
-
},
|
|
1141
|
-
});
|
|
1142
|
-
});
|
|
1143
|
-
const generateConfig = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
1144
|
-
const { config } = yield loadAppConfig(env, pkg, {
|
|
1145
|
-
file: configSourceFiles.app,
|
|
1146
|
-
});
|
|
1147
|
-
return config;
|
|
1148
|
-
});
|
|
1149
|
-
const { appKey } = yield generateManifest();
|
|
1150
|
-
/**
|
|
1151
|
-
* Load application manifest
|
|
1152
|
-
* Application might have overridden the `appKey`
|
|
1153
|
-
*/
|
|
1154
|
-
spinner.info(`resolved application key ${chalk.magenta(appKey)}`);
|
|
1155
|
-
const { viteConfig: baseViteConfig, path: viteConfigPath } = yield loadViteConfig(env, {
|
|
1156
|
-
file: configSourceFiles.vite,
|
|
1157
|
-
});
|
|
1158
|
-
/**
|
|
1159
|
-
* Defines the configuration for the development server.
|
|
1160
|
-
*/
|
|
1161
|
-
const devServerConfig = defineConfig({
|
|
1162
|
-
publicDir: devPortalPath,
|
|
1163
|
-
appType: 'custom',
|
|
1164
|
-
server: {
|
|
1165
|
-
open: `/apps/${appKey}`,
|
|
1166
|
-
port: port !== null && port !== void 0 ? port : (yield portFinder.getPortPromise({ port: 3000 })),
|
|
1167
|
-
},
|
|
1168
|
-
plugins: [
|
|
1169
|
-
// Serve the dev portal as static files
|
|
1170
|
-
externalPublicPlugin(devPortalPath),
|
|
1171
|
-
// Proxy requests to the app server
|
|
1172
|
-
appProxyPlugin({
|
|
1173
|
-
proxy: {
|
|
1174
|
-
path: '/apps-proxy',
|
|
1175
|
-
target: 'https://fusion-s-apps-ci.azurewebsites.net/',
|
|
1176
|
-
onProxyReq: proxyRequestLogger,
|
|
1177
|
-
},
|
|
1178
|
-
app: {
|
|
1179
|
-
key: appKey,
|
|
1180
|
-
version: String(pkg.packageJson.version),
|
|
1181
|
-
generateConfig,
|
|
1182
|
-
generateManifest,
|
|
1183
|
-
},
|
|
1184
|
-
}),
|
|
1185
|
-
// Restart the server when config changes or the dev portal source is updated
|
|
1186
|
-
ViteRestart({
|
|
1187
|
-
restart: [
|
|
1188
|
-
'package.json',
|
|
1189
|
-
viteConfigPath,
|
|
1190
|
-
join(relative(process.cwd(), devPortalPath), '/**/*'),
|
|
1191
|
-
].filter((x) => !!x),
|
|
1192
|
-
/** reload the CLI when config changes, note change to APP-KEY need restart */
|
|
1193
|
-
reload: [
|
|
1194
|
-
...supportedExt.map((ext) => [appConfigFilename, ext].join('')),
|
|
1195
|
-
...supportedExt.map((ext) => [manifestConfigFilename, ext].join('')),
|
|
1196
|
-
],
|
|
1197
|
-
}),
|
|
1198
|
-
],
|
|
1199
|
-
});
|
|
1200
|
-
// Merge the base Vite config with the dev server config
|
|
1201
|
-
const viteConfig = mergeConfig(devServerConfig, baseViteConfig);
|
|
1202
|
-
/** Add library/framework plugins */
|
|
1203
|
-
if (library === 'react') {
|
|
1204
|
-
const reactPlugin = yield import('@vitejs/plugin-react');
|
|
1205
|
-
viteConfig.plugins.push(reactPlugin.default());
|
|
1206
|
-
}
|
|
1207
|
-
assert$1((_b = viteConfig.build) === null || _b === void 0 ? void 0 : _b.lib, 'expected vite build to have library defined');
|
|
1208
|
-
const { entry } = viteConfig.build.lib;
|
|
1209
|
-
spinner.info('💾 application entrypoint', formatPath(String(entry), { relative: true }));
|
|
1210
|
-
spinner.info('resolving cli internal assets from', formatPath(String(viteConfig.publicDir), { relative: true }));
|
|
1211
|
-
const vite = yield createServer(Object.assign(Object.assign({}, env), viteConfig));
|
|
1212
|
-
spinner.start('🚀 start server');
|
|
1213
|
-
yield vite.listen();
|
|
1214
|
-
spinner.succeed('🔗', chalk.underline.green(new URL(`/apps/${appKey}`, (_d = (_c = vite.resolvedUrls) === null || _c === void 0 ? void 0 : _c.local[0]) !== null && _d !== void 0 ? _d : `https://localhost:/${vite.config.server.port}`).href));
|
|
1215
|
-
});
|
|
1216
|
-
|
|
1217
|
-
const buildApplication = (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1218
|
-
var _a, _b;
|
|
1219
|
-
const { configSourceFiles, library, outDir } = options;
|
|
1220
|
-
const env = {
|
|
1221
|
-
command: 'build',
|
|
1222
|
-
mode: (_a = process.env.NODE_ENV) !== null && _a !== void 0 ? _a : 'production',
|
|
1223
|
-
};
|
|
1224
|
-
const spinner = Spinner.Global({ prefixText: chalk.dim('build') });
|
|
1225
|
-
spinner.start('resolve application package');
|
|
1226
|
-
const pkg = yield resolveAppPackage();
|
|
1227
|
-
spinner.succeed();
|
|
1228
|
-
spinner.info('📦', chalk.yellowBright([pkg.packageJson.name, pkg.packageJson.version].join('@')));
|
|
1229
|
-
const packageDirname = dirname(pkg.path);
|
|
1230
|
-
spinner.info(`🏠 ${chalk.blueBright(packageDirname)}`);
|
|
1231
|
-
spinner.start('resolve application manifest');
|
|
1232
|
-
const { manifest } = yield loadAppManifest(env, pkg, {
|
|
1233
|
-
file: configSourceFiles === null || configSourceFiles === void 0 ? void 0 : configSourceFiles.manifest,
|
|
1234
|
-
});
|
|
1235
|
-
spinner.succeed();
|
|
1236
|
-
const { viteConfig } = yield loadViteConfig(env, {
|
|
1237
|
-
file: configSourceFiles === null || configSourceFiles === void 0 ? void 0 : configSourceFiles.vite,
|
|
1238
|
-
});
|
|
1239
|
-
const includeAssetsPattern = ((_b = manifest.build) === null || _b === void 0 ? void 0 : _b.allowedExtensions)
|
|
1240
|
-
? createExtensionFilterPattern(manifest.build.allowedExtensions)
|
|
1241
|
-
: undefined;
|
|
1242
|
-
spinner.info('📂', 'Using asset include filter:', chalk.red(includeAssetsPattern));
|
|
1243
|
-
viteConfig.plugins = [
|
|
1244
|
-
...viteConfig.plugins,
|
|
1245
|
-
AppAssetExportPlugin({
|
|
1246
|
-
include: includeAssetsPattern,
|
|
1247
|
-
}),
|
|
1248
|
-
];
|
|
1249
|
-
if (library === 'react') {
|
|
1250
|
-
const reactPlugin = yield import('@vitejs/plugin-react');
|
|
1251
|
-
viteConfig.plugins.push(reactPlugin.default());
|
|
1252
|
-
}
|
|
1253
|
-
viteConfig.build.outDir = outDir.trim();
|
|
1254
|
-
spinner.attachConsole = true;
|
|
1255
|
-
console.log('Building application...');
|
|
1256
|
-
const viteBuild = yield build(viteConfig);
|
|
1257
|
-
spinner.attachConsole = false;
|
|
1258
|
-
return {
|
|
1259
|
-
viteConfig,
|
|
1260
|
-
viteBuild,
|
|
1261
|
-
pkg,
|
|
1262
|
-
};
|
|
1263
|
-
});
|
|
1264
|
-
|
|
1265
|
-
const createAppManifest = (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1266
|
-
Spinner.Global({ prefixText: chalk.dim('app manifest') });
|
|
1267
|
-
const manifest = yield createManifest(options);
|
|
1268
|
-
if (options === null || options === void 0 ? void 0 : options.outputFile) {
|
|
1269
|
-
yield writeManifestToDisk(manifest, options.outputFile);
|
|
1270
|
-
}
|
|
1271
|
-
else {
|
|
1272
|
-
console.log(JSON.stringify(manifest, undefined, 2));
|
|
1273
|
-
}
|
|
1274
|
-
return manifest;
|
|
1275
|
-
});
|
|
1276
|
-
const createBuildManifest = (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1277
|
-
Spinner.Global({ prefixText: chalk.dim('build manifest') });
|
|
1278
|
-
const { build } = yield createManifest(options);
|
|
1279
|
-
if (options === null || options === void 0 ? void 0 : options.outputFile) {
|
|
1280
|
-
yield writeManifestToDisk(build, options.outputFile);
|
|
1281
|
-
}
|
|
1282
|
-
else {
|
|
1283
|
-
console.log(JSON.stringify(build, undefined, 2));
|
|
1284
|
-
}
|
|
1285
|
-
return build;
|
|
1286
|
-
});
|
|
1287
|
-
const writeManifestToDisk = (content, outputFile) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1288
|
-
const spinner = Spinner.Clone();
|
|
1289
|
-
spinner.start(`Exporting manifest to ${formatPath(outputFile)}`);
|
|
1290
|
-
try {
|
|
1291
|
-
const dir = dirname(outputFile).trim();
|
|
1292
|
-
if (!nodeFs.existsSync(dirname(outputFile))) {
|
|
1293
|
-
nodeFs.mkdirSync(dir, { recursive: true });
|
|
1294
|
-
}
|
|
1295
|
-
yield writeFile(outputFile, JSON.stringify(content));
|
|
1296
|
-
spinner.succeed();
|
|
1297
|
-
}
|
|
1298
|
-
catch (err) {
|
|
1299
|
-
spinner.fail();
|
|
1300
|
-
throw err;
|
|
1301
|
-
}
|
|
1302
|
-
});
|
|
1303
|
-
const createManifest = (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1304
|
-
var _a, _b;
|
|
1305
|
-
const pkg = yield loadPackage();
|
|
1306
|
-
const env = {
|
|
1307
|
-
command: (_a = options === null || options === void 0 ? void 0 : options.command) !== null && _a !== void 0 ? _a : 'build',
|
|
1308
|
-
mode: (_b = process.env.NODE_ENV) !== null && _b !== void 0 ? _b : 'development',
|
|
1309
|
-
root: pkg.root,
|
|
1310
|
-
};
|
|
1311
|
-
const { manifest } = yield loadAppManifest(env, pkg, {
|
|
1312
|
-
file: options === null || options === void 0 ? void 0 : options.configFile,
|
|
1313
|
-
});
|
|
1314
|
-
return manifest;
|
|
1315
|
-
});
|
|
1316
|
-
|
|
1317
|
-
const bundleApplication = (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1318
|
-
const { outDir, archive } = options;
|
|
1319
|
-
const spinner = Spinner.Global({ prefixText: chalk.dim('pack') });
|
|
1320
|
-
spinner.start('build application');
|
|
1321
|
-
const { pkg } = yield buildApplication({ outDir });
|
|
1322
|
-
spinner.succeed();
|
|
1323
|
-
spinner.start('generate manifest');
|
|
1324
|
-
const buildManifest = yield createBuildManifest({ outputFile: `${outDir}/app-manifest.json` });
|
|
1325
|
-
spinner.succeed('generated manifest:', '\n' + JSON.stringify(buildManifest, undefined, 2));
|
|
1326
|
-
const bundle = new AdmZip();
|
|
1327
|
-
bundle.addLocalFile(pkg.path);
|
|
1328
|
-
spinner.info(`added ./package.json`);
|
|
1329
|
-
bundle.addLocalFolder(outDir);
|
|
1330
|
-
spinner.info(`added ./${outDir}`);
|
|
1331
|
-
const appDir = dirname(pkg.path);
|
|
1332
|
-
const licenseFile = resolve(appDir, 'LICENSE.md');
|
|
1333
|
-
if (fileExistsSync(licenseFile)) {
|
|
1334
|
-
bundle.addLocalFile(licenseFile);
|
|
1335
|
-
spinner.info(`added ${licenseFile}`);
|
|
1336
|
-
}
|
|
1337
|
-
else {
|
|
1338
|
-
spinner.warn(`missing ${licenseFile}`);
|
|
1339
|
-
}
|
|
1340
|
-
const readmeFile = resolve(appDir, 'README.md');
|
|
1341
|
-
if (fileExistsSync(readmeFile)) {
|
|
1342
|
-
bundle.addLocalFile(readmeFile);
|
|
1343
|
-
spinner.info(`added ${readmeFile}`);
|
|
1344
|
-
}
|
|
1345
|
-
else {
|
|
1346
|
-
spinner.warn(`missing ${readmeFile}`);
|
|
1347
|
-
}
|
|
1348
|
-
spinner.start('compressing content');
|
|
1349
|
-
if (!fileExistsSync(dirname(archive))) {
|
|
1350
|
-
yield mkdir(dirname(archive), { recursive: true });
|
|
1351
|
-
}
|
|
1352
|
-
bundle.writeZip(archive);
|
|
1353
|
-
spinner.succeed('Bundle complete', formatPath(archive, { relative: true }), formatByteSize(archive));
|
|
1354
|
-
});
|
|
1355
|
-
|
|
1356
|
-
/**
|
|
1357
|
-
* Retreive full endpoint URI to env in service-discovery
|
|
1358
|
-
* @param endpoint <string> The endpoint to call in+ uri
|
|
1359
|
-
* @param fusionEnv <FusionEnv> The Fusion env to get uri for
|
|
1360
|
-
* @param service <string> Custom service uri to use insted of Fusion
|
|
1361
|
-
* @param version <string> The version of the api to use
|
|
1362
|
-
* @returns <string> The uri with endpoint
|
|
1363
|
-
*/
|
|
1364
|
-
const getEndpointUrl = (endpoint_1, fusionEnv_1, service_1, ...args_1) => __awaiter(void 0, [endpoint_1, fusionEnv_1, service_1, ...args_1], void 0, function* (endpoint, fusionEnv, service, version = '1.0') {
|
|
1365
|
-
const { CUSTOM_APPAPI, FUSION_CLI_ENV, FUSION_TOKEN } = process.env;
|
|
1366
|
-
/* use consumer provided api url */
|
|
1367
|
-
if (service || CUSTOM_APPAPI) {
|
|
1368
|
-
return service !== null && service !== void 0 ? service : CUSTOM_APPAPI;
|
|
1369
|
-
}
|
|
1370
|
-
/* Env has changed get new api url */
|
|
1371
|
-
if (FUSION_CLI_ENV !== fusionEnv || !process.env.FUSION_CLI_APPAPI) {
|
|
1372
|
-
process.env.FUSION_CLI_ENV = fusionEnv;
|
|
1373
|
-
const requestService = yield fetch$1(`https://discovery.fusion.equinor.com/service-registry/environments/${fusionEnv}/services/apps`, {
|
|
1374
|
-
headers: {
|
|
1375
|
-
Authorization: `Bearer ${FUSION_TOKEN}`,
|
|
1376
|
-
},
|
|
1377
|
-
});
|
|
1378
|
-
if (requestService.status === 401) {
|
|
1379
|
-
throw new Error(`The provided FUSION_TOKEN is not valid. Refresh your token and try again.`);
|
|
1380
|
-
}
|
|
1381
|
-
if (!requestService.ok) {
|
|
1382
|
-
const response = yield requestService.json();
|
|
1383
|
-
console.log(response);
|
|
1384
|
-
throw new Error(`Failed getEndpointUrl from service-discovery. HTTP status: ${requestService.status} - ${requestService.statusText}`);
|
|
1385
|
-
}
|
|
1386
|
-
const responseService = (yield requestService.json());
|
|
1387
|
-
process.env.FUSION_CLI_APPAPI = responseService.uri;
|
|
1388
|
-
}
|
|
1389
|
-
const uri = new URL(`${process.env.FUSION_CLI_APPAPI}/${endpoint}`);
|
|
1390
|
-
uri.searchParams.set('api-version', version);
|
|
1391
|
-
/* return fresh/cached endpoint url */
|
|
1392
|
-
return uri.href;
|
|
1393
|
-
});
|
|
1394
|
-
|
|
1395
|
-
/**
|
|
1396
|
-
* Make sure the user has a valid azure token.
|
|
1397
|
-
*/
|
|
1398
|
-
const requireToken = () => {
|
|
1399
|
-
var _a;
|
|
1400
|
-
if (!((_a = process === null || process === void 0 ? void 0 : process.env) === null || _a === void 0 ? void 0 : _a.FUSION_TOKEN)) {
|
|
1401
|
-
throw new Error('Missing required environment variable FUSION_TOKEN. Please set it before running this command.');
|
|
1402
|
-
}
|
|
1403
|
-
};
|
|
1404
|
-
|
|
1405
|
-
/**
|
|
1406
|
-
* Make sure the app is registerred in the app-service
|
|
1407
|
-
* @param endpoint <string> The endpoint to make a call to
|
|
1408
|
-
*/
|
|
1409
|
-
const isAppRegistered = (endpoint) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1410
|
-
const requestApp = yield fetch$1(endpoint, {
|
|
1411
|
-
method: 'HEAD',
|
|
1412
|
-
headers: {
|
|
1413
|
-
Authorization: `Bearer ${process.env.FUSION_TOKEN}`,
|
|
1414
|
-
},
|
|
1415
|
-
});
|
|
1416
|
-
/** Assume that ok response asserts that app exists */
|
|
1417
|
-
if (requestApp.ok) {
|
|
1418
|
-
return true;
|
|
1419
|
-
}
|
|
1420
|
-
if (requestApp.status === 404) {
|
|
1421
|
-
return false;
|
|
1422
|
-
}
|
|
1423
|
-
if (requestApp.status === 410) {
|
|
1424
|
-
throw Error('App is deleted.');
|
|
1425
|
-
}
|
|
1426
|
-
const data = yield requestApp.json();
|
|
1427
|
-
throw Error('Custom Fusion error, see cause.', { cause: data });
|
|
1428
|
-
});
|
|
1429
|
-
|
|
1430
|
-
/**
|
|
1431
|
-
* Publishes app config to the apps-service endpoint
|
|
1432
|
-
* @param endpoint string The endpoint to upload to
|
|
1433
|
-
* @param appKey The application key
|
|
1434
|
-
* @param config Object with app config
|
|
1435
|
-
* @returns HTTP response as json
|
|
1436
|
-
*/
|
|
1437
|
-
const publishAppConfig = (endpoint, appKey, config) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1438
|
-
const requestConfig = yield fetch(endpoint, {
|
|
1439
|
-
method: 'PUT',
|
|
1440
|
-
body: JSON.stringify(config),
|
|
1441
|
-
headers: {
|
|
1442
|
-
Authorization: `Bearer ${process.env.FUSION_TOKEN}`,
|
|
1443
|
-
'Content-Type': 'application/json',
|
|
1444
|
-
},
|
|
1445
|
-
});
|
|
1446
|
-
if (requestConfig.status === 410) {
|
|
1447
|
-
throw new Error(`App ${appKey} is deleted from apps-service. HTTP status ${requestConfig.status}, ${requestConfig.statusText}`);
|
|
1448
|
-
}
|
|
1449
|
-
else if (!requestConfig.ok || requestConfig.status >= 400) {
|
|
1450
|
-
const response = yield requestConfig.json();
|
|
1451
|
-
console.log(response);
|
|
1452
|
-
throw new Error(`Failed to upload config. HTTP status ${requestConfig.status}, ${requestConfig.statusText}`);
|
|
1453
|
-
}
|
|
1454
|
-
return requestConfig.json();
|
|
1455
|
-
});
|
|
1456
|
-
|
|
1457
|
-
/**
|
|
1458
|
-
* Send request to apps-service to tag a bundle.
|
|
1459
|
-
* @param endpoint string The endpoint to send request to.
|
|
1460
|
-
* @param version string The version to tag the bundle with.
|
|
1461
|
-
* @returns Response object as json.
|
|
1462
|
-
*/
|
|
1463
|
-
const tagAppBundle = (endpoint, version) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1464
|
-
const requestTag = yield fetch(endpoint, {
|
|
1465
|
-
method: 'PUT',
|
|
1466
|
-
body: JSON.stringify({ version }),
|
|
1467
|
-
headers: {
|
|
1468
|
-
Authorization: `Bearer ${process.env.FUSION_TOKEN}`,
|
|
1469
|
-
'Content-Type': 'application/json',
|
|
1470
|
-
},
|
|
1471
|
-
});
|
|
1472
|
-
if (requestTag.status === 404) {
|
|
1473
|
-
throw new Error(`Failed to tag bundle, make sure version ${version} exist. HTTP status ${requestTag.status} - ${requestTag.statusText}`);
|
|
1474
|
-
}
|
|
1475
|
-
if (requestTag.status !== 200) {
|
|
1476
|
-
const response = yield requestTag.json();
|
|
1477
|
-
console.log(response);
|
|
1478
|
-
throw new Error(`Failed to tag bundle. HTTP status ${requestTag.status}, ${requestTag.statusText}`);
|
|
1479
|
-
}
|
|
1480
|
-
return requestTag.json();
|
|
1481
|
-
});
|
|
1482
|
-
|
|
1483
|
-
/**
|
|
1484
|
-
* Function that uploads a zip bundle to the endpoint.
|
|
1485
|
-
* @param endpoint string The endpoint to upload to
|
|
1486
|
-
* @param bundle string The filename to upload
|
|
1487
|
-
* @returns Object
|
|
1488
|
-
*/
|
|
1489
|
-
const uploadAppBundle = (endpoint, bundle) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1490
|
-
const state = {
|
|
1491
|
-
buffer: null,
|
|
1492
|
-
};
|
|
1493
|
-
try {
|
|
1494
|
-
state.buffer = readFileSync(bundle);
|
|
1495
|
-
}
|
|
1496
|
-
catch (_a) {
|
|
1497
|
-
throw new Error(`😞 Could not read bundle ${bundle}, does it exist?`);
|
|
1498
|
-
}
|
|
1499
|
-
const requestBundle = yield fetch(endpoint, {
|
|
1500
|
-
method: 'POST',
|
|
1501
|
-
body: state.buffer,
|
|
1502
|
-
headers: {
|
|
1503
|
-
Authorization: `Bearer ${process.env.FUSION_TOKEN}`,
|
|
1504
|
-
'Content-Type': 'application/zip',
|
|
1505
|
-
},
|
|
1506
|
-
});
|
|
1507
|
-
if (requestBundle.status === 401 || requestBundle.status === 403) {
|
|
1508
|
-
throw new Error(`This is not allowed for this role on this app. HTTP message: ${requestBundle.statusText}`);
|
|
1509
|
-
}
|
|
1510
|
-
if (requestBundle.status === 404) {
|
|
1511
|
-
throw new Error(`This app do not exist. HTTP message: ${requestBundle.statusText}`);
|
|
1512
|
-
}
|
|
1513
|
-
if (requestBundle.status === 409) {
|
|
1514
|
-
throw new Error(`This version is already published. HTTP message: ${requestBundle.statusText}`);
|
|
1515
|
-
}
|
|
1516
|
-
if (requestBundle.status === 410) {
|
|
1517
|
-
throw new Error(`This app is deleted. HTTP message: ${requestBundle.statusText}`);
|
|
1518
|
-
}
|
|
1519
|
-
if (!requestBundle.ok) {
|
|
1520
|
-
const json = yield requestBundle.json();
|
|
1521
|
-
console.error(json);
|
|
1522
|
-
throw new Error(`Failed to publish bundle. HTTP status ${requestBundle.status}, ${requestBundle.statusText}`);
|
|
1523
|
-
}
|
|
1524
|
-
return requestBundle.json();
|
|
1525
|
-
});
|
|
1526
|
-
|
|
1527
|
-
const publishApplication = (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1528
|
-
const { tag, env, service } = options;
|
|
1529
|
-
const spinner = Spinner.Global({ prefixText: chalk.dim('Publish') });
|
|
1530
|
-
try {
|
|
1531
|
-
spinner.info('Validating FUSION_TOKEN');
|
|
1532
|
-
// make sure token exist
|
|
1533
|
-
requireToken();
|
|
1534
|
-
// call service discovery with token, will throw error if failed
|
|
1535
|
-
yield getEndpointUrl('apps', env, '');
|
|
1536
|
-
spinner.succeed('Found valid FUSION_TOKEN');
|
|
1537
|
-
}
|
|
1538
|
-
catch (e) {
|
|
1539
|
-
const err = e;
|
|
1540
|
-
spinner.fail(chalk.bgRed(err.message));
|
|
1541
|
-
exit(1);
|
|
1542
|
-
}
|
|
1543
|
-
const pkg = yield resolveAppPackage();
|
|
1544
|
-
const appKey = resolveAppKey(pkg.packageJson);
|
|
1545
|
-
try {
|
|
1546
|
-
spinner.info('Verifying that App is registered');
|
|
1547
|
-
const state = { endpoint: '' };
|
|
1548
|
-
try {
|
|
1549
|
-
state.endpoint = yield getEndpointUrl(`apps/${appKey}`, env, service);
|
|
1550
|
-
}
|
|
1551
|
-
catch (e) {
|
|
1552
|
-
const err = e;
|
|
1553
|
-
throw new Error(`Could not get endpoint from service discovery while verifying app is registered. service-discovery status: ${err.message}`);
|
|
1554
|
-
}
|
|
1555
|
-
const exist = yield isAppRegistered(state.endpoint);
|
|
1556
|
-
assert(exist, `${appKey} is not registered`);
|
|
1557
|
-
spinner.succeed(`${appKey} is registered`);
|
|
1558
|
-
}
|
|
1559
|
-
catch (e) {
|
|
1560
|
-
const err = e;
|
|
1561
|
-
spinner.fail('🙅♂️', chalk.bgRed(err.message));
|
|
1562
|
-
throw err;
|
|
1563
|
-
}
|
|
1564
|
-
const bundle = 'app-bundle.zip';
|
|
1565
|
-
/* Zip app bundle */
|
|
1566
|
-
spinner.info('Creating zip bundle');
|
|
1567
|
-
yield bundleApplication({
|
|
1568
|
-
archive: bundle,
|
|
1569
|
-
outDir: 'dist',
|
|
1570
|
-
});
|
|
1571
|
-
const state = {
|
|
1572
|
-
uploadedBundle: { version: '' },
|
|
1573
|
-
endpoint: '',
|
|
1574
|
-
};
|
|
1575
|
-
spinner.info(`Publishing app: "${appKey}" with tag: "${tag}"`);
|
|
1576
|
-
/* Upload app bundle */
|
|
1577
|
-
try {
|
|
1578
|
-
spinner.info(`Uploading bundle ${chalk.yellowBright(bundle)} to appKey ${chalk.yellowBright(appKey)}`);
|
|
1579
|
-
try {
|
|
1580
|
-
state.endpoint = yield getEndpointUrl(`bundles/apps/${appKey}`, env, service);
|
|
1581
|
-
}
|
|
1582
|
-
catch (e) {
|
|
1583
|
-
const err = e;
|
|
1584
|
-
throw new Error(`Could not get endpoint from service discovery while uploading app bundle. service-discovery status: ${err.message}`);
|
|
1585
|
-
}
|
|
1586
|
-
spinner.info(`Posting bundle to => ${state.endpoint}`);
|
|
1587
|
-
state.uploadedBundle = yield uploadAppBundle(state.endpoint, bundle);
|
|
1588
|
-
spinner.succeed('✅', `Uploaded bundle: "${chalk.greenBright(bundle)}" with version: ${chalk.greenBright(state.uploadedBundle.version)}"`);
|
|
1589
|
-
}
|
|
1590
|
-
catch (e) {
|
|
1591
|
-
const err = e;
|
|
1592
|
-
spinner.fail('🙅♂️', chalk.bgRed(err.message));
|
|
1593
|
-
exit(1);
|
|
1594
|
-
}
|
|
1595
|
-
try {
|
|
1596
|
-
spinner.info(`Tagging ${state.uploadedBundle.version} with ${tag}`);
|
|
1597
|
-
try {
|
|
1598
|
-
state.endpoint = yield getEndpointUrl(`apps/${appKey}/tags/${tag}`, env, service);
|
|
1599
|
-
}
|
|
1600
|
-
catch (e) {
|
|
1601
|
-
const err = e;
|
|
1602
|
-
throw new Error(`Could not get endpoint from service discovery while tagging app. service-discovery status: ${err.message}`);
|
|
1603
|
-
}
|
|
1604
|
-
const tagged = yield tagAppBundle(state.endpoint, state.uploadedBundle.version);
|
|
1605
|
-
spinner.succeed('✅', `Tagged version ${chalk.greenBright(tagged.version)} with ${chalk.greenBright(tagged.tagName)}`);
|
|
1606
|
-
}
|
|
1607
|
-
catch (e) {
|
|
1608
|
-
const err = e;
|
|
1609
|
-
spinner.fail('🙅♂️', chalk.bgRed(err.message));
|
|
1610
|
-
exit(1);
|
|
1611
|
-
}
|
|
1612
|
-
spinner.succeed('⭐️', `Published app: "${chalk.greenBright(appKey)}" version: "${chalk.greenBright(state.uploadedBundle.version)}" with tagg: "${chalk.greenBright(tag)}"`);
|
|
1613
|
-
});
|
|
1614
|
-
|
|
1615
|
-
const uploadApplication = (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1616
|
-
const { bundle, env, service } = options;
|
|
1617
|
-
const spinner = Spinner.Global({ prefixText: chalk.dim('Upload') });
|
|
1618
|
-
try {
|
|
1619
|
-
spinner.info('Validating FUSION_TOKEN');
|
|
1620
|
-
// make sure token exist
|
|
1621
|
-
requireToken();
|
|
1622
|
-
// call service discovery with token, will throw error if failed
|
|
1623
|
-
yield getEndpointUrl('apps', env, '');
|
|
1624
|
-
spinner.succeed('Found valid FUSION_TOKEN');
|
|
1625
|
-
}
|
|
1626
|
-
catch (e) {
|
|
1627
|
-
const err = e;
|
|
1628
|
-
spinner.fail(chalk.bgRed(err.message));
|
|
1629
|
-
exit(1);
|
|
1630
|
-
}
|
|
1631
|
-
/* get package.json */
|
|
1632
|
-
const pkg = yield resolveAppPackage();
|
|
1633
|
-
const appKey = resolveAppKey(pkg.packageJson);
|
|
1634
|
-
try {
|
|
1635
|
-
spinner.info(`Verifying that ${appKey} is registered`);
|
|
1636
|
-
const state = { endpoint: '' };
|
|
1637
|
-
try {
|
|
1638
|
-
state.endpoint = yield getEndpointUrl(`apps/${appKey}`, env, service);
|
|
1639
|
-
}
|
|
1640
|
-
catch (e) {
|
|
1641
|
-
const err = e;
|
|
1642
|
-
throw new Error(`Could not get endpoint from service discovery while verifying app. service-discovery status: ${err.message}`);
|
|
1643
|
-
}
|
|
1644
|
-
spinner.info('Using endpoint:', state.endpoint);
|
|
1645
|
-
const exist = yield isAppRegistered(state.endpoint);
|
|
1646
|
-
assert(exist, `${appKey} is not registered`);
|
|
1647
|
-
spinner.succeed(`${appKey} is registered`);
|
|
1648
|
-
}
|
|
1649
|
-
catch (e) {
|
|
1650
|
-
const err = e;
|
|
1651
|
-
spinner.fail('🙅♂️', chalk.bgRed(err.message));
|
|
1652
|
-
throw err;
|
|
1653
|
-
}
|
|
1654
|
-
/* Upload app bundle */
|
|
1655
|
-
try {
|
|
1656
|
-
spinner.info(`Uploading bundle ${chalk.yellowBright(bundle)} to appKey ${chalk.yellowBright(appKey)}`);
|
|
1657
|
-
const endpoint = yield getEndpointUrl(`bundles/apps/${appKey}`, env, service);
|
|
1658
|
-
if (!endpoint) {
|
|
1659
|
-
throw new Error('Could not get endpoint from service discovery');
|
|
1660
|
-
}
|
|
1661
|
-
spinner.info(`Posting bundle to => ${endpoint}`);
|
|
1662
|
-
const uploadedBundle = yield uploadAppBundle(endpoint, bundle);
|
|
1663
|
-
spinner.succeed('✅', `Uploaded app: "${chalk.greenBright(appKey)}"`, `Version: "${chalk.greenBright(uploadedBundle.version)}"`);
|
|
1664
|
-
}
|
|
1665
|
-
catch (e) {
|
|
1666
|
-
const err = e;
|
|
1667
|
-
spinner.fail('🙅♂️', chalk.bgRed(err.message));
|
|
1668
|
-
exit(1);
|
|
1669
|
-
}
|
|
1670
|
-
});
|
|
1671
|
-
|
|
1672
|
-
var Tags;
|
|
1673
|
-
(function (Tags) {
|
|
1674
|
-
Tags["preview"] = "preview";
|
|
1675
|
-
Tags["latest"] = "latest";
|
|
1676
|
-
})(Tags || (Tags = {}));
|
|
1677
|
-
const tagApplication = (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1678
|
-
const { tag, version, env, service } = options;
|
|
1679
|
-
const spinner = Spinner.Global({ prefixText: chalk.dim('Tag') });
|
|
1680
|
-
if (!Object.values(Tags).includes(tag)) {
|
|
1681
|
-
spinner.fail('😞', `Tag must match (${Tags.latest} | ${Tags.preview})`);
|
|
1682
|
-
exit(1);
|
|
1683
|
-
}
|
|
1684
|
-
/** make sure user has a valid token */
|
|
1685
|
-
try {
|
|
1686
|
-
spinner.info('Validating FUSION_TOKEN');
|
|
1687
|
-
// make sure token exist
|
|
1688
|
-
requireToken();
|
|
1689
|
-
// call service discovery with token, will throw error if failed
|
|
1690
|
-
yield getEndpointUrl('apps', env, '');
|
|
1691
|
-
spinner.succeed('Found valid FUSION_TOKEN');
|
|
1692
|
-
}
|
|
1693
|
-
catch (e) {
|
|
1694
|
-
const err = e;
|
|
1695
|
-
spinner.fail(chalk.bgRed(err.message));
|
|
1696
|
-
exit(1);
|
|
1697
|
-
}
|
|
1698
|
-
const pkg = yield resolveAppPackage();
|
|
1699
|
-
const appKey = resolveAppKey(pkg.packageJson);
|
|
1700
|
-
try {
|
|
1701
|
-
spinner.info('Verifying that App is registered');
|
|
1702
|
-
const state = { endpoint: '' };
|
|
1703
|
-
try {
|
|
1704
|
-
state.endpoint = yield getEndpointUrl(`apps/${appKey}`, env, service);
|
|
1705
|
-
}
|
|
1706
|
-
catch (e) {
|
|
1707
|
-
const err = e;
|
|
1708
|
-
throw new Error(`Could not get endpoint from service discovery while verifying app is registered. service-discovery status: ${err.message}`);
|
|
1709
|
-
}
|
|
1710
|
-
const exist = yield isAppRegistered(state.endpoint);
|
|
1711
|
-
assert(exist, `${appKey} is not registered`);
|
|
1712
|
-
spinner.succeed(`${appKey} is registered`);
|
|
1713
|
-
}
|
|
1714
|
-
catch (e) {
|
|
1715
|
-
const err = e;
|
|
1716
|
-
spinner.fail('🙅♂️', chalk.bgRed(err.message));
|
|
1717
|
-
throw err;
|
|
1718
|
-
}
|
|
1719
|
-
try {
|
|
1720
|
-
spinner.info(`Tagging "${appKey}@${version}" with: "${tag}"`);
|
|
1721
|
-
const state = { endpoint: '' };
|
|
1722
|
-
try {
|
|
1723
|
-
state.endpoint = yield getEndpointUrl(`apps/${appKey}/tags/${tag}`, env, service);
|
|
1724
|
-
}
|
|
1725
|
-
catch (e) {
|
|
1726
|
-
const err = e;
|
|
1727
|
-
throw new Error(`Could not get endpoint from service discovery while tagging app. service-discovery status: ${err.message}`);
|
|
1728
|
-
}
|
|
1729
|
-
const tagged = yield tagAppBundle(state.endpoint, version);
|
|
1730
|
-
spinner.succeed('✅', `Tagged app: "${chalk.greenBright(appKey)}"`, `version: "${chalk.greenBright(tagged.version)}"`, `with tag: "${chalk.greenBright(tagged.tagName)}"`);
|
|
1731
|
-
}
|
|
1732
|
-
catch (e) {
|
|
1733
|
-
const err = e;
|
|
1734
|
-
spinner.fail('🙅♂️', chalk.bgRed(err.message));
|
|
1735
|
-
exit(1);
|
|
1736
|
-
}
|
|
1737
|
-
});
|
|
1738
|
-
|
|
1739
|
-
const createExportConfig = (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1740
|
-
var _a;
|
|
1741
|
-
const { command = 'build', outputFile, configFile } = options;
|
|
1742
|
-
const spinner = Spinner.Global({ prefixText: chalk.dim('config') });
|
|
1743
|
-
const pkg = yield loadPackage();
|
|
1744
|
-
const appEnv = {
|
|
1745
|
-
command,
|
|
1746
|
-
mode: (_a = process.env.NODE_ENV) !== null && _a !== void 0 ? _a : 'development',
|
|
1747
|
-
root: pkg.root,
|
|
1748
|
-
};
|
|
1749
|
-
const { config } = yield loadAppConfig(appEnv, pkg, {
|
|
1750
|
-
file: configFile,
|
|
1751
|
-
});
|
|
1752
|
-
if (outputFile) {
|
|
1753
|
-
spinner.start(`outputting config to ${formatPath(outputFile)}`);
|
|
1754
|
-
try {
|
|
1755
|
-
const dir = dirname(outputFile).trim();
|
|
1756
|
-
if (!nodeFs.existsSync(dirname(outputFile))) {
|
|
1757
|
-
nodeFs.mkdirSync(dir, { recursive: true });
|
|
1758
|
-
}
|
|
1759
|
-
writeFile(outputFile, JSON.stringify(config));
|
|
1760
|
-
spinner.succeed();
|
|
1761
|
-
}
|
|
1762
|
-
catch (err) {
|
|
1763
|
-
spinner.fail();
|
|
1764
|
-
throw err;
|
|
1765
|
-
}
|
|
1766
|
-
}
|
|
1767
|
-
else {
|
|
1768
|
-
console.log(config);
|
|
1769
|
-
}
|
|
1770
|
-
return config;
|
|
1771
|
-
});
|
|
1772
|
-
|
|
1773
|
-
const uploadExportConfig = (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1774
|
-
const { configFile, version: pubVersion, env, service } = options;
|
|
1775
|
-
const spinner = Spinner.Global({ prefixText: chalk.dim('config') });
|
|
1776
|
-
const pkg = yield loadPackage();
|
|
1777
|
-
const appKey = resolveAppKey(pkg.packageJson);
|
|
1778
|
-
if (!existsSync(`${configFile}`)) {
|
|
1779
|
-
throw new Error(`Config file ${configFile} does not exist`);
|
|
1780
|
-
}
|
|
1781
|
-
const config = JSON.parse(readFileSync(`${configFile}`, 'utf8'));
|
|
1782
|
-
spinner.info('Preparing to publishing config');
|
|
1783
|
-
/* Make sure version is valid */
|
|
1784
|
-
const version = pubVersion === 'current' ? pkg.packageJson.version : pubVersion;
|
|
1785
|
-
if (!version || (!semverValid(version) && !['latest', 'preview'].includes(version))) {
|
|
1786
|
-
spinner.fail('🙅♂️', 'Can not publish config to invalid version', chalk.redBright(version), '');
|
|
1787
|
-
exit(1);
|
|
1788
|
-
}
|
|
1789
|
-
/** make sure user has a valid token */
|
|
1790
|
-
try {
|
|
1791
|
-
spinner.info('Validating FUSION_TOKEN');
|
|
1792
|
-
// make sure token exist
|
|
1793
|
-
requireToken();
|
|
1794
|
-
// call service discovery with token, will throw error if failed
|
|
1795
|
-
yield getEndpointUrl('apps', env, '');
|
|
1796
|
-
spinner.succeed('Found valid FUSION_TOKEN');
|
|
1797
|
-
}
|
|
1798
|
-
catch (e) {
|
|
1799
|
-
const err = e;
|
|
1800
|
-
spinner.fail(chalk.bgRed(err.message));
|
|
1801
|
-
exit(1);
|
|
1802
|
-
}
|
|
1803
|
-
try {
|
|
1804
|
-
spinner.info('Verifying that App is registered');
|
|
1805
|
-
const state = { endpoint: '' };
|
|
1806
|
-
try {
|
|
1807
|
-
state.endpoint = yield getEndpointUrl(`apps/${appKey}`, env, service);
|
|
1808
|
-
}
|
|
1809
|
-
catch (e) {
|
|
1810
|
-
const err = e;
|
|
1811
|
-
throw new Error(`Could not get endpoint from service discovery while verifying app. service-discovery status: ${err.message}`);
|
|
1812
|
-
}
|
|
1813
|
-
const exist = yield isAppRegistered(state.endpoint);
|
|
1814
|
-
assert(exist, `${appKey} is not registered`);
|
|
1815
|
-
spinner.succeed(`${appKey} is registered`);
|
|
1816
|
-
}
|
|
1817
|
-
catch (e) {
|
|
1818
|
-
const err = e;
|
|
1819
|
-
spinner.fail('🙅♂️', chalk.bgRed(err.message));
|
|
1820
|
-
throw err;
|
|
1821
|
-
}
|
|
1822
|
-
try {
|
|
1823
|
-
spinner.info(`Publishing config to "${appKey}@${version}"`);
|
|
1824
|
-
const state = { endpoint: '' };
|
|
1825
|
-
try {
|
|
1826
|
-
state.endpoint = yield getEndpointUrl(`apps/${appKey}/builds/${version}/config`, env, service);
|
|
1827
|
-
}
|
|
1828
|
-
catch (e) {
|
|
1829
|
-
const err = e;
|
|
1830
|
-
throw new Error(`Could not get endpoint from service discovery while publishig config. service-discovery status: ${err.message}`);
|
|
1831
|
-
}
|
|
1832
|
-
yield publishAppConfig(state.endpoint, appKey, config);
|
|
1833
|
-
spinner.succeed('✅', 'Published config to version', chalk.yellowBright(version));
|
|
1834
|
-
}
|
|
1835
|
-
catch (e) {
|
|
1836
|
-
const err = e;
|
|
1837
|
-
spinner.fail('🙅♂️', chalk.bgRed(err.message));
|
|
1838
|
-
exit(1);
|
|
1839
|
-
}
|
|
1840
|
-
});
|
|
1841
|
-
|
|
1842
|
-
var app = (program) => {
|
|
1843
|
-
const app = program
|
|
1844
|
-
.command('app')
|
|
1845
|
-
.description('Tooling for developing applications build on Fusion Framework');
|
|
1846
|
-
app.command('dev')
|
|
1847
|
-
.description('Start development server for application')
|
|
1848
|
-
.option('-p, --port <number>', 'dev-server port')
|
|
1849
|
-
.option('-P, --portal <string>', 'fusion portal host')
|
|
1850
|
-
.option('-c, --config <file>', `use specified application config, by default search for ${formatPath('app.config.{ts,js,json}')}`)
|
|
1851
|
-
.option(' --manifest <file>', `use specified manifest, by default search for ${formatPath('app.manifest.config.{ts,js,json}')}`)
|
|
1852
|
-
.option(' --vite <file>', `use specified Vite config file, by default search for ${formatPath('app.vite.config.{ts,js,json}')}`)
|
|
1853
|
-
.option('-F, --framework <string>', `application framework to build the application on, supported: [${chalk.yellowBright('react')}]`, 'react')
|
|
1854
|
-
.option('-d, --dev-portal <string>', 'Location of dev-portal you want to use')
|
|
1855
|
-
.action((opt) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1856
|
-
var _a;
|
|
1857
|
-
const devPortalPath = opt.devPortal
|
|
1858
|
-
? resolve(join(process.cwd(), opt.devPortal))
|
|
1859
|
-
: fileURLToPath(new URL('public', import.meta.url));
|
|
1860
|
-
yield createDevServer({
|
|
1861
|
-
portal: (_a = process.env.FUSION_PORTAL_HOST) !== null && _a !== void 0 ? _a : 'https://fusion-s-portal-ci.azurewebsites.net',
|
|
1862
|
-
configSourceFiles: {
|
|
1863
|
-
app: opt.config,
|
|
1864
|
-
manifest: opt.manifest,
|
|
1865
|
-
vite: opt.vite,
|
|
1866
|
-
},
|
|
1867
|
-
library: opt.framework,
|
|
1868
|
-
port: opt.port,
|
|
1869
|
-
devPortalPath: devPortalPath,
|
|
1870
|
-
});
|
|
1871
|
-
}));
|
|
1872
|
-
app.command('manifest')
|
|
1873
|
-
.description('Generate manifest')
|
|
1874
|
-
.option('-o, --output <string>', 'output file')
|
|
1875
|
-
.option('-c, --config <string>', 'manifest config file')
|
|
1876
|
-
.action((opt) => {
|
|
1877
|
-
createAppManifest({
|
|
1878
|
-
outputFile: opt.output,
|
|
1879
|
-
configFile: opt.config,
|
|
1880
|
-
});
|
|
1881
|
-
});
|
|
1882
|
-
app.command('build')
|
|
1883
|
-
.description('Builds application')
|
|
1884
|
-
.option('-o, --outDir, <string>', 'output directory of package', 'dist')
|
|
1885
|
-
.option('-c, --config <string>', 'Use specified config file, see https://vitejs.dev/guide/cli.html#build')
|
|
1886
|
-
.option(' --vite <string>', `use specified Vite config file, by default search for ${formatPath('app.config.vite.{ts,js,json}')}`)
|
|
1887
|
-
.option('-F, --framework <string>', `application framework to build the application on, supported: [${chalk.yellowBright('react')}]`, 'react')
|
|
1888
|
-
.action((opt) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1889
|
-
buildApplication({
|
|
1890
|
-
configSourceFiles: {
|
|
1891
|
-
vite: opt.vite,
|
|
1892
|
-
},
|
|
1893
|
-
outDir: opt.outDir,
|
|
1894
|
-
});
|
|
1895
|
-
}));
|
|
1896
|
-
app.command('build-config')
|
|
1897
|
-
.description('Generate config')
|
|
1898
|
-
.option('-o, --output <string>', 'output file')
|
|
1899
|
-
.option('-c, --config <string>', 'application config file')
|
|
1900
|
-
.option('-p, --publish', 'Publish config to app api')
|
|
1901
|
-
.option('-v, --version <string>', `Publish app config to version [${chalk.yellowBright('(semver | current | latest | preview)')}]`, 'current')
|
|
1902
|
-
.option('-e, --env, <ci | fqa | tr | fprd>', 'Fusion environment to build api urls from. used when publishing config.')
|
|
1903
|
-
.option('-s, --service, <string>', 'Define uri to custom app service. You can also define the env variable CUSTOM_APPAPI to be used on all publish commands. the --env parameter is ignored when set')
|
|
1904
|
-
.action((opt) => {
|
|
1905
|
-
var _a;
|
|
1906
|
-
if (opt.publish) {
|
|
1907
|
-
opt.output = (_a = opt.output) !== null && _a !== void 0 ? _a : 'app.config.json';
|
|
1908
|
-
if (!opt.env) {
|
|
1909
|
-
console.error(chalk.redBright('Missing required option --env when publishing, see --help for usage'));
|
|
1910
|
-
return;
|
|
1911
|
-
}
|
|
1912
|
-
createExportConfig({
|
|
1913
|
-
outputFile: opt.output,
|
|
1914
|
-
configFile: opt.config,
|
|
1915
|
-
}).then(() => {
|
|
1916
|
-
uploadExportConfig({
|
|
1917
|
-
configFile: opt.output,
|
|
1918
|
-
version: opt.version,
|
|
1919
|
-
env: opt.env,
|
|
1920
|
-
service: opt.service,
|
|
1921
|
-
});
|
|
1922
|
-
});
|
|
1923
|
-
return;
|
|
1924
|
-
}
|
|
1925
|
-
createExportConfig({
|
|
1926
|
-
outputFile: opt.output,
|
|
1927
|
-
configFile: opt.config,
|
|
1928
|
-
});
|
|
1929
|
-
});
|
|
1930
|
-
app.command('upload-config')
|
|
1931
|
-
.description('Upload config file to app api')
|
|
1932
|
-
.requiredOption('-c, --config <string>', 'Generated application config json file')
|
|
1933
|
-
.option('-v, --version <string>', `Publish app config to version [${chalk.yellowBright('(semver | current | latest | preview)')}]`, 'current')
|
|
1934
|
-
.requiredOption('-e, --env, <ci | fqa | tr | fprd>', 'Fusion environment to build api urls from. used when publishing config.')
|
|
1935
|
-
.option('-s, --service, <string>', 'Define uri to custom app service. You can also define the env variable CUSTOM_APPAPI to be used on all publish commands. the --env parameter is ignored when set')
|
|
1936
|
-
.action((opt) => {
|
|
1937
|
-
uploadExportConfig({
|
|
1938
|
-
configFile: opt.config,
|
|
1939
|
-
version: opt.version,
|
|
1940
|
-
env: opt.env,
|
|
1941
|
-
service: opt.service,
|
|
1942
|
-
});
|
|
1943
|
-
});
|
|
1944
|
-
app.command('build-manifest')
|
|
1945
|
-
.description('Generate manifest')
|
|
1946
|
-
.option('-o, --output <string>', 'output file')
|
|
1947
|
-
.option('-c, --config <string>', 'manifest config file')
|
|
1948
|
-
.action((opt) => {
|
|
1949
|
-
createBuildManifest({
|
|
1950
|
-
outputFile: opt.output,
|
|
1951
|
-
configFile: opt.config,
|
|
1952
|
-
});
|
|
1953
|
-
});
|
|
1954
|
-
app.command('build-pack')
|
|
1955
|
-
.description('Create distributable app bundle of the application')
|
|
1956
|
-
.option('-o, --outDir, <string>', 'output directory of package', 'dist')
|
|
1957
|
-
.option('-a, --archive, <string>', 'output filename', 'app-bundle.zip')
|
|
1958
|
-
.action((opt) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1959
|
-
const { outDir, archive } = opt;
|
|
1960
|
-
bundleApplication({ archive, outDir });
|
|
1961
|
-
}));
|
|
1962
|
-
app.command('build-publish')
|
|
1963
|
-
.description('Publish application to app api')
|
|
1964
|
-
.option('-t, --tag, <string>', `Tagname to publish this build as [${chalk.yellowBright('(latest | preview)')}]`, 'latest')
|
|
1965
|
-
.requiredOption('-e, --env, <ci | fqa | tr | fprd>', 'Fusion environment to build api urls from')
|
|
1966
|
-
.option('-s, --service, <string>', 'Define uri to custom app service. You can also define the env variable CUSTOM_APPAPI to be used on all publish commands. the --env parameter is ignored when set')
|
|
1967
|
-
.action((opt) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1968
|
-
const { tag, env, service } = opt;
|
|
1969
|
-
publishApplication({ tag, env, service });
|
|
1970
|
-
}));
|
|
1971
|
-
app.command('build-upload')
|
|
1972
|
-
.description('Upload packaged app bundle to app api')
|
|
1973
|
-
.option('-b, --bundle, <string>', 'The packaged app bundle file to upload', 'app-bundle.zip')
|
|
1974
|
-
.requiredOption('-e, --env, <ci | fqa | tr | fprd>', 'Fusion environment to build api urls from')
|
|
1975
|
-
.option('-s, --service, <string>', 'Define uri to custom app service. You can also define the env variable CUSTOM_APPAPI to be used on all publish commands. the --env parameter is ignored when set')
|
|
1976
|
-
.action((opt) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1977
|
-
const { bundle, env, service } = opt;
|
|
1978
|
-
uploadApplication({ bundle, env, service });
|
|
1979
|
-
}));
|
|
1980
|
-
app.command('build-tag')
|
|
1981
|
-
.description('Tag a published version')
|
|
1982
|
-
.option('-t, --tag, <string>', `Tag the published version with tagname [${chalk.yellowBright('(latest | preview)')}]`, 'latest')
|
|
1983
|
-
.requiredOption('-v, --version, <string>', 'Version number to tag, must be a published version number')
|
|
1984
|
-
.requiredOption('-e, --env, <ci | fqa | tr | fprd>', 'Fusion environment to build api urls from')
|
|
1985
|
-
.option('-s, --service, <string>', 'Define uri to custom app service. You can also define the env variable CUSTOM_APPAPI to be used on all publish commands. the --env parameter is ignored when set')
|
|
1986
|
-
.action((opt) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1987
|
-
const { tag, version, env, service } = opt;
|
|
1988
|
-
tagApplication({ tag, version, env, service });
|
|
1989
|
-
}));
|
|
1990
|
-
};
|
|
1991
|
-
|
|
1992
|
-
const pkg = readPackageUpSync({ cwd: fileURLToPath(import.meta.url) });
|
|
1993
|
-
if (!pkg) {
|
|
1994
|
-
throw Error('failed to find program root');
|
|
1995
|
-
}
|
|
1996
|
-
process.env.CLI_BIN = resolve(dirname(pkg.path), String(pkg.packageJson.bin['fusion-framework-cli']));
|
|
1997
|
-
const program = new Command();
|
|
1998
|
-
program.name(pkg.packageJson.name);
|
|
1999
|
-
program.description(`fusion-framework-cli@${pkg.packageJson.version}.\nCLI for the Fusion Framework`);
|
|
2000
|
-
program.version(pkg.packageJson.version, '-V, --vers', 'CLI version');
|
|
2001
|
-
app(program);
|
|
2002
|
-
/** read action and options and start programs */
|
|
2003
|
-
program.parse();
|