@lobb-js/studio 0.7.2 → 0.8.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.
Files changed (164) hide show
  1. package/package.json +2 -1
  2. package/src/App.svelte +5 -0
  3. package/src/app.css +124 -0
  4. package/src/lib/components/LlmButton.svelte +137 -0
  5. package/src/lib/components/Studio.svelte +129 -0
  6. package/src/lib/components/alertView.svelte +20 -0
  7. package/src/lib/components/breadCrumbs.svelte +60 -0
  8. package/src/lib/components/codeEditor.svelte +152 -0
  9. package/src/lib/components/combobox.svelte +92 -0
  10. package/src/lib/components/confirmationDialog/confirmationDialog.svelte +33 -0
  11. package/src/lib/components/confirmationDialog/store.svelte.ts +28 -0
  12. package/src/lib/components/createManyButton.svelte +109 -0
  13. package/src/lib/components/dataTable/childRecords.svelte +142 -0
  14. package/src/lib/components/dataTable/dataTable.svelte +225 -0
  15. package/src/lib/components/dataTable/fieldCell.svelte +77 -0
  16. package/src/lib/components/dataTable/filter.svelte +284 -0
  17. package/src/lib/components/dataTable/filterButton.svelte +39 -0
  18. package/src/lib/components/dataTable/footer.svelte +84 -0
  19. package/src/lib/components/dataTable/header.svelte +155 -0
  20. package/src/lib/components/dataTable/sort.svelte +173 -0
  21. package/src/lib/components/dataTable/sortButton.svelte +36 -0
  22. package/src/lib/components/dataTable/table.svelte +337 -0
  23. package/src/lib/components/dataTable/utils.ts +127 -0
  24. package/src/lib/components/detailView/create/children.svelte +70 -0
  25. package/src/lib/components/detailView/create/createDetailView.svelte +228 -0
  26. package/src/lib/components/detailView/create/createDetailViewButton.svelte +37 -0
  27. package/src/lib/components/detailView/create/createManyView.svelte +252 -0
  28. package/src/lib/components/detailView/create/subRecords.svelte +50 -0
  29. package/src/lib/components/detailView/detailViewForm.svelte +104 -0
  30. package/src/lib/components/detailView/fieldCustomInput.svelte +26 -0
  31. package/src/lib/components/detailView/fieldInput.svelte +258 -0
  32. package/src/lib/components/detailView/fieldInputReplacement.svelte +199 -0
  33. package/src/lib/components/detailView/store.svelte.ts +59 -0
  34. package/src/lib/components/detailView/update/children.svelte +96 -0
  35. package/src/lib/components/detailView/update/updateDetailView.svelte +176 -0
  36. package/src/lib/components/detailView/update/updateDetailViewButton.svelte +56 -0
  37. package/src/lib/components/detailView/utils.ts +176 -0
  38. package/src/lib/components/diffViewer.svelte +105 -0
  39. package/src/lib/components/drawer.svelte +28 -0
  40. package/src/lib/components/extensionsComponents.svelte +33 -0
  41. package/src/lib/components/foreingKeyInput.svelte +80 -0
  42. package/src/lib/components/header.svelte +45 -0
  43. package/src/lib/components/loadingTypesForMonacoEditor.ts +36 -0
  44. package/src/lib/components/miniSidebar.svelte +226 -0
  45. package/src/lib/components/rangeCalendarButton.svelte +257 -0
  46. package/src/lib/components/richTextEditor.svelte +284 -0
  47. package/src/lib/components/routes/collections/collection.svelte +57 -0
  48. package/src/lib/components/routes/collections/collections.svelte +45 -0
  49. package/src/lib/components/routes/data_model/dataModel.svelte +40 -0
  50. package/src/lib/components/routes/data_model/flow.css +22 -0
  51. package/src/lib/components/routes/data_model/flow.svelte +84 -0
  52. package/src/lib/components/routes/data_model/syncManager.svelte +94 -0
  53. package/src/lib/components/routes/data_model/utils.ts +35 -0
  54. package/src/lib/components/routes/extensions/extension.svelte +19 -0
  55. package/src/lib/components/routes/home.svelte +40 -0
  56. package/src/lib/components/routes/workflows/workflows.svelte +136 -0
  57. package/src/lib/components/selectRecord.svelte +130 -0
  58. package/src/lib/components/setServerPage.svelte +50 -0
  59. package/src/lib/components/sidebar/index.ts +4 -0
  60. package/src/lib/components/sidebar/sidebar.svelte +149 -0
  61. package/src/lib/components/sidebar/sidebarElements.svelte +144 -0
  62. package/src/lib/components/sidebar/sidebarTrigger.svelte +33 -0
  63. package/src/lib/components/singletone.svelte +71 -0
  64. package/src/lib/components/ui/accordion/accordion-content.svelte +22 -0
  65. package/src/lib/components/ui/accordion/accordion-item.svelte +12 -0
  66. package/src/lib/components/ui/accordion/accordion-trigger.svelte +31 -0
  67. package/src/lib/components/ui/accordion/index.ts +17 -0
  68. package/src/lib/components/ui/alert/alert-description.svelte +16 -0
  69. package/src/lib/components/ui/alert/alert-title.svelte +24 -0
  70. package/src/lib/components/ui/alert/alert.svelte +39 -0
  71. package/src/lib/components/ui/alert/index.ts +14 -0
  72. package/src/lib/components/ui/alert-dialog/alert-dialog-action.svelte +13 -0
  73. package/src/lib/components/ui/alert-dialog/alert-dialog-cancel.svelte +17 -0
  74. package/src/lib/components/ui/alert-dialog/alert-dialog-content.svelte +26 -0
  75. package/src/lib/components/ui/alert-dialog/alert-dialog-description.svelte +16 -0
  76. package/src/lib/components/ui/alert-dialog/alert-dialog-footer.svelte +20 -0
  77. package/src/lib/components/ui/alert-dialog/alert-dialog-header.svelte +20 -0
  78. package/src/lib/components/ui/alert-dialog/alert-dialog-overlay.svelte +19 -0
  79. package/src/lib/components/ui/alert-dialog/alert-dialog-title.svelte +18 -0
  80. package/src/lib/components/ui/alert-dialog/index.ts +40 -0
  81. package/src/lib/components/ui/breadcrumb/breadcrumb-ellipsis.svelte +23 -0
  82. package/src/lib/components/ui/breadcrumb/breadcrumb-item.svelte +16 -0
  83. package/src/lib/components/ui/breadcrumb/breadcrumb-link.svelte +31 -0
  84. package/src/lib/components/ui/breadcrumb/breadcrumb-list.svelte +23 -0
  85. package/src/lib/components/ui/breadcrumb/breadcrumb-page.svelte +23 -0
  86. package/src/lib/components/ui/breadcrumb/breadcrumb-separator.svelte +27 -0
  87. package/src/lib/components/ui/breadcrumb/breadcrumb.svelte +15 -0
  88. package/src/lib/components/ui/breadcrumb/index.ts +25 -0
  89. package/src/lib/components/ui/button/button.svelte +110 -0
  90. package/src/lib/components/ui/button/index.ts +17 -0
  91. package/src/lib/components/ui/checkbox/checkbox.svelte +35 -0
  92. package/src/lib/components/ui/checkbox/index.ts +6 -0
  93. package/src/lib/components/ui/command/command-dialog.svelte +35 -0
  94. package/src/lib/components/ui/command/command-empty.svelte +12 -0
  95. package/src/lib/components/ui/command/command-group.svelte +31 -0
  96. package/src/lib/components/ui/command/command-input.svelte +25 -0
  97. package/src/lib/components/ui/command/command-item.svelte +19 -0
  98. package/src/lib/components/ui/command/command-link-item.svelte +19 -0
  99. package/src/lib/components/ui/command/command-list.svelte +16 -0
  100. package/src/lib/components/ui/command/command-separator.svelte +12 -0
  101. package/src/lib/components/ui/command/command-shortcut.svelte +20 -0
  102. package/src/lib/components/ui/command/command.svelte +21 -0
  103. package/src/lib/components/ui/command/index.ts +40 -0
  104. package/src/lib/components/ui/dialog/dialog-content.svelte +38 -0
  105. package/src/lib/components/ui/dialog/dialog-description.svelte +16 -0
  106. package/src/lib/components/ui/dialog/dialog-footer.svelte +20 -0
  107. package/src/lib/components/ui/dialog/dialog-header.svelte +20 -0
  108. package/src/lib/components/ui/dialog/dialog-overlay.svelte +19 -0
  109. package/src/lib/components/ui/dialog/dialog-title.svelte +16 -0
  110. package/src/lib/components/ui/dialog/index.ts +37 -0
  111. package/src/lib/components/ui/input/index.ts +7 -0
  112. package/src/lib/components/ui/input/input.svelte +46 -0
  113. package/src/lib/components/ui/label/index.ts +7 -0
  114. package/src/lib/components/ui/label/label.svelte +19 -0
  115. package/src/lib/components/ui/popover/index.ts +17 -0
  116. package/src/lib/components/ui/popover/popover-content.svelte +28 -0
  117. package/src/lib/components/ui/range-calendar/index.ts +30 -0
  118. package/src/lib/components/ui/range-calendar/range-calendar-cell.svelte +19 -0
  119. package/src/lib/components/ui/range-calendar/range-calendar-day.svelte +35 -0
  120. package/src/lib/components/ui/range-calendar/range-calendar-grid-body.svelte +12 -0
  121. package/src/lib/components/ui/range-calendar/range-calendar-grid-head.svelte +12 -0
  122. package/src/lib/components/ui/range-calendar/range-calendar-grid-row.svelte +12 -0
  123. package/src/lib/components/ui/range-calendar/range-calendar-grid.svelte +16 -0
  124. package/src/lib/components/ui/range-calendar/range-calendar-head-cell.svelte +16 -0
  125. package/src/lib/components/ui/range-calendar/range-calendar-header.svelte +16 -0
  126. package/src/lib/components/ui/range-calendar/range-calendar-heading.svelte +16 -0
  127. package/src/lib/components/ui/range-calendar/range-calendar-months.svelte +20 -0
  128. package/src/lib/components/ui/range-calendar/range-calendar-next-button.svelte +27 -0
  129. package/src/lib/components/ui/range-calendar/range-calendar-prev-button.svelte +27 -0
  130. package/src/lib/components/ui/range-calendar/range-calendar.svelte +57 -0
  131. package/src/lib/components/ui/select/index.ts +34 -0
  132. package/src/lib/components/ui/select/select-content.svelte +38 -0
  133. package/src/lib/components/ui/select/select-group-heading.svelte +16 -0
  134. package/src/lib/components/ui/select/select-item.svelte +37 -0
  135. package/src/lib/components/ui/select/select-scroll-down-button.svelte +19 -0
  136. package/src/lib/components/ui/select/select-scroll-up-button.svelte +19 -0
  137. package/src/lib/components/ui/select/select-separator.svelte +13 -0
  138. package/src/lib/components/ui/select/select-trigger.svelte +24 -0
  139. package/src/lib/components/ui/separator/index.ts +7 -0
  140. package/src/lib/components/ui/separator/separator.svelte +22 -0
  141. package/src/lib/components/ui/skeleton/index.ts +7 -0
  142. package/src/lib/components/ui/skeleton/skeleton.svelte +22 -0
  143. package/src/lib/components/ui/sonner/index.ts +1 -0
  144. package/src/lib/components/ui/sonner/sonner.svelte +20 -0
  145. package/src/lib/components/ui/switch/index.ts +7 -0
  146. package/src/lib/components/ui/switch/switch.svelte +27 -0
  147. package/src/lib/components/ui/textarea/index.ts +7 -0
  148. package/src/lib/components/ui/textarea/textarea.svelte +22 -0
  149. package/src/lib/components/ui/tooltip/index.ts +18 -0
  150. package/src/lib/components/ui/tooltip/tooltip-content.svelte +21 -0
  151. package/src/lib/components/workflowEditor.svelte +188 -0
  152. package/src/lib/context.ts +22 -0
  153. package/src/lib/eventSystem.ts +40 -0
  154. package/src/lib/extensions/extension.types.ts +92 -0
  155. package/src/lib/extensions/extensionUtils.ts +156 -0
  156. package/src/lib/index.ts +24 -0
  157. package/src/lib/store.svelte.ts +13 -0
  158. package/src/lib/store.types.ts +28 -0
  159. package/src/lib/utils.ts +68 -0
  160. package/src/main.ts +18 -0
  161. package/src/stories/detailView/detailViewForm.stories.svelte +79 -0
  162. package/src/vite-env.d.ts +2 -0
  163. package/vite-plugins/index.js +2 -0
  164. package/vite-plugins/lobb-proxy.js +36 -0
@@ -0,0 +1,22 @@
1
+ <script lang="ts">
2
+ import type { WithElementRef, WithoutChildren } from "bits-ui";
3
+ import type { HTMLAttributes } from "svelte/elements";
4
+ import { cn } from "../../../utils.js";
5
+
6
+ let {
7
+ ref = $bindable(null),
8
+ class: className,
9
+ ...restProps
10
+ }: WithoutChildren<
11
+ WithElementRef<HTMLAttributes<HTMLDivElement>>
12
+ > = $props();
13
+ </script>
14
+
15
+ <div
16
+ bind:this={ref}
17
+ class={cn(
18
+ "bg-primary/10 animate-pulse rounded-md",
19
+ className,
20
+ )}
21
+ {...restProps}
22
+ ></div>
@@ -0,0 +1 @@
1
+ export { default as Toaster } from "./sonner.svelte";
@@ -0,0 +1,20 @@
1
+ <script lang="ts">
2
+ import { Toaster as Sonner, type ToasterProps as SonnerProps } from "svelte-sonner";
3
+ import { mode } from "mode-watcher";
4
+
5
+ let { ...restProps }: SonnerProps = $props();
6
+ </script>
7
+
8
+ <Sonner
9
+ theme={$mode}
10
+ class="toaster group"
11
+ toastOptions={{
12
+ classes: {
13
+ toast: "group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border group-[.toaster]:shadow-lg",
14
+ description: "group-[.toast]:text-muted-foreground",
15
+ actionButton: "group-[.toast]:bg-primary group-[.toast]:text-primary-foreground",
16
+ cancelButton: "group-[.toast]:bg-muted group-[.toast]:text-muted-foreground",
17
+ },
18
+ }}
19
+ {...restProps}
20
+ />
@@ -0,0 +1,7 @@
1
+ import Root from "./switch.svelte";
2
+
3
+ export {
4
+ Root,
5
+ //
6
+ Root as Switch,
7
+ };
@@ -0,0 +1,27 @@
1
+ <script lang="ts">
2
+ import { Switch as SwitchPrimitive, type WithoutChildrenOrChild } from "bits-ui";
3
+ import { cn } from "../../../utils.js";
4
+
5
+ let {
6
+ ref = $bindable(null),
7
+ checked = $bindable(false),
8
+ class: className,
9
+ ...restProps
10
+ }: WithoutChildrenOrChild<SwitchPrimitive.RootProps> = $props();
11
+ </script>
12
+
13
+ <SwitchPrimitive.Root
14
+ bind:ref
15
+ bind:checked
16
+ class={cn(
17
+ "focus-visible:ring-ring focus-visible:ring-offset-background data-[state=checked]:bg-primary data-[state=unchecked]:bg-input peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
18
+ className
19
+ )}
20
+ {...restProps}
21
+ >
22
+ <SwitchPrimitive.Thumb
23
+ class={cn(
24
+ "bg-background pointer-events-none block size-4 rounded-full shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0"
25
+ )}
26
+ />
27
+ </SwitchPrimitive.Root>
@@ -0,0 +1,7 @@
1
+ import Root from "./textarea.svelte";
2
+
3
+ export {
4
+ Root,
5
+ //
6
+ Root as Textarea,
7
+ };
@@ -0,0 +1,22 @@
1
+ <script lang="ts">
2
+ import type { WithElementRef, WithoutChildren } from "bits-ui";
3
+ import type { HTMLTextareaAttributes } from "svelte/elements";
4
+ import { cn } from "../../../utils.js";
5
+
6
+ let {
7
+ ref = $bindable(null),
8
+ value = $bindable(),
9
+ class: className,
10
+ ...restProps
11
+ }: WithoutChildren<WithElementRef<HTMLTextareaAttributes>> = $props();
12
+ </script>
13
+
14
+ <textarea
15
+ bind:this={ref}
16
+ bind:value
17
+ class={cn(
18
+ "border-input placeholder:text-muted-foreground focus-visible:ring-ring flex min-h-[60px] w-full rounded-md border bg-transparent px-3 py-2 text-base focus-visible:outline-none focus-visible:ring-1 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
19
+ className
20
+ )}
21
+ {...restProps}
22
+ ></textarea>
@@ -0,0 +1,18 @@
1
+ import { Tooltip as TooltipPrimitive } from "bits-ui";
2
+ import Content from "./tooltip-content.svelte";
3
+
4
+ const Root = TooltipPrimitive.Root;
5
+ const Trigger = TooltipPrimitive.Trigger;
6
+ const Provider = TooltipPrimitive.Provider;
7
+
8
+ export {
9
+ Root,
10
+ Trigger,
11
+ Content,
12
+ Provider,
13
+ //
14
+ Root as Tooltip,
15
+ Content as TooltipContent,
16
+ Trigger as TooltipTrigger,
17
+ Provider as TooltipProvider,
18
+ };
@@ -0,0 +1,21 @@
1
+ <script lang="ts">
2
+ import { Tooltip as TooltipPrimitive } from "bits-ui";
3
+ import { cn } from "../../../utils.js";
4
+
5
+ let {
6
+ ref = $bindable(null),
7
+ class: className,
8
+ sideOffset = 4,
9
+ ...restProps
10
+ }: TooltipPrimitive.ContentProps = $props();
11
+ </script>
12
+
13
+ <TooltipPrimitive.Content
14
+ bind:ref
15
+ {sideOffset}
16
+ class={cn(
17
+ "bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 overflow-hidden rounded-md px-3 py-1.5 text-xs",
18
+ className
19
+ )}
20
+ {...restProps}
21
+ />
@@ -0,0 +1,188 @@
1
+ <script lang="ts" module>
2
+ export interface WorkflowEntry {
3
+ id?: string;
4
+ name: string;
5
+ directory: string;
6
+ event_name: string;
7
+ input_schema?: string;
8
+ output_schema?: string;
9
+ handler?: string;
10
+ }
11
+ </script>
12
+
13
+ <script lang="ts">
14
+ import { getStudioContext } from "../context";
15
+ import CodeEditor from "../components/codeEditor.svelte";
16
+
17
+ const { lobb, ctx } = getStudioContext();
18
+ import Button from "../components/ui/button/button.svelte";
19
+ import Input from "../components/ui/input/input.svelte";
20
+ import { location } from "@wjfe/n-savant";
21
+ import { Edit, Plus } from "lucide-svelte";
22
+ import { toast } from "svelte-sonner";
23
+ import { isEqual } from "lodash";
24
+
25
+ interface Props {
26
+ workflow: WorkflowEntry;
27
+ refreshSidebar: () => Promise<void>;
28
+ }
29
+
30
+ let { workflow = $bindable(), refreshSidebar }: Props = $props();
31
+
32
+ let initialWorkflow = $state.snapshot(workflow);
33
+ let workflowHasChanged = $state(false);
34
+
35
+ // track editor change
36
+ $effect(() => {
37
+ const hasChanged = !isEqual(workflow, initialWorkflow);
38
+ workflowHasChanged = hasChanged;
39
+ });
40
+
41
+ $effect(() => {
42
+ handleWorkflowEventChange(workflow.event_name);
43
+ });
44
+
45
+ function handleCtrlSave() {
46
+ if (workflow.id) {
47
+ handleUpdateWorkflow();
48
+ } else {
49
+ handleCreateWorkflow();
50
+ }
51
+ }
52
+
53
+ let types = $state("");
54
+ let eventsOptions = $derived([
55
+ {
56
+ label: "No Event",
57
+ value: "",
58
+ },
59
+ ...ctx.meta.events.map((event) => ({
60
+ label: event.name,
61
+ value: event.name,
62
+ })),
63
+ ]);
64
+
65
+ function handleWorkflowEventChange(eventName: WorkflowEntry["event_name"]) {
66
+ setTimeout(() => {
67
+ const event = ctx.meta.events.find(
68
+ (event) => event.name === eventName,
69
+ );
70
+ let localType = "";
71
+ if (event && event.inputSchema) {
72
+ localType += event.inputSchema;
73
+ } else {
74
+ localType += "type Input = unknown;";
75
+ }
76
+ if (ctx.meta.event_context_type) {
77
+ localType += ctx.meta.event_context_type;
78
+ } else {
79
+ localType += "type Context = unknown;";
80
+ }
81
+ if (event && event.outputSchema) {
82
+ localType += event.outputSchema;
83
+ } else {
84
+ localType += "type Output = Promise<unknown>;";
85
+ }
86
+ types = localType;
87
+ }, 100);
88
+ }
89
+
90
+ async function handleCreateWorkflow() {
91
+ if (!workflow.name) {
92
+ toast.error("You need to specify a workflow name");
93
+ return;
94
+ }
95
+
96
+ const reponse = await lobb.createOne("core_workflows", workflow);
97
+ const result = await reponse.json();
98
+ const workflowEntry = result.data;
99
+ location.navigate(`/studio/workflows/${workflowEntry.name}`);
100
+ await refreshSidebar();
101
+ }
102
+
103
+ async function handleUpdateWorkflow() {
104
+ if (!workflow.id) {
105
+ throw new Error(
106
+ "For some reasont the id of the currentWorkflow doesnt exist",
107
+ );
108
+ }
109
+ const reponse = await lobb.updateOne("core_workflows", workflow.id, {
110
+ name: workflow.name,
111
+ event_name: workflow.event_name,
112
+ handler: workflow.handler,
113
+ });
114
+ const result = await reponse.json();
115
+
116
+ if (!(reponse.status >= 400)) {
117
+ toast.success("The workflow was updated successfully");
118
+ }
119
+
120
+ workflow = result.data;
121
+
122
+ await refreshSidebar();
123
+ }
124
+ </script>
125
+
126
+ <div class="flex flex-col h-full">
127
+ <div
128
+ class="flex justify-between items-start py-2 pl-9 pr-2 bg-background border-b"
129
+ >
130
+ <div class="flex gap-2 flex-wrap">
131
+ <Input
132
+ bind:value={workflow.name}
133
+ class="h-7 w-48 bg-background"
134
+ placeholder="Workflow name"
135
+ />
136
+ <Input
137
+ bind:value={workflow.event_name}
138
+ class="h-7 w-48 bg-background"
139
+ placeholder="Workflow event"
140
+ list="events_options"
141
+ />
142
+ <datalist id="events_options">
143
+ {#each eventsOptions as eventOption}
144
+ <option value={eventOption.value}>
145
+ {eventOption.label}
146
+ </option>
147
+ {/each}
148
+ </datalist>
149
+ <Input
150
+ bind:value={workflow.directory}
151
+ class="h-7 w-48 bg-background"
152
+ placeholder="Workflow directory"
153
+ />
154
+ </div>
155
+ <div>
156
+ {#if workflow.id}
157
+ <Button
158
+ class="h-7 px-3 text-xs font-normal w-full"
159
+ variant="default"
160
+ onclick={handleUpdateWorkflow}
161
+ Icon={Edit}
162
+ disabled={!workflowHasChanged}
163
+ >
164
+ Save
165
+ </Button>
166
+ {:else}
167
+ <Button
168
+ class="h-7 px-3 text-xs font-normal w-full"
169
+ variant="default"
170
+ onclick={handleCreateWorkflow}
171
+ Icon={Plus}
172
+ >
173
+ Create
174
+ </Button>
175
+ {/if}
176
+ </div>
177
+ </div>
178
+ {#key types}
179
+ <CodeEditor
180
+ type="typescript"
181
+ name="workflow"
182
+ class="h-full rounded-none border-none"
183
+ {types}
184
+ {handleCtrlSave}
185
+ bind:value={workflow.handler}
186
+ />
187
+ {/key}
188
+ </div>
@@ -0,0 +1,22 @@
1
+ import { setContext, getContext } from 'svelte';
2
+ import type { LobbClient } from '@lobb-js/sdk';
3
+ import type { CTX } from './store.types';
4
+
5
+ export interface StudioContext {
6
+ ctx: CTX;
7
+ lobb: LobbClient;
8
+ }
9
+
10
+ export const STUDIO_CONTEXT_KEY = Symbol('studio');
11
+
12
+ export function setStudioContext(context: StudioContext) {
13
+ setContext(STUDIO_CONTEXT_KEY, context);
14
+ }
15
+
16
+ export function getStudioContext(): StudioContext {
17
+ return getContext(STUDIO_CONTEXT_KEY);
18
+ }
19
+
20
+ export function createStudioContextMap(context: StudioContext): Map<symbol, StudioContext> {
21
+ return new Map([[STUDIO_CONTEXT_KEY, context]]);
22
+ }
@@ -0,0 +1,40 @@
1
+ import { toast } from "svelte-sonner";
2
+ import type { StudioContext } from "./context";
3
+ import { openCreateDetailView, openUpdateDetailView } from "./components/detailView/store.svelte";
4
+ import type { UpdateDetailViewProp } from "./components/detailView/update/updateDetailView.svelte";
5
+
6
+ export async function emitEvent(studioContext: StudioContext, eventName: string, input: Record<string, any>) {
7
+ const { ctx } = studioContext;
8
+ const workflows = ctx.meta.studio_workflows.filter(
9
+ (workflow) => {
10
+ return eventName.startsWith(workflow.eventName);
11
+ },
12
+ );
13
+
14
+ for (let index = 0; index < workflows.length; index++) {
15
+ const workflow = workflows[index];
16
+ try {
17
+ const localOutput = await workflow.handler(
18
+ input,
19
+ await getEventContext(studioContext),
20
+ );
21
+
22
+ if (localOutput) {
23
+ input = localOutput;
24
+ }
25
+ } catch (error) {
26
+ toast.error((error as any).message);
27
+ throw error;
28
+ }
29
+ }
30
+
31
+ return input;
32
+ }
33
+
34
+ async function getEventContext(studioContext: StudioContext) {
35
+ return {
36
+ toast,
37
+ openCreateDetailView: (props: UpdateDetailViewProp) => openCreateDetailView(studioContext, props),
38
+ openUpdateDetailView: (props: UpdateDetailViewProp) => openUpdateDetailView(studioContext, props),
39
+ };
40
+ }
@@ -0,0 +1,92 @@
1
+ import type { LobbClient } from "@lobb-js/sdk";
2
+ import type { CTX } from "../lib/store.types";
3
+ import type { Button } from "../components/ui/button";
4
+ import type { Input } from "../components/ui/input";
5
+ import type { Separator } from "../components/ui/separator";
6
+ import type { Skeleton } from "../components/ui/skeleton";
7
+ import type LlmButton from "../components/LlmButton.svelte";
8
+ import type Sidebar from "../components/sidebar/sidebar.svelte";
9
+ import type SidebarTrigger from "../components/sidebar/sidebarTrigger.svelte";
10
+ import type CreateDetailViewButton from "../components/detailView/create/createDetailViewButton.svelte";
11
+ import type UpdateDetailViewButton from "../components/detailView/update/updateDetailViewButton.svelte";
12
+ import type { mediaQueries } from "../utils";
13
+ import type Table from "../components/dataTable/table.svelte";
14
+ import type { Location } from "@wjfe/n-savant";
15
+ import type RangeCalendarButton from "../components/rangeCalendarButton.svelte";
16
+ import type DataTable from "../components/dataTable/dataTable.svelte";
17
+ import type Drawer from "../components/drawer.svelte";
18
+ import type SelectRecord from "../components/selectRecord.svelte";
19
+ import * as Popover from "../components/ui/popover";
20
+ import * as intlDate from "@internationalized/date";
21
+ import * as Icons from "lucide-svelte"
22
+ import { ContextMenu } from "bits-ui";
23
+ import * as Tooltip from "../components/ui/tooltip";
24
+ import * as Breadcrumb from "../components/ui/breadcrumb";
25
+ import { showDialog } from "../components/confirmationDialog/store.svelte";
26
+ import { toast } from "svelte-sonner";
27
+ import type Drawer from "../components/drawer.svelte";
28
+ import { Switch } from "../components/ui/switch";
29
+
30
+ // extensions utils
31
+ export interface Components {
32
+ Button: typeof Button;
33
+ Input: typeof Input;
34
+ Separator: typeof Separator;
35
+ Skeleton: typeof Skeleton;
36
+ LlmButton: typeof LlmButton;
37
+ Sidebar: typeof Sidebar;
38
+ SidebarTrigger: typeof SidebarTrigger;
39
+ CreateDetailViewButton: typeof CreateDetailViewButton;
40
+ UpdateDetailViewButton: typeof UpdateDetailViewButton;
41
+ Tooltip: typeof Tooltip;
42
+ Breadcrumb: typeof Breadcrumb;
43
+ ContextMenu: typeof ContextMenu;
44
+ Popover: typeof Popover;
45
+ Icons: typeof Icons;
46
+ Table: typeof Table;
47
+ RangeCalendarButton: typeof RangeCalendarButton;
48
+ DataTable: typeof DataTable;
49
+ Drawer: typeof Drawer;
50
+ SelectRecord: typeof SelectRecord,
51
+ Switch: typeof Switch,
52
+ }
53
+
54
+ export interface ExtensionUtils {
55
+ ctx: CTX;
56
+ lobb: LobbClient;
57
+ location: Location;
58
+ toast: typeof toast;
59
+ showDialog: typeof showDialog;
60
+ components: Components;
61
+ mediaQueries: typeof mediaQueries;
62
+ intlDate: typeof intlDate;
63
+ }
64
+
65
+ // dashboard nav
66
+ interface DashboardNav {
67
+ label: string;
68
+ icon: any;
69
+ href?: string;
70
+ onclick?: () => void;
71
+ navs?: DashboardNav[];
72
+ }
73
+
74
+ export interface DashboardNavs {
75
+ top?: DashboardNav[];
76
+ middle?: DashboardNav[];
77
+ bottom?: DashboardNav[];
78
+ }
79
+
80
+ // extension components base Props
81
+ export interface ExtensionProps {
82
+ utils: ExtensionUtils;
83
+ [key: string]: any;
84
+ }
85
+
86
+ // extension exported object
87
+ export interface Extension {
88
+ name: string;
89
+ onStartup?: (utils: ExtensionUtils) => Promise<void>;
90
+ components?: Record<string, any>;
91
+ dashboardNavs?: DashboardNavs;
92
+ }
@@ -0,0 +1,156 @@
1
+ import type {
2
+ Components,
3
+ DashboardNavs,
4
+ Extension,
5
+ ExtensionUtils,
6
+ } from "./extension.types";
7
+ import type { LobbClient } from "@lobb-js/sdk";
8
+ import type { CTX } from "../store.types";
9
+ import { toast } from "svelte-sonner";
10
+ import { showDialog } from "../components/confirmationDialog/store.svelte";
11
+ import { Button } from "../components/ui/button";
12
+ import { Input } from "../components/ui/input";
13
+ import { Separator } from "../components/ui/separator";
14
+ import { Skeleton } from "../components/ui/skeleton";
15
+ import Table from "../components/dataTable/table.svelte";
16
+ import { mediaQueries } from "../utils";
17
+ import LlmButton from "../components/LlmButton.svelte";
18
+ import Sidebar from "../components/sidebar/sidebar.svelte";
19
+ import SidebarTrigger from "../components/sidebar/sidebarTrigger.svelte";
20
+ import CreateDetailViewButton from "../components/detailView/create/createDetailViewButton.svelte";
21
+ import UpdateDetailViewButton from "../components/detailView/update/updateDetailViewButton.svelte";
22
+ import * as intlDate from "@internationalized/date";
23
+ import * as Tooltip from "../components/ui/tooltip";
24
+ import * as Breadcrumb from "../components/ui/breadcrumb";
25
+ import { ContextMenu } from "bits-ui";
26
+ import * as Popover from "../components/ui/popover";
27
+ import * as Icons from "lucide-svelte";
28
+ import { location } from "@wjfe/n-savant";
29
+ import RangeCalendarButton from "../components/rangeCalendarButton.svelte";
30
+ import DataTable from "../components/dataTable/dataTable.svelte";
31
+ import Drawer from "../components/drawer.svelte";
32
+ import SelectRecord from "../components/selectRecord.svelte";
33
+ import { Switch } from "../components/ui/switch";
34
+
35
+ export function getComponents(): Components {
36
+ return {
37
+ Button: Button,
38
+ Input: Input,
39
+ Separator: Separator,
40
+ Skeleton: Skeleton,
41
+ LlmButton: LlmButton,
42
+ Sidebar: Sidebar,
43
+ SidebarTrigger: SidebarTrigger,
44
+ CreateDetailViewButton: CreateDetailViewButton,
45
+ UpdateDetailViewButton: UpdateDetailViewButton,
46
+ Tooltip: Tooltip,
47
+ Breadcrumb: Breadcrumb,
48
+ ContextMenu: ContextMenu,
49
+ Popover: Popover,
50
+ Icons: Icons,
51
+ Table: Table,
52
+ RangeCalendarButton: RangeCalendarButton,
53
+ DataTable: DataTable,
54
+ Drawer: Drawer,
55
+ SelectRecord: SelectRecord,
56
+ Switch: Switch,
57
+ };
58
+ }
59
+
60
+ export function getExtensionUtils(lobb: LobbClient, ctx: CTX): ExtensionUtils {
61
+ return {
62
+ ctx: ctx,
63
+ lobb: lobb,
64
+ location: location,
65
+ toast: toast,
66
+ showDialog: showDialog,
67
+ components: getComponents(),
68
+ mediaQueries: mediaQueries,
69
+ intlDate: intlDate,
70
+ };
71
+ }
72
+
73
+ export async function loadExtensions(lobb: LobbClient, ctx: CTX, extensionMap: Record<string, any> = {}): Promise<Record<string, Extension>> {
74
+ const extensions: Record<string, Extension> = {};
75
+
76
+ const extensionNames = Object.keys(extensionMap).filter(name => ctx.meta.extensions[name] != null);
77
+ for (let index = 0; index < extensionNames.length; index++) {
78
+ const extensionName = extensionNames[index];
79
+
80
+ const studioExtension = extensionMap[extensionName](getExtensionUtils(lobb, ctx));
81
+ extensions[studioExtension.name] = studioExtension;
82
+ }
83
+
84
+ return extensions;
85
+ }
86
+
87
+ export function loadExtensionComponents(
88
+ ctx: CTX,
89
+ name: string,
90
+ filterByExtensions?: string[],
91
+ ): any[] {
92
+ const components = [];
93
+ for (const [extensionName, extensionValue] of Object.entries(
94
+ ctx.extensions,
95
+ )) {
96
+ if (filterByExtensions && !filterByExtensions.includes(extensionName)) {
97
+ continue;
98
+ }
99
+ if (extensionValue.components) {
100
+ for (const [componentName, componentValue] of Object.entries(
101
+ extensionValue.components,
102
+ )) {
103
+ if (name.startsWith(componentName)) {
104
+ components.push(componentValue);
105
+ }
106
+ }
107
+ }
108
+ }
109
+ return components;
110
+ }
111
+
112
+ export async function executeExtensionsOnStartup(lobb: LobbClient, ctx: CTX) {
113
+ const extensionNames: string[] = Object.keys(ctx.extensions);
114
+ for (let index = 0; index < extensionNames.length; index++) {
115
+ const extensionName = extensionNames[index];
116
+ const extension = ctx.extensions[extensionName];
117
+ if (extension) {
118
+ if (extension.onStartup) {
119
+ await extension.onStartup(getExtensionUtils(lobb, ctx));
120
+ }
121
+ }
122
+ }
123
+ }
124
+
125
+ export function getDashboardNavs(ctx: CTX): DashboardNavs {
126
+ let navs: DashboardNavs = {
127
+ top: [],
128
+ middle: [],
129
+ bottom: [],
130
+ };
131
+ const extensionNames: string[] = Object.keys(ctx.extensions);
132
+ for (let index = 0; index < extensionNames.length; index++) {
133
+ const extensionName = extensionNames[index];
134
+ const extension = ctx.extensions[extensionName];
135
+ if (extension) {
136
+ if (extension.dashboardNavs && extension.dashboardNavs.top && navs.top) {
137
+ navs.top = [...navs.top, ...extension.dashboardNavs.top];
138
+ }
139
+ if (
140
+ extension.dashboardNavs &&
141
+ extension.dashboardNavs.middle &&
142
+ navs.middle
143
+ ) {
144
+ navs.middle = [...navs.middle, ...extension.dashboardNavs.middle];
145
+ }
146
+ if (
147
+ extension.dashboardNavs &&
148
+ extension.dashboardNavs.bottom &&
149
+ navs.bottom
150
+ ) {
151
+ navs.bottom = [...navs.bottom, ...extension.dashboardNavs.bottom];
152
+ }
153
+ }
154
+ }
155
+ return navs;
156
+ }
@@ -0,0 +1,24 @@
1
+ export type { ExtensionProps, Extension, ExtensionUtils } from "./extensions/extension.types"
2
+
3
+ export { default as Studio } from "./components/Studio.svelte";
4
+ export { Button } from "./components/ui/button";
5
+ export { Input } from "./components/ui/input";
6
+ export { Separator } from "./components/ui/separator";
7
+ export { Skeleton } from "./components/ui/skeleton";
8
+ export { default as LlmButton } from "./components/LlmButton.svelte";
9
+ export { default as Sidebar } from "./components/sidebar/sidebar.svelte";
10
+ export { default as SidebarTrigger } from "./components/sidebar/sidebarTrigger.svelte";
11
+ export { default as CreateDetailViewButton } from "./components/detailView/create/createDetailViewButton.svelte";
12
+ export { default as UpdateDetailViewButton } from "./components/detailView/update/updateDetailViewButton.svelte";
13
+ export * as Tooltip from "./components/ui/tooltip";
14
+ export * as Breadcrumb from "./components/ui/breadcrumb";
15
+ export { ContextMenu } from "bits-ui";
16
+ export * as Popover from "./components/ui/popover";
17
+ export * as Icons from "lucide-svelte";
18
+ export * as Dialog from "./components/ui/dialog/index";
19
+ export { default as Table } from "./components/dataTable/table.svelte";
20
+ export { default as RangeCalendarButton } from "./components/rangeCalendarButton.svelte";
21
+ export { default as DataTable } from "./components/dataTable/dataTable.svelte";
22
+ export { default as Drawer } from "./components/drawer.svelte";
23
+ export { default as SelectRecord } from "./components/selectRecord.svelte";
24
+ export { Switch } from "./components/ui/switch";