rune-lab 0.0.8 → 0.0.9
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/dist/components/api/RLApiInterface.svelte +18 -12
- package/dist/components/api/RLApiInterface.svelte.d.ts +4 -6
- package/dist/components/common/RLPripertyTable.svelte +107 -0
- package/dist/components/common/RLPripertyTable.svelte.d.ts +44 -0
- package/dist/components/dataview/RLDetailRow.svelte +61 -0
- package/dist/components/dataview/RLDetailRow.svelte.d.ts +20 -0
- package/dist/components/dataview/RLMetadataList.svelte +53 -0
- package/dist/components/dataview/RLMetadataList.svelte.d.ts +23 -0
- package/dist/components/explorer/RLEnumDisplay.svelte +34 -0
- package/dist/components/explorer/RLEnumDisplay.svelte.d.ts +7 -0
- package/dist/components/explorer/RLFunctionDisplay.svelte +64 -0
- package/dist/components/explorer/RLFunctionDisplay.svelte.d.ts +13 -0
- package/dist/components/explorer/RLSchemaExplorer.svelte +198 -325
- package/dist/components/explorer/RLTableDisplay.svelte +48 -0
- package/dist/components/explorer/RLTableDisplay.svelte.d.ts +16 -0
- package/dist/components/explorer/RLViewDisplay.svelte +46 -0
- package/dist/components/explorer/RLViewDisplay.svelte.d.ts +15 -0
- package/dist/components/stores/explorer.svelte.d.ts +3 -0
- package/dist/tools/schema-transformer.js +1 -0
- package/dist/types/api.d.ts +1 -0
- package/dist/types/api.js +1 -0
- package/dist/types/explorer.d.ts +1 -0
- package/dist/types/explorer.js +1 -0
- package/package.json +2 -1
|
@@ -1,46 +1,52 @@
|
|
|
1
1
|
<!-- src/lib/components/api/RLApiInterface.svelte -->
|
|
2
2
|
<script lang="ts">
|
|
3
|
-
import type { ColumnMetadata } from '@yrrrrrf/prism-ts';
|
|
4
|
-
|
|
3
|
+
import type { ColumnMetadata as PrismColumnMetadata } from '@yrrrrrf/prism-ts';
|
|
4
|
+
// Import RLApiInterfaceActionParams from YOUR definition in the explorer store
|
|
5
|
+
import type { RLApiInterfaceActionParams } from '../stores/explorer.svelte.ts';
|
|
6
|
+
|
|
7
|
+
// For convenience within this component, you can extract the operation type.
|
|
8
|
+
// This is NOT redefining it; it's creating a local alias to a part of an imported type.
|
|
9
|
+
type LocalAPIOperation = RLApiInterfaceActionParams['operation'];
|
|
5
10
|
|
|
6
11
|
let {
|
|
7
12
|
schemaName,
|
|
8
13
|
resourceName,
|
|
9
14
|
resourceType,
|
|
10
15
|
columns,
|
|
11
|
-
onOpenModal
|
|
16
|
+
onOpenModal
|
|
12
17
|
} = $props<{
|
|
13
18
|
schemaName: string;
|
|
14
19
|
resourceName: string;
|
|
15
|
-
resourceType: 'table' | 'view' | 'function';
|
|
16
|
-
columns:
|
|
17
|
-
onOpenModal: (params:
|
|
20
|
+
resourceType: 'table' | 'view' | 'function';
|
|
21
|
+
columns: PrismColumnMetadata[]; // This prop is fine if it's what the component receives
|
|
22
|
+
onOpenModal: (params: RLApiInterfaceActionParams) => void; // Uses your imported interface
|
|
18
23
|
}>();
|
|
19
24
|
|
|
20
|
-
|
|
25
|
+
// Use the local alias or RLApiInterfaceActionParams['operation']
|
|
26
|
+
function getAllowedOps(type: 'table' | 'view' | 'function'): LocalAPIOperation[] {
|
|
21
27
|
if (type === 'table') return ['GET', 'POST', 'PUT', 'DELETE'];
|
|
22
28
|
if (type === 'view') return ['GET'];
|
|
23
|
-
if (type === 'function') return ['POST'];
|
|
29
|
+
if (type === 'function') return ['POST'];
|
|
24
30
|
return [];
|
|
25
31
|
}
|
|
26
32
|
|
|
27
|
-
const operationDetails: Record<
|
|
33
|
+
const operationDetails: Record<LocalAPIOperation, { label: string, class: string }> = {
|
|
28
34
|
GET: { label: 'GET', class: 'btn-info' },
|
|
29
35
|
POST: { label: 'POST', class: 'btn-success' },
|
|
30
36
|
PUT: { label: 'PUT', class: 'btn-warning' },
|
|
31
37
|
DELETE: { label: 'DELETE', class: 'btn-error' },
|
|
32
38
|
};
|
|
33
39
|
|
|
34
|
-
function handleOperationClick(operation:
|
|
40
|
+
function handleOperationClick(operation: LocalAPIOperation) {
|
|
41
|
+
// Construct the object that matches RLApiInterfaceActionParams
|
|
35
42
|
onOpenModal({ operation });
|
|
36
43
|
}
|
|
37
|
-
|
|
38
44
|
</script>
|
|
39
45
|
|
|
40
46
|
<div class="flex flex-wrap gap-2 my-2">
|
|
41
47
|
{#each getAllowedOps(resourceType) as operation}
|
|
42
48
|
{@const detail = operationDetails[operation]}
|
|
43
|
-
{#if detail}
|
|
49
|
+
{#if detail}
|
|
44
50
|
<button
|
|
45
51
|
class="btn btn-sm {detail.class}"
|
|
46
52
|
onclick={() => handleOperationClick(operation)}
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import type { ColumnMetadata } from '@yrrrrrf/prism-ts';
|
|
2
|
-
type
|
|
1
|
+
import type { ColumnMetadata as PrismColumnMetadata } from '@yrrrrrf/prism-ts';
|
|
2
|
+
import type { RLApiInterfaceActionParams } from '../stores/explorer.svelte.ts';
|
|
3
3
|
type $$ComponentProps = {
|
|
4
4
|
schemaName: string;
|
|
5
5
|
resourceName: string;
|
|
6
6
|
resourceType: 'table' | 'view' | 'function';
|
|
7
|
-
columns:
|
|
8
|
-
onOpenModal: (params:
|
|
9
|
-
operation: APIOperation;
|
|
10
|
-
}) => void;
|
|
7
|
+
columns: PrismColumnMetadata[];
|
|
8
|
+
onOpenModal: (params: RLApiInterfaceActionParams) => void;
|
|
11
9
|
};
|
|
12
10
|
declare const RlApiInterface: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
13
11
|
type RlApiInterface = ReturnType<typeof RlApiInterface>;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
<!-- src/lib/components/common/RLPropertyTable.svelte (example structure) -->
|
|
2
|
+
<script lang="ts">
|
|
3
|
+
import type { RLEnumMetadata, RLColumnReference } from '../stores/explorer.svelte';
|
|
4
|
+
|
|
5
|
+
export interface RLPropertyItem {
|
|
6
|
+
name: string;
|
|
7
|
+
type?: string;
|
|
8
|
+
nullable?: boolean;
|
|
9
|
+
isPrimaryKey?: boolean;
|
|
10
|
+
references?: RLColumnReference;
|
|
11
|
+
isEnum?: boolean;
|
|
12
|
+
mode?: string; // For function params
|
|
13
|
+
hasDefault?: boolean;
|
|
14
|
+
defaultValue?: string | null;
|
|
15
|
+
// Any other properties needed to render details
|
|
16
|
+
_rawItem?: any; // Optional: pass the original item if needed by slot
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
let {
|
|
20
|
+
items,
|
|
21
|
+
title = '',
|
|
22
|
+
nameHeader = "Name",
|
|
23
|
+
detailHeader = "Details",
|
|
24
|
+
enumsInSchema, // Pass this if needed for enum badge clicks from here
|
|
25
|
+
onFkClick,
|
|
26
|
+
onEnumClick,
|
|
27
|
+
} = $props<{
|
|
28
|
+
items: RLPropertyItem[];
|
|
29
|
+
title?: string;
|
|
30
|
+
nameHeader?: string;
|
|
31
|
+
detailHeader?: string;
|
|
32
|
+
enumsInSchema?: Record<string, RLEnumMetadata>; // For resolving enum names if items only have partial enum info
|
|
33
|
+
onFkClick?: (ref: RLColumnReference) => void;
|
|
34
|
+
onEnumClick?: (enumData: RLEnumMetadata) => void;
|
|
35
|
+
}>();
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
<div class="card bg-base-100 shadow-sm overflow-hidden my-2">
|
|
39
|
+
{#if title}
|
|
40
|
+
<div class="card-title p-3 text-sm font-semibold bg-base-200/50">{title}</div>
|
|
41
|
+
{/if}
|
|
42
|
+
<div class="card-body p-0">
|
|
43
|
+
{#if items && items.length > 0}
|
|
44
|
+
<div class="overflow-x-auto">
|
|
45
|
+
<table class="table table-sm w-full">
|
|
46
|
+
<thead>
|
|
47
|
+
<tr>
|
|
48
|
+
<th class="w-2/5 pl-4">{nameHeader}</th>
|
|
49
|
+
{#if detailHeader} <th class="w-3/5 pr-4">{detailHeader}</th> {/if}
|
|
50
|
+
</tr>
|
|
51
|
+
</thead>
|
|
52
|
+
<tbody>
|
|
53
|
+
{#each items as item (item.name)}
|
|
54
|
+
<tr class="hover">
|
|
55
|
+
<td class="align-top py-2 pl-4">
|
|
56
|
+
<div class="flex items-baseline">
|
|
57
|
+
<span class="font-medium">{item.name}</span>
|
|
58
|
+
{#if item.nullable === false && item.type && !item.type.toLowerCase().includes('bool')} <!-- Nullability for non-booleans -->
|
|
59
|
+
<span class="text-error ml-1 select-none" title="Required field">*</span>
|
|
60
|
+
{/if}
|
|
61
|
+
</div>
|
|
62
|
+
{#if item.type && detailHeader} <!-- Only show type if details are shown and type exists -->
|
|
63
|
+
<div class="font-mono text-xs text-base-content/60 italic mt-0.5">{item.type}</div>
|
|
64
|
+
{/if}
|
|
65
|
+
</td>
|
|
66
|
+
{#if detailHeader}
|
|
67
|
+
<td class="align-top py-2 pr-4 space-x-1.5">
|
|
68
|
+
{#if $$slots.detail}
|
|
69
|
+
<slot name="detail" itemData={item}></slot>
|
|
70
|
+
{:else}
|
|
71
|
+
<!-- Default detail rendering -->
|
|
72
|
+
{#if item.isPrimaryKey} <span class="badge badge-accent badge-xs font-semibold">PK</span> {/if}
|
|
73
|
+
{#if item.references}
|
|
74
|
+
<span class="badge badge-secondary badge-xs">FK</span>
|
|
75
|
+
<button class="link link-hover text-xs font-mono !text-info normal-case"
|
|
76
|
+
onclick={() => onFkClick && onFkClick(item.references!)}
|
|
77
|
+
title="Navigate to {item.references.schema}.{item.references.table}.{item.references.column}">
|
|
78
|
+
{item.references.schema}.{item.references.table}.{item.references.column}
|
|
79
|
+
</button>
|
|
80
|
+
{/if}
|
|
81
|
+
{#if item.isEnum && enumsInSchema && enumsInSchema[item.name + '_enum'] /* Crude example of finding enum */}
|
|
82
|
+
{@const enumMeta = enumsInSchema[item.name + '_enum']}
|
|
83
|
+
<button class="badge badge-warning badge-xs hover:shadow-md transition-shadow normal-case"
|
|
84
|
+
onclick={() => onEnumClick && onEnumClick(enumMeta)}
|
|
85
|
+
title="Enum: {enumMeta.name}">
|
|
86
|
+
<span class="mr-1 opacity-70">Enum:</span>{enumMeta.name}
|
|
87
|
+
</button>
|
|
88
|
+
{:else if item.isEnum}
|
|
89
|
+
<span class="badge badge-ghost badge-xs">Enum</span>
|
|
90
|
+
{/if}
|
|
91
|
+
{#if item.mode} <span class="badge badge-info badge-xs">{item.mode}</span> {/if}
|
|
92
|
+
{#if item.hasDefault} <span class="badge badge-outline badge-xs" title="Default: {item.defaultValue}">Has Default</span> {/if}
|
|
93
|
+
{/if}
|
|
94
|
+
</td>
|
|
95
|
+
{/if}
|
|
96
|
+
</tr>
|
|
97
|
+
{/each}
|
|
98
|
+
</tbody>
|
|
99
|
+
</table>
|
|
100
|
+
</div>
|
|
101
|
+
{:else}
|
|
102
|
+
<div class="p-4 text-center text-neutral-content/70">
|
|
103
|
+
No items to display.
|
|
104
|
+
</div>
|
|
105
|
+
{/if}
|
|
106
|
+
</div>
|
|
107
|
+
</div>
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { RLEnumMetadata, RLColumnReference } from '../stores/explorer.svelte';
|
|
2
|
+
export interface RLPropertyItem {
|
|
3
|
+
name: string;
|
|
4
|
+
type?: string;
|
|
5
|
+
nullable?: boolean;
|
|
6
|
+
isPrimaryKey?: boolean;
|
|
7
|
+
references?: RLColumnReference;
|
|
8
|
+
isEnum?: boolean;
|
|
9
|
+
mode?: string;
|
|
10
|
+
hasDefault?: boolean;
|
|
11
|
+
defaultValue?: string | null;
|
|
12
|
+
_rawItem?: any;
|
|
13
|
+
}
|
|
14
|
+
type $$ComponentProps = {
|
|
15
|
+
items: RLPropertyItem[];
|
|
16
|
+
title?: string;
|
|
17
|
+
nameHeader?: string;
|
|
18
|
+
detailHeader?: string;
|
|
19
|
+
enumsInSchema?: Record<string, RLEnumMetadata>;
|
|
20
|
+
onFkClick?: (ref: RLColumnReference) => void;
|
|
21
|
+
onEnumClick?: (enumData: RLEnumMetadata) => void;
|
|
22
|
+
};
|
|
23
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
24
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
25
|
+
$$bindings?: Bindings;
|
|
26
|
+
} & Exports;
|
|
27
|
+
(internal: unknown, props: Props & {
|
|
28
|
+
$$events?: Events;
|
|
29
|
+
$$slots?: Slots;
|
|
30
|
+
}): Exports & {
|
|
31
|
+
$set?: any;
|
|
32
|
+
$on?: any;
|
|
33
|
+
};
|
|
34
|
+
z_$$bindings?: Bindings;
|
|
35
|
+
}
|
|
36
|
+
declare const RlPripertyTable: $$__sveltets_2_IsomorphicComponent<$$ComponentProps, {
|
|
37
|
+
[evt: string]: CustomEvent<any>;
|
|
38
|
+
}, {
|
|
39
|
+
detail: {
|
|
40
|
+
itemData: unknown;
|
|
41
|
+
};
|
|
42
|
+
}, {}, "">;
|
|
43
|
+
type RlPripertyTable = InstanceType<typeof RlPripertyTable>;
|
|
44
|
+
export default RlPripertyTable;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
<!-- src/lib/components/dataview/RLDetailRow.svelte -->
|
|
2
|
+
<script lang="ts">
|
|
3
|
+
// No specific types needed from explorer.ts for these direct props.
|
|
4
|
+
// This component is highly generic.
|
|
5
|
+
|
|
6
|
+
type DetailAction = {
|
|
7
|
+
text: string;
|
|
8
|
+
class?: string;
|
|
9
|
+
onClick?: (event: MouseEvent) => void;
|
|
10
|
+
title?: string; // For tooltip on the badge/button
|
|
11
|
+
isLink?: boolean; // To render as a link-styled button
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
let {
|
|
15
|
+
name,
|
|
16
|
+
typeInfo = undefined,
|
|
17
|
+
details = [],
|
|
18
|
+
required = false,
|
|
19
|
+
description = undefined,
|
|
20
|
+
nameClass = 'font-medium',
|
|
21
|
+
typeInfoClass = 'font-mono text-xs text-base-content/60 italic mt-0.5',
|
|
22
|
+
containerClass = 'flex justify-between items-baseline py-1.5 hover:bg-base-content/5 px-1 rounded group',
|
|
23
|
+
} = $props<{
|
|
24
|
+
name: string;
|
|
25
|
+
typeInfo?: string;
|
|
26
|
+
details?: DetailAction[];
|
|
27
|
+
required?: boolean;
|
|
28
|
+
description?: string;
|
|
29
|
+
nameClass?: string;
|
|
30
|
+
typeInfoClass?: string;
|
|
31
|
+
containerClass?: string;
|
|
32
|
+
}>();
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
<div class="{containerClass}" title={description}>
|
|
36
|
+
<div class="flex-grow overflow-hidden pr-2">
|
|
37
|
+
<span class="{nameClass}">{name}</span>
|
|
38
|
+
{#if required}
|
|
39
|
+
<span class="text-error ml-1 select-none" title="Required field">*</span>
|
|
40
|
+
{/if}
|
|
41
|
+
{#if typeInfo}
|
|
42
|
+
<div class="{typeInfoClass} truncate" title={typeInfo}>{typeInfo}</div>
|
|
43
|
+
{/if}
|
|
44
|
+
</div>
|
|
45
|
+
{#if details.length > 0}
|
|
46
|
+
<div class="flex-shrink-0 space-x-1.5 flex items-center">
|
|
47
|
+
{#each details as detailItem}
|
|
48
|
+
<button
|
|
49
|
+
class="badge badge-sm whitespace-nowrap {detailItem.class || 'badge-ghost'}
|
|
50
|
+
{detailItem.isLink ? 'link link-hover !text-info normal-case font-mono' : ''}
|
|
51
|
+
disabled:opacity-50"
|
|
52
|
+
onclick={detailItem.onClick}
|
|
53
|
+
title={detailItem.title || detailItem.text}
|
|
54
|
+
disabled={!detailItem.onClick && !detailItem.isLink}
|
|
55
|
+
>
|
|
56
|
+
{@html detailItem.text} <!-- Use @html if text might contain simple entities like → -->
|
|
57
|
+
</button>
|
|
58
|
+
{/each}
|
|
59
|
+
</div>
|
|
60
|
+
{/if}
|
|
61
|
+
</div>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
type DetailAction = {
|
|
2
|
+
text: string;
|
|
3
|
+
class?: string;
|
|
4
|
+
onClick?: (event: MouseEvent) => void;
|
|
5
|
+
title?: string;
|
|
6
|
+
isLink?: boolean;
|
|
7
|
+
};
|
|
8
|
+
type $$ComponentProps = {
|
|
9
|
+
name: string;
|
|
10
|
+
typeInfo?: string;
|
|
11
|
+
details?: DetailAction[];
|
|
12
|
+
required?: boolean;
|
|
13
|
+
description?: string;
|
|
14
|
+
nameClass?: string;
|
|
15
|
+
typeInfoClass?: string;
|
|
16
|
+
containerClass?: string;
|
|
17
|
+
};
|
|
18
|
+
declare const RlDetailRow: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
19
|
+
type RlDetailRow = ReturnType<typeof RlDetailRow>;
|
|
20
|
+
export default RlDetailRow;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
<!-- src/lib/components/dataview/RLMetadataList.svelte -->
|
|
2
|
+
<script lang="ts">
|
|
3
|
+
import RLDetailRow from './RLDetailRow.svelte';
|
|
4
|
+
|
|
5
|
+
type DetailActionForList = { // Prop structure for items passed to RLDetailRow
|
|
6
|
+
text: string;
|
|
7
|
+
class?: string;
|
|
8
|
+
onClick?: (event: MouseEvent) => void;
|
|
9
|
+
title?: string;
|
|
10
|
+
isLink?: boolean;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export interface RLMetadataListItem {
|
|
14
|
+
name: string;
|
|
15
|
+
typeInfo?: string;
|
|
16
|
+
details?: DetailActionForList[];
|
|
17
|
+
required?: boolean;
|
|
18
|
+
description?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let {
|
|
22
|
+
title = undefined,
|
|
23
|
+
items = [],
|
|
24
|
+
listClass = 'divide-y divide-base-300/50',
|
|
25
|
+
emptyText = 'None.',
|
|
26
|
+
} = $props<{
|
|
27
|
+
title?: string;
|
|
28
|
+
items: RLMetadataListItem[];
|
|
29
|
+
listClass?: string;
|
|
30
|
+
emptyText?: string;
|
|
31
|
+
}>();
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<div>
|
|
35
|
+
{#if title}
|
|
36
|
+
<h4 class="font-semibold text-sm mb-1 mt-2 opacity-80">{title}</h4>
|
|
37
|
+
{/if}
|
|
38
|
+
{#if items.length > 0}
|
|
39
|
+
<div class="{listClass} border-t border-b border-base-300/30 -mx-1">
|
|
40
|
+
{#each items as item (item.name) }
|
|
41
|
+
<RLDetailRow
|
|
42
|
+
name={item.name}
|
|
43
|
+
typeInfo={item.typeInfo}
|
|
44
|
+
details={item.details}
|
|
45
|
+
required={item.required}
|
|
46
|
+
description={item.description}
|
|
47
|
+
/>
|
|
48
|
+
{/each}
|
|
49
|
+
</div>
|
|
50
|
+
{:else}
|
|
51
|
+
<p class="text-xs text-base-content/50 italic py-1.5 px-1">{emptyText}</p>
|
|
52
|
+
{/if}
|
|
53
|
+
</div>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
type DetailActionForList = {
|
|
2
|
+
text: string;
|
|
3
|
+
class?: string;
|
|
4
|
+
onClick?: (event: MouseEvent) => void;
|
|
5
|
+
title?: string;
|
|
6
|
+
isLink?: boolean;
|
|
7
|
+
};
|
|
8
|
+
export interface RLMetadataListItem {
|
|
9
|
+
name: string;
|
|
10
|
+
typeInfo?: string;
|
|
11
|
+
details?: DetailActionForList[];
|
|
12
|
+
required?: boolean;
|
|
13
|
+
description?: string;
|
|
14
|
+
}
|
|
15
|
+
type $$ComponentProps = {
|
|
16
|
+
title?: string;
|
|
17
|
+
items: RLMetadataListItem[];
|
|
18
|
+
listClass?: string;
|
|
19
|
+
emptyText?: string;
|
|
20
|
+
};
|
|
21
|
+
declare const RlMetadataList: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
22
|
+
type RlMetadataList = ReturnType<typeof RlMetadataList>;
|
|
23
|
+
export default RlMetadataList;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<!-- src/lib/components/explorer/RLEnumDisplay.svelte -->
|
|
2
|
+
<script lang="ts">
|
|
3
|
+
import type { RLEnumMetadata } from '../stores/explorer.svelte';
|
|
4
|
+
import RLMetadataList from '../dataview/RLMetadataList.svelte'; // Adjust path as needed
|
|
5
|
+
|
|
6
|
+
let {
|
|
7
|
+
enumData,
|
|
8
|
+
// Optional: if RLEnumDisplay should have its own modal button.
|
|
9
|
+
// Otherwise, RLSchemaExplorer can handle showing the modal if needed via context.
|
|
10
|
+
// For simplicity, let's assume any modal action is handled by the parent (RLSchemaExplorer).
|
|
11
|
+
} = $props<{
|
|
12
|
+
enumData: RLEnumMetadata;
|
|
13
|
+
}>();
|
|
14
|
+
|
|
15
|
+
let enumValueItems = $derived(
|
|
16
|
+
enumData.values.map((value: string) => ({
|
|
17
|
+
name: value,
|
|
18
|
+
}))
|
|
19
|
+
);
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<div class="py-2">
|
|
23
|
+
<RLMetadataList items={enumValueItems} title="Values" emptyText="No values defined for this enum." />
|
|
24
|
+
<!--
|
|
25
|
+
If RLSchemaExplorer needs a way to open its existing enum modal from here,
|
|
26
|
+
you could add a button and an on:click event that bubbles up or calls a prop function.
|
|
27
|
+
Example:
|
|
28
|
+
<div class="mt-2">
|
|
29
|
+
<button class="btn btn-xs btn-outline" on:click>
|
|
30
|
+
Show in Modal (if needed)
|
|
31
|
+
</button>
|
|
32
|
+
</div>
|
|
33
|
+
-->
|
|
34
|
+
</div>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { RLEnumMetadata } from '../stores/explorer.svelte';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
enumData: RLEnumMetadata;
|
|
4
|
+
};
|
|
5
|
+
declare const RlEnumDisplay: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
6
|
+
type RlEnumDisplay = ReturnType<typeof RlEnumDisplay>;
|
|
7
|
+
export default RlEnumDisplay;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<!-- src/lib/components/explorer/RLFunctionDisplay.svelte -->
|
|
2
|
+
<script lang="ts">
|
|
3
|
+
import type { RLApiInterfaceActionParams, RLFunctionMetadata, RLFunctionParameter } from '../stores/explorer.svelte';
|
|
4
|
+
|
|
5
|
+
import RLDetailRow from '../dataview/RLDetailRow.svelte';
|
|
6
|
+
import RLMetadataList from '../dataview/RLMetadataList.svelte';
|
|
7
|
+
import type { RLMetadataListItem } from '../dataview/RLMetadataList.svelte';
|
|
8
|
+
import RLApiInterface from '../api/RLApiInterface.svelte'; // For execution
|
|
9
|
+
|
|
10
|
+
let {
|
|
11
|
+
func,
|
|
12
|
+
onOpenApiModal, // Callback to RLSchemaExplorer
|
|
13
|
+
} = $props<{
|
|
14
|
+
func: RLFunctionMetadata;
|
|
15
|
+
onOpenApiModal: (params: RLApiInterfaceActionParams & { schemaName: string, resourceName: string, resourceType: 'function', options: any }) => void;
|
|
16
|
+
}>();
|
|
17
|
+
|
|
18
|
+
let parameterItems = $derived(
|
|
19
|
+
func.parameters.map((param: RLFunctionParameter): RLMetadataListItem => ({
|
|
20
|
+
name: param.name,
|
|
21
|
+
typeInfo: param.type + (param.defaultValue ? ` (default: ${param.defaultValue})` : ''),
|
|
22
|
+
required: !param.hasDefault && param.mode === 'IN', // Only IN params can be "required" in a form sense
|
|
23
|
+
details: [{ text: param.mode, class: `badge-${param.mode === 'IN' ? 'info' : param.mode === 'OUT' ? 'success' : 'warning'}` }],
|
|
24
|
+
}))
|
|
25
|
+
);
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
<div class="space-y-3 py-2">
|
|
29
|
+
{#if func.description}
|
|
30
|
+
<RLDetailRow name="Description" typeInfo={func.description} nameClass="font-semibold opacity-80" typeInfoClass="italic text-sm" />
|
|
31
|
+
{/if}
|
|
32
|
+
|
|
33
|
+
<RLDetailRow name="Kind" typeInfo={func.kind} nameClass="font-semibold opacity-80" />
|
|
34
|
+
<RLDetailRow name="Return Type" typeInfo={func.returnType || 'void'} nameClass="font-semibold opacity-80" />
|
|
35
|
+
<RLDetailRow name="Is Strict" typeInfo={func.isStrict ? 'Yes' : 'No'} nameClass="font-semibold opacity-80" />
|
|
36
|
+
|
|
37
|
+
{#if func.kind === 'TRIGGER' && func.triggerData}
|
|
38
|
+
<RLMetadataList title="Trigger Details" items={[
|
|
39
|
+
{ name: 'Timing', typeInfo: func.triggerData.timing },
|
|
40
|
+
{ name: 'Events', typeInfo: func.triggerData.events.join(', ') },
|
|
41
|
+
{ name: 'Target', typeInfo: `${func.triggerData.targetTableSchema}.${func.triggerData.targetTableName}` },
|
|
42
|
+
]} />
|
|
43
|
+
{/if}
|
|
44
|
+
|
|
45
|
+
<RLMetadataList items={parameterItems} title="Parameters" emptyText="No parameters." />
|
|
46
|
+
|
|
47
|
+
{#if (func.kind === 'FUNCTION' || func.kind === 'PROCEDURE') && onOpenApiModal}
|
|
48
|
+
<div class="mt-4 pt-3 border-t border-base-300/30">
|
|
49
|
+
<RLApiInterface
|
|
50
|
+
schemaName={func.schema}
|
|
51
|
+
resourceName={func.name}
|
|
52
|
+
resourceType={'function'}
|
|
53
|
+
columns={[]}
|
|
54
|
+
onOpenModal={(opParams) => onOpenApiModal({
|
|
55
|
+
...opParams,
|
|
56
|
+
schemaName: func.schema,
|
|
57
|
+
resourceName: func.name,
|
|
58
|
+
resourceType: 'function',
|
|
59
|
+
options: { functionParams: func.parameters } // Passing RLFunctionParameter[]
|
|
60
|
+
})}
|
|
61
|
+
/>
|
|
62
|
+
</div>
|
|
63
|
+
{/if}
|
|
64
|
+
</div>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { RLApiInterfaceActionParams, RLFunctionMetadata } from '../stores/explorer.svelte';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
func: RLFunctionMetadata;
|
|
4
|
+
onOpenApiModal: (params: RLApiInterfaceActionParams & {
|
|
5
|
+
schemaName: string;
|
|
6
|
+
resourceName: string;
|
|
7
|
+
resourceType: 'function';
|
|
8
|
+
options: any;
|
|
9
|
+
}) => void;
|
|
10
|
+
};
|
|
11
|
+
declare const RlFunctionDisplay: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
12
|
+
type RlFunctionDisplay = ReturnType<typeof RlFunctionDisplay>;
|
|
13
|
+
export default RlFunctionDisplay;
|