@superblocksteam/vite-plugin-file-sync 1.99.99-next.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.txt +87 -0
- package/dist/ai-service/app-interface/shell.d.ts +15 -0
- package/dist/ai-service/app-interface/shell.d.ts.map +1 -0
- package/dist/ai-service/app-interface/shell.js +81 -0
- package/dist/ai-service/app-interface/shell.js.map +1 -0
- package/dist/ai-service/artifacts/bolt.d.ts +8 -0
- package/dist/ai-service/artifacts/bolt.d.ts.map +1 -0
- package/dist/ai-service/artifacts/bolt.js +34 -0
- package/dist/ai-service/artifacts/bolt.js.map +1 -0
- package/dist/ai-service/const.d.ts +9 -0
- package/dist/ai-service/const.d.ts.map +1 -0
- package/dist/ai-service/const.js +10 -0
- package/dist/ai-service/const.js.map +1 -0
- package/dist/ai-service/eval/template-renderer.d.ts +13 -0
- package/dist/ai-service/eval/template-renderer.d.ts.map +1 -0
- package/dist/ai-service/eval/template-renderer.js +67 -0
- package/dist/ai-service/eval/template-renderer.js.map +1 -0
- package/dist/ai-service/index.d.ts +21 -0
- package/dist/ai-service/index.d.ts.map +1 -0
- package/dist/ai-service/index.js +153 -0
- package/dist/ai-service/index.js.map +1 -0
- package/dist/ai-service/integrations/const.d.ts +41 -0
- package/dist/ai-service/integrations/const.d.ts.map +1 -0
- package/dist/ai-service/integrations/const.js +76 -0
- package/dist/ai-service/integrations/const.js.map +1 -0
- package/dist/ai-service/integrations/from-prompt-context.d.ts +4 -0
- package/dist/ai-service/integrations/from-prompt-context.d.ts.map +1 -0
- package/dist/ai-service/integrations/from-prompt-context.js +56 -0
- package/dist/ai-service/integrations/from-prompt-context.js.map +1 -0
- package/dist/ai-service/integrations/to-sdk-prompt.d.ts +3 -0
- package/dist/ai-service/integrations/to-sdk-prompt.d.ts.map +1 -0
- package/dist/ai-service/integrations/to-sdk-prompt.js +45 -0
- package/dist/ai-service/integrations/to-sdk-prompt.js.map +1 -0
- package/dist/ai-service/integrations/types.d.ts +31 -0
- package/dist/ai-service/integrations/types.d.ts.map +1 -0
- package/dist/ai-service/integrations/types.js +2 -0
- package/dist/ai-service/integrations/types.js.map +1 -0
- package/dist/ai-service/prompts/draft-subprompts/superblocks-api-draft.d.ts +2 -0
- package/dist/ai-service/prompts/draft-subprompts/superblocks-api-draft.d.ts.map +1 -0
- package/dist/ai-service/prompts/draft-subprompts/superblocks-api-draft.js +386 -0
- package/dist/ai-service/prompts/draft-subprompts/superblocks-api-draft.js.map +1 -0
- package/dist/ai-service/prompts/draft-subprompts/superblocks-layouts-with-grid-examples.d.ts +2 -0
- package/dist/ai-service/prompts/draft-subprompts/superblocks-layouts-with-grid-examples.d.ts.map +1 -0
- package/dist/ai-service/prompts/draft-subprompts/superblocks-layouts-with-grid-examples.js +219 -0
- package/dist/ai-service/prompts/draft-subprompts/superblocks-layouts-with-grid-examples.js.map +1 -0
- package/dist/ai-service/prompts/generated/index.d.ts +4 -0
- package/dist/ai-service/prompts/generated/index.d.ts.map +1 -0
- package/dist/ai-service/prompts/generated/index.js +6 -0
- package/dist/ai-service/prompts/generated/index.js.map +1 -0
- package/dist/ai-service/prompts/generated/library-components/SbButtonPropsDocs.d.ts +2 -0
- package/dist/ai-service/prompts/generated/library-components/SbButtonPropsDocs.d.ts.map +1 -0
- package/dist/ai-service/prompts/generated/library-components/SbButtonPropsDocs.js +6 -0
- package/dist/ai-service/prompts/generated/library-components/SbButtonPropsDocs.js.map +1 -0
- package/dist/ai-service/prompts/generated/library-components/SbCheckboxPropsDocs.d.ts +2 -0
- package/dist/ai-service/prompts/generated/library-components/SbCheckboxPropsDocs.d.ts.map +1 -0
- package/dist/ai-service/prompts/generated/library-components/SbCheckboxPropsDocs.js +6 -0
- package/dist/ai-service/prompts/generated/library-components/SbCheckboxPropsDocs.js.map +1 -0
- package/dist/ai-service/prompts/generated/library-components/SbColumnPropsDocs.d.ts +2 -0
- package/dist/ai-service/prompts/generated/library-components/SbColumnPropsDocs.d.ts.map +1 -0
- package/dist/ai-service/prompts/generated/library-components/SbColumnPropsDocs.js +6 -0
- package/dist/ai-service/prompts/generated/library-components/SbColumnPropsDocs.js.map +1 -0
- package/dist/ai-service/prompts/generated/library-components/SbContainerPropsDocs.d.ts +2 -0
- package/dist/ai-service/prompts/generated/library-components/SbContainerPropsDocs.d.ts.map +1 -0
- package/dist/ai-service/prompts/generated/library-components/SbContainerPropsDocs.js +6 -0
- package/dist/ai-service/prompts/generated/library-components/SbContainerPropsDocs.js.map +1 -0
- package/dist/ai-service/prompts/generated/library-components/SbDatePickerPropsDocs.d.ts +2 -0
- package/dist/ai-service/prompts/generated/library-components/SbDatePickerPropsDocs.d.ts.map +1 -0
- package/dist/ai-service/prompts/generated/library-components/SbDatePickerPropsDocs.js +6 -0
- package/dist/ai-service/prompts/generated/library-components/SbDatePickerPropsDocs.js.map +1 -0
- package/dist/ai-service/prompts/generated/library-components/SbDropdownPropsDocs.d.ts +2 -0
- package/dist/ai-service/prompts/generated/library-components/SbDropdownPropsDocs.d.ts.map +1 -0
- package/dist/ai-service/prompts/generated/library-components/SbDropdownPropsDocs.js +6 -0
- package/dist/ai-service/prompts/generated/library-components/SbDropdownPropsDocs.js.map +1 -0
- package/dist/ai-service/prompts/generated/library-components/SbIconPropsDocs.d.ts +2 -0
- package/dist/ai-service/prompts/generated/library-components/SbIconPropsDocs.d.ts.map +1 -0
- package/dist/ai-service/prompts/generated/library-components/SbIconPropsDocs.js +6 -0
- package/dist/ai-service/prompts/generated/library-components/SbIconPropsDocs.js.map +1 -0
- package/dist/ai-service/prompts/generated/library-components/SbImagePropsDocs.d.ts +2 -0
- package/dist/ai-service/prompts/generated/library-components/SbImagePropsDocs.d.ts.map +1 -0
- package/dist/ai-service/prompts/generated/library-components/SbImagePropsDocs.js +6 -0
- package/dist/ai-service/prompts/generated/library-components/SbImagePropsDocs.js.map +1 -0
- package/dist/ai-service/prompts/generated/library-components/SbInputPropsDocs.d.ts +2 -0
- package/dist/ai-service/prompts/generated/library-components/SbInputPropsDocs.d.ts.map +1 -0
- package/dist/ai-service/prompts/generated/library-components/SbInputPropsDocs.js +6 -0
- package/dist/ai-service/prompts/generated/library-components/SbInputPropsDocs.js.map +1 -0
- package/dist/ai-service/prompts/generated/library-components/SbModalPropsDocs.d.ts +2 -0
- package/dist/ai-service/prompts/generated/library-components/SbModalPropsDocs.d.ts.map +1 -0
- package/dist/ai-service/prompts/generated/library-components/SbModalPropsDocs.js +6 -0
- package/dist/ai-service/prompts/generated/library-components/SbModalPropsDocs.js.map +1 -0
- package/dist/ai-service/prompts/generated/library-components/SbPagePropsDocs.d.ts +2 -0
- package/dist/ai-service/prompts/generated/library-components/SbPagePropsDocs.d.ts.map +1 -0
- package/dist/ai-service/prompts/generated/library-components/SbPagePropsDocs.js +6 -0
- package/dist/ai-service/prompts/generated/library-components/SbPagePropsDocs.js.map +1 -0
- package/dist/ai-service/prompts/generated/library-components/SbSectionPropsDocs.d.ts +2 -0
- package/dist/ai-service/prompts/generated/library-components/SbSectionPropsDocs.d.ts.map +1 -0
- package/dist/ai-service/prompts/generated/library-components/SbSectionPropsDocs.js +6 -0
- package/dist/ai-service/prompts/generated/library-components/SbSectionPropsDocs.js.map +1 -0
- package/dist/ai-service/prompts/generated/library-components/SbSlideoutPropsDocs.d.ts +2 -0
- package/dist/ai-service/prompts/generated/library-components/SbSlideoutPropsDocs.d.ts.map +1 -0
- package/dist/ai-service/prompts/generated/library-components/SbSlideoutPropsDocs.js +6 -0
- package/dist/ai-service/prompts/generated/library-components/SbSlideoutPropsDocs.js.map +1 -0
- package/dist/ai-service/prompts/generated/library-components/SbSwitchPropsDocs.d.ts +2 -0
- package/dist/ai-service/prompts/generated/library-components/SbSwitchPropsDocs.d.ts.map +1 -0
- package/dist/ai-service/prompts/generated/library-components/SbSwitchPropsDocs.js +6 -0
- package/dist/ai-service/prompts/generated/library-components/SbSwitchPropsDocs.js.map +1 -0
- package/dist/ai-service/prompts/generated/library-components/SbTablePropsDocs.d.ts +2 -0
- package/dist/ai-service/prompts/generated/library-components/SbTablePropsDocs.d.ts.map +1 -0
- package/dist/ai-service/prompts/generated/library-components/SbTablePropsDocs.js +6 -0
- package/dist/ai-service/prompts/generated/library-components/SbTablePropsDocs.js.map +1 -0
- package/dist/ai-service/prompts/generated/library-components/SbTextPropsDocs.d.ts +2 -0
- package/dist/ai-service/prompts/generated/library-components/SbTextPropsDocs.d.ts.map +1 -0
- package/dist/ai-service/prompts/generated/library-components/SbTextPropsDocs.js +6 -0
- package/dist/ai-service/prompts/generated/library-components/SbTextPropsDocs.js.map +1 -0
- package/dist/ai-service/prompts/generated/library-components/index.d.ts +17 -0
- package/dist/ai-service/prompts/generated/library-components/index.d.ts.map +1 -0
- package/dist/ai-service/prompts/generated/library-components/index.js +19 -0
- package/dist/ai-service/prompts/generated/library-components/index.js.map +1 -0
- package/dist/ai-service/prompts/generated/library-typedefs/Dim.d.ts +2 -0
- package/dist/ai-service/prompts/generated/library-typedefs/Dim.d.ts.map +1 -0
- package/dist/ai-service/prompts/generated/library-typedefs/Dim.js +6 -0
- package/dist/ai-service/prompts/generated/library-typedefs/Dim.js.map +1 -0
- package/dist/ai-service/prompts/generated/library-typedefs/SbEventFlow.d.ts +2 -0
- package/dist/ai-service/prompts/generated/library-typedefs/SbEventFlow.d.ts.map +1 -0
- package/dist/ai-service/prompts/generated/library-typedefs/SbEventFlow.js +6 -0
- package/dist/ai-service/prompts/generated/library-typedefs/SbEventFlow.js.map +1 -0
- package/dist/ai-service/prompts/generated/library-typedefs/index.d.ts +3 -0
- package/dist/ai-service/prompts/generated/library-typedefs/index.d.ts.map +1 -0
- package/dist/ai-service/prompts/generated/library-typedefs/index.js +5 -0
- package/dist/ai-service/prompts/generated/library-typedefs/index.js.map +1 -0
- package/dist/ai-service/prompts/generated/subprompts/index.d.ts +11 -0
- package/dist/ai-service/prompts/generated/subprompts/index.d.ts.map +1 -0
- package/dist/ai-service/prompts/generated/subprompts/index.js +13 -0
- package/dist/ai-service/prompts/generated/subprompts/index.js.map +1 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-api.d.ts +2 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-api.d.ts.map +1 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-api.js +6 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-api.js.map +1 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-components-rules.d.ts +2 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-components-rules.d.ts.map +1 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-components-rules.js +6 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-components-rules.js.map +1 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-custom-components.d.ts +2 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-custom-components.d.ts.map +1 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-custom-components.js +6 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-custom-components.js.map +1 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-event-flow.d.ts +2 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-event-flow.d.ts.map +1 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-event-flow.js +6 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-event-flow.js.map +1 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-layouts.d.ts +2 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-layouts.d.ts.map +1 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-layouts.js +6 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-layouts.js.map +1 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-page.d.ts +2 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-page.d.ts.map +1 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-page.js +6 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-page.js.map +1 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-routes.d.ts +2 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-routes.d.ts.map +1 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-routes.js +6 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-routes.js.map +1 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-state.d.ts +2 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-state.d.ts.map +1 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-state.js +6 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-state.js.map +1 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-theming.d.ts +2 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-theming.d.ts.map +1 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-theming.js +6 -0
- package/dist/ai-service/prompts/generated/subprompts/superblocks-theming.js.map +1 -0
- package/dist/ai-service/prompts/generated/subprompts/system.d.ts +2 -0
- package/dist/ai-service/prompts/generated/subprompts/system.d.ts.map +1 -0
- package/dist/ai-service/prompts/generated/subprompts/system.js +6 -0
- package/dist/ai-service/prompts/generated/subprompts/system.js.map +1 -0
- package/dist/ai-service/prompts/markdown-loader.d.ts +10 -0
- package/dist/ai-service/prompts/markdown-loader.d.ts.map +1 -0
- package/dist/ai-service/prompts/markdown-loader.js +71 -0
- package/dist/ai-service/prompts/markdown-loader.js.map +1 -0
- package/dist/ai-service/prompts/system.d.ts +2 -0
- package/dist/ai-service/prompts/system.d.ts.map +1 -0
- package/dist/ai-service/prompts/system.js +152 -0
- package/dist/ai-service/prompts/system.js.map +1 -0
- package/dist/ai-service/result-buffer/bolt.d.ts +15 -0
- package/dist/ai-service/result-buffer/bolt.d.ts.map +1 -0
- package/dist/ai-service/result-buffer/bolt.js +73 -0
- package/dist/ai-service/result-buffer/bolt.js.map +1 -0
- package/dist/ai-service/result-buffer/shared.d.ts +13 -0
- package/dist/ai-service/result-buffer/shared.d.ts.map +1 -0
- package/dist/ai-service/result-buffer/shared.js +7 -0
- package/dist/ai-service/result-buffer/shared.js.map +1 -0
- package/dist/ai-service/state-machine/clark-fsm.d.ts +177 -0
- package/dist/ai-service/state-machine/clark-fsm.d.ts.map +1 -0
- package/dist/ai-service/state-machine/clark-fsm.js +70 -0
- package/dist/ai-service/state-machine/clark-fsm.js.map +1 -0
- package/dist/ai-service/state-machine/fsm.d.ts +42 -0
- package/dist/ai-service/state-machine/fsm.d.ts.map +1 -0
- package/dist/ai-service/state-machine/fsm.js +64 -0
- package/dist/ai-service/state-machine/fsm.js.map +1 -0
- package/dist/ai-service/state-machine/handlers/agent-planning.d.ts +3 -0
- package/dist/ai-service/state-machine/handlers/agent-planning.d.ts.map +1 -0
- package/dist/ai-service/state-machine/handlers/agent-planning.js +263 -0
- package/dist/ai-service/state-machine/handlers/agent-planning.js.map +1 -0
- package/dist/ai-service/state-machine/handlers/awaiting-user.d.ts +3 -0
- package/dist/ai-service/state-machine/handlers/awaiting-user.d.ts.map +1 -0
- package/dist/ai-service/state-machine/handlers/awaiting-user.js +36 -0
- package/dist/ai-service/state-machine/handlers/awaiting-user.js.map +1 -0
- package/dist/ai-service/state-machine/handlers/idle.d.ts +3 -0
- package/dist/ai-service/state-machine/handlers/idle.d.ts.map +1 -0
- package/dist/ai-service/state-machine/handlers/idle.js +24 -0
- package/dist/ai-service/state-machine/handlers/idle.js.map +1 -0
- package/dist/ai-service/state-machine/handlers/llm-generating.d.ts +3 -0
- package/dist/ai-service/state-machine/handlers/llm-generating.d.ts.map +1 -0
- package/dist/ai-service/state-machine/handlers/llm-generating.js +160 -0
- package/dist/ai-service/state-machine/handlers/llm-generating.js.map +1 -0
- package/dist/ai-service/state-machine/handlers/play-dead.d.ts +3 -0
- package/dist/ai-service/state-machine/handlers/play-dead.d.ts.map +1 -0
- package/dist/ai-service/state-machine/handlers/play-dead.js +11 -0
- package/dist/ai-service/state-machine/handlers/play-dead.js.map +1 -0
- package/dist/ai-service/state-machine/handlers/post-processing.d.ts +3 -0
- package/dist/ai-service/state-machine/handlers/post-processing.d.ts.map +1 -0
- package/dist/ai-service/state-machine/handlers/post-processing.js +85 -0
- package/dist/ai-service/state-machine/handlers/post-processing.js.map +1 -0
- package/dist/ai-service/state-machine/handlers/runtime-reviewing.d.ts +4 -0
- package/dist/ai-service/state-machine/handlers/runtime-reviewing.d.ts.map +1 -0
- package/dist/ai-service/state-machine/handlers/runtime-reviewing.js +40 -0
- package/dist/ai-service/state-machine/handlers/runtime-reviewing.js.map +1 -0
- package/dist/ai-service/state-machine/helpers/metadata.d.ts +6 -0
- package/dist/ai-service/state-machine/helpers/metadata.d.ts.map +1 -0
- package/dist/ai-service/state-machine/helpers/metadata.js +11 -0
- package/dist/ai-service/state-machine/helpers/metadata.js.map +1 -0
- package/dist/ai-service/state-machine/helpers/peer.d.ts +5 -0
- package/dist/ai-service/state-machine/helpers/peer.d.ts.map +1 -0
- package/dist/ai-service/state-machine/helpers/peer.js +7 -0
- package/dist/ai-service/state-machine/helpers/peer.js.map +1 -0
- package/dist/ai-service/state-machine/helpers/transition.d.ts +12 -0
- package/dist/ai-service/state-machine/helpers/transition.d.ts.map +1 -0
- package/dist/ai-service/state-machine/helpers/transition.js +12 -0
- package/dist/ai-service/state-machine/helpers/transition.js.map +1 -0
- package/dist/ai-service/state-machine/mocks.d.ts +7 -0
- package/dist/ai-service/state-machine/mocks.d.ts.map +1 -0
- package/dist/ai-service/state-machine/mocks.js +72 -0
- package/dist/ai-service/state-machine/mocks.js.map +1 -0
- package/dist/ai-service/state-machine/test-util.d.ts +5 -0
- package/dist/ai-service/state-machine/test-util.d.ts.map +1 -0
- package/dist/ai-service/state-machine/test-util.js +29 -0
- package/dist/ai-service/state-machine/test-util.js.map +1 -0
- package/dist/ai-service/transform/add-metadata-to-api-yaml/transformer.d.ts +21 -0
- package/dist/ai-service/transform/add-metadata-to-api-yaml/transformer.d.ts.map +1 -0
- package/dist/ai-service/transform/add-metadata-to-api-yaml/transformer.js +48 -0
- package/dist/ai-service/transform/add-metadata-to-api-yaml/transformer.js.map +1 -0
- package/dist/ai-service/transform/api-builder/shared.d.ts +11 -0
- package/dist/ai-service/transform/api-builder/shared.d.ts.map +1 -0
- package/dist/ai-service/transform/api-builder/shared.js +55 -0
- package/dist/ai-service/transform/api-builder/shared.js.map +1 -0
- package/dist/ai-service/transform/api-builder/to-sdk-transformer.d.ts +27 -0
- package/dist/ai-service/transform/api-builder/to-sdk-transformer.d.ts.map +1 -0
- package/dist/ai-service/transform/api-builder/to-sdk-transformer.js +67 -0
- package/dist/ai-service/transform/api-builder/to-sdk-transformer.js.map +1 -0
- package/dist/ai-service/transform/api-builder/to-yaml-transformer.d.ts +23 -0
- package/dist/ai-service/transform/api-builder/to-yaml-transformer.d.ts.map +1 -0
- package/dist/ai-service/transform/api-builder/to-yaml-transformer.js +59 -0
- package/dist/ai-service/transform/api-builder/to-yaml-transformer.js.map +1 -0
- package/dist/ai-service/transform/remove-api-builder-imports/transformer.d.ts +19 -0
- package/dist/ai-service/transform/remove-api-builder-imports/transformer.d.ts.map +1 -0
- package/dist/ai-service/transform/remove-api-builder-imports/transformer.js +45 -0
- package/dist/ai-service/transform/remove-api-builder-imports/transformer.js.map +1 -0
- package/dist/ai-service/transform/shared.d.ts +20 -0
- package/dist/ai-service/transform/shared.d.ts.map +1 -0
- package/dist/ai-service/transform/shared.js +134 -0
- package/dist/ai-service/transform/shared.js.map +1 -0
- package/dist/ai-service/transform/workaround-missing-sbapi/transformer.d.ts +17 -0
- package/dist/ai-service/transform/workaround-missing-sbapi/transformer.d.ts.map +1 -0
- package/dist/ai-service/transform/workaround-missing-sbapi/transformer.js +33 -0
- package/dist/ai-service/transform/workaround-missing-sbapi/transformer.js.map +1 -0
- package/dist/ai-service/types.d.ts +71 -0
- package/dist/ai-service/types.d.ts.map +1 -0
- package/dist/ai-service/types.js +8 -0
- package/dist/ai-service/types.js.map +1 -0
- package/dist/binding-extraction/extract-control-block-identifiers.d.ts +4 -0
- package/dist/binding-extraction/extract-control-block-identifiers.d.ts.map +1 -0
- package/dist/binding-extraction/extract-control-block-identifiers.js +86 -0
- package/dist/binding-extraction/extract-control-block-identifiers.js.map +1 -0
- package/dist/binding-extraction/extract-embedded-identifiers.d.ts +16 -0
- package/dist/binding-extraction/extract-embedded-identifiers.d.ts.map +1 -0
- package/dist/binding-extraction/extract-embedded-identifiers.js +100 -0
- package/dist/binding-extraction/extract-embedded-identifiers.js.map +1 -0
- package/dist/binding-extraction/extract-identifiers.d.ts +8 -0
- package/dist/binding-extraction/extract-identifiers.d.ts.map +1 -0
- package/dist/binding-extraction/extract-identifiers.js +150 -0
- package/dist/binding-extraction/extract-identifiers.js.map +1 -0
- package/dist/binding-extraction/extract-js-identifiers.d.ts +19 -0
- package/dist/binding-extraction/extract-js-identifiers.d.ts.map +1 -0
- package/dist/binding-extraction/extract-js-identifiers.js +161 -0
- package/dist/binding-extraction/extract-js-identifiers.js.map +1 -0
- package/dist/binding-extraction/extract-py-identifiers.d.ts +4 -0
- package/dist/binding-extraction/extract-py-identifiers.d.ts.map +1 -0
- package/dist/binding-extraction/extract-py-identifiers.js +161 -0
- package/dist/binding-extraction/extract-py-identifiers.js.map +1 -0
- package/dist/binding-extraction/shared.d.ts +225 -0
- package/dist/binding-extraction/shared.d.ts.map +1 -0
- package/dist/binding-extraction/shared.js +43 -0
- package/dist/binding-extraction/shared.js.map +1 -0
- package/dist/binding-extraction/template-strings.d.ts +9 -0
- package/dist/binding-extraction/template-strings.d.ts.map +1 -0
- package/dist/binding-extraction/template-strings.js +45 -0
- package/dist/binding-extraction/template-strings.js.map +1 -0
- package/dist/codegen.d.ts +26 -0
- package/dist/codegen.d.ts.map +1 -0
- package/dist/codegen.js +222 -0
- package/dist/codegen.js.map +1 -0
- package/dist/components-manager.d.ts +38 -0
- package/dist/components-manager.d.ts.map +1 -0
- package/dist/components-manager.js +177 -0
- package/dist/components-manager.js.map +1 -0
- package/dist/custom-components.d.ts +6 -0
- package/dist/custom-components.d.ts.map +1 -0
- package/dist/custom-components.js +51 -0
- package/dist/custom-components.js.map +1 -0
- package/dist/draft-interface.d.ts +12 -0
- package/dist/draft-interface.d.ts.map +1 -0
- package/dist/draft-interface.js +2 -0
- package/dist/draft-interface.js.map +1 -0
- package/dist/errors/error-handler.d.ts +35 -0
- package/dist/errors/error-handler.d.ts.map +1 -0
- package/dist/errors/error-handler.js +65 -0
- package/dist/errors/error-handler.js.map +1 -0
- package/dist/errors/make-server-error.d.ts +5 -0
- package/dist/errors/make-server-error.d.ts.map +1 -0
- package/dist/errors/make-server-error.js +21 -0
- package/dist/errors/make-server-error.js.map +1 -0
- package/dist/file-sync-vite-plugin.d.ts +4 -0
- package/dist/file-sync-vite-plugin.d.ts.map +1 -0
- package/dist/file-sync-vite-plugin.js +691 -0
- package/dist/file-sync-vite-plugin.js.map +1 -0
- package/dist/file-system-helpers.d.ts +7 -0
- package/dist/file-system-helpers.d.ts.map +1 -0
- package/dist/file-system-helpers.js +12 -0
- package/dist/file-system-helpers.js.map +1 -0
- package/dist/file-system-manager.d.ts +133 -0
- package/dist/file-system-manager.d.ts.map +1 -0
- package/dist/file-system-manager.js +1205 -0
- package/dist/file-system-manager.js.map +1 -0
- package/dist/generate.d.ts +8 -0
- package/dist/generate.d.ts.map +1 -0
- package/dist/generate.js +7 -0
- package/dist/generate.js.map +1 -0
- package/dist/ids.d.ts +2 -0
- package/dist/ids.d.ts.map +1 -0
- package/dist/ids.js +21 -0
- package/dist/ids.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/injected-index.d.ts +12 -0
- package/dist/injected-index.d.ts.map +1 -0
- package/dist/injected-index.js +38 -0
- package/dist/injected-index.js.map +1 -0
- package/dist/lock-service/index.d.ts +108 -0
- package/dist/lock-service/index.d.ts.map +1 -0
- package/dist/lock-service/index.js +324 -0
- package/dist/lock-service/index.js.map +1 -0
- package/dist/parsing/bindings.d.ts +4 -0
- package/dist/parsing/bindings.d.ts.map +1 -0
- package/dist/parsing/bindings.js +17 -0
- package/dist/parsing/bindings.js.map +1 -0
- package/dist/parsing/computed/index.d.ts +4 -0
- package/dist/parsing/computed/index.d.ts.map +1 -0
- package/dist/parsing/computed/index.js +7 -0
- package/dist/parsing/computed/index.js.map +1 -0
- package/dist/parsing/computed/to-code-computed.d.ts +2 -0
- package/dist/parsing/computed/to-code-computed.d.ts.map +1 -0
- package/dist/parsing/computed/to-code-computed.js +43 -0
- package/dist/parsing/computed/to-code-computed.js.map +1 -0
- package/dist/parsing/computed/to-value-computed.d.ts +4 -0
- package/dist/parsing/computed/to-value-computed.d.ts.map +1 -0
- package/dist/parsing/computed/to-value-computed.js +13 -0
- package/dist/parsing/computed/to-value-computed.js.map +1 -0
- package/dist/parsing/dim/index.d.ts +5 -0
- package/dist/parsing/dim/index.d.ts.map +1 -0
- package/dist/parsing/dim/index.js +7 -0
- package/dist/parsing/dim/index.js.map +1 -0
- package/dist/parsing/dim/to-code-dimensions.d.ts +3 -0
- package/dist/parsing/dim/to-code-dimensions.d.ts.map +1 -0
- package/dist/parsing/dim/to-code-dimensions.js +22 -0
- package/dist/parsing/dim/to-code-dimensions.js.map +1 -0
- package/dist/parsing/dim/to-value-dimensions.d.ts +4 -0
- package/dist/parsing/dim/to-value-dimensions.d.ts.map +1 -0
- package/dist/parsing/dim/to-value-dimensions.js +39 -0
- package/dist/parsing/dim/to-value-dimensions.js.map +1 -0
- package/dist/parsing/entity/index.d.ts +7 -0
- package/dist/parsing/entity/index.d.ts.map +1 -0
- package/dist/parsing/entity/index.js +7 -0
- package/dist/parsing/entity/index.js.map +1 -0
- package/dist/parsing/entity/to-code-entity.d.ts +3 -0
- package/dist/parsing/entity/to-code-entity.d.ts.map +1 -0
- package/dist/parsing/entity/to-code-entity.js +41 -0
- package/dist/parsing/entity/to-code-entity.js.map +1 -0
- package/dist/parsing/entity/to-value-entity.d.ts +8 -0
- package/dist/parsing/entity/to-value-entity.d.ts.map +1 -0
- package/dist/parsing/entity/to-value-entity.js +120 -0
- package/dist/parsing/entity/to-value-entity.js.map +1 -0
- package/dist/parsing/events/index.d.ts +5 -0
- package/dist/parsing/events/index.d.ts.map +1 -0
- package/dist/parsing/events/index.js +7 -0
- package/dist/parsing/events/index.js.map +1 -0
- package/dist/parsing/events/to-code-events.d.ts +3 -0
- package/dist/parsing/events/to-code-events.d.ts.map +1 -0
- package/dist/parsing/events/to-code-events.js +100 -0
- package/dist/parsing/events/to-code-events.js.map +1 -0
- package/dist/parsing/events/to-value-events.d.ts +6 -0
- package/dist/parsing/events/to-value-events.d.ts.map +1 -0
- package/dist/parsing/events/to-value-events.js +194 -0
- package/dist/parsing/events/to-value-events.js.map +1 -0
- package/dist/parsing/ids.d.ts +17 -0
- package/dist/parsing/ids.d.ts.map +1 -0
- package/dist/parsing/ids.js +143 -0
- package/dist/parsing/ids.js.map +1 -0
- package/dist/parsing/imports.d.ts +6 -0
- package/dist/parsing/imports.d.ts.map +1 -0
- package/dist/parsing/imports.js +31 -0
- package/dist/parsing/imports.js.map +1 -0
- package/dist/parsing/jsx-utils.d.ts +9 -0
- package/dist/parsing/jsx-utils.d.ts.map +1 -0
- package/dist/parsing/jsx-utils.js +48 -0
- package/dist/parsing/jsx-utils.js.map +1 -0
- package/dist/parsing/jsx.d.ts +23 -0
- package/dist/parsing/jsx.d.ts.map +1 -0
- package/dist/parsing/jsx.js +330 -0
- package/dist/parsing/jsx.js.map +1 -0
- package/dist/parsing/page.d.ts +9 -0
- package/dist/parsing/page.d.ts.map +1 -0
- package/dist/parsing/page.js +156 -0
- package/dist/parsing/page.js.map +1 -0
- package/dist/parsing/properties.d.ts +5 -0
- package/dist/parsing/properties.d.ts.map +1 -0
- package/dist/parsing/properties.js +89 -0
- package/dist/parsing/properties.js.map +1 -0
- package/dist/parsing/scope.d.ts +90 -0
- package/dist/parsing/scope.d.ts.map +1 -0
- package/dist/parsing/scope.js +669 -0
- package/dist/parsing/scope.js.map +1 -0
- package/dist/parsing/template/index.d.ts +5 -0
- package/dist/parsing/template/index.d.ts.map +1 -0
- package/dist/parsing/template/index.js +7 -0
- package/dist/parsing/template/index.js.map +1 -0
- package/dist/parsing/template/to-code-template.d.ts +2 -0
- package/dist/parsing/template/to-code-template.d.ts.map +1 -0
- package/dist/parsing/template/to-code-template.js +5 -0
- package/dist/parsing/template/to-code-template.js.map +1 -0
- package/dist/parsing/template/to-value-template.d.ts +4 -0
- package/dist/parsing/template/to-value-template.d.ts.map +1 -0
- package/dist/parsing/template/to-value-template.js +30 -0
- package/dist/parsing/template/to-value-template.js.map +1 -0
- package/dist/parsing/theme.d.ts +3 -0
- package/dist/parsing/theme.d.ts.map +1 -0
- package/dist/parsing/theme.js +87 -0
- package/dist/parsing/theme.js.map +1 -0
- package/dist/parsing/type-parsing-registry.d.ts +8 -0
- package/dist/parsing/type-parsing-registry.d.ts.map +1 -0
- package/dist/parsing/type-parsing-registry.js +11 -0
- package/dist/parsing/type-parsing-registry.js.map +1 -0
- package/dist/parsing/types.d.ts +9 -0
- package/dist/parsing/types.d.ts.map +1 -0
- package/dist/parsing/types.js +2 -0
- package/dist/parsing/types.js.map +1 -0
- package/dist/parsing/util.d.ts +34 -0
- package/dist/parsing/util.d.ts.map +1 -0
- package/dist/parsing/util.js +338 -0
- package/dist/parsing/util.js.map +1 -0
- package/dist/plugin-options.d.ts +25 -0
- package/dist/plugin-options.d.ts.map +1 -0
- package/dist/plugin-options.js +14 -0
- package/dist/plugin-options.js.map +1 -0
- package/dist/refactor/blocks.d.ts +10 -0
- package/dist/refactor/blocks.d.ts.map +1 -0
- package/dist/refactor/blocks.js +214 -0
- package/dist/refactor/blocks.js.map +1 -0
- package/dist/refactor/javascript.d.ts +15 -0
- package/dist/refactor/javascript.d.ts.map +1 -0
- package/dist/refactor/javascript.js +182 -0
- package/dist/refactor/javascript.js.map +1 -0
- package/dist/refactor-jsx.d.ts +28 -0
- package/dist/refactor-jsx.d.ts.map +1 -0
- package/dist/refactor-jsx.js +77 -0
- package/dist/refactor-jsx.js.map +1 -0
- package/dist/rename-manager.d.ts +27 -0
- package/dist/rename-manager.d.ts.map +1 -0
- package/dist/rename-manager.js +140 -0
- package/dist/rename-manager.js.map +1 -0
- package/dist/routing.d.ts +6 -0
- package/dist/routing.d.ts.map +1 -0
- package/dist/routing.js +76 -0
- package/dist/routing.js.map +1 -0
- package/dist/sb-scope-manager.d.ts +102 -0
- package/dist/sb-scope-manager.d.ts.map +1 -0
- package/dist/sb-scope-manager.js +507 -0
- package/dist/sb-scope-manager.js.map +1 -0
- package/dist/socket-manager.d.ts +39 -0
- package/dist/socket-manager.d.ts.map +1 -0
- package/dist/socket-manager.js +184 -0
- package/dist/socket-manager.js.map +1 -0
- package/dist/source-tracker.d.ts +190 -0
- package/dist/source-tracker.d.ts.map +1 -0
- package/dist/source-tracker.js +962 -0
- package/dist/source-tracker.js.map +1 -0
- package/dist/sync-service/download.d.ts +15 -0
- package/dist/sync-service/download.d.ts.map +1 -0
- package/dist/sync-service/download.js +116 -0
- package/dist/sync-service/download.js.map +1 -0
- package/dist/sync-service/draft-helpers.d.ts +77 -0
- package/dist/sync-service/draft-helpers.d.ts.map +1 -0
- package/dist/sync-service/draft-helpers.js +512 -0
- package/dist/sync-service/draft-helpers.js.map +1 -0
- package/dist/sync-service/hash-cache.d.ts +15 -0
- package/dist/sync-service/hash-cache.d.ts.map +1 -0
- package/dist/sync-service/hash-cache.js +58 -0
- package/dist/sync-service/hash-cache.js.map +1 -0
- package/dist/sync-service/hash-dir-tree.d.ts +10 -0
- package/dist/sync-service/hash-dir-tree.d.ts.map +1 -0
- package/dist/sync-service/hash-dir-tree.js +53 -0
- package/dist/sync-service/hash-dir-tree.js.map +1 -0
- package/dist/sync-service/index.d.ts +143 -0
- package/dist/sync-service/index.d.ts.map +1 -0
- package/dist/sync-service/index.js +351 -0
- package/dist/sync-service/index.js.map +1 -0
- package/dist/sync-service/list-dir.d.ts +29 -0
- package/dist/sync-service/list-dir.d.ts.map +1 -0
- package/dist/sync-service/list-dir.js +66 -0
- package/dist/sync-service/list-dir.js.map +1 -0
- package/dist/sync-service/server-rpc/client.d.ts +13 -0
- package/dist/sync-service/server-rpc/client.d.ts.map +1 -0
- package/dist/sync-service/server-rpc/client.js +65 -0
- package/dist/sync-service/server-rpc/client.js.map +1 -0
- package/dist/sync-service/server-rpc/handlers.d.ts +3 -0
- package/dist/sync-service/server-rpc/handlers.d.ts.map +1 -0
- package/dist/sync-service/server-rpc/handlers.js +18 -0
- package/dist/sync-service/server-rpc/handlers.js.map +1 -0
- package/dist/sync-service/snapshot/take-snapshot.d.ts +35 -0
- package/dist/sync-service/snapshot/take-snapshot.d.ts.map +1 -0
- package/dist/sync-service/snapshot/take-snapshot.js +227 -0
- package/dist/sync-service/snapshot/take-snapshot.js.map +1 -0
- package/dist/sync-service/snapshot/types.d.ts +24 -0
- package/dist/sync-service/snapshot/types.d.ts.map +1 -0
- package/dist/sync-service/snapshot/types.js +3 -0
- package/dist/sync-service/snapshot/types.js.map +1 -0
- package/dist/sync-service/snapshot/upload-snapshot.d.ts +5 -0
- package/dist/sync-service/snapshot/upload-snapshot.d.ts.map +1 -0
- package/dist/sync-service/snapshot/upload-snapshot.js +63 -0
- package/dist/sync-service/snapshot/upload-snapshot.js.map +1 -0
- package/dist/traverse.d.ts +6 -0
- package/dist/traverse.d.ts.map +1 -0
- package/dist/traverse.js +7 -0
- package/dist/traverse.js.map +1 -0
- package/dist/util/generation-number-sequence.d.ts +7 -0
- package/dist/util/generation-number-sequence.d.ts.map +1 -0
- package/dist/util/generation-number-sequence.js +13 -0
- package/dist/util/generation-number-sequence.js.map +1 -0
- package/dist/util/logger.d.ts +22 -0
- package/dist/util/logger.d.ts.map +1 -0
- package/dist/util/logger.js +64 -0
- package/dist/util/logger.js.map +1 -0
- package/dist/util/operation-queue.d.ts +17 -0
- package/dist/util/operation-queue.d.ts.map +1 -0
- package/dist/util/operation-queue.js +27 -0
- package/dist/util/operation-queue.js.map +1 -0
- package/dist/util/tracing.d.ts +4 -0
- package/dist/util/tracing.d.ts.map +1 -0
- package/dist/util/tracing.js +56 -0
- package/dist/util/tracing.js.map +1 -0
- package/dist/util/with-resolvers.d.ts +10 -0
- package/dist/util/with-resolvers.d.ts.map +1 -0
- package/dist/util/with-resolvers.js +14 -0
- package/dist/util/with-resolvers.js.map +1 -0
- package/dist/util.d.ts +28 -0
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +123 -0
- package/dist/util.js.map +1 -0
- package/package.json +127 -0
|
@@ -0,0 +1,1205 @@
|
|
|
1
|
+
import fs from "fs/promises";
|
|
2
|
+
import EventEmitter from "node:events";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { transformFromAstAsync } from "@babel/core";
|
|
5
|
+
import t from "@babel/types";
|
|
6
|
+
import { getClientApiId, PROCESSED_TRANSACTIONS_ATTRIBUTE, ROOT_WIDGET_ATTRIBUTE, WIDGET_SOURCE_ID_ATTRIBUTE, } from "@superblocksteam/library-shared";
|
|
7
|
+
import { readAppApiYamlFile, writeApiFiles, } from "@superblocksteam/util";
|
|
8
|
+
import { glob } from "glob";
|
|
9
|
+
import { isEqual } from "lodash-es";
|
|
10
|
+
import yaml from "yaml";
|
|
11
|
+
import { generateJSXAttribute } from "./codegen.js";
|
|
12
|
+
import { addLegacyCustomComponentVariables, modifyLegacyCustomComponentElements, modifyLegacyCustomComponentImports, } from "./custom-components.js";
|
|
13
|
+
import { applyErrorHandling, } from "./errors/error-handler.js";
|
|
14
|
+
import { getPageFolder, PAGES_DIRECTORY, ROUTES_FILE, SCOPE_FILE, } from "./file-system-helpers.js";
|
|
15
|
+
import { generate } from "./generate.js";
|
|
16
|
+
import { doesElementHaveBinding } from "./parsing/bindings.js";
|
|
17
|
+
import { getSbElementId } from "./parsing/ids.js";
|
|
18
|
+
import { makeJSXAttribute } from "./parsing/jsx.js";
|
|
19
|
+
import { getPageRoots } from "./parsing/page.js";
|
|
20
|
+
import { getScope } from "./parsing/scope.js";
|
|
21
|
+
import { getLegacyComponentsFolder, isCustomBuildEnabled, } from "./plugin-options.js";
|
|
22
|
+
import { RenameManager } from "./rename-manager.js";
|
|
23
|
+
import { SourceTracker } from "./source-tracker.js";
|
|
24
|
+
import { traverse } from "./traverse.js";
|
|
25
|
+
import { getErrorMeta, getLogger } from "./util/logger.js";
|
|
26
|
+
import { isValidApi } from "./util.js";
|
|
27
|
+
const SUPPORTED_FILETYPES = [
|
|
28
|
+
{
|
|
29
|
+
type: "tsx",
|
|
30
|
+
extension: ".tsx",
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
type: "scope",
|
|
34
|
+
extension: SCOPE_FILE,
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
type: "api",
|
|
38
|
+
extension: ".yaml",
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
type: "python-api-step",
|
|
42
|
+
extension: ".py",
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
type: "js-api-step",
|
|
46
|
+
extension: ".js",
|
|
47
|
+
},
|
|
48
|
+
];
|
|
49
|
+
const APP_THEME_FILE_NAME = "appTheme.ts";
|
|
50
|
+
export class FileSyncManager extends EventEmitter {
|
|
51
|
+
rootDir;
|
|
52
|
+
tsFiles = {};
|
|
53
|
+
apiFiles = {};
|
|
54
|
+
sourceTracker;
|
|
55
|
+
fsOperationQueue;
|
|
56
|
+
generationNumberSequence;
|
|
57
|
+
routes = {};
|
|
58
|
+
watcher;
|
|
59
|
+
registeredComponentPaths = {};
|
|
60
|
+
renameManager = new RenameManager();
|
|
61
|
+
constructor(fsOperationQueue, generationNumberSequence) {
|
|
62
|
+
super({ captureRejections: true });
|
|
63
|
+
this.rootDir = "/";
|
|
64
|
+
this.fsOperationQueue = fsOperationQueue;
|
|
65
|
+
this.generationNumberSequence = generationNumberSequence;
|
|
66
|
+
applyErrorHandling(this, {
|
|
67
|
+
watch: { operation: "editing from code" },
|
|
68
|
+
handleCreatePage: { operation: "creating a page" },
|
|
69
|
+
handleReparent: { operation: "moving a component" },
|
|
70
|
+
handleCreateComponent: { operation: "creating a component" },
|
|
71
|
+
handleDeleteComponents: { operation: "deleting components" },
|
|
72
|
+
handleSetProperty: { operation: "setting a property" },
|
|
73
|
+
handleSetProperties: { operation: "setting properties" },
|
|
74
|
+
handleDeleteProperties: { operation: "deleting properties" },
|
|
75
|
+
handleBatchUpdate: { operation: "updating multiple things" },
|
|
76
|
+
handleUpdateApi: { operation: "updating an API" },
|
|
77
|
+
handleDeleteApi: { operation: "deleting an API" },
|
|
78
|
+
handleRenameApi: { operation: "renaming an API" },
|
|
79
|
+
handleAddEntity: { operation: "adding an entity" },
|
|
80
|
+
handleUpdateEntity: { operation: "updating an entity" },
|
|
81
|
+
handleDeleteEntity: { operation: "deleting an entity" },
|
|
82
|
+
handleUpdateTheme: { operation: "updating the theme" },
|
|
83
|
+
handleRenameElement: { operation: "renaming an element" },
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
get appFilePath() {
|
|
87
|
+
if (!this.rootDir) {
|
|
88
|
+
throw new Error("Root directory not set");
|
|
89
|
+
}
|
|
90
|
+
return path.join(this.rootDir, "App.tsx");
|
|
91
|
+
}
|
|
92
|
+
updateApi = (content, path) => {
|
|
93
|
+
if (!this.rootDir) {
|
|
94
|
+
throw new Error("Root directory not set");
|
|
95
|
+
}
|
|
96
|
+
const { api: apiContents, stepPathMap } = content;
|
|
97
|
+
const pageName = getPageName(path);
|
|
98
|
+
let scopeId = this.sourceTracker?.getScopeDefinitionForPage(pageName)?.id;
|
|
99
|
+
if (!scopeId) {
|
|
100
|
+
console.warn("Scope ID not found for API", apiContents.metadata.name);
|
|
101
|
+
scopeId = "";
|
|
102
|
+
}
|
|
103
|
+
const updatedApi = {
|
|
104
|
+
apiPb: yaml.parse(JSON.stringify(apiContents)),
|
|
105
|
+
pageName,
|
|
106
|
+
stepPathMap,
|
|
107
|
+
scopeId,
|
|
108
|
+
};
|
|
109
|
+
const isNewApi = !this.apiFiles[path];
|
|
110
|
+
this.apiFiles[path] = updatedApi;
|
|
111
|
+
return { updatedApi, pageName, isNewApi };
|
|
112
|
+
};
|
|
113
|
+
async watch(watcher, rootPath) {
|
|
114
|
+
const logger = getLogger();
|
|
115
|
+
this.rootDir = rootPath;
|
|
116
|
+
this.watcher = watcher;
|
|
117
|
+
// APIs and pages are in the pages subfolder
|
|
118
|
+
const fileNames = await readFiles(path.join(rootPath));
|
|
119
|
+
// this reads all files excluding ignore list in the root path. Should we read all files in pages and add root.tsx and App.tsx instead?
|
|
120
|
+
const tsxFiles = fileNames.filter((f) => f.endsWith(".tsx") && !f.includes(`${getLegacyComponentsFolder()}/`));
|
|
121
|
+
const yamlFiles = fileNames.filter((f) => f.endsWith(".yaml"));
|
|
122
|
+
const scopeFiles = fileNames.filter((f) => f.endsWith(SCOPE_FILE));
|
|
123
|
+
// For the moment, the theme file is `appTheme.ts`. This may change in the future.
|
|
124
|
+
const appThemeFile = path.join(rootPath, APP_THEME_FILE_NAME);
|
|
125
|
+
logger.info(`files to be scanned ${JSON.stringify(tsxFiles)}`);
|
|
126
|
+
logger.info(`api files to be scanned ${JSON.stringify(yamlFiles)}`);
|
|
127
|
+
logger.info(`app theme file to be scanned ${JSON.stringify(appThemeFile)}`);
|
|
128
|
+
logger.info(`scope files to be scanned ${JSON.stringify(scopeFiles)}`);
|
|
129
|
+
const allFiles = [
|
|
130
|
+
...tsxFiles.map((f) => {
|
|
131
|
+
return {
|
|
132
|
+
type: "tsx",
|
|
133
|
+
path: f,
|
|
134
|
+
content: readFile(f),
|
|
135
|
+
};
|
|
136
|
+
}),
|
|
137
|
+
...scopeFiles.map((f) => {
|
|
138
|
+
return {
|
|
139
|
+
type: "ts",
|
|
140
|
+
path: f,
|
|
141
|
+
content: readFile(f),
|
|
142
|
+
};
|
|
143
|
+
}),
|
|
144
|
+
...yamlFiles.map((f) => {
|
|
145
|
+
return {
|
|
146
|
+
type: "api",
|
|
147
|
+
path: f,
|
|
148
|
+
content: getMergedApiContent(f),
|
|
149
|
+
};
|
|
150
|
+
}),
|
|
151
|
+
].flat();
|
|
152
|
+
if (appThemeFile) {
|
|
153
|
+
allFiles.push({
|
|
154
|
+
type: "ts",
|
|
155
|
+
path: appThemeFile,
|
|
156
|
+
content: readFile(appThemeFile),
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
const contents = await Promise.all(allFiles.map((f) => f.content));
|
|
160
|
+
contents.forEach((content, i) => {
|
|
161
|
+
if (!content)
|
|
162
|
+
return;
|
|
163
|
+
const file = allFiles[i];
|
|
164
|
+
if (!file)
|
|
165
|
+
return;
|
|
166
|
+
const { type, path } = file;
|
|
167
|
+
// We only want to load the typescript files here, before the source tracker is initialized
|
|
168
|
+
// API setup needs to be deferred until we've parsed the scope files (which is done in the source tracker)
|
|
169
|
+
if (type === "tsx" || type === "ts") {
|
|
170
|
+
this.tsFiles[path] = content;
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
// And routes are in the root
|
|
174
|
+
const routePath = path.join(rootPath, ROUTES_FILE);
|
|
175
|
+
const routeFile = await readFile(routePath);
|
|
176
|
+
if (routeFile) {
|
|
177
|
+
try {
|
|
178
|
+
this.routes = JSON.parse(routeFile);
|
|
179
|
+
}
|
|
180
|
+
catch (e) {
|
|
181
|
+
logger.error("Error parsing routes file", getErrorMeta(e));
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
try {
|
|
185
|
+
this.initializeSourceTracker();
|
|
186
|
+
}
|
|
187
|
+
catch (e) {
|
|
188
|
+
logger.error("Error initializing source tracker", getErrorMeta(e));
|
|
189
|
+
}
|
|
190
|
+
contents.forEach((content, i) => {
|
|
191
|
+
if (!content)
|
|
192
|
+
return;
|
|
193
|
+
const file = allFiles[i];
|
|
194
|
+
if (!file)
|
|
195
|
+
return;
|
|
196
|
+
const { type, path } = file;
|
|
197
|
+
if (type === "api") {
|
|
198
|
+
this.updateApi(content, path);
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
watcher.on("all", async (event, filePath) => {
|
|
202
|
+
logger.info(`File changed: ${filePath}, event: ${event}`);
|
|
203
|
+
switch (event) {
|
|
204
|
+
case "add": {
|
|
205
|
+
const fileType = SUPPORTED_FILETYPES.find((f) => filePath.endsWith(f.extension));
|
|
206
|
+
if (!fileType || !filePath.startsWith(rootPath)) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
const data = await readFile(filePath);
|
|
210
|
+
if (typeof data !== "string")
|
|
211
|
+
return;
|
|
212
|
+
// if we match pages/*/index.tsx, we want to emit an addPage event
|
|
213
|
+
if (/pages\/.*\/index\.tsx/.test(filePath)) {
|
|
214
|
+
const file = await readFile(filePath);
|
|
215
|
+
if (!file) {
|
|
216
|
+
logger.error(`Failed to read file: ${filePath}`);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
if (!(filePath in this.tsFiles)) {
|
|
220
|
+
this.tsFiles[filePath] = file;
|
|
221
|
+
this.handleNonVisualChangeByDeletingIds(filePath, file);
|
|
222
|
+
this.emit("addPage", filePath);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
switch (fileType.type) {
|
|
226
|
+
case "api":
|
|
227
|
+
case "python-api-step":
|
|
228
|
+
case "js-api-step": {
|
|
229
|
+
await this.processApiUpdates(filePath, fileType);
|
|
230
|
+
break;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
break;
|
|
234
|
+
}
|
|
235
|
+
case "change": {
|
|
236
|
+
// Special routes file handling
|
|
237
|
+
if (filePath === routePath) {
|
|
238
|
+
const data = await readFile(filePath);
|
|
239
|
+
try {
|
|
240
|
+
this.routes = JSON.parse(data);
|
|
241
|
+
this.emit("routesChanged", this.routes);
|
|
242
|
+
}
|
|
243
|
+
catch (e) {
|
|
244
|
+
logger.error("Error parsing routes file", getErrorMeta(e));
|
|
245
|
+
}
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
const fileType = SUPPORTED_FILETYPES.find((f) => filePath.endsWith(f.extension));
|
|
249
|
+
if (!fileType || !filePath.startsWith(rootPath)) {
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
const data = await readFile(filePath);
|
|
253
|
+
if (typeof data !== "string")
|
|
254
|
+
return;
|
|
255
|
+
switch (fileType.type) {
|
|
256
|
+
case "tsx":
|
|
257
|
+
case "scope":
|
|
258
|
+
{
|
|
259
|
+
if (!(filePath in this.tsFiles && this.tsFiles[filePath] === data)) {
|
|
260
|
+
logger.info(`File changed: ${filePath} updating AST tracker`);
|
|
261
|
+
this.tsFiles[filePath] = data;
|
|
262
|
+
// only update the source tracker if the file is different
|
|
263
|
+
this.handleNonVisualChangeByDeletingIds(filePath, data);
|
|
264
|
+
this.emit("fileChanged", filePath, data, true);
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
logger.info(`File unchanged from last tracked state: ${filePath}`);
|
|
268
|
+
this.emit("fileChanged", filePath, data, false);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
break;
|
|
272
|
+
case "api":
|
|
273
|
+
case "python-api-step":
|
|
274
|
+
case "js-api-step":
|
|
275
|
+
{
|
|
276
|
+
await this.processApiUpdates(filePath, fileType);
|
|
277
|
+
}
|
|
278
|
+
break;
|
|
279
|
+
}
|
|
280
|
+
break;
|
|
281
|
+
}
|
|
282
|
+
case "unlink": {
|
|
283
|
+
if (filePath in this.apiFiles) {
|
|
284
|
+
const api = this.apiFiles[filePath];
|
|
285
|
+
delete this.apiFiles[filePath];
|
|
286
|
+
if (!api || !this.sourceTracker)
|
|
287
|
+
break;
|
|
288
|
+
const scopeId = await this.sourceTracker.deleteApi({
|
|
289
|
+
pageName: api.pageName,
|
|
290
|
+
apiName: api.apiPb.metadata.name,
|
|
291
|
+
});
|
|
292
|
+
const changes = (await this.sourceTracker?.getAndFlushChanges()) ?? [];
|
|
293
|
+
await this.writeChanges(changes);
|
|
294
|
+
this.emit("apiManualDelete", {
|
|
295
|
+
api: {
|
|
296
|
+
id: getClientApiId(api.apiPb.metadata.name, api.pageName),
|
|
297
|
+
apiName: api.apiPb.metadata.name,
|
|
298
|
+
// TODO(saksham): get pagename more defensively
|
|
299
|
+
pageName: getPageName(filePath),
|
|
300
|
+
scopeId,
|
|
301
|
+
},
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
if (filePath in this.tsFiles) {
|
|
305
|
+
delete this.tsFiles[filePath];
|
|
306
|
+
this.sourceTracker?.removeFile(filePath);
|
|
307
|
+
this.emit("deletePage", filePath);
|
|
308
|
+
}
|
|
309
|
+
break;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
getApiFiles() {
|
|
315
|
+
return this.formatApisToClientApis(this.apiFiles);
|
|
316
|
+
}
|
|
317
|
+
getTsFilePaths() {
|
|
318
|
+
return Object.keys(this.tsFiles);
|
|
319
|
+
}
|
|
320
|
+
async writeFile(path, content, kind) {
|
|
321
|
+
if (kind === "ts") {
|
|
322
|
+
// happens eagerly regardless of error - possible desync
|
|
323
|
+
this.tsFiles[path] = content;
|
|
324
|
+
// TODO(george): as an optimization, we could update the memory snapshot of the file that SyncService is holding
|
|
325
|
+
await this.fsOperationQueue.enqueue(async () => {
|
|
326
|
+
await fs.writeFile(path, content);
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
else if (kind === "api") {
|
|
330
|
+
const currentApiFile = this.apiFiles[path];
|
|
331
|
+
const apiPb = yaml.parse(content);
|
|
332
|
+
// Client APIs have id, but server APIs don't
|
|
333
|
+
if (apiPb.metadata.id) {
|
|
334
|
+
delete apiPb.metadata.id;
|
|
335
|
+
}
|
|
336
|
+
const stepPathMap = currentApiFile?.stepPathMap ?? {};
|
|
337
|
+
this.updateApi({ api: apiPb, stepPathMap }, path);
|
|
338
|
+
// TODO(george): as an optimization, we could update the memory snapshot of the file that SyncService is holding
|
|
339
|
+
await this.fsOperationQueue.enqueue(async () => {
|
|
340
|
+
await writeApiFiles({ apiPb }, "api", path.split("/").slice(0, -1).join("/"), false, [], [], { extractLargeSourceFiles: true, minLinesForExtraction: 1 }, new Set(Object.keys(this.apiFiles)), stepPathMap);
|
|
341
|
+
// stepPathMap will be generated after the write when the file doesn't exist
|
|
342
|
+
if (this.apiFiles[path]) {
|
|
343
|
+
this.apiFiles[path].stepPathMap = stepPathMap;
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
readFile(path) {
|
|
349
|
+
return this.tsFiles[path];
|
|
350
|
+
}
|
|
351
|
+
initializeSourceTracker() {
|
|
352
|
+
this.sourceTracker = new SourceTracker();
|
|
353
|
+
this.sourceTracker.initializeSourceTracker({
|
|
354
|
+
files: this.tsFiles,
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
handleNonVisualChangeByDeletingIds(path, content) {
|
|
358
|
+
if (!this.sourceTracker) {
|
|
359
|
+
throw new Error("Source tracker not initialized");
|
|
360
|
+
}
|
|
361
|
+
return this.sourceTracker.handleNonVisualChangeByDeletingIds(path, content);
|
|
362
|
+
}
|
|
363
|
+
async getFileWithIds(path) {
|
|
364
|
+
const logger = getLogger();
|
|
365
|
+
if (!this.sourceTracker) {
|
|
366
|
+
throw new Error("Source tracker not initialized");
|
|
367
|
+
}
|
|
368
|
+
const files = this.sourceTracker.getCurrentFiles();
|
|
369
|
+
if (!files[path]) {
|
|
370
|
+
throw new Error("File not found in source tracker " + path);
|
|
371
|
+
}
|
|
372
|
+
const ast = files[path].ast;
|
|
373
|
+
if (!ast) {
|
|
374
|
+
throw new Error("No AST found for file in source tracker " + path);
|
|
375
|
+
}
|
|
376
|
+
const clonedAst = await transformFromAstAsync(ast, undefined, {
|
|
377
|
+
ast: true,
|
|
378
|
+
});
|
|
379
|
+
if (!clonedAst?.ast) {
|
|
380
|
+
throw new Error("Failed to clone AST for file " + path);
|
|
381
|
+
}
|
|
382
|
+
const processedTransactions = this.getProcessedTransactionsWithNonce();
|
|
383
|
+
const customImports = new Set();
|
|
384
|
+
let customBuildTraversal = {};
|
|
385
|
+
if (isCustomBuildEnabled()) {
|
|
386
|
+
customBuildTraversal = {
|
|
387
|
+
ImportDeclaration(path) {
|
|
388
|
+
// when we see a custom component, we want to track the import and modify it to point
|
|
389
|
+
// to the built source
|
|
390
|
+
modifyLegacyCustomComponentImports(path, customImports);
|
|
391
|
+
},
|
|
392
|
+
JSXElement(path) {
|
|
393
|
+
// based on the imports we see, we want to modify the JSXElement that uses the custom component
|
|
394
|
+
modifyLegacyCustomComponentElements(path, customImports);
|
|
395
|
+
},
|
|
396
|
+
Program: {
|
|
397
|
+
// we want to write the wrapped custom elements as local variables to the file
|
|
398
|
+
exit(path) {
|
|
399
|
+
addLegacyCustomComponentVariables(path, customImports);
|
|
400
|
+
},
|
|
401
|
+
},
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
traverse(clonedAst.ast, {
|
|
405
|
+
...customBuildTraversal,
|
|
406
|
+
ReturnStatement(path) {
|
|
407
|
+
const argument = path.get("argument");
|
|
408
|
+
if (!argument.isJSXElement()) {
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
const openingElement = argument.get("openingElement");
|
|
412
|
+
if (!openingElement.isJSXOpeningElement()) {
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
openingElement.pushContainer("attributes", makeJSXAttribute(ROOT_WIDGET_ATTRIBUTE, "true"));
|
|
416
|
+
openingElement.pushContainer("attributes", generateJSXAttribute(PROCESSED_TRANSACTIONS_ATTRIBUTE, {
|
|
417
|
+
value: processedTransactions,
|
|
418
|
+
type: "EXPRESSION",
|
|
419
|
+
__info: true,
|
|
420
|
+
}));
|
|
421
|
+
},
|
|
422
|
+
JSXOpeningElement(path) {
|
|
423
|
+
const elementId = getSbElementId(path.node);
|
|
424
|
+
if (elementId) {
|
|
425
|
+
path.pushContainer("attributes", makeJSXAttribute(WIDGET_SOURCE_ID_ATTRIBUTE, elementId));
|
|
426
|
+
}
|
|
427
|
+
},
|
|
428
|
+
ObjectProperty(path) {
|
|
429
|
+
const elementId = getSbElementId(path.node);
|
|
430
|
+
if (!elementId) {
|
|
431
|
+
path.skip();
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
path.traverse({
|
|
435
|
+
ObjectExpression(path) {
|
|
436
|
+
path.pushContainer("properties", t.objectProperty(t.identifier("id"), t.stringLiteral(elementId)));
|
|
437
|
+
path.skip();
|
|
438
|
+
},
|
|
439
|
+
});
|
|
440
|
+
},
|
|
441
|
+
});
|
|
442
|
+
try {
|
|
443
|
+
const result = generate(clonedAst.ast);
|
|
444
|
+
return result.code;
|
|
445
|
+
}
|
|
446
|
+
catch (e) {
|
|
447
|
+
logger.error("Error generating file with ids", getErrorMeta(e));
|
|
448
|
+
return null;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
getLocalBindingEntities(path) {
|
|
452
|
+
const logger = getLogger();
|
|
453
|
+
const files = this.sourceTracker?.getCurrentFiles();
|
|
454
|
+
if (!files || !files[path]) {
|
|
455
|
+
logger.warn(`File not found in source tracker for local binding entities: ${path}`);
|
|
456
|
+
return [];
|
|
457
|
+
}
|
|
458
|
+
const ast = files[path].ast;
|
|
459
|
+
if (!ast) {
|
|
460
|
+
logger.warn(`No AST found for file in source tracker for local binding entities: ${path}`);
|
|
461
|
+
return [];
|
|
462
|
+
}
|
|
463
|
+
const localBindingEntities = new Set();
|
|
464
|
+
traverse(ast, {
|
|
465
|
+
JSXOpeningElement(path) {
|
|
466
|
+
const elementId = getSbElementId(path.node);
|
|
467
|
+
if (!elementId) {
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
470
|
+
const hasLocalBinding = doesElementHaveBinding(path);
|
|
471
|
+
if (hasLocalBinding) {
|
|
472
|
+
localBindingEntities.add(elementId);
|
|
473
|
+
}
|
|
474
|
+
},
|
|
475
|
+
});
|
|
476
|
+
return Array.from(localBindingEntities);
|
|
477
|
+
}
|
|
478
|
+
pendingTransactions = new Set();
|
|
479
|
+
processedTransactions = [];
|
|
480
|
+
flushTransactions = () => {
|
|
481
|
+
// TODO do something more sophisticated than this.
|
|
482
|
+
this.processedTransactions = this.processedTransactions.slice(-20);
|
|
483
|
+
this.processedTransactions.push(...Array.from(this.pendingTransactions));
|
|
484
|
+
this.pendingTransactions.clear();
|
|
485
|
+
};
|
|
486
|
+
trackTransaction = (transactionId) => {
|
|
487
|
+
if (!transactionId) {
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
this.pendingTransactions.add(transactionId);
|
|
491
|
+
};
|
|
492
|
+
transactionNonce = Date.now();
|
|
493
|
+
// Until we have a sophisticated way to track ALL operations, including non-UI initiated ops, we will use a nonce
|
|
494
|
+
// TODO https://github.com/superblocksteam/superblocks/pull/11788
|
|
495
|
+
getProcessedTransactionsWithNonce() {
|
|
496
|
+
const nonce = `t-${this.transactionNonce++}`;
|
|
497
|
+
return this.processedTransactions.concat(nonce);
|
|
498
|
+
}
|
|
499
|
+
handleCreatePage = async (payload) => {
|
|
500
|
+
const { name } = payload;
|
|
501
|
+
if (!this.rootDir) {
|
|
502
|
+
throw new Error("Root directory not set");
|
|
503
|
+
}
|
|
504
|
+
const pagePath = getPageFolder(this.rootDir, name);
|
|
505
|
+
const pageIndexPath = path.join(pagePath, "index.tsx");
|
|
506
|
+
const pageContent = /*js*/ `import { SbPage, SbContainer, registerPage } from "@superblocksteam/library";
|
|
507
|
+
function Page() {
|
|
508
|
+
return <SbPage name="${name}">
|
|
509
|
+
<SbContainer width={Dim.fill()} />
|
|
510
|
+
</SbPage>;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
export default registerPage(Page, { name: "${name}" });
|
|
514
|
+
`;
|
|
515
|
+
await fs.mkdir(pagePath, { recursive: true });
|
|
516
|
+
await this.writeFile(pageIndexPath, pageContent, "ts");
|
|
517
|
+
await this.handleNonVisualChangeByDeletingIds(pageIndexPath, pageContent);
|
|
518
|
+
this.emit("addPage", pageIndexPath);
|
|
519
|
+
};
|
|
520
|
+
handleReparent = async (payload, writeFile = true) => {
|
|
521
|
+
const { from, to, changedProps, transaction } = payload;
|
|
522
|
+
this.trackTransaction(transaction?.id);
|
|
523
|
+
await this.sourceTracker?.setProperties({
|
|
524
|
+
source: from.source,
|
|
525
|
+
changes: changedProps ?? {},
|
|
526
|
+
});
|
|
527
|
+
await this.sourceTracker?.moveElement({
|
|
528
|
+
from,
|
|
529
|
+
to,
|
|
530
|
+
});
|
|
531
|
+
if (writeFile) {
|
|
532
|
+
const changes = (await this.sourceTracker?.getAndFlushChanges()) ?? [];
|
|
533
|
+
await this.writeChanges(changes ?? [], (fileName) => {
|
|
534
|
+
this.emit("reparent", fileName);
|
|
535
|
+
});
|
|
536
|
+
this.flushTransactions();
|
|
537
|
+
}
|
|
538
|
+
};
|
|
539
|
+
handleCreateComponent = async (payload, writeFile = true) => {
|
|
540
|
+
this.trackTransaction(payload.transaction?.id);
|
|
541
|
+
const sourceId = await this.sourceTracker?.addElement(payload);
|
|
542
|
+
if (writeFile) {
|
|
543
|
+
const changes = (await this.sourceTracker?.getAndFlushChanges()) ?? [];
|
|
544
|
+
await this.writeChanges(changes ?? [], (fileName) => {
|
|
545
|
+
this.emit("createComponent", fileName);
|
|
546
|
+
});
|
|
547
|
+
this.flushTransactions();
|
|
548
|
+
}
|
|
549
|
+
return sourceId;
|
|
550
|
+
};
|
|
551
|
+
handleDeleteComponents = async (payload, writeFile = true) => {
|
|
552
|
+
const { elements, transaction } = payload;
|
|
553
|
+
this.trackTransaction(transaction?.id);
|
|
554
|
+
for (const element of elements) {
|
|
555
|
+
await this.sourceTracker?.deleteElement({
|
|
556
|
+
source: element.source,
|
|
557
|
+
scopeName: element.scopeName,
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
if (writeFile) {
|
|
561
|
+
const changes = (await this.sourceTracker?.getAndFlushChanges()) ?? [];
|
|
562
|
+
await this.writeChanges(changes ?? [], (fileName) => {
|
|
563
|
+
this.emit("deleteComponents", fileName, elements.map((el) => el.source.id));
|
|
564
|
+
});
|
|
565
|
+
this.flushTransactions();
|
|
566
|
+
}
|
|
567
|
+
};
|
|
568
|
+
handleSetProperty = async (payload, writeFile = true) => {
|
|
569
|
+
const { element: { source }, property, value: { value, type }, transaction, } = payload;
|
|
570
|
+
this.trackTransaction(transaction?.id);
|
|
571
|
+
await this.sourceTracker?.setProperty({
|
|
572
|
+
source,
|
|
573
|
+
property,
|
|
574
|
+
value: value,
|
|
575
|
+
type,
|
|
576
|
+
});
|
|
577
|
+
if (writeFile) {
|
|
578
|
+
const changes = (await this.sourceTracker?.getAndFlushChanges()) ?? [];
|
|
579
|
+
await this.writeChanges(changes ?? []);
|
|
580
|
+
this.flushTransactions();
|
|
581
|
+
}
|
|
582
|
+
this.emit("setProperty", payload);
|
|
583
|
+
};
|
|
584
|
+
handleSetProperties = async (payload, writeFile = true) => {
|
|
585
|
+
const { element: { source }, properties, transaction, } = payload;
|
|
586
|
+
this.trackTransaction(transaction?.id);
|
|
587
|
+
await this.sourceTracker?.setProperties({
|
|
588
|
+
source,
|
|
589
|
+
changes: properties,
|
|
590
|
+
});
|
|
591
|
+
if (writeFile) {
|
|
592
|
+
const changes = (await this.sourceTracker?.getAndFlushChanges()) ?? [];
|
|
593
|
+
await this.writeChanges(changes ?? []);
|
|
594
|
+
this.flushTransactions();
|
|
595
|
+
}
|
|
596
|
+
this.emit("setProperties", payload);
|
|
597
|
+
};
|
|
598
|
+
handleDeleteProperties = async (payload, writeFile = true) => {
|
|
599
|
+
this.trackTransaction(payload.transaction?.id);
|
|
600
|
+
await this.sourceTracker?.deleteProperties({
|
|
601
|
+
source: payload.element.source,
|
|
602
|
+
properties: payload.properties,
|
|
603
|
+
});
|
|
604
|
+
if (writeFile) {
|
|
605
|
+
const changes = (await this.sourceTracker?.getAndFlushChanges()) ?? [];
|
|
606
|
+
await this.writeChanges(changes ?? []);
|
|
607
|
+
this.flushTransactions();
|
|
608
|
+
}
|
|
609
|
+
this.emit("deleteProperties", payload);
|
|
610
|
+
};
|
|
611
|
+
handleBatchUpdate = async (payload) => {
|
|
612
|
+
const { updates, transaction } = payload;
|
|
613
|
+
this.trackTransaction(transaction?.id);
|
|
614
|
+
const returnValues = [];
|
|
615
|
+
for (const update of updates) {
|
|
616
|
+
switch (update.type) {
|
|
617
|
+
case "editor:setProperty":
|
|
618
|
+
returnValues.push(await this.handleSetProperty(update.payload, false));
|
|
619
|
+
break;
|
|
620
|
+
case "editor:setProperties":
|
|
621
|
+
returnValues.push(await this.handleSetProperties(update.payload, false));
|
|
622
|
+
break;
|
|
623
|
+
case "editor:moveComponent":
|
|
624
|
+
returnValues.push(await this.handleReparent(update.payload, false));
|
|
625
|
+
break;
|
|
626
|
+
case "editor:createComponent":
|
|
627
|
+
returnValues.push(await this.handleCreateComponent(update.payload, false));
|
|
628
|
+
break;
|
|
629
|
+
case "editor:deleteProperties":
|
|
630
|
+
returnValues.push(await this.handleDeleteProperties(update.payload, false));
|
|
631
|
+
break;
|
|
632
|
+
case "editor:deleteComponents":
|
|
633
|
+
returnValues.push(await this.handleDeleteComponents(update.payload, false));
|
|
634
|
+
break;
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
const changes = (await this.sourceTracker?.getAndFlushChanges()) ?? [];
|
|
638
|
+
await this.writeChanges(changes ?? []);
|
|
639
|
+
this.emit("batchUpdate", Array.from(new Set(changes.map((c) => c.fileName))));
|
|
640
|
+
this.flushTransactions();
|
|
641
|
+
return returnValues;
|
|
642
|
+
};
|
|
643
|
+
handleUpdateApi = async (payload) => {
|
|
644
|
+
const { api } = payload;
|
|
645
|
+
if (!this.sourceTracker) {
|
|
646
|
+
throw new Error("Source tracker not initialized");
|
|
647
|
+
}
|
|
648
|
+
if (!this.rootDir) {
|
|
649
|
+
throw new Error("Root directory not set");
|
|
650
|
+
}
|
|
651
|
+
if (!api.pageName) {
|
|
652
|
+
throw new Error("API page name is not set");
|
|
653
|
+
}
|
|
654
|
+
const apiName = api.apiPb.metadata.name;
|
|
655
|
+
if (!apiName) {
|
|
656
|
+
throw new Error("API name is not set");
|
|
657
|
+
}
|
|
658
|
+
const apiDir = path.join(this.rootDir, "pages", api.pageName, "apis", apiName);
|
|
659
|
+
const apiPath = path.join(apiDir, "api.yaml");
|
|
660
|
+
const isNewApi = !this.getApiFiles()[apiPath];
|
|
661
|
+
try {
|
|
662
|
+
const stats = await fs.stat(apiDir);
|
|
663
|
+
if (!stats.isDirectory()) {
|
|
664
|
+
await fs.mkdir(apiDir, { recursive: true });
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
catch {
|
|
668
|
+
await fs.mkdir(apiDir, { recursive: true });
|
|
669
|
+
}
|
|
670
|
+
await this.writeFile(apiPath, yaml.stringify(api.apiPb), "api");
|
|
671
|
+
const generationNumber = this.generationNumberSequence.next();
|
|
672
|
+
const apiDef = this.createClientApi(api);
|
|
673
|
+
let scopeId = "";
|
|
674
|
+
if (isNewApi) {
|
|
675
|
+
scopeId = await this.createScopedApi(api);
|
|
676
|
+
}
|
|
677
|
+
else {
|
|
678
|
+
const scopeDef = this.sourceTracker.getScopeDefinitionForPage(api.pageName);
|
|
679
|
+
scopeId = scopeDef?.id ?? "";
|
|
680
|
+
}
|
|
681
|
+
this.emit("apiUpdate", { api: apiDef, scopeId });
|
|
682
|
+
return { api: apiDef, scopeId, generationNumber };
|
|
683
|
+
};
|
|
684
|
+
createScopedApi = async (api) => {
|
|
685
|
+
if (!this.sourceTracker) {
|
|
686
|
+
throw new Error("Source tracker not initialized");
|
|
687
|
+
}
|
|
688
|
+
// We want to add the API entity to our scope, but we do not want to emit entity events, because
|
|
689
|
+
// the API update event handles this particular side effect.
|
|
690
|
+
const scopeId = await this.sourceTracker.addApi({
|
|
691
|
+
pageName: api.pageName,
|
|
692
|
+
apiName: api.apiPb.metadata.name,
|
|
693
|
+
});
|
|
694
|
+
const changes = (await this.sourceTracker?.getAndFlushChanges()) ?? [];
|
|
695
|
+
await this.writeChanges(changes);
|
|
696
|
+
return scopeId;
|
|
697
|
+
};
|
|
698
|
+
handleDeleteApi = async (payload) => {
|
|
699
|
+
const logger = getLogger();
|
|
700
|
+
const { apis } = payload;
|
|
701
|
+
if (!this.rootDir) {
|
|
702
|
+
throw new Error("Root directory not set");
|
|
703
|
+
}
|
|
704
|
+
const rootDir = this.rootDir;
|
|
705
|
+
const executeDeleteApis = Promise.all(apis.map(({ apiName, pageName }) => {
|
|
706
|
+
return new Promise(
|
|
707
|
+
// eslint-disable-next-line no-async-promise-executor
|
|
708
|
+
async (resolve) => {
|
|
709
|
+
const apiFilePath = path.join(rootDir, "pages", pageName, "apis", apiName, "api.yaml");
|
|
710
|
+
const api = this.apiFiles[apiFilePath];
|
|
711
|
+
if (!api || !this.sourceTracker) {
|
|
712
|
+
return resolve(undefined);
|
|
713
|
+
}
|
|
714
|
+
const apiDir = path.join(rootDir, "pages", pageName, "apis", apiName);
|
|
715
|
+
try {
|
|
716
|
+
const stats = await fs.stat(apiDir);
|
|
717
|
+
if (stats.isDirectory()) {
|
|
718
|
+
await fs.rmdir(apiDir, { recursive: true });
|
|
719
|
+
}
|
|
720
|
+
delete this.apiFiles[apiFilePath];
|
|
721
|
+
const scopeId = await this.sourceTracker.deleteApi({
|
|
722
|
+
pageName,
|
|
723
|
+
apiName,
|
|
724
|
+
});
|
|
725
|
+
resolve({
|
|
726
|
+
apiName,
|
|
727
|
+
pageName,
|
|
728
|
+
scopeId,
|
|
729
|
+
});
|
|
730
|
+
}
|
|
731
|
+
catch (e) {
|
|
732
|
+
logger.warn(`Could not delete api ${apiFilePath} ${JSON.stringify(e)}`);
|
|
733
|
+
resolve(undefined);
|
|
734
|
+
}
|
|
735
|
+
resolve(undefined);
|
|
736
|
+
});
|
|
737
|
+
}));
|
|
738
|
+
const deletedApis = (await executeDeleteApis).filter((api) => api !== undefined);
|
|
739
|
+
const changes = (await this.sourceTracker?.getAndFlushChanges()) ?? [];
|
|
740
|
+
await this.writeChanges(changes);
|
|
741
|
+
this.emit("apiDelete", {
|
|
742
|
+
apis: deletedApis.filter((api) => api !== undefined),
|
|
743
|
+
});
|
|
744
|
+
return { deletedApis };
|
|
745
|
+
};
|
|
746
|
+
handleRenameApi = async (payload) => {
|
|
747
|
+
const { oldName, newName, pageName } = payload;
|
|
748
|
+
if (!this.rootDir) {
|
|
749
|
+
throw new Error("Root directory not set");
|
|
750
|
+
}
|
|
751
|
+
const pagePath = getPageFolder(this.rootDir, pageName);
|
|
752
|
+
const existingApiFolder = path.join(this.rootDir, "pages", pageName, "apis", oldName);
|
|
753
|
+
const newApiFolder = path.join(this.rootDir, "pages", pageName, "apis", newName);
|
|
754
|
+
const files = this.sourceTracker?.getCurrentFiles();
|
|
755
|
+
const file = files?.[path.join(pagePath, "index.tsx")];
|
|
756
|
+
if (!file || !file.ast) {
|
|
757
|
+
throw new Error(`Page ${pageName} not found`);
|
|
758
|
+
}
|
|
759
|
+
const apiFilePath = path.join(existingApiFolder, "api.yaml");
|
|
760
|
+
const apiDef = this.apiFiles[apiFilePath];
|
|
761
|
+
if (!apiDef) {
|
|
762
|
+
throw new Error(`API ${oldName} not found`);
|
|
763
|
+
}
|
|
764
|
+
const otherPageAPIs = structuredClone(Object.keys(this.apiFiles)
|
|
765
|
+
.filter((path) => path.startsWith(pagePath) && path !== apiFilePath)
|
|
766
|
+
.map((path) => ({
|
|
767
|
+
api: { apiPb: this.apiFiles[path]?.apiPb },
|
|
768
|
+
filePath: path,
|
|
769
|
+
}))
|
|
770
|
+
.filter((api) => !!api.api));
|
|
771
|
+
const newApiFolderExists = await fs.stat(newApiFolder).catch(() => false);
|
|
772
|
+
if (newApiFolderExists) {
|
|
773
|
+
throw new Error(`API ${newName} already exists`);
|
|
774
|
+
}
|
|
775
|
+
this.watcher?.unwatch(existingApiFolder);
|
|
776
|
+
this.watcher?.unwatch(newApiFolder);
|
|
777
|
+
apiDef.apiPb.metadata.name = newName;
|
|
778
|
+
await fs.rename(existingApiFolder, newApiFolder);
|
|
779
|
+
const scopeDef = this.sourceTracker?.getScopeDefinitionForPage(pageName);
|
|
780
|
+
if (!scopeDef) {
|
|
781
|
+
throw new Error(`Scope definition not found for API`);
|
|
782
|
+
}
|
|
783
|
+
this.sourceTracker?.renameEntity({
|
|
784
|
+
oldName,
|
|
785
|
+
newName,
|
|
786
|
+
entityId: scopeDef.scopeNameToEntityId[oldName],
|
|
787
|
+
});
|
|
788
|
+
delete this.apiFiles[apiFilePath];
|
|
789
|
+
this.writeFile(path.join(newApiFolder, "api.yaml"), yaml.stringify(apiDef.apiPb), "api");
|
|
790
|
+
this.watcher?.add(existingApiFolder);
|
|
791
|
+
this.watcher?.add(newApiFolder);
|
|
792
|
+
const changes = (await this.sourceTracker?.getAndFlushChanges()) ?? [];
|
|
793
|
+
await this.writeChanges(changes);
|
|
794
|
+
this.emit("apiManualUpdate", {
|
|
795
|
+
api: this.createClientApi(apiDef),
|
|
796
|
+
oldName,
|
|
797
|
+
pageName,
|
|
798
|
+
scopeId: scopeDef?.id ?? "",
|
|
799
|
+
}, true);
|
|
800
|
+
await this.renameManager.renameEntityInApis({
|
|
801
|
+
oldName,
|
|
802
|
+
newName,
|
|
803
|
+
apis: otherPageAPIs,
|
|
804
|
+
});
|
|
805
|
+
// only save the APIs that have changed
|
|
806
|
+
await Promise.all(otherPageAPIs.map(async ({ api, filePath }) => {
|
|
807
|
+
if (isEqual(api?.apiPb, this.apiFiles[filePath]?.apiPb)) {
|
|
808
|
+
return Promise.resolve();
|
|
809
|
+
}
|
|
810
|
+
await this.writeFile(filePath, yaml.stringify(api?.apiPb), "api");
|
|
811
|
+
this.emit("apiManualUpdate", {
|
|
812
|
+
api: this.createClientApi(api),
|
|
813
|
+
pageName,
|
|
814
|
+
scopeId: scopeDef?.id ?? "",
|
|
815
|
+
}, true);
|
|
816
|
+
// TODO: Should I delete here?
|
|
817
|
+
}));
|
|
818
|
+
};
|
|
819
|
+
handleAddEntity = async (payload) => {
|
|
820
|
+
await this.sourceTracker?.addEntity({
|
|
821
|
+
scopeId: payload.scopeId,
|
|
822
|
+
entity: {
|
|
823
|
+
type: payload.type,
|
|
824
|
+
name: payload.name,
|
|
825
|
+
attributes: payload.attributes,
|
|
826
|
+
},
|
|
827
|
+
});
|
|
828
|
+
const changes = (await this.sourceTracker?.getAndFlushChanges()) ?? [];
|
|
829
|
+
await this.writeChanges(changes, (fileName) => {
|
|
830
|
+
this.emit("addEntity", fileName, payload);
|
|
831
|
+
});
|
|
832
|
+
};
|
|
833
|
+
handleUpdateEntity = async (payload) => {
|
|
834
|
+
await this.sourceTracker?.updateEntity({
|
|
835
|
+
entityId: payload.entityId,
|
|
836
|
+
updates: payload.updates,
|
|
837
|
+
});
|
|
838
|
+
const changes = (await this.sourceTracker?.getAndFlushChanges()) ?? [];
|
|
839
|
+
await this.writeChanges(changes, (fileName) => {
|
|
840
|
+
this.emit("updateEntity", fileName, payload);
|
|
841
|
+
});
|
|
842
|
+
};
|
|
843
|
+
handleDeleteEntity = async (payload) => {
|
|
844
|
+
const deletedEntityName = await this.sourceTracker?.deleteEntity({
|
|
845
|
+
entityId: payload.entityId,
|
|
846
|
+
});
|
|
847
|
+
const changes = (await this.sourceTracker?.getAndFlushChanges()) ?? [];
|
|
848
|
+
await this.writeChanges(changes, (fileName) => {
|
|
849
|
+
if (deletedEntityName) {
|
|
850
|
+
this.emit("deleteEntity", fileName, deletedEntityName);
|
|
851
|
+
}
|
|
852
|
+
});
|
|
853
|
+
};
|
|
854
|
+
handleUpdateTheme = async (payload) => {
|
|
855
|
+
const { theme } = payload;
|
|
856
|
+
if (!this.rootDir) {
|
|
857
|
+
throw new Error("Root directory not set");
|
|
858
|
+
}
|
|
859
|
+
const filePath = path.join(this.rootDir, APP_THEME_FILE_NAME);
|
|
860
|
+
await this.sourceTracker?.updateTheme({
|
|
861
|
+
themeFilePath: filePath,
|
|
862
|
+
theme,
|
|
863
|
+
});
|
|
864
|
+
const changes = (await this.sourceTracker?.getAndFlushChanges()) ?? [];
|
|
865
|
+
await this.writeChanges(changes);
|
|
866
|
+
};
|
|
867
|
+
handleRenameElement = async (payload) => {
|
|
868
|
+
if (payload.kind === "component") {
|
|
869
|
+
return this.handleRenameComponent(payload);
|
|
870
|
+
}
|
|
871
|
+
else if (payload.kind === "entity") {
|
|
872
|
+
return this.handleRenameEntity(payload);
|
|
873
|
+
}
|
|
874
|
+
else if (payload.kind === "page") {
|
|
875
|
+
return this.handleRenamePage(payload);
|
|
876
|
+
}
|
|
877
|
+
};
|
|
878
|
+
handleRenameComponent = async (payload) => {
|
|
879
|
+
const { elementId, newName, oldName, scopeName } = payload;
|
|
880
|
+
await this.sourceTracker?.renameComponent({
|
|
881
|
+
widgetSourceId: elementId,
|
|
882
|
+
oldName,
|
|
883
|
+
newName,
|
|
884
|
+
scopeName,
|
|
885
|
+
});
|
|
886
|
+
await this.renameIdentifierInApis({
|
|
887
|
+
elementId,
|
|
888
|
+
oldName,
|
|
889
|
+
newName,
|
|
890
|
+
});
|
|
891
|
+
const changes = (await this.sourceTracker?.getAndFlushChanges()) ?? [];
|
|
892
|
+
await this.writeChanges(changes, (fileName) => {
|
|
893
|
+
this.emit("renameComponent", fileName);
|
|
894
|
+
});
|
|
895
|
+
};
|
|
896
|
+
handleRenameEntity = async (payload) => {
|
|
897
|
+
const { elementId, newName, oldName, scopeName } = payload;
|
|
898
|
+
await this.sourceTracker?.renameEntity({
|
|
899
|
+
entityId: elementId,
|
|
900
|
+
oldName,
|
|
901
|
+
newName,
|
|
902
|
+
scopeName,
|
|
903
|
+
});
|
|
904
|
+
await this.renameIdentifierInApis(payload);
|
|
905
|
+
const changes = (await this.sourceTracker?.getAndFlushChanges()) ?? [];
|
|
906
|
+
await this.writeChanges(changes, (fileName) => {
|
|
907
|
+
this.emit("renameEntity", fileName);
|
|
908
|
+
});
|
|
909
|
+
};
|
|
910
|
+
handleRenamePage = async (payload) => {
|
|
911
|
+
const { newName, oldName } = payload;
|
|
912
|
+
if (!this.rootDir) {
|
|
913
|
+
throw new Error("Root directory not set");
|
|
914
|
+
}
|
|
915
|
+
const newPageFolder = getPageFolder(this.rootDir, newName);
|
|
916
|
+
const newIndexFilePath = path.join(newPageFolder, "index.tsx");
|
|
917
|
+
const oldIndexFilePath = path.join(this.rootDir, "pages", oldName, "index.tsx");
|
|
918
|
+
const oldPageFolder = getPageFolder(this.rootDir, oldName);
|
|
919
|
+
this.watcher?.unwatch(newPageFolder);
|
|
920
|
+
this.watcher?.unwatch(oldPageFolder);
|
|
921
|
+
const existingRoute = Object.keys(this.routes).find((route) => this.routes[route]?.file ===
|
|
922
|
+
this.getRelativeRoutePath(oldIndexFilePath));
|
|
923
|
+
if (!existingRoute) {
|
|
924
|
+
throw new Error(`Route for ${oldName} not found`);
|
|
925
|
+
}
|
|
926
|
+
// Write the name attribute to the page file
|
|
927
|
+
await this.sourceTracker?.renamePage({
|
|
928
|
+
newName,
|
|
929
|
+
filePath: oldIndexFilePath,
|
|
930
|
+
});
|
|
931
|
+
const changes = (await this.sourceTracker?.getAndFlushChanges()) ?? [];
|
|
932
|
+
await this.writeChanges(changes);
|
|
933
|
+
// A rename of a folder is an unlink followed by an add, so the file watcher will take over initializing this
|
|
934
|
+
// "new" page
|
|
935
|
+
await fs.rename(oldPageFolder, newPageFolder);
|
|
936
|
+
// Now we just clean up the routes
|
|
937
|
+
await this.removeRoute(oldIndexFilePath);
|
|
938
|
+
await this.addRoute(existingRoute, newIndexFilePath);
|
|
939
|
+
const newIndexFile = await readFile(newIndexFilePath);
|
|
940
|
+
if (!newIndexFile) {
|
|
941
|
+
throw new Error(`New index file ${newIndexFilePath} not found`);
|
|
942
|
+
}
|
|
943
|
+
this.tsFiles[newIndexFilePath] = newIndexFile;
|
|
944
|
+
await this.handleNonVisualChangeByDeletingIds(newIndexFilePath, newIndexFile);
|
|
945
|
+
this.emit("renamePage", newIndexFilePath);
|
|
946
|
+
// Re-add the watcher
|
|
947
|
+
this.watcher?.add(newPageFolder);
|
|
948
|
+
this.watcher?.add(oldPageFolder);
|
|
949
|
+
};
|
|
950
|
+
getPageRoots(filePath) {
|
|
951
|
+
const scopeFilePath = path.join(path.dirname(filePath), "index.tsx");
|
|
952
|
+
const currentFile = this.sourceTracker?.getCurrentFiles()[scopeFilePath];
|
|
953
|
+
if (!currentFile) {
|
|
954
|
+
return null;
|
|
955
|
+
}
|
|
956
|
+
return getPageRoots(filePath, currentFile);
|
|
957
|
+
}
|
|
958
|
+
getScope(filePath) {
|
|
959
|
+
// get the scope.ts file in the same directory as path
|
|
960
|
+
const scopeFilePath = path.join(path.dirname(filePath), SCOPE_FILE);
|
|
961
|
+
const currentFile = this.sourceTracker?.getCurrentFiles()[scopeFilePath];
|
|
962
|
+
if (!currentFile) {
|
|
963
|
+
console.log("File not found", scopeFilePath);
|
|
964
|
+
return null;
|
|
965
|
+
}
|
|
966
|
+
const scope = getScope(scopeFilePath, currentFile);
|
|
967
|
+
return scope;
|
|
968
|
+
}
|
|
969
|
+
getRoutes() {
|
|
970
|
+
const routes = [];
|
|
971
|
+
for (const [path, { file }] of Object.entries(this.routes)) {
|
|
972
|
+
routes.push({
|
|
973
|
+
path,
|
|
974
|
+
component: file,
|
|
975
|
+
});
|
|
976
|
+
}
|
|
977
|
+
return routes;
|
|
978
|
+
}
|
|
979
|
+
async addRoute(route, filePath) {
|
|
980
|
+
if (!this.rootDir) {
|
|
981
|
+
throw new Error("Root directory not set");
|
|
982
|
+
}
|
|
983
|
+
this.routes[route] = { file: this.getRelativeRoutePath(filePath) };
|
|
984
|
+
await this.writeFile(path.join(this.rootDir, ROUTES_FILE), JSON.stringify(this.routes, null, 2));
|
|
985
|
+
}
|
|
986
|
+
async removeRoute(filePath) {
|
|
987
|
+
if (!this.rootDir) {
|
|
988
|
+
throw new Error("Root directory not set");
|
|
989
|
+
}
|
|
990
|
+
const relativeFilePath = this.getRelativeRoutePath(filePath);
|
|
991
|
+
this.routes = Object.fromEntries(Object.entries(this.routes).filter(([_, value]) => value.file !== relativeFilePath));
|
|
992
|
+
await this.writeFile(path.join(this.rootDir, ROUTES_FILE), JSON.stringify(this.routes, null, 2));
|
|
993
|
+
}
|
|
994
|
+
async writeChanges(changes, callback) {
|
|
995
|
+
return Promise.all(changes.map(async ({ fileName, source, kind }) => {
|
|
996
|
+
await this.writeFile(fileName, source, kind);
|
|
997
|
+
return callback?.(fileName, source);
|
|
998
|
+
}));
|
|
999
|
+
}
|
|
1000
|
+
getNodeForWidgetSourceId(id) {
|
|
1001
|
+
return this.sourceTracker?.getElementToLocation(id);
|
|
1002
|
+
}
|
|
1003
|
+
getAstForWidgetSourceId(id) {
|
|
1004
|
+
const filePath = this.sourceTracker?.getElementToFilePath(id);
|
|
1005
|
+
if (!filePath) {
|
|
1006
|
+
return null;
|
|
1007
|
+
}
|
|
1008
|
+
return this.sourceTracker?.getCurrentFiles()[filePath]?.ast;
|
|
1009
|
+
}
|
|
1010
|
+
renameIdentifierInApis = async ({ elementId, oldName, newName, parentBinding, }) => {
|
|
1011
|
+
const apisInScope = structuredClone(this.getApisInScope(elementId));
|
|
1012
|
+
await this.renameManager.renameEntityInApis({
|
|
1013
|
+
oldName,
|
|
1014
|
+
newName,
|
|
1015
|
+
parentBinding,
|
|
1016
|
+
apis: apisInScope,
|
|
1017
|
+
});
|
|
1018
|
+
// only save the APIs that have changed
|
|
1019
|
+
await Promise.all(apisInScope.map(({ api, filePath }) => {
|
|
1020
|
+
if (isEqual(api?.apiPb, this.apiFiles[filePath]?.apiPb)) {
|
|
1021
|
+
return Promise.resolve();
|
|
1022
|
+
}
|
|
1023
|
+
return this.writeFile(filePath, yaml.stringify(api?.apiPb), "api");
|
|
1024
|
+
}));
|
|
1025
|
+
};
|
|
1026
|
+
getApisInScope = (elementId) => {
|
|
1027
|
+
const filePath = this.sourceTracker?.getElementToFilePath(elementId);
|
|
1028
|
+
if (!filePath) {
|
|
1029
|
+
return [];
|
|
1030
|
+
}
|
|
1031
|
+
const pagePath = path.dirname(filePath);
|
|
1032
|
+
return Object.entries(this.apiFiles)
|
|
1033
|
+
.filter(([filePath]) => filePath.includes(pagePath))
|
|
1034
|
+
.map(([filePath, api]) => ({ api, filePath }));
|
|
1035
|
+
};
|
|
1036
|
+
getRelativeRoutePath(filePath) {
|
|
1037
|
+
if (!this.rootDir) {
|
|
1038
|
+
throw new Error("Root directory not set");
|
|
1039
|
+
}
|
|
1040
|
+
// no leading slash
|
|
1041
|
+
return path.relative(path.join(this.rootDir, PAGES_DIRECTORY), filePath);
|
|
1042
|
+
}
|
|
1043
|
+
// Utilities for converting server API format to Client API format
|
|
1044
|
+
// We internally save the API as the server does, but we return should always return it
|
|
1045
|
+
// to the client with an id generated as PageName_ApiName
|
|
1046
|
+
createClientApi(api) {
|
|
1047
|
+
return {
|
|
1048
|
+
pageName: api.pageName,
|
|
1049
|
+
apiPb: {
|
|
1050
|
+
...api.apiPb,
|
|
1051
|
+
metadata: {
|
|
1052
|
+
...api.apiPb.metadata,
|
|
1053
|
+
id: getClientApiId(api.apiPb.metadata.name, api.pageName),
|
|
1054
|
+
},
|
|
1055
|
+
},
|
|
1056
|
+
};
|
|
1057
|
+
}
|
|
1058
|
+
formatApisToClientApis(serverApis) {
|
|
1059
|
+
return Object.keys(serverApis).reduce((acc, key) => {
|
|
1060
|
+
if (!serverApis[key]) {
|
|
1061
|
+
return acc;
|
|
1062
|
+
}
|
|
1063
|
+
acc[key] = {
|
|
1064
|
+
api: this.createClientApi(serverApis[key]),
|
|
1065
|
+
scopeId: serverApis[key].scopeId,
|
|
1066
|
+
};
|
|
1067
|
+
return acc;
|
|
1068
|
+
}, {});
|
|
1069
|
+
}
|
|
1070
|
+
async processApiUpdates(filePath, fileType) {
|
|
1071
|
+
let yamlPath = filePath;
|
|
1072
|
+
if (fileType.type === "python-api-step" ||
|
|
1073
|
+
fileType.type === "js-api-step") {
|
|
1074
|
+
const apiFolderPath = filePath.split("/").slice(0, -1).join("/");
|
|
1075
|
+
yamlPath = path.join(apiFolderPath, "api.yaml");
|
|
1076
|
+
}
|
|
1077
|
+
const logger = getLogger();
|
|
1078
|
+
try {
|
|
1079
|
+
const apiContent = await getMergedApiContent(yamlPath);
|
|
1080
|
+
if (!isValidApi(apiContent.api)) {
|
|
1081
|
+
return;
|
|
1082
|
+
}
|
|
1083
|
+
if (!apiContent) {
|
|
1084
|
+
return;
|
|
1085
|
+
}
|
|
1086
|
+
const parsedData = { apiPb: apiContent?.api };
|
|
1087
|
+
if (!(yamlPath in this.apiFiles &&
|
|
1088
|
+
isEqual(this.apiFiles[yamlPath]?.apiPb, parsedData.apiPb))) {
|
|
1089
|
+
const { updatedApi, pageName, isNewApi } = this.updateApi({
|
|
1090
|
+
api: parsedData.apiPb,
|
|
1091
|
+
stepPathMap: apiContent.stepPathMap,
|
|
1092
|
+
}, yamlPath);
|
|
1093
|
+
logger.info(`API changed: ${yamlPath}`);
|
|
1094
|
+
const scopeDef = this.sourceTracker?.getScopeDefinitionForPage(pageName);
|
|
1095
|
+
if (!scopeDef) {
|
|
1096
|
+
logger.error(`Scope definition not found for API`);
|
|
1097
|
+
return;
|
|
1098
|
+
}
|
|
1099
|
+
if (isNewApi) {
|
|
1100
|
+
await this.createScopedApi(updatedApi);
|
|
1101
|
+
}
|
|
1102
|
+
this.emit("apiManualUpdate", {
|
|
1103
|
+
api: this.createClientApi(updatedApi),
|
|
1104
|
+
pageName,
|
|
1105
|
+
scopeId: scopeDef.id,
|
|
1106
|
+
}, isNewApi);
|
|
1107
|
+
}
|
|
1108
|
+
else {
|
|
1109
|
+
logger.info(`File unchanged from last tracked state: ${filePath}`);
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
catch {
|
|
1113
|
+
logger.info(`API file incomplete: ${yamlPath}`);
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
// Add new mock implementation
|
|
1118
|
+
export class MockFileSyncManager extends FileSyncManager {
|
|
1119
|
+
tsFiles = {};
|
|
1120
|
+
apiFiles = {};
|
|
1121
|
+
async watch(_watcher, _path) {
|
|
1122
|
+
// Mock implementation doesn't actually watch files
|
|
1123
|
+
}
|
|
1124
|
+
async writeFile(path, content, kind) {
|
|
1125
|
+
await this.fsOperationQueue.enqueue(async () => {
|
|
1126
|
+
if (kind === "ts") {
|
|
1127
|
+
this.tsFiles[path] = content;
|
|
1128
|
+
}
|
|
1129
|
+
else {
|
|
1130
|
+
this.apiFiles[path] = {
|
|
1131
|
+
apiPb: yaml.parse(content),
|
|
1132
|
+
pageName: getPageName(path),
|
|
1133
|
+
stepPathMap: {},
|
|
1134
|
+
// TODO: generate a scope ID for tests
|
|
1135
|
+
scopeId: "",
|
|
1136
|
+
};
|
|
1137
|
+
}
|
|
1138
|
+
// Notify subscribers
|
|
1139
|
+
this.emit("fileChanged", path, content, true);
|
|
1140
|
+
});
|
|
1141
|
+
}
|
|
1142
|
+
// Helper methods for testing
|
|
1143
|
+
mockFileChange(path, content) {
|
|
1144
|
+
this.tsFiles[path] = content;
|
|
1145
|
+
this.emit("fileChanged", path, content, true);
|
|
1146
|
+
}
|
|
1147
|
+
handleUpdateApi = async (payload) => {
|
|
1148
|
+
const apiName = payload.api.apiPb.metadata.name;
|
|
1149
|
+
this.apiFiles[apiName] = {
|
|
1150
|
+
...payload.api,
|
|
1151
|
+
stepPathMap: {},
|
|
1152
|
+
scopeId: payload.scopeId,
|
|
1153
|
+
};
|
|
1154
|
+
const scopeDef = this.sourceTracker?.getScopeDefinitionForPage(payload.api.pageName);
|
|
1155
|
+
const generationNumber = this.generationNumberSequence.next();
|
|
1156
|
+
this.emit("apiUpdate", {
|
|
1157
|
+
api: payload.api,
|
|
1158
|
+
scopeId: scopeDef?.id ?? "",
|
|
1159
|
+
});
|
|
1160
|
+
return {
|
|
1161
|
+
api: payload.api,
|
|
1162
|
+
generationNumber,
|
|
1163
|
+
scopeId: scopeDef?.id ?? "",
|
|
1164
|
+
};
|
|
1165
|
+
};
|
|
1166
|
+
getSourceTracker() {
|
|
1167
|
+
return this.sourceTracker;
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
async function readFile(path) {
|
|
1171
|
+
try {
|
|
1172
|
+
// in order for try-catch to work, we need to intentionally await the readFile call,
|
|
1173
|
+
// otherwise the error won't be be caught
|
|
1174
|
+
// see: https://github.com/nodejs/node/issues/51894#issuecomment-1974017737
|
|
1175
|
+
const content = await fs.readFile(path, "utf-8");
|
|
1176
|
+
return content;
|
|
1177
|
+
}
|
|
1178
|
+
catch (e) {
|
|
1179
|
+
getLogger().error(`error reading file: ${path}`, getErrorMeta(e));
|
|
1180
|
+
return null;
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
async function readFiles(dir) {
|
|
1184
|
+
return await glob(path.join(dir, "**/*.{tsx,yaml,ts}"), {
|
|
1185
|
+
ignore: [
|
|
1186
|
+
"node_modules/**",
|
|
1187
|
+
"dist/**",
|
|
1188
|
+
"build/**",
|
|
1189
|
+
".superblocks/**",
|
|
1190
|
+
`./${getLegacyComponentsFolder()}/**`,
|
|
1191
|
+
],
|
|
1192
|
+
});
|
|
1193
|
+
}
|
|
1194
|
+
const getMergedApiContent = async (path) => {
|
|
1195
|
+
return readAppApiYamlFile(path.split("/").slice(0, -1).join("/"));
|
|
1196
|
+
};
|
|
1197
|
+
const getPageName = (path) => {
|
|
1198
|
+
const parts = path.split("/");
|
|
1199
|
+
const pagesIndex = parts.findIndex((part) => part === "pages");
|
|
1200
|
+
if (pagesIndex !== -1 && parts[pagesIndex + 1]) {
|
|
1201
|
+
return parts[pagesIndex + 1] ?? "";
|
|
1202
|
+
}
|
|
1203
|
+
return "";
|
|
1204
|
+
};
|
|
1205
|
+
//# sourceMappingURL=file-system-manager.js.map
|