@supabase/lite 0.8.0 → 0.8.1-next.1

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.
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "dev/vite/main.tsx": {
3
- "file": "assets/main-DO_xnvTw.js",
3
+ "file": "assets/main-1bwWb_1q.js",
4
4
  "name": "main",
5
5
  "src": "dev/vite/main.tsx",
6
6
  "isEntry": true,
7
7
  "css": [
8
- "assets/main-BITGMylP.css"
8
+ "assets/main-BDsRycsc.css"
9
9
  ]
10
10
  }
11
11
  }
@@ -28220,9 +28220,7 @@ function Studio({
28220
28220
  ),
28221
28221
  /* @__PURE__ */ jsxRuntimeExports.jsx(Button$1, { type: "dashed", className: "h-[28px] px-1.5", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(Funnel, {}) })
28222
28222
  ] }),
28223
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-col grow gap-0", children: entities?.filter(
28224
- (entity) => entity.schema === selectedSchema || selectedSchema === "public" && entity.schema === ""
28225
- ).map((entity) => /* @__PURE__ */ jsxRuntimeExports.jsx(
28223
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-col grow gap-0", children: entities?.filter((entity) => entity.schema === selectedSchema).map((entity) => /* @__PURE__ */ jsxRuntimeExports.jsx(
28226
28224
  EntityListItem,
28227
28225
  {
28228
28226
  id: entityActiveId,
@@ -40342,15 +40340,82 @@ function shouldShowDeprecationWarning() {
40342
40340
  return parseInt(versionMatch[1], 10) <= 18;
40343
40341
  }
40344
40342
  if (shouldShowDeprecationWarning()) console.warn("⚠️ Node.js 18 and below are deprecated and will no longer be supported in future versions of @supabase/supabase-js. Please upgrade to Node.js 20 or later. For more information, visit: https://github.com/orgs/supabase/discussions/37217");
40343
+ const STRIPPED_HEADERS = ["apikey", "authorization"];
40344
+ function studioAuth(runtime) {
40345
+ if (runtime.admin) {
40346
+ return { mode: "admin", key: "...", fetch: keylessFetch };
40347
+ }
40348
+ if (runtime.publishableKey) {
40349
+ return { mode: "restricted", key: runtime.publishableKey };
40350
+ }
40351
+ return {
40352
+ mode: "unavailable",
40353
+ reason: "Admin mode is off and no publishable key is configured, so studio has no credential it can use from the browser. Restart without --no-admin, or add auth.publishable_key (`lite generate-keys`)."
40354
+ };
40355
+ }
40356
+ const keylessFetch = (input, init) => {
40357
+ if (input instanceof Request) {
40358
+ const request = new Request(input, init);
40359
+ for (const name of STRIPPED_HEADERS) request.headers.delete(name);
40360
+ return fetch(request);
40361
+ }
40362
+ const headers = new Headers(init?.headers);
40363
+ for (const name of STRIPPED_HEADERS) headers.delete(name);
40364
+ return fetch(input, { ...init, headers });
40365
+ };
40345
40366
  const StudioContext = reactExports.createContext({});
40346
40367
  function StudioProvider({
40347
40368
  children,
40348
40369
  baseUrl,
40349
40370
  anonKey
40350
40371
  }) {
40351
- const api = hc(baseUrl);
40352
- const client2 = createClient(baseUrl, anonKey ?? "...");
40353
- return /* @__PURE__ */ jsxRuntimeExports.jsx(StudioContext.Provider, { value: { api, client: client2 }, children });
40372
+ const api = reactExports.useMemo(() => hc(baseUrl), [baseUrl]);
40373
+ const [runtime, setRuntime] = reactExports.useState(null);
40374
+ reactExports.useEffect(() => {
40375
+ let cancelled = false;
40376
+ void (async () => {
40377
+ try {
40378
+ const res = await fetch(`${baseUrl}/_system/info`);
40379
+ const info = await res.json();
40380
+ if (!cancelled) {
40381
+ setRuntime({
40382
+ admin: info.admin === true,
40383
+ publishableKey: anonKey ?? info.config?.auth?.publishable_key
40384
+ });
40385
+ }
40386
+ } catch {
40387
+ if (!cancelled) setRuntime({ admin: false, publishableKey: anonKey });
40388
+ }
40389
+ })();
40390
+ return () => {
40391
+ cancelled = true;
40392
+ };
40393
+ }, [baseUrl, anonKey]);
40394
+ const value = reactExports.useMemo(() => {
40395
+ if (!runtime) return null;
40396
+ const auth = studioAuth(runtime);
40397
+ if (auth.mode === "unavailable") return { unavailable: auth.reason };
40398
+ const client2 = createClient(baseUrl, auth.key, {
40399
+ ...auth.mode === "admin" ? { global: { fetch: auth.fetch } } : {},
40400
+ // Studio shares an origin with the user's app under `lite dev`;
40401
+ // picking their session out of localStorage would attach a user JWT
40402
+ // and silently opt studio out of admin elevation.
40403
+ auth: {
40404
+ persistSession: false,
40405
+ autoRefreshToken: false,
40406
+ detectSessionInUrl: false
40407
+ }
40408
+ });
40409
+ return { api, client: client2, restricted: auth.mode === "restricted" };
40410
+ }, [api, baseUrl, runtime]);
40411
+ if (!value) return null;
40412
+ if ("unavailable" in value) {
40413
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mx-auto max-w-xl p-8 text-sm text-foreground-light", children: [
40414
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h1", { className: "pb-2 text-base text-foreground", children: "Studio is unavailable" }),
40415
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: value.unavailable })
40416
+ ] });
40417
+ }
40418
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(StudioContext.Provider, { value, children });
40354
40419
  }
40355
40420
  function useStudioContext() {
40356
40421
  return reactExports.useContext(StudioContext);
@@ -40358,13 +40423,24 @@ function useStudioContext() {
40358
40423
  async function getDbIntrospection(api) {
40359
40424
  return await api._system.introspect.$get().then((res) => res.json());
40360
40425
  }
40426
+ const DEFAULT_SCHEMA = "public";
40427
+ function normalizeIntrospection(raw) {
40428
+ const out = { ...raw };
40429
+ for (const [key, value] of Object.entries(raw)) {
40430
+ if (!Array.isArray(value)) continue;
40431
+ out[key] = value.map(
40432
+ (item) => item && typeof item === "object" && "schema" in item && !item.schema ? { ...item, schema: DEFAULT_SCHEMA } : item
40433
+ );
40434
+ }
40435
+ return out;
40436
+ }
40361
40437
  function useDbInfo() {
40362
40438
  const { api } = useStudioContext();
40363
40439
  const [raw, setRaw] = reactExports.useState(null);
40364
40440
  reactExports.useEffect(() => {
40365
40441
  (async () => {
40366
40442
  const res = await getDbIntrospection(api);
40367
- setRaw(res);
40443
+ setRaw(normalizeIntrospection(res));
40368
40444
  })();
40369
40445
  }, []);
40370
40446
  return {
@@ -40372,7 +40448,7 @@ function useDbInfo() {
40372
40448
  entities: raw?.tables?.map((table, index2) => ({
40373
40449
  id: index2,
40374
40450
  name: table.name,
40375
- schema: table.schema ?? "public",
40451
+ schema: table.schema,
40376
40452
  type: "r"
40377
40453
  }))
40378
40454
  };
@@ -40710,7 +40786,7 @@ function Impl() {
40710
40786
  const [selectedEntity, setSelectedEntity] = reactExports.useState(void 0);
40711
40787
  const [rows, setRows] = reactExports.useState([]);
40712
40788
  const [columns, setColumns] = reactExports.useState([]);
40713
- const { client: client2 } = useStudioContext();
40789
+ const { client: client2, restricted } = useStudioContext();
40714
40790
  const [insertPanelOpen, setInsertPanelOpen] = reactExports.useState(false);
40715
40791
  const [insertLoading, setInsertLoading] = reactExports.useState(false);
40716
40792
  const [insertValues, setInsertValues] = reactExports.useState({});
@@ -40776,7 +40852,7 @@ function Impl() {
40776
40852
  window.alert("No entity selected, cannot insert row");
40777
40853
  return;
40778
40854
  }
40779
- const tableSchema = selectedEntity.schema ?? schema;
40855
+ const tableSchema = selectedEntity.schema || schema;
40780
40856
  setInsertLoading(true);
40781
40857
  try {
40782
40858
  const { data, error } = await client2.schema(tableSchema).from(selectedEntity.name).insert(payload).select("*");
@@ -40817,9 +40893,7 @@ function Impl() {
40817
40893
  } else if (entity.includes(".")) {
40818
40894
  const [schema2, table] = entity.split(".");
40819
40895
  console.log("entities", entities);
40820
- setSelectedEntity(
40821
- entities?.find((e) => e.name === table && (e.schema === schema2 || e.schema === ""))
40822
- );
40896
+ setSelectedEntity(entities?.find((e) => e.name === table && e.schema === schema2));
40823
40897
  } else if (raw.tables.some((t) => t.schema === "public")) {
40824
40898
  setSelectedEntity(entities?.find((e) => e.name === entity));
40825
40899
  }
@@ -40850,6 +40924,18 @@ function Impl() {
40850
40924
  Boolean
40851
40925
  );
40852
40926
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
40927
+ restricted && // Admin mode off → studio authenticates as `anon`, so RLS applies
40928
+ // and rows/writes the policies hide will simply be missing. Say so,
40929
+ // rather than letting it look like an empty or broken table.
40930
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border-b border-amber-600/40 bg-amber-500/10 px-4 py-2 text-sm text-foreground-light", children: [
40931
+ "Admin mode is off, so studio is connected with the publishable key and sees only what",
40932
+ " ",
40933
+ /* @__PURE__ */ jsxRuntimeExports.jsx("code", { className: "font-mono", children: "anon" }),
40934
+ " may see under RLS. Restart without",
40935
+ " ",
40936
+ /* @__PURE__ */ jsxRuntimeExports.jsx("code", { className: "font-mono", children: "--no-admin" }),
40937
+ " for full access."
40938
+ ] }),
40853
40939
  /* @__PURE__ */ jsxRuntimeExports.jsx(
40854
40940
  SidePanel,
40855
40941
  {
@@ -40895,10 +40981,7 @@ function Impl() {
40895
40981
  onOpenInsertPanel: () => setInsertPanelOpen(true),
40896
40982
  onEntityClick: (entity2) => {
40897
40983
  setSelectedEntity(entity2);
40898
- const path = [
40899
- entity2.schema && entity2.schema.length > 0 ? entity2.schema : "public",
40900
- entity2.name
40901
- ].filter(Boolean).join(".");
40984
+ const path = [entity2.schema, entity2.name].filter(Boolean).join(".");
40902
40985
  navigate2(`/${path}`);
40903
40986
  },
40904
40987
  schema,
@@ -132,6 +132,8 @@
132
132
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
133
133
  "Courier New", monospace;
134
134
  --color-red-500: oklch(63.7% .237 25.331);
135
+ --color-amber-500: oklch(76.9% .188 70.08);
136
+ --color-amber-600: oklch(66.6% .179 58.318);
135
137
  --color-amber-700: oklch(55.5% .163 48.998);
136
138
  --color-yellow-500: oklch(79.5% .184 86.047);
137
139
  --color-yellow-900: oklch(42.1% .095 57.708);
@@ -139,6 +141,7 @@
139
141
  --color-purple-500: oklch(62.7% .265 303.9);
140
142
  --spacing: .25rem;
141
143
  --container-md: 28rem;
144
+ --container-xl: 36rem;
142
145
  --container-2xl: 42rem;
143
146
  --container-3xl: 48rem;
144
147
  --container-4xl: 56rem;
@@ -653,6 +656,10 @@
653
656
  margin-inline: 2px;
654
657
  }
655
658
 
659
+ .mx-auto {
660
+ margin-inline: auto;
661
+ }
662
+
656
663
  .my-0\.5 {
657
664
  margin-block: calc(var(--spacing) * .5);
658
665
  }
@@ -1067,6 +1074,10 @@
1067
1074
  max-width: 100vw;
1068
1075
  }
1069
1076
 
1077
+ .max-w-xl {
1078
+ max-width: var(--container-xl);
1079
+ }
1080
+
1070
1081
  .min-w-0 {
1071
1082
  min-width: calc(var(--spacing) * 0);
1072
1083
  }
@@ -1361,6 +1372,16 @@
1361
1372
  border-style: dashed;
1362
1373
  }
1363
1374
 
1375
+ .border-amber-600\/40 {
1376
+ border-color: #dd740066;
1377
+ }
1378
+
1379
+ @supports (color: color-mix(in lab, red, red)) {
1380
+ .border-amber-600\/40 {
1381
+ border-color: color-mix(in oklab, var(--color-amber-600) 40%, transparent);
1382
+ }
1383
+ }
1384
+
1364
1385
  .border-border-default {
1365
1386
  border-color: var(--color-border-default);
1366
1387
  }
@@ -1419,6 +1440,16 @@
1419
1440
  background-color: var(--color-background-alternative);
1420
1441
  }
1421
1442
 
1443
+ .bg-amber-500\/10 {
1444
+ background-color: #f99c001a;
1445
+ }
1446
+
1447
+ @supports (color: color-mix(in lab, red, red)) {
1448
+ .bg-amber-500\/10 {
1449
+ background-color: color-mix(in oklab, var(--color-amber-500) 10%, transparent);
1450
+ }
1451
+ }
1452
+
1422
1453
  .bg-background {
1423
1454
  background-color: var(--color-background);
1424
1455
  }
@@ -1547,6 +1578,10 @@
1547
1578
  padding: calc(var(--spacing) * 4);
1548
1579
  }
1549
1580
 
1581
+ .p-8 {
1582
+ padding: calc(var(--spacing) * 8);
1583
+ }
1584
+
1550
1585
  .px-1 {
1551
1586
  padding-inline: calc(var(--spacing) * 1);
1552
1587
  }
@@ -1643,6 +1678,10 @@
1643
1678
  padding-right: calc(var(--spacing) * 7);
1644
1679
  }
1645
1680
 
1681
+ .pb-2 {
1682
+ padding-bottom: calc(var(--spacing) * 2);
1683
+ }
1684
+
1646
1685
  .pb-4 {
1647
1686
  padding-bottom: calc(var(--spacing) * 4);
1648
1687
  }