Skip to content

Commit

Permalink
Merge pull request #30277 from storybookjs/version-non-patch-from-8.6…
Browse files Browse the repository at this point in the history
….0-alpha.0

Release: Prerelease 8.6.0-alpha.1
  • Loading branch information
shilman authored Jan 22, 2025
2 parents 89631e6 + f644ad9 commit c479037
Show file tree
Hide file tree
Showing 64 changed files with 4,314 additions and 1,523 deletions.
7 changes: 4 additions & 3 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -174,12 +174,13 @@ jobs:
git commit -m "Update CHANGELOG.md for v${{ steps.version.outputs.current-version }} [skip ci]" || true
git push origin next
# TODO: remove this step - @JReinhold
# Sync the next.json version file to the main branch so it gets deployed to the docs site
# but only if this is a prerelease, because in minor/major releases we're already force pushing next-release onto main, so it's already there
- name: Sync version JSONs from `next-release` to `main`
if: github.ref_name == 'next-release'
if: github.ref_name == 'next-release' && steps.is-prerelease.outputs.prerelease == 'true'
working-directory: .
run: |
VERSION_FILE="./docs/versions/${{ steps.is-prerelease.outputs.prerelease == 'true' && 'next' || 'latest' }}.json"
VERSION_FILE="./docs/versions/next.json"
git fetch origin main
git checkout main
git pull
Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.prerelease.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
## 8.6.0-alpha.1

- Addon Test: Replace `interaction test` -> `component test` - [#30333](https://github.com/storybookjs/storybook/pull/30333), thanks @kylegach!
- Angular: Fix accent character issue - [#30276](https://github.com/storybookjs/storybook/pull/30276), thanks @valentinpalkovic!
- Angular: Support experimental zoneless mode - [#28657](https://github.com/storybookjs/storybook/pull/28657), thanks @anedomansky!
- CLI: Use correct storybook internals import in automigration - [#30290](https://github.com/storybookjs/storybook/pull/30290), thanks @yannbf!
- Core: Add connection timeout notification - [#30288](https://github.com/storybookjs/storybook/pull/30288), thanks @valentinpalkovic!
- Csf Tools: Allow ConfigFile to create more import syntaxes - [#30204](https://github.com/storybookjs/storybook/pull/30204), thanks @yannbf!
- Manager: Escape single quotes in dynamic import paths in wrapManagerEntries function - [#30278](https://github.com/storybookjs/storybook/pull/30278), thanks @valentinpalkovic!
- RNW-Vite: Support requires for images/fonts - [#30305](https://github.com/storybookjs/storybook/pull/30305), thanks @dannyhw!

## 8.6.0-alpha.0


Expand Down
37 changes: 34 additions & 3 deletions MIGRATION.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<h1>Migration</h1>

- [From version 8.4.x to 8.5.x](#from-version-84x-to-85x)
- [Introducing features.developmentModeForBuild](#introducing-featuresdevelopmentmodeforbuild)
- [From version 8.5.x to 8.6.x](#from-version-85x-to-86x)
- [Angular: Support experimental zoneless support](#angular-support-experimental-zoneless-support)
- [Added source code panel to docs](#added-source-code-panel-to-docs)
- [Addon-a11y: Component test integration](#addon-a11y-component-test-integration)
- [Addon-a11y: Changing the default element selector](#addon-a11y-changing-the-default-element-selector)
Expand Down Expand Up @@ -427,6 +427,37 @@
- [Packages renaming](#packages-renaming)
- [Deprecated embedded addons](#deprecated-embedded-addons)

## From version 8.5.x to 8.6.x

### Angular: Support experimental zoneless support

Storybook now supports [Angular's experimental zoneless mode](https://angular.dev/guide/experimental/zoneless). This mode is intended to improve performance by removing Angular's zone.js dependency. To enable zoneless mode in your Angular Storybook, set the `experimentalZoneless` config in your `angular.json` file:

````diff
{
"projects": {
"your-project": {
"architect": {
"storybook": {
...
"options": {
...
+ "experimentalZoneless": true
}
}
"build-storybook": {
...
"options": {
...
+ "experimentalZoneless": true
}
}
}
}
}
}
```

## From version 8.4.x to 8.5.x

### Introducing features.developmentModeForBuild
Expand All @@ -442,7 +473,7 @@ export default {
developmentModeForBuild: true,
},
};
```
````

### Added source code panel to docs

Expand Down
4 changes: 2 additions & 2 deletions code/addons/test/src/components/EmptyState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ export const Empty = () => {

return (
<EmptyTabContent
title="Interaction testing"
title="Component testing"
description={
<>
Interaction tests allow you to verify the functional aspects of UIs. Write a play function
Component tests allow you to verify the functional aspects of UIs. Write a play function
for your story and you&apos;ll see it run here.
</>
}
Expand Down
1 change: 1 addition & 0 deletions code/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@
},
"dependencies": {
"@storybook/csf": "0.1.12",
"@storybook/theming": "workspace:*",
"better-opn": "^3.0.2",
"browser-assert": "^1.2.1",
"esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0",
Expand Down
2 changes: 1 addition & 1 deletion code/core/scripts/entries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,6 @@ export const getFinals = (cwd: string) => {

return [
//
define('src/manager/runtime.ts', ['browser'], false),
define('src/manager/runtime.tsx', ['browser'], false),
];
};
6 changes: 3 additions & 3 deletions code/core/scripts/helpers/generateTypesMapperFiles.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { existsSync } from 'node:fs';
import { mkdir, writeFile } from 'node:fs/promises';
import { dirname, join, relative } from 'node:path';
import { dirname, join, relative, sep } from 'node:path';

import { dedent } from '../../../../scripts/prepare/tools';
import type { getEntries } from '../entries';
Expand All @@ -13,8 +13,8 @@ async function generateTypesMapperContent(filePath: string) {

return dedent`
// auto generated file from ${__filename}, do not edit
export * from '${join(upwards, downwards)}';
export type * from '${join(upwards, downwards)}';
export * from '${join(upwards, downwards).replaceAll(sep, '/')}';
export type * from '${join(upwards, downwards).replaceAll(sep, '/')}';
`;
}

Expand Down
3 changes: 2 additions & 1 deletion code/core/src/builder-manager/utils/managerEntries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ export async function wrapManagerEntries(entrypoints: string[], uniqueId?: strin
const directory = dirname(location);
await mkdir(directory, { recursive: true });
}
await writeFile(location, `import '${slash(entry)}';`);

await writeFile(location, `import '${slash(entry).replaceAll(/'/g, "\\'")}';`);

return location;
})
Expand Down
11 changes: 8 additions & 3 deletions code/core/src/channels/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const MockedWebsocket = vi.hoisted(() => {

onerror: (e: any) => void;

onclose: () => void;
onclose: (event: any) => void;

constructor(url: string) {
this.onopen = vi.fn();
Expand Down Expand Up @@ -293,11 +293,16 @@ describe('WebsocketTransport', () => {
});

transport.setHandler(handler);
MockedWebsocket.ref.current.onclose();
MockedWebsocket.ref.current.onclose({ code: 1000, reason: 'test' });

expect(handler.mock.calls[0][0]).toMatchInlineSnapshot(`
{
"args": [],
"args": [
{
"code": 1000,
"reason": "test",
},
],
"from": "preview",
"type": "channelWSDisconnect",
}
Expand Down
2 changes: 1 addition & 1 deletion code/core/src/channels/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export * from './main';
export default Channel;

export { PostMessageTransport } from './postmessage';
export { WebsocketTransport } from './websocket';
export { WebsocketTransport, HEARTBEAT_INTERVAL, HEARTBEAT_MAX_LATENCY } from './websocket';

type Options = Config & {
extraTransports?: ChannelTransport[];
Expand Down
40 changes: 34 additions & 6 deletions code/core/src/channels/websocket/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ interface WebsocketTransportArgs extends Partial<Config> {
onError: OnError;
}

export const HEARTBEAT_INTERVAL = 15000;
export const HEARTBEAT_MAX_LATENCY = 5000;

export class WebsocketTransport implements ChannelTransport {
private buffer: string[] = [];

Expand All @@ -26,25 +29,48 @@ export class WebsocketTransport implements ChannelTransport {

private isReady = false;

private isClosed = false;

private pingTimeout: number | NodeJS.Timeout = 0;

private heartbeat() {
clearTimeout(this.pingTimeout);

this.pingTimeout = setTimeout(() => {
this.socket.close(3008, 'timeout');
}, HEARTBEAT_INTERVAL + HEARTBEAT_MAX_LATENCY);
}

constructor({ url, onError, page }: WebsocketTransportArgs) {
this.socket = new WebSocket(url);
this.socket.onopen = () => {
this.isReady = true;
this.heartbeat();
this.flush();
};
this.socket.onmessage = ({ data }) => {
const event = typeof data === 'string' && isJSON(data) ? parse(data) : data;
invariant(this.handler, 'WebsocketTransport handler should be set');
this.handler(event);
if (event.type === 'ping') {
this.heartbeat();
this.send({ type: 'pong' });
}
};
this.socket.onerror = (e) => {
if (onError) {
onError(e);
}
};
this.socket.onclose = () => {
this.socket.onclose = (ev) => {
invariant(this.handler, 'WebsocketTransport handler should be set');
this.handler({ type: EVENTS.CHANNEL_WS_DISCONNECT, args: [], from: page || 'preview' });
this.handler({
type: EVENTS.CHANNEL_WS_DISCONNECT,
args: [{ reason: ev.reason, code: ev.code }],
from: page || 'preview',
});
this.isClosed = true;
clearTimeout(this.pingTimeout);
};
}

Expand All @@ -53,10 +79,12 @@ export class WebsocketTransport implements ChannelTransport {
}

send(event: any) {
if (!this.isReady) {
this.sendLater(event);
} else {
this.sendNow(event);
if (!this.isClosed) {
if (!this.isReady) {
this.sendLater(event);
} else {
this.sendNow(event);
}
}
}

Expand Down
38 changes: 37 additions & 1 deletion code/core/src/core-server/utils/get-server-channel.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ChannelHandler } from '@storybook/core/channels';
import { Channel } from '@storybook/core/channels';
import { Channel, HEARTBEAT_INTERVAL } from '@storybook/core/channels';

import { isJSON, parse, stringify } from 'telejson';
import WebSocket, { WebSocketServer } from 'ws';
Expand All @@ -17,7 +17,15 @@ export class ServerChannelTransport {

private handler?: ChannelHandler;

isAlive = false;

private heartbeat() {
this.isAlive = true;
}

constructor(server: Server) {
this.heartbeat = this.heartbeat.bind(this);

this.socket = new WebSocketServer({ noServer: true });

server.on('upgrade', (request, socket, head) => {
Expand All @@ -28,14 +36,42 @@ export class ServerChannelTransport {
}
});
this.socket.on('connection', (wss) => {
this.isAlive = true;
wss.on('message', (raw) => {
const data = raw.toString();
const event =
typeof data === 'string' && isJSON(data)
? parse(data, { allowFunction: false, allowClass: false })
: data;
this.handler?.(event);
if (event.type === 'pong') {
this.heartbeat();
}
});
});

const interval = setInterval(() => {
this.socket.clients.forEach((ws) => {
if (this.isAlive === false) {
return ws.terminate();
}

this.isAlive = false;
this.send({ type: 'ping' });
});
}, HEARTBEAT_INTERVAL);

this.socket.on('close', function close() {
clearInterval(interval);
});

process.on('SIGTERM', () => {
this.socket.clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.close(1001, 'Server is shutting down');
}
});
this.socket.close(() => process.exit(0));
});
}

Expand Down
18 changes: 18 additions & 0 deletions code/core/src/csf-tools/ConfigFile.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1146,6 +1146,24 @@ describe('ConfigFile', () => {
export default config;
`);
});

it(`supports setting a namespaced import`, () => {
const config = loadConfig('').parse();
config.setImport({ namespace: 'path' }, 'path');

const parsed = babelPrint(config._ast);

expect(parsed).toMatchInlineSnapshot(`import * as path from 'path';`);
});

it(`supports setting import without specifier`, () => {
const config = loadConfig('').parse();
config.setImport(null, 'path');

const parsed = babelPrint(config._ast);

expect(parsed).toMatchInlineSnapshot(`import 'path';`);
});
});

describe('setRequireImport', () => {
Expand Down
Loading

0 comments on commit c479037

Please sign in to comment.