Skip to content
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: Merge channels into a single package #23032

Merged
merged 11 commits into from
Jun 13, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export async function generateAddonSetupCode() {
return `
import { createChannel as createPostMessageChannel } from '@storybook/channel-postmessage';
import { createPostMessageChannel } from '@storybook/channels';
import { addons } from '@storybook/preview-api';

const channel = createPostMessageChannel({ page: 'preview' });
Expand Down
1 change: 1 addition & 0 deletions code/builders/builder-vite/src/optimizeDeps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const INCLUDE_CANDIDATES = [
'@storybook/addon-docs > acorn-jsx',
'@storybook/addon-docs',
'@storybook/addon-essentials/docs/mdx-react-shim',
'@storybook/channels',
'@storybook/channel-postmessage',
'@storybook/channel-websocket',
'@storybook/client-api',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { global } from '@storybook/global';

import { ClientApi, PreviewWeb, addons, composeConfigs } from '@storybook/preview-api';
import { createChannel as createPostMessageChannel } from '@storybook/channel-postmessage';
import { createPostMessageChannel } from '@storybook/channels';

import { importFn } from './{{storiesFilename}}';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,16 @@
"sideEffects": false,
"exports": {
".": {
"types": "./dist/index.d.ts",
"node": "./dist/index.js",
"require": "./dist/index.js",
"import": "./dist/index.mjs"
"types": "./dist/entry.d.ts",
"node": "./dist/entry.js",
"require": "./dist/entry.js",
"import": "./dist/entry.mjs"
},
"./package.json": "./package.json"
},
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"main": "dist/entry.js",
"module": "dist/entry.mjs",
"types": "dist/entry.d.ts",
"files": [
"dist/**/*",
"README.md",
Expand All @@ -43,14 +43,8 @@
"prep": "../../../scripts/prepare/bundle.ts"
},
"dependencies": {
"@storybook/channel-websocket": "7.1.0-alpha.31",
"@storybook/channels": "7.1.0-alpha.31",
"@storybook/client-logger": "7.1.0-alpha.31",
"@storybook/core-events": "7.1.0-alpha.31",
"@storybook/global": "^5.0.0",
"qs": "^6.10.0",
"telejson": "^7.0.3",
"tiny-invariant": "^1.3.1"
"@storybook/client-logger": "7.1.0-alpha.31"
},
"devDependencies": {
"typescript": "~4.9.3"
Expand All @@ -60,8 +54,9 @@
},
"bundler": {
"entries": [
"./src/index.ts"
]
"./src/entry.ts"
],
"shim": "@storybook/channels/dist/postmessage/index"
},
"gitHead": "e6a7fd8a655c69780bc20b9749c2699e44beae16"
}
7 changes: 7 additions & 0 deletions code/deprecated/channel-postmessage/src/entry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { deprecate } from '@storybook/client-logger';

deprecate(
'importing from @storybook/channel-postmessage is deprecated and will be removed in 8.0, please import createPostmessageChannel from @storybook/channels'
);

export * from '@storybook/channels/dist/postmessage/index';
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,16 @@
"sideEffects": false,
"exports": {
".": {
"types": "./dist/index.d.ts",
"node": "./dist/index.js",
"require": "./dist/index.js",
"import": "./dist/index.mjs"
"types": "./dist/entry.d.ts",
"node": "./dist/entry.js",
"require": "./dist/entry.js",
"import": "./dist/entry.mjs"
},
"./package.json": "./package.json"
},
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"main": "dist/entry.js",
"module": "dist/entry.mjs",
"types": "dist/entry.d.ts",
"files": [
"dist/**/*",
"README.md",
Expand All @@ -40,14 +40,11 @@
],
"scripts": {
"check": "../../../scripts/node_modules/.bin/tsc --noEmit",
"prep": "../../../scripts/prepare/bundle.ts"
"prep": "../../../scripts/prepare/facade.ts"
},
"dependencies": {
"@storybook/channels": "7.1.0-alpha.31",
"@storybook/client-logger": "7.1.0-alpha.31",
"@storybook/global": "^5.0.0",
"telejson": "^7.0.3",
"tiny-invariant": "^1.3.1"
"@storybook/client-logger": "7.1.0-alpha.31"
},
"devDependencies": {
"typescript": "~4.9.3"
Expand All @@ -57,8 +54,9 @@
},
"bundler": {
"entries": [
"./src/index.ts"
]
"./src/entry.ts"
],
"shim": "@storybook/channels/dist/websocket/index"
},
"gitHead": "e6a7fd8a655c69780bc20b9749c2699e44beae16"
}
7 changes: 7 additions & 0 deletions code/deprecated/channel-websocket/src/entry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { deprecate } from '@storybook/client-logger';

deprecate(
'importing from @storybook/channel-websocket is deprecated and will be removed in 8.0, please import createWebsocketChannel from @storybook/channels'
);

export * from '@storybook/channels/dist/websocket/index';
2 changes: 0 additions & 2 deletions code/lib/channel-websocket/src/typings.d.ts

This file was deleted.

38 changes: 37 additions & 1 deletion code/lib/channels/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,36 @@
"require": "./dist/index.js",
"import": "./dist/index.mjs"
},
"./dist/postmessage/index": {
"types": "./dist/postmessage/index.d.ts",
"node": "./dist/postmessage/index.js",
"require": "./dist/postmessage/index.js",
"import": "./dist/postmessage/index.mjs"
},
"./dist/websocket/index": {
"types": "./dist/websocket/index.d.ts",
"node": "./dist/websocket/index.js",
"require": "./dist/websocket/index.js",
"import": "./dist/websocket/index.mjs"
},
"./package.json": "./package.json"
},
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"typesVersions": {
"*": {
"*": [
"dist/index.d.ts"
],
"dist/postmessage/index": [
"dist/postmessage/index.d.ts"
],
"dist/websocket/index": [
"dist/websocket/index.d.ts"
]
}
},
"files": [
"dist/**/*",
"README.md",
Expand All @@ -42,6 +67,15 @@
"check": "../../../scripts/node_modules/.bin/tsc --noEmit",
"prep": "../../../scripts/prepare/bundle.ts"
},
"dependencies": {
"@storybook/channels": "7.1.0-alpha.31",
"@storybook/client-logger": "7.1.0-alpha.31",
"@storybook/core-events": "7.1.0-alpha.31",
"@storybook/global": "^5.0.0",
"qs": "^6.10.0",
"telejson": "^7.0.3",
"tiny-invariant": "^1.3.1"
},
"devDependencies": {
"typescript": "~4.9.3"
},
Expand All @@ -50,7 +84,9 @@
},
"bundler": {
"entries": [
"./src/index.ts"
"./src/index.ts",
"./src/postmessage/index.ts",
"./src/websocket/index.ts"
]
},
"gitHead": "e6a7fd8a655c69780bc20b9749c2699e44beae16"
Expand Down
174 changes: 7 additions & 167 deletions code/lib/channels/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,171 +1,11 @@
/// <reference types="node" />
/* eslint-disable @typescript-eslint/triple-slash-reference */
/// <reference path="./typings.d.ts" />

export type ChannelHandler = (event: ChannelEvent) => void;
import { Channel } from './main';

export interface ChannelTransport {
send(event: ChannelEvent, options?: any): void;
setHandler(handler: ChannelHandler): void;
}

export interface ChannelEvent {
type: string; // eventName
from: string;
args: any[];
}

export interface Listener {
(...args: any[]): void;
}

interface EventsKeyValue {
[key: string]: Listener[];
}

type ChannelArgs = ChannelArgsSingle | ChannelArgsMulti;
interface ChannelArgsSingle {
transport?: ChannelTransport;
async?: boolean;
}
interface ChannelArgsMulti {
transports: ChannelTransport[];
async?: boolean;
}

const isMulti = (args: ChannelArgs): args is ChannelArgsMulti => {
// @ts-expect-error (we guard against this right here)
return args.transports !== undefined;
};

const generateRandomId = () => {
// generates a random 13 character string
return Math.random().toString(16).slice(2);
};

export class Channel {
readonly isAsync: boolean;

private sender = generateRandomId();

private events: EventsKeyValue = {};

private data: Record<string, any> = {};

private readonly transports: ChannelTransport[] = [];

constructor(input: ChannelArgsMulti);
constructor(input: ChannelArgsSingle);
constructor(input: ChannelArgs = {}) {
this.isAsync = input.async || false;

if (isMulti(input)) {
this.transports = input.transports || [];

this.transports.forEach((t) => {
t.setHandler((event) => this.handleEvent(event));
});
} else {
this.transports = input.transport ? [input.transport] : [];
}

this.transports.forEach((t) => {
t.setHandler((event) => this.handleEvent(event));
});
}

get hasTransport() {
return this.transports.length > 0;
}

addListener(eventName: string, listener: Listener) {
this.events[eventName] = this.events[eventName] || [];
this.events[eventName].push(listener);
}

emit(eventName: string, ...args: any) {
const event: ChannelEvent = { type: eventName, args, from: this.sender };
let options = {};
if (args.length >= 1 && args[0] && args[0].options) {
options = args[0].options;
}

const handler = () => {
this.transports.forEach((t) => {
t.send(event, options);
});
this.handleEvent(event);
};

if (this.isAsync) {
// todo I'm not sure how to test this
setImmediate(handler);
} else {
handler();
}
}

last(eventName: string) {
return this.data[eventName];
}

eventNames() {
return Object.keys(this.events);
}

listenerCount(eventName: string) {
const listeners = this.listeners(eventName);
return listeners ? listeners.length : 0;
}

listeners(eventName: string): Listener[] | undefined {
const listeners = this.events[eventName];
return listeners || undefined;
}

once(eventName: string, listener: Listener) {
const onceListener: Listener = this.onceListener(eventName, listener);
this.addListener(eventName, onceListener);
}

removeAllListeners(eventName?: string) {
if (!eventName) {
this.events = {};
} else if (this.events[eventName]) {
delete this.events[eventName];
}
}

removeListener(eventName: string, listener: Listener) {
const listeners = this.listeners(eventName);
if (listeners) {
this.events[eventName] = listeners.filter((l) => l !== listener);
}
}

on(eventName: string, listener: Listener) {
this.addListener(eventName, listener);
}

off(eventName: string, listener: Listener) {
this.removeListener(eventName, listener);
}

private handleEvent(event: ChannelEvent) {
const listeners = this.listeners(event.type);
if (listeners && listeners.length) {
listeners.forEach((fn) => {
fn.apply(event, event.args);
});
}
this.data[event.type] = event.args;
}

private onceListener(eventName: string, listener: Listener) {
const onceListener: Listener = (...args: any[]) => {
this.removeListener(eventName, onceListener);
return listener(...args);
};
return onceListener;
}
}
export * from './main';

export default Channel;

export { createChannel as createPostMessageChannel } from './postmessage';
export { createChannel as createWebSocketChannel } from './websocket';
Loading