okengine 0.13.0 → 0.15.2
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/manifest.v1.schema.json +7 -1
- package/package.json +4 -5
- package/site/content/docs/ai/mcp.mdx +27 -2
- package/site/content/docs/elements/ai.mdx +59 -11
- package/site/content/docs/elements/channel.mdx +1 -0
- package/site/content/docs/elements/clock.mdx +30 -12
- package/site/content/docs/elements/flow.mdx +9 -3
- package/site/content/docs/elements/gate.mdx +25 -22
- package/site/content/docs/elements/signal.mdx +71 -25
- package/site/content/docs/elements/store.mdx +87 -28
- package/site/content/docs/elements/vault.mdx +1 -0
- package/site/content/docs/get-started/basic-usage.mdx +22 -13
- package/site/content/docs/get-started/index.mdx +5 -0
- package/site/content/docs/get-started/installation.mdx +2 -2
- package/site/content/docs/get-started/introduction.mdx +11 -3
- package/site/content/docs/get-started/meta.json +1 -1
- package/site/content/docs/get-started/project-structure.mdx +932 -0
- package/site/content/docs/reference/cli.md +13 -10
- package/site/content/docs/reference/client.mdx +25 -21
- package/site/content/docs/reference/fx.mdx +27 -22
- package/site/content/docs/reference/security.md +1 -1
- package/src/auth/bindings.ts +14 -5
- package/src/auth/cross-plane.ts +10 -3
- package/src/cli/ai-setup/ai-setup.test.ts +62 -0
- package/src/cli/ai-setup/apply.ts +32 -1
- package/src/cli/ai-setup/recommend.test.ts +25 -0
- package/src/cli/ai-setup/recommend.ts +8 -3
- package/src/cli/attach-host-console.test.ts +3 -2
- package/src/cli/attach-host-console.ts +3 -0
- package/src/cli/build.test.ts +4 -2
- package/src/cli/db-seed.ts +48 -15
- package/src/cli/db.test.ts +104 -0
- package/src/cli/db.ts +122 -10
- package/src/cli/dev-controls.test.ts +20 -0
- package/src/cli/dev-controls.ts +13 -0
- package/src/cli/dev.test.ts +15 -4
- package/src/cli/dev.ts +102 -29
- package/src/cli/ensure-drizzle-config.ts +2 -1
- package/src/cli/tui/DevLive.tsx +12 -2
- package/src/cli/tui/keys.test.ts +2 -1
- package/src/cli/tui/keys.ts +3 -2
- package/src/compiler/aot.test.ts +1 -1
- package/src/compiler/effects-infer.ts +58 -3
- package/src/compiler/extract.test.ts +458 -29
- package/src/compiler/extract.ts +387 -69
- package/src/compiler/flow-path.test.ts +96 -0
- package/src/compiler/flow-path.ts +173 -0
- package/src/compiler/generate-adopt.test.ts +112 -3
- package/src/compiler/generate-adopt.ts +280 -26
- package/src/compiler/response.ts +45 -1
- package/src/compiler/schema-from-ast.ts +609 -0
- package/src/console/server/ai.ts +5 -2
- package/src/console/server/bind.ts +2 -2
- package/src/console/server/console.test.ts +3 -0
- package/src/console/server/flows.ts +121 -40
- package/src/console/server/invoke-user-flow.test.ts +3 -1
- package/src/console/server/invoke-user-flow.ts +17 -2
- package/src/console/server/iso-at.test.ts +9 -0
- package/src/console/server/iso-at.ts +11 -0
- package/src/console/server/security-headers.ts +6 -3
- package/src/console/server/serve.ts +17 -2
- package/src/console/server/spa-proxy.test.ts +1 -0
- package/src/console/server/sql-catalog.ts +147 -7
- package/src/console/server/sql-rls.test.ts +16 -0
- package/src/console/server/state.ts +8 -0
- package/src/console/server/store.test.ts +7 -4
- package/src/console/server/store.ts +142 -58
- package/src/console/ui-next/dist/assets/agent-disclosure-C0X1fbWF.js +1 -0
- package/src/console/ui-next/dist/assets/cache-glyph-F1FI122b.js +1 -0
- package/src/console/ui-next/dist/assets/{call-pii-button-bqkxMrJH.js → call-pii-button-DEDCl_j3.js} +1 -1
- package/src/console/ui-next/dist/assets/collapsible-LPqGvfoz.js +1 -0
- package/src/console/ui-next/dist/assets/{confirm-sheet-DDCRmG62.js → confirm-sheet-3ptDzXbz.js} +1 -1
- package/src/console/ui-next/dist/assets/{duration-tone-oiRxPVsZ.js → duration-tone-sC3lGABz.js} +1 -1
- package/src/console/ui-next/dist/assets/{explorer-empty-HjTnVQoR.js → explorer-empty-BvYrygyO.js} +1 -1
- package/src/console/ui-next/dist/assets/flows-page-Dluo1Bd7.js +1 -0
- package/src/console/ui-next/dist/assets/{highlighted-json-CvDPvveV.js → highlighted-json-CS_O8L-r.js} +1 -1
- package/src/console/ui-next/dist/assets/http-method--sWDdXSB.js +1 -0
- package/src/console/ui-next/dist/assets/index-Ca3HZMVq.js +66 -0
- package/src/console/ui-next/dist/assets/index-UtTDRQpS.css +2 -0
- package/src/console/ui-next/dist/assets/{link-DF7SZ9Ek.js → link-COeyggt-.js} +1 -1
- package/src/console/ui-next/dist/assets/observability-page-HK9-BO8z.js +4 -0
- package/src/console/ui-next/dist/assets/react-D8E3mtu1.js +1 -0
- package/src/console/ui-next/dist/assets/replica-lag-DBIFFf7d.js +18 -0
- package/src/console/ui-next/dist/assets/sheet-form-Dnwa5oOR.js +1 -0
- package/src/console/ui-next/dist/assets/shortcut-keys-CoqwEIi0.js +1 -0
- package/src/console/ui-next/dist/assets/skeleton-BHcfDYcb.js +1 -0
- package/src/console/ui-next/dist/assets/store-page-BSohH3wM.js +41 -0
- package/src/console/ui-next/dist/assets/trace-detail-sheet-CFIGRnnA.js +2 -0
- package/src/console/ui-next/dist/assets/tree-expand-toggle-BgLl34w7.js +54 -0
- package/src/console/ui-next/dist/assets/units-page-B0cFE76A.js +1 -0
- package/src/console/ui-next/dist/assets/{use-vault-list-Cl79j_ku.js → use-vault-list-BLbZhzyF.js} +1 -1
- package/src/console/ui-next/dist/assets/vault-page-B1SbYe10.js +2 -0
- package/src/console/ui-next/dist/index.html +6 -6
- package/src/console/ui-next/seed-invoke-host.ts +2 -0
- package/src/console/ui-next/src/client.ts +35 -7
- package/src/console/ui-next/src/components/motion/table/index.tsx +16 -0
- package/src/console/ui-next/src/components/motion/table/types.ts +4 -0
- package/src/console/ui-next/src/components/ui/kbd.tsx +2 -2
- package/src/console/ui-next/src/features/flows/graph/build-flow-graph.test.ts +18 -0
- package/src/console/ui-next/src/features/flows/graph/build-flow-graph.ts +14 -1
- package/src/console/ui-next/src/features/flows/graph/neighborhood.test.ts +17 -0
- package/src/console/ui-next/src/features/flows/graph/neighborhood.ts +16 -3
- package/src/console/ui-next/src/features/flows/traces/effect-kind.ts +3 -1
- package/src/console/ui-next/src/features/flows/traces/effect-summary.ts +24 -0
- package/src/console/ui-next/src/features/flows/traces/http-method.ts +19 -0
- package/src/console/ui-next/src/features/flows/traces/trace-detail-sheet.tsx +9 -3
- package/src/console/ui-next/src/features/flows/traces/trace-detail.test.ts +29 -2
- package/src/console/ui-next/src/features/flows/traces/traces-pane.tsx +10 -3
- package/src/console/ui-next/src/features/observability/lib/ask-count.test.ts +25 -0
- package/src/console/ui-next/src/features/observability/lib/ask-count.ts +4 -1
- package/src/console/ui-next/src/features/store/detail/browse-section.tsx +45 -1
- package/src/console/ui-next/src/features/store/detail/resource-panel.tsx +78 -16
- package/src/console/ui-next/src/features/store/detail/store-row-detail-sheet.tsx +155 -14
- package/src/console/ui-next/src/features/store/explorer/store-tree.tsx +33 -133
- package/src/console/ui-next/src/features/store/files/file-preview.tsx +4 -1
- package/src/console/ui-next/src/features/store/grid/rls-policy-sheet.tsx +326 -165
- package/src/console/ui-next/src/features/store/grid/sql-insert-sheet.tsx +6 -0
- package/src/console/ui-next/src/features/store/grid/store-data-grid.tsx +50 -3
- package/src/console/ui-next/src/features/store/lib/files-meta.test.ts +3 -0
- package/src/console/ui-next/src/features/store/lib/files-meta.ts +12 -0
- package/src/console/ui-next/src/features/store/lib/query-defaults.test.ts +25 -0
- package/src/console/ui-next/src/features/store/lib/query-defaults.ts +85 -3
- package/src/console/ui-next/src/features/store/lib/query-gate.ts +30 -4
- package/src/console/ui-next/src/features/store/lib/rls-policy.test.ts +139 -0
- package/src/console/ui-next/src/features/store/lib/rls-policy.ts +223 -21
- package/src/console/ui-next/src/features/store/lib/schema-graph.ts +4 -0
- package/src/console/ui-next/src/features/store/lib/sql-catalog.test.ts +24 -0
- package/src/console/ui-next/src/features/store/lib/sql-catalog.ts +19 -0
- package/src/console/ui-next/src/features/store/lib/store-tree.test.ts +6 -0
- package/src/console/ui-next/src/features/store/lib/store-tree.ts +13 -0
- package/src/console/ui-next/src/features/store/query/query-console.tsx +48 -14
- package/src/console/ui-next/src/features/store/query/query-gate-menu.tsx +19 -20
- package/src/console/ui-next/src/features/store/query/query-gate-parts.tsx +2 -1
- package/src/console/ui-next/src/features/store/query/query-results.tsx +110 -83
- package/src/console/ui-next/src/features/store/schema/schema-table-node.tsx +17 -0
- package/src/console/ui-next/src/features/units/call/call-api-panel.tsx +112 -72
- package/src/console/ui-next/src/features/units/detail/effects-summary.tsx +12 -4
- package/src/console/ui-next/src/features/units/lib/contract-input.test.ts +206 -1
- package/src/console/ui-next/src/features/units/lib/contract-input.ts +55 -0
- package/src/console/ui-next/src/features/vault/lib/types.ts +1 -1
- package/src/docker/compose-health.test.ts +27 -0
- package/src/docker/compose-health.ts +19 -3
- package/src/docker/docker.test.ts +4 -1
- package/src/docker/dockerfile.ts +1 -1
- package/src/docker/recipes/pgdog.ts +2 -0
- package/src/drivers/ai-anthropic.ts +5 -0
- package/src/drivers/ai-ollama.ts +49 -30
- package/src/drivers/ai-openai-compatible.ts +57 -46
- package/src/drivers/ai-providers.test.ts +3 -0
- package/src/drivers/bun-native-completeness.test.ts +7 -9
- package/src/drivers/clock-postgres.ts +13 -9
- package/src/drivers/instances-postgres.ts +4 -6
- package/src/drivers/journal-postgres.ts +13 -9
- package/src/drivers/pg-rls.test.ts +87 -0
- package/src/drivers/pg-rls.ts +233 -7
- package/src/drivers/pglite.ts +26 -3
- package/src/drivers/postgres.test.ts +23 -0
- package/src/drivers/postgres.ts +133 -9
- package/src/drivers/redis.ts +11 -4
- package/src/drivers/signal-redis.ts +24 -14
- package/src/drivers/signal-types.ts +2 -1
- package/src/drivers/types.ts +10 -0
- package/src/elements/ai/declare.ts +109 -0
- package/src/elements/ai/errors.test.ts +5 -1
- package/src/elements/ai/errors.ts +30 -2
- package/src/elements/ai/eval.ts +4 -6
- package/src/elements/ai/mcp-client.test.ts +206 -0
- package/src/elements/ai/mcp-client.ts +362 -0
- package/src/elements/ai/mcp-http.ts +159 -0
- package/src/elements/ai/mcp-mock.ts +134 -0
- package/src/elements/ai/mcp-protocol.ts +234 -0
- package/src/elements/ai/mcp-stdio.test.ts +50 -0
- package/src/elements/ai/mcp-stdio.ts +212 -0
- package/src/elements/ai/mcp-transport.ts +70 -0
- package/src/elements/ai/runtime.ts +159 -29
- package/src/elements/ai.test.ts +139 -0
- package/src/elements/ai.ts +16 -0
- package/src/elements/clock/declare.ts +26 -1
- package/src/elements/clock/health.test.ts +43 -0
- package/src/elements/clock/runtime.ts +55 -2
- package/src/elements/clock/schedule.ts +71 -142
- package/src/elements/clock.test.ts +9 -40
- package/src/elements/clock.ts +6 -1
- package/src/elements/gate/boot.ts +5 -5
- package/src/elements/gate/declare.ts +36 -4
- package/src/elements/gate/flatten.ts +1 -1
- package/src/elements/gate/runtime.ts +1 -1
- package/src/elements/index.ts +2 -0
- package/src/elements/signal/declare.ts +2 -1
- package/src/elements/signal/runtime.ts +16 -1
- package/src/elements/signal.ts +1 -0
- package/src/elements/store/cache.test.ts +2 -0
- package/src/elements/store/cache.ts +3 -3
- package/src/elements/store/declare.ts +9 -6
- package/src/elements/store/emit-drizzle.ts +44 -8
- package/src/elements/store/resource.test.ts +1 -1
- package/src/elements/store/rls-identity.test.ts +95 -0
- package/src/elements/store/rls-identity.ts +116 -0
- package/src/elements/store/runtime.ts +4 -0
- package/src/elements/store/schema-decl.test.ts +37 -0
- package/src/elements/store/schema-decl.ts +161 -0
- package/src/elements/store/seed.ts +1 -1
- package/src/elements/store/sql-condition.test.ts +12 -0
- package/src/elements/store/sql-condition.ts +26 -2
- package/src/elements/store/sql-rls-isolation.test.ts +165 -0
- package/src/elements/store/sql-rls-stamp.test.ts +117 -0
- package/src/elements/store/sql-session.ts +81 -3
- package/src/elements/store/upsert-app.test.ts +1 -1
- package/src/elements/store.ts +14 -0
- package/src/elements/vault/builtin-adapter.ts +17 -0
- package/src/full.ts +2 -0
- package/src/http.ts +20 -3
- package/src/index.ts +14 -1
- package/src/kernel/adopt-barrel-fresh.test.ts +1 -1
- package/src/kernel/adopt-routes.ts +30 -2
- package/src/kernel/app.ts +227 -77
- package/src/kernel/auto-cache.test.ts +8 -8
- package/src/kernel/auto-registry.test.ts +54 -9
- package/src/kernel/boot-bind/ai.ts +24 -0
- package/src/kernel/boot-bind/clock.ts +2 -0
- package/src/kernel/boot.test.ts +4 -4
- package/src/kernel/boot.ts +5 -3
- package/src/kernel/effects-stamping.test.ts +3 -3
- package/src/kernel/element-registries.ts +15 -5
- package/src/kernel/errors.ts +24 -0
- package/src/kernel/flow-units.ts +64 -0
- package/src/kernel/flow.ts +29 -17
- package/src/kernel/fx-dead-letters.test.ts +77 -0
- package/src/kernel/fx.test.ts +22 -0
- package/src/kernel/fx.ts +135 -6
- package/src/kernel/horizontal-child.ts +4 -4
- package/src/kernel/http-path-pending.ts +20 -0
- package/src/kernel/http-resource.ts +4 -0
- package/src/kernel/http-stream.test.ts +174 -0
- package/src/kernel/index.ts +2 -0
- package/src/kernel/pipeline.test.ts +2 -2
- package/src/kernel/plugin-elements.test.ts +1 -1
- package/src/kernel/plugin-needs.test.ts +1 -1
- package/src/kernel/ready.test.ts +2 -2
- package/src/kernel/resource-mount.test.ts +14 -0
- package/src/kernel/run-duration.test.ts +2 -2
- package/src/kernel/stamp-http.test.ts +79 -0
- package/src/kernel/stamp-http.ts +75 -0
- package/src/kernel/triggers.ts +52 -27
- package/src/manifest/mcp-ref.ts +88 -0
- package/src/manifest/types.ts +41 -2
- package/src/manifest/validate.test.ts +20 -0
- package/src/mcp/docs-server.ts +1 -1
- package/src/mcp/server.ts +1 -1
- package/src/plugins/compression.test.ts +21 -0
- package/src/plugins/compression.ts +1 -0
- package/src/release/measure.ts +2 -2
- package/src/runtime/bun.ts +41 -4
- package/src/runtime/json-code-block.test.ts +2 -2
- package/src/runtime/serve.test.ts +4 -4
- package/src/term.test.ts +52 -4
- package/src/term.ts +125 -17
- package/src/test/reset-element-registries.ts +10 -3
- package/src/cli/ask-seed.test.ts +0 -96
- package/src/cli/ask-seed.ts +0 -82
- package/src/console/ui-next/dist/assets/cache-glyph-CLPBqZeb.js +0 -1
- package/src/console/ui-next/dist/assets/collapsible-DYb0xU8C.js +0 -1
- package/src/console/ui-next/dist/assets/flows-page-Dg8CTE29.js +0 -1
- package/src/console/ui-next/dist/assets/http-method-BJ92Z_ke.js +0 -1
- package/src/console/ui-next/dist/assets/index-Bp-R7jtM.js +0 -66
- package/src/console/ui-next/dist/assets/index-D4Ldtj79.css +0 -2
- package/src/console/ui-next/dist/assets/observability-page-DAnpEaq1.js +0 -4
- package/src/console/ui-next/dist/assets/query-gate-parts-1m8m1iNp.js +0 -2
- package/src/console/ui-next/dist/assets/react-B1ML8gxg.js +0 -1
- package/src/console/ui-next/dist/assets/replica-lag-C8_BRt2x.js +0 -18
- package/src/console/ui-next/dist/assets/sheet-form-D-ata7jy.js +0 -1
- package/src/console/ui-next/dist/assets/shortcut-keys-DO4IsVqv.js +0 -1
- package/src/console/ui-next/dist/assets/skeleton-CL_X0GCj.js +0 -1
- package/src/console/ui-next/dist/assets/store-page-v3LXdYpr.js +0 -45
- package/src/console/ui-next/dist/assets/trace-detail-sheet-D16lWQMt.js +0 -2
- package/src/console/ui-next/dist/assets/units-page-BtQ0bqMe.js +0 -1
- package/src/console/ui-next/dist/assets/vault-page-Ca-MvcmJ.js +0 -2
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
} from "@hugeicons/core-free-icons";
|
|
18
18
|
import { HugeiconsIcon } from "@hugeicons/react";
|
|
19
19
|
import { AgentCode } from "@/components/agents/agent-code";
|
|
20
|
+
import { EXPLORER_ICON_BUTTON_CLASS } from "@/components/explorer/explorer-chrome.ts";
|
|
20
21
|
import { Input } from "@/components/ui/input";
|
|
21
22
|
import {
|
|
22
23
|
SHEET_CONTROL,
|
|
@@ -39,16 +40,19 @@ import {
|
|
|
39
40
|
} from "@/components/motion/select.tsx";
|
|
40
41
|
import {
|
|
41
42
|
Sheet,
|
|
43
|
+
SheetClose,
|
|
42
44
|
SheetContent,
|
|
43
45
|
SheetDescription,
|
|
44
46
|
SheetFooter,
|
|
45
47
|
SheetHeader,
|
|
46
48
|
SheetTitle,
|
|
47
49
|
} from "@/components/ui/sheet";
|
|
50
|
+
import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from "@/components/ui/resizable";
|
|
48
51
|
import { Switch } from "@/components/motion/switch.tsx";
|
|
49
52
|
import { LayoutGroup, motion, useReducedMotion } from "@/lib/motion.ts";
|
|
50
53
|
import { SPRING_LAYOUT } from "@/lib/ease.ts";
|
|
51
54
|
import { cn } from "@/lib/utils.ts";
|
|
55
|
+
import { SchemaColumnMarks } from "../schema/schema-constraint-icon.tsx";
|
|
52
56
|
import type { Manifest } from "../../../../../../manifest/types.ts";
|
|
53
57
|
import { useGates } from "../data/use-gates.ts";
|
|
54
58
|
import { useStoreEdit } from "../data/use-store-edit.ts";
|
|
@@ -70,11 +74,21 @@ import {
|
|
|
70
74
|
parseSqlPolicySpec,
|
|
71
75
|
RLS_POLICY_COMMANDS,
|
|
72
76
|
RLS_POLICY_TEMPLATES,
|
|
77
|
+
rlsBindOwnerExpr,
|
|
73
78
|
rlsCommandFromGateMode,
|
|
79
|
+
rlsExprNeedsOwnerColumn,
|
|
80
|
+
rlsExprUsesUserIdentity,
|
|
74
81
|
rlsGateActionsForMode,
|
|
75
82
|
rlsGateModeFromCommand,
|
|
83
|
+
rlsOwnerColumn,
|
|
76
84
|
rlsPolicyPredicates,
|
|
77
85
|
rlsPolicyPreviewSql,
|
|
86
|
+
rlsPolicyCodeSource,
|
|
87
|
+
rlsRewriteIdentityColumn,
|
|
88
|
+
rlsGatePredicateSql,
|
|
89
|
+
rlsTableColumns,
|
|
90
|
+
rlsTableSqlColumns,
|
|
91
|
+
rlsTemplateUsesOwner,
|
|
78
92
|
type RlsGateMode,
|
|
79
93
|
type RlsPolicyTemplate,
|
|
80
94
|
type SqlPolicyBehavior,
|
|
@@ -117,7 +131,9 @@ export function RlsPolicySheet({
|
|
|
117
131
|
const edit = useStoreEdit();
|
|
118
132
|
const gatesQuery = useGates(open);
|
|
119
133
|
const [name, setName] = useState("");
|
|
134
|
+
const [dock, setDock] = useState<"sql" | "code">("sql");
|
|
120
135
|
const [table, setTable] = useState(tables[0] ?? "");
|
|
136
|
+
const [identityCol, setIdentityCol] = useState("");
|
|
121
137
|
const [command, setCommand] = useState<SqlPolicyCommand>("SELECT");
|
|
122
138
|
const [behavior, setBehavior] = useState<SqlPolicyBehavior>("PERMISSIVE");
|
|
123
139
|
const [using, setUsing] = useState("true");
|
|
@@ -135,6 +151,24 @@ export function RlsPolicySheet({
|
|
|
135
151
|
);
|
|
136
152
|
const gateMode = rlsGateModeFromCommand(command);
|
|
137
153
|
const predicates = rlsPolicyPredicates(command);
|
|
154
|
+
const tableColumns = useMemo(
|
|
155
|
+
() => rlsTableColumns(manifest, storeRef, table),
|
|
156
|
+
[manifest, storeRef, table],
|
|
157
|
+
);
|
|
158
|
+
const sqlColumns = useMemo(() => tableColumns.map((col) => col.sqlName), [tableColumns]);
|
|
159
|
+
const suggestedCol = rlsOwnerColumn(sqlColumns);
|
|
160
|
+
const identityValue =
|
|
161
|
+
identityCol !== "" && sqlColumns.includes(identityCol) ? identityCol : (suggestedCol ?? "");
|
|
162
|
+
const ownerStyle =
|
|
163
|
+
(templateId !== null &&
|
|
164
|
+
rlsTemplateUsesOwner(RLS_POLICY_TEMPLATES.find((tpl) => tpl.id === templateId) ?? {})) ||
|
|
165
|
+
(predicates.using && rlsExprUsesUserIdentity(using)) ||
|
|
166
|
+
(predicates.withCheck && rlsExprUsesUserIdentity(withCheck));
|
|
167
|
+
const showIdentitySelect = sqlColumns.length > 0 && ownerStyle;
|
|
168
|
+
const ownerUnbound =
|
|
169
|
+
((predicates.using && rlsExprNeedsOwnerColumn(using)) ||
|
|
170
|
+
(predicates.withCheck && rlsExprNeedsOwnerColumn(withCheck))) &&
|
|
171
|
+
identityValue === "";
|
|
138
172
|
const catalog = useMemo(
|
|
139
173
|
() => mergeRlsGateCatalog(rlsGateCatalog(manifest), gatesQuery.data ?? null),
|
|
140
174
|
[manifest, gatesQuery.data],
|
|
@@ -155,20 +189,48 @@ export function RlsPolicySheet({
|
|
|
155
189
|
using: predicates.using ? using : "",
|
|
156
190
|
withCheck: predicates.withCheck ? withCheck : "",
|
|
157
191
|
});
|
|
158
|
-
return
|
|
192
|
+
return {
|
|
193
|
+
sql: rlsPolicyPreviewSql(spec, enableRls),
|
|
194
|
+
code: rlsPolicyCodeSource(spec),
|
|
195
|
+
};
|
|
159
196
|
} catch {
|
|
160
197
|
return null;
|
|
161
198
|
}
|
|
162
199
|
}, [name, table, command, behavior, predicates, using, withCheck, enableRls]);
|
|
163
200
|
|
|
201
|
+
const bindIdentity = (expr: string, col: string): string =>
|
|
202
|
+
col !== "" ? rlsBindOwnerExpr(expr, col) : expr;
|
|
203
|
+
|
|
164
204
|
const applyTemplate = (tpl: RlsPolicyTemplate): void => {
|
|
205
|
+
const col = rlsTemplateUsesOwner(tpl) ? identityValue : "";
|
|
165
206
|
setTemplateId(tpl.id);
|
|
166
207
|
setName(tpl.name);
|
|
167
208
|
setCommand(tpl.command);
|
|
168
209
|
setBehavior(tpl.behavior ?? "PERMISSIVE");
|
|
169
210
|
setSelectedActions((prev) => rlsSyncActionsForCommand(prev, tpl.command));
|
|
170
|
-
setUsing(tpl.using ?? "true");
|
|
171
|
-
setWithCheck(tpl.withCheck ?? "true");
|
|
211
|
+
setUsing(bindIdentity(tpl.using ?? "true", col));
|
|
212
|
+
setWithCheck(bindIdentity(tpl.withCheck ?? "true", col));
|
|
213
|
+
if (col !== "") setIdentityCol(col);
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
const setPolicyTable = (next: string): void => {
|
|
217
|
+
const nextCols = rlsTableSqlColumns(manifest, storeRef, next);
|
|
218
|
+
const nextCol =
|
|
219
|
+
(identityCol !== "" && nextCols.includes(identityCol) ? identityCol : null) ??
|
|
220
|
+
rlsOwnerColumn(nextCols) ??
|
|
221
|
+
"";
|
|
222
|
+
setTable(next);
|
|
223
|
+
setIdentityCol(nextCol);
|
|
224
|
+
const from = identityValue || "owner";
|
|
225
|
+
setUsing((prev) => rlsRewriteIdentityColumn(prev, from, nextCol));
|
|
226
|
+
setWithCheck((prev) => rlsRewriteIdentityColumn(prev, from, nextCol));
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
const setIdentityColumn = (next: string): void => {
|
|
230
|
+
const from = identityValue || "owner";
|
|
231
|
+
setIdentityCol(next);
|
|
232
|
+
setUsing((prev) => rlsRewriteIdentityColumn(prev, from, next));
|
|
233
|
+
setWithCheck((prev) => rlsRewriteIdentityColumn(prev, from, next));
|
|
172
234
|
};
|
|
173
235
|
|
|
174
236
|
const setGateMode = (next: RlsGateMode): void => {
|
|
@@ -184,13 +246,21 @@ export function RlsPolicySheet({
|
|
|
184
246
|
};
|
|
185
247
|
|
|
186
248
|
const toggleGate = (id: string): void => {
|
|
187
|
-
setSelectedGates((current) =>
|
|
188
|
-
current.includes(id) ? current.filter((item) => item !== id) : [...current, id]
|
|
189
|
-
|
|
249
|
+
setSelectedGates((current) => {
|
|
250
|
+
const next = current.includes(id) ? current.filter((item) => item !== id) : [...current, id];
|
|
251
|
+
const expr = rlsGatePredicateSql(next);
|
|
252
|
+
setUsing(expr);
|
|
253
|
+
setWithCheck(expr);
|
|
254
|
+
return next;
|
|
255
|
+
});
|
|
190
256
|
};
|
|
191
257
|
|
|
192
258
|
const submit = async (): Promise<void> => {
|
|
193
259
|
setError(null);
|
|
260
|
+
if (ownerUnbound) {
|
|
261
|
+
setError(`Pick a column on ${table} that stores the user id.`);
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
194
264
|
try {
|
|
195
265
|
const spec = parseSqlPolicySpec({
|
|
196
266
|
name,
|
|
@@ -234,6 +304,7 @@ export function RlsPolicySheet({
|
|
|
234
304
|
>
|
|
235
305
|
<SheetContent
|
|
236
306
|
side="right"
|
|
307
|
+
showCloseButton={false}
|
|
237
308
|
className="flex-col gap-0 overflow-hidden rounded-none bg-popover p-0 shadow-lg sm:flex-row sm:items-stretch data-[side=right]:w-auto data-[side=right]:max-w-[calc(100vw-1.5rem)] data-[side=right]:sm:max-w-none"
|
|
238
309
|
data-slot="rls-policy-sheet"
|
|
239
310
|
>
|
|
@@ -241,8 +312,8 @@ export function RlsPolicySheet({
|
|
|
241
312
|
className="relative flex min-h-0 w-full flex-1 flex-col sm:w-[28rem] sm:flex-none"
|
|
242
313
|
data-slot="rls-policy-form-sheet"
|
|
243
314
|
>
|
|
244
|
-
<SheetHeader className="
|
|
245
|
-
<div className="flex items-start gap-3
|
|
315
|
+
<SheetHeader className="flex-row items-stretch gap-0 border-b border-border/60 p-0">
|
|
316
|
+
<div className="flex min-w-0 flex-1 items-start gap-3 p-4">
|
|
246
317
|
<div className="flex size-9 items-center justify-center rounded-full border border-border/50 bg-muted/20">
|
|
247
318
|
<HugeiconsIcon icon={SecurityCheckIcon} className="size-4" aria-hidden />
|
|
248
319
|
</div>
|
|
@@ -253,154 +324,229 @@ export function RlsPolicySheet({
|
|
|
253
324
|
</SheetDescription>
|
|
254
325
|
</div>
|
|
255
326
|
</div>
|
|
327
|
+
<span className="w-px shrink-0 self-stretch bg-border/60" aria-hidden />
|
|
328
|
+
<SheetClose
|
|
329
|
+
className={cn(EXPLORER_ICON_BUTTON_CLASS, "min-w-11")}
|
|
330
|
+
data-slot="rls-policy-form-close"
|
|
331
|
+
aria-label="Close"
|
|
332
|
+
>
|
|
333
|
+
<HugeiconsIcon icon={Cancel01Icon} className="size-4" aria-hidden />
|
|
334
|
+
<span className="sr-only">Close</span>
|
|
335
|
+
</SheetClose>
|
|
256
336
|
</SheetHeader>
|
|
257
|
-
<
|
|
258
|
-
<
|
|
259
|
-
<div className="
|
|
260
|
-
<
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
/>
|
|
330
|
-
) : null}
|
|
331
|
-
<SheetChapter
|
|
332
|
-
label="Rows"
|
|
333
|
-
hint={
|
|
334
|
-
predicates.using && predicates.withCheck
|
|
335
|
-
? "Existing rows and new rows"
|
|
336
|
-
: predicates.withCheck
|
|
337
|
-
? "New rows"
|
|
338
|
-
: "Existing rows"
|
|
339
|
-
}
|
|
340
|
-
/>
|
|
341
|
-
{predicates.using ? (
|
|
342
|
-
<SheetField label="USING">
|
|
343
|
-
<Input
|
|
344
|
-
value={using}
|
|
345
|
-
onChange={(event) => setUsing(event.target.value)}
|
|
346
|
-
placeholder="true"
|
|
347
|
-
flat
|
|
348
|
-
className={cn(SHEET_CONTROL, "font-mono")}
|
|
349
|
-
/>
|
|
350
|
-
</SheetField>
|
|
351
|
-
) : null}
|
|
352
|
-
{predicates.withCheck ? (
|
|
353
|
-
<SheetField label="WITH CHECK">
|
|
354
|
-
<Input
|
|
355
|
-
value={withCheck}
|
|
356
|
-
onChange={(event) => setWithCheck(event.target.value)}
|
|
357
|
-
placeholder="true"
|
|
358
|
-
flat
|
|
359
|
-
className={cn(SHEET_CONTROL, "font-mono")}
|
|
360
|
-
/>
|
|
361
|
-
</SheetField>
|
|
362
|
-
) : null}
|
|
363
|
-
</div>
|
|
364
|
-
<div
|
|
365
|
-
className="shrink-0 border-t border-border/50 bg-muted/15"
|
|
366
|
-
data-slot="rls-policy-sql-dock"
|
|
367
|
-
>
|
|
368
|
-
<div className="flex items-center justify-between gap-3 px-4 py-2">
|
|
369
|
-
<p className="text-[10px] font-semibold tracking-[0.12em] text-muted-foreground uppercase">
|
|
370
|
-
SQL
|
|
371
|
-
</p>
|
|
372
|
-
<label className="inline-flex items-center gap-2">
|
|
373
|
-
<span className="text-[11px] text-muted-foreground">Enable RLS</span>
|
|
374
|
-
<Switch
|
|
375
|
-
size="sm"
|
|
376
|
-
checked={enableRls}
|
|
377
|
-
onCheckedChange={setEnableRls}
|
|
378
|
-
ariaLabel="Enable RLS on this table"
|
|
337
|
+
<ResizablePanelGroup orientation="vertical" className="min-h-0 flex-1">
|
|
338
|
+
<ResizablePanel defaultSize="68%" minSize="28%" className="min-h-0">
|
|
339
|
+
<div className="h-full min-h-0 overflow-y-auto" data-slot="rls-policy-form-scroll">
|
|
340
|
+
<div className="border-b border-border/50">
|
|
341
|
+
<div className="flex items-center justify-between gap-2 px-4 pt-2.5">
|
|
342
|
+
<p className="text-[10px] font-semibold tracking-[0.12em] text-muted-foreground uppercase">
|
|
343
|
+
Policy name
|
|
344
|
+
</p>
|
|
345
|
+
<SheetTextToggle
|
|
346
|
+
active={templatesOpen}
|
|
347
|
+
aria-expanded={templatesOpen}
|
|
348
|
+
aria-controls={templatesOpen ? "rls-policy-templates-sheet" : undefined}
|
|
349
|
+
onClick={() => setTemplatesOpen((open) => !open)}
|
|
350
|
+
>
|
|
351
|
+
<HugeiconsIcon
|
|
352
|
+
icon={LeftToRightListBulletIcon}
|
|
353
|
+
className="size-3"
|
|
354
|
+
aria-hidden
|
|
355
|
+
/>
|
|
356
|
+
Templates
|
|
357
|
+
</SheetTextToggle>
|
|
358
|
+
</div>
|
|
359
|
+
<Input
|
|
360
|
+
value={name}
|
|
361
|
+
onChange={(event) => setName(event.target.value)}
|
|
362
|
+
placeholder="read_all"
|
|
363
|
+
aria-label="Policy name"
|
|
364
|
+
flat
|
|
365
|
+
className={cn(SHEET_CONTROL, "font-mono")}
|
|
366
|
+
/>
|
|
367
|
+
</div>
|
|
368
|
+
<SheetPair>
|
|
369
|
+
<SheetField label="Table" split="start">
|
|
370
|
+
<Select value={table} onValueChange={setPolicyTable}>
|
|
371
|
+
<SelectTrigger flat className={cn(SHEET_CONTROL, "font-mono")}>
|
|
372
|
+
<SelectValue placeholder="Select a table" />
|
|
373
|
+
</SelectTrigger>
|
|
374
|
+
<SelectContent>
|
|
375
|
+
{tables.map((item) => (
|
|
376
|
+
<SelectItem key={item} value={item} className="font-mono text-[12px]">
|
|
377
|
+
{item}
|
|
378
|
+
</SelectItem>
|
|
379
|
+
))}
|
|
380
|
+
</SelectContent>
|
|
381
|
+
</Select>
|
|
382
|
+
</SheetField>
|
|
383
|
+
<SheetField label="Behavior" split="end">
|
|
384
|
+
<Select
|
|
385
|
+
value={behavior}
|
|
386
|
+
onValueChange={(next) => setBehavior(next as SqlPolicyBehavior)}
|
|
387
|
+
>
|
|
388
|
+
<SelectTrigger flat className={SHEET_CONTROL}>
|
|
389
|
+
<SelectValue />
|
|
390
|
+
</SelectTrigger>
|
|
391
|
+
<SelectContent>
|
|
392
|
+
<SelectItem value="PERMISSIVE">Permissive</SelectItem>
|
|
393
|
+
<SelectItem value="RESTRICTIVE">Restrictive</SelectItem>
|
|
394
|
+
</SelectContent>
|
|
395
|
+
</Select>
|
|
396
|
+
</SheetField>
|
|
397
|
+
</SheetPair>
|
|
398
|
+
<SheetChapter label="Gate" hint="Who this policy pairs with" />
|
|
399
|
+
<GateSection
|
|
400
|
+
advanced={advanced}
|
|
401
|
+
onAdvancedChange={setAdvanced}
|
|
402
|
+
mode={gateMode}
|
|
403
|
+
onModeChange={setGateMode}
|
|
404
|
+
catalog={catalog}
|
|
405
|
+
query={gateQuery}
|
|
406
|
+
onQueryChange={setGateQuery}
|
|
407
|
+
selection={selection}
|
|
408
|
+
onToggleGate={toggleGate}
|
|
379
409
|
/>
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
410
|
+
{advanced || gateMode === "write" ? (
|
|
411
|
+
<CommandRow
|
|
412
|
+
commands={advanced ? RLS_POLICY_COMMANDS : WRITE_COMMANDS}
|
|
413
|
+
value={command}
|
|
414
|
+
onChange={setPolicyCommand}
|
|
415
|
+
/>
|
|
416
|
+
) : null}
|
|
417
|
+
<SheetChapter
|
|
418
|
+
label="Rows"
|
|
419
|
+
hint={
|
|
420
|
+
predicates.using && predicates.withCheck
|
|
421
|
+
? "Existing rows and new rows"
|
|
422
|
+
: predicates.withCheck
|
|
423
|
+
? "New rows"
|
|
424
|
+
: "Existing rows"
|
|
425
|
+
}
|
|
388
426
|
/>
|
|
427
|
+
{showIdentitySelect ? (
|
|
428
|
+
<SheetField label="Column" hint="compared to oke.user()">
|
|
429
|
+
<Select value={identityValue} onValueChange={setIdentityColumn}>
|
|
430
|
+
<SelectTrigger
|
|
431
|
+
flat
|
|
432
|
+
className={cn(SHEET_CONTROL, "font-mono")}
|
|
433
|
+
data-slot="rls-identity-column"
|
|
434
|
+
>
|
|
435
|
+
<SelectValue placeholder="Select a column" />
|
|
436
|
+
</SelectTrigger>
|
|
437
|
+
<SelectContent>
|
|
438
|
+
{tableColumns.map((col) => (
|
|
439
|
+
<SelectItem key={col.sqlName} value={col.sqlName}>
|
|
440
|
+
<span className="flex min-w-0 items-center gap-2">
|
|
441
|
+
<SchemaColumnMarks
|
|
442
|
+
primaryKey={col.primaryKey}
|
|
443
|
+
foreignKey={col.foreignKey}
|
|
444
|
+
unique={col.unique}
|
|
445
|
+
inferred={col.inferred}
|
|
446
|
+
/>
|
|
447
|
+
<span className="min-w-0 truncate font-mono text-[12px]">
|
|
448
|
+
{col.sqlName}
|
|
449
|
+
</span>
|
|
450
|
+
</span>
|
|
451
|
+
</SelectItem>
|
|
452
|
+
))}
|
|
453
|
+
</SelectContent>
|
|
454
|
+
</Select>
|
|
455
|
+
</SheetField>
|
|
456
|
+
) : null}
|
|
457
|
+
{predicates.using ? (
|
|
458
|
+
<SheetField label="USING">
|
|
459
|
+
<Input
|
|
460
|
+
value={using}
|
|
461
|
+
onChange={(event) => setUsing(event.target.value)}
|
|
462
|
+
placeholder="true"
|
|
463
|
+
flat
|
|
464
|
+
className={cn(SHEET_CONTROL, "font-mono")}
|
|
465
|
+
/>
|
|
466
|
+
</SheetField>
|
|
467
|
+
) : null}
|
|
468
|
+
{predicates.withCheck ? (
|
|
469
|
+
<SheetField label="WITH CHECK">
|
|
470
|
+
<Input
|
|
471
|
+
value={withCheck}
|
|
472
|
+
onChange={(event) => setWithCheck(event.target.value)}
|
|
473
|
+
placeholder="true"
|
|
474
|
+
flat
|
|
475
|
+
className={cn(SHEET_CONTROL, "font-mono")}
|
|
476
|
+
/>
|
|
477
|
+
</SheetField>
|
|
478
|
+
) : null}
|
|
479
|
+
</div>
|
|
480
|
+
</ResizablePanel>
|
|
481
|
+
<ResizableHandle withHandle data-slot="rls-policy-sql-handle" />
|
|
482
|
+
<ResizablePanel defaultSize="32%" minSize="16%" className="min-h-0">
|
|
483
|
+
<div
|
|
484
|
+
className="flex h-full min-h-0 flex-col bg-muted/15"
|
|
485
|
+
data-slot="rls-policy-sql-dock"
|
|
486
|
+
>
|
|
487
|
+
<div className="flex items-center justify-between gap-3 px-4 py-2">
|
|
488
|
+
<div className="flex items-center gap-2">
|
|
489
|
+
<button
|
|
490
|
+
type="button"
|
|
491
|
+
className={cn(
|
|
492
|
+
"text-[10px] font-semibold tracking-[0.12em] uppercase",
|
|
493
|
+
dock === "sql" ? "text-foreground" : "text-muted-foreground",
|
|
494
|
+
)}
|
|
495
|
+
onClick={() => setDock("sql")}
|
|
496
|
+
>
|
|
497
|
+
SQL
|
|
498
|
+
</button>
|
|
499
|
+
<button
|
|
500
|
+
type="button"
|
|
501
|
+
className={cn(
|
|
502
|
+
"text-[10px] font-semibold tracking-[0.12em] uppercase",
|
|
503
|
+
dock === "code" ? "text-foreground" : "text-muted-foreground",
|
|
504
|
+
)}
|
|
505
|
+
onClick={() => setDock("code")}
|
|
506
|
+
>
|
|
507
|
+
Code
|
|
508
|
+
</button>
|
|
509
|
+
</div>
|
|
510
|
+
<label className="inline-flex items-center gap-2">
|
|
511
|
+
<span className="text-[11px] text-muted-foreground">Enable RLS</span>
|
|
512
|
+
<Switch
|
|
513
|
+
size="sm"
|
|
514
|
+
checked={enableRls}
|
|
515
|
+
onCheckedChange={setEnableRls}
|
|
516
|
+
ariaLabel="Enable RLS on this table"
|
|
517
|
+
/>
|
|
518
|
+
</label>
|
|
519
|
+
</div>
|
|
520
|
+
{preview ? (
|
|
521
|
+
<div className="min-h-0 flex-1 overflow-y-auto px-4 pb-3">
|
|
522
|
+
<AgentCode
|
|
523
|
+
code={dock === "sql" ? preview.sql : preview.code}
|
|
524
|
+
language={dock === "sql" ? "sql" : "typescript"}
|
|
525
|
+
className="overflow-visible whitespace-pre-wrap break-words text-[11px] leading-relaxed"
|
|
526
|
+
/>
|
|
527
|
+
</div>
|
|
528
|
+
) : (
|
|
529
|
+
<p className="min-h-0 flex-1 px-4 pb-3 text-[11px] text-muted-foreground">
|
|
530
|
+
Fill name, table, and an expression.
|
|
531
|
+
</p>
|
|
532
|
+
)}
|
|
533
|
+
{ownerUnbound ? (
|
|
534
|
+
<SheetError slot="rls-owner-missing">
|
|
535
|
+
Pick a column on {table} — this table has no owner / owner_email / creator_email
|
|
536
|
+
guess.
|
|
537
|
+
</SheetError>
|
|
538
|
+
) : null}
|
|
539
|
+
{error ? <SheetError>{error}</SheetError> : null}
|
|
389
540
|
</div>
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
Fill name, table, and an expression.
|
|
393
|
-
</p>
|
|
394
|
-
)}
|
|
395
|
-
{error ? <SheetError>{error}</SheetError> : null}
|
|
396
|
-
</div>
|
|
541
|
+
</ResizablePanel>
|
|
542
|
+
</ResizablePanelGroup>
|
|
397
543
|
<SheetFooter>
|
|
398
544
|
<SheetFooterButton split onClick={() => onOpenChange(false)}>
|
|
399
545
|
Cancel
|
|
400
546
|
</SheetFooterButton>
|
|
401
547
|
<SheetFooterButton
|
|
402
548
|
variant="default"
|
|
403
|
-
disabled={edit.isPending || !preview}
|
|
549
|
+
disabled={edit.isPending || !preview || ownerUnbound}
|
|
404
550
|
onClick={() => void submit()}
|
|
405
551
|
>
|
|
406
552
|
{edit.isPending ? "Creating…" : "Create policy"}
|
|
@@ -418,6 +564,7 @@ export function RlsPolicySheet({
|
|
|
418
564
|
onQueryChange={setTemplateQuery}
|
|
419
565
|
selectedId={templateId}
|
|
420
566
|
onSelect={applyTemplate}
|
|
567
|
+
onClose={() => setTemplatesOpen(false)}
|
|
421
568
|
/>
|
|
422
569
|
</aside>
|
|
423
570
|
) : null}
|
|
@@ -439,34 +586,48 @@ function PolicyTemplateLibrary({
|
|
|
439
586
|
onQueryChange,
|
|
440
587
|
selectedId,
|
|
441
588
|
onSelect,
|
|
589
|
+
onClose,
|
|
442
590
|
}: {
|
|
443
591
|
readonly query: string;
|
|
444
592
|
readonly onQueryChange: (query: string) => void;
|
|
445
593
|
readonly selectedId: string | null;
|
|
446
594
|
readonly onSelect: (tpl: RlsPolicyTemplate) => void;
|
|
595
|
+
readonly onClose: () => void;
|
|
447
596
|
}): JSX.Element {
|
|
448
597
|
const visible = filterRlsPolicyTemplates(RLS_POLICY_TEMPLATES, query);
|
|
449
598
|
return (
|
|
450
599
|
<div className="flex min-h-0 flex-1 flex-col" data-slot="rls-policy-templates">
|
|
451
|
-
<div className="shrink-0 border-b border-border/
|
|
452
|
-
<
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
<
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
600
|
+
<div className="flex shrink-0 items-stretch border-b border-border/60">
|
|
601
|
+
<div className="min-w-0 flex-1">
|
|
602
|
+
<p className="px-3 pt-2.5 text-[10px] font-semibold tracking-[0.12em] text-muted-foreground uppercase">
|
|
603
|
+
Templates
|
|
604
|
+
</p>
|
|
605
|
+
<label className="relative block">
|
|
606
|
+
<HugeiconsIcon
|
|
607
|
+
icon={Search01Icon}
|
|
608
|
+
className="pointer-events-none absolute top-1/2 left-3 size-3.5 -translate-y-1/2 text-muted-foreground"
|
|
609
|
+
aria-hidden
|
|
610
|
+
/>
|
|
611
|
+
<Input
|
|
612
|
+
value={query}
|
|
613
|
+
onChange={(event) => onQueryChange(event.target.value)}
|
|
614
|
+
placeholder="Search templates"
|
|
615
|
+
aria-label="Search templates"
|
|
616
|
+
flat
|
|
617
|
+
className={cn(SHEET_SEARCH, "font-mono")}
|
|
618
|
+
/>
|
|
619
|
+
</label>
|
|
620
|
+
</div>
|
|
621
|
+
<span className="w-px shrink-0 self-stretch bg-border/60" aria-hidden />
|
|
622
|
+
<button
|
|
623
|
+
type="button"
|
|
624
|
+
className={cn(EXPLORER_ICON_BUTTON_CLASS, "min-w-11")}
|
|
625
|
+
onClick={onClose}
|
|
626
|
+
aria-label="Close templates"
|
|
627
|
+
data-slot="rls-policy-templates-close"
|
|
628
|
+
>
|
|
629
|
+
<HugeiconsIcon icon={Cancel01Icon} className="size-4" aria-hidden />
|
|
630
|
+
</button>
|
|
470
631
|
</div>
|
|
471
632
|
<ul className="min-h-0 flex-1 overflow-y-auto p-2">
|
|
472
633
|
{visible.length === 0 ? (
|
|
@@ -33,6 +33,8 @@ export interface SqlInsertSheetProps {
|
|
|
33
33
|
readonly childName: string;
|
|
34
34
|
readonly tenant?: string | null;
|
|
35
35
|
readonly columns: readonly StoreGridColumn[];
|
|
36
|
+
readonly asGate?: string | null;
|
|
37
|
+
readonly asUserId?: string | null;
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
/**
|
|
@@ -47,6 +49,8 @@ export function SqlInsertSheet({
|
|
|
47
49
|
childName,
|
|
48
50
|
tenant,
|
|
49
51
|
columns,
|
|
52
|
+
asGate = null,
|
|
53
|
+
asUserId = null,
|
|
50
54
|
}: SqlInsertSheetProps): JSX.Element {
|
|
51
55
|
const { mutate, isPending, reset } = useStoreEdit();
|
|
52
56
|
const fields = useMemo(() => insertFormColumns(columns), [columns]);
|
|
@@ -77,6 +81,8 @@ export function SqlInsertSheet({
|
|
|
77
81
|
ref: storeRef,
|
|
78
82
|
child: childName,
|
|
79
83
|
...(tenant ? { tenant } : {}),
|
|
84
|
+
...(asGate ? { asGate } : {}),
|
|
85
|
+
...(asUserId ? { asUserId } : {}),
|
|
80
86
|
patch: built.patch,
|
|
81
87
|
commit: true,
|
|
82
88
|
},
|