@standardbeagle/edit-db 0.3.229 → 0.4.327
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.txt +21 -0
- package/README.md +305 -0
- package/dist/common/schema.d.ts +1 -1
- package/dist/components/confirm-dialog.d.ts +14 -0
- package/dist/components/content-editor.d.ts +12 -0
- package/dist/components/content-panel.d.ts +18 -0
- package/dist/components/content-viewer.d.ts +7 -0
- package/dist/components/data-table-column-header.d.ts +8 -0
- package/dist/components/data-table-column-header.test.d.ts +0 -0
- package/dist/components/data-table.d.ts +71 -2
- package/dist/components/data-table.test.d.ts +0 -0
- package/dist/components/detail-panel.d.ts +10 -0
- package/dist/components/filters/boolean-filter.d.ts +6 -0
- package/dist/components/filters/date-filter.d.ts +6 -0
- package/dist/components/filters/fk-filter.d.ts +15 -0
- package/dist/components/filters/number-filter.d.ts +6 -0
- package/dist/components/filters/text-filter.d.ts +6 -0
- package/dist/components/fk-cell-popover.d.ts +14 -0
- package/dist/components/row-actions.d.ts +14 -0
- package/dist/components/table-dimensions.test.d.ts +1 -0
- package/dist/components/ui/button.d.ts +1 -1
- package/dist/components/ui/dialog.d.ts +12 -12
- package/dist/components/ui/hover-card.d.ts +6 -0
- package/dist/components/ui/input.d.ts +1 -1
- package/dist/components/ui/sheet.d.ts +14 -0
- package/dist/components/ui/table.d.ts +9 -2
- package/dist/data-data-table.d.ts +6 -1
- package/dist/data-edit.d.ts +14 -0
- package/dist/data-edit.test.d.ts +0 -0
- package/dist/data-panel.d.ts +11 -0
- package/dist/edit-db.css +1 -1
- package/dist/editor.d.ts +32 -0
- package/dist/editor.es.js +9501 -6510
- package/dist/editor.umd.cjs +55 -34
- package/dist/hooks/useColumnNav.d.ts +28 -0
- package/dist/hooks/useDataTable.d.ts +54 -3
- package/dist/hooks/useDeleteMutation.d.ts +10 -0
- package/dist/hooks/useDeleteMutation.test.d.ts +0 -0
- package/dist/hooks/useSchema.d.ts +25 -0
- package/dist/hooks/useTableStats.d.ts +76 -0
- package/dist/hooks/useTableStats.test.d.ts +1 -0
- package/dist/lib/composite-pk-roundtrip.test.d.ts +1 -0
- package/dist/lib/content-detect.d.ts +14 -0
- package/dist/lib/drill-stack.d.ts +52 -0
- package/dist/lib/drill-stack.test.d.ts +1 -0
- package/dist/lib/humanize.d.ts +5 -0
- package/dist/lib/pk-hygiene.test.d.ts +1 -0
- package/dist/lib/query-builder.d.ts +52 -0
- package/dist/lib/query-builder.test.d.ts +1 -0
- package/dist/lib/row-id.d.ts +14 -0
- package/dist/lib/row-id.test.d.ts +1 -0
- package/dist/tableList.d.ts +15 -0
- package/dist/tableList.test.d.ts +0 -0
- package/dist/types/schema.d.ts +88 -0
- package/package.json +21 -16
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { ColumnPanel } from '../data-panel';
|
|
3
|
+
interface ColumnNavEntry {
|
|
4
|
+
panel: ColumnPanel;
|
|
5
|
+
element: HTMLElement | null;
|
|
6
|
+
}
|
|
7
|
+
interface ColumnNavState {
|
|
8
|
+
mainTable: string | null;
|
|
9
|
+
columns: ColumnNavEntry[];
|
|
10
|
+
focusedIndex: number;
|
|
11
|
+
focusColumn: (index: number) => void;
|
|
12
|
+
closeColumn: (index: number) => void;
|
|
13
|
+
}
|
|
14
|
+
interface ColumnNavRegistration {
|
|
15
|
+
mainTable: string | null;
|
|
16
|
+
columns: ColumnPanel[];
|
|
17
|
+
columnRefs: Map<number, HTMLElement | null>;
|
|
18
|
+
onClose: (index: number) => void;
|
|
19
|
+
}
|
|
20
|
+
export declare function ColumnNavProvider({ children }: {
|
|
21
|
+
children: ReactNode;
|
|
22
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
export declare function useColumnNav(): ColumnNavState;
|
|
24
|
+
export declare function useColumnNavRegister(): {
|
|
25
|
+
register: (reg: ColumnNavRegistration) => void;
|
|
26
|
+
unregister: () => void;
|
|
27
|
+
};
|
|
28
|
+
export {};
|
|
@@ -1,21 +1,72 @@
|
|
|
1
1
|
import { Table } from '../types/schema';
|
|
2
|
-
import { ColumnDef, SortingState } from '@tanstack/react-table';
|
|
2
|
+
import { ColumnDef, ColumnFiltersState, SortingState } from '@tanstack/react-table';
|
|
3
|
+
import { ColumnPanel } from '../data-panel';
|
|
4
|
+
export { getFilterOperators } from '../lib/query-builder';
|
|
5
|
+
export type { ColumnFilterValue } from '../lib/query-builder';
|
|
3
6
|
interface RowData {
|
|
4
7
|
id?: number | string;
|
|
5
8
|
[key: string]: unknown;
|
|
6
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* Return type for the useDataTable hook.
|
|
12
|
+
* @interface UseDataTableResult
|
|
13
|
+
*/
|
|
7
14
|
interface UseDataTableResult {
|
|
15
|
+
/** Column definitions for the table */
|
|
8
16
|
columns: ColumnDef<RowData, unknown>[];
|
|
17
|
+
/** Current sorting state */
|
|
9
18
|
sorting: SortingState;
|
|
19
|
+
/** Active column filters */
|
|
20
|
+
columnFilters: ColumnFiltersState;
|
|
21
|
+
/** Primary-key column names in declaration order (empty when the table has no PK). */
|
|
22
|
+
primaryKeys: string[];
|
|
23
|
+
/** Current page index (0-based) */
|
|
10
24
|
pageIndex: number;
|
|
25
|
+
/** Number of rows per page */
|
|
11
26
|
pageSize: number;
|
|
27
|
+
/** Total number of pages */
|
|
12
28
|
pageCount: number;
|
|
29
|
+
/** Current page data rows */
|
|
13
30
|
rows: RowData[];
|
|
31
|
+
/** Whether data is currently loading */
|
|
14
32
|
loading: boolean;
|
|
33
|
+
/** Error object if the query failed */
|
|
15
34
|
error: Error | null;
|
|
35
|
+
/** Update sorting state */
|
|
16
36
|
onSortingChange: (sorting: SortingState) => void;
|
|
37
|
+
/** Update column filters */
|
|
38
|
+
onColumnFiltersChange: (filters: ColumnFiltersState) => void;
|
|
39
|
+
/** Update page index */
|
|
17
40
|
onPageIndexChange: (pageIndex: number) => void;
|
|
41
|
+
/** Update page size */
|
|
18
42
|
onPageSizeChange: (pageSize: number) => void;
|
|
19
43
|
}
|
|
20
|
-
|
|
21
|
-
|
|
44
|
+
/**
|
|
45
|
+
* Hook for managing data table state including sorting, filtering, and pagination.
|
|
46
|
+
*
|
|
47
|
+
* Automatically builds GraphQL queries based on table schema and current state,
|
|
48
|
+
* handles data fetching via React Query, and provides column definitions with
|
|
49
|
+
* proper rendering for foreign keys, dates, and content fields.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```tsx
|
|
53
|
+
* const {
|
|
54
|
+
* columns,
|
|
55
|
+
* rows,
|
|
56
|
+
* loading,
|
|
57
|
+
* pageIndex,
|
|
58
|
+
* pageCount,
|
|
59
|
+
* onSortingChange,
|
|
60
|
+
* onPageIndexChange,
|
|
61
|
+
* } = useDataTable(table, recordId, parentTable);
|
|
62
|
+
* ```
|
|
63
|
+
*
|
|
64
|
+
* @param table - Table schema definition
|
|
65
|
+
* @param id - Optional record ID for filtering to a specific row
|
|
66
|
+
* @param filterTable - Optional parent table name for relationship filtering
|
|
67
|
+
* @param filterColumn - Optional column name for explicit FK filtering
|
|
68
|
+
* @param onExpandContent - Callback when content expansion is requested
|
|
69
|
+
* @param onOpenColumn - Callback when opening a side panel column
|
|
70
|
+
* @returns Data table state and control functions
|
|
71
|
+
*/
|
|
72
|
+
export declare function useDataTable(table: Table | null, id?: string, filterTable?: string, filterColumn?: string, onExpandContent?: (rowIndex: number, columnName: string) => void, onOpenColumn?: (panel: ColumnPanel) => void): UseDataTableResult;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Table } from '../types/schema';
|
|
2
|
+
import { PkFilter } from '../lib/row-id';
|
|
3
|
+
export type DeleteInput = PkFilter | string | number;
|
|
4
|
+
export interface UseDeleteMutationResult {
|
|
5
|
+
deleteRow: (detail: DeleteInput) => Promise<unknown>;
|
|
6
|
+
deleteRows: (details: DeleteInput[]) => Promise<unknown>;
|
|
7
|
+
isPending: boolean;
|
|
8
|
+
error: Error | null;
|
|
9
|
+
}
|
|
10
|
+
export declare function useDeleteMutation(table: Table): UseDeleteMutationResult;
|
|
File without changes
|
|
@@ -1,6 +1,31 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
2
|
import { Schema } from '../types/schema';
|
|
3
|
+
/**
|
|
4
|
+
* Provider component for database schema context.
|
|
5
|
+
* Fetches schema via GraphQL and makes it available to child components.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```tsx
|
|
9
|
+
* <SchemaProvider>
|
|
10
|
+
* <YourApp />
|
|
11
|
+
* </SchemaProvider>
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
3
14
|
export declare const SchemaProvider: ({ children }: {
|
|
4
15
|
children: ReactNode;
|
|
5
16
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
/**
|
|
18
|
+
* Hook to access the database schema context.
|
|
19
|
+
*
|
|
20
|
+
* Returns schema loading state, error information, table definitions,
|
|
21
|
+
* and a utility function to find tables by name.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```tsx
|
|
25
|
+
* const { loading, error, data, findTable } = useSchema();
|
|
26
|
+
* const userTable = findTable('users');
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @returns Schema context value with tables and metadata
|
|
30
|
+
*/
|
|
6
31
|
export declare function useSchema(): Schema;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interface representing statistics for a single table.
|
|
3
|
+
* @interface TableStats
|
|
4
|
+
*/
|
|
5
|
+
export interface TableStats {
|
|
6
|
+
/** Number of columns in the table */
|
|
7
|
+
columnCount: number;
|
|
8
|
+
/** Number of rows in the table (null if loading/error) */
|
|
9
|
+
rowCount: number | null;
|
|
10
|
+
/** Number of foreign key relationships (singleJoins) */
|
|
11
|
+
fkCount: number;
|
|
12
|
+
/** Whether row count is currently loading */
|
|
13
|
+
isLoading: boolean;
|
|
14
|
+
/** Error message if row count fetch failed */
|
|
15
|
+
error: string | null;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Type for table stats record keyed by table name.
|
|
19
|
+
* @type TableStatsMap
|
|
20
|
+
*/
|
|
21
|
+
export type TableStatsMap = Record<string, TableStats>;
|
|
22
|
+
/**
|
|
23
|
+
* Result type for the useTableStats hook.
|
|
24
|
+
* @interface UseTableStatsResult
|
|
25
|
+
*/
|
|
26
|
+
export interface UseTableStatsResult {
|
|
27
|
+
/** Map of table names to their stats */
|
|
28
|
+
stats: TableStatsMap;
|
|
29
|
+
/** Whether any stats are loading */
|
|
30
|
+
isLoading: boolean;
|
|
31
|
+
/** Error if schema loading failed */
|
|
32
|
+
error: {
|
|
33
|
+
message: string;
|
|
34
|
+
} | null;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Hook to fetch table statistics including row counts.
|
|
38
|
+
*
|
|
39
|
+
* Automatically fetches row counts for all tables in the schema.
|
|
40
|
+
* Column counts and FK counts are derived from schema metadata (synchronous).
|
|
41
|
+
* Row counts are fetched via GraphQL (asynchronous).
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```tsx
|
|
45
|
+
* const { stats, isLoading } = useTableStats();
|
|
46
|
+
* const customerStats = stats['customers'];
|
|
47
|
+
* // customerStats = { columnCount: 12, rowCount: 1250, fkCount: 3, isLoading: false, error: null }
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* @returns Table statistics map and loading state
|
|
51
|
+
*/
|
|
52
|
+
export declare function useTableStats(): UseTableStatsResult;
|
|
53
|
+
/**
|
|
54
|
+
* Formats a number into an abbreviated string representation.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```typescript
|
|
58
|
+
* abbreviateNumber(12) // "12"
|
|
59
|
+
* abbreviateNumber(1200) // "1.2k"
|
|
60
|
+
* abbreviateNumber(45000) // "45k"
|
|
61
|
+
* abbreviateNumber(1200000) // "1.2M"
|
|
62
|
+
* ```
|
|
63
|
+
*
|
|
64
|
+
* @param num - Number to abbreviate
|
|
65
|
+
* @returns Abbreviated string representation
|
|
66
|
+
*/
|
|
67
|
+
export declare function abbreviateNumber(num: number | null): string;
|
|
68
|
+
/**
|
|
69
|
+
* Calculates a visual bar width (1-10) based on row count.
|
|
70
|
+
* Used for sparkline visualization.
|
|
71
|
+
*
|
|
72
|
+
* @param count - Row count
|
|
73
|
+
* @param maxCount - Maximum row count across all tables for scaling
|
|
74
|
+
* @returns Width value from 1-10
|
|
75
|
+
*/
|
|
76
|
+
export declare function calculateBarWidth(count: number | null, maxCount: number): number;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Detected content type for smart rendering */
|
|
2
|
+
export type ContentKind = 'json' | 'xml' | 'php-serialized' | 'binary' | 'longtext' | 'text';
|
|
3
|
+
/** Check if a dbType is a binary/blob type */
|
|
4
|
+
export declare function isBinaryDbType(dbType: string): boolean;
|
|
5
|
+
/** Check if a dbType is a long text type (text, ntext, varchar(max), xml) */
|
|
6
|
+
export declare function isLongTextDbType(dbType: string): boolean;
|
|
7
|
+
/** Detect content kind from a string value and optional dbType hint */
|
|
8
|
+
export declare function detectContentKind(value: string, dbType?: string): ContentKind;
|
|
9
|
+
/** Max characters to show in a table cell before truncating */
|
|
10
|
+
export declare const CELL_TRUNCATE = 80;
|
|
11
|
+
/** Truncate text for table cell display */
|
|
12
|
+
export declare function truncateForCell(value: string): string;
|
|
13
|
+
/** Format binary data (base64 string) for display */
|
|
14
|
+
export declare function formatBinaryPreview(value: string): string;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { ColumnPanel } from '../data-panel';
|
|
2
|
+
/**
|
|
3
|
+
* A single frame in the drill navigation chain, visible as one side column.
|
|
4
|
+
*/
|
|
5
|
+
export type DrillFrame = ColumnPanel;
|
|
6
|
+
/**
|
|
7
|
+
* Is `frame` the same drill target as `other` (same table + same filter)?
|
|
8
|
+
*
|
|
9
|
+
* Used for cycle detection — drilling the same (table, filterId, filterColumn)
|
|
10
|
+
* we already have on the stack is a no-op. Using strict equality on all four
|
|
11
|
+
* fields is safe because they are primitives.
|
|
12
|
+
*/
|
|
13
|
+
export declare function framesEqual(a: DrillFrame, b: DrillFrame): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Push `frame` onto `stack`, guarding against:
|
|
16
|
+
* 1. Exact duplicates of the top frame (no-op, returns `stack`).
|
|
17
|
+
* 2. Cycles — if `frame` already appears anywhere in the stack, truncate
|
|
18
|
+
* back to that frame instead of re-pushing. This produces the natural
|
|
19
|
+
* "breadcrumb jump" behaviour when a user drills back into an ancestor.
|
|
20
|
+
*
|
|
21
|
+
* Returns a new array; never mutates the input.
|
|
22
|
+
*/
|
|
23
|
+
export declare function pushDrillFrame(stack: DrillFrame[], frame: DrillFrame): DrillFrame[];
|
|
24
|
+
/**
|
|
25
|
+
* Pop entries from `stack` down to (and including) `index`.
|
|
26
|
+
* Popping index 0 yields an empty stack (all side columns closed); popping
|
|
27
|
+
* an out-of-range index is a no-op.
|
|
28
|
+
*/
|
|
29
|
+
export declare function popDrillFramesTo(stack: DrillFrame[], index: number): DrillFrame[];
|
|
30
|
+
/**
|
|
31
|
+
* A crumb displayed in the breadcrumb bar above the drill panels.
|
|
32
|
+
* `index = -1` represents the main (non-stack) view.
|
|
33
|
+
*/
|
|
34
|
+
export interface DrillCrumb {
|
|
35
|
+
/** -1 for the main view, 0+ for each side-column stack entry. */
|
|
36
|
+
index: number;
|
|
37
|
+
/** Display label — usually the table's human label. */
|
|
38
|
+
label: string;
|
|
39
|
+
/** Optional secondary label showing filter context (e.g. "from Customers #42"). */
|
|
40
|
+
detail?: string;
|
|
41
|
+
/** The underlying frame for index >= 0 (undefined for main view). */
|
|
42
|
+
frame?: DrillFrame;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Resolve table labels for a drill stack and produce breadcrumb entries.
|
|
46
|
+
*
|
|
47
|
+
* @param mainTable - GraphQL name of the root/main table
|
|
48
|
+
* @param stack - Current drill stack
|
|
49
|
+
* @param lookup - Function returning a human label for a given GraphQL table name,
|
|
50
|
+
* or `undefined` if not found (caller falls back to the raw name).
|
|
51
|
+
*/
|
|
52
|
+
export declare function buildDrillCrumbs(mainTable: string, stack: DrillFrame[], lookup: (tableName: string) => string | undefined): DrillCrumb[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Table, Schema } from '../types/schema';
|
|
2
|
+
import { ColumnFiltersState } from '@tanstack/react-table';
|
|
3
|
+
export interface FilterResult {
|
|
4
|
+
variables: Record<string, unknown>;
|
|
5
|
+
param: string;
|
|
6
|
+
filterText: string;
|
|
7
|
+
}
|
|
8
|
+
export interface ColumnFilterValue {
|
|
9
|
+
operator: string;
|
|
10
|
+
value: unknown;
|
|
11
|
+
}
|
|
12
|
+
export interface ColumnFilterResult {
|
|
13
|
+
variables: Record<string, unknown>;
|
|
14
|
+
params: string[];
|
|
15
|
+
filterTexts: string[];
|
|
16
|
+
}
|
|
17
|
+
export interface PkTypeInfo {
|
|
18
|
+
name: string;
|
|
19
|
+
gqlType: string;
|
|
20
|
+
}
|
|
21
|
+
interface RowData {
|
|
22
|
+
id?: number | string | null;
|
|
23
|
+
[key: string]: unknown;
|
|
24
|
+
}
|
|
25
|
+
export declare function getFilterOperators(paramType: string): string[];
|
|
26
|
+
export declare function getFilterObj(filterString: string): FilterResult;
|
|
27
|
+
export declare function toLocaleDate(d: string): string;
|
|
28
|
+
export declare function getRowPkValue(row: RowData, table: Table): string;
|
|
29
|
+
export declare function getGraphQlType(paramType: string): string;
|
|
30
|
+
export declare function buildColumnFilters(columnFilters: ColumnFiltersState, table: Table): ColumnFilterResult;
|
|
31
|
+
export declare function serializeColumnFilters(columnFilters: ColumnFiltersState): string;
|
|
32
|
+
export declare function deserializeColumnFilters(raw: string): ColumnFiltersState;
|
|
33
|
+
/**
|
|
34
|
+
* Returns the GraphQL type of the first PK column. For composite PKs use {@link getPkTypes}.
|
|
35
|
+
*/
|
|
36
|
+
export declare function getPkType(table: Table): string;
|
|
37
|
+
/**
|
|
38
|
+
* Returns one {name, gqlType} per primary-key column in declaration order.
|
|
39
|
+
* Empty array if the table has no primary keys.
|
|
40
|
+
*/
|
|
41
|
+
export declare function getPkTypes(table: Table): PkTypeInfo[];
|
|
42
|
+
/**
|
|
43
|
+
* Builds the variables dict that accompanies a buildQuery result for a single-record lookup.
|
|
44
|
+
* - Single PK: returns `{ id: <coerced value> }` matching the `$id` variable in the query.
|
|
45
|
+
* - Composite PK: returns `{ pk_${col1}: ..., pk_${col2}: ... }` matching the composite form.
|
|
46
|
+
*
|
|
47
|
+
* `idRoute` is the same string passed to buildQuery's `id` parameter — for composite PKs
|
|
48
|
+
* it is a route-encoded string produced by {@link encodePkRoute}.
|
|
49
|
+
*/
|
|
50
|
+
export declare function buildPkEqVariables(idRoute: string, table: Table): Record<string, unknown>;
|
|
51
|
+
export declare function buildQuery(table: Table, schema: Schema, filterString: string, columnFilters: ColumnFiltersState, id?: string, tableFilter?: string, filterColumn?: string): string | null;
|
|
52
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Table } from '../types/schema';
|
|
2
|
+
export type PkFilter = Record<string, unknown>;
|
|
3
|
+
export interface PkEqFilterResult {
|
|
4
|
+
filterText: string;
|
|
5
|
+
variables: Record<string, unknown>;
|
|
6
|
+
params: string[];
|
|
7
|
+
}
|
|
8
|
+
type TableLike = Pick<Table, 'primaryKeys'> & Partial<Pick<Table, 'columns'>>;
|
|
9
|
+
export declare function rowIdOf(row: Record<string, unknown> | null | undefined, table: TableLike, index: number): string;
|
|
10
|
+
export declare function pkFilterFor(row: Record<string, unknown> | null | undefined, table: TableLike): PkFilter | null;
|
|
11
|
+
export declare function buildPkEqFilter(row: Record<string, unknown> | null | undefined, table: Pick<Table, 'primaryKeys' | 'columns'>): PkEqFilterResult | null;
|
|
12
|
+
export declare function encodePkRoute(filter: PkFilter, table: TableLike): string;
|
|
13
|
+
export declare function parsePkRoute(raw: string, table: TableLike): PkFilter | null;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/tableList.d.ts
CHANGED
|
@@ -1 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TableList component that displays database tables in a sidebar.
|
|
3
|
+
*
|
|
4
|
+
* Features:
|
|
5
|
+
* - Lists all tables from the schema
|
|
6
|
+
* - Shows loading and error states
|
|
7
|
+
* - Displays table statistics (columns, rows, FKs) as sparklines
|
|
8
|
+
* - Responsive layout with visual hierarchy
|
|
9
|
+
*
|
|
10
|
+
* @component
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* <TableList />
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
1
16
|
export declare function TableList(): import("react/jsx-runtime").JSX.Element;
|
|
File without changes
|
package/dist/types/schema.d.ts
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module types/schema
|
|
3
|
+
*
|
|
4
|
+
* TypeScript type definitions for database schema metadata.
|
|
5
|
+
* These types represent the structure returned by the _dbSchema GraphQL query.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Metadata attached to tables for custom behavior configuration.
|
|
9
|
+
* @interface TableMetadata
|
|
10
|
+
*/
|
|
1
11
|
export interface TableMetadata {
|
|
12
|
+
/** Lookup configuration for reference tables */
|
|
2
13
|
type?: {
|
|
3
14
|
type: 'lookup';
|
|
4
15
|
id: string;
|
|
@@ -6,50 +17,127 @@ export interface TableMetadata {
|
|
|
6
17
|
};
|
|
7
18
|
[key: string]: any;
|
|
8
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Lookup table metadata defining ID and label columns.
|
|
22
|
+
* @interface LookupMetadata
|
|
23
|
+
*/
|
|
9
24
|
export interface LookupMetadata {
|
|
10
25
|
type: 'lookup';
|
|
11
26
|
id: string;
|
|
12
27
|
label: string;
|
|
13
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* Column-level metadata for custom configuration.
|
|
31
|
+
* @interface ColumnMetadata
|
|
32
|
+
*/
|
|
14
33
|
export interface ColumnMetadata {
|
|
15
34
|
[key: string]: string | LookupMetadata | undefined;
|
|
16
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Column definition from database schema introspection.
|
|
38
|
+
* @interface Column
|
|
39
|
+
*/
|
|
17
40
|
export interface Column {
|
|
41
|
+
/** Original database column name */
|
|
18
42
|
dbName: string;
|
|
43
|
+
/** GraphQL field name for the column */
|
|
19
44
|
graphQlName: string;
|
|
45
|
+
/** Alias for graphQlName */
|
|
20
46
|
name: string;
|
|
47
|
+
/** Human-readable label for the column */
|
|
21
48
|
label: string;
|
|
49
|
+
/** GraphQL parameter type (e.g., "String", "Int!") */
|
|
22
50
|
paramType: string;
|
|
51
|
+
/** Database-specific type (e.g., "nvarchar", "int") */
|
|
52
|
+
dbType: string;
|
|
53
|
+
/** Whether this column is part of the primary key */
|
|
23
54
|
isPrimaryKey: boolean;
|
|
55
|
+
/** Whether this column is auto-generated by the database */
|
|
24
56
|
isIdentity: boolean;
|
|
57
|
+
/** Whether this column allows NULL values */
|
|
25
58
|
isNullable: boolean;
|
|
59
|
+
/** Whether this column is read-only (e.g., computed columns) */
|
|
26
60
|
isReadOnly: boolean;
|
|
61
|
+
/** Custom metadata for the column */
|
|
27
62
|
metadata: ColumnMetadata;
|
|
63
|
+
/** Maximum string length (for validation) */
|
|
64
|
+
maxLength?: number;
|
|
65
|
+
/** Minimum string length (for validation) */
|
|
66
|
+
minLength?: number;
|
|
67
|
+
/** Minimum numeric value (for validation) */
|
|
68
|
+
min?: number;
|
|
69
|
+
/** Maximum numeric value (for validation) */
|
|
70
|
+
max?: number;
|
|
71
|
+
/** Step increment for numeric inputs */
|
|
72
|
+
step?: number;
|
|
73
|
+
/** Regex pattern for validation */
|
|
74
|
+
pattern?: string;
|
|
75
|
+
/** Error message for pattern validation failures */
|
|
76
|
+
patternMessage?: string;
|
|
77
|
+
/** HTML input type override */
|
|
78
|
+
inputType?: 'text' | 'email' | 'url' | 'tel' | 'date' | 'datetime-local' | 'number' | 'password' | 'search';
|
|
79
|
+
/** Default value for new records */
|
|
80
|
+
defaultValue?: string;
|
|
81
|
+
/** Allowed enum values */
|
|
82
|
+
enumValues?: string[];
|
|
83
|
+
/** Display labels for enum values */
|
|
84
|
+
enumLabels?: string[];
|
|
28
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* Relationship join definition between tables.
|
|
88
|
+
* @interface Join
|
|
89
|
+
*/
|
|
29
90
|
export interface Join {
|
|
91
|
+
/** Name of the join relationship */
|
|
30
92
|
name: string;
|
|
93
|
+
/** Column names in the source table */
|
|
31
94
|
sourceColumnNames: string[];
|
|
95
|
+
/** Target table name */
|
|
32
96
|
destinationTable: string;
|
|
97
|
+
/** Column names in the target table */
|
|
33
98
|
destinationColumnNames: string[];
|
|
34
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* Table definition from database schema introspection.
|
|
102
|
+
* @interface Table
|
|
103
|
+
*/
|
|
35
104
|
export interface Table {
|
|
105
|
+
/** Original database table name */
|
|
36
106
|
dbName: string;
|
|
107
|
+
/** GraphQL type name for the table */
|
|
37
108
|
graphQlName: string;
|
|
109
|
+
/** Alias for graphQlName */
|
|
38
110
|
name: string;
|
|
111
|
+
/** Human-readable label for the table */
|
|
39
112
|
label: string;
|
|
113
|
+
/** Column used as the display label for foreign key references */
|
|
40
114
|
labelColumn: string;
|
|
115
|
+
/** Primary key column names */
|
|
41
116
|
primaryKeys: string[];
|
|
117
|
+
/** Whether this table supports mutations */
|
|
42
118
|
isEditable: boolean;
|
|
119
|
+
/** Custom metadata for the table */
|
|
43
120
|
metadata: TableMetadata;
|
|
121
|
+
/** Column definitions */
|
|
44
122
|
columns: Column[];
|
|
123
|
+
/** One-to-many relationship joins */
|
|
45
124
|
multiJoins: Join[];
|
|
125
|
+
/** Many-to-one relationship joins */
|
|
46
126
|
singleJoins: Join[];
|
|
47
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* Schema context value containing database metadata and loading state.
|
|
130
|
+
* @interface Schema
|
|
131
|
+
*/
|
|
48
132
|
export interface Schema {
|
|
133
|
+
/** Whether schema data is currently loading */
|
|
49
134
|
loading: boolean;
|
|
135
|
+
/** Error object if schema loading failed, null otherwise */
|
|
50
136
|
error: {
|
|
51
137
|
message: string;
|
|
52
138
|
} | null;
|
|
139
|
+
/** Array of table definitions */
|
|
53
140
|
data: Table[];
|
|
141
|
+
/** Find a table by its GraphQL name */
|
|
54
142
|
findTable: (tableName: string) => Table | undefined;
|
|
55
143
|
}
|
package/package.json
CHANGED
|
@@ -1,17 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@standardbeagle/edit-db",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.4.327",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"dev": "vite",
|
|
8
|
-
"build": "tsc && vite build --mode production",
|
|
9
|
-
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
|
10
|
-
"preview": "vite preview",
|
|
11
|
-
"storybook": "storybook dev -p 6006",
|
|
12
|
-
"storybook-build": "storybook build",
|
|
13
|
-
"ts": "tsc"
|
|
14
|
-
},
|
|
15
6
|
"dependencies": {
|
|
16
7
|
"@radix-ui/react-slot": "^1.2.4",
|
|
17
8
|
"@tanstack/react-form": "^1.28.5",
|
|
@@ -35,6 +26,8 @@
|
|
|
35
26
|
"@storybook/react": "^10.2.7",
|
|
36
27
|
"@storybook/react-vite": "^10.2.7",
|
|
37
28
|
"@tailwindcss/vite": "^4.2.1",
|
|
29
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
30
|
+
"@testing-library/react": "^16.3.2",
|
|
38
31
|
"@types/react": "^18.3.28",
|
|
39
32
|
"@types/react-dom": "^18.3.7",
|
|
40
33
|
"@types/redux-actions": "^2.6.5",
|
|
@@ -47,14 +40,13 @@
|
|
|
47
40
|
"eslint": "^8.55.0",
|
|
48
41
|
"eslint-plugin-react-hooks": "^4.6.2",
|
|
49
42
|
"eslint-plugin-react-refresh": "^0.4.7",
|
|
50
|
-
"
|
|
43
|
+
"jsdom": "^25.0.1",
|
|
51
44
|
"storybook": "^10.2.7",
|
|
52
|
-
"stylelint": "^17.1.1",
|
|
53
45
|
"tailwindcss": "^4.2.1",
|
|
54
46
|
"typescript": "^5.9.3",
|
|
55
47
|
"vite": "^7.3.1",
|
|
56
|
-
"vite-plugin-
|
|
57
|
-
"
|
|
48
|
+
"vite-plugin-dts": "^4.5.4",
|
|
49
|
+
"vitest": "^3.2.4"
|
|
58
50
|
},
|
|
59
51
|
"peerDependencies": {
|
|
60
52
|
"@tanstack/react-query": "^5.0.0"
|
|
@@ -65,6 +57,7 @@
|
|
|
65
57
|
"main": "./dist/editor.umd.cjs",
|
|
66
58
|
"module": "./dist/editor.es.js",
|
|
67
59
|
"types": "./dist/index.d.ts",
|
|
60
|
+
"style": "./dist/edit-db.css",
|
|
68
61
|
"exports": {
|
|
69
62
|
".": {
|
|
70
63
|
"import": {
|
|
@@ -75,6 +68,18 @@
|
|
|
75
68
|
"types": "./dist/index.d.ts",
|
|
76
69
|
"default": "./dist/editor.umd.cjs"
|
|
77
70
|
}
|
|
78
|
-
}
|
|
71
|
+
},
|
|
72
|
+
"./style.css": "./dist/edit-db.css"
|
|
73
|
+
},
|
|
74
|
+
"scripts": {
|
|
75
|
+
"dev": "vite",
|
|
76
|
+
"build": "tsc && vite build --mode production",
|
|
77
|
+
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
|
78
|
+
"preview": "vite preview",
|
|
79
|
+
"storybook": "storybook dev -p 6006",
|
|
80
|
+
"storybook-build": "storybook build",
|
|
81
|
+
"ts": "tsc",
|
|
82
|
+
"test": "vitest run",
|
|
83
|
+
"test:watch": "vitest"
|
|
79
84
|
}
|
|
80
|
-
}
|
|
85
|
+
}
|