mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-27 02:42:25 +08:00
feat: init @affine/copilot (#2511)
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`ProviderComposer 1`] = `
|
||||
<DocumentFragment>
|
||||
test1
|
||||
</DocumentFragment>
|
||||
`;
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* @vitest-environment happy-dom
|
||||
*/
|
||||
import { render } from '@testing-library/react';
|
||||
import type React from 'react';
|
||||
import { createContext, useContext } from 'react';
|
||||
import { expect, test } from 'vitest';
|
||||
|
||||
import { ProviderComposer } from '..';
|
||||
|
||||
test('ProviderComposer', async () => {
|
||||
const Context = createContext('null');
|
||||
const Provider: React.FC<React.PropsWithChildren> = ({ children }) => {
|
||||
return <Context.Provider value="test1">{children}</Context.Provider>;
|
||||
};
|
||||
const ConsumerComponent = () => {
|
||||
const value = useContext(Context);
|
||||
return <>{value}</>;
|
||||
};
|
||||
const Component = () => {
|
||||
return (
|
||||
<ProviderComposer contexts={[<Provider key={1} />]}>
|
||||
<ConsumerComponent />
|
||||
</ProviderComposer>
|
||||
);
|
||||
};
|
||||
|
||||
const result = render(<Component />);
|
||||
await result.findByText('test1');
|
||||
expect(result.asFragment()).toMatchSnapshot();
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
import type { FC, PropsWithChildren, ReactNode } from 'react';
|
||||
import { cloneElement } from 'react';
|
||||
|
||||
export const ProviderComposer: FC<
|
||||
PropsWithChildren<{
|
||||
contexts: any;
|
||||
}>
|
||||
> = ({ contexts, children }) =>
|
||||
contexts.reduceRight(
|
||||
(kids: ReactNode, parent: any) =>
|
||||
cloneElement(parent, {
|
||||
children: kids,
|
||||
}),
|
||||
children
|
||||
);
|
||||
28
packages/component/src/components/theme-provider/index.tsx
Normal file
28
packages/component/src/components/theme-provider/index.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import { ThemeProvider as NextThemeProvider, useTheme } from 'next-themes';
|
||||
import type { PropsWithChildren } from 'react';
|
||||
import { memo, useRef } from 'react';
|
||||
|
||||
const themes = ['dark', 'light'];
|
||||
|
||||
const DesktopThemeSync = memo(function DesktopThemeSync() {
|
||||
const { theme } = useTheme();
|
||||
const lastThemeRef = useRef(theme);
|
||||
const onceRef = useRef(false);
|
||||
if (lastThemeRef.current !== theme || !onceRef.current) {
|
||||
if (environment.isDesktop && theme) {
|
||||
window.apis?.ui.handleThemeChange(theme as 'dark' | 'light' | 'system');
|
||||
}
|
||||
lastThemeRef.current = theme;
|
||||
onceRef.current = true;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
export const ThemeProvider = ({ children }: PropsWithChildren) => {
|
||||
return (
|
||||
<NextThemeProvider themes={themes} enableSystem={true}>
|
||||
{children}
|
||||
<DesktopThemeSync />
|
||||
</NextThemeProvider>
|
||||
);
|
||||
};
|
||||
4
packages/env/package.json
vendored
4
packages/env/package.json
vendored
@@ -5,7 +5,7 @@
|
||||
"module": "./src/index.ts",
|
||||
"devDependencies": {
|
||||
"@blocksuite/global": "0.0.0-20230530061436-d0702cc0-nightly",
|
||||
"next": "^13.4.2",
|
||||
"next": "=13.4.2",
|
||||
"react": "18.3.0-canary-16d053d59-20230506",
|
||||
"react-dom": "18.3.0-canary-16d053d59-20230506",
|
||||
"zod": "^3.21.4"
|
||||
@@ -20,6 +20,8 @@
|
||||
"@blocksuite/global": "0.0.0-20230409084303-221991d4-nightly"
|
||||
},
|
||||
"dependencies": {
|
||||
"@affine/copilot": "workspace:*",
|
||||
"@toeverything/plugin-infra": "workspace:*",
|
||||
"lit": "^2.7.4"
|
||||
},
|
||||
"version": "0.5.4-beta.2"
|
||||
|
||||
7
packages/env/src/bootstrap.ts
vendored
Normal file
7
packages/env/src/bootstrap.ts
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import { config, getEnvironment, setupGlobal } from './config';
|
||||
|
||||
if (config.enablePlugin && !getEnvironment().isServer) {
|
||||
import('@affine/copilot');
|
||||
}
|
||||
|
||||
setupGlobal();
|
||||
1
packages/env/src/config.ts
vendored
1
packages/env/src/config.ts
vendored
@@ -12,6 +12,7 @@ export const buildFlagsSchema = z.object({
|
||||
* filter feature in the all pages.
|
||||
*/
|
||||
enableAllPageFilter: z.boolean(),
|
||||
enablePlugin: z.boolean(),
|
||||
enableImagePreviewModal: z.boolean(),
|
||||
enableTestProperties: z.boolean(),
|
||||
enableBroadCastChannelProvider: z.boolean(),
|
||||
|
||||
25
packages/plugin-infra/package.json
Normal file
25
packages/plugin-infra/package.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "@toeverything/plugin-infra",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "vite build"
|
||||
},
|
||||
"exports": {
|
||||
"./manager": "./src/manager.ts",
|
||||
"./type": "./src/type.ts",
|
||||
"./react": "./src/react/index.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@affine/component": "workspace:*",
|
||||
"@affine/env": "workspace:*",
|
||||
"@affine/workspace": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"jotai": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"jotai": "*",
|
||||
"react": "*",
|
||||
"react-dom": "*"
|
||||
}
|
||||
}
|
||||
50
packages/plugin-infra/src/manager.ts
Normal file
50
packages/plugin-infra/src/manager.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { DebugLogger } from '@affine/debug';
|
||||
import { rootStore } from '@affine/workspace/atom';
|
||||
import { atom } from 'jotai';
|
||||
|
||||
import type { AffinePlugin, Definition } from './type';
|
||||
import type { Loader, PluginUIAdapter } from './type';
|
||||
|
||||
// todo: for now every plugin is enabled by default
|
||||
export const affinePluginsAtom = atom<Record<string, AffinePlugin<string>>>({});
|
||||
|
||||
const pluginLogger = new DebugLogger('affine:plugin');
|
||||
import { config } from '@affine/env';
|
||||
export function definePlugin<ID extends string>(
|
||||
definition: Definition<ID>,
|
||||
uiAdapterLoader?: Loader<Partial<PluginUIAdapter>>
|
||||
) {
|
||||
if (!config.enablePlugin) {
|
||||
return;
|
||||
}
|
||||
const basePlugin = {
|
||||
definition,
|
||||
uiAdapter: {},
|
||||
};
|
||||
rootStore.set(affinePluginsAtom, plugins => ({
|
||||
...plugins,
|
||||
[definition.id]: basePlugin,
|
||||
}));
|
||||
if (uiAdapterLoader) {
|
||||
const updateAdapter = (adapter: Partial<PluginUIAdapter>) => {
|
||||
rootStore.set(affinePluginsAtom, plugins => ({
|
||||
...plugins,
|
||||
[definition.id]: {
|
||||
...basePlugin,
|
||||
uiAdapter: adapter,
|
||||
},
|
||||
}));
|
||||
};
|
||||
|
||||
uiAdapterLoader
|
||||
.load()
|
||||
.then(({ default: adapter }) => updateAdapter(adapter));
|
||||
if (import.meta.webpackHot) {
|
||||
uiAdapterLoader.hotModuleReload(async _ => {
|
||||
const adapter = (await _).default;
|
||||
updateAdapter(adapter);
|
||||
pluginLogger.info('[HMR] Plugin', definition.id, 'hot reloaded.');
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
23
packages/plugin-infra/src/react/context.tsx
Normal file
23
packages/plugin-infra/src/react/context.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import { ProviderComposer } from '@affine/component/provider-composer';
|
||||
import { ThemeProvider } from '@affine/component/theme-provider';
|
||||
import { rootStore } from '@affine/workspace/atom';
|
||||
import { Provider } from 'jotai';
|
||||
import type { PropsWithChildren } from 'react';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
export function AffinePluginContext(props: PropsWithChildren) {
|
||||
return (
|
||||
<ProviderComposer
|
||||
contexts={useMemo(
|
||||
() =>
|
||||
[
|
||||
<Provider key="JotaiProvider" store={rootStore} />,
|
||||
<ThemeProvider key="ThemeProvider" />,
|
||||
].filter(Boolean),
|
||||
[]
|
||||
)}
|
||||
>
|
||||
{props.children}
|
||||
</ProviderComposer>
|
||||
);
|
||||
}
|
||||
1
packages/plugin-infra/src/react/index.ts
Normal file
1
packages/plugin-infra/src/react/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './context';
|
||||
162
packages/plugin-infra/src/type.ts
Normal file
162
packages/plugin-infra/src/type.ts
Normal file
@@ -0,0 +1,162 @@
|
||||
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
|
||||
/// <reference path="./webpack-hmr.d.ts" />
|
||||
|
||||
/**
|
||||
* AFFiNE Plugin System Types
|
||||
*/
|
||||
|
||||
import type { WritableAtom } from 'jotai';
|
||||
import type { ReactElement } from 'react';
|
||||
import type { MosaicDirection, MosaicNode } from 'react-mosaic-component';
|
||||
|
||||
/**
|
||||
* A code loader interface of the plugin API.
|
||||
*
|
||||
* Plugin should be lazy-loaded. If a plugin is not enabled, it will not be loaded into the Mask.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const loader = {
|
||||
* load: () => import("./code"),
|
||||
* hotModuleReload: hot => import.meta.webpackHot && import.meta.webpackHot.accept('./code', () => hot(import("./code")))
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* The `./code` should use `export default` to export what loader expects.
|
||||
*/
|
||||
export interface Loader<DeferredModule> {
|
||||
/**
|
||||
* The `load()` function will be called on demand.
|
||||
*
|
||||
* It should not have side effects (e.g. start some daemon, start a new HTTP request or WebSocket client),
|
||||
* those work should be in the `.init()` function.
|
||||
* @returns the actual definition of this plugin
|
||||
* @example load: () => import('./path')
|
||||
*/
|
||||
load(): Promise<{
|
||||
default: DeferredModule;
|
||||
}>;
|
||||
|
||||
/**
|
||||
* This provides the functionality for hot module reload on the plugin.
|
||||
* When the callback is called, the old instance of the plugin will be unloaded, then the new instance will be init.
|
||||
* @example hotModuleReload: hot => import.meta.webpackHot && import.meta.webpackHot.accept('./path', () => hot(import('./path')))
|
||||
*/
|
||||
hotModuleReload(
|
||||
onHot: (
|
||||
hot: Promise<{
|
||||
default: DeferredModule;
|
||||
}>
|
||||
) => void
|
||||
): void;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface, @typescript-eslint/no-unused-vars
|
||||
interface AFFiNEPlugin {
|
||||
// todo: add more fields
|
||||
}
|
||||
|
||||
export interface I18NStringField {
|
||||
/** The i18n key of the string content. */
|
||||
i18nKey?: string;
|
||||
/** The fallback content to display if there is no i18n string found. */
|
||||
fallback: string;
|
||||
}
|
||||
|
||||
/** The publisher of the plugin */
|
||||
export interface Publisher {
|
||||
/** The name of the publisher */
|
||||
name: I18NStringField;
|
||||
/** URL of the publisher */
|
||||
link: string;
|
||||
}
|
||||
|
||||
/** For what stage the plugin */
|
||||
export enum ReleaseStage {
|
||||
NIGHTLY = 'nightly',
|
||||
PROD = 'prod',
|
||||
DEV = 'dev',
|
||||
}
|
||||
|
||||
export type ExpectedLayout =
|
||||
| {
|
||||
direction: MosaicDirection;
|
||||
// the first element is always the editor
|
||||
first: 'editor';
|
||||
second: MosaicNode<string>;
|
||||
// the percentage should be greater than 70
|
||||
splitPercentage?: number;
|
||||
}
|
||||
| 'editor';
|
||||
|
||||
type SetStateAction<Value> = Value | ((prev: Value) => Value);
|
||||
|
||||
export type ContentLayoutAtom = WritableAtom<
|
||||
ExpectedLayout,
|
||||
[SetStateAction<ExpectedLayout>],
|
||||
void
|
||||
>;
|
||||
|
||||
export type Definition<ID extends string> = {
|
||||
/**
|
||||
* ID of the plugin. It should be unique.
|
||||
* @example "com.affine.pro"
|
||||
*/
|
||||
id: ID;
|
||||
/**
|
||||
* The human-readable name of the plugin.
|
||||
* @example { i18nKey: "name", fallback: "Never gonna give you up" }
|
||||
*/
|
||||
name: I18NStringField;
|
||||
/**
|
||||
* A brief description of this plugin.
|
||||
* @example { i18nKey: "description", fallback: "This plugin is going to replace every link in the page to https://www.youtube.com/watch?v=dQw4w9WgXcQ" }
|
||||
*/
|
||||
description?: I18NStringField;
|
||||
/**
|
||||
* Publisher of this plugin.
|
||||
* @example { link: "https://affine.pro", name: { fallback: "AFFiNE", i18nKey: "org_name" } }
|
||||
*/
|
||||
publisher?: Publisher;
|
||||
|
||||
/**
|
||||
* The version of this plugin.
|
||||
* @example "1.0.0"
|
||||
*/
|
||||
version: string;
|
||||
|
||||
/**
|
||||
* The loader of this plugin.
|
||||
* @example ReleaseStage.PROD
|
||||
*/
|
||||
stage: ReleaseStage;
|
||||
};
|
||||
|
||||
// todo(himself65): support Vue.js
|
||||
export type Adapter<Props extends Record<string, unknown>> = (
|
||||
props: Props
|
||||
) => ReactElement;
|
||||
|
||||
export type AffinePluginContext = {
|
||||
toast: (text: string) => void;
|
||||
};
|
||||
|
||||
export type BaseProps = {
|
||||
contentLayoutAtom: ContentLayoutAtom;
|
||||
};
|
||||
|
||||
export type PluginUIAdapter = {
|
||||
sidebarItem: Adapter<BaseProps>;
|
||||
headerItem: Adapter<BaseProps>;
|
||||
detailContent: Adapter<BaseProps>;
|
||||
debugContent: Adapter<Record<string, unknown>>;
|
||||
};
|
||||
|
||||
export type PluginAdapterCreator = (
|
||||
context: AffinePluginContext
|
||||
) => PluginUIAdapter;
|
||||
|
||||
export type AffinePlugin<ID extends string> = {
|
||||
definition: Definition<ID>;
|
||||
uiAdapter: Partial<PluginUIAdapter>;
|
||||
};
|
||||
224
packages/plugin-infra/src/webpack-hmr.d.ts
vendored
Normal file
224
packages/plugin-infra/src/webpack-hmr.d.ts
vendored
Normal file
@@ -0,0 +1,224 @@
|
||||
// Copied from @types/webpack-env
|
||||
/**
|
||||
* Webpack module API - variables and global functions available inside modules
|
||||
*/
|
||||
|
||||
declare namespace __WebpackModuleApi {
|
||||
type ModuleId = any;
|
||||
interface HotNotifierInfo {
|
||||
type:
|
||||
| 'self-declined'
|
||||
| 'declined'
|
||||
| 'unaccepted'
|
||||
| 'accepted'
|
||||
| 'disposed'
|
||||
| 'accept-errored'
|
||||
| 'self-accept-errored'
|
||||
| 'self-accept-error-handler-errored';
|
||||
/**
|
||||
* The module in question.
|
||||
*/
|
||||
moduleId: number;
|
||||
/**
|
||||
* For errors: the module id owning the accept handler.
|
||||
*/
|
||||
dependencyId?: number | undefined;
|
||||
/**
|
||||
* For declined/accepted/unaccepted: the chain from where the update was propagated.
|
||||
*/
|
||||
chain?: number[] | undefined;
|
||||
/**
|
||||
* For declined: the module id of the declining parent
|
||||
*/
|
||||
parentId?: number | undefined;
|
||||
/**
|
||||
* For accepted: the modules that are outdated and will be disposed
|
||||
*/
|
||||
outdatedModules?: number[] | undefined;
|
||||
/**
|
||||
* For accepted: The location of accept handlers that will handle the update
|
||||
*/
|
||||
outdatedDependencies?:
|
||||
| {
|
||||
[dependencyId: number]: number[];
|
||||
}
|
||||
| undefined;
|
||||
/**
|
||||
* For errors: the thrown error
|
||||
*/
|
||||
error?: Error | undefined;
|
||||
/**
|
||||
* For self-accept-error-handler-errored: the error thrown by the module
|
||||
* before the error handler tried to handle it.
|
||||
*/
|
||||
originalError?: Error | undefined;
|
||||
}
|
||||
|
||||
interface Hot {
|
||||
/**
|
||||
* Accept code updates for the specified dependencies. The callback is called when dependencies were replaced.
|
||||
* @param dependencies
|
||||
* @param callback
|
||||
* @param errorHandler
|
||||
*/
|
||||
accept(
|
||||
dependencies: string[],
|
||||
callback?: (updatedDependencies: ModuleId[]) => void,
|
||||
errorHandler?: (err: Error) => void
|
||||
): void;
|
||||
/**
|
||||
* Accept code updates for the specified dependencies. The callback is called when dependencies were replaced.
|
||||
* @param dependency
|
||||
* @param callback
|
||||
* @param errorHandler
|
||||
*/
|
||||
accept(
|
||||
dependency: string,
|
||||
callback?: () => void,
|
||||
errorHandler?: (err: Error) => void
|
||||
): void;
|
||||
/**
|
||||
* Accept code updates for this module without notification of parents.
|
||||
* This should only be used if the module doesn’t export anything.
|
||||
* The errHandler can be used to handle errors that occur while loading the updated module.
|
||||
* @param errHandler
|
||||
*/
|
||||
accept(errHandler?: (err: Error) => void): void;
|
||||
/**
|
||||
* Do not accept updates for the specified dependencies. If any dependencies is updated, the code update fails with code "decline".
|
||||
*/
|
||||
decline(dependencies: string[]): void;
|
||||
/**
|
||||
* Do not accept updates for the specified dependencies. If any dependencies is updated, the code update fails with code "decline".
|
||||
*/
|
||||
decline(dependency: string): void;
|
||||
/**
|
||||
* Flag the current module as not update-able. If updated the update code would fail with code "decline".
|
||||
*/
|
||||
decline(): void;
|
||||
/**
|
||||
* Add a one time handler, which is executed when the current module code is replaced.
|
||||
* Here you should destroy/remove any persistent resource you have claimed/created.
|
||||
* If you want to transfer state to the new module, add it to data object.
|
||||
* The data will be available at module.hot.data on the new module.
|
||||
* @param callback
|
||||
*/
|
||||
dispose(callback: (data: any) => void): void;
|
||||
dispose(callback: <T>(data: T) => void): void;
|
||||
/**
|
||||
* Add a one time handler, which is executed when the current module code is replaced.
|
||||
* Here you should destroy/remove any persistent resource you have claimed/created.
|
||||
* If you want to transfer state to the new module, add it to data object.
|
||||
* The data will be available at module.hot.data on the new module.
|
||||
* @param callback
|
||||
*/
|
||||
addDisposeHandler(callback: (data: any) => void): void;
|
||||
addDisposeHandler<T>(callback: (data: T) => void): void;
|
||||
/**
|
||||
* Remove a handler.
|
||||
* This can useful to add a temporary dispose handler. You could i. e. replace code while in the middle of a multi-step async function.
|
||||
* @param callback
|
||||
*/
|
||||
removeDisposeHandler(callback: (data: any) => void): void;
|
||||
removeDisposeHandler<T>(callback: (data: T) => void): void;
|
||||
/**
|
||||
* Throws an exceptions if status() is not idle.
|
||||
* Check all currently loaded modules for updates and apply updates if found.
|
||||
* If no update was found, the callback is called with null.
|
||||
* If autoApply is truthy the callback will be called with all modules that were disposed.
|
||||
* apply() is automatically called with autoApply as options parameter.
|
||||
* If autoApply is not set the callback will be called with all modules that will be disposed on apply().
|
||||
* @param autoApply
|
||||
* @param callback
|
||||
*/
|
||||
check(
|
||||
autoApply: boolean,
|
||||
callback: (err: Error, outdatedModules: ModuleId[]) => void
|
||||
): void;
|
||||
/**
|
||||
* Throws an exceptions if status() is not idle.
|
||||
* Check all currently loaded modules for updates and apply updates if found.
|
||||
* If no update was found, the callback is called with null.
|
||||
* The callback will be called with all modules that will be disposed on apply().
|
||||
* @param callback
|
||||
*/
|
||||
check(callback: (err: Error, outdatedModules: ModuleId[]) => void): void;
|
||||
/**
|
||||
* If status() != "ready" it throws an error.
|
||||
* Continue the update process.
|
||||
* @param options
|
||||
* @param callback
|
||||
*/
|
||||
apply(
|
||||
options: AcceptOptions,
|
||||
callback: (err: Error, outdatedModules: ModuleId[]) => void
|
||||
): void;
|
||||
/**
|
||||
* If status() != "ready" it throws an error.
|
||||
* Continue the update process.
|
||||
* @param callback
|
||||
*/
|
||||
apply(callback: (err: Error, outdatedModules: ModuleId[]) => void): void;
|
||||
/**
|
||||
* Return one of idle, check, watch, watch-delay, prepare, ready, dispose, apply, abort or fail.
|
||||
*/
|
||||
status(): string;
|
||||
/** Register a callback on status change. */
|
||||
status(callback: (status: string) => void): void;
|
||||
/** Register a callback on status change. */
|
||||
addStatusHandler(callback: (status: string) => void): void;
|
||||
/**
|
||||
* Remove a registered status change handler.
|
||||
* @param callback
|
||||
*/
|
||||
removeStatusHandler(callback: (status: string) => void): void;
|
||||
|
||||
active: boolean;
|
||||
data: any;
|
||||
}
|
||||
|
||||
interface AcceptOptions {
|
||||
/**
|
||||
* If true the update process continues even if some modules are not accepted (and would bubble to the entry point).
|
||||
*/
|
||||
ignoreUnaccepted?: boolean | undefined;
|
||||
/**
|
||||
* Ignore changes made to declined modules.
|
||||
*/
|
||||
ignoreDeclined?: boolean | undefined;
|
||||
/**
|
||||
* Ignore errors throw in accept handlers, error handlers and while reevaluating module.
|
||||
*/
|
||||
ignoreErrored?: boolean | undefined;
|
||||
/**
|
||||
* Notifier for declined modules.
|
||||
*/
|
||||
onDeclined?: ((info: HotNotifierInfo) => void) | undefined;
|
||||
/**
|
||||
* Notifier for unaccepted modules.
|
||||
*/
|
||||
onUnaccepted?: ((info: HotNotifierInfo) => void) | undefined;
|
||||
/**
|
||||
* Notifier for accepted modules.
|
||||
*/
|
||||
onAccepted?: ((info: HotNotifierInfo) => void) | undefined;
|
||||
/**
|
||||
* Notifier for disposed modules.
|
||||
*/
|
||||
onDisposed?: ((info: HotNotifierInfo) => void) | undefined;
|
||||
/**
|
||||
* Notifier for errors.
|
||||
*/
|
||||
onErrored?: ((info: HotNotifierInfo) => void) | undefined;
|
||||
/**
|
||||
* Indicates that apply() is automatically called by check function
|
||||
*/
|
||||
autoApply?: boolean | undefined;
|
||||
}
|
||||
}
|
||||
interface ImportMeta {
|
||||
/**
|
||||
* `import.meta.webpackHot` is an alias for` module.hot` which is also available in strict ESM
|
||||
*/
|
||||
webpackHot?: __WebpackModuleApi.Hot | undefined;
|
||||
}
|
||||
9
packages/plugin-infra/tsconfig.json
Normal file
9
packages/plugin-infra/tsconfig.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"include": ["./src"],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.node.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
9
packages/plugin-infra/tsconfig.node.json
Normal file
9
packages/plugin-infra/tsconfig.node.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
@@ -37,7 +37,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/ws": "^8.5.4",
|
||||
"next": "^13.4.2",
|
||||
"next": "=13.4.2",
|
||||
"ws": "^8.13.0"
|
||||
},
|
||||
"version": "0.5.4-beta.2"
|
||||
|
||||
Reference in New Issue
Block a user