@guard-rail/core 0.3.0 → 0.6.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.
Files changed (46) hide show
  1. package/README.md +111 -28
  2. package/dist/adapters/supabase/auth.js +50 -0
  3. package/dist/adapters/supabase/auth.js.map +1 -1
  4. package/dist/cli/init-db.d.ts +1 -0
  5. package/dist/cli/init-db.js +121 -0
  6. package/dist/cli/init-db.js.map +1 -0
  7. package/dist/core/adapter-types.d.ts +43 -1
  8. package/dist/core/defs.d.ts +43 -2
  9. package/dist/core/defs.js +29 -2
  10. package/dist/core/defs.js.map +1 -1
  11. package/dist/core/types.d.ts +16 -1
  12. package/dist/index.client.d.ts +7 -4
  13. package/dist/index.client.js +22 -1
  14. package/dist/index.client.js.map +1 -1
  15. package/dist/index.d.ts +4 -3
  16. package/dist/index.js +11 -1
  17. package/dist/index.js.map +1 -1
  18. package/dist/react/Admin.js +83 -7
  19. package/dist/react/Admin.js.map +1 -1
  20. package/dist/react/AuthRedirectSync.d.ts +20 -0
  21. package/dist/react/AuthRedirectSync.js +38 -0
  22. package/dist/react/AuthRedirectSync.js.map +1 -0
  23. package/dist/react/GRail/client.js +5 -1
  24. package/dist/react/GRail/client.js.map +1 -1
  25. package/dist/react/Provider.js +5 -1
  26. package/dist/react/Provider.js.map +1 -1
  27. package/dist/react/Syncer.d.ts +10 -8
  28. package/dist/react/Syncer.js +8 -6
  29. package/dist/react/Syncer.js.map +1 -1
  30. package/dist/react/useAnchorRect.d.ts +17 -1
  31. package/dist/react/useAnchorRect.js +37 -9
  32. package/dist/react/useAnchorRect.js.map +1 -1
  33. package/dist/server/access.d.ts +76 -0
  34. package/dist/server/access.js +33 -0
  35. package/dist/server/access.js.map +1 -0
  36. package/dist/server/actions.d.ts +49 -8
  37. package/dist/server/actions.js +65 -10
  38. package/dist/server/actions.js.map +1 -1
  39. package/dist/server/fieldData.d.ts +4 -2
  40. package/dist/server/fieldData.js.map +1 -1
  41. package/dist/server/repeaterActions.js +1 -1
  42. package/dist/server/repeaterActions.js.map +1 -1
  43. package/dist/server/wrapper.js +9 -4
  44. package/dist/server/wrapper.js.map +1 -1
  45. package/package.json +3 -2
  46. package/scripts/postinstall.mjs +4 -4
@@ -8,8 +8,8 @@ import {
8
8
  resolveSiteId
9
9
  } from "../core/config";
10
10
  import { getCachedViewer } from "./session";
11
+ import { resolveEditMode } from "./access";
11
12
  import { loadPreloadedContent } from "./loader";
12
- import { GR_COOKIES } from "../core/defs";
13
13
  import { GRailProvider } from "../react/Provider";
14
14
  import { GRailAdmin } from "../react/Admin";
15
15
  function withGuardrail(LayoutComponent, config) {
@@ -22,16 +22,21 @@ function withGuardrail(LayoutComponent, config) {
22
22
  loadPreloadedContent()
23
23
  ]);
24
24
  const auth = getAuth();
25
+ const isAuth = viewer !== null;
26
+ const { isEditMode, needsPassword } = resolveEditMode(viewer, cookieStore);
27
+ const role = viewer?.role ?? null;
25
28
  const state = {
26
29
  storage: getStorage() !== void 0,
27
30
  auth: {
28
31
  password: typeof auth.authenticate === "function",
29
32
  ...auth.signInUrl ? { signInUrl: auth.signInUrl } : {}
30
33
  },
31
- isAuth: viewer !== null,
32
- isEditMode: cookieStore.get(GR_COOKIES.EDIT_MODE)?.value === "true",
34
+ isAuth,
35
+ isEditMode,
36
+ needsPassword,
33
37
  siteId: await resolveSiteId(),
34
- role: viewer?.role ?? null,
38
+ role,
39
+ canEdit: isEditMode && role !== null,
35
40
  ...viewer?.email ? { email: viewer.email } : {}
36
41
  };
37
42
  return /* @__PURE__ */ jsxs(GRailProvider, { state, content, children: [
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/server/wrapper.tsx"],"sourcesContent":["import React, { Suspense } from \"react\";\nimport { cookies } from \"next/headers\";\nimport {\n configureGuardrail,\n getAuth,\n getStorage,\n resolveSiteId,\n} from \"../core/config\";\nimport { getCachedViewer } from \"./session\";\nimport { loadPreloadedContent } from \"./loader\";\nimport type { GRConfig } from \"../core/adapter-types\";\nimport { GR_COOKIES } from \"../core/defs\";\nimport { GRailProvider } from \"../react/Provider\";\nimport { GRailAdmin } from \"../react/Admin\";\nimport type { GRState } from \"../core/types\";\n\n/**\n * Wraps a root layout so every route carries Guardrail's edit state and admin\n * chrome. Stays a Server Component: the provider below is the client boundary.\n */\nexport function withGuardrail<P extends object>(\n LayoutComponent: React.ComponentType<P>,\n config: GRConfig,\n) {\n // Applied at module evaluation so the config is present as soon as anything\n // imports the layout, and again per render because Next.js does not\n // guarantee one shared module instance across its server contexts.\n configureGuardrail(config);\n\n return async function GuardrailLayout(props: P) {\n configureGuardrail(config);\n\n const cookieStore = await cookies();\n\n // Verified against the auth provider, not inferred from a cookie. Loaded\n // alongside the content preload: independent round trips, and the preload\n // is shared with the page's own fields, so it costs them nothing extra.\n const [viewer, content] = await Promise.all([\n getCachedViewer(),\n loadPreloadedContent(),\n ]);\n\n const auth = getAuth();\n\n const state: GRState = {\n storage: getStorage() !== undefined,\n auth: {\n password: typeof auth.authenticate === \"function\",\n ...(auth.signInUrl ? { signInUrl: auth.signInUrl } : {}),\n },\n isAuth: viewer !== null,\n isEditMode: cookieStore.get(GR_COOKIES.EDIT_MODE)?.value === \"true\",\n siteId: await resolveSiteId(),\n role: viewer?.role ?? null,\n ...(viewer?.email ? { email: viewer.email } : {}),\n };\n\n return (\n <GRailProvider state={state} content={content}>\n <LayoutComponent {...props} />\n <Suspense fallback={null}>\n <GRailAdmin toolbarExtra={config.toolbarExtra} />\n </Suspense>\n </GRailProvider>\n );\n };\n}\n"],"mappings":"AA0DM,SACE,KADF;AA1DN,OAAO,SAAS,gBAAgB;AAChC,SAAS,eAAe;AACxB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,uBAAuB;AAChC,SAAS,4BAA4B;AAErC,SAAS,kBAAkB;AAC3B,SAAS,qBAAqB;AAC9B,SAAS,kBAAkB;AAOpB,SAAS,cACd,iBACA,QACA;AAIA,qBAAmB,MAAM;AAEzB,SAAO,eAAe,gBAAgB,OAAU;AAC9C,uBAAmB,MAAM;AAEzB,UAAM,cAAc,MAAM,QAAQ;AAKlC,UAAM,CAAC,QAAQ,OAAO,IAAI,MAAM,QAAQ,IAAI;AAAA,MAC1C,gBAAgB;AAAA,MAChB,qBAAqB;AAAA,IACvB,CAAC;AAED,UAAM,OAAO,QAAQ;AAErB,UAAM,QAAiB;AAAA,MACrB,SAAS,WAAW,MAAM;AAAA,MAC1B,MAAM;AAAA,QACJ,UAAU,OAAO,KAAK,iBAAiB;AAAA,QACvC,GAAI,KAAK,YAAY,EAAE,WAAW,KAAK,UAAU,IAAI,CAAC;AAAA,MACxD;AAAA,MACA,QAAQ,WAAW;AAAA,MACnB,YAAY,YAAY,IAAI,WAAW,SAAS,GAAG,UAAU;AAAA,MAC7D,QAAQ,MAAM,cAAc;AAAA,MAC5B,MAAM,QAAQ,QAAQ;AAAA,MACtB,GAAI,QAAQ,QAAQ,EAAE,OAAO,OAAO,MAAM,IAAI,CAAC;AAAA,IACjD;AAEA,WACE,qBAAC,iBAAc,OAAc,SAC3B;AAAA,0BAAC,mBAAiB,GAAG,OAAO;AAAA,MAC5B,oBAAC,YAAS,UAAU,MAClB,8BAAC,cAAW,cAAc,OAAO,cAAc,GACjD;AAAA,OACF;AAAA,EAEJ;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/server/wrapper.tsx"],"sourcesContent":["import React, { Suspense } from \"react\";\nimport { cookies } from \"next/headers\";\nimport {\n configureGuardrail,\n getAuth,\n getStorage,\n resolveSiteId,\n} from \"../core/config\";\nimport { getCachedViewer } from \"./session\";\nimport { resolveEditMode } from \"./access\";\nimport { loadPreloadedContent } from \"./loader\";\nimport type { GRConfig } from \"../core/adapter-types\";\nimport { GRailProvider } from \"../react/Provider\";\nimport { GRailAdmin } from \"../react/Admin\";\nimport type { GRState } from \"../core/types\";\n\n/**\n * Wraps a root layout so every route carries Guardrail's edit state and admin\n * chrome. Stays a Server Component: the provider below is the client boundary.\n */\nexport function withGuardrail<P extends object>(\n LayoutComponent: React.ComponentType<P>,\n config: GRConfig,\n) {\n // Applied at module evaluation so the config is present as soon as anything\n // imports the layout, and again per render because Next.js does not\n // guarantee one shared module instance across its server contexts.\n configureGuardrail(config);\n\n return async function GuardrailLayout(props: P) {\n configureGuardrail(config);\n\n const cookieStore = await cookies();\n\n // Verified against the auth provider, not inferred from a cookie. Loaded\n // alongside the content preload: independent round trips, and the preload\n // is shared with the page's own fields, so it costs them nothing extra.\n const [viewer, content] = await Promise.all([\n getCachedViewer(),\n loadPreloadedContent(),\n ]);\n\n const auth = getAuth();\n\n // The rule for what counts as \"in edit mode\" lives in resolveEditMode —\n // shared with canEdit() so the layout and the server helper can't disagree.\n const isAuth = viewer !== null;\n const { isEditMode, needsPassword } = resolveEditMode(viewer, cookieStore);\n const role = viewer?.role ?? null;\n\n const state: GRState = {\n storage: getStorage() !== undefined,\n auth: {\n password: typeof auth.authenticate === \"function\",\n ...(auth.signInUrl ? { signInUrl: auth.signInUrl } : {}),\n },\n isAuth,\n isEditMode,\n needsPassword,\n siteId: await resolveSiteId(),\n role,\n canEdit: isEditMode && role !== null,\n ...(viewer?.email ? { email: viewer.email } : {}),\n };\n\n return (\n <GRailProvider state={state} content={content}>\n <LayoutComponent {...props} />\n <Suspense fallback={null}>\n <GRailAdmin toolbarExtra={config.toolbarExtra} />\n </Suspense>\n </GRailProvider>\n );\n };\n}\n"],"mappings":"AAkEM,SACE,KADF;AAlEN,OAAO,SAAS,gBAAgB;AAChC,SAAS,eAAe;AACxB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,uBAAuB;AAChC,SAAS,uBAAuB;AAChC,SAAS,4BAA4B;AAErC,SAAS,qBAAqB;AAC9B,SAAS,kBAAkB;AAOpB,SAAS,cACd,iBACA,QACA;AAIA,qBAAmB,MAAM;AAEzB,SAAO,eAAe,gBAAgB,OAAU;AAC9C,uBAAmB,MAAM;AAEzB,UAAM,cAAc,MAAM,QAAQ;AAKlC,UAAM,CAAC,QAAQ,OAAO,IAAI,MAAM,QAAQ,IAAI;AAAA,MAC1C,gBAAgB;AAAA,MAChB,qBAAqB;AAAA,IACvB,CAAC;AAED,UAAM,OAAO,QAAQ;AAIrB,UAAM,SAAS,WAAW;AAC1B,UAAM,EAAE,YAAY,cAAc,IAAI,gBAAgB,QAAQ,WAAW;AACzE,UAAM,OAAO,QAAQ,QAAQ;AAE7B,UAAM,QAAiB;AAAA,MACrB,SAAS,WAAW,MAAM;AAAA,MAC1B,MAAM;AAAA,QACJ,UAAU,OAAO,KAAK,iBAAiB;AAAA,QACvC,GAAI,KAAK,YAAY,EAAE,WAAW,KAAK,UAAU,IAAI,CAAC;AAAA,MACxD;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ,MAAM,cAAc;AAAA,MAC5B;AAAA,MACA,SAAS,cAAc,SAAS;AAAA,MAChC,GAAI,QAAQ,QAAQ,EAAE,OAAO,OAAO,MAAM,IAAI,CAAC;AAAA,IACjD;AAEA,WACE,qBAAC,iBAAc,OAAc,SAC3B;AAAA,0BAAC,mBAAiB,GAAG,OAAO;AAAA,MAC5B,oBAAC,YAAS,UAAU,MAClB,8BAAC,cAAW,cAAc,OAAO,cAAc,GACjD;AAAA,OACF;AAAA,EAEJ;AACF;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@guard-rail/core",
3
- "version": "0.3.0",
3
+ "version": "0.6.0",
4
4
  "description": "Lightweight inline content editing for developer-owned Next.js sites.",
5
5
  "license": "ISC",
6
6
  "type": "module",
@@ -32,7 +32,8 @@
32
32
  "scripts"
33
33
  ],
34
34
  "bin": {
35
- "guardrail-seed-user": "dist/cli/seed-user.js"
35
+ "guardrail-seed-user": "dist/cli/seed-user.js",
36
+ "guardrail-init-db": "dist/cli/init-db.js"
36
37
  },
37
38
  "publishConfig": {
38
39
  "access": "public"
@@ -30,10 +30,10 @@ Guardrail installed. Next steps:
30
30
  1. Set up the database (skip both if this Supabase project already has
31
31
  Guardrail applied for another site — see "Many sites, one Supabase
32
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.
33
+ - npx guardrail-init-db --push
34
+ - If that project is hosted (not local Docker), also add "guardrail"
35
+ under Settings > API > Exposed schemas in the Supabase dashboard —
36
+ config.toml only covers local dev.
37
37
 
38
38
  2. Wrap your root layout with withGuardrail and mark fields with <GRail>.
39
39
  Full guide: https://www.npmjs.com/package/@guard-rail/core