windmill-components 1.447.7 → 1.448.1

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 (82) hide show
  1. package/package/autosize.js +3 -8
  2. package/package/components/AppConnectInner.svelte +7 -1
  3. package/package/components/ArgInput.svelte +673 -596
  4. package/package/components/ArgInput.svelte.d.ts +11 -0
  5. package/package/components/AssignableTags.svelte +2 -1
  6. package/package/components/AssignableTags.svelte.d.ts +1 -0
  7. package/package/components/AssignableTagsInner.svelte +5 -1
  8. package/package/components/AssignableTagsInner.svelte.d.ts +3 -1
  9. package/package/components/AuthSettings.svelte +1 -1
  10. package/package/components/AuthSettings.svelte.d.ts +1 -0
  11. package/package/components/EditableSchemaForm.svelte +61 -29
  12. package/package/components/EditableSchemaForm.svelte.d.ts +9 -0
  13. package/package/components/FirstStepInputs.svelte +3 -1
  14. package/package/components/FlowPreviewContent.svelte +46 -45
  15. package/package/components/HistoricInputs.svelte +2 -0
  16. package/package/components/InstanceSettings.svelte +5 -1
  17. package/package/components/Range.svelte +5 -4
  18. package/package/components/Range.svelte.d.ts +2 -0
  19. package/package/components/RunFormAdvancedPopup.svelte +2 -2
  20. package/package/components/SavedInputsPicker.svelte +6 -0
  21. package/package/components/SchemaForm.svelte +70 -4
  22. package/package/components/SchemaForm.svelte.d.ts +11 -0
  23. package/package/components/ScriptBuilder.svelte +9 -1
  24. package/package/components/ScriptEditor.svelte.d.ts +2 -2
  25. package/package/components/ScriptPicker.svelte.d.ts +1 -1
  26. package/package/components/SimpleEditor.svelte +3 -1
  27. package/package/components/TestConnection.svelte +1 -1
  28. package/package/components/WorkerGroup.svelte +21 -0
  29. package/package/components/WorkerTagPicker.svelte +2 -2
  30. package/package/components/WorkerTagSelect.svelte +2 -2
  31. package/package/components/apps/components/display/table/AppAggridTable.svelte +3 -1
  32. package/package/components/apps/editor/component/components.d.ts +79 -79
  33. package/package/components/details/EmailTriggerConfigSection.svelte.d.ts +1 -1
  34. package/package/components/flows/content/FlowEditorPanel.svelte +2 -2
  35. package/package/components/flows/content/FlowInput.svelte +193 -130
  36. package/package/components/flows/content/FlowInputEditor.svelte +12 -36
  37. package/package/components/flows/content/FlowInputEditor.svelte.d.ts +1 -5
  38. package/package/components/flows/content/FlowInputsQuick.svelte.d.ts +1 -1
  39. package/package/components/flows/content/FlowModuleWorkerTagSelect.svelte +2 -2
  40. package/package/components/flows/flowStateUtils.d.ts +1 -2
  41. package/package/components/flows/flowStateUtils.js +1 -1
  42. package/package/components/flows/pickers/WorkspaceScriptPickerQuick.svelte.d.ts +1 -1
  43. package/package/components/meltComponents/SideBarTab.svelte +60 -0
  44. package/package/components/meltComponents/SideBarTab.svelte.d.ts +24 -0
  45. package/package/components/runs/NoWorkerWithTagWarning.svelte +5 -1
  46. package/package/components/schema/AddProperty.svelte +3 -1
  47. package/package/components/schema/AddPropertyV2.svelte +5 -8
  48. package/package/components/schema/AddPropertyV2.svelte.d.ts +3 -0
  49. package/package/components/schema/EditableSchemaDrawer.svelte +12 -3
  50. package/package/components/schema/EditableSchemaWrapper.svelte +5 -0
  51. package/package/components/schema/SchemaFormDND.svelte +25 -9
  52. package/package/components/schema/SchemaFormDND.svelte.d.ts +12 -0
  53. package/package/components/schema/schemaUtils.d.ts +26 -0
  54. package/package/components/schema/schemaUtils.js +185 -0
  55. package/package/components/settings/PremiumInfo.svelte +212 -30
  56. package/package/components/triggers/CaptureSection.svelte.d.ts +1 -1
  57. package/package/components/triggers/CaptureTable.svelte +10 -2
  58. package/package/components/triggers/CaptureWrapper.svelte +2 -1
  59. package/package/components/triggers/KafkaTriggersConfigSection.svelte.d.ts +1 -1
  60. package/package/components/triggers/NatsTriggersConfigSection.svelte.d.ts +1 -1
  61. package/package/components/triggers/RouteEditorConfigSection.svelte +3 -2
  62. package/package/components/triggers/RouteEditorConfigSection.svelte.d.ts +2 -1
  63. package/package/components/triggers/RoutesPanel.svelte +2 -0
  64. package/package/components/triggers/RoutesPanel.svelte.d.ts +1 -0
  65. package/package/components/triggers/TriggersEditor.svelte +3 -1
  66. package/package/components/triggers/TriggersEditor.svelte.d.ts +1 -0
  67. package/package/components/triggers/TriggersEditorSection.svelte +0 -1
  68. package/package/components/triggers/TriggersWrapper.svelte +1 -1
  69. package/package/components/triggers/WebhooksConfigSection.svelte +9 -9
  70. package/package/components/triggers/WebhooksConfigSection.svelte.d.ts +2 -2
  71. package/package/components/triggers/WebhooksPanel.svelte +2 -2
  72. package/package/components/triggers/WebhooksPanel.svelte.d.ts +1 -1
  73. package/package/components/triggers/WebsocketEditorConfigSection.svelte.d.ts +1 -1
  74. package/package/gen/core/OpenAPI.js +1 -1
  75. package/package/gen/schemas.gen.d.ts +2 -2
  76. package/package/gen/schemas.gen.js +2 -2
  77. package/package/gen/services.gen.d.ts +22 -2
  78. package/package/gen/services.gen.js +44 -2
  79. package/package/gen/types.gen.d.ts +62 -2
  80. package/package/script_helpers.d.ts +1 -1
  81. package/package/script_helpers.js +7 -7
  82. package/package.json +11 -3
@@ -11,7 +11,7 @@ export declare function pickScript(path: string, summary: string, id: string, ha
11
11
  export declare function pickFlow(path: string, summary: string, id: string): Promise<[FlowModule & {
12
12
  value: PathFlow;
13
13
  }, FlowModuleState]>;
14
- export declare function createInlineScriptModule(language: RawScript['language'], kind: Script['kind'], subkind: 'pgsql' | 'flow' | 'preprocessor', id: string, summary?: string): Promise<[FlowModule, FlowModuleState]>;
14
+ export declare function createInlineScriptModule(language: RawScript['language'], kind: Script['kind'], subkind: 'pgsql' | 'flow' | undefined, id: string, summary?: string): Promise<[FlowModule, FlowModuleState]>;
15
15
  export declare function createLoop(id: string, enabledAi: boolean): Promise<[FlowModule, FlowModuleState]>;
16
16
  export declare function createWhileLoop(id: string): Promise<[FlowModule, FlowModuleState]>;
17
17
  export declare function createBranches(id: string): Promise<[FlowModule, FlowModuleState]>;
@@ -28,7 +28,6 @@ export declare function deleteFlowStateById(id: string, flowStateStore: Writable
28
28
  export declare function sliceModules(modules: FlowModule[], upTo: number, idOrders: string[]): FlowModule[];
29
29
  export declare function insertNewPreprocessorModule(flowStore: Writable<ExtendedOpenFlow>, flowStateStore: Writable<FlowState>, inlineScript?: {
30
30
  language: RawScript['language'];
31
- subkind: 'preprocessor';
32
31
  }, wsScript?: {
33
32
  path: string;
34
33
  summary: string;
@@ -219,7 +219,7 @@ export async function insertNewPreprocessorModule(flowStore, flowStateStore, inl
219
219
  var state = emptyFlowModuleState();
220
220
  if (inlineScript) {
221
221
  ;
222
- [module, state] = await createInlineScriptModule(inlineScript.language, 'script', inlineScript.subkind, 'preprocessor');
222
+ [module, state] = await createInlineScriptModule(inlineScript.language, 'preprocessor', undefined, 'preprocessor');
223
223
  }
224
224
  else if (wsScript) {
225
225
  ;
@@ -1,7 +1,7 @@
1
1
  import { SvelteComponent } from "svelte";
2
2
  declare const __propDef: {
3
3
  props: {
4
- kind?: "script" | "failure" | "trigger" | "approval" | "flow" | "preprocessor" | undefined;
4
+ kind?: "script" | "failure" | "trigger" | "approval" | "preprocessor" | "flow" | undefined;
5
5
  isTemplate?: boolean | undefined;
6
6
  selected?: number | undefined;
7
7
  displayPath?: boolean | undefined;
@@ -0,0 +1,60 @@
1
+ <script>export let dropdownItems = [];
2
+ export let fullMenu = false;
3
+ let open = false;
4
+ let timeout = null;
5
+ function handleMouseEnter() {
6
+ if (!fullMenu)
7
+ return;
8
+ timeout = setTimeout(() => {
9
+ open = true;
10
+ }, 500);
11
+ }
12
+ function handleMouseLeave() {
13
+ if (timeout) {
14
+ clearTimeout(timeout);
15
+ timeout = null;
16
+ }
17
+ open = false;
18
+ }
19
+ </script>
20
+
21
+ <!-- svelte-ignore a11y-no-static-element-interactions -->
22
+ <div
23
+ class="flex flex-col relative !overflow-visible"
24
+ on:mouseenter={handleMouseEnter}
25
+ on:mouseleave={handleMouseLeave}
26
+ >
27
+ <slot name="close button" />
28
+
29
+ {#if fullMenu}
30
+ <div
31
+ class="absolute flex-col top-[30px] left-0 z-50 bg-surface border-l border-b {open
32
+ ? 'rounded-md rounded-tl-none overflow-hidden shadow-md'
33
+ : 'rounded-bl-md'}"
34
+ >
35
+ {#each dropdownItems as item}
36
+ <button
37
+ class="hover:bg-surface-hover p-2 transition-colors duration-150 w-full {item.selected
38
+ ? 'bg-surface-selected'
39
+ : 'text-secondary'}"
40
+ on:click={() => {
41
+ item.onClick()
42
+ open = false
43
+ }}
44
+ >
45
+ <div class="flex flex-row items-center gap-2 min-h-[20px]">
46
+ {#if item.icon}
47
+ <svelte:component this={item.icon} size={14} />
48
+ {/if}
49
+
50
+ {#if open}
51
+ <p class="text-xs text-secondary whitespace-nowrap text-left">
52
+ {item.label}
53
+ </p>
54
+ {/if}
55
+ </div>
56
+ </button>
57
+ {/each}
58
+ </div>
59
+ {/if}
60
+ </div>
@@ -0,0 +1,24 @@
1
+ import { SvelteComponent } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ dropdownItems?: {
5
+ label: string;
6
+ onClick: () => void;
7
+ icon?: any;
8
+ selected?: boolean | undefined;
9
+ }[] | undefined;
10
+ fullMenu?: boolean | undefined;
11
+ };
12
+ events: {
13
+ [evt: string]: CustomEvent<any>;
14
+ };
15
+ slots: {
16
+ 'close button': {};
17
+ };
18
+ };
19
+ export type SideBarTabProps = typeof __propDef.props;
20
+ export type SideBarTabEvents = typeof __propDef.events;
21
+ export type SideBarTabSlots = typeof __propDef.slots;
22
+ export default class SideBarTab extends SvelteComponent<SideBarTabProps, SideBarTabEvents, SideBarTabSlots> {
23
+ }
24
+ export {};
@@ -5,13 +5,16 @@ import { onDestroy } from 'svelte';
5
5
  export let tag;
6
6
  let noWorkerWithTag = false;
7
7
  let timeout = undefined;
8
+ let visible = true;
8
9
  async function lookForTag() {
9
10
  try {
10
11
  const existsWorkerWithTag = await WorkerService.existsWorkerWithTag({ tag });
11
12
  noWorkerWithTag = !existsWorkerWithTag;
12
13
  if (noWorkerWithTag) {
13
14
  timeout = setTimeout(() => {
14
- lookForTag();
15
+ if (visible) {
16
+ lookForTag();
17
+ }
15
18
  }, 1000);
16
19
  }
17
20
  }
@@ -21,6 +24,7 @@ async function lookForTag() {
21
24
  }
22
25
  lookForTag();
23
26
  onDestroy(() => {
27
+ visible = false;
24
28
  if (timeout) {
25
29
  clearTimeout(timeout);
26
30
  }
@@ -112,7 +112,9 @@ export function handleDeleteArgument(argPath) {
112
112
  });
113
113
  if (Object.keys(modifiedProperties).includes(argName)) {
114
114
  delete modifiedProperties[argName];
115
- modifiedObject.required = schema.required.filter((arg) => arg !== argName);
115
+ if (modifiedObject.required) {
116
+ modifiedObject.required = schema.required.filter((arg) => arg !== argName);
117
+ }
116
118
  if (modifiedObject.order) {
117
119
  modifiedObject.order = modifiedObject.order.filter((arg) => arg !== argName);
118
120
  }
@@ -1,7 +1,6 @@
1
1
  <script>import { modalToSchema } from '../../common';
2
2
  import { emptySchema, sendUserToast } from '../../utils';
3
3
  import { createEventDispatcher } from 'svelte';
4
- import SimpleEditor from '../SimpleEditor.svelte';
5
4
  import AddPropertyFormV2 from './AddPropertyFormV2.svelte';
6
5
  export let schema = emptySchema();
7
6
  export const DEFAULT_PROPERTY = {
@@ -14,12 +13,10 @@ const dispatch = createEventDispatcher();
14
13
  if (!schema) {
15
14
  schema = emptySchema();
16
15
  }
17
- let schemaString = '';
18
16
  // Internal state: bound to args builder modal
19
17
  let argError = '';
20
18
  let editing = false;
21
19
  let oldArgName; // when editing argument and changing name
22
- let jsonEditor;
23
20
  reorder();
24
21
  function reorder() {
25
22
  if (schema.order && Array.isArray(schema.order)) {
@@ -42,7 +39,7 @@ function syncOrders() {
42
39
  schema.order = Object.keys(schema.properties ?? {});
43
40
  }
44
41
  }
45
- function handleAddOrEditArgument(modalProperty) {
42
+ export function handleAddOrEditArgument(modalProperty) {
46
43
  // If editing the arg's name, oldName containing the old argument name must be provided
47
44
  argError = '';
48
45
  modalProperty.name = modalProperty.name.trim();
@@ -89,8 +86,6 @@ function handleAddOrEditArgument(modalProperty) {
89
86
  oldArgName = undefined;
90
87
  }
91
88
  schema = schema;
92
- schemaString = JSON.stringify(schema, null, '\t');
93
- jsonEditor?.setCode(schemaString);
94
89
  if (argError !== '') {
95
90
  sendUserToast(argError, true);
96
91
  }
@@ -112,12 +107,13 @@ export function handleDeleteArgument(argPath) {
112
107
  });
113
108
  if (Object.keys(modifiedProperties).includes(argName)) {
114
109
  delete modifiedProperties[argName];
115
- modifiedObject.required = schema.required.filter((arg) => arg !== argName);
110
+ if (modifiedObject.required) {
111
+ modifiedObject.required = schema.required.filter((arg) => arg !== argName);
112
+ }
116
113
  if (modifiedObject.order) {
117
114
  modifiedObject.order = modifiedObject.order.filter((arg) => arg !== argName);
118
115
  }
119
116
  schema = schema;
120
- schemaString = JSON.stringify(schema, null, '\t');
121
117
  dispatch('change', schema);
122
118
  }
123
119
  else {
@@ -140,6 +136,7 @@ export function handleDeleteArgument(argPath) {
140
136
  selectedType: 'string',
141
137
  name: e.detail.name
142
138
  })
139
+ dispatch('addNew', e.detail.name)
143
140
  } catch (err) {
144
141
  sendUserToast(`Could not add argument: ${err}`, true)
145
142
  }
@@ -4,9 +4,11 @@ declare const __propDef: {
4
4
  props: {
5
5
  schema?: Schema | any;
6
6
  DEFAULT_PROPERTY?: ModalSchemaProperty | undefined;
7
+ handleAddOrEditArgument?: ((modalProperty: ModalSchemaProperty) => void) | undefined;
7
8
  handleDeleteArgument?: ((argPath: string[]) => void) | undefined;
8
9
  };
9
10
  events: {
11
+ addNew: CustomEvent<any>;
10
12
  change: CustomEvent<any>;
11
13
  } & {
12
14
  [evt: string]: CustomEvent<any>;
@@ -20,6 +22,7 @@ export type AddPropertyV2Events = typeof __propDef.events;
20
22
  export type AddPropertyV2Slots = typeof __propDef.slots;
21
23
  export default class AddPropertyV2 extends SvelteComponent<AddPropertyV2Props, AddPropertyV2Events, AddPropertyV2Slots> {
22
24
  get DEFAULT_PROPERTY(): ModalSchemaProperty;
25
+ get handleAddOrEditArgument(): (modalProperty: ModalSchemaProperty) => void;
23
26
  get handleDeleteArgument(): (argPath: string[]) => void;
24
27
  }
25
28
  export {};
@@ -135,8 +135,11 @@ let error = undefined;
135
135
  <div class="flex flex-col w-full mt-2">
136
136
  <Label label="Nested properties">
137
137
  <svelte:self
138
- on:change={() => (schema = schema)}
139
- schema={schema.properties[item.value]}
138
+ on:change={() => {
139
+ schema = schema
140
+ dispatch('change', schema)
141
+ }}
142
+ bind:schema={schema.properties[item.value]}
140
143
  parentId={item.value}
141
144
  />
142
145
  </Label>
@@ -168,7 +171,13 @@ let error = undefined;
168
171
  editTab="inputEditor"
169
172
  >
170
173
  <svelte:fragment slot="addProperty">
171
- <AddPropertyV2 bind:schema on:change>
174
+ <AddPropertyV2
175
+ bind:schema
176
+ on:change
177
+ on:addNew={(e) => {
178
+ editableSchemaForm?.openField(e.detail)
179
+ }}
180
+ >
172
181
  <svelte:fragment slot="trigger">
173
182
  <div
174
183
  class="w-full py-2 flex justify-center items-center border border-dashed rounded-md hover:bg-surface-hover"
@@ -15,6 +15,7 @@ export let lightweightMode = false;
15
15
  export let formatExtension = undefined;
16
16
  let resourceIsTextFile = false;
17
17
  let addProperty = undefined;
18
+ let editableSchemaForm = undefined;
18
19
  const dispatch = createEventDispatcher();
19
20
  $: !resourceIsTextFile && (formatExtension = undefined);
20
21
  $: invalidExtension =
@@ -80,6 +81,9 @@ let autocompleteExtension = true;
80
81
  bind:schema
81
82
  bind:this={addProperty}
82
83
  on:change={() => dispatch('change', schema)}
84
+ on:addNew={(e) => {
85
+ editableSchemaForm?.openField(e.detail)
86
+ }}
83
87
  >
84
88
  <svelte:fragment slot="trigger">
85
89
  <div
@@ -91,6 +95,7 @@ let autocompleteExtension = true;
91
95
  </AddPropertyV2>
92
96
  {/if}
93
97
  <EditableSchemaForm
98
+ bind:this={editableSchemaForm}
94
99
  bind:schema
95
100
  on:change={() => dispatch('change', schema)}
96
101
  isFlowInput
@@ -12,6 +12,11 @@ export let onlyMaskPassword = false;
12
12
  export let disablePortal = false;
13
13
  export let disabled = false;
14
14
  export let schemaSkippedValues = [];
15
+ export let nestedParent = undefined;
16
+ export let disableDnd = false;
17
+ export let shouldDispatchChanges = false;
18
+ export let diff = {};
19
+ export let nestedClasses = '';
15
20
  const dispatch = createEventDispatcher();
16
21
  const flipDurationMs = 200;
17
22
  let items = computeItems();
@@ -48,12 +53,16 @@ function handleFinalize(e) {
48
53
  <!-- svelte-ignore a11y-no-static-element-interactions -->
49
54
  <!-- svelte-ignore a11y-no-noninteractive-tabindex -->
50
55
  <SchemaForm
56
+ {nestedClasses}
51
57
  {schemaSkippedValues}
52
58
  on:click
53
59
  on:change
54
60
  on:reorder
55
61
  on:consider={handleConsider}
56
62
  on:finalize={handleFinalize}
63
+ on:acceptChange
64
+ on:rejectChange
65
+ on:nestedChange
57
66
  {lightweightMode}
58
67
  bind:args
59
68
  {prettifyHeader}
@@ -61,17 +70,24 @@ function handleFinalize(e) {
61
70
  {disablePortal}
62
71
  {disabled}
63
72
  bind:schema
64
- dndConfig={{
65
- items,
66
- flipDurationMs,
67
- dropTargetStyle: {},
68
- type: dndType ?? 'top-level'
69
- }}
73
+ dndConfig={disableDnd
74
+ ? undefined
75
+ : {
76
+ items,
77
+ flipDurationMs,
78
+ dropTargetStyle: {},
79
+ type: dndType ?? 'top-level'
80
+ }}
70
81
  {items}
82
+ {diff}
83
+ {nestedParent}
84
+ {shouldDispatchChanges}
71
85
  >
72
86
  <svelte:fragment slot="actions">
73
- <div class="w-4 h-8 cursor-move ml-2 handle" aria-label="drag-handle" use:dragHandle>
74
- <GripVertical size={16} />
75
- </div>
87
+ {#if !disableDnd}
88
+ <div class="w-4 h-8 cursor-move ml-2 handle" aria-label="drag-handle" use:dragHandle>
89
+ <GripVertical size={16} />
90
+ </div>
91
+ {/if}
76
92
  </svelte:fragment>
77
93
  </SchemaForm>
@@ -1,5 +1,6 @@
1
1
  import { SvelteComponent } from "svelte";
2
2
  import type { Schema } from '../../common';
3
+ import type { SchemaDiff } from './schemaUtils';
3
4
  declare const __propDef: {
4
5
  props: {
5
6
  dndType?: string | undefined;
@@ -11,11 +12,22 @@ declare const __propDef: {
11
12
  disablePortal?: boolean | undefined;
12
13
  disabled?: boolean | undefined;
13
14
  schemaSkippedValues?: string[] | undefined;
15
+ nestedParent?: {
16
+ label: string;
17
+ nestedParent: any | undefined;
18
+ } | undefined;
19
+ disableDnd?: boolean | undefined;
20
+ shouldDispatchChanges?: boolean | undefined;
21
+ diff?: Record<string, SchemaDiff> | undefined;
22
+ nestedClasses?: string | undefined;
14
23
  };
15
24
  events: {
16
25
  click: CustomEvent<any>;
17
26
  change: CustomEvent<any>;
18
27
  reorder: CustomEvent<any>;
28
+ acceptChange: CustomEvent<any>;
29
+ rejectChange: CustomEvent<any>;
30
+ nestedChange: CustomEvent<any>;
19
31
  } & {
20
32
  [evt: string]: CustomEvent<any>;
21
33
  };
@@ -0,0 +1,26 @@
1
+ export type SchemaDiff = {
2
+ diff: 'same' | 'added' | 'removed' | 'modified' | Record<string, SchemaDiff>;
3
+ fullSchema: {
4
+ [key: string]: any;
5
+ } | undefined;
6
+ oldSchema?: {
7
+ [key: string]: any;
8
+ } | undefined;
9
+ };
10
+ export declare function computeDiff(previewSchema: {
11
+ [key: string]: any;
12
+ } | undefined, currentSchema: {
13
+ [key: string]: any;
14
+ } | undefined): Record<string, SchemaDiff>;
15
+ export declare function schemaFromDiff(diff: Record<string, SchemaDiff>, schema: {
16
+ [key: string]: any;
17
+ } | undefined): {
18
+ [key: string]: any;
19
+ } | undefined;
20
+ export declare function getFullPath(arg: {
21
+ label: string;
22
+ nestedParent: any | undefined;
23
+ }): string[];
24
+ export declare function getNestedProperty(obj: any, path: string[], field?: string): any;
25
+ export declare function setNestedProperty(obj: any, path: string[], value: any, field?: string): void;
26
+ export declare function applyDiff(schema: Record<string, any> | undefined, diff: Record<string, SchemaDiff> | undefined): Record<string, any> | undefined;
@@ -0,0 +1,185 @@
1
+ function isCompatible(diff) {
2
+ let compatible = true;
3
+ Object.values(diff).forEach((diff) => {
4
+ if (diff.diff === 'added' || diff.diff === 'modified' || diff.diff === 'removed') {
5
+ compatible = false;
6
+ }
7
+ else if (isRecordSchemaDiff(diff.diff)) {
8
+ compatible = isCompatible(diff.diff);
9
+ }
10
+ });
11
+ return compatible;
12
+ }
13
+ function isCompatibleObject(a, b) {
14
+ if (!a || !b) {
15
+ return false;
16
+ }
17
+ if (a.type === 'null' || b.type === 'null') {
18
+ return true;
19
+ }
20
+ if (a.type !== b.type) {
21
+ if ((a.type === 'number' || a.type === 'integer') &&
22
+ (b.type === 'number' || b.type === 'integer')) {
23
+ return true;
24
+ }
25
+ return false;
26
+ }
27
+ switch (a.type) {
28
+ case 'object':
29
+ if (a.oneOf || b.oneOf) {
30
+ //TODO: handle oneOf compatibility. here we assume that only b is oneOf
31
+ return true;
32
+ }
33
+ return a.format === b.format;
34
+ case 'array':
35
+ return !a.items || !b.items || a.items?.type === b.items?.type;
36
+ case 'string':
37
+ return a.format === b.format;
38
+ case 'boolean':
39
+ case 'number':
40
+ case 'integer':
41
+ return true;
42
+ default:
43
+ return false;
44
+ }
45
+ }
46
+ export function computeDiff(previewSchema, currentSchema) {
47
+ if (!previewSchema || !currentSchema) {
48
+ return {};
49
+ }
50
+ const diff = {};
51
+ if (previewSchema?.properties) {
52
+ Object.keys(previewSchema.properties).forEach((key) => {
53
+ if (!currentSchema?.properties?.[key]) {
54
+ diff[key] = {
55
+ diff: 'added',
56
+ fullSchema: previewSchema.properties[key]
57
+ };
58
+ }
59
+ else {
60
+ const previewProp = previewSchema.properties[key];
61
+ const currentProp = currentSchema.properties[key];
62
+ if (previewProp.type === 'object' && currentProp.type === 'object') {
63
+ if (JSON.stringify(previewProp) === JSON.stringify(currentProp)) {
64
+ diff[key] = { diff: 'same', fullSchema: undefined };
65
+ }
66
+ else if (previewProp.oneOf || currentProp.oneOf) {
67
+ if (isCompatibleObject(previewProp, currentProp)) {
68
+ diff[key] = { diff: 'same', fullSchema: undefined };
69
+ }
70
+ else {
71
+ diff[key] = { diff: 'modified', fullSchema: previewProp, oldSchema: currentProp };
72
+ }
73
+ }
74
+ else if (previewProp.format || currentProp.format) {
75
+ //TODO: handle s3 object compatibility
76
+ diff[key] = { diff: 'modified', fullSchema: previewProp, oldSchema: currentProp };
77
+ }
78
+ else {
79
+ const diffProp = computeDiff(previewProp, currentProp);
80
+ const checkIfSame = isCompatible(diffProp);
81
+ if (checkIfSame) {
82
+ diff[key] = { diff: 'same', fullSchema: undefined };
83
+ }
84
+ else {
85
+ diff[key] = {
86
+ diff: diffProp,
87
+ fullSchema: previewProp,
88
+ oldSchema: currentProp
89
+ };
90
+ }
91
+ }
92
+ }
93
+ else if (isCompatibleObject(previewProp, currentProp)) {
94
+ diff[key] = { diff: 'same', fullSchema: undefined };
95
+ }
96
+ else {
97
+ diff[key] = { diff: 'modified', fullSchema: previewProp, oldSchema: currentProp };
98
+ }
99
+ }
100
+ });
101
+ }
102
+ if (currentSchema?.properties) {
103
+ Object.keys(currentSchema.properties).forEach((key) => {
104
+ if (!previewSchema?.properties?.[key]) {
105
+ diff[key] = { diff: 'removed', fullSchema: undefined };
106
+ }
107
+ });
108
+ }
109
+ return diff;
110
+ }
111
+ export function schemaFromDiff(diff, schema) {
112
+ if (!schema) {
113
+ return undefined;
114
+ }
115
+ const newSchema = structuredClone(schema);
116
+ Object.keys(diff).forEach((key) => {
117
+ const diffValue = diff[key].diff;
118
+ if (diffValue === 'added' || diffValue === 'modified') {
119
+ newSchema.properties[key] = diff[key].fullSchema;
120
+ if (newSchema.order && !newSchema.order.includes(key)) {
121
+ newSchema.order.push(key);
122
+ }
123
+ }
124
+ else if (isRecordSchemaDiff(diffValue)) {
125
+ // Handle nested diffs
126
+ newSchema.properties[key] = schemaFromDiff(diffValue, schema.properties[key]);
127
+ }
128
+ });
129
+ return newSchema;
130
+ }
131
+ export function getFullPath(arg) {
132
+ const getPath = (current) => {
133
+ if (!current.nestedParent) {
134
+ return [current.label];
135
+ }
136
+ return [...getPath(current.nestedParent), current.label];
137
+ };
138
+ return getPath(arg);
139
+ }
140
+ export function getNestedProperty(obj, path, field = 'properties') {
141
+ return path.reduce((curr, key) => curr?.[field]?.[key], obj);
142
+ }
143
+ export function setNestedProperty(obj, path, value, field = 'properties') {
144
+ const pathCopy = [...path];
145
+ const lastKey = pathCopy.pop();
146
+ const target = pathCopy.reduce((curr, key) => {
147
+ if (!(key in curr[field])) {
148
+ curr[field][key] = { [field]: {} };
149
+ }
150
+ return curr[field][key];
151
+ }, obj);
152
+ if (lastKey && value) {
153
+ const newValue = structuredClone(value);
154
+ target[field][lastKey] = newValue;
155
+ return;
156
+ }
157
+ else if (lastKey && !value) {
158
+ delete target[field][lastKey];
159
+ }
160
+ }
161
+ function isRecordSchemaDiff(value) {
162
+ return typeof value === 'object' && value !== null;
163
+ }
164
+ export function applyDiff(schema, diff) {
165
+ if (!diff || !schema) {
166
+ return;
167
+ }
168
+ let newSchema = structuredClone(schema);
169
+ Object.keys(diff).forEach((key) => {
170
+ const diffValue = diff[key].diff;
171
+ if (diffValue === 'removed') {
172
+ delete newSchema.properties[key];
173
+ if (newSchema.order) {
174
+ newSchema.order = newSchema.order.filter((x) => x !== key);
175
+ }
176
+ }
177
+ else if (diffValue === 'added' || diffValue === 'modified' || isRecordSchemaDiff(diffValue)) {
178
+ newSchema.properties[key] = diff[key].fullSchema;
179
+ if (newSchema.order && !newSchema.order.includes(key)) {
180
+ newSchema.order.push(key);
181
+ }
182
+ }
183
+ });
184
+ return newSchema;
185
+ }