Skip to content

Commit

Permalink
POC for persistable state service.
Browse files Browse the repository at this point in the history
  • Loading branch information
lukeelmers committed Apr 9, 2020
1 parent 184f594 commit a356286
Show file tree
Hide file tree
Showing 6 changed files with 236 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/plugins/share/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ export {
ShareContextMenuPanelItem,
} from './types';

export {
PersistableState,
PersistableStates,
PersistableStateDefinition,
} from './persistable_state';

export {
UrlGeneratorId,
UrlGeneratorState,
Expand Down
21 changes: 21 additions & 0 deletions src/plugins/share/public/persistable_state/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

export * from './persistable_state_service';
export * from './types';
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { identity, noop } from 'lodash';
import { i18n } from '@kbn/i18n';
import { PersistableStateContract, PersistableStateDefinition } from './types';

export function createPersistableStateContract<Definition extends PersistableStateDefinition>(
definition: Definition
): PersistableStateContract<Definition['id']> {
const { id, isDeprecated, extractReferences, injectReferences, migrate } = definition;

if (isDeprecated && !migrate) {
throw new Error(
i18n.translate('share.persistableState.error.noMigrationFnProvided', {
defaultMessage:
'If the persistable state is marked as deprecated, you must provide a migration function.',
})
);
}

if (!isDeprecated && migrate) {
throw new Error(
i18n.translate('share.persistableState.error.migrationFnGivenNotDeprecated', {
defaultMessage:
'If you provide a migration function, you must mark this persistable state as deprecated.',
})
);
}

return {
id,
isDeprecated: !!isDeprecated,
extractReferences: extractReferences || identity,
injectReferences: injectReferences || noop,
migrate,
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { CoreSetup, CoreStart, Plugin } from 'src/core/public';
import { i18n } from '@kbn/i18n';
import { createPersistableStateContract } from './persistable_state_contract';
import { PersistableStateDefinition, PersistableStateContract } from './types';

export interface PersistableStateSetup {
register: (definition: PersistableStateDefinition) => Promise<void>;
}

export interface PersistableStateStart {
get: (definitionId: string) => Promise<PersistableStateContract<string>>;
}

export class PersistableStateService
implements Plugin<PersistableStateSetup, PersistableStateStart> {
private definitions: Map<string, PersistableStateContract<string>> = new Map();

public setup(core: CoreSetup): PersistableStateSetup {
return {
register: async definition => {
this.definitions.set(definition.id, createPersistableStateContract(definition));
},
};
}

public start(core: CoreStart): PersistableStateStart {
return {
get: async id => {
const definition = this.definitions.get(id);

if (!definition) {
throw new Error(
i18n.translate('share.persistableState.errors.noDefinitionWithId', {
defaultMessage: 'No persistable state definition found with id "{id}"',
values: { id },
})
);
}

return definition;
},
};
}

public stop() {}
}
80 changes: 80 additions & 0 deletions src/plugins/share/public/persistable_state/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { SavedObjectAttributes, SavedObjectReference } from 'src/core/public';

export interface PersistableState<
S extends SavedObjectAttributes,
I extends string | undefined = undefined,
MS extends SavedObjectAttributes | undefined = undefined
> {
state: S;
migratedId?: I;
migratedState?: MS;
}

/**
* Anybody registering persistable state should add a property to this
* interface so that any module importing PersistableStates can
* have the interfaces of all persistable states available to them.
*
* declare module '../../plugins/share/public' {
* interface PersistableStates {
* myId: PersistableState<myState, myMigratedId, myMigratedState>;
* }
* }
*
* @public
*/
export interface PersistableStates {
[key: string]: PersistableState<SavedObjectAttributes>;
}

interface SavedObjectWithReferences {
attributes: SavedObjectAttributes;
references: SavedObjectReference[];
}
type ExtractReferences = (opts: SavedObjectWithReferences) => SavedObjectWithReferences;
type InjectReferences = (opts: SavedObjectWithReferences) => void;

export interface PersistableStateDefinition<Id extends string = string> {
id: Id;
isDeprecated?: boolean;
extractReferences?: ExtractReferences;
injectReferences?: InjectReferences;
migrate?: (
state: PersistableStates[Id]['state']
) => Promise<{
state: PersistableStates[Id]['migratedState'];
id: PersistableStates[Id]['migratedId'];
}>;
}

export interface PersistableStateContract<Id extends string> {
id: Id;
isDeprecated: boolean;
extractReferences: ExtractReferences;
injectReferences: InjectReferences;
migrate?: (
state: PersistableStates[Id]['state']
) => Promise<{
state: PersistableStates[Id]['migratedState'];
id: PersistableStates[Id]['migratedId'];
}>;
}
10 changes: 10 additions & 0 deletions src/plugins/share/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,34 +28,44 @@ import {
UrlGeneratorsSetup,
UrlGeneratorsStart,
} from './url_generators/url_generator_service';
import {
PersistableStateService,
PersistableStateSetup,
PersistableStateStart,
} from './persistable_state';

export class SharePlugin implements Plugin<SharePluginSetup, SharePluginStart> {
private readonly shareMenuRegistry = new ShareMenuRegistry();
private readonly shareContextMenu = new ShareMenuManager();
private readonly persistableStateService = new PersistableStateService();
private readonly urlGeneratorsService = new UrlGeneratorsService();

public setup(core: CoreSetup): SharePluginSetup {
core.application.register(createShortUrlRedirectApp(core, window.location));
return {
...this.shareMenuRegistry.setup(),
persistableState: this.persistableStateService.setup(core),
urlGenerators: this.urlGeneratorsService.setup(core),
};
}

public start(core: CoreStart): SharePluginStart {
return {
...this.shareContextMenu.start(core, this.shareMenuRegistry.start()),
persistableState: this.persistableStateService.start(core),
urlGenerators: this.urlGeneratorsService.start(core),
};
}
}

/** @public */
export type SharePluginSetup = ShareMenuRegistrySetup & {
persistableState: PersistableStateSetup;
urlGenerators: UrlGeneratorsSetup;
};

/** @public */
export type SharePluginStart = ShareMenuManagerStart & {
persistableState: PersistableStateStart;
urlGenerators: UrlGeneratorsStart;
};

0 comments on commit a356286

Please sign in to comment.