@helloleo/plugins 0.1.14 → 0.1.16
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/index.js +197 -469
- package/dist/templates/tanstack-router-2026-06-15/components.json +22 -0
- package/dist/templates/tanstack-router-2026-06-15/index.html +13 -0
- package/dist/templates/tanstack-router-2026-06-15/package.json +94 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/accordion.tsx +51 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/alert-dialog.tsx +115 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/alert.tsx +49 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/aspect-ratio.tsx +5 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/avatar.tsx +47 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/badge.tsx +32 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/breadcrumb.tsx +101 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/button.tsx +49 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/calendar.tsx +177 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/card.tsx +55 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/carousel.tsx +240 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/chart.tsx +331 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/checkbox.tsx +26 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/collapsible.tsx +11 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/command.tsx +143 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/context-menu.tsx +187 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/dialog.tsx +104 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/drawer.tsx +98 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/dropdown-menu.tsx +188 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/form.tsx +171 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/hover-card.tsx +27 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/input-otp.tsx +69 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/input.tsx +22 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/label.tsx +21 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/menubar.tsx +229 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/navigation-menu.tsx +120 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/pagination.tsx +98 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/popover.tsx +31 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/progress.tsx +25 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/radio-group.tsx +36 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/resizable.tsx +37 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/scroll-area.tsx +44 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/select.tsx +152 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/separator.tsx +24 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/sheet.tsx +122 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/sidebar.tsx +744 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/skeleton.tsx +7 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/slider.tsx +23 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/sonner.tsx +23 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/switch.tsx +27 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/table.tsx +94 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/tabs.tsx +53 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/textarea.tsx +21 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/toggle-group.tsx +57 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/toggle.tsx +42 -0
- package/dist/templates/tanstack-router-2026-06-15/src/components/ui/tooltip.tsx +32 -0
- package/dist/templates/tanstack-router-2026-06-15/src/hooks/use-mobile.tsx +19 -0
- package/dist/templates/tanstack-router-2026-06-15/src/lib/proxy.ts +83 -0
- package/dist/templates/tanstack-router-2026-06-15/src/lib/utils.ts +6 -0
- package/dist/templates/tanstack-router-2026-06-15/src/main.tsx +33 -0
- package/dist/templates/tanstack-router-2026-06-15/src/routeTree.gen.ts +59 -0
- package/dist/templates/tanstack-router-2026-06-15/src/router.tsx +23 -0
- package/dist/templates/tanstack-router-2026-06-15/src/routes/__root.tsx +16 -0
- package/dist/templates/tanstack-router-2026-06-15/src/routes/index.tsx +14 -0
- package/dist/templates/tanstack-router-2026-06-15/src/styles.css +214 -0
- package/dist/templates/tanstack-router-2026-06-15/tsconfig.json +27 -0
- package/dist/templates/tanstack-router-2026-06-15/vite.config.ts +24 -0
- package/package.json +3 -2
- package/src/template-render.ts +48 -0
- package/src/templates/tanstack-router-2026-06-15/components.json +22 -0
- package/src/templates/tanstack-router-2026-06-15/index.html +13 -0
- package/src/templates/tanstack-router-2026-06-15/package.json +94 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/accordion.tsx +51 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/alert-dialog.tsx +115 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/alert.tsx +49 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/aspect-ratio.tsx +5 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/avatar.tsx +47 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/badge.tsx +32 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/breadcrumb.tsx +101 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/button.tsx +49 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/calendar.tsx +177 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/card.tsx +55 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/carousel.tsx +240 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/chart.tsx +331 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/checkbox.tsx +26 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/collapsible.tsx +11 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/command.tsx +143 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/context-menu.tsx +187 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/dialog.tsx +104 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/drawer.tsx +98 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/dropdown-menu.tsx +188 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/form.tsx +171 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/hover-card.tsx +27 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/input-otp.tsx +69 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/input.tsx +22 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/label.tsx +21 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/menubar.tsx +229 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/navigation-menu.tsx +120 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/pagination.tsx +98 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/popover.tsx +31 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/progress.tsx +25 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/radio-group.tsx +36 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/resizable.tsx +37 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/scroll-area.tsx +44 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/select.tsx +152 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/separator.tsx +24 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/sheet.tsx +122 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/sidebar.tsx +744 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/skeleton.tsx +7 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/slider.tsx +23 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/sonner.tsx +23 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/switch.tsx +27 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/table.tsx +94 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/tabs.tsx +53 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/textarea.tsx +21 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/toggle-group.tsx +57 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/toggle.tsx +42 -0
- package/src/templates/tanstack-router-2026-06-15/src/components/ui/tooltip.tsx +32 -0
- package/src/templates/tanstack-router-2026-06-15/src/hooks/use-mobile.tsx +19 -0
- package/src/templates/tanstack-router-2026-06-15/src/lib/proxy.ts +83 -0
- package/src/templates/tanstack-router-2026-06-15/src/lib/utils.ts +6 -0
- package/src/templates/tanstack-router-2026-06-15/src/main.tsx +33 -0
- package/src/templates/tanstack-router-2026-06-15/src/routeTree.gen.ts +59 -0
- package/src/templates/tanstack-router-2026-06-15/src/router.tsx +23 -0
- package/src/templates/tanstack-router-2026-06-15/src/routes/__root.tsx +16 -0
- package/src/templates/tanstack-router-2026-06-15/src/routes/index.tsx +14 -0
- package/src/templates/tanstack-router-2026-06-15/src/styles.css +214 -0
- package/src/templates/tanstack-router-2026-06-15/tsconfig.json +27 -0
- package/src/templates/tanstack-router-2026-06-15/vite.config.ts +24 -0
- package/src/tools/scaffold.ts +51 -444
- package/src/tools/setup-netsuite.ts +161 -80
|
@@ -6,10 +6,13 @@ import { writeBaseScaffold } from "./scaffold.ts";
|
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* One-shot bootstrap for a NetSuite project. Writes the base HelloLeo
|
|
9
|
-
* scaffold (via writeBaseScaffold) plus
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
9
|
+
* scaffold (via writeBaseScaffold) plus ADDITIVE NetSuite OAuth wiring:
|
|
10
|
+
* the netsuite OAuth client, a NetSuite auth context (auth.tsx), and the
|
|
11
|
+
* AuthLayout / LoginPage / SignInWithNetSuite components. It never
|
|
12
|
+
* overwrites a scaffold file -- the one manual step is wrapping the root
|
|
13
|
+
* route's <Outlet /> with <AuthLayout> (the tool's output shows the
|
|
14
|
+
* snippet). All NetSuite-specific templates live in this file -- one place
|
|
15
|
+
* to read or change anything NetSuite-related.
|
|
13
16
|
*
|
|
14
17
|
* Use INSTEAD of `scaffold` when the project needs NetSuite. The tool
|
|
15
18
|
* name carries the intent so the LLM can't accidentally ship a project
|
|
@@ -209,34 +212,120 @@ export function LoginPage() {
|
|
|
209
212
|
`;
|
|
210
213
|
}
|
|
211
214
|
|
|
212
|
-
function
|
|
213
|
-
return `import
|
|
215
|
+
function authTsx(): string {
|
|
216
|
+
return `import * as React from 'react';
|
|
217
|
+
import {
|
|
218
|
+
getNetSuiteSession,
|
|
219
|
+
signInWithNetSuite,
|
|
220
|
+
signOutNetSuite,
|
|
221
|
+
type NetSuiteSession,
|
|
222
|
+
} from './netsuite';
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* NetSuite auth context. Holds the current session (resolved from the Worker's
|
|
226
|
+
* /api/me via getNetSuiteSession) and exposes sign-in / sign-out. The only
|
|
227
|
+
* authoritative auth check is /api/me -- never trust sessionStorage directly.
|
|
228
|
+
*/
|
|
229
|
+
export interface NetSuiteAuthContextValue {
|
|
230
|
+
pending: boolean;
|
|
231
|
+
isAuthenticated: boolean;
|
|
232
|
+
session: NetSuiteSession | null;
|
|
233
|
+
signIn: () => void;
|
|
234
|
+
signOut: () => Promise<void>;
|
|
235
|
+
refresh: () => Promise<void>;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const NetSuiteAuthContext =
|
|
239
|
+
React.createContext<NetSuiteAuthContextValue | null>(null);
|
|
240
|
+
|
|
241
|
+
export function NetSuiteAuthProvider({
|
|
242
|
+
children,
|
|
243
|
+
}: {
|
|
244
|
+
children: React.ReactNode;
|
|
245
|
+
}) {
|
|
246
|
+
const [session, setSession] = React.useState<NetSuiteSession | null>(null);
|
|
247
|
+
const [pending, setPending] = React.useState(true);
|
|
248
|
+
|
|
249
|
+
const refresh = React.useCallback(async () => {
|
|
250
|
+
setPending(true);
|
|
251
|
+
try {
|
|
252
|
+
setSession(await getNetSuiteSession());
|
|
253
|
+
} finally {
|
|
254
|
+
setPending(false);
|
|
255
|
+
}
|
|
256
|
+
}, []);
|
|
257
|
+
|
|
258
|
+
React.useEffect(() => {
|
|
259
|
+
refresh();
|
|
260
|
+
}, [refresh]);
|
|
261
|
+
|
|
262
|
+
const value: NetSuiteAuthContextValue = {
|
|
263
|
+
pending,
|
|
264
|
+
isAuthenticated: Boolean(session?.authenticated),
|
|
265
|
+
session,
|
|
266
|
+
signIn: () => signInWithNetSuite(),
|
|
267
|
+
signOut: signOutNetSuite,
|
|
268
|
+
refresh,
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
return (
|
|
272
|
+
<NetSuiteAuthContext.Provider value={value}>
|
|
273
|
+
{children}
|
|
274
|
+
</NetSuiteAuthContext.Provider>
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
export function useNetSuiteAuth(): NetSuiteAuthContextValue {
|
|
279
|
+
const ctx = React.useContext(NetSuiteAuthContext);
|
|
280
|
+
if (!ctx) {
|
|
281
|
+
throw new Error('useNetSuiteAuth must be used within <NetSuiteAuthProvider>');
|
|
282
|
+
}
|
|
283
|
+
return ctx;
|
|
284
|
+
}
|
|
285
|
+
`;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function authLayoutTsx(): string {
|
|
289
|
+
return `import type { ReactNode } from 'react';
|
|
290
|
+
import { NetSuiteAuthProvider, useNetSuiteAuth } from '../../lib/auth';
|
|
214
291
|
import { LoginPage } from './LoginPage';
|
|
215
|
-
import { getNetSuiteSession, type NetSuiteSession } from '../../lib/netsuite';
|
|
216
292
|
|
|
217
293
|
/**
|
|
218
|
-
*
|
|
219
|
-
*
|
|
220
|
-
* is the ONLY supported authentication for a NetSuite project (no password
|
|
221
|
-
* gates, no sessionStorage flags, no shared credential).
|
|
222
|
-
*
|
|
223
|
-
* Pattern in src/App.tsx:
|
|
294
|
+
* NetSuite auth layout. This is the ONLY wiring you need to add by hand --
|
|
295
|
+
* wrap the root route's <Outlet /> with it:
|
|
224
296
|
*
|
|
225
|
-
*
|
|
226
|
-
*
|
|
297
|
+
* // src/routes/__root.tsx
|
|
298
|
+
* import { AuthLayout } from '../components/auth/AuthLayout';
|
|
299
|
+
* ...
|
|
300
|
+
* function RootComponent() {
|
|
227
301
|
* return (
|
|
228
|
-
*
|
|
229
|
-
* <
|
|
230
|
-
*
|
|
302
|
+
* <>
|
|
303
|
+
* <AuthLayout>
|
|
304
|
+
* <Outlet />
|
|
305
|
+
* </AuthLayout>
|
|
306
|
+
* { ...devtools... }
|
|
307
|
+
* </>
|
|
231
308
|
* );
|
|
232
309
|
* }
|
|
310
|
+
*
|
|
311
|
+
* It provides NetSuite auth context to the whole tree and gates rendering:
|
|
312
|
+
* while the session resolves it shows a spinner, unauthenticated users see
|
|
313
|
+
* <LoginPage />, authenticated users see your routes. Use useNetSuiteAuth()
|
|
314
|
+
* anywhere below it to read the session or sign out. NEVER swap this for a
|
|
315
|
+
* password gate -- real OAuth is the only supported login.
|
|
233
316
|
*/
|
|
234
|
-
export function
|
|
235
|
-
|
|
317
|
+
export function AuthLayout({ children }: { children: ReactNode }) {
|
|
318
|
+
return (
|
|
319
|
+
<NetSuiteAuthProvider>
|
|
320
|
+
<Gate>{children}</Gate>
|
|
321
|
+
</NetSuiteAuthProvider>
|
|
322
|
+
);
|
|
323
|
+
}
|
|
236
324
|
|
|
237
|
-
|
|
325
|
+
function Gate({ children }: { children: ReactNode }) {
|
|
326
|
+
const { pending, isAuthenticated } = useNetSuiteAuth();
|
|
238
327
|
|
|
239
|
-
if (
|
|
328
|
+
if (pending) {
|
|
240
329
|
return (
|
|
241
330
|
<div className="min-h-screen flex items-center justify-center bg-background">
|
|
242
331
|
<div className="h-8 w-8 rounded-full border-2 border-primary border-t-transparent animate-spin" />
|
|
@@ -244,46 +333,26 @@ export function AuthGate({ children }: { children: React.ReactNode }) {
|
|
|
244
333
|
);
|
|
245
334
|
}
|
|
246
335
|
|
|
247
|
-
if (!
|
|
336
|
+
if (!isAuthenticated) return <LoginPage />;
|
|
248
337
|
|
|
249
338
|
return <>{children}</>;
|
|
250
339
|
}
|
|
251
340
|
`;
|
|
252
341
|
}
|
|
253
342
|
|
|
254
|
-
function netsuiteAppTsx(): string {
|
|
255
|
-
return `import { AuthGate } from './components/auth/AuthGate';
|
|
256
|
-
|
|
257
|
-
/**
|
|
258
|
-
* NetSuite project entry point. KEEP <AuthGate> as the outermost element --
|
|
259
|
-
* removing it disables real OAuth and exposes NetSuite data to anonymous
|
|
260
|
-
* users. Build your dashboard / pages inside the gate.
|
|
261
|
-
*/
|
|
262
|
-
export default function App() {
|
|
263
|
-
return (
|
|
264
|
-
<AuthGate>
|
|
265
|
-
<div className="min-h-screen bg-background text-foreground p-8">
|
|
266
|
-
<h1 className="text-2xl font-bold">You are signed in to NetSuite.</h1>
|
|
267
|
-
<p className="text-muted-foreground mt-2">
|
|
268
|
-
Replace this placeholder with your dashboard.
|
|
269
|
-
</p>
|
|
270
|
-
</div>
|
|
271
|
-
</AuthGate>
|
|
272
|
-
);
|
|
273
|
-
}
|
|
274
|
-
`;
|
|
275
|
-
}
|
|
276
|
-
|
|
277
343
|
export const setupNetsuite = tool({
|
|
278
344
|
description:
|
|
279
|
-
"Bootstrap a NetSuite-backed React + Vite + Tailwind
|
|
280
|
-
"Writes the full HelloLeo base scaffold
|
|
281
|
-
"
|
|
282
|
-
"src/
|
|
345
|
+
"Bootstrap a NetSuite-backed React + Vite + Tailwind v4 + TanStack Router " +
|
|
346
|
+
"project in one call. Writes the full HelloLeo base scaffold PLUS the " +
|
|
347
|
+
"NetSuite OAuth wiring, all ADDITIVE -- it never overwrites a scaffold " +
|
|
348
|
+
"file. Adds src/lib/netsuite.ts (OAuth client), src/lib/auth.tsx " +
|
|
349
|
+
"(NetSuiteAuthProvider + useNetSuiteAuth), and " +
|
|
350
|
+
"src/components/auth/{AuthLayout,LoginPage,SignInWithNetSuite}.tsx. " +
|
|
283
351
|
"Use this INSTEAD of `scaffold` for any project that needs NetSuite. " +
|
|
284
|
-
"
|
|
285
|
-
"
|
|
286
|
-
"
|
|
352
|
+
"After it runs there is exactly ONE manual step: wrap the root route's " +
|
|
353
|
+
"<Outlet /> with <AuthLayout> in src/routes/__root.tsx (the tool's output " +
|
|
354
|
+
"shows the snippet). Real OAuth is wired from day one -- never replace " +
|
|
355
|
+
"<AuthLayout> with a password placeholder.",
|
|
287
356
|
args: {},
|
|
288
357
|
async execute(_args, context) {
|
|
289
358
|
const dir = context.directory;
|
|
@@ -293,55 +362,67 @@ export const setupNetsuite = tool({
|
|
|
293
362
|
recursive: true,
|
|
294
363
|
});
|
|
295
364
|
|
|
365
|
+
// All additive -- nothing the base scaffold wrote is touched.
|
|
296
366
|
const nsFiles: [string, string][] = [
|
|
297
367
|
[path.join("src", "lib", "netsuite.ts"), netsuiteTs()],
|
|
368
|
+
[path.join("src", "lib", "auth.tsx"), authTsx()],
|
|
298
369
|
[
|
|
299
|
-
path.join("src", "components", "auth", "
|
|
300
|
-
|
|
370
|
+
path.join("src", "components", "auth", "AuthLayout.tsx"),
|
|
371
|
+
authLayoutTsx(),
|
|
301
372
|
],
|
|
302
373
|
[
|
|
303
374
|
path.join("src", "components", "auth", "LoginPage.tsx"),
|
|
304
375
|
netsuiteLoginPageTsx(),
|
|
305
376
|
],
|
|
306
377
|
[
|
|
307
|
-
path.join("src", "components", "auth", "
|
|
308
|
-
|
|
378
|
+
path.join("src", "components", "auth", "SignInWithNetSuite.tsx"),
|
|
379
|
+
signInButtonTsx(),
|
|
309
380
|
],
|
|
310
|
-
[path.join("src", "App.tsx"), netsuiteAppTsx()],
|
|
311
381
|
];
|
|
312
382
|
|
|
313
|
-
const nsCreated: string[] = [];
|
|
314
383
|
for (const [filePath, content] of nsFiles) {
|
|
315
384
|
await Bun.write(path.join(dir, filePath), content);
|
|
316
|
-
nsCreated.push(filePath);
|
|
317
385
|
}
|
|
318
386
|
|
|
319
|
-
const all = [...base, ...
|
|
387
|
+
const all = [...base, ...nsFiles.map(([f]) => f)];
|
|
320
388
|
return [
|
|
321
|
-
`
|
|
322
|
-
|
|
389
|
+
`Generated ${all.length} files (base scaffold + NetSuite OAuth, all additive -- nothing overwritten).`,
|
|
390
|
+
"",
|
|
391
|
+
"All you need to do is wrap the root layout with the auth layout.",
|
|
392
|
+
"In src/routes/__root.tsx, import AuthLayout and wrap <Outlet />:",
|
|
393
|
+
"",
|
|
394
|
+
" import { AuthLayout } from '../components/auth/AuthLayout'",
|
|
395
|
+
"",
|
|
396
|
+
" function RootComponent() {",
|
|
397
|
+
" return (",
|
|
398
|
+
" <>",
|
|
399
|
+
" <AuthLayout>",
|
|
400
|
+
" <Outlet />",
|
|
401
|
+
" </AuthLayout>",
|
|
402
|
+
" {/* keep the existing <TanStackDevtools ... /> here */}",
|
|
403
|
+
" </>",
|
|
404
|
+
" )",
|
|
405
|
+
" }",
|
|
406
|
+
"",
|
|
407
|
+
"That single wrap gates every route: <LoginPage /> until the user signs",
|
|
408
|
+
"in with NetSuite, your routes after. Read the session anywhere below it",
|
|
409
|
+
"with useNetSuiteAuth() from src/lib/auth.tsx. NEVER swap <AuthLayout>",
|
|
410
|
+
"for a password gate -- real OAuth is the only supported login.",
|
|
323
411
|
"",
|
|
324
|
-
"
|
|
325
|
-
"
|
|
326
|
-
"
|
|
412
|
+
"NetSuite OAuth files written:",
|
|
413
|
+
" - src/lib/netsuite.ts OAuth client (signIn / session / workerFetch)",
|
|
414
|
+
" - src/lib/auth.tsx NetSuiteAuthProvider + useNetSuiteAuth",
|
|
415
|
+
" - src/components/auth/AuthLayout.tsx provider + gate (wrap root with this)",
|
|
416
|
+
" - src/components/auth/LoginPage.tsx unauthenticated view",
|
|
417
|
+
" - src/components/auth/SignInWithNetSuite.tsx sign-in button",
|
|
327
418
|
"",
|
|
328
|
-
"
|
|
329
|
-
" - App.tsx wraps everything in <AuthGate>. NEVER remove the gate",
|
|
330
|
-
" or build a password placeholder -- real OAuth is the only login.",
|
|
331
|
-
" - LoginPage.tsx + SignInWithNetSuite.tsx are the unauthenticated",
|
|
332
|
-
" view. Customise the copy / imagery, keep <SignInWithNetSuite/>",
|
|
333
|
-
" as the call-to-action.",
|
|
334
|
-
" - signInWithNetSuite() in src/lib/netsuite.ts hits the Worker at",
|
|
335
|
-
" /auth/netsuite/start. Deploy the Worker via cloudflare-backend",
|
|
336
|
-
" MCP with routes:",
|
|
419
|
+
"Worker (deploy via cloudflare-backend MCP) must serve:",
|
|
337
420
|
" GET /auth/netsuite/start -- redirect to NetSuite OAuth",
|
|
338
421
|
" GET /auth/netsuite/callback -- code -> token exchange",
|
|
339
|
-
" GET /api/me
|
|
422
|
+
" GET /api/me -- current session",
|
|
340
423
|
" POST /auth/netsuite/logout -- clear session",
|
|
341
|
-
"
|
|
342
|
-
"
|
|
343
|
-
" - VITE_WORKER_URL must be set so the frontend knows where to",
|
|
344
|
-
" send users. The HelloLeo Cloud provisioner seeds this.",
|
|
424
|
+
" Reads env.NETSUITE_ACCOUNT_ID / _CLIENT_ID / _CLIENT_SECRET.",
|
|
425
|
+
" VITE_WORKER_URL must be set (HelloLeo Cloud provisioner seeds it).",
|
|
345
426
|
].join("\n");
|
|
346
427
|
},
|
|
347
428
|
});
|