@rebasepro/studio 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +73 -140
- package/dist/{JSEditor-Br4ke-J4.js → JSEditor-DfwRLBZg.js} +2 -15
- package/dist/JSEditor-DfwRLBZg.js.map +1 -0
- package/dist/RLSEditor-CHEExeSB.js.map +1 -1
- package/dist/{SQLEditor-BC0IOUQu.js → SQLEditor-CQXaI0iU.js} +2 -2
- package/dist/SQLEditor-CQXaI0iU.js.map +1 -0
- package/dist/SchemaVisualizer-BGpmzyXT.js.map +1 -1
- package/dist/common/src/collections/default-collections.d.ts +5 -8
- package/dist/common/src/data/query_builder.d.ts +6 -2
- package/dist/common/src/util/permissions.d.ts +14 -6
- package/dist/core/src/components/LoginView/LoginView.d.ts +9 -1
- package/dist/core/src/components/common/types.d.ts +3 -3
- package/dist/core/src/hooks/data/useCollectionFetch.d.ts +12 -1
- package/dist/index.es.js +2 -2
- package/dist/index.umd.js +2 -15
- package/dist/index.umd.js.map +1 -1
- package/dist/studio/src/components/RLSEditor/RLSEditor.d.ts +0 -6
- package/dist/studio/src/components/SchemaVisualizer/schema-visualizer.utils.d.ts +0 -8
- package/dist/studio/src/utils/pgColumnToProperty.d.ts +1 -1
- package/dist/types/src/controllers/auth.d.ts +2 -2
- package/dist/types/src/controllers/client.d.ts +25 -40
- package/dist/types/src/controllers/data.d.ts +21 -3
- package/dist/types/src/controllers/data_driver.d.ts +5 -0
- package/dist/types/src/controllers/email.d.ts +2 -0
- package/dist/types/src/types/auth_adapter.d.ts +3 -56
- package/dist/types/src/types/backend.d.ts +38 -3
- package/dist/types/src/types/backend_hooks.d.ts +2 -17
- package/dist/types/src/types/collections.d.ts +30 -6
- package/dist/types/src/types/entity_views.d.ts +19 -28
- package/dist/types/src/types/properties.d.ts +9 -15
- package/dist/types/src/types/user_management_delegate.d.ts +16 -53
- package/dist/types/src/users/index.d.ts +0 -1
- package/dist/types/src/users/user.d.ts +0 -1
- package/dist/ui/src/components/Card.d.ts +2 -3
- package/dist/ui/src/components/FilterChip.d.ts +2 -10
- package/dist/ui/src/components/VirtualTable/VirtualTableProps.d.ts +8 -2
- package/package.json +8 -8
- package/src/components/JSEditor/JSEditor.tsx +1 -1
- package/src/components/JSEditor/JSMonacoEditor.tsx +0 -13
- package/src/components/RLSEditor/RLSEditor.tsx +1 -1
- package/src/components/SchemaVisualizer/schema-visualizer.utils.ts +3 -3
- package/src/components/SchemaVisualizer/useSchemaGraph.ts +2 -2
- package/src/utils/pgColumnToProperty.test.ts +1 -0
- package/src/utils/pgColumnToProperty.ts +42 -22
- package/src/utils/sql_utils.ts +1 -1
- package/dist/JSEditor-Br4ke-J4.js.map +0 -1
- package/dist/SQLEditor-BC0IOUQu.js.map +0 -1
- package/dist/studio/src/components/SchemaVisualizer/index.d.ts +0 -5
- package/dist/studio/src/utils/entities.d.ts +0 -0
- package/dist/types/src/users/roles.d.ts +0 -14
- package/src/components/SchemaVisualizer/index.ts +0 -5
- package/src/utils/entities.ts +0 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { User } from "../users";
|
|
2
2
|
/**
|
|
3
3
|
* Result of creating a new user via admin flow.
|
|
4
4
|
* Contains the created user plus information about how credentials were delivered.
|
|
@@ -15,56 +15,46 @@ export interface UserCreationResult<USER extends User = User> {
|
|
|
15
15
|
temporaryPassword?: string;
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
18
|
-
* Delegate to manage
|
|
19
|
-
*
|
|
20
|
-
*
|
|
18
|
+
* Delegate to manage auth-specific user operations.
|
|
19
|
+
*
|
|
20
|
+
* This interface allows the CMS to be agnostic of the underlying
|
|
21
|
+
* authentication provider or backend. User/role CRUD is now handled
|
|
22
|
+
* by the collection system; this delegate only exposes auth-specific
|
|
23
|
+
* operations (password hashing, invitations, bootstrap).
|
|
21
24
|
*
|
|
22
25
|
* @group Models
|
|
23
26
|
*/
|
|
24
27
|
export interface UserManagementDelegate<USER extends User = User> {
|
|
25
28
|
/**
|
|
26
|
-
* Are
|
|
29
|
+
* Are auth-related operations currently loading?
|
|
27
30
|
*/
|
|
28
31
|
loading: boolean;
|
|
29
32
|
/**
|
|
30
|
-
*
|
|
33
|
+
* In-memory list of users (used for client-side filtering fallback).
|
|
31
34
|
*/
|
|
32
|
-
users
|
|
35
|
+
users?: USER[];
|
|
33
36
|
/**
|
|
34
|
-
*
|
|
37
|
+
* Error from fetching the users list, if any.
|
|
35
38
|
*/
|
|
36
39
|
usersError?: Error;
|
|
37
40
|
/**
|
|
38
|
-
*
|
|
39
|
-
* user information when assigning ownership of an entity.
|
|
40
|
-
* @param uid
|
|
41
|
+
* Look up a single user by UID from the in-memory cache.
|
|
41
42
|
*/
|
|
42
|
-
getUser
|
|
43
|
+
getUser?: (uid: string) => USER | null;
|
|
43
44
|
/**
|
|
44
|
-
*
|
|
45
|
-
* When provided, the CMS will use this for the users table
|
|
46
|
-
* instead of loading all users into memory.
|
|
45
|
+
* Server-side user search with pagination.
|
|
47
46
|
*/
|
|
48
|
-
searchUsers?: (
|
|
47
|
+
searchUsers?: (params: {
|
|
49
48
|
search?: string;
|
|
50
49
|
limit?: number;
|
|
51
50
|
offset?: number;
|
|
52
|
-
orderBy?: string;
|
|
53
|
-
orderDir?: "asc" | "desc";
|
|
54
|
-
roleId?: string;
|
|
55
51
|
}) => Promise<{
|
|
56
52
|
users: USER[];
|
|
57
53
|
total: number;
|
|
58
54
|
}>;
|
|
59
|
-
/**
|
|
60
|
-
* Save a user (create or update)
|
|
61
|
-
* @param user
|
|
62
|
-
*/
|
|
63
|
-
saveUser?: (user: USER) => Promise<USER>;
|
|
64
55
|
/**
|
|
65
56
|
* Create a new user with invitation/password generation support.
|
|
66
57
|
* Returns additional info about how the credentials were delivered.
|
|
67
|
-
* Falls back to saveUser if not provided.
|
|
68
58
|
*/
|
|
69
59
|
createUser?: (user: USER) => Promise<UserCreationResult<USER>>;
|
|
70
60
|
/**
|
|
@@ -73,42 +63,15 @@ export interface UserManagementDelegate<USER extends User = User> {
|
|
|
73
63
|
* or a flag indicating an email invitation was sent.
|
|
74
64
|
*/
|
|
75
65
|
resetPassword?: (user: USER) => Promise<UserCreationResult<USER>>;
|
|
76
|
-
/**
|
|
77
|
-
* Delete a user
|
|
78
|
-
* @param user
|
|
79
|
-
*/
|
|
80
|
-
deleteUser?: (user: USER) => Promise<void>;
|
|
81
|
-
/**
|
|
82
|
-
* List of roles defined in the CMS.
|
|
83
|
-
*/
|
|
84
|
-
roles?: Role[];
|
|
85
|
-
/**
|
|
86
|
-
* Optional error if roles failed to load.
|
|
87
|
-
*/
|
|
88
|
-
rolesError?: Error;
|
|
89
|
-
/**
|
|
90
|
-
* Save a role (create or update)
|
|
91
|
-
* @param role
|
|
92
|
-
*/
|
|
93
|
-
saveRole?: (role: Role) => Promise<void>;
|
|
94
|
-
/**
|
|
95
|
-
* Delete a role
|
|
96
|
-
* @param role
|
|
97
|
-
*/
|
|
98
|
-
deleteRole?: (role: Role) => Promise<void>;
|
|
99
66
|
/**
|
|
100
67
|
* Is the currently logged in user an admin?
|
|
101
68
|
*/
|
|
102
69
|
isAdmin?: boolean;
|
|
103
|
-
/**
|
|
104
|
-
* If true, the UI will allow the user to create the default roles (admin, editor, viewer).
|
|
105
|
-
*/
|
|
106
|
-
allowDefaultRolesCreation?: boolean;
|
|
107
70
|
/**
|
|
108
71
|
* Optionally define roles for a given user. This is useful when the roles
|
|
109
72
|
* are coming from a separate provider than the one issuing the tokens.
|
|
110
73
|
*/
|
|
111
|
-
defineRolesFor?: (user: USER) => Promise<
|
|
74
|
+
defineRolesFor?: (user: USER) => Promise<string[] | undefined> | string[] | undefined;
|
|
112
75
|
/**
|
|
113
76
|
* Whether any admin users exist. Used by the bootstrap banner to decide
|
|
114
77
|
* whether to prompt. Populated via a lightweight check (e.g. `limit=1`
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
|
|
2
|
+
declare const Card: React.ForwardRefExoticComponent<{
|
|
3
3
|
children: React.ReactNode;
|
|
4
4
|
style?: React.CSSProperties;
|
|
5
5
|
onClick?: (e?: React.MouseEvent) => void;
|
|
6
6
|
className?: string;
|
|
7
|
-
}
|
|
8
|
-
declare const Card: React.ForwardRefExoticComponent<CardProps & React.RefAttributes<HTMLDivElement>>;
|
|
7
|
+
} & React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
|
|
9
8
|
export { Card };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
export interface FilterChipProps {
|
|
2
|
+
export interface FilterChipProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "children"> {
|
|
3
3
|
/**
|
|
4
4
|
* The text label displayed on the chip.
|
|
5
5
|
*/
|
|
@@ -8,10 +8,6 @@ export interface FilterChipProps {
|
|
|
8
8
|
* Whether the chip is currently in an active/selected state.
|
|
9
9
|
*/
|
|
10
10
|
active?: boolean;
|
|
11
|
-
/**
|
|
12
|
-
* Callback when the chip is clicked.
|
|
13
|
-
*/
|
|
14
|
-
onClick?: () => void;
|
|
15
11
|
/**
|
|
16
12
|
* Optional icon rendered before the label.
|
|
17
13
|
*/
|
|
@@ -21,10 +17,6 @@ export interface FilterChipProps {
|
|
|
21
17
|
* @default "medium"
|
|
22
18
|
*/
|
|
23
19
|
size?: "small" | "medium";
|
|
24
|
-
/**
|
|
25
|
-
* Additional class names.
|
|
26
|
-
*/
|
|
27
|
-
className?: string;
|
|
28
20
|
/**
|
|
29
21
|
* Whether the chip is disabled.
|
|
30
22
|
*/
|
|
@@ -39,4 +31,4 @@ export interface FilterChipProps {
|
|
|
39
31
|
*
|
|
40
32
|
* @group Interactive components
|
|
41
33
|
*/
|
|
42
|
-
export declare
|
|
34
|
+
export declare const FilterChip: React.ForwardRefExoticComponent<FilterChipProps & React.RefAttributes<HTMLButtonElement>>;
|
|
@@ -224,6 +224,12 @@ export type OnVirtualTableColumnResizeParams = {
|
|
|
224
224
|
key: string;
|
|
225
225
|
column: VirtualTableColumn;
|
|
226
226
|
};
|
|
227
|
+
/**
|
|
228
|
+
* @see Table
|
|
229
|
+
* @group Components
|
|
230
|
+
*/
|
|
231
|
+
export type WhereFilterOp = "<" | "<=" | "==" | "!=" | ">=" | ">" | "array-contains" | "in" | "not-in" | "array-contains-any";
|
|
232
|
+
export type FilterValues<Key extends string> = Partial<Record<Key, [WhereFilterOp, unknown] | [WhereFilterOp, unknown][]>>;
|
|
227
233
|
/**
|
|
228
234
|
* @see Table
|
|
229
235
|
* @group Components
|
|
@@ -233,11 +239,11 @@ export type VirtualTableSort = "asc" | "desc" | undefined;
|
|
|
233
239
|
* @see Table
|
|
234
240
|
* @group Components
|
|
235
241
|
*/
|
|
236
|
-
export type VirtualTableFilterValues<Key extends string> =
|
|
242
|
+
export type VirtualTableFilterValues<Key extends string> = FilterValues<Key>;
|
|
237
243
|
/**
|
|
238
244
|
* Filter conditions in a `Query.where()` clause are specified using the
|
|
239
245
|
* strings `<`, `<=`, `==`, `>=`, `>`, `array-contains`, `in`, and `array-contains-any`.
|
|
240
246
|
* @see Table
|
|
241
247
|
* @group Models
|
|
242
248
|
*/
|
|
243
|
-
export type VirtualTableWhereFilterOp =
|
|
249
|
+
export type VirtualTableWhereFilterOp = WhereFilterOp;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rebasepro/studio",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.5.0",
|
|
5
5
|
"main": "./dist/index.umd.js",
|
|
6
6
|
"module": "./dist/index.es.js",
|
|
7
7
|
"types": "dist/studio/src/index.d.ts",
|
|
@@ -15,19 +15,19 @@
|
|
|
15
15
|
"pgsql-ast-parser": "12.0.2",
|
|
16
16
|
"prism-react-renderer": "^2.4.1",
|
|
17
17
|
"react-dropzone": "^14.4.1",
|
|
18
|
-
"@rebasepro/client": "0.
|
|
19
|
-
"@rebasepro/
|
|
20
|
-
"@rebasepro/
|
|
21
|
-
"@rebasepro/
|
|
22
|
-
"@rebasepro/
|
|
23
|
-
"@rebasepro/
|
|
18
|
+
"@rebasepro/client": "0.5.0",
|
|
19
|
+
"@rebasepro/common": "0.5.0",
|
|
20
|
+
"@rebasepro/utils": "0.5.0",
|
|
21
|
+
"@rebasepro/core": "0.5.0",
|
|
22
|
+
"@rebasepro/types": "0.5.0",
|
|
23
|
+
"@rebasepro/ui": "0.5.0"
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|
|
26
26
|
"react": ">=19.0.0",
|
|
27
27
|
"react-dom": ">=19.0.0",
|
|
28
28
|
"react-router": "^7.0.0",
|
|
29
29
|
"react-router-dom": "^7.0.0",
|
|
30
|
-
"@rebasepro/admin": "0.
|
|
30
|
+
"@rebasepro/admin": "0.5.0"
|
|
31
31
|
},
|
|
32
32
|
"peerDependenciesMeta": {
|
|
33
33
|
"@rebasepro/admin": {
|
|
@@ -166,7 +166,7 @@ function detectCollectionsInResult(
|
|
|
166
166
|
for (const slug of mentionedSlugs) {
|
|
167
167
|
const normalised = toSnakeCase(slug);
|
|
168
168
|
const col = collections.find(c => {
|
|
169
|
-
const tableName = (
|
|
169
|
+
const tableName = ("table" in c ? c.table : undefined) || toSnakeCase(c.slug);
|
|
170
170
|
return c.slug === slug || tableName === normalised || toSnakeCase(c.slug) === normalised;
|
|
171
171
|
});
|
|
172
172
|
if (col) {
|
|
@@ -129,25 +129,12 @@ interface AdminUser {
|
|
|
129
129
|
updatedAt: string;
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
interface RebaseRole {
|
|
133
|
-
id: string;
|
|
134
|
-
name: string;
|
|
135
|
-
isAdmin: boolean;
|
|
136
|
-
defaultPermissions: Record<string, unknown> | null;
|
|
137
|
-
config: Record<string, unknown> | null;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
132
|
interface RebaseAdmin {
|
|
141
133
|
listUsers(): Promise<{ users: AdminUser[] }>;
|
|
142
134
|
getUser(userId: string): Promise<{ user: AdminUser }>;
|
|
143
135
|
createUser(data: { email: string; displayName?: string; password?: string; roles?: string[] }): Promise<{ user: AdminUser }>;
|
|
144
136
|
updateUser(userId: string, data: { email?: string; displayName?: string; password?: string; roles?: string[] }): Promise<{ user: AdminUser }>;
|
|
145
137
|
deleteUser(userId: string): Promise<{ success: boolean }>;
|
|
146
|
-
listRoles(): Promise<{ roles: RebaseRole[] }>;
|
|
147
|
-
getRole(roleId: string): Promise<{ role: RebaseRole }>;
|
|
148
|
-
createRole(data: { id: string; name: string; isAdmin?: boolean; defaultPermissions?: Record<string, unknown>; config?: Record<string, unknown> }): Promise<{ role: RebaseRole }>;
|
|
149
|
-
updateRole(roleId: string, data: { name?: string; isAdmin?: boolean; defaultPermissions?: Record<string, unknown>; config?: Record<string, unknown> }): Promise<{ role: RebaseRole }>;
|
|
150
|
-
deleteRole(roleId: string): Promise<{ success: boolean }>;
|
|
151
138
|
bootstrap(): Promise<{ success: boolean; message: string; user: { uid: string; roles: string[] } }>;
|
|
152
139
|
}
|
|
153
140
|
|
|
@@ -4,9 +4,9 @@ import type { Node, Edge } from "@xyflow/react";
|
|
|
4
4
|
// ─── Layout Constants ─────────────────────────────────────────────────
|
|
5
5
|
export const NODE_WIDTH = 280;
|
|
6
6
|
/** Header with a single line of text (junction tables or tableName === collectionName). */
|
|
7
|
-
|
|
7
|
+
const HEADER_HEIGHT_SINGLE = 33;
|
|
8
8
|
/** Header with two lines (name + subtitle when collectionName !== tableName). */
|
|
9
|
-
|
|
9
|
+
const HEADER_HEIGHT_DOUBLE = 47;
|
|
10
10
|
const ROW_HEIGHT = 28; // height per column row
|
|
11
11
|
|
|
12
12
|
/**
|
|
@@ -26,7 +26,7 @@ export const getHeaderHeight = (opts: {
|
|
|
26
26
|
/**
|
|
27
27
|
* Estimate the pixel height of a table node based on column count.
|
|
28
28
|
*/
|
|
29
|
-
|
|
29
|
+
const estimateNodeHeight = (columnCount: number, headerHeight: number = HEADER_HEIGHT_DOUBLE): number =>
|
|
30
30
|
headerHeight + Math.max(columnCount, 1) * ROW_HEIGHT + 4; // +4 for bottom padding
|
|
31
31
|
|
|
32
32
|
/**
|
|
@@ -46,9 +46,9 @@ const extractColumns = (collection: EntityCollection): ColumnInfo[] => {
|
|
|
46
46
|
if (prop.type === "relation") continue; // Relations are shown as edges, not columns
|
|
47
47
|
|
|
48
48
|
const isPk =
|
|
49
|
-
("isId" in prop && Boolean(
|
|
49
|
+
("isId" in prop && Boolean(prop.isId)) ||
|
|
50
50
|
(!Object.values(properties).some(
|
|
51
|
-
(p) => "isId" in p && Boolean(
|
|
51
|
+
(p) => "isId" in p && Boolean(p.isId)
|
|
52
52
|
) &&
|
|
53
53
|
propName === "id");
|
|
54
54
|
|
|
@@ -311,6 +311,7 @@ character_maximum_length: null }
|
|
|
311
311
|
|
|
312
312
|
const prop = collection.properties!.tags as ArrayProperty;
|
|
313
313
|
expect(prop.type).toBe("array");
|
|
314
|
+
expect(prop.columnType).toBe("text[]");
|
|
314
315
|
expect(!Array.isArray(prop.of) && prop.of?.type).toBe("string");
|
|
315
316
|
});
|
|
316
317
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EntityCollection, Property, StringProperty, NumberProperty, ArrayProperty, TableColumnInfo, TableMetadata } from "@rebasepro/types";
|
|
1
|
+
import type { EntityCollection, Property, StringProperty, NumberProperty, ArrayProperty, TableColumnInfo, TableMetadata, SecurityOperation, SecurityRule } from "@rebasepro/types";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Maps a PostgreSQL column data type to a Rebase property type.
|
|
@@ -159,12 +159,29 @@ label: v.replace(/_/g, " ").replace(/\b\w/g, (c: string) => c.toUpperCase()) }))
|
|
|
159
159
|
};
|
|
160
160
|
|
|
161
161
|
case "array":
|
|
162
|
-
case "ARRAY":
|
|
162
|
+
case "ARRAY": {
|
|
163
|
+
let innerType = "string";
|
|
164
|
+
let colType: ArrayProperty["columnType"] = undefined;
|
|
165
|
+
if (udt_name === "_text" || udt_name === "_varchar") {
|
|
166
|
+
innerType = "string";
|
|
167
|
+
colType = "text[]";
|
|
168
|
+
} else if (udt_name === "_int4" || udt_name === "_int2" || udt_name === "_int8") {
|
|
169
|
+
innerType = "number";
|
|
170
|
+
colType = "integer[]";
|
|
171
|
+
} else if (udt_name === "_bool") {
|
|
172
|
+
innerType = "boolean";
|
|
173
|
+
colType = "boolean[]";
|
|
174
|
+
} else if (udt_name === "_numeric") {
|
|
175
|
+
innerType = "number";
|
|
176
|
+
colType = "numeric[]";
|
|
177
|
+
}
|
|
163
178
|
return {
|
|
164
179
|
type: "array",
|
|
165
180
|
name: prettifiedName,
|
|
166
|
-
|
|
181
|
+
columnType: colType,
|
|
182
|
+
of: { type: innerType }
|
|
167
183
|
} as ArrayProperty;
|
|
184
|
+
}
|
|
168
185
|
|
|
169
186
|
default:
|
|
170
187
|
// Fallback: treat unknown types as string
|
|
@@ -195,13 +212,7 @@ export function buildCollectionFromTableMetadata(
|
|
|
195
212
|
localKey?: string;
|
|
196
213
|
through?: { table: string; sourceColumn: string; targetColumn: string };
|
|
197
214
|
}> = [];
|
|
198
|
-
const securityRules:
|
|
199
|
-
name: string;
|
|
200
|
-
operations: string[];
|
|
201
|
-
roles: string[];
|
|
202
|
-
qual: string | null | undefined;
|
|
203
|
-
with_check: string | null | undefined;
|
|
204
|
-
}> = [];
|
|
215
|
+
const securityRules: SecurityRule[] = [];
|
|
205
216
|
|
|
206
217
|
// Parse columns
|
|
207
218
|
for (const column of metadata.columns) {
|
|
@@ -254,22 +265,31 @@ export function buildCollectionFromTableMetadata(
|
|
|
254
265
|
for (const policy of metadata.policies) {
|
|
255
266
|
// Attempt to map typical cmds to operations.
|
|
256
267
|
// Postgres cmd: SELECT, INSERT, UPDATE, DELETE, ALL
|
|
257
|
-
let operations:
|
|
268
|
+
let operations: SecurityOperation[] = [];
|
|
258
269
|
switch (policy.cmd) {
|
|
259
|
-
case "ALL": operations = ["
|
|
260
|
-
case "SELECT": operations = ["
|
|
261
|
-
case "INSERT": operations = ["
|
|
270
|
+
case "ALL": operations = ["all"]; break;
|
|
271
|
+
case "SELECT": operations = ["select"]; break;
|
|
272
|
+
case "INSERT": operations = ["insert"]; break;
|
|
262
273
|
case "UPDATE": operations = ["update"]; break;
|
|
263
274
|
case "DELETE": operations = ["delete"]; break;
|
|
264
275
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
276
|
+
const qual = policy.qual ?? undefined;
|
|
277
|
+
const withCheck = policy.with_check ?? undefined;
|
|
278
|
+
if (qual) {
|
|
279
|
+
securityRules.push({
|
|
280
|
+
name: policy.policy_name,
|
|
281
|
+
operations,
|
|
282
|
+
roles: policy.roles ?? [],
|
|
283
|
+
using: qual,
|
|
284
|
+
...(withCheck ? { withCheck } : {})
|
|
285
|
+
});
|
|
286
|
+
} else {
|
|
287
|
+
securityRules.push({
|
|
288
|
+
name: policy.policy_name,
|
|
289
|
+
operations,
|
|
290
|
+
roles: policy.roles ?? [],
|
|
291
|
+
});
|
|
292
|
+
}
|
|
273
293
|
}
|
|
274
294
|
}
|
|
275
295
|
|
package/src/utils/sql_utils.ts
CHANGED
|
@@ -105,7 +105,7 @@ export function resolveQueryCollections(
|
|
|
105
105
|
for (const table of tables) {
|
|
106
106
|
// Match table name against collection table or slug->snake_case
|
|
107
107
|
const matched = collections.find(c => {
|
|
108
|
-
const tableName = (
|
|
108
|
+
const tableName = ("table" in c ? c.table : undefined) || toSnakeCase(c.slug);
|
|
109
109
|
return tableName === table.name;
|
|
110
110
|
});
|
|
111
111
|
|