[New platform] Restrict import from core&plugin internals for ts files (#34688) (#34859)

* eslint-plugin-import should resolve *.ts files

* no_restricted_paths adc support filename exclusion

* fix linter errors

* update autogenerateds docs

* export directly
This commit is contained in:
Mikhail Shustov 2019-04-10 15:58:32 +02:00 committed by GitHub
parent ddd5b5fa54
commit e0afa46852
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 292 additions and 20 deletions

View file

@ -132,11 +132,13 @@ module.exports = {
],
from: [
'src/core/public/**/*',
'!src/core/public/index*',
'!src/core/public/index.ts',
'!src/core/public/mocks.ts',
'!src/core/public/utils/**/*',
'src/core/server/**/*',
'!src/core/server/index*',
'!src/core/server/index.ts',
'!src/core/server/mocks.ts',
'src/plugins/**/public/**/*',
'!src/plugins/**/public/index*',

View file

@ -0,0 +1,23 @@
[Home](./index) > [kibana-plugin-server](./kibana-plugin-server.md) > [ConfigService](./kibana-plugin-server.configservice.md) > [atPath](./kibana-plugin-server.configservice.atpath.md)
## ConfigService.atPath() method
Reads the subset of the config at the specified `path` and validates it against the static `schema` on the given `ConfigClass`<!-- -->.
<b>Signature:</b>
```typescript
atPath<TSchema extends Type<any>, TConfig>(path: ConfigPath, ConfigClass: ConfigWithSchema<TSchema, TConfig>): Observable<TConfig>;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| path | <code>ConfigPath</code> | The path to the desired subset of the config. |
| ConfigClass | <code>ConfigWithSchema&lt;TSchema, TConfig&gt;</code> | A class (not an instance of a class) that contains a static <code>schema</code> that we validate the config at the given <code>path</code> against. |
<b>Returns:</b>
`Observable<TConfig>`

View file

@ -0,0 +1,15 @@
[Home](./index) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [ConfigService](./kibana-plugin-server.configservice.md) &gt; [getConfig$](./kibana-plugin-server.configservice.getconfig$.md)
## ConfigService.getConfig$() method
Returns the full config object observable. This is not intended for "normal use", but for features that \_need\_ access to the full object.
<b>Signature:</b>
```typescript
getConfig$(): Observable<Config>;
```
<b>Returns:</b>
`Observable<Config>`

View file

@ -0,0 +1,13 @@
[Home](./index) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [ConfigService](./kibana-plugin-server.configservice.md) &gt; [getUnusedPaths](./kibana-plugin-server.configservice.getunusedpaths.md)
## ConfigService.getUnusedPaths() method
<b>Signature:</b>
```typescript
getUnusedPaths(): Promise<string[]>;
```
<b>Returns:</b>
`Promise<string[]>`

View file

@ -0,0 +1,13 @@
[Home](./index) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [ConfigService](./kibana-plugin-server.configservice.md) &gt; [getUsedPaths](./kibana-plugin-server.configservice.getusedpaths.md)
## ConfigService.getUsedPaths() method
<b>Signature:</b>
```typescript
getUsedPaths(): Promise<string[]>;
```
<b>Returns:</b>
`Promise<string[]>`

View file

@ -0,0 +1,20 @@
[Home](./index) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [ConfigService](./kibana-plugin-server.configservice.md) &gt; [isEnabledAtPath](./kibana-plugin-server.configservice.isenabledatpath.md)
## ConfigService.isEnabledAtPath() method
<b>Signature:</b>
```typescript
isEnabledAtPath(path: ConfigPath): Promise<boolean>;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| path | <code>ConfigPath</code> | |
<b>Returns:</b>
`Promise<boolean>`

View file

@ -0,0 +1,22 @@
[Home](./index) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [ConfigService](./kibana-plugin-server.configservice.md)
## ConfigService class
<b>Signature:</b>
```typescript
export declare class ConfigService
```
## Methods
| Method | Modifiers | Description |
| --- | --- | --- |
| [atPath(path, ConfigClass)](./kibana-plugin-server.configservice.atpath.md) | | Reads the subset of the config at the specified <code>path</code> and validates it against the static <code>schema</code> on the given <code>ConfigClass</code>. |
| [getConfig$()](./kibana-plugin-server.configservice.getconfig$.md) | | Returns the full config object observable. This is not intended for "normal use", but for features that \_need\_ access to the full object. |
| [getUnusedPaths()](./kibana-plugin-server.configservice.getunusedpaths.md) | | |
| [getUsedPaths()](./kibana-plugin-server.configservice.getusedpaths.md) | | |
| [isEnabledAtPath(path)](./kibana-plugin-server.configservice.isenabledatpath.md) | | |
| [optionalAtPath(path, ConfigClass)](./kibana-plugin-server.configservice.optionalatpath.md) | | Same as <code>atPath</code>, but returns <code>undefined</code> if there is no config at the specified path.[ConfigService.atPath()](./kibana-plugin-server.configservice.atpath.md) |

View file

@ -0,0 +1,25 @@
[Home](./index) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [ConfigService](./kibana-plugin-server.configservice.md) &gt; [optionalAtPath](./kibana-plugin-server.configservice.optionalatpath.md)
## ConfigService.optionalAtPath() method
Same as `atPath`<!-- -->, but returns `undefined` if there is no config at the specified path.
[ConfigService.atPath()](./kibana-plugin-server.configservice.atpath.md)
<b>Signature:</b>
```typescript
optionalAtPath<TSchema extends Type<any>, TConfig>(path: ConfigPath, ConfigClass: ConfigWithSchema<TSchema, TConfig>): Observable<TConfig | undefined>;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| path | <code>ConfigPath</code> | |
| ConfigClass | <code>ConfigWithSchema&lt;TSchema, TConfig&gt;</code> | |
<b>Returns:</b>
`Observable<TConfig | undefined>`

View file

@ -0,0 +1,9 @@
[Home](./index) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [ElasticsearchServiceSetup](./kibana-plugin-server.elasticsearchservicesetup.md) &gt; [adminClient$](./kibana-plugin-server.elasticsearchservicesetup.adminclient$.md)
## ElasticsearchServiceSetup.adminClient$ property
<b>Signature:</b>
```typescript
readonly adminClient$: Observable<ClusterClient>;
```

View file

@ -0,0 +1,9 @@
[Home](./index) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [ElasticsearchServiceSetup](./kibana-plugin-server.elasticsearchservicesetup.md) &gt; [createClient](./kibana-plugin-server.elasticsearchservicesetup.createclient.md)
## ElasticsearchServiceSetup.createClient property
<b>Signature:</b>
```typescript
readonly createClient: (type: string, config: ElasticsearchClientConfig) => ClusterClient;
```

View file

@ -0,0 +1,9 @@
[Home](./index) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [ElasticsearchServiceSetup](./kibana-plugin-server.elasticsearchservicesetup.md) &gt; [dataClient$](./kibana-plugin-server.elasticsearchservicesetup.dataclient$.md)
## ElasticsearchServiceSetup.dataClient$ property
<b>Signature:</b>
```typescript
readonly dataClient$: Observable<ClusterClient>;
```

View file

@ -0,0 +1,11 @@
[Home](./index) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [ElasticsearchServiceSetup](./kibana-plugin-server.elasticsearchservicesetup.md) &gt; [legacy](./kibana-plugin-server.elasticsearchservicesetup.legacy.md)
## ElasticsearchServiceSetup.legacy property
<b>Signature:</b>
```typescript
readonly legacy: {
readonly config$: Observable<ElasticsearchConfig>;
};
```

View file

@ -0,0 +1,20 @@
[Home](./index) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [ElasticsearchServiceSetup](./kibana-plugin-server.elasticsearchservicesetup.md)
## ElasticsearchServiceSetup interface
<b>Signature:</b>
```typescript
export interface ElasticsearchServiceSetup
```
## Properties
| Property | Type | Description |
| --- | --- | --- |
| [adminClient$](./kibana-plugin-server.elasticsearchservicesetup.adminclient$.md) | <code>Observable&lt;ClusterClient&gt;</code> | |
| [createClient](./kibana-plugin-server.elasticsearchservicesetup.createclient.md) | <code>(type: string, config: ElasticsearchClientConfig) =&gt; ClusterClient</code> | |
| [dataClient$](./kibana-plugin-server.elasticsearchservicesetup.dataclient$.md) | <code>Observable&lt;ClusterClient&gt;</code> | |
| [legacy](./kibana-plugin-server.elasticsearchservicesetup.legacy.md) | <code>{`<p/>` readonly config$: Observable&lt;ElasticsearchConfig&gt;;`<p/>` }</code> | |

View file

@ -7,6 +7,7 @@
| Class | Description |
| --- | --- |
| [ClusterClient](./kibana-plugin-server.clusterclient.md) | Represents an Elasticsearch cluster API client and allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via <code>asScoped(...)</code>). |
| [ConfigService](./kibana-plugin-server.configservice.md) | |
| [ScopedClusterClient](./kibana-plugin-server.scopedclusterclient.md) | Serves the same purpose as "normal" <code>ClusterClient</code> but exposes additional <code>callAsCurrentUser</code> method that doesn't use credentials of the Kibana internal user (as <code>callAsInternalUser</code> does) to request Elasticsearch API, but rather passes HTTP headers extracted from the current user request to the API |
## Interfaces
@ -15,6 +16,7 @@
| --- | --- |
| [CallAPIOptions](./kibana-plugin-server.callapioptions.md) | The set of options that defines how API call should be made and result be processed. |
| [CoreSetup](./kibana-plugin-server.coresetup.md) | |
| [ElasticsearchServiceSetup](./kibana-plugin-server.elasticsearchservicesetup.md) | |
| [Logger](./kibana-plugin-server.logger.md) | Logger exposes all the necessary methods to log any type of information and this is the interface used by the logging consumers including plugins. |
| [LoggerFactory](./kibana-plugin-server.loggerfactory.md) | The single purpose of <code>LoggerFactory</code> interface is to define a way to retrieve a context-based logger instance. |
| [LogMeta](./kibana-plugin-server.logmeta.md) | Contextual metadata |

View file

@ -23,6 +23,11 @@ module.exports = {
],
settings: {
'import/resolver': {
node: {
extensions: ['.mjs', '.js', '.json', '.ts', '.tsx'],
},
},
react: {
version: semver.valid(semver.coerce(PKG.dependencies.react)),
},

View file

@ -156,6 +156,22 @@ ruleTester.run('@kbn/eslint/no-restricted-paths', rule, {
},
],
},
{
code: 'const d = require("./deep/d.js")',
filename: path.join(__dirname, './files/no_restricted_paths/server/b.js'),
options: [
{
basePath: __dirname,
zones: [
{
allowSameFolder: true,
target: 'files/no_restricted_paths/**/*',
from: ['files/no_restricted_paths/**/*', '!files/no_restricted_paths/server/b*'],
},
],
},
],
},
],
invalid: [

View file

@ -51,8 +51,10 @@ function traverseToTopFolder(src, pattern) {
}
function isSameFolderOrDescendent(src, imported, pattern) {
const srcFileFolderRoot = traverseToTopFolder(src, pattern);
const importedFileFolderRoot = traverseToTopFolder(imported, pattern);
// to allow to exclude file by name in pattern (e.g., !**/index*) we start with file dirname and then traverse
const srcFileFolderRoot = traverseToTopFolder(path.dirname(src), pattern);
const importedFileFolderRoot = traverseToTopFolder(path.dirname(imported), pattern);
return srcFileFolderRoot === importedFileFolderRoot;
}

View file

@ -25,7 +25,7 @@ import { distinctUntilChanged, first, map } from 'rxjs/operators';
import { Config, ConfigPath, ConfigWithSchema, Env } from '.';
import { Logger, LoggerFactory } from '../logging';
/** @internal */
/** @public */
export class ConfigService {
private readonly log: Logger;
@ -37,7 +37,7 @@ export class ConfigService {
constructor(
private readonly config$: Observable<Config>,
readonly env: Env,
private readonly env: Env,
logger: LoggerFactory
) {
this.log = logger.get('config');
@ -55,8 +55,8 @@ export class ConfigService {
* Reads the subset of the config at the specified `path` and validates it
* against the static `schema` on the given `ConfigClass`.
*
* @param path The path to the desired subset of the config.
* @param ConfigClass A class (not an instance of a class) that contains a
* @param path - The path to the desired subset of the config.
* @param ConfigClass - A class (not an instance of a class) that contains a
* static `schema` that we validate the config at the given `path` against.
*/
public atPath<TSchema extends Type<any>, TConfig>(
@ -72,7 +72,7 @@ export class ConfigService {
* Same as `atPath`, but returns `undefined` if there is no config at the
* specified path.
*
* @see atPath
* {@link ConfigService.atPath}
*/
public optionalAtPath<TSchema extends Type<any>, TConfig>(
path: ConfigPath,

View file

@ -26,12 +26,14 @@ import { ClusterClient } from './cluster_client';
import { ElasticsearchClientConfig } from './elasticsearch_client_config';
import { ElasticsearchConfig } from './elasticsearch_config';
/** @internal */
interface CoreClusterClients {
config: ElasticsearchConfig;
adminClient: ClusterClient;
dataClient: ClusterClient;
}
/** @public */
export interface ElasticsearchServiceSetup {
// Required for the BWC with the legacy Kibana only.
readonly legacy: {

View file

@ -21,6 +21,7 @@ import { HttpServiceSetup } from './http';
import { PluginsServiceSetup } from './plugins';
export { bootstrap } from './bootstrap';
export { ConfigService } from './config';
export {
CallAPIOptions,
ClusterClient,
@ -43,3 +44,5 @@ export interface CoreSetup {
elasticsearch: ElasticsearchServiceSetup;
plugins: PluginsServiceSetup;
}
export { ElasticsearchServiceSetup, HttpServiceSetup, PluginsServiceSetup };

View file

@ -38,16 +38,34 @@ export class ClusterClient {
}
// @public (undocumented)
export interface CoreSetup {
// Warning: (ae-forgotten-export) The symbol "ElasticsearchServiceSetup" needs to be exported by the entry point index.d.ts
export class ConfigService {
// Warning: (ae-forgotten-export) The symbol "Config" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "Env" needs to be exported by the entry point index.d.ts
//
// (undocumented)
constructor(config$: Observable<Config>, env: Env, logger: LoggerFactory);
// Warning: (ae-forgotten-export) The symbol "ConfigPath" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "ConfigWithSchema" needs to be exported by the entry point index.d.ts
atPath<TSchema extends Type<any>, TConfig>(path: ConfigPath, ConfigClass: ConfigWithSchema<TSchema, TConfig>): Observable<TConfig>;
getConfig$(): Observable<Config>;
// (undocumented)
getUnusedPaths(): Promise<string[]>;
// (undocumented)
getUsedPaths(): Promise<string[]>;
// (undocumented)
isEnabledAtPath(path: ConfigPath): Promise<boolean>;
optionalAtPath<TSchema extends Type<any>, TConfig>(path: ConfigPath, ConfigClass: ConfigWithSchema<TSchema, TConfig>): Observable<TConfig | undefined>;
}
// @public (undocumented)
export interface CoreSetup {
// (undocumented)
elasticsearch: ElasticsearchServiceSetup;
// Warning: (ae-forgotten-export) The symbol "HttpServiceSetup" needs to be exported by the entry point index.d.ts
// Warning: (ae-incompatible-release-tags) The symbol "http" is marked as @public, but its signature references "HttpServiceSetup" which is marked as @internal
//
// (undocumented)
http: HttpServiceSetup;
// Warning: (ae-forgotten-export) The symbol "PluginsServiceSetup" needs to be exported by the entry point index.d.ts
// Warning: (ae-incompatible-release-tags) The symbol "plugins" is marked as @public, but its signature references "PluginsServiceSetup" which is marked as @internal
//
// (undocumented)
plugins: PluginsServiceSetup;
@ -57,7 +75,6 @@ export interface CoreSetup {
//
// @internal
export interface DiscoveredPlugin {
// Warning: (ae-forgotten-export) The symbol "ConfigPath" needs to be exported by the entry point index.d.ts
readonly configPath: ConfigPath;
readonly id: PluginName;
readonly optionalPlugins: ReadonlyArray<PluginName>;
@ -74,9 +91,29 @@ export type ElasticsearchClientConfig = Pick<ConfigOptions, 'keepAlive' | 'log'
ssl?: Partial<ElasticsearchConfig['ssl']>;
};
// @public (undocumented)
export interface ElasticsearchServiceSetup {
// (undocumented)
readonly adminClient$: Observable<ClusterClient>;
// (undocumented)
readonly createClient: (type: string, config: ElasticsearchClientConfig) => ClusterClient;
// (undocumented)
readonly dataClient$: Observable<ClusterClient>;
// (undocumented)
readonly legacy: {
readonly config$: Observable<ElasticsearchConfig>;
};
}
// @public (undocumented)
export type Headers = Record<string, string | string[] | undefined>;
// Warning: (ae-forgotten-export) The symbol "HttpServerInfo" needs to be exported by the entry point index.d.ts
// Warning: (ae-internal-missing-underscore) The name HttpServiceSetup should be prefixed with an underscore because the declaration is marked as "@internal"
//
// @internal (undocumented)
export type HttpServiceSetup = HttpServerInfo;
// @public
export interface Logger {
debug(message: string, meta?: LogMeta): void;
@ -177,6 +214,19 @@ export interface PluginSetupContext {
};
}
// Warning: (ae-internal-missing-underscore) The name PluginsServiceSetup should be prefixed with an underscore because the declaration is marked as "@internal"
//
// @internal (undocumented)
export interface PluginsServiceSetup {
// (undocumented)
contracts: Map<PluginName, unknown>;
// (undocumented)
uiPlugins: {
public: Map<PluginName, DiscoveredPlugin>;
internal: Map<PluginName, DiscoveredPluginInternal>;
};
}
// @public
export class ScopedClusterClient {
// (undocumented)
@ -189,7 +239,7 @@ export class ScopedClusterClient {
// Warnings were encountered during analysis:
//
// src/core/server/plugins/plugin_context.ts:35:9 - (ae-forgotten-export) The symbol "EnvironmentMode" needs to be exported by the entry point index.d.ts
// src/core/server/plugins/plugin_context.ts:39:9 - (ae-forgotten-export) The symbol "ConfigWithSchema" needs to be exported by the entry point index.d.ts
// src/core/server/plugins/plugins_service.ts:33:17 - (ae-forgotten-export) The symbol "DiscoveredPluginInternal" needs to be exported by the entry point index.d.ts
// (No @packageDocumentation comment for this package)

View file

@ -19,10 +19,10 @@
import { Server } from 'hapi';
import { ConfigService } from '../../core/server/config';
import { ElasticsearchServiceSetup } from '../../core/server/elasticsearch';
import { HttpServerInfo } from '../../core/server/http/';
import { PluginsServiceSetup } from '../../core/server/plugins/plugins_service';
import { ConfigService } from '../../core/server/';
import { ElasticsearchServiceSetup } from '../../core/server/';
import { HttpServiceSetup } from '../../core/server/';
import { PluginsServiceSetup } from '../../core/server/';
import { ApmOssPlugin } from '../core_plugins/apm_oss';
import { CallClusterWithRequest, ElasticsearchPlugin } from '../core_plugins/elasticsearch';
@ -71,7 +71,7 @@ export default class KbnServer {
};
stop: null;
params: {
serverOptions: HttpServerInfo;
serverOptions: ElasticsearchServiceSetup;
handledConfigPaths: Unpromise<ReturnType<ConfigService['getUsedPaths']>>;
};
};

View file

@ -18,6 +18,7 @@
*/
import Hapi from 'hapi';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { defaultValidationErrorHandler } from '../../../../core/server/http/http_tools';
const defaultConfig = {