Skip to content

Commit

Permalink
feat(admin-ui-plugin): Allow ui languages to be set in the AdminUiPlugin
Browse files Browse the repository at this point in the history
Relates to #264
  • Loading branch information
michaelbromley committed Mar 23, 2020
1 parent aa4452e commit db3bce3
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 33 deletions.
91 changes: 59 additions & 32 deletions packages/admin-ui-plugin/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import {
Type,
} from '@vendure/common/lib/shared-types';
import {
AuthOptions,
ConfigService,
createProxyHandler,
LanguageCode,
Logger,
OnVendureBootstrap,
OnVendureClose,
Expand All @@ -29,7 +29,7 @@ import { DEFAULT_APP_PATH, loggerCtx } from './constants';
*
* @docsCategory AdminUiPlugin
*/
export interface AdminUiOptions {
export interface AdminUiPluginOptions {
/**
* @description
* The port on which the server will listen. If not
Expand All @@ -55,6 +55,7 @@ export interface AdminUiOptions {
* to. If set to "auto", the admin ui app will determine the hostname from the
* current location (i.e. `window.location.hostname`).
*
* @deprecated Use the adminUiConfig property instead
* @default 'auto'
*/
apiHost?: string | 'auto';
Expand All @@ -64,9 +65,16 @@ export interface AdminUiOptions {
* to. If set to "auto", the admin ui app will determine the port from the
* current location (i.e. `window.location.port`).
*
* @deprecated Use the adminUiConfig property instead
* @default 'auto'
*/
apiPort?: number | 'auto';
/**
* @description
* Allows the contents of the `vendure-ui-config.json` file to be set, e.g.
* for specifying the Vendure GraphQL API host, available UI languages, etc.
*/
adminUiConfig?: Partial<AdminUiConfig>;
}

/**
Expand Down Expand Up @@ -104,7 +112,7 @@ export interface AdminUiOptions {
configuration: config => AdminUiPlugin.configure(config),
})
export class AdminUiPlugin implements OnVendureBootstrap, OnVendureClose {
private static options: AdminUiOptions;
private static options: AdminUiPluginOptions;
private server: Server;

constructor(private configService: ConfigService) {}
Expand All @@ -113,7 +121,7 @@ export class AdminUiPlugin implements OnVendureBootstrap, OnVendureClose {
* @description
* Set the plugin options
*/
static init(options: AdminUiOptions): Type<AdminUiPlugin> {
static init(options: AdminUiPluginOptions): Type<AdminUiPlugin> {
this.options = options;
return AdminUiPlugin;
}
Expand Down Expand Up @@ -156,20 +164,27 @@ export class AdminUiPlugin implements OnVendureBootstrap, OnVendureClose {

/** @internal */
async onVendureBootstrap() {
const { adminApiPath, authOptions } = this.configService;
const { apiHost, apiPort, port, app } = AdminUiPlugin.options;
const { apiHost, apiPort, port, app, adminUiConfig } = AdminUiPlugin.options;
// TODO: Remove in next minor version (0.11.0)
if (apiHost || apiPort) {
Logger.warn(
`The "apiHost" and "apiPort" options are deprecated and will be removed in a future version.`,
loggerCtx,
);
Logger.warn(
`Use the "adminUiConfig.apiHost", "adminUiConfig.apiPort" properties instead.`,
loggerCtx,
);
}
const adminUiAppPath = AdminUiPlugin.isDevModeApp(app)
? path.join(app.sourcePath, 'src')
: (app && app.path) || DEFAULT_APP_PATH;
const adminUiConfigPath = path.join(adminUiAppPath, 'vendure-ui-config.json');
const overwriteConfig = () =>
this.overwriteAdminUiConfig({
host: apiHost || 'auto',
port: apiPort || 'auto',
adminApiPath,
authOptions,
adminUiConfigPath,
});

const overwriteConfig = () => {
const uiConfig = this.getAdminUiConfig(adminUiConfig);
return this.overwriteAdminUiConfig(adminUiConfigPath, uiConfig);
};

if (!AdminUiPlugin.isDevModeApp(app)) {
// If not in dev mode, start a static server for the compiled app
Expand Down Expand Up @@ -215,19 +230,38 @@ export class AdminUiPlugin implements OnVendureBootstrap, OnVendureClose {
}
}

/**
* Takes an optional AdminUiConfig provided in the plugin options, and returns a complete
* config object for writing to disk.
*/
private getAdminUiConfig(partialConfig?: Partial<AdminUiConfig>): AdminUiConfig {
const { authOptions } = this.configService;

const propOrDefault = <Prop extends keyof AdminUiConfig>(
prop: Prop,
defaultVal: AdminUiConfig[Prop],
): AdminUiConfig[Prop] => {
return partialConfig ? (partialConfig as AdminUiConfig)[prop] || defaultVal : defaultVal;
};
return {
adminApiPath: propOrDefault('adminApiPath', this.configService.adminApiPath),
apiHost: propOrDefault('apiHost', AdminUiPlugin.options.apiHost || 'http://localhost'),
apiPort: propOrDefault('apiPort', AdminUiPlugin.options.apiPort || this.configService.port),
tokenMethod: propOrDefault('tokenMethod', authOptions.tokenMethod || 'cookie'),
authTokenHeaderKey: propOrDefault(
'authTokenHeaderKey',
authOptions.authTokenHeaderKey || DEFAULT_AUTH_TOKEN_HEADER_KEY,
),
defaultLanguage: propOrDefault('defaultLanguage', LanguageCode.en),
availableLanguages: propOrDefault('availableLanguages', [LanguageCode.en, LanguageCode.es]),
};
}

/**
* Overwrites the parts of the admin-ui app's `vendure-ui-config.json` file relating to connecting to
* the server admin API.
*/
private async overwriteAdminUiConfig(options: {
host: string | 'auto';
port: number | 'auto';
adminApiPath: string;
authOptions: AuthOptions;
adminUiConfigPath: string;
}) {
const { host, port, adminApiPath, authOptions, adminUiConfigPath } = options;

private async overwriteAdminUiConfig(adminUiConfigPath: string, config: AdminUiConfig) {
/**
* It might be that the ui-devkit compiler has not yet copied the config
* file to the expected location (perticularly when running in watch mode),
Expand Down Expand Up @@ -258,18 +292,11 @@ export class AdminUiPlugin implements OnVendureBootstrap, OnVendureClose {
}

const content = await pollForConfigFile();
let config: AdminUiConfig;
try {
config = JSON.parse(content);
await fs.writeFile(adminUiConfigPath, JSON.stringify(config, null, 2));
} catch (e) {
throw new Error('[AdminUiPlugin] Could not parse vendure-ui-config.json file:\n' + e.message);
throw new Error('[AdminUiPlugin] Could not write vendure-ui-config.json file:\n' + e.message);
}
config.apiHost = host || 'http://localhost';
config.apiPort = port;
config.adminApiPath = adminApiPath;
config.tokenMethod = authOptions.tokenMethod || 'cookie';
config.authTokenHeaderKey = authOptions.authTokenHeaderKey || DEFAULT_AUTH_TOKEN_HEADER_KEY;
await fs.writeFile(adminUiConfigPath, JSON.stringify(config, null, 2));
Logger.verbose(`Applied configuration to vendure-ui-config.json file`, loggerCtx);
}

Expand Down
58 changes: 57 additions & 1 deletion packages/common/src/shared-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,15 +97,71 @@ export type ConfigArgSubset<T extends ConfigArgType> = T;
export type CustomFieldsObject = { [key: string]: any };

/**
* This interface describes the shape of the JSON config file used by the Admin UI.
* @description
* This interface describes JSON config file (vendure-ui-config.json) used by the Admin UI.
* The values are loaded at run-time by the Admin UI app, and allow core configuration to be
* managed without the need to re-build the application.
*
* @docsCategory AdminUiPlugin
*/
export interface AdminUiConfig {
/**
* @description
* The hostname of the Vendure server which the admin ui will be making API calls
* to. If set to "auto", the Admin UI app will determine the hostname from the
* current location (i.e. `window.location.hostname`).
*
* @default 'http://localhost'
*/
apiHost: string | 'auto';
/**
* @description
* The port of the Vendure server which the admin ui will be making API calls
* to. If set to "auto", the Admin UI app will determine the port from the
* current location (i.e. `window.location.port`).
*
* @default 3000
*/
apiPort: number | 'auto';
/**
* @description
* The path to the GraphQL Admin API.
*
* @default 'admin-api'
*/
adminApiPath: string;
/**
* @description
* Whether to use cookies or bearer tokens to track sessions.
* Should match the setting of in the server's `tokenMethod` config
* option.
*
* @default 'cookie'
*/
tokenMethod: 'cookie' | 'bearer';
/**
* @description
* The header used when using the 'bearer' auth method. Should match the
* setting of the server's `authOptions.authTokenHeaderKey` config
* option.
*
* @default 'vendure-auth-token'
*/
authTokenHeaderKey: string;
/**
* @description
* The default language for the Admin UI. Must be one of the
* items specified in the `availableLanguages` property.
*
* @default LanguageCode.en
*/
defaultLanguage: LanguageCode;
/**
* @description
* An array of languages for which translations exist for the Admin UI.
*
* @default [LanguageCode.en, LanguageCode.es]
*/
availableLanguages: LanguageCode[];
}

Expand Down

0 comments on commit db3bce3

Please sign in to comment.