import { Failure, fold, Initialized, Pending, RemoteData, Success } from '@abraham/remotedata'; import { html, property, Seed, svg, TemplateResult } from '@nutmeg/seed'; import { Api } from './api'; import { FailureView } from './failure.view'; import { PendingView } from './pending.view'; import { DEFAULT_INSTALL_SOURCE, InstallSource, Pkg } from './pkg'; import { SuccessView } from './success.view'; interface SuccessData { pkg: Pkg, selectedTab: InstallSource, } type State = RemoteData; export class NodePackage extends Seed { @property({ type: Boolean }) public global: boolean = false; @property({ type: String }) public name?: string; private api = new Api(); private state: State = new Initialized(); constructor() { super(); } /** The component instance has been inserted into the DOM. */ public connectedCallback() { super.connectedCallback(); } /** The component instance has been removed from the DOM. */ public disconnectedCallback() { super.disconnectedCallback(); } /** Watch for changes to these attributes. */ public static get observedAttributes(): string[] { return super.observedAttributes; } /** Rerender when the observed attributes change. */ public attributeChangedCallback(name: string, oldValue: any, newValue: any) { super.attributeChangedCallback(name, oldValue, newValue); } /** Styling for the component. */ public get styles(): TemplateResult { return html` `; } public get logo(): TemplateResult { return svg` `; } private get header(): TemplateResult { if (this.name) { return html` `; } else { return html` `; } } /** HTML Template for the component. */ public get template(): TemplateResult { return html`
${this.header} ${this.view(this.state)}
`; } public set selectedTab(tab: InstallSource) { if (this.state instanceof Success) { this.state.data.selectedTab = tab; } } private pendingHandler(): TemplateResult { return new PendingView().content; } private initializedHandler(): TemplateResult { if (this.name) { this.fetchPackage(); return this.pendingHandler() } else { return new FailureView('Missing required value "name"').content; } } private errorHandler(error: string): TemplateResult { if (this.updateData) { this.fetchPackage(); } return new FailureView(error).content; } private successHandler(data: SuccessData): TemplateResult { if (this.updateData) { this.fetchPackage(); } return new SuccessView(this, data.pkg, data.selectedTab).content; } private get view(): (state: State) => TemplateResult { return fold( () => this.initializedHandler(), () => this.pendingHandler(), (error: string) => this.errorHandler(error), (data: SuccessData) => this.successHandler(data), ); } private async fetchPackage(): Promise { if (this.name) { this.state = new Pending(); try { const pkg = new Pkg(await this.api.fetch(this.name)); this.state = new Success({ selectedTab: DEFAULT_INSTALL_SOURCE, pkg }); } catch (error) { this.state = new Failure(error); } this.render(); } } private get updateData(): boolean { return this.state instanceof Success && this.state.data.pkg.name !== this.name; } } window.customElements.define('node-package', NodePackage);