Kaynağa Gözat

feat: demo add customService

xiamidaxia 9 ay önce
ebeveyn
işleme
aed1695396

+ 6 - 0
apps/demo-fixed-layout/rsbuild.config.ts

@@ -7,6 +7,12 @@ export default defineConfig({
     entry: {
       index: './src/app.tsx',
     },
+    /**
+     * support inversify @injectable() and @inject decorators
+     */
+    decorators: {
+      version: 'legacy',
+    },
   },
   html: {
     title: 'demo-fixed-layout',

+ 7 - 0
apps/demo-fixed-layout/src/hooks/use-editor-props.ts

@@ -13,6 +13,7 @@ import {
 
 import { type FlowNodeRegistry } from '../typings';
 import { shortcutGetter } from '../shortcuts';
+import { CustomService } from '../services';
 import { GroupBoxHeader, GroupNode } from '../plugins/group-plugin';
 import { createSyncVariablePlugin, createClipboardPlugin } from '../plugins';
 import { defaultFormMeta } from '../nodes';
@@ -161,6 +162,12 @@ export function useEditorProps(
           'loop-traverse-text': 'Loop',
         },
       },
+      /**
+       * Bind custom service
+       */
+      onBind: ({ bind }) => {
+        bind(CustomService).toSelf().inSingletonScope();
+      },
       /**
        * Playground init
        */

+ 42 - 0
apps/demo-fixed-layout/src/services/custom-service.ts

@@ -0,0 +1,42 @@
+import { injectable, inject } from '@flowgram.ai/fixed-layout-editor';
+import {
+  FixedLayoutPluginContext,
+  SelectionService,
+  Playground,
+  FlowDocument,
+} from '@flowgram.ai/fixed-layout-editor';
+
+/**
+ * Docs: https://inversify.io/docs/introduction/getting-started/
+ * Warning: Use decorator legacy
+ *   // rsbuild.config.ts
+ *   {
+ *     source: {
+ *       decorators: {
+ *         version: 'legacy'
+ *       }
+ *     }
+ *   }
+ * Usage:
+ *  1.
+ *    const myService = useService(CustomService)
+ *    myService.save()
+ *  2.
+ *    const myService = useClientContext().get(CustomService)
+ *  3.
+ *    const myService = node.getService(CustomService)
+ */
+@injectable()
+export class CustomService {
+  @inject(FixedLayoutPluginContext) ctx: FixedLayoutPluginContext;
+
+  @inject(SelectionService) selectionService: SelectionService;
+
+  @inject(Playground) playground: Playground;
+
+  @inject(FlowDocument) document: FlowDocument;
+
+  save() {
+    console.log(this.document.toJSON());
+  }
+}

+ 1 - 0
apps/demo-fixed-layout/src/services/index.ts

@@ -0,0 +1 @@
+export { CustomService } from './custom-service';

+ 7 - 2
apps/demo-free-layout/rsbuild.config.ts

@@ -1,13 +1,18 @@
 import { pluginReact } from '@rsbuild/plugin-react';
-import { pluginLess } from '@rsbuild/plugin-less';
 import { defineConfig } from '@rsbuild/core';
 
 export default defineConfig({
-  plugins: [pluginReact(), pluginLess()],
+  plugins: [pluginReact()],
   source: {
     entry: {
       index: './src/app.tsx',
     },
+    /**
+     * support inversify @injectable() and @inject decorators
+     */
+    decorators: {
+      version: 'legacy',
+    },
   },
   html: {
     title: 'demo-free-layout',

+ 7 - 0
apps/demo-free-layout/src/hooks/use-editor-props.tsx

@@ -14,6 +14,7 @@ import { createContainerNodePlugin } from '@flowgram.ai/free-container-plugin';
 
 import { FlowNodeRegistry, FlowDocumentJSON } from '../typings';
 import { shortcuts } from '../shortcuts';
+import { CustomService } from '../services';
 import { createSyncVariablePlugin } from '../plugins';
 import { defaultFormMeta } from '../nodes/default-form-meta';
 import { SelectorBoxPopover } from '../components/selector-box-popover';
@@ -146,6 +147,12 @@ export function useEditorProps(
        * Shortcuts
        */
       shortcuts,
+      /**
+       * Bind custom service
+       */
+      onBind: ({ bind }) => {
+        bind(CustomService).toSelf().inSingletonScope();
+      },
       /**
        * Playground init
        */

+ 42 - 0
apps/demo-free-layout/src/services/custom-service.ts

@@ -0,0 +1,42 @@
+import { injectable, inject } from '@flowgram.ai/free-layout-editor';
+import {
+  FreeLayoutPluginContext,
+  SelectionService,
+  Playground,
+  WorkflowDocument,
+} from '@flowgram.ai/free-layout-editor';
+
+/**
+ * Docs: https://inversify.io/docs/introduction/getting-started/
+ * Warning: Use decorator legacy
+ *   // rsbuild.config.ts
+ *   {
+ *     source: {
+ *       decorators: {
+ *         version: 'legacy'
+ *       }
+ *     }
+ *   }
+ * Usage:
+ *  1.
+ *    const myService = useService(CustomService)
+ *    myService.save()
+ *  2.
+ *    const myService = useClientContext().get(CustomService)
+ *  3.
+ *    const myService = node.getService(CustomService)
+ */
+@injectable()
+export class CustomService {
+  @inject(FreeLayoutPluginContext) ctx: FreeLayoutPluginContext;
+
+  @inject(SelectionService) selectionService: SelectionService;
+
+  @inject(Playground) playground: Playground;
+
+  @inject(WorkflowDocument) document: WorkflowDocument;
+
+  save() {
+    console.log(this.document.toJSON());
+  }
+}

+ 1 - 0
apps/demo-free-layout/src/services/index.ts

@@ -0,0 +1 @@
+export { CustomService } from './custom-service';

+ 5 - 0
apps/docs/rspress.config.ts

@@ -9,6 +9,11 @@ export default defineConfig({
   title: 'FlowGram.AI',
   globalStyles: path.join(__dirname, './global.less'),
   builderConfig: {
+    source: {
+      decorators: {
+        version: 'legacy',
+      },
+    },
     tools: {
       rspack(options) {
         return merge(options, {

+ 21 - 5
apps/docs/src/en/guide/advanced/custom-service.mdx

@@ -3,13 +3,29 @@
 In business, it is necessary to abstract singleton services for easy plug-in management.
 
 ```tsx pure
-/**
- *  inversify: https://github.com/inversify/InversifyJS
- */
-import { injectable, inject } from 'inversify'
 import { useMemo } from 'react';
-import { FlowDocument, type FixedLayoutProps } from '@flowgram.ai/fixed-layout-editor'
+import { FlowDocument, type FixedLayoutProps, inject, injectable } from '@flowgram.ai/fixed-layout-editor'
 
+/**
+ * Docs: https://inversify.io/docs/introduction/getting-started/
+ * Warning: Use decorator legacy
+ *   // rsbuild.config.ts
+ *   {
+ *     source: {
+ *       decorators: {
+ *         version: 'legacy'
+ *       }
+ *     }
+ *   }
+ * Usage:
+ *  1.
+ *    const myService = useService(MyService)
+ *    myService.save()
+ *  2.
+ *    const myService = useClientContext().get(MyService)
+ *  3.
+ *    const myService = node.getService(MyService)
+ */
 @injectable()
 class MyService {
   // Dependency injection of singleton module

+ 21 - 5
apps/docs/src/zh/guide/advanced/custom-service.mdx

@@ -3,13 +3,29 @@
 业务中需要抽象出单例服务便于插件化管理
 
 ```tsx pure
-/**
- *  inversify: https://github.com/inversify/InversifyJS
- */
-import { injectable, inject } from 'inversify'
 import { useMemo } from 'react';
-import { FlowDocument, type FixedLayoutProps } from '@flowgram.ai/fixed-layout-editor'
+import { FlowDocument, type FixedLayoutProps, inject, injectable } from '@flowgram.ai/fixed-layout-editor'
 
+/**
+ * Docs: https://inversify.io/docs/introduction/getting-started/
+ * Warning: Use decorator legacy
+ *   // rsbuild.config.ts
+ *   {
+ *     source: {
+ *       decorators: {
+ *         version: 'legacy'
+ *       }
+ *     }
+ *   }
+ * Usage:
+ *  1.
+ *    const myService = useService(MyService)
+ *    myService.save()
+ *  2.
+ *    const myService = useClientContext().get(MyService)
+ *  3.
+ *    const myService = node.getService(MyService)
+ */
 @injectable()
 class MyService {
   // 依赖注入单例模块

+ 3 - 0
packages/client/fixed-layout-editor/src/preset/fixed-layout-props.ts

@@ -9,10 +9,13 @@ import {
   FlowDocumentJSON,
   FlowLayoutDefault,
   SelectionService,
+  PluginContext,
 } from '@flowgram.ai/editor';
 
 import { FlowOperationService } from '../types';
 
+export const FixedLayoutPluginContext = PluginContext;
+
 export interface FixedLayoutPluginContext extends EditorPluginContext {
   document: FlowDocument;
   /**

+ 3 - 0
packages/client/free-layout-editor/src/preset/free-layout-props.ts

@@ -24,8 +24,11 @@ import {
   FlowNodeFormData,
   type FlowNodeJSON,
   SelectionService,
+  PluginContext,
 } from '@flowgram.ai/editor';
 
+export const FreeLayoutPluginContext = PluginContext;
+
 export interface FreeLayoutPluginContext extends EditorPluginContext {
   /**
    * 文档