@githat/nextjs 0.4.1 → 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/dist/githat.css CHANGED
@@ -332,3 +332,44 @@
332
332
  color: #a1a1aa;
333
333
  font-size: 0.875rem;
334
334
  }
335
+
336
+ /* Dev Mode Banner */
337
+ .githat-dev-banner {
338
+ position: fixed;
339
+ top: 0;
340
+ left: 0;
341
+ right: 0;
342
+ z-index: 99999;
343
+ display: flex;
344
+ align-items: center;
345
+ justify-content: space-between;
346
+ padding: 0.5rem 1rem;
347
+ background: #fef3c7;
348
+ border-bottom: 1px solid #f59e0b;
349
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
350
+ font-size: 0.8125rem;
351
+ color: #92400e;
352
+ }
353
+
354
+ .githat-dev-banner a {
355
+ color: #d97706;
356
+ font-weight: 600;
357
+ text-decoration: underline;
358
+ }
359
+
360
+ .githat-dev-banner button {
361
+ background: none;
362
+ border: none;
363
+ color: #92400e;
364
+ font-size: 1.25rem;
365
+ cursor: pointer;
366
+ padding: 0 0.25rem;
367
+ line-height: 1;
368
+ }
369
+
370
+ /* Success Alert */
371
+ .githat-alert-success {
372
+ background: rgba(16, 185, 129, 0.1);
373
+ border: 1px solid rgba(16, 185, 129, 0.3);
374
+ color: #6ee7b7;
375
+ }
package/dist/index.js CHANGED
@@ -126,14 +126,21 @@ function createClient(apiUrl, appKey, options = {}) {
126
126
  });
127
127
  } catch (networkError) {
128
128
  if (networkError instanceof TypeError) {
129
- const isMissingKey = !appKey || !appKey.startsWith("pk_live_");
129
+ const isMissingKey = !appKey || !appKey.startsWith("pk_live_") && !appKey.startsWith("pk_test_");
130
130
  const isLocalhost = typeof window !== "undefined" && (window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1");
131
131
  if (isMissingKey && !isLocalhost) {
132
132
  throw new Error(
133
- "Missing GitHat API key. Add NEXT_PUBLIC_GITHAT_PUBLISHABLE_KEY to .env.local"
133
+ "GitHat: Missing or invalid publishable key. Add NEXT_PUBLIC_GITHAT_PUBLISHABLE_KEY to your environment variables. Get your key at https://githat.io/dashboard/apps"
134
134
  );
135
135
  }
136
- throw new Error("Unable to connect to GitHat API. Check your network connection.");
136
+ if (isLocalhost) {
137
+ throw new Error(
138
+ "GitHat: Cannot reach api.githat.io. Check your internet connection."
139
+ );
140
+ }
141
+ throw new Error(
142
+ "GitHat: API request failed. Verify your publishable key and app domain at https://githat.io/dashboard/apps"
143
+ );
137
144
  }
138
145
  throw networkError;
139
146
  }
@@ -171,10 +178,59 @@ function createClient(apiUrl, appKey, options = {}) {
171
178
  // src/provider.tsx
172
179
  var import_jsx_runtime = require("react/jsx-runtime");
173
180
  var GitHatContext = (0, import_react.createContext)(null);
181
+ function isDevMode(key) {
182
+ return !key || !key.startsWith("pk_live_") && !key.startsWith("pk_test_");
183
+ }
184
+ function DevModeBanner() {
185
+ const [dismissed, setDismissed] = (0, import_react.useState)(() => {
186
+ if (typeof window === "undefined") return true;
187
+ return localStorage.getItem("githat_dev_banner_dismissed") === "1";
188
+ });
189
+ if (dismissed || typeof window === "undefined") return null;
190
+ const hostname = window.location.hostname;
191
+ if (hostname !== "localhost" && hostname !== "127.0.0.1") return null;
192
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "githat-dev-banner", role: "status", children: [
193
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
194
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: "GitHat Dev Mode" }),
195
+ " \u2014 No publishable key. Auth works on localhost.",
196
+ " ",
197
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: "https://githat.io/dashboard/apps", target: "_blank", rel: "noopener noreferrer", children: "Get your key" })
198
+ ] }),
199
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
200
+ "button",
201
+ {
202
+ onClick: () => {
203
+ setDismissed(true);
204
+ localStorage.setItem("githat_dev_banner_dismissed", "1");
205
+ },
206
+ "aria-label": "Dismiss",
207
+ children: "\xD7"
208
+ }
209
+ )
210
+ ] });
211
+ }
174
212
  function GitHatProvider({ config: rawConfig, children }) {
175
213
  const config = (0, import_react.useMemo)(() => resolveConfig(rawConfig), [rawConfig]);
176
214
  const useCookies = config.tokenStorage === "cookie";
215
+ const devMode = isDevMode(config.publishableKey);
177
216
  const clientRef = (0, import_react.useRef)(createClient(config.apiUrl, config.publishableKey, { useCookies }));
217
+ (0, import_react.useEffect)(() => {
218
+ if (!devMode || typeof window === "undefined") return;
219
+ const hostname = window.location.hostname;
220
+ if (hostname === "localhost" || hostname === "127.0.0.1") {
221
+ console.warn(
222
+ "%c GitHat Dev Mode %c No publishable key configured. Auth works on localhost but will fail in production. Get your key at https://githat.io/dashboard/apps",
223
+ "background: #f59e0b; color: #000; font-weight: bold; padding: 2px 6px; border-radius: 3px;",
224
+ "color: #f59e0b;"
225
+ );
226
+ } else {
227
+ console.error(
228
+ "%c GitHat %c Missing publishable key. Auth requests will fail. Add NEXT_PUBLIC_GITHAT_PUBLISHABLE_KEY to your environment. Get your key at https://githat.io/dashboard/apps",
229
+ "background: #ef4444; color: #fff; font-weight: bold; padding: 2px 6px; border-radius: 3px;",
230
+ "color: #ef4444;"
231
+ );
232
+ }
233
+ }, []);
178
234
  const [user, setUser] = (0, import_react.useState)(null);
179
235
  const [org, setOrg] = (0, import_react.useState)(null);
180
236
  const [isSignedIn, setIsSignedIn] = (0, import_react.useState)(false);
@@ -322,7 +378,10 @@ function GitHatProvider({ config: rawConfig, children }) {
322
378
  signOut,
323
379
  switchOrg
324
380
  }), [user, org, isSignedIn, isLoading, authError, config, signIn, signUp, signOut, switchOrg]);
325
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(GitHatContext.Provider, { value, children });
381
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(GitHatContext.Provider, { value, children: [
382
+ devMode && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DevModeBanner, {}),
383
+ children
384
+ ] });
326
385
  }
327
386
 
328
387
  // src/hooks.ts
@@ -631,6 +690,8 @@ function SignUpForm({ onSuccess, signInUrl }) {
631
690
  const [password, setPassword] = (0, import_react5.useState)("");
632
691
  const [error, setError] = (0, import_react5.useState)("");
633
692
  const [loading, setLoading] = (0, import_react5.useState)(false);
693
+ const [verificationSent, setVerificationSent] = (0, import_react5.useState)(false);
694
+ const [verificationEmail, setVerificationEmail] = (0, import_react5.useState)("");
634
695
  const emailValid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
635
696
  const passwordValid = password.length >= 8 && /[A-Z]/.test(password) && /[a-z]/.test(password) && /\d/.test(password);
636
697
  const handleSubmit = async (e) => {
@@ -649,6 +710,9 @@ function SignUpForm({ onSuccess, signInUrl }) {
649
710
  const result = await signUp({ email, password, name });
650
711
  if (onSuccess) {
651
712
  onSuccess(result);
713
+ } else if (result.requiresVerification) {
714
+ setVerificationSent(true);
715
+ setVerificationEmail(result.email);
652
716
  } else if (typeof window !== "undefined") {
653
717
  window.location.href = config.afterSignInUrl;
654
718
  }
@@ -658,6 +722,23 @@ function SignUpForm({ onSuccess, signInUrl }) {
658
722
  setLoading(false);
659
723
  }
660
724
  };
725
+ if (verificationSent) {
726
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "githat-form-container", children: [
727
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "githat-form-header", children: [
728
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { className: "githat-form-title", children: "Check your email" }),
729
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { className: "githat-form-subtitle", children: [
730
+ "We sent a verification link to ",
731
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: verificationEmail })
732
+ ] })
733
+ ] }),
734
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "githat-alert githat-alert-success", role: "status", children: "Account created! Click the link in your email to verify, then sign in." }),
735
+ signInUrl && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "githat-form-footer", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("a", { href: signInUrl, className: "githat-link", children: "Go to sign in" }) }),
736
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { className: "githat-powered-by", children: [
737
+ "Secured by ",
738
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: "GitHat" })
739
+ ] })
740
+ ] });
741
+ }
661
742
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "githat-form-container", children: [
662
743
  /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "githat-form-header", children: [
663
744
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { className: "githat-form-title", children: "Create an account" }),