@donotdev/cli 0.0.4 → 0.0.6
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/dependencies-matrix.json +234 -114
- package/dist/bin/commands/build.js +9 -3
- package/dist/bin/commands/bump.js +119 -100
- package/dist/bin/commands/cacheout.js +9 -3
- package/dist/bin/commands/create-app.js +60 -34
- package/dist/bin/commands/create-project.js +61 -34
- package/dist/bin/commands/deploy.js +22 -14
- package/dist/bin/commands/dev.js +9 -3
- package/dist/bin/commands/emu.js +9 -3
- package/dist/bin/commands/format.js +9 -3
- package/dist/bin/commands/lint.js +9 -3
- package/dist/bin/commands/make-admin.d.ts +11 -0
- package/dist/bin/commands/make-admin.d.ts.map +1 -0
- package/dist/bin/commands/make-admin.js +12 -0
- package/dist/bin/commands/make-admin.js.map +1 -0
- package/dist/bin/commands/preview.js +9 -3
- package/dist/bin/commands/sync-secrets.js +9 -3
- package/dist/index.js +72 -44
- package/package.json +1 -1
- package/templates/app-demo/index.html.example +4 -0
- package/templates/app-demo/src/App.tsx.example +28 -10
- package/templates/app-demo/src/config/app.ts.example +56 -0
- package/templates/app-demo/src/pages/components/DemoLayout.tsx.example +5 -5
- package/templates/app-next/src/app/ClientLayout.tsx.example +5 -4
- package/templates/app-next/src/app/layout.tsx.example +17 -25
- package/templates/app-next/src/globals.css.example +10 -7
- package/templates/app-next/src/locales/dndev_en.json.example +68 -0
- package/templates/app-next/src/pages/locales/example_en.json.example +5 -0
- package/templates/app-vite/index.html.example +3 -0
- package/templates/app-vite/src/App.tsx.example +1 -1
- package/templates/app-vite/src/globals.css.example +14 -6
- package/templates/app-vite/src/locales/dndev_en.json.example +68 -0
- package/templates/functions-firebase/README.md.example +25 -0
- package/templates/functions-firebase/tsconfig.json.example +3 -13
- package/templates/functions-vercel/tsconfig.json.example +1 -13
- package/templates/root-consumer/firebase.json.example +1 -1
- package/templates/root-consumer/guides/AGENT_START_HERE.md.example +229 -7
- package/templates/root-consumer/guides/COMPONENTS_ADV.md.example +456 -0
- package/templates/root-consumer/guides/COMPONENTS_ATOMIC.md.example +43 -1
- package/templates/root-consumer/guides/COMPONENTS_UI.md.example +6 -0
- package/templates/root-consumer/guides/INDEX.md.example +3 -0
- package/templates/root-consumer/guides/SETUP_APP_CONFIG.md.example +5 -2
- package/templates/root-consumer/guides/SETUP_BILLING.md.example +44 -4
- package/templates/root-consumer/guides/SETUP_CRUD.md.example +1244 -0
- package/templates/root-consumer/guides/SETUP_FUNCTIONS.md.example +52 -0
- package/templates/root-consumer/guides/SETUP_I18N.md.example +145 -6
- package/templates/root-consumer/guides/SETUP_LAYOUTS.md.example +18 -0
- package/templates/root-consumer/guides/SETUP_PAGES.md.example +25 -0
- package/templates/root-consumer/guides/SETUP_PWA.md.example +213 -0
- package/templates/root-consumer/guides/USE_ROUTING.md.example +503 -0
- package/templates/root-consumer/vercel.json.example +315 -20
- package/templates/app-demo/src/Routes.tsx.example +0 -20
- package/templates/app-vite/src/Routes.tsx.example +0 -16
- package/templates/app-vite/src/pages/locales/README.md.example +0 -1
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>DoNotDev Components Demo</title>
|
|
7
|
+
|
|
8
|
+
<!-- ✅ PERFORMANCE: Critical font preloads (loads before CSS) -->
|
|
9
|
+
<link rel="preload" href="/fonts/Inter-latin.woff2" as="font" type="font/woff2" crossorigin="anonymous">
|
|
10
|
+
|
|
7
11
|
<style>
|
|
8
12
|
body {
|
|
9
13
|
margin: 0;
|
|
@@ -1,17 +1,35 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Main application component
|
|
3
|
+
* @description Root application component with configuration-driven architecture
|
|
4
|
+
* @version 0.0.4
|
|
5
|
+
* @since 0.0.1
|
|
6
|
+
* @author AMBROISE PARK Consulting
|
|
7
|
+
*/
|
|
2
8
|
|
|
3
|
-
import {
|
|
4
|
-
import { TooltipProvider, Toaster } from '@donotdev/components';
|
|
9
|
+
import { ViteAppProviders } from '@donotdev/ui/vite';
|
|
5
10
|
|
|
6
|
-
import {
|
|
11
|
+
import { appConfig } from './config/app';
|
|
7
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Main application component
|
|
15
|
+
*
|
|
16
|
+
* Configuration-driven architecture with smart defaults.
|
|
17
|
+
* Layout preset comes from appConfig.preset (configured in config/app.ts).
|
|
18
|
+
* Routes are automatically discovered from src/pages/*Page.tsx files.
|
|
19
|
+
*
|
|
20
|
+
* Note: HomePage.tsx in src/pages/ is automatically used for the root route "/"
|
|
21
|
+
*
|
|
22
|
+
* @version 0.0.4
|
|
23
|
+
* @since 0.0.1
|
|
24
|
+
* @author AMBROISE PARK Consulting
|
|
25
|
+
*/
|
|
8
26
|
export function App() {
|
|
9
27
|
return (
|
|
10
|
-
<
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
28
|
+
<ViteAppProviders
|
|
29
|
+
config={appConfig}
|
|
30
|
+
layout={{
|
|
31
|
+
breadcrumbs: 'smart', // 'smart' | 'always' | 'never'
|
|
32
|
+
}}
|
|
33
|
+
/>
|
|
16
34
|
);
|
|
17
35
|
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Application configuration
|
|
3
|
+
* @description Defines application metadata and feature flags
|
|
4
|
+
* @version 0.0.1
|
|
5
|
+
* @since 0.0.1
|
|
6
|
+
* @author AMBROISE PARK Consulting
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { AppConfig } from '@donotdev/core';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Application name constant
|
|
13
|
+
*
|
|
14
|
+
* @version 0.0.1
|
|
15
|
+
* @since 0.0.1
|
|
16
|
+
* @author AMBROISE PARK Consulting
|
|
17
|
+
*/
|
|
18
|
+
export const APP_NAME = '{{appName}}';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Application short name constant
|
|
22
|
+
*
|
|
23
|
+
* @version 0.0.1
|
|
24
|
+
* @since 0.0.1
|
|
25
|
+
* @author AMBROISE PARK Consulting
|
|
26
|
+
*/
|
|
27
|
+
export const APP_SHORT_NAME = '{{appShortName}}';
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Application description constant
|
|
31
|
+
*
|
|
32
|
+
* @version 0.0.1
|
|
33
|
+
* @since 0.0.1
|
|
34
|
+
* @author AMBROISE PARK Consulting
|
|
35
|
+
*/
|
|
36
|
+
export const APP_DESCRIPTION = 'DoNotDev Components Demo';
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Application configuration object
|
|
40
|
+
*
|
|
41
|
+
* @version 0.0.1
|
|
42
|
+
* @since 0.0.1
|
|
43
|
+
* @author AMBROISE PARK Consulting
|
|
44
|
+
*/
|
|
45
|
+
export const appConfig: AppConfig = {
|
|
46
|
+
app: {
|
|
47
|
+
name: APP_NAME,
|
|
48
|
+
shortName: APP_SHORT_NAME,
|
|
49
|
+
description: APP_DESCRIPTION,
|
|
50
|
+
},
|
|
51
|
+
preset: 'landing', // 'landing' | 'admin' | 'moolti' | 'docs' | 'blog' | 'game' | 'plain'
|
|
52
|
+
features: {
|
|
53
|
+
// Optional: Enable debug tools in development
|
|
54
|
+
// debug: true,
|
|
55
|
+
},
|
|
56
|
+
};
|
|
@@ -49,7 +49,7 @@ export function DemoLayout({
|
|
|
49
49
|
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
|
|
50
50
|
const location = useLocation();
|
|
51
51
|
const navigate = useNavigate();
|
|
52
|
-
const
|
|
52
|
+
const isLaptop = useMediaQuery('(min-width: 1024px)');
|
|
53
53
|
|
|
54
54
|
const handleBack = () => {
|
|
55
55
|
if (location.pathname === '/full') {
|
|
@@ -140,11 +140,11 @@ export function DemoLayout({
|
|
|
140
140
|
return (
|
|
141
141
|
<Grid
|
|
142
142
|
className="dndev-h-screen dndev-w-full dndev-overflow-hidden"
|
|
143
|
-
templateColumns={
|
|
144
|
-
areas={
|
|
143
|
+
templateColumns={isLaptop ? '280px 1fr' : '1fr'}
|
|
144
|
+
areas={isLaptop ? 'sidebar main' : 'main'}
|
|
145
145
|
gap="none"
|
|
146
146
|
>
|
|
147
|
-
{
|
|
147
|
+
{isLaptop && (
|
|
148
148
|
<GridArea
|
|
149
149
|
name="sidebar"
|
|
150
150
|
style={{
|
|
@@ -224,7 +224,7 @@ export function DemoLayout({
|
|
|
224
224
|
{/* Right side: Theme Toggle + Mobile Menu */}
|
|
225
225
|
<Stack direction="row" gap="medium" justify="end" align="center">
|
|
226
226
|
<ThemeToggle />
|
|
227
|
-
{!
|
|
227
|
+
{!isLaptop && (
|
|
228
228
|
<Sheet
|
|
229
229
|
open={isMobileMenuOpen}
|
|
230
230
|
onOpenChange={setIsMobileMenuOpen}
|
|
@@ -6,7 +6,6 @@ import { appConfig } from '../config/app';
|
|
|
6
6
|
|
|
7
7
|
interface ClientLayoutProps {
|
|
8
8
|
children: React.ReactNode;
|
|
9
|
-
serverCookies?: string;
|
|
10
9
|
}
|
|
11
10
|
|
|
12
11
|
/**
|
|
@@ -17,15 +16,16 @@ interface ClientLayoutProps {
|
|
|
17
16
|
* Layout prop is for breadcrumbs and slot customizations only.
|
|
18
17
|
* CSS variable overrides should be done in themes.css.
|
|
19
18
|
* Override only what you need - everything else has sensible defaults.
|
|
19
|
+
*
|
|
20
|
+
* Theme detection happens client-side to avoid Next.js 16 race condition.
|
|
20
21
|
*/
|
|
21
|
-
export function ClientLayout({ children
|
|
22
|
+
export function ClientLayout({ children }: ClientLayoutProps) {
|
|
22
23
|
return (
|
|
23
24
|
<div id="root">
|
|
24
25
|
<NextJsAppProviders
|
|
25
26
|
config={appConfig}
|
|
26
|
-
serverCookies={serverCookies}
|
|
27
27
|
layout={{
|
|
28
|
-
breadcrumbs: 'smart', // 'smart' | 'always' | 'never'
|
|
28
|
+
breadcrumbs: 'smart', // 'smart' | 'always' | 'never'
|
|
29
29
|
header: {
|
|
30
30
|
// end: () => <YourHeaderActions />,
|
|
31
31
|
},
|
|
@@ -37,3 +37,4 @@ export function ClientLayout({ children, serverCookies }: ClientLayoutProps) {
|
|
|
37
37
|
</div>
|
|
38
38
|
);
|
|
39
39
|
}
|
|
40
|
+
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import type { Metadata } from 'next';
|
|
2
|
-
import { cookies } from 'next/headers';
|
|
3
2
|
import '../globals.css';
|
|
4
3
|
import { ClientLayout } from './ClientLayout';
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* Framework fonts are loaded via CSS @font-face rules in dndev.css
|
|
8
7
|
*
|
|
9
|
-
* The framework CSS includes optimized @font-face declarations for
|
|
10
|
-
* with proper unicode-range subsetting for performance.
|
|
8
|
+
* The framework CSS includes optimized @font-face declarations for Inter
|
|
9
|
+
* (default) and Roboto (optional) with proper unicode-range subsetting for performance.
|
|
11
10
|
* Fonts are copied from framework to public/fonts/ by AssetDiscovery during build.
|
|
12
11
|
*/
|
|
13
12
|
|
|
@@ -16,36 +15,29 @@ export const metadata: Metadata = {
|
|
|
16
15
|
description: 'Next.js site using DNDev framework',
|
|
17
16
|
};
|
|
18
17
|
|
|
19
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Root layout for Next.js App Router
|
|
20
|
+
*
|
|
21
|
+
* Theme detection happens client-side via ClientLayout to avoid
|
|
22
|
+
* Next.js 16 + Turbopack race condition with async layouts.
|
|
23
|
+
* Brief FOUC possible on first load, but prevents build-manifest.json errors.
|
|
24
|
+
*/
|
|
25
|
+
export default function RootLayout({
|
|
20
26
|
children,
|
|
21
27
|
}: {
|
|
22
28
|
children: React.ReactNode;
|
|
23
29
|
}) {
|
|
24
|
-
/**
|
|
25
|
-
* SSR: Read theme from cookies to apply correct theme class to HTML
|
|
26
|
-
*
|
|
27
|
-
* This ensures the server-rendered HTML has the correct theme class,
|
|
28
|
-
* preventing FOUC (Flash of Unstyled Content) when client hydrates.
|
|
29
|
-
*
|
|
30
|
-
* Flow:
|
|
31
|
-
* 1. Server reads cookie → applies theme class to <html>/<body>
|
|
32
|
-
* 2. NextJsStoresInitializer hydrates store from cookie
|
|
33
|
-
* 3. Client hydrates → Zustand persist matches server state
|
|
34
|
-
* 4. setAvailableThemes() ensures DOM matches persisted theme
|
|
35
|
-
*/
|
|
36
|
-
const cookieStore = await cookies();
|
|
37
|
-
const themeCookie = cookieStore.get('dndev-theme');
|
|
38
|
-
const themeClass = themeCookie?.value || 'light';
|
|
39
|
-
|
|
40
30
|
return (
|
|
41
|
-
<html
|
|
31
|
+
<html
|
|
32
|
+
lang="en"
|
|
33
|
+
className="dndev-design-tokens light"
|
|
34
|
+
suppressHydrationWarning
|
|
35
|
+
>
|
|
42
36
|
<head>
|
|
43
37
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
44
38
|
</head>
|
|
45
|
-
<body className=
|
|
46
|
-
<ClientLayout
|
|
47
|
-
{children}
|
|
48
|
-
</ClientLayout>
|
|
39
|
+
<body className="light">
|
|
40
|
+
<ClientLayout>{children}</ClientLayout>
|
|
49
41
|
</body>
|
|
50
42
|
</html>
|
|
51
43
|
);
|
|
@@ -6,10 +6,13 @@
|
|
|
6
6
|
/**
|
|
7
7
|
* Font configuration
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
* Framework defaults to Inter (defined in @donotdev/components/styles/variables.css).
|
|
10
|
+
* Fonts are loaded via CSS @font-face rules in @donotdev/ui/assets/fonts/fonts.css
|
|
11
|
+
* and copied to public/fonts/ by AssetDiscovery during build.
|
|
12
|
+
*
|
|
13
|
+
* To override, uncomment and customize:
|
|
14
|
+
* :root {
|
|
15
|
+
* --font-sans: 'YourFont', sans-serif;
|
|
16
|
+
* --font-family: var(--font-sans);
|
|
17
|
+
* }
|
|
18
|
+
*/
|
|
@@ -496,6 +496,10 @@
|
|
|
496
496
|
"copied": "Copied!",
|
|
497
497
|
"copyCodeToClipboard": "Copy code to clipboard"
|
|
498
498
|
},
|
|
499
|
+
"video": {
|
|
500
|
+
"clickToWatch": "Click to watch video",
|
|
501
|
+
"watchVideo": "Watch Video"
|
|
502
|
+
},
|
|
499
503
|
"inspector": {
|
|
500
504
|
"pageSource": "Page Source",
|
|
501
505
|
"inspectPageSourceCode": "Inspect page source code"
|
|
@@ -512,5 +516,69 @@
|
|
|
512
516
|
"goHome": "Go Home",
|
|
513
517
|
"goBack": "Go Back",
|
|
514
518
|
"contactSupport": "If the problem persists, please contact support."
|
|
519
|
+
},
|
|
520
|
+
"redirectOverlay": {
|
|
521
|
+
"phases": {
|
|
522
|
+
"connecting": "Connecting to secure server...",
|
|
523
|
+
"preparing": "Preparing your session...",
|
|
524
|
+
"redirecting": "Redirecting...",
|
|
525
|
+
"timeout": "Taking longer than expected..."
|
|
526
|
+
},
|
|
527
|
+
"cancel": "Cancel",
|
|
528
|
+
"doNotRefresh": "Please do not refresh or press back",
|
|
529
|
+
"default": {
|
|
530
|
+
"title": "Redirecting",
|
|
531
|
+
"message": "Please wait while we redirect you...",
|
|
532
|
+
"subtitle": "This may take a moment",
|
|
533
|
+
"ariaLabel": "Redirecting, please wait"
|
|
534
|
+
},
|
|
535
|
+
"stripe-checkout": {
|
|
536
|
+
"title": "Redirecting to Stripe",
|
|
537
|
+
"message": "Initializing secure payment...",
|
|
538
|
+
"subtitle": "This may take a moment on first load",
|
|
539
|
+
"ariaLabel": "Preparing secure checkout, please wait"
|
|
540
|
+
},
|
|
541
|
+
"stripe-portal": {
|
|
542
|
+
"title": "Redirecting to Stripe",
|
|
543
|
+
"message": "Opening billing portal...",
|
|
544
|
+
"subtitle": "Manage your subscription and invoices",
|
|
545
|
+
"ariaLabel": "Opening billing portal, please wait"
|
|
546
|
+
},
|
|
547
|
+
"oauth-google": {
|
|
548
|
+
"title": "Signing in with Google",
|
|
549
|
+
"message": "Connecting to Google...",
|
|
550
|
+
"subtitle": "You will be redirected to sign in",
|
|
551
|
+
"ariaLabel": "Signing in with Google, please wait"
|
|
552
|
+
},
|
|
553
|
+
"oauth-github": {
|
|
554
|
+
"title": "Signing in with GitHub",
|
|
555
|
+
"message": "Connecting to GitHub...",
|
|
556
|
+
"subtitle": "You will be redirected to sign in",
|
|
557
|
+
"ariaLabel": "Signing in with GitHub, please wait"
|
|
558
|
+
},
|
|
559
|
+
"oauth-apple": {
|
|
560
|
+
"title": "Signing in with Apple",
|
|
561
|
+
"message": "Connecting to Apple...",
|
|
562
|
+
"subtitle": "You will be redirected to sign in",
|
|
563
|
+
"ariaLabel": "Signing in with Apple, please wait"
|
|
564
|
+
},
|
|
565
|
+
"oauth-microsoft": {
|
|
566
|
+
"title": "Signing in with Microsoft",
|
|
567
|
+
"message": "Connecting to Microsoft...",
|
|
568
|
+
"subtitle": "You will be redirected to sign in",
|
|
569
|
+
"ariaLabel": "Signing in with Microsoft, please wait"
|
|
570
|
+
},
|
|
571
|
+
"oauth-facebook": {
|
|
572
|
+
"title": "Signing in with Facebook",
|
|
573
|
+
"message": "Connecting to Facebook...",
|
|
574
|
+
"subtitle": "You will be redirected to sign in",
|
|
575
|
+
"ariaLabel": "Signing in with Facebook, please wait"
|
|
576
|
+
},
|
|
577
|
+
"auth-email-link": {
|
|
578
|
+
"title": "Sending verification",
|
|
579
|
+
"message": "Preparing your verification link...",
|
|
580
|
+
"subtitle": "Check your email inbox",
|
|
581
|
+
"ariaLabel": "Sending verification email, please wait"
|
|
582
|
+
}
|
|
515
583
|
}
|
|
516
584
|
}
|
|
@@ -30,6 +30,9 @@
|
|
|
30
30
|
<title>Loading...</title>
|
|
31
31
|
<meta name="description" content="Modern web application powered by DoNotDev" />
|
|
32
32
|
|
|
33
|
+
<!-- ✅ PERFORMANCE: Critical font preloads (loads before CSS) -->
|
|
34
|
+
<!-- Only preload fonts with font-display: swap (not optional) -->
|
|
35
|
+
<!-- Example: <link rel="preload" href="/fonts/YourFont.woff2" as="font" type="font/woff2" crossorigin="anonymous"> -->
|
|
33
36
|
|
|
34
37
|
<!-- ✅ PERFORMANCE: Critical CSS inlined here by build -->
|
|
35
38
|
<style>
|
|
@@ -29,7 +29,7 @@ export function App() {
|
|
|
29
29
|
<ViteAppProviders
|
|
30
30
|
config={appConfig}
|
|
31
31
|
layout={{
|
|
32
|
-
breadcrumbs: 'smart', // 'smart' | 'always' | 'never'
|
|
32
|
+
breadcrumbs: 'smart', // 'smart' | 'always' | 'never'
|
|
33
33
|
header: {
|
|
34
34
|
// end: () => <YourHeaderActions />,
|
|
35
35
|
},
|
|
@@ -3,9 +3,17 @@
|
|
|
3
3
|
|
|
4
4
|
@import './themes.css';
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Font configuration
|
|
8
|
+
*
|
|
9
|
+
* Framework defaults to Inter (defined in @donotdev/components/styles/variables.css).
|
|
10
|
+
* Fonts are loaded via CSS @font-face rules in @donotdev/ui/assets/fonts/fonts.css
|
|
11
|
+
* and copied to public/fonts/ by AssetDiscovery during build.
|
|
12
|
+
*
|
|
13
|
+
* To override, uncomment and customize:
|
|
14
|
+
* :root {
|
|
15
|
+
* --font-sans: 'YourFont', sans-serif;
|
|
16
|
+
* --font-mono: 'YourMonoFont', monospace;
|
|
17
|
+
* --font-family: var(--font-sans);
|
|
18
|
+
* }
|
|
19
|
+
*/
|
|
@@ -496,6 +496,10 @@
|
|
|
496
496
|
"copied": "Copied!",
|
|
497
497
|
"copyCodeToClipboard": "Copy code to clipboard"
|
|
498
498
|
},
|
|
499
|
+
"video": {
|
|
500
|
+
"clickToWatch": "Click to watch video",
|
|
501
|
+
"watchVideo": "Watch Video"
|
|
502
|
+
},
|
|
499
503
|
"inspector": {
|
|
500
504
|
"pageSource": "Page Source",
|
|
501
505
|
"inspectPageSourceCode": "Inspect page source code"
|
|
@@ -512,5 +516,69 @@
|
|
|
512
516
|
"goHome": "Go Home",
|
|
513
517
|
"goBack": "Go Back",
|
|
514
518
|
"contactSupport": "If the problem persists, please contact support."
|
|
519
|
+
},
|
|
520
|
+
"redirectOverlay": {
|
|
521
|
+
"phases": {
|
|
522
|
+
"connecting": "Connecting to secure server...",
|
|
523
|
+
"preparing": "Preparing your session...",
|
|
524
|
+
"redirecting": "Redirecting...",
|
|
525
|
+
"timeout": "Taking longer than expected..."
|
|
526
|
+
},
|
|
527
|
+
"cancel": "Cancel",
|
|
528
|
+
"doNotRefresh": "Please do not refresh or press back",
|
|
529
|
+
"default": {
|
|
530
|
+
"title": "Redirecting",
|
|
531
|
+
"message": "Please wait while we redirect you...",
|
|
532
|
+
"subtitle": "This may take a moment",
|
|
533
|
+
"ariaLabel": "Redirecting, please wait"
|
|
534
|
+
},
|
|
535
|
+
"stripe-checkout": {
|
|
536
|
+
"title": "Redirecting to Stripe",
|
|
537
|
+
"message": "Initializing secure payment...",
|
|
538
|
+
"subtitle": "This may take a moment on first load",
|
|
539
|
+
"ariaLabel": "Preparing secure checkout, please wait"
|
|
540
|
+
},
|
|
541
|
+
"stripe-portal": {
|
|
542
|
+
"title": "Redirecting to Stripe",
|
|
543
|
+
"message": "Opening billing portal...",
|
|
544
|
+
"subtitle": "Manage your subscription and invoices",
|
|
545
|
+
"ariaLabel": "Opening billing portal, please wait"
|
|
546
|
+
},
|
|
547
|
+
"oauth-google": {
|
|
548
|
+
"title": "Signing in with Google",
|
|
549
|
+
"message": "Connecting to Google...",
|
|
550
|
+
"subtitle": "You will be redirected to sign in",
|
|
551
|
+
"ariaLabel": "Signing in with Google, please wait"
|
|
552
|
+
},
|
|
553
|
+
"oauth-github": {
|
|
554
|
+
"title": "Signing in with GitHub",
|
|
555
|
+
"message": "Connecting to GitHub...",
|
|
556
|
+
"subtitle": "You will be redirected to sign in",
|
|
557
|
+
"ariaLabel": "Signing in with GitHub, please wait"
|
|
558
|
+
},
|
|
559
|
+
"oauth-apple": {
|
|
560
|
+
"title": "Signing in with Apple",
|
|
561
|
+
"message": "Connecting to Apple...",
|
|
562
|
+
"subtitle": "You will be redirected to sign in",
|
|
563
|
+
"ariaLabel": "Signing in with Apple, please wait"
|
|
564
|
+
},
|
|
565
|
+
"oauth-microsoft": {
|
|
566
|
+
"title": "Signing in with Microsoft",
|
|
567
|
+
"message": "Connecting to Microsoft...",
|
|
568
|
+
"subtitle": "You will be redirected to sign in",
|
|
569
|
+
"ariaLabel": "Signing in with Microsoft, please wait"
|
|
570
|
+
},
|
|
571
|
+
"oauth-facebook": {
|
|
572
|
+
"title": "Signing in with Facebook",
|
|
573
|
+
"message": "Connecting to Facebook...",
|
|
574
|
+
"subtitle": "You will be redirected to sign in",
|
|
575
|
+
"ariaLabel": "Signing in with Facebook, please wait"
|
|
576
|
+
},
|
|
577
|
+
"auth-email-link": {
|
|
578
|
+
"title": "Sending verification",
|
|
579
|
+
"message": "Preparing your verification link...",
|
|
580
|
+
"subtitle": "Check your email inbox",
|
|
581
|
+
"ariaLabel": "Sending verification email, please wait"
|
|
582
|
+
}
|
|
515
583
|
}
|
|
516
584
|
}
|
|
@@ -2,6 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
This directory contains the Firebase Functions for the {{APP_NAME}} app, generated using the DoNotDev framework's scaffolding system.
|
|
4
4
|
|
|
5
|
+
## ⚠️ CRITICAL: Import Rules
|
|
6
|
+
|
|
7
|
+
**Functions run on Node.js - you MUST use `/server` imports or your function will crash on deploy.**
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
// ✅ CORRECT - Functions MUST use /server imports
|
|
11
|
+
import { getFirebaseAdminAuth } from '@donotdev/firebase/server';
|
|
12
|
+
import { getFirebaseAdminFirestore } from '@donotdev/firebase/server';
|
|
13
|
+
import { handleError } from '@donotdev/core/server';
|
|
14
|
+
|
|
15
|
+
// ❌ WRONG - This will crash on deploy (pulls in React/client code)
|
|
16
|
+
import { getAuth } from '@donotdev/firebase';
|
|
17
|
+
import { getFirestore } from '@donotdev/firebase';
|
|
18
|
+
import { handleError } from '@donotdev/core';
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**Why?** Functions run in Node.js, not the browser. Client imports (`@donotdev/firebase`) include React and browser-only code that will crash your function.
|
|
22
|
+
|
|
23
|
+
**Rule:** Always use `/server` suffix for:
|
|
24
|
+
- `@donotdev/firebase/server` (not `@donotdev/firebase`)
|
|
25
|
+
- `@donotdev/core/server` (not `@donotdev/core`)
|
|
26
|
+
- `@donotdev/utils/server` (not `@donotdev/utils`)
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
5
30
|
## Structure
|
|
6
31
|
|
|
7
32
|
```
|
|
@@ -1,18 +1,8 @@
|
|
|
1
1
|
{
|
|
2
|
+
"extends": "../../../tsconfig.functions.json",
|
|
2
3
|
"compilerOptions": {
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"moduleResolution": "NodeNext",
|
|
6
|
-
"lib": ["ES2022"],
|
|
7
|
-
"strict": true,
|
|
8
|
-
"skipLibCheck": true,
|
|
9
|
-
"esModuleInterop": true,
|
|
10
|
-
"resolveJsonModule": true,
|
|
11
|
-
"isolatedModules": true,
|
|
12
|
-
"forceConsistentCasingInFileNames": true,
|
|
13
|
-
"allowSyntheticDefaultImports": true,
|
|
14
|
-
"noUncheckedIndexedAccess": true,
|
|
15
|
-
"types": ["node"],
|
|
4
|
+
"module": "preserve",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
16
6
|
"outDir": "./lib",
|
|
17
7
|
"rootDir": "./src",
|
|
18
8
|
"declaration": true,
|
|
@@ -1,18 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
+
"extends": "../../../tsconfig.functions.json",
|
|
2
3
|
"compilerOptions": {
|
|
3
|
-
"target": "ES2022",
|
|
4
|
-
"module": "NodeNext",
|
|
5
|
-
"moduleResolution": "NodeNext",
|
|
6
|
-
"lib": ["ES2022"],
|
|
7
|
-
"strict": true,
|
|
8
|
-
"skipLibCheck": true,
|
|
9
|
-
"esModuleInterop": true,
|
|
10
|
-
"resolveJsonModule": true,
|
|
11
|
-
"isolatedModules": true,
|
|
12
|
-
"forceConsistentCasingInFileNames": true,
|
|
13
|
-
"allowSyntheticDefaultImports": true,
|
|
14
|
-
"noUncheckedIndexedAccess": true,
|
|
15
|
-
"types": ["node"],
|
|
16
4
|
"outDir": "./lib",
|
|
17
5
|
"rootDir": "./src",
|
|
18
6
|
"declaration": true,
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
},
|
|
32
32
|
{
|
|
33
33
|
"key": "Content-Security-Policy",
|
|
34
|
-
"value": "default-src 'self'; script-src 'self' https://accounts.google.com https://apis.google.com https://www.google.com https://www.gstatic.com; connect-src 'self' http://localhost:* ws://localhost:* https://accounts.google.com https://apis.google.com https://www.googleapis.com https://identitytoolkit.googleapis.com https://securetoken.googleapis.com https://firestore.googleapis.com https://{{YOUR_FIREBASE_PROJECT_ID}}.firebaseio.com https://{{YOUR_REGION}}-{{YOUR_FIREBASE_PROJECT_ID}}.cloudfunctions.net https://*.a.run.app https://{{YOUR_FIREBASE_PROJECT_ID}}.firebasestorage.app https://recaptchaenterprise.googleapis.com https://content-firebaseappcheck.googleapis.com https://firebaseappcheck.googleapis.com https://www.google.com https://github.com https://api.github.com https://api.stripe.com https://checkout.stripe.com; img-src 'self' data: https: http://localhost:* https://avatars.githubusercontent.com https://lh3.googleusercontent.com https://{{YOUR_FIREBASE_PROJECT_ID}}.firebasestorage.app; frame-src 'self' http://localhost:* https://accounts.google.com https://checkout.stripe.com https://js.stripe.com https://www.google.com https://recaptcha.google.com; font-src 'self' data:; style-src 'self' 'unsafe-inline'; object-src 'none'; base-uri 'self'; form-action 'self' http://localhost:* https://accounts.google.com https://github.com https://checkout.stripe.com"
|
|
34
|
+
"value": "default-src 'self'; script-src 'self' https://accounts.google.com https://apis.google.com https://www.google.com https://www.gstatic.com; connect-src 'self' http://localhost:* ws://localhost:* https://accounts.google.com https://apis.google.com https://www.googleapis.com https://identitytoolkit.googleapis.com https://securetoken.googleapis.com https://firestore.googleapis.com https://{{YOUR_FIREBASE_PROJECT_ID}}.firebaseio.com https://{{YOUR_REGION}}-{{YOUR_FIREBASE_PROJECT_ID}}.cloudfunctions.net https://*.a.run.app https://{{YOUR_FIREBASE_PROJECT_ID}}.firebasestorage.app https://recaptchaenterprise.googleapis.com https://content-firebaseappcheck.googleapis.com https://firebaseappcheck.googleapis.com https://www.google.com https://github.com https://api.github.com https://api.stripe.com https://checkout.stripe.com; img-src 'self' data: blob: https: http://localhost:* https://avatars.githubusercontent.com https://lh3.googleusercontent.com https://{{YOUR_FIREBASE_PROJECT_ID}}.firebasestorage.app; frame-src 'self' http://localhost:* https://accounts.google.com https://checkout.stripe.com https://js.stripe.com https://www.google.com https://recaptcha.google.com; font-src 'self' data:; style-src 'self' 'unsafe-inline'; object-src 'none'; base-uri 'self'; form-action 'self' http://localhost:* https://accounts.google.com https://github.com https://checkout.stripe.com"
|
|
35
35
|
},
|
|
36
36
|
{
|
|
37
37
|
"key": "X-Content-Type-Options",
|