-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[core/ui] bootstrap the legacy platform within the new platform #20699
[core/ui] bootstrap the legacy platform within the new platform #20699
Conversation
injectedMetadataForTesting: { | ||
legacyMetadata | ||
} | ||
}).initLegacyPlatform(() => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The convention we've talked about is having a core start
function and then invoking legacy startup/bootstrap through a legacy service within the core system. This way we can identify precisely when the legacy code kicks off in the context of all the new platform services we'd be rolling out.
Is there a reason we need to abandon that approach for this initLegacyPlatform approach?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope, happy to move it there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just didn't want to worry about start()/stop() right now, but it's not a big deal.
This comment has been minimized.
This comment has been minimized.
import { InjectedMetadataService } from '../injected_metadata'; | ||
|
||
interface Deps { | ||
injectedMetadata: ReturnType<InjectedMetadataService['start']>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm really not sure what to name this type
, but once we get plugins in the mix we will probably want to export a named type they can use to define the dependencies of their start functions... InjectedMetadataContract
? InjectedMetadataStartContract
? StartedInjectedMetadata
...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
InjectedMetadataStartContract
works for me. I never really intended the word "contract" to be codified, but if that's the language we're using when we talk about this thing, we might as well just write it that way as well.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
d1bcd06
to
4f8fe21
Compare
4bfb104
to
5357110
Compare
@epixa this is ready for another look |
This comment has been minimized.
This comment has been minimized.
💚 Build Succeeded |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes here look good, and I spun up Kibana and clicked around, everything seemed unaffected by this change as we'd expect.
This all needs unit tests though.
src/core/public/core_system.test.ts
Outdated
@@ -100,16 +100,22 @@ describe('constructor', () => { | |||
}); | |||
|
|||
describe('#start()', () => { | |||
it('calls lifecycleSystem#start() and injectedMetadata#start()', () => { | |||
const core = new CoreSystem({ | |||
let core; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought you were the one in particular that hated this pattern and wanted everyone to use setup functions instead!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haha, I do, but setup functions are best because they take arguments, when there aren't any arguments I'm not super picky. But point taken!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is also the issue that the mocks are cleared between each test, so starting core once and reusing the value for each test wouldn't work anyway.
Still LGTM |
127ef04
to
3e5a2ab
Compare
💚 Build Succeeded |
And still LGTM |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code looks good to me, just few nits and questions. Running PR locally and approve it after a smoke test :)
@@ -66,8 +64,8 @@ export default (kibana) => { | |||
|
|||
// add the modules from all of this plugins apps | |||
for (const app of uiApps) { | |||
if (app.getPluginId() === pluginId) { | |||
modules = union(modules, app.getModules()); | |||
if (app.getPluginId() === pluginId && !modules.includes(app.getMainModuleId())) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
optional nit: if we use const modules = new Set()
we won't need this !....includes
checks (that we can accidentally forget about if we decide to add new for
for some reason). The only cons is that we'll have to do modules: [...modules] or Array.from(modules)
later.
@@ -22,5 +22,5 @@ import { ToolingLog } from '@kbn/dev-utils'; | |||
import { File } from '../file'; | |||
|
|||
export function pickFilesToLint(log: ToolingLog, files: File[]) { | |||
return files.filter(file => file.isTypescript()); | |||
return files.filter(file => file.isTypescript() && !file.isFixture()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: what issues do we have without this? Can't we have nice linted fixtures? :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The issue this is that the fixture files are excluded from our main TS project because they can (and in my case need to) include invalid typescript for the purpose of making sure our types impose certain limitations. Since the files are not a part of a TS project they fail the pre-commit hook since TSLint needs the project file for a specific file to run the type-aware checks.
It's possible that we could run fixtures through a linting phase that isn't type enabled, but I'd rather do that in a separate PR. See #20910
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, got it, thanks for explanation.
src/core/public/core_system.ts
Outdated
useLegacyTestHarness?: LegacyPlatformParams['useLegacyTestHarness']; | ||
} | ||
|
||
export class CoreSystem { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: would be really great if you can add a top level comment for CoreSystem
explaining what its role and what it's supposed to do.
* under the License. | ||
*/ | ||
|
||
type Freezable = { [k: string]: any } | any[]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: hmm, | any[]
- is it really supposed to work for arrays as expected? I don't see any test that would check that case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Object.freeze works just fine on arrays, but you're right that there are not tests for this. I'll add them.
}; | ||
} | ||
|
||
export class InjectedMetadataService { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: could you please add a top level comment for this service as well?
src/core/public/core_system.test.ts
Outdated
|
||
it('calls injectedMetadata#start()', () => { | ||
startCore(); | ||
expect(MockInjectedMetadataService.mock.instances[0].start).toHaveBeenCalledTimes(1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
optional nit: maybe destructuring can make it a little bit more readable: const [mockInstance] = MockInjectedMetadataService.mock.instances;
body(kbn-chrome, id='#{appName}-body') | ||
kbn-initial-state(data=JSON.stringify(kibanaPayload)) | ||
body | ||
kbn-injected-metadata(data=JSON.stringify(injectedMetadata)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: can you please also remove the last kbn-initial-state
occurrence from
'<div><div id="editor" /><div id="editor_actions" /><div id="copy_as_curl" /><kbn-initial-state data="{}"/></div>'; |
"description": "When using the state:storeInSessionStorage setting with the short-urls, we need some way to get the full URL's hashed states into sessionStorage, this app will grab the URL from the kbn-initial-state and and put the URL hashed states into sessionStorage before redirecting the user." |
getModules() { | ||
return this._main ? [this._main] : []; | ||
getMainModuleId() { | ||
return this._main; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎉
src/ui/ui_bundles/ui_bundle.js
Outdated
await fcb(cb => unlink(this.getOutputPath(), cb)); | ||
} catch (e) { | ||
return null; | ||
async isCacheValid() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: while you're here, would you mind adding comment for isCacheValid
explaining how it works exactly?
@@ -28,7 +28,7 @@ export const UI_EXPORT_DEFAULTS = { | |||
|
|||
webpackAliases: { | |||
ui: resolve(ROOT, 'src/ui/public'), | |||
ui_framework: resolve(ROOT, 'ui_framework'), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: btw, not related to this PR, do we still need ui_framework
here
ui_framework: fromKibana('ui_framework'), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, I don't think so.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested locally in dev and non-dev modes, haven't noticed anything suspicious.
…-platform-bootstrap
💚 Build Succeeded |
…tic#20699) Fixes elastic#20694 Implements super basic new platform `core` system, which includes two services: `core.injectedMetadata` and `core.legacyPlatform`. The `core` currently has two responsibilities: 1. read the metadata from the DOM and initialize the `ui/metadata` module with legacy metadata, proving out how we plan to expose data from the new platform through the existing APIs/modules to the legacy platform. 2. bootstrap the legacy platform by loading either `ui/chrome` or `ui/test_harness` Because `core` mutates the `ui/metadata` module before bootstrapping the legacy platform all existing consumers of `ui/metadata` won't be impacted by the fact that metadata loading was moved into the new platform. We plan to do this for many other services that will need to exist in both the legacy and new platforms, like `ui/chrome` (see elastic#20696).
…) (#20913) Fixes #20694 Implements super basic new platform `core` system, which includes two services: `core.injectedMetadata` and `core.legacyPlatform`. The `core` currently has two responsibilities: 1. read the metadata from the DOM and initialize the `ui/metadata` module with legacy metadata, proving out how we plan to expose data from the new platform through the existing APIs/modules to the legacy platform. 2. bootstrap the legacy platform by loading either `ui/chrome` or `ui/test_harness` Because `core` mutates the `ui/metadata` module before bootstrapping the legacy platform all existing consumers of `ui/metadata` won't be impacted by the fact that metadata loading was moved into the new platform. We plan to do this for many other services that will need to exist in both the legacy and new platforms, like `ui/chrome` (see #20696).
6.4/6.x: 360c50b |
Fixes #20694
Implements super basic new platform
core
system, which includes two services:core.injectedMetadata
andcore.legacyPlatform
. Thecore
currently has two responsibilities:ui/metadata
module with legacy metadata, proving out how we plan to expose data from the new platform through the existing APIs/modules to the legacy platform.ui/chrome
orui/test_harness
Because
core
mutates theui/metadata
module before bootstrapping the legacy platform all existing consumers ofui/metadata
won't be impacted by the fact that metadata loading was moved into the new platform. We plan to do this for many other services that will need to exist in both the legacy and new platforms, likeui/chrome
(see #20696).