@guard-rail/core 0.1.1 → 0.2.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.
- package/README.md +63 -3
- package/dist/cli/seed-user.d.ts +1 -0
- package/dist/cli/seed-user.js +105 -0
- package/dist/cli/seed-user.js.map +1 -0
- package/dist/react/Admin.d.ts +6 -1
- package/dist/react/Admin.js +14 -6
- package/dist/react/Admin.js.map +1 -1
- package/dist/react/GRail/client.js +87 -16
- package/dist/react/GRail/client.js.map +1 -1
- package/dist/react/Icons.d.ts +2 -1
- package/dist/react/Icons.js +5 -0
- package/dist/react/Icons.js.map +1 -1
- package/dist/react/MediaPicker.js +3 -3
- package/dist/react/MediaPicker.js.map +1 -1
- package/dist/react/Repeater/client.js +2 -2
- package/dist/react/Repeater/client.js.map +1 -1
- package/dist/react/Team.js +6 -6
- package/dist/react/Team.js.map +1 -1
- package/dist/react/styles.d.ts +104 -30
- package/dist/react/styles.js +154 -65
- package/dist/react/styles.js.map +1 -1
- package/dist/react/useAnchorRect.js +1 -0
- package/dist/react/useAnchorRect.js.map +1 -1
- package/package.json +9 -3
- package/scripts/postinstall.mjs +48 -0
- package/supabase/migrations/20260911000000_guardrail_init.sql +17 -8
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// Plain, already-final JS — deliberately NOT part of the tsup build. A
|
|
2
|
+
// postinstall script has to exist the instant npm/pnpm/yarn extracts the
|
|
3
|
+
// package, with no dependency on a build step having run yet, which would
|
|
4
|
+
// otherwise race tsup during this very monorepo's own installs (lifecycle
|
|
5
|
+
// script ordering between "postinstall" and "prepare" isn't a guarantee
|
|
6
|
+
// worth relying on).
|
|
7
|
+
//
|
|
8
|
+
// Runs after `npm install @guard-rail/core` in a consuming project — just
|
|
9
|
+
// onboarding guidance, easy to miss otherwise among the rest of an install's
|
|
10
|
+
// output.
|
|
11
|
+
//
|
|
12
|
+
// Deliberately silent in two cases:
|
|
13
|
+
// - CI: this is guidance for a human at a keyboard, not something that
|
|
14
|
+
// belongs in build logs.
|
|
15
|
+
// - Running inside this very monorepo: pnpm runs a workspace package's own
|
|
16
|
+
// lifecycle scripts too (already visible via the "prepare" build step on
|
|
17
|
+
// every `pnpm install`), which would otherwise print this on every
|
|
18
|
+
// contributor's install of this repo, not just a real consumer's. Resolved
|
|
19
|
+
// through the pnpm workspace symlink, this file's own real path sits under
|
|
20
|
+
// packages/guardrail/ — never inside a node_modules/ — which a real
|
|
21
|
+
// consumer's install always does.
|
|
22
|
+
import { fileURLToPath } from "node:url";
|
|
23
|
+
|
|
24
|
+
const isRealInstall = fileURLToPath(import.meta.url).includes("node_modules");
|
|
25
|
+
|
|
26
|
+
if (isRealInstall && !process.env.CI) {
|
|
27
|
+
console.log(`
|
|
28
|
+
Guardrail installed. Next steps:
|
|
29
|
+
|
|
30
|
+
1. Set up the database (skip both if this Supabase project already has
|
|
31
|
+
Guardrail applied for another site — see "Many sites, one Supabase
|
|
32
|
+
project" in the README):
|
|
33
|
+
- Copy node_modules/@guard-rail/core/supabase/migrations/*.sql into
|
|
34
|
+
your own supabase/migrations/, then \`supabase db push\`.
|
|
35
|
+
- Add "guardrail" under Settings > API > Exposed schemas in the
|
|
36
|
+
Supabase dashboard.
|
|
37
|
+
|
|
38
|
+
2. Wrap your root layout with withGuardrail and mark fields with <GRail>.
|
|
39
|
+
Full guide: https://www.npmjs.com/package/@guard-rail/core
|
|
40
|
+
|
|
41
|
+
3. Once SUPABASE_URL / SUPABASE_ANON_KEY are set, seed yourself as the
|
|
42
|
+
first admin on a site (needs the service_role key, not the anon key —
|
|
43
|
+
Settings > API in the dashboard; pass it inline, don't store it):
|
|
44
|
+
|
|
45
|
+
SERVICE_KEY=... npx guardrail-seed-user \\
|
|
46
|
+
--email=you@example.com --password=... --site-id=my-site
|
|
47
|
+
`);
|
|
48
|
+
}
|
|
@@ -17,7 +17,12 @@
|
|
|
17
17
|
-- sufficient — keep both.
|
|
18
18
|
|
|
19
19
|
create schema if not exists guardrail;
|
|
20
|
-
|
|
20
|
+
-- service_role bypasses RLS (a Postgres role attribute Supabase configures
|
|
21
|
+
-- automatically), but that doesn't waive ordinary schema/table grants —
|
|
22
|
+
-- without this, any service_role-authenticated call (guardrail-seed-user,
|
|
23
|
+
-- say) fails with "permission denied for schema guardrail" despite using
|
|
24
|
+
-- the right key entirely.
|
|
25
|
+
grant usage on schema guardrail to anon, authenticated, service_role;
|
|
21
26
|
|
|
22
27
|
/* ------------------------------------------------------------- members --- */
|
|
23
28
|
|
|
@@ -38,7 +43,7 @@ alter table guardrail.gr_members enable row level security;
|
|
|
38
43
|
-- Anon has no legitimate reason to read team membership, so it gets no grant
|
|
39
44
|
-- at all here (unlike gr_content, which anonymous visitors must be able to
|
|
40
45
|
-- read to render the site).
|
|
41
|
-
grant select, insert, update, delete on guardrail.gr_members to authenticated;
|
|
46
|
+
grant select, insert, update, delete on guardrail.gr_members to authenticated, service_role;
|
|
42
47
|
|
|
43
48
|
-- Does the current user hold one of these roles on this site? SECURITY
|
|
44
49
|
-- DEFINER so the membership policies below can call it without recursing
|
|
@@ -121,8 +126,8 @@ create index gr_content_site_path_idx on guardrail.gr_content (site_id, path_key
|
|
|
121
126
|
|
|
122
127
|
alter table guardrail.gr_content enable row level security;
|
|
123
128
|
|
|
124
|
-
grant select on guardrail.gr_content to anon, authenticated;
|
|
125
|
-
grant insert, update, delete on guardrail.gr_content to authenticated;
|
|
129
|
+
grant select on guardrail.gr_content to anon, authenticated, service_role;
|
|
130
|
+
grant insert, update, delete on guardrail.gr_content to authenticated, service_role;
|
|
126
131
|
|
|
127
132
|
-- Anyone may read published content: this is what anonymous visitors render.
|
|
128
133
|
create policy "content is publicly readable"
|
|
@@ -179,8 +184,8 @@ create index gr_repeater_items_order_idx
|
|
|
179
184
|
|
|
180
185
|
alter table guardrail.gr_repeater_items enable row level security;
|
|
181
186
|
|
|
182
|
-
grant select on guardrail.gr_repeater_items to anon, authenticated;
|
|
183
|
-
grant insert, update, delete on guardrail.gr_repeater_items to authenticated;
|
|
187
|
+
grant select on guardrail.gr_repeater_items to anon, authenticated, service_role;
|
|
188
|
+
grant insert, update, delete on guardrail.gr_repeater_items to authenticated, service_role;
|
|
184
189
|
|
|
185
190
|
-- Anyone may enumerate items: this is what renders the page for anonymous
|
|
186
191
|
-- visitors, same reasoning as gr_content's public read policy.
|
|
@@ -289,8 +294,12 @@ grant execute on function guardrail.gr_ensure_bucket(text) to authenticated;
|
|
|
289
294
|
|
|
290
295
|
/* ----------------------------------------------------------- bootstrap --- */
|
|
291
296
|
-- A site with no members has nobody who can add members, and there is
|
|
292
|
-
-- deliberately no in-app way to grant yourself a role.
|
|
293
|
-
--
|
|
297
|
+
-- deliberately no in-app way to grant yourself a role. Prefer the bundled
|
|
298
|
+
-- `guardrail-seed-user` command (see the README's Bootstrapping section) —
|
|
299
|
+
-- it creates the account via Supabase's own Admin API if it doesn't exist
|
|
300
|
+
-- yet, rather than assuming one already does. The raw SQL below still works
|
|
301
|
+
-- if you'd rather not use the service_role key it needs, replacing both
|
|
302
|
+
-- values:
|
|
294
303
|
--
|
|
295
304
|
-- insert into guardrail.gr_members (site_id, email, user_id, role, status)
|
|
296
305
|
-- select 'your-site-id', u.email, u.id, 'admin', 'active'
|