@pylonsync/create-pylon 0.3.309 → 0.3.311

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pylonsync/create-pylon",
3
- "version": "0.3.309",
3
+ "version": "0.3.311",
4
4
  "description": "Scaffold a new Pylon app — realtime backend + web/mobile/expo frontends in one command. Run via `npm create @pylonsync/pylon@latest`.",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import React, { useState } from "react";
3
+ import React, { useEffect, useState } from "react";
4
4
  import { db } from "@pylonsync/react";
5
5
  import {
6
6
  passwordLogin,
@@ -29,6 +29,26 @@ export function AuthForm({ mode }: { mode: "login" | "signup" }) {
29
29
  const [password, setPassword] = useState("");
30
30
  const [error, setError] = useState<string | null>(null);
31
31
  const [pending, setPending] = useState(false);
32
+ // OAuth buttons render only for providers the server actually has
33
+ // configured (GET /api/auth/providers) — an unconfigured provider's
34
+ // login URL is a JSON error dead-end, not a login page. `null` while
35
+ // loading so nothing flashes in.
36
+ const [providers, setProviders] = useState<string[] | null>(null);
37
+
38
+ useEffect(() => {
39
+ let alive = true;
40
+ fetch("/api/auth/providers")
41
+ .then((r) => (r.ok ? r.json() : []))
42
+ .then((list: Array<{ provider: string }>) => {
43
+ if (alive) setProviders(list.map((p) => p.provider));
44
+ })
45
+ .catch(() => {
46
+ if (alive) setProviders([]);
47
+ });
48
+ return () => {
49
+ alive = false;
50
+ };
51
+ }, []);
32
52
 
33
53
  async function onSubmit(e: React.FormEvent) {
34
54
  e.preventDefault();
@@ -114,22 +134,38 @@ export function AuthForm({ mode }: { mode: "login" | "signup" }) {
114
134
  </button>
115
135
  </form>
116
136
 
117
- <div className="flex items-center gap-3 text-[11px] uppercase tracking-wide text-zinc-400">
118
- <span className="h-px flex-1 bg-zinc-200" />
119
- or continue with
120
- <span className="h-px flex-1 bg-zinc-200" />
121
- </div>
137
+ {/* Social sign-in only for providers the server reports as
138
+ configured. Enable Google with PYLON_OAUTH_GOOGLE_CLIENT_ID /
139
+ _CLIENT_SECRET / _REDIRECT (GitHub: PYLON_OAUTH_GITHUB_*) and the
140
+ button appears with zero code changes. */}
141
+ {providers && providers.length > 0 ? (
142
+ <>
143
+ <div className="flex items-center gap-3 text-[11px] uppercase tracking-wide text-zinc-400">
144
+ <span className="h-px flex-1 bg-zinc-200" />
145
+ or continue with
146
+ <span className="h-px flex-1 bg-zinc-200" />
147
+ </div>
122
148
 
123
- {/* Social sign-in. The Google provider must be configured (set
124
- PYLON_OAUTH_GOOGLE_CLIENT_ID / _CLIENT_SECRET / _REDIRECT) — until then
125
- this button returns a helpful "configure the provider" error. */}
126
- <a
127
- href="/api/auth/login/google?callback=/dashboard&redirect=1"
128
- className="inline-flex h-10 w-full items-center justify-center gap-2 rounded-lg border border-zinc-300 bg-white text-sm font-medium text-zinc-900 transition-colors hover:bg-zinc-50"
129
- >
130
- <GoogleIcon />
131
- Google
132
- </a>
149
+ {providers.includes("google") ? (
150
+ <a
151
+ href="/api/auth/login/google?callback=/dashboard&redirect=1"
152
+ className="inline-flex h-10 w-full items-center justify-center gap-2 rounded-lg border border-zinc-300 bg-white text-sm font-medium text-zinc-900 transition-colors hover:bg-zinc-50"
153
+ >
154
+ <GoogleIcon />
155
+ Google
156
+ </a>
157
+ ) : null}
158
+ {providers.includes("github") ? (
159
+ <a
160
+ href="/api/auth/login/github?callback=/dashboard&redirect=1"
161
+ className="inline-flex h-10 w-full items-center justify-center gap-2 rounded-lg border border-zinc-300 bg-white text-sm font-medium text-zinc-900 transition-colors hover:bg-zinc-50"
162
+ >
163
+ <GitHubIcon />
164
+ GitHub
165
+ </a>
166
+ ) : null}
167
+ </>
168
+ ) : null}
133
169
  </div>
134
170
  );
135
171
  }
@@ -194,6 +230,14 @@ function LockIcon() {
194
230
  );
195
231
  }
196
232
 
233
+ function GitHubIcon() {
234
+ return (
235
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" aria-hidden>
236
+ <path d="M12 1C5.92 1 1 5.92 1 12c0 4.87 3.15 9 7.52 10.45.55.1.75-.24.75-.53 0-.26-.01-.96-.01-1.88-3.06.66-3.71-1.48-3.71-1.48-.5-1.27-1.22-1.61-1.22-1.61-1-.68.08-.67.08-.67 1.1.08 1.68 1.13 1.68 1.13.98 1.68 2.57 1.19 3.2.91.1-.71.38-1.19.69-1.47-2.44-.28-5.01-1.22-5.01-5.44 0-1.2.43-2.18 1.13-2.95-.11-.28-.49-1.4.11-2.91 0 0 .92-.3 3.03 1.13a10.5 10.5 0 0 1 5.52 0c2.1-1.43 3.03-1.13 3.03-1.13.6 1.51.22 2.63.11 2.91.7.77 1.13 1.75 1.13 2.95 0 4.23-2.58 5.16-5.03 5.43.39.34.74 1 .74 2.02 0 1.47-.01 2.65-.01 3.01 0 .29.2.64.76.53A11.01 11.01 0 0 0 23 12c0-6.08-4.92-11-11-11z" />
237
+ </svg>
238
+ );
239
+ }
240
+
197
241
  function GoogleIcon() {
198
242
  return (
199
243
  <svg width="16" height="16" viewBox="0 0 24 24" aria-hidden>