@dxos/plugin-routine 0.9.1-staging.ee54ba693a → 0.11.0
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/PLUGIN.mdl +18 -13
- package/dist/lib/RoutinePlugin.mjs +2 -0
- package/dist/lib/RoutinePlugin.node.mjs +894 -0
- package/dist/lib/RoutinePlugin.node.mjs.map +1 -0
- package/dist/lib/RoutinePlugin.workerd.mjs +20 -0
- package/dist/lib/RoutinePlugin.workerd.mjs.map +1 -0
- package/dist/lib/capabilities/node.mjs +12 -0
- package/dist/lib/capabilities/node.mjs.map +1 -0
- package/dist/lib/capabilities.mjs +14 -0
- package/dist/lib/capabilities.mjs.map +1 -0
- package/dist/lib/chunk-RoutineArticle.mjs +79 -0
- package/dist/lib/chunk-RoutineArticle.mjs.map +1 -0
- package/dist/lib/chunk-RoutineCompanion.mjs +192 -0
- package/dist/lib/chunk-RoutineCompanion.mjs.map +1 -0
- package/dist/lib/chunk-RoutinePlugin.mjs +38 -0
- package/dist/lib/chunk-RoutinePlugin.mjs.map +1 -0
- package/dist/lib/chunk-RoutineSettings.mjs +50 -0
- package/dist/lib/chunk-RoutineSettings.mjs.map +1 -0
- package/dist/lib/chunk-RoutineTraceCompanion.mjs +208 -0
- package/dist/lib/chunk-RoutineTraceCompanion.mjs.map +1 -0
- package/dist/lib/chunk-SkillArticle.mjs +28 -0
- package/dist/lib/chunk-SkillArticle.mjs.map +1 -0
- package/dist/lib/chunk-app-graph-builder.mjs +71 -0
- package/dist/lib/chunk-app-graph-builder.mjs.map +1 -0
- package/dist/lib/chunk-create-object.mjs +23 -0
- package/dist/lib/chunk-create-object.mjs.map +1 -0
- package/dist/lib/chunk-create-routine.mjs +34 -0
- package/dist/lib/chunk-create-routine.mjs.map +1 -0
- package/dist/lib/chunk-create-trigger-from-template.mjs +48 -0
- package/dist/lib/chunk-create-trigger-from-template.mjs.map +1 -0
- package/dist/lib/chunk-layer-specs.mjs +179 -0
- package/dist/lib/chunk-layer-specs.mjs.map +1 -0
- package/dist/lib/{neutral/chunk-HLO4LYXT.mjs → chunk-meta.mjs} +19 -27
- package/dist/lib/chunk-meta.mjs.map +1 -0
- package/dist/lib/chunk-operation-handler.mjs +11 -0
- package/dist/lib/chunk-operation-handler.mjs.map +1 -0
- package/dist/lib/chunk-paths.mjs +11 -0
- package/dist/lib/chunk-paths.mjs.map +1 -0
- package/dist/lib/chunk-react-surface.mjs +64 -0
- package/dist/lib/chunk-react-surface.mjs.map +1 -0
- package/dist/lib/chunk-registry-sync.mjs +104 -0
- package/dist/lib/chunk-registry-sync.mjs.map +1 -0
- package/dist/lib/chunk-run-routine.mjs +57 -0
- package/dist/lib/chunk-run-routine.mjs.map +1 -0
- package/dist/lib/chunk-templates.mjs +37 -0
- package/dist/lib/chunk-templates.mjs.map +1 -0
- package/dist/lib/chunk-trigger-runtime-controller.mjs +73 -0
- package/dist/lib/chunk-trigger-runtime-controller.mjs.map +1 -0
- package/dist/lib/chunk-types.mjs +149 -0
- package/dist/lib/chunk-types.mjs.map +1 -0
- package/dist/lib/chunk-util.mjs +142 -0
- package/dist/lib/chunk-util.mjs.map +1 -0
- package/dist/lib/components.mjs +1645 -0
- package/dist/lib/components.mjs.map +1 -0
- package/dist/lib/containers.mjs +11 -0
- package/dist/lib/containers.mjs.map +1 -0
- package/dist/lib/hooks.mjs +37 -0
- package/dist/lib/hooks.mjs.map +1 -0
- package/dist/lib/index.mjs +5 -0
- package/dist/lib/meta.mjs +2 -0
- package/dist/lib/operations.mjs +7 -0
- package/dist/lib/operations.mjs.map +1 -0
- package/dist/lib/plugin.mjs +9 -0
- package/dist/lib/plugin.mjs.map +1 -0
- package/dist/lib/testing.mjs +2 -0
- package/dist/lib/translations.mjs +110 -0
- package/dist/lib/translations.mjs.map +1 -0
- package/dist/lib/types.mjs +2 -0
- package/dist/types/src/RoutinePlugin.d.ts.map +1 -1
- package/dist/types/src/RoutinePlugin.node.d.ts.map +1 -1
- package/dist/types/src/RoutinePlugin.workerd.d.ts.map +1 -1
- package/dist/types/src/capabilities/app-graph-builder.d.ts +1 -1
- package/dist/types/src/capabilities/create-object.d.ts +1 -1
- package/dist/types/src/capabilities/index.d.ts +0 -1
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/layer-specs.d.ts +1 -1
- package/dist/types/src/capabilities/operation-handler.d.ts +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
- package/dist/types/src/capabilities/registry-sync.d.ts +1 -1
- package/dist/types/src/capabilities/templates.d.ts +1 -1
- package/dist/types/src/capabilities/trigger-runtime-controller.d.ts +1 -1
- package/dist/types/src/commands/trigger/create/{queue.d.ts → feed.d.ts} +2 -2
- package/dist/types/src/commands/trigger/create/feed.d.ts.map +1 -0
- package/dist/types/src/commands/trigger/update/{queue.d.ts → feed.d.ts} +2 -2
- package/dist/types/src/commands/trigger/update/feed.d.ts.map +1 -0
- package/dist/types/src/commands/trigger/util.d.ts +1 -1
- package/dist/types/src/commands/trigger/util.d.ts.map +1 -1
- package/dist/types/src/components/InstructionsEditor/InstructionsEditor.d.ts +7 -5
- package/dist/types/src/components/InstructionsEditor/InstructionsEditor.d.ts.map +1 -1
- package/dist/types/src/components/InstructionsEditor/InstructionsEditor.stories.d.ts +3 -3
- package/dist/types/src/components/InstructionsEditor/InstructionsEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/RoutineCard/RoutineCard.d.ts +9 -0
- package/dist/types/src/components/RoutineCard/RoutineCard.d.ts.map +1 -0
- package/dist/types/src/components/RoutineCard/RoutineCard.stories.d.ts +21 -0
- package/dist/types/src/components/RoutineCard/RoutineCard.stories.d.ts.map +1 -0
- package/dist/types/src/components/RoutineCard/index.d.ts +2 -0
- package/dist/types/src/components/RoutineCard/index.d.ts.map +1 -0
- package/dist/types/src/components/RoutineForm/RoutineForm.d.ts +7 -2
- package/dist/types/src/components/RoutineForm/RoutineForm.d.ts.map +1 -1
- package/dist/types/src/components/Schedule/Schedule.d.ts +2 -26
- package/dist/types/src/components/Schedule/Schedule.d.ts.map +1 -1
- package/dist/types/src/components/Schedule/days.d.ts +24 -0
- package/dist/types/src/components/Schedule/days.d.ts.map +1 -0
- package/dist/types/src/components/Schedule/describe-schedule.d.ts +3 -0
- package/dist/types/src/components/Schedule/describe-schedule.d.ts.map +1 -0
- package/dist/types/src/components/Schedule/index.d.ts +2 -0
- package/dist/types/src/components/Schedule/index.d.ts.map +1 -1
- package/dist/types/src/components/TemplateEditor/TemplateEditor.d.ts +1 -1
- package/dist/types/src/components/TemplateEditor/TemplateEditor.d.ts.map +1 -1
- package/dist/types/src/components/TriggerEditor/TriggerEditor.d.ts +1 -2
- package/dist/types/src/components/TriggerEditor/TriggerEditor.d.ts.map +1 -1
- package/dist/types/src/components/TriggerEditor/TriggerKindSelector.d.ts +5 -2
- package/dist/types/src/components/TriggerEditor/TriggerKindSelector.d.ts.map +1 -1
- package/dist/types/src/components/TriggerEditor/trigger-kind-icon.d.ts +5 -0
- package/dist/types/src/components/TriggerEditor/trigger-kind-icon.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +1 -1
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/containers/RoutineArticle/RoutineArticle.d.ts +5 -10
- package/dist/types/src/containers/RoutineArticle/RoutineArticle.d.ts.map +1 -1
- package/dist/types/src/containers/RoutineArticle/RoutineArticle.stories.d.ts +6 -2
- package/dist/types/src/containers/RoutineArticle/RoutineArticle.stories.d.ts.map +1 -1
- package/dist/types/src/containers/RoutineCompanion/RoutineCompanion.d.ts +4 -12
- package/dist/types/src/containers/RoutineCompanion/RoutineCompanion.d.ts.map +1 -1
- package/dist/types/src/containers/RoutineCompanion/RoutineCompanion.stories.d.ts.map +1 -1
- package/dist/types/src/containers/RoutineSettings/RoutineSettings.d.ts +4 -8
- package/dist/types/src/containers/RoutineSettings/RoutineSettings.d.ts.map +1 -1
- package/dist/types/src/containers/RoutineTraceCompanion/RoutineTraceCompanion.d.ts +5 -3
- package/dist/types/src/containers/RoutineTraceCompanion/RoutineTraceCompanion.d.ts.map +1 -1
- package/dist/types/src/containers/RoutineTraceCompanion/RoutineTraceCompanion.stories.d.ts.map +1 -1
- package/dist/types/src/containers/RoutineTraceCompanion/useRoutineRuns.d.ts +1 -1
- package/dist/types/src/containers/RoutineTraceCompanion/useRoutineRuns.d.ts.map +1 -1
- package/dist/types/src/containers/SkillArticle/SkillArticle.d.ts +4 -1
- package/dist/types/src/containers/SkillArticle/SkillArticle.d.ts.map +1 -1
- package/dist/types/src/hooks/useTriggerRuntimeControls.d.ts +1 -1
- package/dist/types/src/hooks/useTriggerRuntimeControls.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/operations/run-routine.d.ts.map +1 -1
- package/dist/types/src/operations/run-routine.test.d.ts +2 -0
- package/dist/types/src/operations/run-routine.test.d.ts.map +1 -0
- package/dist/types/src/paths.d.ts.map +1 -1
- package/dist/types/src/templates/index.d.ts +1 -1
- package/dist/types/src/templates/index.d.ts.map +1 -1
- package/dist/types/src/testing/test-functions.d.ts +30 -6
- package/dist/types/src/testing/test-functions.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/RoutineCapabilities.d.ts +9 -3
- package/dist/types/src/types/RoutineCapabilities.d.ts.map +1 -1
- package/dist/types/src/types/RoutineOperation.d.ts +2 -3
- package/dist/types/src/types/RoutineOperation.d.ts.map +1 -1
- package/dist/types/src/types/index.d.ts +0 -1
- package/dist/types/src/types/index.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +1 -0
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/src/util/routines-for-object.d.ts +6 -3
- package/dist/types/src/util/routines-for-object.d.ts.map +1 -1
- package/dist/types/src/util/wire.d.ts +21 -0
- package/dist/types/src/util/wire.d.ts.map +1 -0
- package/dist/types/src/util/wire.test.d.ts +2 -0
- package/dist/types/src/util/wire.test.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/dx.config.ts +3 -2
- package/package.json +73 -71
- package/src/RoutinePlugin.node.ts +1 -2
- package/src/RoutinePlugin.tsx +2 -4
- package/src/RoutinePlugin.workerd.ts +1 -2
- package/src/capabilities/app-graph-builder.ts +9 -7
- package/src/capabilities/create-object.ts +2 -2
- package/src/capabilities/index.ts +0 -1
- package/src/capabilities/layer-specs.ts +78 -12
- package/src/capabilities/{react-surface.tsx → react-surface.ts} +18 -22
- package/src/capabilities/trigger-runtime-controller.test.ts +12 -18
- package/src/capabilities/trigger-runtime-controller.ts +22 -25
- package/src/commands/trigger/create/{queue.ts → feed.ts} +1 -1
- package/src/commands/trigger/create/index.ts +2 -2
- package/src/commands/trigger/update/{queue.ts → feed.ts} +1 -1
- package/src/commands/trigger/update/index.ts +2 -2
- package/src/commands/trigger/util.ts +1 -2
- package/src/components/InstructionsEditor/InstructionsEditor.stories.tsx +7 -6
- package/src/components/InstructionsEditor/InstructionsEditor.tsx +31 -19
- package/src/components/RoutineCard/RoutineCard.stories.tsx +95 -0
- package/src/components/RoutineCard/RoutineCard.tsx +60 -0
- package/src/components/{MasterDetail → RoutineCard}/index.ts +1 -1
- package/src/components/RoutineForm/RoutineForm.tsx +60 -52
- package/src/components/Schedule/Schedule.stories.tsx +1 -1
- package/src/components/Schedule/Schedule.tsx +4 -73
- package/src/components/Schedule/days.ts +18 -0
- package/src/components/Schedule/describe-schedule.ts +64 -0
- package/src/components/Schedule/index.ts +2 -0
- package/src/components/TemplateEditor/TemplateEditor.stories.tsx +1 -1
- package/src/components/TemplateEditor/TemplateForm.tsx +1 -1
- package/src/components/TriggerEditor/TriggerEditor.stories.tsx +3 -3
- package/src/components/TriggerEditor/TriggerEditor.tsx +79 -66
- package/src/components/TriggerEditor/TriggerKindSelector.tsx +4 -30
- package/src/components/TriggerEditor/trigger-kind-icon.ts +38 -0
- package/src/components/index.ts +1 -1
- package/src/containers/RoutineArticle/RoutineArticle.stories.tsx +78 -19
- package/src/containers/RoutineArticle/RoutineArticle.tsx +8 -4
- package/src/containers/RoutineCompanion/RoutineCompanion.stories.tsx +5 -4
- package/src/containers/RoutineCompanion/RoutineCompanion.tsx +11 -7
- package/src/containers/RoutineSettings/RoutineSettings.tsx +22 -33
- package/src/containers/RoutineTraceCompanion/RoutineTraceCompanion.stories.tsx +6 -5
- package/src/containers/RoutineTraceCompanion/RoutineTraceCompanion.tsx +3 -1
- package/src/containers/RoutineTraceCompanion/useRoutineRuns.ts +3 -5
- package/src/containers/SkillArticle/SkillArticle.tsx +2 -0
- package/src/hooks/useTriggerRuntimeControls.ts +2 -2
- package/src/index.ts +1 -0
- package/src/operations/create-routine.ts +1 -1
- package/src/operations/create-trigger-from-template.ts +2 -2
- package/src/operations/run-routine.test.ts +150 -0
- package/src/operations/run-routine.ts +18 -2
- package/src/paths.ts +5 -5
- package/src/templates/index.ts +5 -3
- package/src/translations.ts +5 -6
- package/src/types/RoutineCapabilities.ts +10 -4
- package/src/types/RoutineOperation.ts +7 -6
- package/src/types/index.ts +0 -1
- package/src/util/index.ts +1 -0
- package/src/util/routines-for-object.test.ts +37 -5
- package/src/util/routines-for-object.ts +33 -8
- package/src/util/wire.test.ts +77 -0
- package/src/util/wire.ts +76 -0
- package/dist/lib/neutral/RoutineArticle-UNTMV4CC.mjs +0 -95
- package/dist/lib/neutral/RoutineArticle-UNTMV4CC.mjs.map +0 -7
- package/dist/lib/neutral/RoutineCompanion-ZZ6WMY7I.mjs +0 -249
- package/dist/lib/neutral/RoutineCompanion-ZZ6WMY7I.mjs.map +0 -7
- package/dist/lib/neutral/RoutinePlugin.mjs +0 -10
- package/dist/lib/neutral/RoutinePlugin.mjs.map +0 -7
- package/dist/lib/neutral/RoutinePlugin.node.mjs +0 -1133
- package/dist/lib/neutral/RoutinePlugin.node.mjs.map +0 -7
- package/dist/lib/neutral/RoutinePlugin.workerd.mjs +0 -36
- package/dist/lib/neutral/RoutinePlugin.workerd.mjs.map +0 -7
- package/dist/lib/neutral/RoutineSettings-ZJOM4F3S.mjs +0 -48
- package/dist/lib/neutral/RoutineSettings-ZJOM4F3S.mjs.map +0 -7
- package/dist/lib/neutral/RoutineTraceCompanion-5U6R7LJE.mjs +0 -236
- package/dist/lib/neutral/RoutineTraceCompanion-5U6R7LJE.mjs.map +0 -7
- package/dist/lib/neutral/SkillArticle-WWDNKW2Z.mjs +0 -27
- package/dist/lib/neutral/SkillArticle-WWDNKW2Z.mjs.map +0 -7
- package/dist/lib/neutral/app-graph-builder-FALWLZTI.mjs +0 -90
- package/dist/lib/neutral/app-graph-builder-FALWLZTI.mjs.map +0 -7
- package/dist/lib/neutral/capabilities/index.mjs +0 -25
- package/dist/lib/neutral/capabilities/index.mjs.map +0 -7
- package/dist/lib/neutral/capabilities/node.mjs +0 -19
- package/dist/lib/neutral/capabilities/node.mjs.map +0 -7
- package/dist/lib/neutral/chunk-674LDIUJ.mjs +0 -9
- package/dist/lib/neutral/chunk-674LDIUJ.mjs.map +0 -7
- package/dist/lib/neutral/chunk-HLO4LYXT.mjs.map +0 -7
- package/dist/lib/neutral/chunk-J5LGTIGS.mjs +0 -10
- package/dist/lib/neutral/chunk-J5LGTIGS.mjs.map +0 -7
- package/dist/lib/neutral/chunk-P3TDQKOO.mjs +0 -8
- package/dist/lib/neutral/chunk-P3TDQKOO.mjs.map +0 -7
- package/dist/lib/neutral/chunk-R7J2MU2M.mjs +0 -263
- package/dist/lib/neutral/chunk-R7J2MU2M.mjs.map +0 -7
- package/dist/lib/neutral/chunk-WLNL77C7.mjs +0 -14
- package/dist/lib/neutral/chunk-WLNL77C7.mjs.map +0 -7
- package/dist/lib/neutral/chunk-YGWSAKLD.mjs +0 -65
- package/dist/lib/neutral/chunk-YGWSAKLD.mjs.map +0 -7
- package/dist/lib/neutral/components/index.mjs +0 -1921
- package/dist/lib/neutral/components/index.mjs.map +0 -7
- package/dist/lib/neutral/containers/index.mjs +0 -17
- package/dist/lib/neutral/containers/index.mjs.map +0 -7
- package/dist/lib/neutral/create-object-V23KVDMJ.mjs +0 -25
- package/dist/lib/neutral/create-object-V23KVDMJ.mjs.map +0 -7
- package/dist/lib/neutral/create-routine-6QBY6TWF.mjs +0 -38
- package/dist/lib/neutral/create-routine-6QBY6TWF.mjs.map +0 -7
- package/dist/lib/neutral/create-trigger-from-template-U3KNS77V.mjs +0 -70
- package/dist/lib/neutral/create-trigger-from-template-U3KNS77V.mjs.map +0 -7
- package/dist/lib/neutral/hooks/index.mjs +0 -47
- package/dist/lib/neutral/hooks/index.mjs.map +0 -7
- package/dist/lib/neutral/index.mjs +0 -27
- package/dist/lib/neutral/index.mjs.map +0 -7
- package/dist/lib/neutral/layer-specs-2TWJU5HI.mjs +0 -135
- package/dist/lib/neutral/layer-specs-2TWJU5HI.mjs.map +0 -7
- package/dist/lib/neutral/meta.json +0 -1
- package/dist/lib/neutral/meta.mjs +0 -8
- package/dist/lib/neutral/meta.mjs.map +0 -7
- package/dist/lib/neutral/navigation-resolver-KQIWUH6F.mjs +0 -18
- package/dist/lib/neutral/navigation-resolver-KQIWUH6F.mjs.map +0 -7
- package/dist/lib/neutral/operation-handler-QKLJSDCQ.mjs +0 -13
- package/dist/lib/neutral/operation-handler-QKLJSDCQ.mjs.map +0 -7
- package/dist/lib/neutral/operations/index.mjs +0 -8
- package/dist/lib/neutral/operations/index.mjs.map +0 -7
- package/dist/lib/neutral/plugin.mjs +0 -16
- package/dist/lib/neutral/plugin.mjs.map +0 -7
- package/dist/lib/neutral/react-surface-GMO7I7YE.mjs +0 -67
- package/dist/lib/neutral/react-surface-GMO7I7YE.mjs.map +0 -7
- package/dist/lib/neutral/registry-sync-DYPOC7ZG.mjs +0 -86
- package/dist/lib/neutral/registry-sync-DYPOC7ZG.mjs.map +0 -7
- package/dist/lib/neutral/run-routine-AEWO6SYD.mjs +0 -37
- package/dist/lib/neutral/run-routine-AEWO6SYD.mjs.map +0 -7
- package/dist/lib/neutral/templates-IIUCEBAX.mjs +0 -49
- package/dist/lib/neutral/templates-IIUCEBAX.mjs.map +0 -7
- package/dist/lib/neutral/testing.mjs +0 -8
- package/dist/lib/neutral/testing.mjs.map +0 -7
- package/dist/lib/neutral/translations.mjs +0 -115
- package/dist/lib/neutral/translations.mjs.map +0 -7
- package/dist/lib/neutral/trigger-runtime-controller-WIDDFGQT.mjs +0 -77
- package/dist/lib/neutral/trigger-runtime-controller-WIDDFGQT.mjs.map +0 -7
- package/dist/lib/neutral/types/index.mjs +0 -17
- package/dist/lib/neutral/types/index.mjs.map +0 -7
- package/dist/types/src/capabilities/navigation-resolver.d.ts +0 -5
- package/dist/types/src/capabilities/navigation-resolver.d.ts.map +0 -1
- package/dist/types/src/commands/trigger/create/queue.d.ts.map +0 -1
- package/dist/types/src/commands/trigger/update/queue.d.ts.map +0 -1
- package/dist/types/src/components/MasterDetail/MasterDetail.d.ts +0 -51
- package/dist/types/src/components/MasterDetail/MasterDetail.d.ts.map +0 -1
- package/dist/types/src/components/MasterDetail/MasterDetail.stories.d.ts +0 -16
- package/dist/types/src/components/MasterDetail/MasterDetail.stories.d.ts.map +0 -1
- package/dist/types/src/components/MasterDetail/index.d.ts +0 -2
- package/dist/types/src/components/MasterDetail/index.d.ts.map +0 -1
- package/dist/types/src/types/Routine.d.ts +0 -55
- package/dist/types/src/types/Routine.d.ts.map +0 -1
- package/dist/types/src/types/Routine.test.d.ts +0 -2
- package/dist/types/src/types/Routine.test.d.ts.map +0 -1
- package/src/capabilities/navigation-resolver.ts +0 -21
- package/src/components/MasterDetail/MasterDetail.stories.tsx +0 -100
- package/src/components/MasterDetail/MasterDetail.tsx +0 -175
- package/src/types/Routine.test.ts +0 -51
- package/src/types/Routine.ts +0 -144
|
@@ -0,0 +1,894 @@
|
|
|
1
|
+
import { ActivationEvent, ActivationEvents, Plugin } from "@dxos/app-framework";
|
|
2
|
+
import { AppActivationEvents, AppPlugin } from "@dxos/app-toolkit";
|
|
3
|
+
import { Operation, Routine, Trace, Trigger } from "@dxos/compute";
|
|
4
|
+
import { meta } from "#meta";
|
|
5
|
+
import { Annotation, Database, Entity, Feed, Filter, JsonSchema, Obj, Query, Ref, Scope, Type } from "@dxos/echo";
|
|
6
|
+
import { DXN as DXN$1, EID } from "@dxos/keys";
|
|
7
|
+
import { ClientEvents } from "@dxos/plugin-client";
|
|
8
|
+
import { AppGraphBuilder, LayerSpecs, OperationHandler, RegistrySync, Templates, TriggerRuntimeController } from "#capabilities";
|
|
9
|
+
import * as Command from "@effect/cli/Command";
|
|
10
|
+
import * as Options from "@effect/cli/Options";
|
|
11
|
+
import * as Prompt from "@effect/cli/Prompt";
|
|
12
|
+
import * as Console from "effect/Console";
|
|
13
|
+
import * as Effect from "effect/Effect";
|
|
14
|
+
import * as HashMap from "effect/HashMap";
|
|
15
|
+
import * as Option from "effect/Option";
|
|
16
|
+
import { CommandConfig, Common, FormBuilder, flushAndSync, print, printList, spaceIdWithDefault, spaceLayer, withTypes } from "@dxos/cli-util";
|
|
17
|
+
import * as Ansi from "@effect/printer-ansi/Ansi";
|
|
18
|
+
import * as Match from "effect/Match";
|
|
19
|
+
import * as SchemaAST from "effect/SchemaAST";
|
|
20
|
+
import { SchemaEx } from "@dxos/effect";
|
|
21
|
+
import { FeedAnnotation } from "@dxos/schema";
|
|
22
|
+
import { ClientService } from "@dxos/client";
|
|
23
|
+
import { Context } from "@dxos/context";
|
|
24
|
+
//#region src/commands/trigger/options.ts
|
|
25
|
+
var TriggerId = Options.text("id").pipe(Options.withDescription("The id of the trigger."));
|
|
26
|
+
var Enabled = Options.boolean("enabled", { ifPresent: true }).pipe(Options.withDescription("Whether the trigger is enabled."));
|
|
27
|
+
var Input = Options.keyValueMap("input").pipe(Options.withDescription("Input data to pass to the function. Must match the function's input schema."));
|
|
28
|
+
var Typename = Options.text("typename").pipe(Options.withDescription("The type name to query for the subscription trigger."));
|
|
29
|
+
var Deep = Options.boolean("deep", { ifPresent: true }).pipe(Options.withDescription("Watch changes to nested properties (not just creation)."));
|
|
30
|
+
var Delay = Options.integer("delay").pipe(Options.withDescription("Debounce changes with a delay in milliseconds."));
|
|
31
|
+
var Cron = Options.text("cron").pipe(Options.withDescription("The cron expression to use for the timer trigger."));
|
|
32
|
+
var Feed$1 = Options.text("feed").pipe(Options.withDescription("The EID of the feed for the feed trigger (echo://<spaceId>/<objectId>)."));
|
|
33
|
+
//#endregion
|
|
34
|
+
//#region src/commands/trigger/util.ts
|
|
35
|
+
/**
|
|
36
|
+
* Determines the remote status of a trigger.
|
|
37
|
+
* Only timer/cron triggers can be checked for remote availability.
|
|
38
|
+
*/
|
|
39
|
+
var getTriggerRemoteStatus = (trigger, remoteCronIds) => {
|
|
40
|
+
if (trigger.spec?.kind !== "timer") return "n/a";
|
|
41
|
+
return remoteCronIds.includes(trigger.id) ? "available" : "not available";
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Pretty prints a trigger with ANSI colors.
|
|
45
|
+
*/
|
|
46
|
+
var printTrigger = Effect.fn(function* (trigger, remoteStatus) {
|
|
47
|
+
const fn = trigger.runnable && (yield* Database.load(trigger.runnable));
|
|
48
|
+
return FormBuilder.make({ title: trigger.id }).pipe(FormBuilder.set("status", trigger.enabled ? "enabled" : "disabled", trigger.enabled ? Ansi.green : Ansi.blackBright), FormBuilder.option("kind", Option.fromNullable(trigger.spec?.kind)), FormBuilder.option("remote", Option.fromNullable(remoteStatus), Match.type().pipe(Match.withReturnType(), Match.when("available", () => Ansi.green), Match.when("not available", () => Ansi.yellow), Match.when("n/a", () => Ansi.blackBright), Match.exhaustive)), FormBuilder.when(fn, FormBuilder.nest("function", FormBuilder.make().pipe(FormBuilder.set("key", Obj.getMeta(fn).key), FormBuilder.set("dxn", Obj.getURI(fn))))), FormBuilder.nestedOption("spec", Option.fromNullable(trigger.spec).pipe(Option.map(printSpec))), FormBuilder.build);
|
|
49
|
+
});
|
|
50
|
+
var printSpec = (spec) => {
|
|
51
|
+
switch (spec.kind) {
|
|
52
|
+
case "timer": return printTimer(spec);
|
|
53
|
+
case "subscription": return printSubscription(spec);
|
|
54
|
+
case "webhook": return printWebhook(spec);
|
|
55
|
+
case "feed": return printFeed(spec);
|
|
56
|
+
default: return FormBuilder.make({}).pipe(FormBuilder.set("unknown", "Unknown spec type"));
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
var printTimer = (spec) => FormBuilder.make({}).pipe(FormBuilder.set("cron", spec.cron));
|
|
60
|
+
var printSubscription = (spec) => FormBuilder.make({}).pipe(FormBuilder.set("query", spec.query?.raw ?? "[Query AST]"));
|
|
61
|
+
var printWebhook = (spec) => FormBuilder.make({}).pipe(FormBuilder.set("method", spec.method), FormBuilder.set("port", spec.port));
|
|
62
|
+
var printFeed = (spec) => FormBuilder.make({}).pipe(FormBuilder.set("feed", spec.feed ? spec.feed.uri.toString() : "(none)"));
|
|
63
|
+
/**
|
|
64
|
+
* Prompts for input values based on an Effect schema.
|
|
65
|
+
* First shows a multi-select to choose which properties to specify,
|
|
66
|
+
* then prompts for values of the selected properties.
|
|
67
|
+
* Required properties are automatically included and cannot be unselected.
|
|
68
|
+
* @param schema - The Effect schema to prompt for
|
|
69
|
+
* @param defaults - Optional default values to use as initial values and pre-select optional properties
|
|
70
|
+
*/
|
|
71
|
+
var promptForSchemaInput = Effect.fn(function* (schema, defaults) {
|
|
72
|
+
if (!schema) return {};
|
|
73
|
+
const ast = schema.ast;
|
|
74
|
+
if (!SchemaAST.isTypeLiteral(ast)) return {};
|
|
75
|
+
const properties = SchemaEx.getProperties(ast);
|
|
76
|
+
if (properties.length === 0) return {};
|
|
77
|
+
const requiredProperties = [];
|
|
78
|
+
const optionalProperties = [];
|
|
79
|
+
for (const prop of properties) if (prop.isOptional) optionalProperties.push(prop);
|
|
80
|
+
else requiredProperties.push(prop);
|
|
81
|
+
const propertyInfo = properties.map((prop) => {
|
|
82
|
+
return {
|
|
83
|
+
prop,
|
|
84
|
+
key: prop.name.toString(),
|
|
85
|
+
isRequired: !prop.isOptional
|
|
86
|
+
};
|
|
87
|
+
});
|
|
88
|
+
const selectedKeys = /* @__PURE__ */ new Set();
|
|
89
|
+
for (const info of propertyInfo) if (info.isRequired) selectedKeys.add(info.key);
|
|
90
|
+
if (requiredProperties.length > 0) {
|
|
91
|
+
const requiredNames = requiredProperties.map((p) => {
|
|
92
|
+
return propertyInfo.find((i) => i.prop === p)?.key ?? p.name.toString();
|
|
93
|
+
});
|
|
94
|
+
yield* Console.log(`Required properties (will be included): ${requiredNames.join(", ")}`);
|
|
95
|
+
}
|
|
96
|
+
if (optionalProperties.length > 0) {
|
|
97
|
+
const choices = propertyInfo.filter((info) => !info.isRequired).map((info) => {
|
|
98
|
+
const hasDefault = defaults?.[info.key] !== void 0;
|
|
99
|
+
const defaultText = hasDefault ? ` (current: ${JSON.stringify(defaults[info.key])})` : "";
|
|
100
|
+
return {
|
|
101
|
+
title: `${info.key}${defaultText}`,
|
|
102
|
+
value: info.key,
|
|
103
|
+
description: hasDefault ? "Has default value" : void 0
|
|
104
|
+
};
|
|
105
|
+
});
|
|
106
|
+
const selected = yield* Prompt.multiSelect({
|
|
107
|
+
message: "Select optional properties to include:",
|
|
108
|
+
choices
|
|
109
|
+
});
|
|
110
|
+
for (const key of selected) selectedKeys.add(String(key));
|
|
111
|
+
}
|
|
112
|
+
if (selectedKeys.size === 0) return {};
|
|
113
|
+
const inputObj = {};
|
|
114
|
+
for (const info of propertyInfo) {
|
|
115
|
+
if (!selectedKeys.has(info.key)) continue;
|
|
116
|
+
const key = info.key;
|
|
117
|
+
const propType = info.prop.type;
|
|
118
|
+
const schemaDefault = Option.getOrUndefined(SchemaAST.getDefaultAnnotation(propType));
|
|
119
|
+
const defaultValue = defaults?.[key] ?? schemaDefault;
|
|
120
|
+
if (SchemaAST.isBooleanKeyword(propType)) {
|
|
121
|
+
const initialValue = typeof defaultValue === "boolean" ? defaultValue : typeof schemaDefault === "boolean" ? schemaDefault : false;
|
|
122
|
+
inputObj[key] = yield* Prompt.confirm({
|
|
123
|
+
message: `${info.key}${defaults?.[key] !== void 0 ? ` (current: ${defaults[key]})` : ""}:`,
|
|
124
|
+
initial: initialValue
|
|
125
|
+
});
|
|
126
|
+
} else if (SchemaAST.isNumberKeyword(propType)) {
|
|
127
|
+
const currentValue = typeof defaultValue === "number" ? String(defaultValue) : "";
|
|
128
|
+
const valueStr = yield* Prompt.text({ message: `${info.key}${currentValue ? ` (current: ${currentValue}, press Enter to keep)` : ""}:` }).pipe(Prompt.run);
|
|
129
|
+
inputObj[key] = valueStr === "" && defaultValue !== void 0 ? defaultValue : parseFloat(valueStr) || 0;
|
|
130
|
+
} else if (SchemaAST.isStringKeyword(propType)) {
|
|
131
|
+
const currentValue = typeof defaultValue === "string" ? defaultValue : "";
|
|
132
|
+
const valueStr = yield* Prompt.text({ message: `${info.key}${currentValue ? ` (current: ${currentValue}, press Enter to keep)` : ""}:` }).pipe(Prompt.run);
|
|
133
|
+
inputObj[key] = valueStr === "" && defaultValue !== void 0 ? defaultValue : valueStr;
|
|
134
|
+
} else if (Ref.isRefType(propType)) {
|
|
135
|
+
const isDefaultTemplate = typeof defaultValue === "string" && defaultValue.startsWith("{{") && defaultValue.endsWith("}}");
|
|
136
|
+
if (yield* Prompt.confirm({
|
|
137
|
+
message: `Use a template to specify ${info.key}?${isDefaultTemplate ? " (current: template)" : ""}`,
|
|
138
|
+
initial: isDefaultTemplate
|
|
139
|
+
})) {
|
|
140
|
+
const currentValue = typeof defaultValue === "string" ? defaultValue : "";
|
|
141
|
+
const templateStr = yield* Prompt.text({ message: `${info.key} template${currentValue ? ` (current: ${currentValue}, press Enter to keep)` : ""}:` }).pipe(Prompt.run);
|
|
142
|
+
inputObj[key] = templateStr === "" && defaultValue !== void 0 ? defaultValue : templateStr;
|
|
143
|
+
} else {
|
|
144
|
+
const annotation = Annotation.ReferenceAnnotation.getFromAst(propType).pipe(Option.getOrThrow);
|
|
145
|
+
const objects = yield* Database.query(Filter.type(DXN$1.make(annotation.typename))).run;
|
|
146
|
+
if (objects.length === 0) inputObj[key] = void 0;
|
|
147
|
+
else inputObj[key] = yield* Prompt.select({
|
|
148
|
+
message: `Select ${info.key}:`,
|
|
149
|
+
choices: objects.map((obj) => ({
|
|
150
|
+
title: Entity.getLabel(obj) ?? obj.id,
|
|
151
|
+
value: Ref.make(obj),
|
|
152
|
+
description: Entity.getDescription(obj)
|
|
153
|
+
}))
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
} else {
|
|
157
|
+
const currentValue = defaultValue !== void 0 ? String(defaultValue) : "";
|
|
158
|
+
const valueStr = yield* Prompt.text({ message: `${info.key}${currentValue ? ` (current: ${currentValue}, press Enter to keep)` : ""}:` }).pipe(Prompt.run);
|
|
159
|
+
inputObj[key] = valueStr === "" && defaultValue !== void 0 ? defaultValue : valueStr;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return inputObj;
|
|
163
|
+
});
|
|
164
|
+
/**
|
|
165
|
+
* Selects a function interactively from available functions in the database.
|
|
166
|
+
* Queries the database for functions and prompts the user to select one.
|
|
167
|
+
*/
|
|
168
|
+
var selectFunction = Effect.fn(function* () {
|
|
169
|
+
const functions = (yield* Database.query(Filter.type(Operation.PersistentOperation)).run).filter((fn) => Operation.isVisible(fn));
|
|
170
|
+
if (functions.length === 0) return yield* Effect.fail(/* @__PURE__ */ new Error("No functions available"));
|
|
171
|
+
const selected = yield* Prompt.select({
|
|
172
|
+
message: "Select a function:",
|
|
173
|
+
choices: functions.map((fn) => ({
|
|
174
|
+
title: fn.name ?? fn.id,
|
|
175
|
+
value: fn.id,
|
|
176
|
+
description: fn.description
|
|
177
|
+
}))
|
|
178
|
+
});
|
|
179
|
+
return String(selected);
|
|
180
|
+
});
|
|
181
|
+
/**
|
|
182
|
+
* Selects a trigger interactively from available triggers.
|
|
183
|
+
* If kind is provided, filters triggers by that kind.
|
|
184
|
+
* Queries the database for triggers and prompts the user to select one.
|
|
185
|
+
*/
|
|
186
|
+
var selectTrigger = Effect.fn(function* (kind) {
|
|
187
|
+
const triggers = yield* Database.query(Query.select(Filter.type(Trigger.Trigger)).debugLabel("cli.trigger.selectTrigger")).run;
|
|
188
|
+
const filteredTriggers = kind ? triggers.filter((trigger) => trigger.spec?.kind === kind) : triggers;
|
|
189
|
+
if (filteredTriggers.length === 0) return yield* Effect.fail(/* @__PURE__ */ new Error(kind ? `No ${kind} triggers available` : "No triggers available"));
|
|
190
|
+
const choices = yield* Effect.all(filteredTriggers.map((trigger) => Effect.gen(function* () {
|
|
191
|
+
const fn = trigger.runnable ? yield* Database.load(trigger.runnable) : void 0;
|
|
192
|
+
const title = (fn && Obj.instanceOf(Operation.PersistentOperation, fn) ? fn.name ?? Obj.getMeta(fn).key ?? fn.id : void 0) ?? trigger.id;
|
|
193
|
+
const description = `${trigger.enabled ? "enabled" : "disabled"} - ${trigger.spec?.kind ?? "unknown"}`;
|
|
194
|
+
return {
|
|
195
|
+
title,
|
|
196
|
+
value: trigger.id,
|
|
197
|
+
description
|
|
198
|
+
};
|
|
199
|
+
})));
|
|
200
|
+
const selected = yield* Prompt.select({
|
|
201
|
+
message: kind ? `Select a ${kind} trigger:` : "Select a trigger:",
|
|
202
|
+
choices
|
|
203
|
+
});
|
|
204
|
+
return String(selected);
|
|
205
|
+
});
|
|
206
|
+
/**
|
|
207
|
+
* Selects a feed interactively from available feeds in the database.
|
|
208
|
+
* Queries schemas with FeedAnnotation, then queries objects of those types,
|
|
209
|
+
* and returns the chosen Feed object.
|
|
210
|
+
*/
|
|
211
|
+
var selectFeed = Effect.fn(function* () {
|
|
212
|
+
const feedSchemas = (yield* Database.query(Query.select(Filter.type(Type.Type)).from(Scope.space(), Scope.registry())).run).filter((type) => {
|
|
213
|
+
const schema = Type.getSchema(type);
|
|
214
|
+
const annotation = FeedAnnotation.get(schema);
|
|
215
|
+
return Option.isSome(annotation) && annotation.value === true;
|
|
216
|
+
});
|
|
217
|
+
if (feedSchemas.length === 0) return yield* Effect.fail(/* @__PURE__ */ new Error("No schemas with Feed annotation found"));
|
|
218
|
+
const feedChoices = [];
|
|
219
|
+
for (const schema of feedSchemas) yield* Effect.gen(function* () {
|
|
220
|
+
const objects = yield* Database.query(Filter.type(Type.getURI(schema))).run;
|
|
221
|
+
for (const obj of objects) {
|
|
222
|
+
const feedRef = obj.feed;
|
|
223
|
+
if (!feedRef) continue;
|
|
224
|
+
const feedObj = yield* Effect.promise(() => feedRef.tryLoad());
|
|
225
|
+
if (!feedObj || !Obj.instanceOf(Feed.Feed, feedObj)) continue;
|
|
226
|
+
const label = Obj.getLabel(obj) ?? obj.id;
|
|
227
|
+
const description = Obj.getTypename(obj);
|
|
228
|
+
feedChoices.push({
|
|
229
|
+
title: label,
|
|
230
|
+
value: feedObj,
|
|
231
|
+
description
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
}).pipe(Effect.catchAll(() => Effect.void));
|
|
235
|
+
if (feedChoices.length === 0) return yield* Effect.fail(/* @__PURE__ */ new Error("No objects with feed properties found"));
|
|
236
|
+
return yield* Prompt.select({
|
|
237
|
+
message: "Select a feed:",
|
|
238
|
+
choices: feedChoices
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
/**
|
|
242
|
+
* Pretty prints trigger removal result with ANSI colors.
|
|
243
|
+
*/
|
|
244
|
+
var printTriggerRemoved = (id) => FormBuilder.make({ title: "Trigger removed" }).pipe(FormBuilder.set("id", id), FormBuilder.build);
|
|
245
|
+
//#endregion
|
|
246
|
+
//#region src/commands/trigger/create/feed.ts
|
|
247
|
+
var feed$1 = Command.make("feed", {
|
|
248
|
+
spaceId: Common.spaceId.pipe(Options.optional),
|
|
249
|
+
enabled: Enabled,
|
|
250
|
+
functionId: Common.functionId.pipe(Options.optional),
|
|
251
|
+
feed: Feed$1.pipe(Options.optional),
|
|
252
|
+
input: Input.pipe(Options.optional)
|
|
253
|
+
}, (options) => Effect.gen(function* () {
|
|
254
|
+
const { json } = yield* CommandConfig;
|
|
255
|
+
const functionId = yield* Option.match(options.functionId, {
|
|
256
|
+
onNone: () => selectFunction(),
|
|
257
|
+
onSome: (id) => Effect.succeed(id)
|
|
258
|
+
});
|
|
259
|
+
const fn = (yield* Database.query(Filter.type(Operation.PersistentOperation)).run).find((fn) => fn.id === functionId);
|
|
260
|
+
if (!fn) return yield* Effect.fail(/* @__PURE__ */ new Error(`Function not found: ${functionId}`));
|
|
261
|
+
const feed = yield* Option.match(options.feed, {
|
|
262
|
+
onNone: () => selectFeed(),
|
|
263
|
+
onSome: (uri) => Database.resolve(EID.parse(uri), Feed.Feed)
|
|
264
|
+
});
|
|
265
|
+
const input = yield* Option.match(options.input, {
|
|
266
|
+
onNone: () => promptForSchemaInput(fn.inputSchema ? JsonSchema.toEffectSchema(fn.inputSchema) : void 0),
|
|
267
|
+
onSome: (value) => Effect.succeed(Object.fromEntries(HashMap.toEntries(value)))
|
|
268
|
+
});
|
|
269
|
+
const enabled = yield* Option.match(options.functionId, {
|
|
270
|
+
onNone: () => Prompt.confirm({
|
|
271
|
+
message: "Enable the trigger?",
|
|
272
|
+
initial: true
|
|
273
|
+
}).pipe(Prompt.run),
|
|
274
|
+
onSome: () => Effect.succeed(options.enabled)
|
|
275
|
+
});
|
|
276
|
+
const trigger = Trigger.make({
|
|
277
|
+
runnable: Ref.make(fn),
|
|
278
|
+
enabled,
|
|
279
|
+
spec: Trigger.specFeed(feed),
|
|
280
|
+
input
|
|
281
|
+
});
|
|
282
|
+
yield* Database.add(trigger);
|
|
283
|
+
if (json) yield* Console.log(JSON.stringify(trigger, null, 2));
|
|
284
|
+
else yield* Console.log(print(yield* printTrigger(trigger)));
|
|
285
|
+
yield* flushAndSync({ indexes: true });
|
|
286
|
+
})).pipe(Command.withDescription("Create a feed trigger."), Command.provide(({ spaceId }) => spaceLayer(spaceId, true)), Command.provideEffectDiscard(() => withTypes(Operation.PersistentOperation, Trigger.Trigger)));
|
|
287
|
+
//#endregion
|
|
288
|
+
//#region src/commands/trigger/create/subscription.ts
|
|
289
|
+
var subscription$1 = Command.make("subscription", {
|
|
290
|
+
spaceId: Common.spaceId.pipe(Options.optional),
|
|
291
|
+
enabled: Enabled,
|
|
292
|
+
functionId: Common.functionId.pipe(Options.optional),
|
|
293
|
+
typename: Typename.pipe(Options.optional),
|
|
294
|
+
deep: Deep.pipe(Options.optional),
|
|
295
|
+
delay: Delay.pipe(Options.optional),
|
|
296
|
+
input: Input.pipe(Options.optional)
|
|
297
|
+
}, (options) => Effect.gen(function* () {
|
|
298
|
+
const { json } = yield* CommandConfig;
|
|
299
|
+
const functionId = yield* Option.match(options.functionId, {
|
|
300
|
+
onNone: () => selectFunction(),
|
|
301
|
+
onSome: (id) => Effect.succeed(id)
|
|
302
|
+
});
|
|
303
|
+
const fn = (yield* Database.query(Filter.type(Operation.PersistentOperation)).run).find((fn) => fn.id === functionId);
|
|
304
|
+
if (!fn) return yield* Effect.fail(/* @__PURE__ */ new Error(`Function not found: ${functionId}`));
|
|
305
|
+
const typename = yield* Option.match(options.typename, {
|
|
306
|
+
onNone: () => Prompt.text({ message: "Enter type name:" }).pipe(Prompt.run),
|
|
307
|
+
onSome: (value) => Effect.succeed(value)
|
|
308
|
+
});
|
|
309
|
+
const subscriptionQuery = Query.select(Filter.type(DXN$1.make(typename)));
|
|
310
|
+
const deepOption = yield* Option.match(options.deep, {
|
|
311
|
+
onNone: () => Prompt.confirm({
|
|
312
|
+
message: "Watch changes to nested properties (deep)?",
|
|
313
|
+
initial: false
|
|
314
|
+
}).pipe(Prompt.run, Effect.map((value) => value ? Option.some(value) : Option.none())),
|
|
315
|
+
onSome: () => Effect.succeed(Option.some(true))
|
|
316
|
+
});
|
|
317
|
+
const delayOption = yield* Option.match(options.delay, {
|
|
318
|
+
onNone: () => Effect.gen(function* () {
|
|
319
|
+
const delayStr = yield* Prompt.text({ message: "Debounce delay in milliseconds (optional, press Enter to skip):" }).pipe(Prompt.run);
|
|
320
|
+
return delayStr === "" ? Option.none() : Option.some(parseInt(delayStr, 10));
|
|
321
|
+
}),
|
|
322
|
+
onSome: (value) => Effect.succeed(Option.some(value))
|
|
323
|
+
});
|
|
324
|
+
const subscriptionOptions = {};
|
|
325
|
+
if (Option.isSome(deepOption)) subscriptionOptions.deep = deepOption.value;
|
|
326
|
+
if (Option.isSome(delayOption)) subscriptionOptions.delay = delayOption.value;
|
|
327
|
+
const input = yield* Option.match(options.input, {
|
|
328
|
+
onNone: () => promptForSchemaInput(fn.inputSchema ? JsonSchema.toEffectSchema(fn.inputSchema) : void 0),
|
|
329
|
+
onSome: (value) => Effect.succeed(Object.fromEntries(HashMap.toEntries(value)))
|
|
330
|
+
});
|
|
331
|
+
const enabled = yield* Option.match(options.functionId, {
|
|
332
|
+
onNone: () => Prompt.confirm({
|
|
333
|
+
message: "Enable the trigger?",
|
|
334
|
+
initial: true
|
|
335
|
+
}).pipe(Prompt.run),
|
|
336
|
+
onSome: () => Effect.succeed(options.enabled)
|
|
337
|
+
});
|
|
338
|
+
const trigger = Trigger.make({
|
|
339
|
+
runnable: Ref.make(fn),
|
|
340
|
+
enabled,
|
|
341
|
+
spec: Trigger.specSubscription(subscriptionQuery, Object.keys(subscriptionOptions).length > 0 ? subscriptionOptions : void 0),
|
|
342
|
+
input
|
|
343
|
+
});
|
|
344
|
+
yield* Database.add(trigger);
|
|
345
|
+
if (json) yield* Console.log(JSON.stringify(trigger, null, 2));
|
|
346
|
+
else yield* Console.log(print(yield* printTrigger(trigger)));
|
|
347
|
+
yield* flushAndSync({ indexes: true });
|
|
348
|
+
})).pipe(Command.withDescription("Create a subscription trigger."), Command.provide(({ spaceId }) => spaceLayer(spaceId, true)), Command.provideEffectDiscard(() => withTypes(Operation.PersistentOperation, Trigger.Trigger)));
|
|
349
|
+
//#endregion
|
|
350
|
+
//#region src/commands/trigger/create/timer.ts
|
|
351
|
+
var timer$1 = Command.make("timer", {
|
|
352
|
+
spaceId: Common.spaceId.pipe(Options.optional),
|
|
353
|
+
enabled: Enabled,
|
|
354
|
+
functionId: Common.functionId.pipe(Options.optional),
|
|
355
|
+
cron: Cron.pipe(Options.optional),
|
|
356
|
+
input: Input.pipe(Options.optional)
|
|
357
|
+
}, (options) => Effect.gen(function* () {
|
|
358
|
+
const { json } = yield* CommandConfig;
|
|
359
|
+
const functionId = yield* Option.match(options.functionId, {
|
|
360
|
+
onNone: () => selectFunction(),
|
|
361
|
+
onSome: (id) => Effect.succeed(id)
|
|
362
|
+
});
|
|
363
|
+
const fn = (yield* Database.query(Filter.type(Operation.PersistentOperation)).run).find((fn) => fn.id === functionId);
|
|
364
|
+
if (!fn) return yield* Effect.fail(/* @__PURE__ */ new Error(`Function not found: ${functionId}`));
|
|
365
|
+
const cron = yield* Option.match(options.cron, {
|
|
366
|
+
onNone: () => Prompt.text({ message: "Enter cron expression:" }).pipe(Prompt.run),
|
|
367
|
+
onSome: (value) => Effect.succeed(value)
|
|
368
|
+
});
|
|
369
|
+
const input = yield* Option.match(options.input, {
|
|
370
|
+
onNone: () => promptForSchemaInput(fn.inputSchema ? JsonSchema.toEffectSchema(fn.inputSchema) : void 0),
|
|
371
|
+
onSome: (value) => Effect.succeed(Object.fromEntries(HashMap.toEntries(value)))
|
|
372
|
+
});
|
|
373
|
+
const enabled = yield* Option.match(options.functionId, {
|
|
374
|
+
onNone: () => Prompt.confirm({
|
|
375
|
+
message: "Enable the trigger?",
|
|
376
|
+
initial: true
|
|
377
|
+
}).pipe(Prompt.run),
|
|
378
|
+
onSome: () => Effect.succeed(options.enabled)
|
|
379
|
+
});
|
|
380
|
+
const trigger = Trigger.make({
|
|
381
|
+
runnable: Ref.make(fn),
|
|
382
|
+
enabled,
|
|
383
|
+
spec: Trigger.specTimer(cron),
|
|
384
|
+
input
|
|
385
|
+
});
|
|
386
|
+
yield* Database.add(trigger);
|
|
387
|
+
if (json) yield* Console.log(JSON.stringify(trigger, null, 2));
|
|
388
|
+
else yield* Console.log(print(yield* printTrigger(trigger)));
|
|
389
|
+
yield* flushAndSync({ indexes: true });
|
|
390
|
+
})).pipe(Command.withDescription("Create a timer trigger."), Command.provide(({ spaceId }) => spaceLayer(spaceId, true)), Command.provideEffectDiscard(() => withTypes(Operation.PersistentOperation, Trigger.Trigger)));
|
|
391
|
+
//#endregion
|
|
392
|
+
//#region src/commands/trigger/create/index.ts
|
|
393
|
+
var create = Command.make("create").pipe(Command.withDescription("Create a trigger."), Command.withSubcommands([
|
|
394
|
+
subscription$1,
|
|
395
|
+
timer$1,
|
|
396
|
+
feed$1
|
|
397
|
+
]));
|
|
398
|
+
//#endregion
|
|
399
|
+
//#region src/commands/trigger/list.ts
|
|
400
|
+
var __dxlog_file = "/__w/dxos/dxos/packages/plugins/plugin-routine/src/commands/trigger/list.ts";
|
|
401
|
+
var list = Command.make("list", { spaceId: Common.spaceId.pipe(Options.optional) }, Effect.fn(function* ({ spaceId: spaceIdOption }) {
|
|
402
|
+
const { json } = yield* CommandConfig;
|
|
403
|
+
const triggers = yield* Database.query(Query.select(Filter.type(Trigger.Trigger)).debugLabel("cli.trigger.list")).run;
|
|
404
|
+
const remoteCronIds = yield* Effect.gen(function* () {
|
|
405
|
+
const client = yield* ClientService;
|
|
406
|
+
const spaceId = yield* spaceIdWithDefault(spaceIdOption);
|
|
407
|
+
return (yield* Effect.promise(() => client.edge.http.getCronTriggers(Context.default(void 0, {
|
|
408
|
+
"~LogMeta": "~LogMeta",
|
|
409
|
+
F: __dxlog_file,
|
|
410
|
+
L: 34
|
|
411
|
+
}), spaceId)).pipe(Effect.catchAll(() => Effect.succeed({ cronIds: [] })))).cronIds;
|
|
412
|
+
});
|
|
413
|
+
const triggersWithStatus = triggers.map((trigger) => ({
|
|
414
|
+
trigger,
|
|
415
|
+
remoteStatus: getTriggerRemoteStatus(trigger, remoteCronIds)
|
|
416
|
+
}));
|
|
417
|
+
if (json) yield* Console.log(JSON.stringify(triggersWithStatus.map(({ trigger, remoteStatus }) => ({
|
|
418
|
+
...trigger,
|
|
419
|
+
remoteStatus
|
|
420
|
+
})), null, 2));
|
|
421
|
+
else if (triggersWithStatus.length === 0) yield* Console.log("No triggers found.");
|
|
422
|
+
else {
|
|
423
|
+
const items = yield* Effect.all(triggersWithStatus.map(({ trigger, remoteStatus }) => printTrigger(trigger, remoteStatus)));
|
|
424
|
+
yield* Console.log(printList(items));
|
|
425
|
+
}
|
|
426
|
+
})).pipe(Command.withDescription("List triggers configured on EDGE."), Command.provide(({ spaceId }) => spaceLayer(spaceId, true)));
|
|
427
|
+
//#endregion
|
|
428
|
+
//#region src/commands/trigger/remove.ts
|
|
429
|
+
var remove = Command.make("remove", {
|
|
430
|
+
spaceId: Common.spaceId.pipe(Options.optional),
|
|
431
|
+
id: TriggerId.pipe(Options.optional)
|
|
432
|
+
}, (options) => Effect.gen(function* () {
|
|
433
|
+
const { json } = yield* CommandConfig;
|
|
434
|
+
const triggerId = yield* Option.match(options.id, {
|
|
435
|
+
onNone: () => selectTrigger(),
|
|
436
|
+
onSome: (id) => Effect.succeed(id)
|
|
437
|
+
});
|
|
438
|
+
const dxn = EID.make({ entityId: triggerId });
|
|
439
|
+
const trigger = yield* Database.resolve(Ref.fromURI(dxn), Trigger.Trigger);
|
|
440
|
+
yield* Database.remove(trigger);
|
|
441
|
+
if (json) yield* Console.log(JSON.stringify({
|
|
442
|
+
id: trigger.id,
|
|
443
|
+
removed: true
|
|
444
|
+
}, null, 2));
|
|
445
|
+
else yield* Console.log(print(printTriggerRemoved(trigger.id)));
|
|
446
|
+
})).pipe(Command.withDescription("Remove a trigger."), Command.provide(({ spaceId }) => spaceLayer(spaceId, true)), Command.provideEffectDiscard(() => withTypes(Trigger.Trigger)));
|
|
447
|
+
//#endregion
|
|
448
|
+
//#region src/commands/trigger/update/feed.ts
|
|
449
|
+
var feed = Command.make("feed", {
|
|
450
|
+
spaceId: Common.spaceId.pipe(Options.optional),
|
|
451
|
+
id: TriggerId.pipe(Options.optional),
|
|
452
|
+
enabled: Enabled,
|
|
453
|
+
functionId: Common.functionId.pipe(Options.optional),
|
|
454
|
+
feed: Feed$1.pipe(Options.optional),
|
|
455
|
+
input: Input.pipe(Options.optional)
|
|
456
|
+
}, (options) => Effect.gen(function* () {
|
|
457
|
+
const { json } = yield* CommandConfig;
|
|
458
|
+
const triggerId = yield* Option.match(options.id, {
|
|
459
|
+
onNone: () => selectTrigger("feed"),
|
|
460
|
+
onSome: (id) => Effect.succeed(id)
|
|
461
|
+
});
|
|
462
|
+
const dxn = EID.make({ entityId: triggerId });
|
|
463
|
+
const trigger = yield* Database.resolve(dxn, Trigger.Trigger);
|
|
464
|
+
if (trigger.spec?.kind !== "feed") return yield* Effect.fail(/* @__PURE__ */ new Error(`Invalid trigger type: ${trigger.spec?.kind}`));
|
|
465
|
+
const currentFn = yield* updateFunction$2(trigger, options.functionId);
|
|
466
|
+
yield* updateFeed(trigger, options.feed);
|
|
467
|
+
yield* updateInput$2(trigger, currentFn, options.input);
|
|
468
|
+
yield* updateEnabled$2(trigger, options.id, options.enabled);
|
|
469
|
+
if (json) yield* Console.log(JSON.stringify(trigger, null, 2));
|
|
470
|
+
else yield* Console.log(print(yield* printTrigger(trigger)));
|
|
471
|
+
yield* flushAndSync({ indexes: true });
|
|
472
|
+
})).pipe(Command.withDescription("Update a feed trigger."), Command.provide(({ spaceId }) => spaceLayer(spaceId, true)), Command.provideEffectDiscard(() => withTypes(Operation.PersistentOperation, Trigger.Trigger)));
|
|
473
|
+
/**
|
|
474
|
+
* Handles updating the function for a trigger.
|
|
475
|
+
* Prompts for confirmation if functionId is not provided, then updates the function if confirmed.
|
|
476
|
+
* @returns The current function (either original or newly assigned)
|
|
477
|
+
*/
|
|
478
|
+
var updateFunction$2 = Effect.fn(function* (trigger, functionIdOption) {
|
|
479
|
+
let currentFn = trigger.runnable ? yield* Database.load(trigger.runnable) : void 0;
|
|
480
|
+
if (currentFn && !Obj.instanceOf(Operation.PersistentOperation, currentFn)) currentFn = void 0;
|
|
481
|
+
const currentFunctionName = currentFn ? currentFn.name ?? currentFn.id : void 0;
|
|
482
|
+
if (yield* Option.match(functionIdOption, {
|
|
483
|
+
onNone: () => Prompt.confirm({
|
|
484
|
+
message: `Change the function${currentFunctionName ? ` (current: ${currentFunctionName})` : ""}?`,
|
|
485
|
+
initial: false
|
|
486
|
+
}).pipe(Prompt.run),
|
|
487
|
+
onSome: () => Effect.succeed(true)
|
|
488
|
+
})) {
|
|
489
|
+
const functionId = yield* Option.match(functionIdOption, {
|
|
490
|
+
onNone: () => selectFunction(),
|
|
491
|
+
onSome: (id) => Effect.succeed(id)
|
|
492
|
+
});
|
|
493
|
+
const foundFn = (yield* Database.query(Filter.type(Operation.PersistentOperation)).run).find((fn) => fn.id === functionId);
|
|
494
|
+
if (!foundFn || !Obj.instanceOf(Operation.PersistentOperation, foundFn)) return yield* Effect.fail(/* @__PURE__ */ new Error(`Function not found: ${functionId}`));
|
|
495
|
+
Obj.update(trigger, (trigger) => {
|
|
496
|
+
trigger.runnable = Ref.make(foundFn);
|
|
497
|
+
});
|
|
498
|
+
currentFn = foundFn;
|
|
499
|
+
}
|
|
500
|
+
if (!currentFn) {
|
|
501
|
+
const runnableId = (trigger.runnable ? trigger.runnable.uri.toString() : void 0) ?? "unknown";
|
|
502
|
+
return yield* Effect.fail(/* @__PURE__ */ new Error(`Invalid reference for ${runnableId}`));
|
|
503
|
+
}
|
|
504
|
+
return currentFn;
|
|
505
|
+
});
|
|
506
|
+
/**
|
|
507
|
+
* Handles updating the feed reference for a feed trigger.
|
|
508
|
+
* Prompts for confirmation if feed is not provided, then updates the feed if confirmed.
|
|
509
|
+
*/
|
|
510
|
+
var updateFeed = Effect.fn(function* (trigger, feedOption) {
|
|
511
|
+
const currentFeed = trigger.spec?.kind === "feed" ? trigger.spec.feed : void 0;
|
|
512
|
+
const currentFeedStr = currentFeed ? currentFeed.uri.toString() : void 0;
|
|
513
|
+
if (yield* Option.match(feedOption, {
|
|
514
|
+
onNone: () => Prompt.confirm({
|
|
515
|
+
message: `Change the feed${currentFeedStr ? ` (current: ${currentFeedStr})` : ""}?`,
|
|
516
|
+
initial: false
|
|
517
|
+
}).pipe(Prompt.run),
|
|
518
|
+
onSome: () => Effect.succeed(true)
|
|
519
|
+
})) {
|
|
520
|
+
const feed = yield* Option.match(feedOption, {
|
|
521
|
+
onNone: () => selectFeed(),
|
|
522
|
+
onSome: (uri) => Database.resolve(EID.parse(uri), Feed.Feed)
|
|
523
|
+
});
|
|
524
|
+
Obj.update(trigger, (trigger) => {
|
|
525
|
+
if (trigger.spec?.kind === "feed") trigger.spec.feed = Ref.make(feed);
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
});
|
|
529
|
+
/**
|
|
530
|
+
* Handles updating the input for a trigger.
|
|
531
|
+
* Prompts for confirmation if input is not provided, then updates the input if confirmed.
|
|
532
|
+
*/
|
|
533
|
+
var updateInput$2 = Effect.fn(function* (trigger, fn, inputOption) {
|
|
534
|
+
const currentInput = trigger.input;
|
|
535
|
+
const currentInputStr = currentInput ? JSON.stringify(currentInput) : "none";
|
|
536
|
+
if (yield* Option.match(inputOption, {
|
|
537
|
+
onNone: () => Effect.gen(function* () {
|
|
538
|
+
yield* Console.log(`Current input: ${currentInputStr}`);
|
|
539
|
+
return yield* Prompt.confirm({
|
|
540
|
+
message: "Change input?",
|
|
541
|
+
initial: false
|
|
542
|
+
}).pipe(Prompt.run);
|
|
543
|
+
}),
|
|
544
|
+
onSome: () => Effect.succeed(true)
|
|
545
|
+
})) {
|
|
546
|
+
const inputObj = yield* Option.match(inputOption, {
|
|
547
|
+
onNone: () => promptForSchemaInput(fn.inputSchema ? JsonSchema.toEffectSchema(fn.inputSchema) : void 0, currentInput),
|
|
548
|
+
onSome: (value) => Effect.succeed(value)
|
|
549
|
+
});
|
|
550
|
+
Obj.update(trigger, (trigger) => {
|
|
551
|
+
trigger.input = inputObj;
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
});
|
|
555
|
+
/**
|
|
556
|
+
* Handles updating the enabled status for a trigger.
|
|
557
|
+
* Prompts for enabled if id is not provided.
|
|
558
|
+
*/
|
|
559
|
+
var updateEnabled$2 = Effect.fn(function* (trigger, idOption, enabled) {
|
|
560
|
+
const enabledValue = yield* Option.match(idOption, {
|
|
561
|
+
onNone: () => Prompt.confirm({
|
|
562
|
+
message: "Enable the trigger?",
|
|
563
|
+
initial: trigger.enabled
|
|
564
|
+
}).pipe(Prompt.run),
|
|
565
|
+
onSome: () => Effect.succeed(enabled)
|
|
566
|
+
});
|
|
567
|
+
Obj.update(trigger, (trigger) => {
|
|
568
|
+
trigger.enabled = enabledValue;
|
|
569
|
+
});
|
|
570
|
+
});
|
|
571
|
+
//#endregion
|
|
572
|
+
//#region src/commands/trigger/update/subscription.ts
|
|
573
|
+
var subscription = Command.make("subscription", {
|
|
574
|
+
spaceId: Common.spaceId.pipe(Options.optional),
|
|
575
|
+
id: TriggerId.pipe(Options.optional),
|
|
576
|
+
enabled: Enabled,
|
|
577
|
+
functionId: Common.functionId.pipe(Options.optional),
|
|
578
|
+
typename: Typename.pipe(Options.optional),
|
|
579
|
+
deep: Deep.pipe(Options.optional),
|
|
580
|
+
delay: Delay.pipe(Options.optional),
|
|
581
|
+
input: Input.pipe(Options.optional)
|
|
582
|
+
}, (options) => Effect.gen(function* () {
|
|
583
|
+
const { json } = yield* CommandConfig;
|
|
584
|
+
const triggerId = yield* Option.match(options.id, {
|
|
585
|
+
onNone: () => selectTrigger("subscription"),
|
|
586
|
+
onSome: (id) => Effect.succeed(id)
|
|
587
|
+
});
|
|
588
|
+
const dxn = EID.make({ entityId: triggerId });
|
|
589
|
+
const trigger = yield* Database.resolve(Ref.fromURI(dxn), Trigger.Trigger);
|
|
590
|
+
if (trigger.spec?.kind !== "subscription") return yield* Effect.fail(/* @__PURE__ */ new Error(`Invalid trigger type: ${trigger.spec?.kind}`));
|
|
591
|
+
const currentFn = yield* updateFunction$1(trigger, options.functionId);
|
|
592
|
+
yield* updateSpec(trigger, options.typename, options.deep, options.delay);
|
|
593
|
+
yield* updateInput$1(trigger, currentFn, options.input);
|
|
594
|
+
yield* updateEnabled$1(trigger, options.id, options.enabled);
|
|
595
|
+
if (json) yield* Console.log(JSON.stringify(trigger, null, 2));
|
|
596
|
+
else yield* Console.log(print(yield* printTrigger(trigger)));
|
|
597
|
+
yield* flushAndSync({ indexes: true });
|
|
598
|
+
})).pipe(Command.withDescription("Update a subscription trigger."), Command.provide(({ spaceId }) => spaceLayer(spaceId, true)), Command.provideEffectDiscard(() => withTypes(Operation.PersistentOperation, Trigger.Trigger)));
|
|
599
|
+
/**
|
|
600
|
+
* Extracts the current typename from a subscription trigger's query AST.
|
|
601
|
+
*/
|
|
602
|
+
var extractCurrentTypename = (spec) => {
|
|
603
|
+
if (!spec?.query?.ast) return Option.none();
|
|
604
|
+
return Match.value(spec.query.ast).pipe(Match.withReturnType(), Match.when({ type: "select" }, (q) => Match.value(q.filter).pipe(Match.withReturnType(), Match.when({ type: "object" }, (f) => Option.fromNullable(f.typename).pipe(Option.flatMap((dxn) => Option.fromNullable(DXN$1.isDXN(dxn) ? DXN$1.getName(dxn) : void 0)))), Match.orElse(() => Option.none()))), Match.orElse(() => Option.none()));
|
|
605
|
+
};
|
|
606
|
+
/**
|
|
607
|
+
* Handles updating the function for a trigger.
|
|
608
|
+
* Prompts for confirmation if functionId is not provided, then updates the function if confirmed.
|
|
609
|
+
* @returns The current function (either original or newly assigned)
|
|
610
|
+
*/
|
|
611
|
+
var updateFunction$1 = Effect.fn(function* (trigger, functionIdOption) {
|
|
612
|
+
let currentFn = trigger.runnable ? yield* Database.load(trigger.runnable) : void 0;
|
|
613
|
+
if (currentFn && !Obj.instanceOf(Operation.PersistentOperation, currentFn)) currentFn = void 0;
|
|
614
|
+
const currentFunctionName = currentFn ? currentFn.name ?? currentFn.id : void 0;
|
|
615
|
+
if (yield* Option.match(functionIdOption, {
|
|
616
|
+
onNone: () => Prompt.confirm({
|
|
617
|
+
message: `Change the function${currentFunctionName ? ` (current: ${currentFunctionName})` : ""}?`,
|
|
618
|
+
initial: false
|
|
619
|
+
}).pipe(Prompt.run),
|
|
620
|
+
onSome: () => Effect.succeed(true)
|
|
621
|
+
})) {
|
|
622
|
+
const functionId = yield* Option.match(functionIdOption, {
|
|
623
|
+
onNone: () => selectFunction(),
|
|
624
|
+
onSome: (id) => Effect.succeed(id)
|
|
625
|
+
});
|
|
626
|
+
const foundFn = (yield* Database.query(Filter.type(Operation.PersistentOperation)).run).find((fn) => fn.id === functionId);
|
|
627
|
+
if (!foundFn || !Obj.instanceOf(Operation.PersistentOperation, foundFn)) return yield* Effect.fail(/* @__PURE__ */ new Error(`Function not found: ${functionId}`));
|
|
628
|
+
Obj.update(trigger, (trigger) => {
|
|
629
|
+
trigger.runnable = Ref.make(foundFn);
|
|
630
|
+
});
|
|
631
|
+
currentFn = foundFn;
|
|
632
|
+
}
|
|
633
|
+
if (!currentFn) {
|
|
634
|
+
const runnableId = trigger.runnable?.uri.toString() ?? "unknown";
|
|
635
|
+
return yield* Effect.fail(/* @__PURE__ */ new Error(`Invalid reference for ${runnableId}`));
|
|
636
|
+
}
|
|
637
|
+
return currentFn;
|
|
638
|
+
});
|
|
639
|
+
/**
|
|
640
|
+
* Handles updating the subscription trigger spec (typename, deep, delay).
|
|
641
|
+
* Prompts for confirmation if no spec options are provided, then updates the spec if confirmed.
|
|
642
|
+
*/
|
|
643
|
+
var updateSpec = Effect.fn(function* (trigger, typenameOption, deepOption, delayOption) {
|
|
644
|
+
const currentSpec = trigger.spec?.kind === "subscription" ? trigger.spec : void 0;
|
|
645
|
+
const currentTypename = extractCurrentTypename(currentSpec);
|
|
646
|
+
const currentTypenameStr = Option.getOrUndefined(currentTypename);
|
|
647
|
+
const currentDeep = currentSpec?.options?.deep;
|
|
648
|
+
const currentDelay = currentSpec?.options?.delay;
|
|
649
|
+
const specParts = [];
|
|
650
|
+
if (currentTypenameStr) specParts.push(`typename: ${currentTypenameStr}`);
|
|
651
|
+
if (currentDeep !== void 0) specParts.push(`deep: ${currentDeep}`);
|
|
652
|
+
if (currentDelay !== void 0) specParts.push(`delay: ${currentDelay}`);
|
|
653
|
+
const currentSpecStr = specParts.length > 0 ? specParts.join(", ") : "none";
|
|
654
|
+
if (yield* Option.isSome(typenameOption) || Option.isSome(deepOption) || Option.isSome(delayOption) ? Effect.succeed(true) : Prompt.confirm({
|
|
655
|
+
message: `Change the trigger spec (current: ${currentSpecStr})?`,
|
|
656
|
+
initial: false
|
|
657
|
+
}).pipe(Prompt.run)) {
|
|
658
|
+
const typename = yield* Option.match(typenameOption, {
|
|
659
|
+
onNone: () => Prompt.text({ message: `Enter type name${currentTypenameStr ? ` (current: ${currentTypenameStr})` : ""}:` }).pipe(Prompt.run),
|
|
660
|
+
onSome: (value) => Effect.succeed(value)
|
|
661
|
+
});
|
|
662
|
+
const queryAst = Query.select(Filter.type(DXN$1.make(typename))).ast;
|
|
663
|
+
const deepOptionValue = yield* Option.match(deepOption, {
|
|
664
|
+
onNone: () => Prompt.confirm({
|
|
665
|
+
message: "Watch changes to nested properties (deep)?",
|
|
666
|
+
initial: currentSpec?.options?.deep ?? false
|
|
667
|
+
}).pipe(Prompt.run, Effect.map((value) => value ? Option.some(value) : Option.none())),
|
|
668
|
+
onSome: () => Effect.succeed(Option.some(true))
|
|
669
|
+
});
|
|
670
|
+
const delayOptionValue = yield* Option.match(delayOption, {
|
|
671
|
+
onNone: () => Effect.gen(function* () {
|
|
672
|
+
const currentDelay = currentSpec?.options?.delay;
|
|
673
|
+
const delayStr = yield* Prompt.text({ message: `Debounce delay in milliseconds (optional, press Enter to skip)${currentDelay ? ` (current: ${currentDelay})` : ""}:` }).pipe(Prompt.run);
|
|
674
|
+
return delayStr === "" ? Option.none() : Option.some(parseInt(delayStr, 10));
|
|
675
|
+
}),
|
|
676
|
+
onSome: (value) => Effect.succeed(Option.some(value))
|
|
677
|
+
});
|
|
678
|
+
const subscriptionOptions = {};
|
|
679
|
+
if (Option.isSome(deepOptionValue)) subscriptionOptions.deep = deepOptionValue.value;
|
|
680
|
+
if (Option.isSome(delayOptionValue)) subscriptionOptions.delay = delayOptionValue.value;
|
|
681
|
+
Obj.update(trigger, (trigger) => {
|
|
682
|
+
const spec = trigger.spec;
|
|
683
|
+
if (spec?.kind === "subscription") {
|
|
684
|
+
spec.query = { ast: queryAst };
|
|
685
|
+
spec.options = Object.keys(subscriptionOptions).length > 0 ? subscriptionOptions : void 0;
|
|
686
|
+
}
|
|
687
|
+
});
|
|
688
|
+
}
|
|
689
|
+
});
|
|
690
|
+
/**
|
|
691
|
+
* Handles updating the input for a trigger.
|
|
692
|
+
* Prompts for confirmation if input is not provided, then updates the input if confirmed.
|
|
693
|
+
*/
|
|
694
|
+
var updateInput$1 = Effect.fn(function* (trigger, fn, inputOption) {
|
|
695
|
+
const currentInput = trigger.input;
|
|
696
|
+
const currentInputStr = currentInput ? JSON.stringify(currentInput) : "none";
|
|
697
|
+
if (yield* Option.match(inputOption, {
|
|
698
|
+
onNone: () => Effect.gen(function* () {
|
|
699
|
+
yield* Console.log(`Current input: ${currentInputStr}`);
|
|
700
|
+
return yield* Prompt.confirm({
|
|
701
|
+
message: "Change input?",
|
|
702
|
+
initial: false
|
|
703
|
+
}).pipe(Prompt.run);
|
|
704
|
+
}),
|
|
705
|
+
onSome: () => Effect.succeed(true)
|
|
706
|
+
})) {
|
|
707
|
+
const inputObj = yield* Option.match(inputOption, {
|
|
708
|
+
onNone: () => promptForSchemaInput(fn.inputSchema ? JsonSchema.toEffectSchema(fn.inputSchema) : void 0, currentInput),
|
|
709
|
+
onSome: (value) => Effect.succeed(value)
|
|
710
|
+
});
|
|
711
|
+
Obj.update(trigger, (trigger) => {
|
|
712
|
+
trigger.input = inputObj;
|
|
713
|
+
});
|
|
714
|
+
}
|
|
715
|
+
});
|
|
716
|
+
/**
|
|
717
|
+
* Handles updating the enabled status for a trigger.
|
|
718
|
+
* Prompts for enabled if id is not provided.
|
|
719
|
+
*/
|
|
720
|
+
var updateEnabled$1 = Effect.fn(function* (trigger, idOption, enabled) {
|
|
721
|
+
const enabledValue = yield* Option.match(idOption, {
|
|
722
|
+
onNone: () => Prompt.confirm({
|
|
723
|
+
message: "Enable the trigger?",
|
|
724
|
+
initial: trigger.enabled
|
|
725
|
+
}).pipe(Prompt.run),
|
|
726
|
+
onSome: () => Effect.succeed(enabled)
|
|
727
|
+
});
|
|
728
|
+
Obj.update(trigger, (trigger) => {
|
|
729
|
+
trigger.enabled = enabledValue;
|
|
730
|
+
});
|
|
731
|
+
});
|
|
732
|
+
//#endregion
|
|
733
|
+
//#region src/commands/trigger/update/timer.ts
|
|
734
|
+
var timer = Command.make("timer", {
|
|
735
|
+
spaceId: Common.spaceId.pipe(Options.optional),
|
|
736
|
+
id: TriggerId.pipe(Options.optional),
|
|
737
|
+
enabled: Enabled,
|
|
738
|
+
functionId: Common.functionId.pipe(Options.optional),
|
|
739
|
+
cron: Cron.pipe(Options.optional),
|
|
740
|
+
input: Input.pipe(Options.optional)
|
|
741
|
+
}, (options) => Effect.gen(function* () {
|
|
742
|
+
const { json } = yield* CommandConfig;
|
|
743
|
+
const triggerId = yield* Option.match(options.id, {
|
|
744
|
+
onNone: () => selectTrigger("timer"),
|
|
745
|
+
onSome: (id) => Effect.succeed(id)
|
|
746
|
+
});
|
|
747
|
+
const dxn = EID.make({ entityId: triggerId });
|
|
748
|
+
const trigger = yield* Database.resolve(Ref.fromURI(dxn), Trigger.Trigger);
|
|
749
|
+
if (!trigger.spec || trigger.spec?.kind !== "timer") return yield* Effect.fail(/* @__PURE__ */ new Error(`Invalid trigger type: ${trigger.spec?.kind}`));
|
|
750
|
+
const currentFn = yield* updateFunction(trigger, options.functionId);
|
|
751
|
+
yield* updateCron(trigger, options.cron);
|
|
752
|
+
yield* updateInput(trigger, currentFn, options.input);
|
|
753
|
+
yield* updateEnabled(trigger, options.id, options.enabled);
|
|
754
|
+
if (json) yield* Console.log(JSON.stringify(trigger, null, 2));
|
|
755
|
+
else yield* Console.log(print(yield* printTrigger(trigger)));
|
|
756
|
+
yield* flushAndSync({ indexes: true });
|
|
757
|
+
})).pipe(Command.withDescription("Update a timer trigger."), Command.provide(({ spaceId }) => spaceLayer(spaceId, true)), Command.provideEffectDiscard(() => withTypes(Operation.PersistentOperation, Trigger.Trigger)));
|
|
758
|
+
/**
|
|
759
|
+
* Handles updating the function for a trigger.
|
|
760
|
+
* Prompts for confirmation if functionId is not provided, then updates the function if confirmed.
|
|
761
|
+
* @returns The current function (either original or newly assigned)
|
|
762
|
+
*/
|
|
763
|
+
var updateFunction = Effect.fn(function* (trigger, functionIdOption) {
|
|
764
|
+
let currentFn = trigger.runnable ? yield* Database.load(trigger.runnable) : void 0;
|
|
765
|
+
if (currentFn && !Obj.instanceOf(Operation.PersistentOperation, currentFn)) currentFn = void 0;
|
|
766
|
+
const currentFunctionName = currentFn ? currentFn.name ?? currentFn.id : void 0;
|
|
767
|
+
if (yield* Option.match(functionIdOption, {
|
|
768
|
+
onNone: () => Prompt.confirm({
|
|
769
|
+
message: `Change the function${currentFunctionName ? ` (current: ${currentFunctionName})` : ""}?`,
|
|
770
|
+
initial: false
|
|
771
|
+
}).pipe(Prompt.run),
|
|
772
|
+
onSome: () => Effect.succeed(true)
|
|
773
|
+
})) {
|
|
774
|
+
const functionId = yield* Option.match(functionIdOption, {
|
|
775
|
+
onNone: () => selectFunction(),
|
|
776
|
+
onSome: (id) => Effect.succeed(id)
|
|
777
|
+
});
|
|
778
|
+
const foundFn = (yield* Database.query(Filter.type(Operation.PersistentOperation)).run).find((fn) => fn.id === functionId);
|
|
779
|
+
if (!foundFn || !Obj.instanceOf(Operation.PersistentOperation, foundFn)) return yield* Effect.fail(/* @__PURE__ */ new Error(`Function not found: ${functionId}`));
|
|
780
|
+
Obj.update(trigger, (trigger) => {
|
|
781
|
+
trigger.runnable = Ref.make(foundFn);
|
|
782
|
+
});
|
|
783
|
+
currentFn = foundFn;
|
|
784
|
+
}
|
|
785
|
+
if (!currentFn) {
|
|
786
|
+
const runnableId = trigger.runnable?.uri.toString() ?? "unknown";
|
|
787
|
+
return yield* Effect.fail(/* @__PURE__ */ new Error(`Invalid reference for ${runnableId}`));
|
|
788
|
+
}
|
|
789
|
+
return currentFn;
|
|
790
|
+
});
|
|
791
|
+
/**
|
|
792
|
+
* Handles updating the cron expression for a timer trigger.
|
|
793
|
+
* Prompts for confirmation if cron is not provided, then updates the cron if confirmed.
|
|
794
|
+
*/
|
|
795
|
+
var updateCron = Effect.fn(function* (trigger, cronOption) {
|
|
796
|
+
const currentCron = trigger.spec?.kind === "timer" ? trigger.spec.cron : void 0;
|
|
797
|
+
if (yield* Option.match(cronOption, {
|
|
798
|
+
onNone: () => Prompt.confirm({
|
|
799
|
+
message: `Change the cron expression${currentCron ? ` (current: ${currentCron})` : ""}?`,
|
|
800
|
+
initial: false
|
|
801
|
+
}).pipe(Prompt.run),
|
|
802
|
+
onSome: () => Effect.succeed(true)
|
|
803
|
+
})) {
|
|
804
|
+
const cron = yield* Option.match(cronOption, {
|
|
805
|
+
onNone: () => Prompt.text({ message: `Enter cron expression${currentCron ? ` (current: ${currentCron})` : ""}:` }).pipe(Prompt.run),
|
|
806
|
+
onSome: (value) => Effect.succeed(value)
|
|
807
|
+
});
|
|
808
|
+
Obj.update(trigger, (trigger) => {
|
|
809
|
+
if (trigger.spec?.kind === "timer") trigger.spec.cron = cron;
|
|
810
|
+
});
|
|
811
|
+
}
|
|
812
|
+
});
|
|
813
|
+
/**
|
|
814
|
+
* Handles updating the input for a trigger.
|
|
815
|
+
* Prompts for confirmation if input is not provided, then updates the input if confirmed.
|
|
816
|
+
*/
|
|
817
|
+
var updateInput = Effect.fn(function* (trigger, fn, inputOption) {
|
|
818
|
+
const currentInput = trigger.input;
|
|
819
|
+
const currentInputStr = currentInput ? JSON.stringify(currentInput) : "none";
|
|
820
|
+
if (yield* Option.match(inputOption, {
|
|
821
|
+
onNone: () => Effect.gen(function* () {
|
|
822
|
+
yield* Console.log(`Current input: ${currentInputStr}`);
|
|
823
|
+
return yield* Prompt.confirm({
|
|
824
|
+
message: "Change input?",
|
|
825
|
+
initial: false
|
|
826
|
+
}).pipe(Prompt.run);
|
|
827
|
+
}),
|
|
828
|
+
onSome: () => Effect.succeed(true)
|
|
829
|
+
})) {
|
|
830
|
+
const inputObj = yield* Option.match(inputOption, {
|
|
831
|
+
onNone: () => promptForSchemaInput(fn.inputSchema ? JsonSchema.toEffectSchema(fn.inputSchema) : void 0, currentInput),
|
|
832
|
+
onSome: (value) => Effect.succeed(value)
|
|
833
|
+
});
|
|
834
|
+
Obj.update(trigger, (trigger) => {
|
|
835
|
+
trigger.input = inputObj;
|
|
836
|
+
});
|
|
837
|
+
}
|
|
838
|
+
});
|
|
839
|
+
/**
|
|
840
|
+
* Handles updating the enabled status for a trigger.
|
|
841
|
+
* Prompts for enabled if id is not provided.
|
|
842
|
+
*/
|
|
843
|
+
var updateEnabled = Effect.fn(function* (trigger, idOption, enabled) {
|
|
844
|
+
const enabledValue = yield* Option.match(idOption, {
|
|
845
|
+
onNone: () => Prompt.confirm({
|
|
846
|
+
message: "Enable the trigger?",
|
|
847
|
+
initial: trigger.enabled
|
|
848
|
+
}).pipe(Prompt.run),
|
|
849
|
+
onSome: () => Effect.succeed(enabled)
|
|
850
|
+
});
|
|
851
|
+
Obj.update(trigger, (trigger) => {
|
|
852
|
+
trigger.enabled = enabledValue;
|
|
853
|
+
});
|
|
854
|
+
});
|
|
855
|
+
//#endregion
|
|
856
|
+
//#region src/commands/trigger/update/index.ts
|
|
857
|
+
var update = Command.make("update").pipe(Command.withDescription("Update a trigger."), Command.withSubcommands([
|
|
858
|
+
subscription,
|
|
859
|
+
timer,
|
|
860
|
+
feed
|
|
861
|
+
]));
|
|
862
|
+
//#endregion
|
|
863
|
+
//#region src/commands/trigger/index.ts
|
|
864
|
+
var trigger = Command.make("trigger").pipe(Command.withDescription("Manage EDGE triggers."), Command.withSubcommands([
|
|
865
|
+
create,
|
|
866
|
+
list,
|
|
867
|
+
remove,
|
|
868
|
+
update
|
|
869
|
+
]));
|
|
870
|
+
//#endregion
|
|
871
|
+
//#region src/RoutinePlugin.node.ts
|
|
872
|
+
var RoutinePlugin = Plugin.define(meta).pipe(AppPlugin.addAppGraphModule({ activate: AppGraphBuilder }), AppPlugin.addCommandModule({ commands: [trigger] }), AppPlugin.addOperationHandlerModule({ activate: OperationHandler }), AppPlugin.addSchemaModule({ schema: [
|
|
873
|
+
Routine.Routine,
|
|
874
|
+
Operation.PersistentOperation,
|
|
875
|
+
Trigger.Trigger,
|
|
876
|
+
Trace.Message
|
|
877
|
+
] }), Plugin.addModule({
|
|
878
|
+
id: "automation-templates",
|
|
879
|
+
activatesOn: AppActivationEvents.SetupSchema,
|
|
880
|
+
activate: Templates
|
|
881
|
+
}), Plugin.addModule({
|
|
882
|
+
activatesOn: ActivationEvents.SetupProcessManager,
|
|
883
|
+
activate: LayerSpecs
|
|
884
|
+
}), Plugin.addModule({
|
|
885
|
+
activatesOn: ClientEvents.ClientReady,
|
|
886
|
+
activate: RegistrySync
|
|
887
|
+
}), Plugin.addModule({
|
|
888
|
+
activatesOn: ActivationEvent.allOf(ActivationEvents.ProcessManagerReady, ClientEvents.SpacesReady),
|
|
889
|
+
activate: TriggerRuntimeController
|
|
890
|
+
}), Plugin.make);
|
|
891
|
+
//#endregion
|
|
892
|
+
export { RoutinePlugin, RoutinePlugin as default };
|
|
893
|
+
|
|
894
|
+
//# sourceMappingURL=RoutinePlugin.node.mjs.map
|