@standardbeagle/edit-db 0.4.478 → 0.4.494
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/common/fetcher.d.ts +7 -2
- package/dist/components/content-panel.d.ts +5 -2
- package/dist/components/filters/fk-filter.d.ts +2 -0
- package/dist/components/filters/fk-filter.test.d.ts +1 -0
- package/dist/components/filters/number-filter.d.ts +1 -0
- package/dist/components/filters/number-filter.test.d.ts +1 -0
- package/dist/components/filters/use-debounced-commit.d.ts +19 -0
- package/dist/components/filters/use-debounced-commit.test.d.ts +1 -0
- package/dist/components/fk-cell-popover.d.ts +8 -1
- package/dist/components/fk-cell-popover.test.d.ts +1 -0
- package/dist/data-data-table.test.d.ts +0 -0
- package/dist/data-edit.d.ts +8 -0
- package/dist/edit-db.css +1 -1
- package/dist/editor.es.js +5726 -15712
- package/dist/editor.umd.cjs +33 -69
- package/dist/hooks/useCompositeTableRef.d.ts +19 -1
- package/dist/hooks/useCompositeTableRef.test.d.ts +1 -0
- package/dist/hooks/useDataTable.d.ts +13 -1
- package/dist/hooks/usePath.d.ts +1 -5
- package/dist/hooks/useTableMutation.test.d.ts +0 -0
- package/dist/hooks/useTableRef.d.ts +22 -1
- package/dist/hooks/useTableRef.test.d.ts +1 -0
- package/dist/hooks/useTableStats.d.ts +7 -0
- package/dist/hooks/useToast.d.ts +15 -0
- package/dist/lib/content-detect.d.ts +5 -0
- package/dist/lib/date-input.d.ts +21 -0
- package/dist/lib/date-input.test.d.ts +1 -0
- package/dist/lib/fk.d.ts +10 -2
- package/dist/lib/invalidate.d.ts +7 -0
- package/dist/lib/invalidate.test.d.ts +1 -0
- package/dist/lib/label-match.d.ts +13 -0
- package/dist/lib/label-match.test.d.ts +1 -0
- package/dist/lib/m2m.d.ts +19 -5
- package/dist/lib/query-builder.d.ts +24 -2
- package/dist/lib/row-id.d.ts +9 -0
- package/dist/lib/table-ref.d.ts +45 -0
- package/dist/lib/table-ref.test.d.ts +1 -0
- package/dist/types/schema.d.ts +12 -6
- package/package.json +1 -3
- package/dist/error-panel.d.ts +0 -1
|
@@ -10,10 +10,28 @@ export interface CompositeTableRef {
|
|
|
10
10
|
loading: boolean;
|
|
11
11
|
error: unknown;
|
|
12
12
|
data: CompositeTableRefValue[];
|
|
13
|
+
/** True when `search` narrows server-side (String label column, `_contains`);
|
|
14
|
+
* false means the caller must filter the fetched window client-side. */
|
|
15
|
+
serverSearch: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface CompositeTableRefOptions {
|
|
18
|
+
/** Free-text search term. Applied server-side when the label column is String. */
|
|
19
|
+
search?: string;
|
|
20
|
+
/** Defer the list fetch until the dropdown is opened (fetch-on-open). */
|
|
21
|
+
enabled?: boolean;
|
|
22
|
+
/** The currently-selected destination-column values, so the selected parent row
|
|
23
|
+
* can be looked up and shown even when it falls outside the fetched window. */
|
|
24
|
+
currentValues?: Record<string, unknown> | null;
|
|
13
25
|
}
|
|
14
26
|
/**
|
|
15
27
|
* Fetch parent rows for a composite-FK Select widget. Returns one row per parent
|
|
16
28
|
* with its label plus every destination column value so the caller can write
|
|
17
29
|
* each composite-FK source column on the child form when a selection is made.
|
|
30
|
+
*
|
|
31
|
+
* Mirrors the single-column FK data source (table-ref.ts / useTableRef +
|
|
32
|
+
* useTableRefValue): the window is sorted by the label column (deterministic),
|
|
33
|
+
* narrowed server-side when a search term is given and the label is String-typed,
|
|
34
|
+
* and the currently-selected row is resolved via a single-row lookup when it lies
|
|
35
|
+
* outside the fetched window so it stays selectable instead of showing blank.
|
|
18
36
|
*/
|
|
19
|
-
export declare function useCompositeTableRef(schema: Schema, destTableName: string, destColumnNames: string[]): CompositeTableRef;
|
|
37
|
+
export declare function useCompositeTableRef(schema: Schema, destTableName: string, destColumnNames: string[], options?: CompositeTableRefOptions): CompositeTableRef;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -7,13 +7,25 @@ interface RowData {
|
|
|
7
7
|
id?: number | string;
|
|
8
8
|
[key: string]: unknown;
|
|
9
9
|
}
|
|
10
|
+
export declare function getJoinedRowPkValue(row: RowData | undefined, joinSchema: Table | undefined): string;
|
|
10
11
|
/**
|
|
11
12
|
* Clamp a page index into the valid [0, pageCount-1] range. Guards against a
|
|
12
13
|
* stale/out-of-range page (e.g. "page 2 of 1" after switching to a smaller
|
|
13
14
|
* table or when the row count shrinks).
|
|
14
15
|
*/
|
|
15
16
|
export declare function clampPageIndex(pageIndex: number, pageCount: number): number;
|
|
17
|
+
/**
|
|
18
|
+
* Reconcile in-memory column-filter state with the URL `cf` param, which is the
|
|
19
|
+
* source of truth. Returns `prev` unchanged when it already serializes to the
|
|
20
|
+
* same string as `cfParam` — this both preserves referential identity (no
|
|
21
|
+
* needless re-render) and stops the setState → syncFiltersToUrl → cfParam →
|
|
22
|
+
* effect cycle from looping on our own writes. Otherwise it deserializes the URL
|
|
23
|
+
* value so browser back/forward and table switches (which drop the query string)
|
|
24
|
+
* drive the filters instead of leaving stale state behind.
|
|
25
|
+
*/
|
|
26
|
+
export declare function reconcileColumnFiltersFromUrl(prev: ColumnFiltersState, cfParam: string): ColumnFiltersState;
|
|
16
27
|
export declare function getMultiJoinRows(row: RowData, join: Join): RowData[];
|
|
28
|
+
export declare function getMultiJoinTotal(row: RowData, join: Join): number;
|
|
17
29
|
/**
|
|
18
30
|
* Return type for the useDataTable hook.
|
|
19
31
|
* @interface UseDataTableResult
|
|
@@ -35,7 +47,7 @@ interface UseDataTableResult {
|
|
|
35
47
|
pageCount: number;
|
|
36
48
|
/** Current page data rows */
|
|
37
49
|
rows: RowData[];
|
|
38
|
-
/** Whether data is currently loading */
|
|
50
|
+
/** Whether data is currently loading (no rows to show yet) */
|
|
39
51
|
loading: boolean;
|
|
40
52
|
/** Error object if the query failed */
|
|
41
53
|
error: Error | null;
|
package/dist/hooks/usePath.d.ts
CHANGED
|
@@ -23,10 +23,6 @@ interface SearchParamsResult {
|
|
|
23
23
|
search: URLSearchParams;
|
|
24
24
|
hash: string;
|
|
25
25
|
}
|
|
26
|
-
interface RouteError {
|
|
27
|
-
message?: string;
|
|
28
|
-
status?: number;
|
|
29
|
-
}
|
|
30
26
|
interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
|
|
31
27
|
to: string;
|
|
32
28
|
children?: ReactNode;
|
|
@@ -41,7 +37,6 @@ export declare function useNavigate(): (url: string) => void;
|
|
|
41
37
|
export declare function useNavigation(): NavigationState;
|
|
42
38
|
export declare function useParams<T extends RouteParams = RouteParams>(): T;
|
|
43
39
|
export declare function useSearchParams(): SearchParamsResult;
|
|
44
|
-
export declare function useRouteError(): RouteError;
|
|
45
40
|
export declare function PathProvider({ path, children }: {
|
|
46
41
|
path: string;
|
|
47
42
|
children: ReactNode;
|
|
@@ -68,4 +63,5 @@ export declare function Route({ path, element }: {
|
|
|
68
63
|
path: string;
|
|
69
64
|
element: ReactElement;
|
|
70
65
|
}): ReactElement;
|
|
66
|
+
export declare const matchPath: (route: string, path: string) => PathMatch;
|
|
71
67
|
export {};
|
|
File without changes
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Schema } from '../types/schema';
|
|
2
|
-
export declare function useTableRef(schema: Schema, tableName: string, columnName: string): TableRef;
|
|
3
2
|
export interface TableRefValue {
|
|
4
3
|
key: string;
|
|
5
4
|
label: string;
|
|
@@ -8,4 +7,26 @@ export interface TableRef {
|
|
|
8
7
|
loading: boolean;
|
|
9
8
|
error: unknown;
|
|
10
9
|
data: TableRefValue[];
|
|
10
|
+
/** True when `search` narrows server-side (String label column, `_contains`);
|
|
11
|
+
* false means the caller must filter the fetched window client-side. */
|
|
12
|
+
serverSearch: boolean;
|
|
11
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Fetch the option rows for an FK dropdown (key + label per parent row).
|
|
16
|
+
* When `search` is non-empty and the parent's label column is String-typed the
|
|
17
|
+
* list is narrowed server-side, so parents beyond the fetch window stay
|
|
18
|
+
* findable; otherwise one window is fetched and the caller filters it.
|
|
19
|
+
*/
|
|
20
|
+
export declare function useTableRef(schema: Schema, tableName: string, columnName: string, search?: string, enabled?: boolean): TableRef;
|
|
21
|
+
export interface TableRefLookup {
|
|
22
|
+
loading: boolean;
|
|
23
|
+
error: unknown;
|
|
24
|
+
value: TableRefValue | null;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Resolve key + label for a single parent row by its key value. Used when the
|
|
28
|
+
* currently stored FK value falls outside the fetched dropdown window, so the
|
|
29
|
+
* Select can still display the stored value instead of a misleading
|
|
30
|
+
* placeholder. Pass `key` as null/'' to disable the lookup.
|
|
31
|
+
*/
|
|
32
|
+
export declare function useTableRefValue(schema: Schema, tableName: string, columnName: string, key: unknown): TableRefLookup;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -33,6 +33,13 @@ export interface UseTableStatsResult {
|
|
|
33
33
|
message: string;
|
|
34
34
|
} | null;
|
|
35
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Builds a GraphQL query to fetch row counts for all tables.
|
|
38
|
+
*
|
|
39
|
+
* @param tableNames - Array of table GraphQL names
|
|
40
|
+
* @returns GraphQL query string
|
|
41
|
+
*/
|
|
42
|
+
export declare function buildRowCountQuery(tableNames: string[]): string | null;
|
|
36
43
|
/**
|
|
37
44
|
* Hook to fetch table statistics including row counts.
|
|
38
45
|
*
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Minimal dependency-free toast system for transient success/error feedback
|
|
4
|
+
* after mutations (create, save, delete, inline content edits). Kept small and
|
|
5
|
+
* self-contained so the published editor pulls in no extra runtime dependency.
|
|
6
|
+
*/
|
|
7
|
+
export type ToastVariant = 'success' | 'error';
|
|
8
|
+
interface ToastApi {
|
|
9
|
+
toast: (message: string, variant?: ToastVariant) => void;
|
|
10
|
+
}
|
|
11
|
+
export declare function ToastProvider({ children }: {
|
|
12
|
+
children: ReactNode;
|
|
13
|
+
}): import("react").JSX.Element;
|
|
14
|
+
export declare function useToast(): ToastApi;
|
|
15
|
+
export {};
|
|
@@ -4,6 +4,11 @@ export type ContentKind = 'json' | 'xml' | 'php-serialized' | 'binary' | 'longte
|
|
|
4
4
|
export declare function isBinaryDbType(dbType: string): boolean;
|
|
5
5
|
/** Check if a dbType is a native JSON type (json, jsonb). */
|
|
6
6
|
export declare function isJsonDbType(dbType: string): boolean;
|
|
7
|
+
/** Column-level JSON check: native JSON dbType or the JSON GraphQL scalar. */
|
|
8
|
+
export declare function isJsonColumn(col: {
|
|
9
|
+
dbType: string;
|
|
10
|
+
paramType?: string;
|
|
11
|
+
}): boolean;
|
|
7
12
|
/** Check if a dbType is a long text type (text, ntext, varchar(max), xml) */
|
|
8
13
|
export declare function isLongTextDbType(dbType: string): boolean;
|
|
9
14
|
/** Detect content kind from a string value and optional dbType hint */
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Column } from '../types/schema';
|
|
2
|
+
/** True for any date-ish column (bare date or datetime). */
|
|
3
|
+
export declare function isDateColumn(column: Column): boolean;
|
|
4
|
+
/** True when a date-ish column carries a time-of-day component (datetime, not a bare date). */
|
|
5
|
+
export declare function isDateTimeColumn(column: Column): boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Normalizes a stored date/datetime string into the value an `<input type="date">`
|
|
8
|
+
* or `<input type="datetime-local">` expects. For datetime columns the time-of-day
|
|
9
|
+
* is preserved (fractional seconds and timezone offset are trimmed) so re-saving an
|
|
10
|
+
* unrelated field does not overwrite the time with midnight. Returns '' for the
|
|
11
|
+
* SQL "zero" date and unparseable input.
|
|
12
|
+
*/
|
|
13
|
+
export declare function toDateInputValue(raw: string | undefined, withTime: boolean): string;
|
|
14
|
+
/**
|
|
15
|
+
* Restore the original raw value for every date/datetime field the user did not
|
|
16
|
+
* edit. The form holds `toDateInputValue` projections; a field whose current form
|
|
17
|
+
* value still equals the projection of the original raw value is untouched, so
|
|
18
|
+
* the raw value (offset and fractional seconds intact) is sent instead of the
|
|
19
|
+
* lossy projection. Fields the user actually changed keep the new form value.
|
|
20
|
+
*/
|
|
21
|
+
export declare function preserveUntouchedDateValues(formValues: Record<string, unknown>, originalRow: Record<string, unknown>, columns: Column[]): Record<string, unknown>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/lib/fk.d.ts
CHANGED
|
@@ -1,13 +1,21 @@
|
|
|
1
|
-
import { Join, Table } from '../types/schema';
|
|
1
|
+
import { Column, Join, Table } from '../types/schema';
|
|
2
2
|
export interface FkEqFilterResult {
|
|
3
3
|
filterText: string;
|
|
4
4
|
variables: Record<string, unknown>;
|
|
5
5
|
params: string[];
|
|
6
6
|
}
|
|
7
|
+
/**
|
|
8
|
+
* Coerce a raw cell/route value to the JS type matching a GraphQL scalar so the
|
|
9
|
+
* variable payload agrees with its declared type (e.g. a Boolean FK is sent as
|
|
10
|
+
* `true`, not `"true"`). Unparseable numerics are passed through untouched so
|
|
11
|
+
* the server reports the real error instead of receiving `NaN`.
|
|
12
|
+
*/
|
|
13
|
+
export declare function coerceForGql(value: unknown, gqlType: string): unknown;
|
|
14
|
+
/** The base GraphQL scalar of a column (`paramType` minus non-null marker), defaulting to String. */
|
|
15
|
+
export declare function gqlTypeOf(column: Column | undefined): string;
|
|
7
16
|
export declare function isFkMember(join: Join, columnName: string): boolean;
|
|
8
17
|
export declare function isComposite(join: Join): boolean;
|
|
9
18
|
export declare function findJoinBySource(joins: Join[], columnName: string): Join | undefined;
|
|
10
|
-
export declare function findJoinByDestinationTable(joins: Join[], destinationTable: string): Join | undefined;
|
|
11
19
|
/**
|
|
12
20
|
* Build a `{_eq}`-per-column composite filter against the destination side of a join,
|
|
13
21
|
* using values pulled from a source-side row. Single-column joins emit a single
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { QueryClient } from '@tanstack/react-query';
|
|
2
|
+
/**
|
|
3
|
+
* Invalidate every query family that can serve rows affected by a write to
|
|
4
|
+
* `tableName`. Returns the refetch promise for callers that want to await it;
|
|
5
|
+
* queries are marked invalidated synchronously either way.
|
|
6
|
+
*/
|
|
7
|
+
export declare function invalidateAfterTableWrite(queryClient: QueryClient, tableName: string): Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module lib/label-match
|
|
3
|
+
*
|
|
4
|
+
* Client-side label filter shared by FK dropdowns (`ParentField`) and the
|
|
5
|
+
* many-to-many `TargetPicker` fallback. Used when the label column is not
|
|
6
|
+
* String-typed, so the server-side `_contains` search is unavailable and rows
|
|
7
|
+
* are filtered within the fetched window instead.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Case-insensitive substring match against a row's `label`, falling back to its
|
|
11
|
+
* id field (`idKey`) when no label was fetched.
|
|
12
|
+
*/
|
|
13
|
+
export declare function matchesLabel(row: object, idKey: string, term: string): boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/lib/m2m.d.ts
CHANGED
|
@@ -32,12 +32,19 @@ export declare function m2mRowsQuery(junction: Table, target: Table, m2m: ManyTo
|
|
|
32
32
|
export interface M2mTargetPickerPlan {
|
|
33
33
|
query: string;
|
|
34
34
|
idColumn: string;
|
|
35
|
+
/** True when the label column is String-typed and thus supports the
|
|
36
|
+
* server-side `_contains` search; callers fall back to client filtering. */
|
|
37
|
+
serverSearch: boolean;
|
|
35
38
|
}
|
|
36
39
|
/**
|
|
37
40
|
* Build the target-list query used when adding a many-to-many link.
|
|
38
41
|
* Sort values are BifrostQL enum literals, so they must not be quoted.
|
|
42
|
+
*
|
|
43
|
+
* When `search` is non-empty the list is filtered server-side (a `_contains` on
|
|
44
|
+
* the label column) so a large target table stays findable beyond the fetch
|
|
45
|
+
* limit, instead of searching only within a client-side window.
|
|
39
46
|
*/
|
|
40
|
-
export declare function m2mTargetPickerPlan(target: Table, m2m: ManyToManyJoin): M2mTargetPickerPlan;
|
|
47
|
+
export declare function m2mTargetPickerPlan(target: Table, m2m: ManyToManyJoin, search?: string): M2mTargetPickerPlan;
|
|
41
48
|
/**
|
|
42
49
|
* Read the target row's id and display label from a junction row's nested target
|
|
43
50
|
* selection (emitted by {@link m2mRowsQuery}). Returns null when the link has no
|
|
@@ -53,9 +60,16 @@ export declare function targetDisplay(junctionRow: Record<string, unknown>, m2m:
|
|
|
53
60
|
* the chosen target key on the junction target FK. Any payload columns are left
|
|
54
61
|
* unset so the database applies its defaults; the user edits them afterwards.
|
|
55
62
|
*
|
|
56
|
-
* Single-column junction FKs only. `parentId
|
|
57
|
-
*
|
|
58
|
-
* would be written verbatim into one column —
|
|
59
|
-
* than guess a decomposition, fail loudly until
|
|
63
|
+
* Single-column junction FKs only. `parentId` is a route-encoded string
|
|
64
|
+
* (produced by rowIdOf/encodePkRoute); for a composite FK it carries multiple
|
|
65
|
+
* values joined by "::", which would be written verbatim into one column —
|
|
66
|
+
* silent data corruption. Rather than guess a decomposition, fail loudly until
|
|
67
|
+
* composite-FK support is built.
|
|
68
|
+
*
|
|
69
|
+
* The parent value is percent-DECODED before being written: the read side
|
|
70
|
+
* (m2mRowsQuery) decodes the route id before filtering, so writing the encoded
|
|
71
|
+
* form (e.g. 'caf%C3%A9' for a 'café' key) would insert a dangling FK that the
|
|
72
|
+
* panel's filter never matches. `targetId` is NOT route-encoded — it comes raw
|
|
73
|
+
* from the picker row — so it is written as-is.
|
|
60
74
|
*/
|
|
61
75
|
export declare function attachJunctionDetail(m2m: ManyToManyJoin, parentId: string, targetId: string): Record<string, unknown>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { Table, Schema } from '../types/schema';
|
|
1
|
+
import { Table, Join, Schema } from '../types/schema';
|
|
2
2
|
import { ColumnFiltersState } from '@tanstack/react-table';
|
|
3
|
+
import { PkEqFilterResult } from './row-id';
|
|
3
4
|
export interface FilterResult {
|
|
4
5
|
variables: Record<string, unknown>;
|
|
5
6
|
param: string;
|
|
@@ -22,10 +23,12 @@ interface RowData {
|
|
|
22
23
|
id?: number | string | null;
|
|
23
24
|
[key: string]: unknown;
|
|
24
25
|
}
|
|
26
|
+
export declare function isGraphQlName(value: unknown): value is string;
|
|
27
|
+
export declare function assertGraphQlName(value: unknown, kind: string): asserts value is string;
|
|
25
28
|
export declare function getFilterOperators(paramType: string): string[];
|
|
26
29
|
export declare function getFilterObj(filterString: string): FilterResult;
|
|
27
30
|
export declare function toLocaleDate(d: string): string;
|
|
28
|
-
export declare function getRowPkValue(row: RowData, table: Table): string;
|
|
31
|
+
export declare function getRowPkValue(row: RowData, table: Table, index?: number): string;
|
|
29
32
|
export declare function getGraphQlType(paramType: string): string;
|
|
30
33
|
export declare function buildColumnFilters(columnFilters: ColumnFiltersState, table: Table): ColumnFilterResult;
|
|
31
34
|
export declare function serializeColumnFilters(columnFilters: ColumnFiltersState): string;
|
|
@@ -48,13 +51,32 @@ export declare function getPkTypes(table: Table): PkTypeInfo[];
|
|
|
48
51
|
* it is a route-encoded string produced by {@link encodePkRoute}.
|
|
49
52
|
*/
|
|
50
53
|
export declare function buildPkEqVariables(idRoute: string, table: Table): Record<string, unknown>;
|
|
54
|
+
/**
|
|
55
|
+
* Builds a single-row lookup query keyed by a primary-key equality filter
|
|
56
|
+
* (produced by {@link buildPkEqFilter}). The row comes back under the `value`
|
|
57
|
+
* alias: `{ value: { data: [row] } }`. Used by the content panel to re-read a
|
|
58
|
+
* row fresh before echoing it back in an update.
|
|
59
|
+
*/
|
|
60
|
+
export declare function buildSingleRowQuery(table: Pick<Table, 'name'>, pkEq: Pick<PkEqFilterResult, 'filterText' | 'params'>, fields: readonly string[]): string;
|
|
51
61
|
export declare function buildQuery(table: Table, schema: Schema, filterString: string, columnFilters: ColumnFiltersState, id?: string, tableFilter?: string, filterColumn?: string): string | null;
|
|
52
62
|
export interface DrillDownTarget {
|
|
53
63
|
/** The parent table whose row owns the child collection. */
|
|
54
64
|
parentTable: Table;
|
|
55
65
|
/** The child collection field name on the parent type. */
|
|
56
66
|
childField: string;
|
|
67
|
+
/** The parent multi-join that owns the child collection. Lets callers
|
|
68
|
+
* decide whether the drill can use a flat FK filter (simple single-column
|
|
69
|
+
* FK) or must keep the MODEL B parent traversal (composite/polymorphic). */
|
|
70
|
+
childJoin: Join;
|
|
57
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* A drill can render as a flat root-filtered child grid — `childTable(filter:
|
|
74
|
+
* { fk: { _eq: $id } })`, i.e. a "parent grid with a filter applied" — only for
|
|
75
|
+
* a simple single-column, non-polymorphic FK. Composite FKs have no single
|
|
76
|
+
* filter column and polymorphic links need the server-injected discriminator;
|
|
77
|
+
* both must keep MODEL B's parent traversal.
|
|
78
|
+
*/
|
|
79
|
+
export declare function canFlatFilterDrill(childJoin: Join): boolean;
|
|
58
80
|
/**
|
|
59
81
|
* Resolve the parent table + child collection field for a parent→child
|
|
60
82
|
* related-records drill-down. The child is `table`; the parent is `tableFilter`
|
package/dist/lib/row-id.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export interface PkEqFilterResult {
|
|
|
6
6
|
params: string[];
|
|
7
7
|
}
|
|
8
8
|
type TableLike = Pick<Table, 'primaryKeys'> & Partial<Pick<Table, 'columns'>>;
|
|
9
|
+
export declare function decodePkPart(raw: string): string | null;
|
|
9
10
|
/**
|
|
10
11
|
* Encodes an ordered list of key values into a route string. The single source
|
|
11
12
|
* of truth for composite-key route encoding — every producer (row lists) and
|
|
@@ -13,6 +14,14 @@ type TableLike = Pick<Table, 'primaryKeys'> & Partial<Pick<Table, 'columns'>>;
|
|
|
13
14
|
* never drift apart and silently fail to match.
|
|
14
15
|
*/
|
|
15
16
|
export declare function encodeRouteParts(values: readonly unknown[]): string;
|
|
17
|
+
/**
|
|
18
|
+
* Inverse of {@link encodeRouteParts}: splits a route-encoded id into its ordered
|
|
19
|
+
* values and percent-decodes each. `expectedCount <= 1` treats the whole string as a
|
|
20
|
+
* single value (never split, so a value that itself contains the delimiter survives).
|
|
21
|
+
* Throws when a multi-part id does not carry exactly `expectedCount` parts, so a caller
|
|
22
|
+
* building a composite filter cannot silently under-constrain it.
|
|
23
|
+
*/
|
|
24
|
+
export declare function decodeRouteParts(raw: string, expectedCount: number): string[];
|
|
16
25
|
export declare function rowIdOf(row: Record<string, unknown> | null | undefined, table: TableLike, index: number): string;
|
|
17
26
|
export declare function pkFilterFor(row: Record<string, unknown> | null | undefined, table: TableLike): PkFilter | null;
|
|
18
27
|
export declare function buildPkEqFilter(row: Record<string, unknown> | null | undefined, table: Pick<Table, 'primaryKeys' | 'columns'>): PkEqFilterResult | null;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Table } from '../types/schema';
|
|
2
|
+
export declare const TABLE_REF_LIMIT = 1000;
|
|
3
|
+
export declare const TABLE_REF_SEARCH_LIMIT = 50;
|
|
4
|
+
/**
|
|
5
|
+
* The column used as the display label for a table's FK dropdown rows.
|
|
6
|
+
* Falls back to schema-derived names only — never a guessed literal like `id`,
|
|
7
|
+
* which is a server error on tables without such a column: first primary-key
|
|
8
|
+
* column, then the first column. (Taking the first PK column here is a label
|
|
9
|
+
* fallback for display, not a composite-key shortcut — one column is all a
|
|
10
|
+
* label can show.) `||` (not `??`) so an empty-string labelColumn falls
|
|
11
|
+
* through instead of emitting `label: ` (a GraphQL syntax error).
|
|
12
|
+
*/
|
|
13
|
+
export declare function refLabelColumn(table: Table): string;
|
|
14
|
+
export interface TableRefPlan {
|
|
15
|
+
query: string;
|
|
16
|
+
labelColumn: string;
|
|
17
|
+
/** True when the label column is String-typed and thus supports the
|
|
18
|
+
* server-side `_contains` search; callers fall back to client filtering. */
|
|
19
|
+
serverSearch: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Build the FK-dropdown list query. Sorted by the label column so the fetched
|
|
23
|
+
* window is deterministic. When `search` is non-empty and the label column is
|
|
24
|
+
* String-typed, the list is narrowed server-side (`_contains` on the label
|
|
25
|
+
* column) so parents beyond the fetch limit stay findable; otherwise the caller
|
|
26
|
+
* filters client-side over the fetched window.
|
|
27
|
+
*/
|
|
28
|
+
export declare function tableRefPlan(table: Table, keyColumn: string, search?: string): TableRefPlan;
|
|
29
|
+
export interface TableRefLookupPlan {
|
|
30
|
+
query: string;
|
|
31
|
+
/** GraphQL type of the key column (non-null suffix stripped), for coercion. */
|
|
32
|
+
keyType: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Build the single-row lookup that resolves the label of the currently stored
|
|
36
|
+
* FK value when it falls outside the fetched dropdown window, so the Select can
|
|
37
|
+
* display it instead of a misleading placeholder.
|
|
38
|
+
*/
|
|
39
|
+
export declare function tableRefLookupPlan(table: Table, keyColumn: string): TableRefLookupPlan;
|
|
40
|
+
/**
|
|
41
|
+
* Coerce a stored/route FK value to what the lookup's `$key` variable expects.
|
|
42
|
+
* Delegates to the shared coerceForGql so BigInt keys stay strings (Number()
|
|
43
|
+
* loses precision past 2^53) and Boolean keys stay booleans.
|
|
44
|
+
*/
|
|
45
|
+
export declare function coerceKeyValue(keyType: string, value: unknown): unknown;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/types/schema.d.ts
CHANGED
|
@@ -10,12 +10,9 @@
|
|
|
10
10
|
*/
|
|
11
11
|
export interface TableMetadata {
|
|
12
12
|
/** Lookup configuration for reference tables */
|
|
13
|
-
type?:
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
label: string;
|
|
17
|
-
};
|
|
18
|
-
[key: string]: any;
|
|
13
|
+
type?: LookupMetadata;
|
|
14
|
+
/** Other free-form metadata entries keyed by metadata name (parsed from key/value pairs). */
|
|
15
|
+
[key: string]: string | LookupMetadata | undefined;
|
|
19
16
|
}
|
|
20
17
|
/**
|
|
21
18
|
* Lookup table metadata defining ID and label columns.
|
|
@@ -98,6 +95,15 @@ export interface Join {
|
|
|
98
95
|
destinationTable: string;
|
|
99
96
|
/** Column names in the target table */
|
|
100
97
|
destinationColumnNames: string[];
|
|
98
|
+
/** True for a polymorphic child link — the relation carries a server-side
|
|
99
|
+
* discriminator predicate (entity_type) rather than a plain FK. Such drills
|
|
100
|
+
* must keep the MODEL B parent traversal so the server injects the
|
|
101
|
+
* discriminator; a flat FK filter would leak sibling-type rows. */
|
|
102
|
+
isPolymorphic?: boolean;
|
|
103
|
+
/** Discriminator column backing a polymorphic link (when isPolymorphic). */
|
|
104
|
+
polymorphicTypeColumn?: string;
|
|
105
|
+
/** Discriminator value backing a polymorphic link (when isPolymorphic). */
|
|
106
|
+
polymorphicTypeValue?: string;
|
|
101
107
|
}
|
|
102
108
|
/**
|
|
103
109
|
* Many-to-many bridge between this entity and a target entity through a
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@standardbeagle/edit-db",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.4.
|
|
4
|
+
"version": "0.4.494",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"@radix-ui/react-slot": "^1.2.4",
|
|
@@ -14,7 +14,6 @@
|
|
|
14
14
|
"radix-ui": "^1.4.3",
|
|
15
15
|
"react": "^18.3.1",
|
|
16
16
|
"react-dom": "^18.3.1",
|
|
17
|
-
"redux-actions": "^3.0.3",
|
|
18
17
|
"tailwind-merge": "^3.6.0"
|
|
19
18
|
},
|
|
20
19
|
"devDependencies": {
|
|
@@ -27,7 +26,6 @@
|
|
|
27
26
|
"@testing-library/react": "^16.3.2",
|
|
28
27
|
"@types/react": "^18.3.29",
|
|
29
28
|
"@types/react-dom": "^18.3.7",
|
|
30
|
-
"@types/redux-actions": "^2.6.5",
|
|
31
29
|
"@typescript-eslint/eslint-plugin": "^7.18.0",
|
|
32
30
|
"@typescript-eslint/parser": "^7.18.0",
|
|
33
31
|
"@vitejs/plugin-react-swc": "^4.3.1",
|
package/dist/error-panel.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export default function ErrorPage(): import("react").JSX.Element;
|