@donotdev/cli 0.0.6 → 0.0.8
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/README.md +3 -18
- package/dependencies-matrix.json +64 -121
- package/dist/bin/commands/build.js +173 -161
- package/dist/bin/commands/bump.js +181 -156
- package/dist/bin/commands/cacheout.js +188 -171
- package/dist/bin/commands/create-app.js +213 -156
- package/dist/bin/commands/create-project.js +183 -154
- package/dist/bin/commands/deploy.js +491 -477
- package/dist/bin/commands/dev.js +176 -160
- package/dist/bin/commands/emu.js +181 -165
- package/dist/bin/commands/format.js +191 -174
- package/dist/bin/commands/lint.js +191 -171
- package/dist/bin/commands/preview.js +177 -161
- package/dist/bin/commands/sync-secrets.js +172 -158
- package/dist/bin/commands/wai.d.ts +11 -0
- package/dist/bin/commands/wai.d.ts.map +1 -0
- package/dist/bin/commands/wai.js +12 -0
- package/dist/bin/commands/wai.js.map +1 -0
- package/dist/bin/dndev.js +24 -24
- package/dist/bin/donotdev.js +24 -24
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +661 -669
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/app-demo/src/config/app.ts.example +12 -0
- package/templates/app-next/src/config/app.ts.example +75 -48
- package/templates/app-vite/index.html.example +71 -37
- package/templates/app-vite/src/config/app.ts.example +75 -47
- package/templates/app-vite/src/pages/FormPageExample.tsx.example +152 -0
- package/templates/app-vite/src/pages/HomePage.tsx.example +81 -134
- package/templates/app-vite/src/pages/ListPageExample.tsx.example +88 -0
- package/templates/functions-firebase/build.mjs.example +8 -1
- package/templates/functions-firebase/functions-firebase/build.mjs.example +8 -1
- package/templates/functions-firebase/functions-firebase/src/index.ts.example +19 -25
- package/templates/functions-firebase/functions.config.js.example +35 -0
- package/templates/root-consumer/entities/ExampleEntity.ts.example +223 -0
- package/templates/root-consumer/entities/demo.ts.example +576 -0
- package/templates/root-consumer/entities/index.ts.example +15 -0
- package/templates/root-consumer/eslint.config.js.example +2 -80
- package/templates/root-consumer/guides/{AGENT_START_HERE.md.example → dndev/AGENT_START_HERE.md.example} +22 -0
- package/templates/root-consumer/guides/dndev/COMPONENTS_CRUD.md.example +231 -0
- package/templates/root-consumer/guides/{SETUP_AUTH.md.example → dndev/SETUP_AUTH.md.example} +30 -0
- package/templates/root-consumer/guides/dndev/SETUP_CRUD.md.example +539 -0
- package/templates/root-consumer/guides/dndev/SETUP_FUNCTIONS.md.example +116 -0
- package/templates/root-consumer/guides/{SETUP_I18N.md.example → dndev/SETUP_I18N.md.example} +46 -0
- package/templates/root-consumer/guides/wai-way/WAI_WAY_CLI.md.example +404 -0
- package/templates/root-consumer/guides/wai-way/agents/architect.md.example +78 -0
- package/templates/root-consumer/guides/wai-way/agents/builder.md.example +87 -0
- package/templates/root-consumer/guides/wai-way/agents/extractor.md.example +325 -0
- package/templates/root-consumer/guides/wai-way/agents/polisher.md.example +100 -0
- package/templates/root-consumer/guides/wai-way/blueprints/0_brainstorm.md.example +281 -0
- package/templates/root-consumer/guides/wai-way/blueprints/1_scaffold.md.example +77 -0
- package/templates/root-consumer/guides/wai-way/blueprints/2_entities.md.example +104 -0
- package/templates/root-consumer/guides/wai-way/blueprints/3_compose.md.example +124 -0
- package/templates/root-consumer/guides/wai-way/blueprints/4_configure.md.example +165 -0
- package/templates/root-consumer/guides/wai-way/context_map.json.example +95 -0
- package/templates/root-consumer/guides/wai-way/entity_patterns.md.example +840 -0
- package/templates/root-consumer/guides/wai-way/page_patterns.md.example +686 -0
- package/templates/root-consumer/guides/wai-way/presets_guide.md.example +217 -0
- package/templates/root-consumer/guides/wai-way/spec_template.md.example +312 -0
- package/templates/functions-firebase/functions-firebase/src/crud/createEntity.ts.example +0 -19
- package/templates/functions-firebase/functions-firebase/src/crud/deleteEntity.ts.example +0 -14
- package/templates/functions-firebase/functions-firebase/src/crud/getEntity.ts.example +0 -14
- package/templates/functions-firebase/functions-firebase/src/crud/index.ts.example +0 -12
- package/templates/functions-firebase/functions-firebase/src/crud/listEntities.ts.example +0 -14
- package/templates/functions-firebase/functions-firebase/src/crud/updateEntity.ts.example +0 -14
- package/templates/root-consumer/guides/COMPONENTS_CRUD.md.example +0 -70
- package/templates/root-consumer/guides/SETUP_CRUD.md.example +0 -1244
- package/templates/root-consumer/guides/SETUP_FUNCTIONS.md.example +0 -114
- /package/templates/root-consumer/guides/{COMPONENTS_ADV.md.example → dndev/COMPONENTS_ADV.md.example} +0 -0
- /package/templates/root-consumer/guides/{COMPONENTS_ATOMIC.md.example → dndev/COMPONENTS_ATOMIC.md.example} +0 -0
- /package/templates/root-consumer/guides/{COMPONENTS_UI.md.example → dndev/COMPONENTS_UI.md.example} +0 -0
- /package/templates/root-consumer/guides/{ENV_SETUP.md.example → dndev/ENV_SETUP.md.example} +0 -0
- /package/templates/root-consumer/guides/{INDEX.md.example → dndev/INDEX.md.example} +0 -0
- /package/templates/root-consumer/guides/{SETUP_APP_CONFIG.md.example → dndev/SETUP_APP_CONFIG.md.example} +0 -0
- /package/templates/root-consumer/guides/{SETUP_BILLING.md.example → dndev/SETUP_BILLING.md.example} +0 -0
- /package/templates/root-consumer/guides/{SETUP_LAYOUTS.md.example → dndev/SETUP_LAYOUTS.md.example} +0 -0
- /package/templates/root-consumer/guides/{SETUP_OAUTH.md.example → dndev/SETUP_OAUTH.md.example} +0 -0
- /package/templates/root-consumer/guides/{SETUP_PAGES.md.example → dndev/SETUP_PAGES.md.example} +0 -0
- /package/templates/root-consumer/guides/{SETUP_PWA.md.example → dndev/SETUP_PWA.md.example} +0 -0
- /package/templates/root-consumer/guides/{SETUP_THEMES.md.example → dndev/SETUP_THEMES.md.example} +0 -0
- /package/templates/root-consumer/guides/{USE_ROUTING.md.example → dndev/USE_ROUTING.md.example} +0 -0
- /package/templates/root-consumer/guides/{advanced → dndev/advanced}/APP_CHECK.md.example +0 -0
- /package/templates/root-consumer/guides/{advanced → dndev/advanced}/COOKIE_REFERENCE.md.example +0 -0
- /package/templates/root-consumer/guides/{advanced → dndev/advanced}/EMULATORS.md.example +0 -0
- /package/templates/root-consumer/guides/{advanced → dndev/advanced}/VERSION_CONTROL.md.example +0 -0
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4BAA4B;AAE5B;;;;;GAKG;AAEH,qFAAqF;AACrF,OAAO,EACL,SAAS,EACT,aAAa,EACb,MAAM,EACN,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4BAA4B;AAE5B;;;;;GAKG;AAEH,qFAAqF;AACrF,OAAO,EACL,SAAS,EACT,aAAa,EACb,MAAM,EACN,GAAG,EACH,KAAK,EACL,OAAO,EACP,GAAG,EACH,QAAQ,EACR,WAAW,EACX,MAAM,GACP,MAAM,mBAAmB,CAAC"}
|
package/package.json
CHANGED
|
@@ -53,4 +53,16 @@ export const appConfig: AppConfig = {
|
|
|
53
53
|
// Optional: Enable debug tools in development
|
|
54
54
|
// debug: true,
|
|
55
55
|
},
|
|
56
|
+
// Optional: Override query cache defaults
|
|
57
|
+
// Framework defaults (infinite cache - cost-optimized):
|
|
58
|
+
// - staleTime: Infinity (data never becomes stale)
|
|
59
|
+
// - refetchOnWindowFocus: false (no auto-refetch on focus)
|
|
60
|
+
// - refetchOnReconnect: false (no auto-refetch on reconnect)
|
|
61
|
+
// This minimizes API costs and is ideal for single-admin apps with manual refresh buttons.
|
|
62
|
+
// Uncomment below to enable auto-refetch behavior:
|
|
63
|
+
// query: {
|
|
64
|
+
// staleTime: 1000 * 60 * 5, // 5 minutes - data becomes stale after 5 minutes
|
|
65
|
+
// refetchOnWindowFocus: true, // Automatically refetch when window regains focus
|
|
66
|
+
// refetchOnReconnect: true, // Automatically refetch when network reconnects
|
|
67
|
+
// },
|
|
56
68
|
};
|
|
@@ -1,75 +1,102 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @fileoverview Application
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
2
|
+
* @fileoverview Application Configuration
|
|
3
|
+
*
|
|
4
|
+
* THIS FILE IS YOUR MAIN CONFIGURATION. Update the values below.
|
|
5
|
+
*
|
|
6
|
+
* QUICK START:
|
|
7
|
+
* 1. Set APP_NAME and APP_SHORT_NAME
|
|
8
|
+
* 2. Choose your preset (see guide below)
|
|
9
|
+
* 3. Configure footer links
|
|
10
|
+
* 4. Run `bun dev` - everything else is automatic
|
|
7
11
|
*/
|
|
8
12
|
|
|
9
13
|
import type { AppConfig } from '@donotdev/core';
|
|
10
14
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
* @version 0.0.1
|
|
15
|
-
* @since 0.0.1
|
|
16
|
-
* @author AMBROISE PARK Consulting
|
|
17
|
-
*/
|
|
18
|
-
export const APP_NAME = '{{appName}}';
|
|
15
|
+
// ============================================================================
|
|
16
|
+
// APP IDENTITY - Update these values
|
|
17
|
+
// ============================================================================
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
* Application short name constant
|
|
22
|
-
*
|
|
23
|
-
* @version 0.0.1
|
|
24
|
-
* @since 0.0.1
|
|
25
|
-
* @author AMBROISE PARK Consulting
|
|
26
|
-
*/
|
|
19
|
+
export const APP_NAME = '{{appName}}';
|
|
27
20
|
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
21
|
export const APP_DESCRIPTION = 'Built with DoNotDev Framework';
|
|
37
22
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
* @since 0.0.1
|
|
43
|
-
* @author AMBROISE PARK Consulting
|
|
44
|
-
*/
|
|
23
|
+
// ============================================================================
|
|
24
|
+
// MAIN CONFIGURATION
|
|
25
|
+
// ============================================================================
|
|
26
|
+
|
|
45
27
|
export const appConfig: AppConfig = {
|
|
46
28
|
app: {
|
|
47
29
|
name: APP_NAME,
|
|
48
30
|
shortName: APP_SHORT_NAME,
|
|
49
31
|
description: APP_DESCRIPTION,
|
|
50
|
-
//
|
|
51
|
-
|
|
32
|
+
// url: 'https://yourapp.com', // Uncomment for production
|
|
33
|
+
|
|
34
|
+
// Footer legal links - remove any you don't need
|
|
52
35
|
footer: {
|
|
53
36
|
legalLinks: [
|
|
54
37
|
{ path: '#cookie-settings', label: 'footer.legal.cookieSettings' },
|
|
55
38
|
{ path: '/legal/privacy', label: 'footer.legal.privacyPolicy' },
|
|
56
39
|
{ path: '/legal/terms', label: 'footer.legal.termsOfService' },
|
|
57
|
-
//
|
|
58
|
-
// { path: '/legal/legal-notice', label: 'footer.legal.legalNotice' },
|
|
59
|
-
// { path: '/license', label: 'License' },
|
|
40
|
+
// { path: '/legal/notice', label: 'footer.legal.legalNotice' },
|
|
60
41
|
],
|
|
61
42
|
},
|
|
62
43
|
},
|
|
63
|
-
|
|
44
|
+
|
|
45
|
+
// ==========================================================================
|
|
46
|
+
// PRESET GUIDE - Choose your layout
|
|
47
|
+
// ==========================================================================
|
|
48
|
+
//
|
|
49
|
+
// 'landing' → Marketing site. Full-width sections, centered content, no sidebar.
|
|
50
|
+
// Best for: Homepage, product pages, pricing, landing pages.
|
|
51
|
+
//
|
|
52
|
+
// 'admin' → Dashboard app. Collapsible sidebar, header with user menu.
|
|
53
|
+
// Best for: Admin panels, CRM, internal tools, CRUD apps.
|
|
54
|
+
//
|
|
55
|
+
// 'moolti' → Multi-panel. Left sidebar nav, optional right context sidebar.
|
|
56
|
+
// Best for: Complex apps with nested navigation, settings panels.
|
|
57
|
+
//
|
|
58
|
+
// 'docs' → Documentation. Left sidebar TOC, right sidebar on-page nav.
|
|
59
|
+
// Best for: Documentation sites, knowledge bases, help centers.
|
|
60
|
+
//
|
|
61
|
+
// 'blog' → Blog layout. Wide content area, optional category sidebar.
|
|
62
|
+
// Best for: Blog, news, articles, content-heavy sites.
|
|
63
|
+
//
|
|
64
|
+
// 'game' → Fullscreen. Minimal chrome, focus on content area.
|
|
65
|
+
// Best for: Games, immersive experiences, presentations.
|
|
66
|
+
//
|
|
67
|
+
// 'plain' → No layout. Just your pages, you handle everything.
|
|
68
|
+
// Best for: Custom layouts, embedded widgets, special cases.
|
|
69
|
+
//
|
|
70
|
+
preset: 'docs',
|
|
71
|
+
|
|
72
|
+
// ==========================================================================
|
|
73
|
+
// FEATURES - Uncomment to enable
|
|
74
|
+
// ==========================================================================
|
|
64
75
|
features: {
|
|
65
|
-
//
|
|
66
|
-
// debug: true,
|
|
76
|
+
// debug: true, // Enable debug tools in development
|
|
67
77
|
},
|
|
68
|
-
|
|
78
|
+
|
|
79
|
+
// ==========================================================================
|
|
80
|
+
// AUTH CONFIG - Uncomment to customize
|
|
81
|
+
// ==========================================================================
|
|
69
82
|
// auth: {
|
|
70
|
-
// authRoute: '/signin',
|
|
71
|
-
// roleRoute: '/403',
|
|
72
|
-
// tierRoute: '/pricing',
|
|
83
|
+
// authRoute: '/signin', // Redirect when auth required
|
|
84
|
+
// roleRoute: '/403', // Redirect when role insufficient
|
|
85
|
+
// tierRoute: '/pricing', // Redirect when subscription required
|
|
86
|
+
// profilePath: '/profile', // Profile page path (undefined to hide)
|
|
87
|
+
// authMenuItems: [ // Custom menu items for logged-in users
|
|
88
|
+
// { path: '/dashboard', label: 'Dashboard' },
|
|
89
|
+
// ],
|
|
73
90
|
// },
|
|
74
|
-
};
|
|
75
91
|
|
|
92
|
+
// ==========================================================================
|
|
93
|
+
// QUERY CACHE - Uncomment to enable auto-refetch
|
|
94
|
+
// ==========================================================================
|
|
95
|
+
// Default: Infinite cache (cost-optimized, manual refresh)
|
|
96
|
+
// Uncomment for auto-refetch behavior:
|
|
97
|
+
// query: {
|
|
98
|
+
// staleTime: 1000 * 60 * 5, // 5 minutes
|
|
99
|
+
// refetchOnWindowFocus: true,
|
|
100
|
+
// refetchOnReconnect: true,
|
|
101
|
+
// },
|
|
102
|
+
};
|
|
@@ -16,6 +16,9 @@
|
|
|
16
16
|
<!-- ✅ PWA: Manifest link (if exists) -->
|
|
17
17
|
<link rel="manifest" href="/manifest.json" />
|
|
18
18
|
|
|
19
|
+
<!-- ✅ PERFORMANCE: Load fonts early to avoid preload warnings -->
|
|
20
|
+
<link rel="stylesheet" href="/fonts/fonts.css" />
|
|
21
|
+
|
|
19
22
|
<!-- ✅ PERFORMANCE: Preconnect to external domains (OAuth providers) -->
|
|
20
23
|
<!-- GitHub OAuth -->
|
|
21
24
|
<link rel="preconnect" href="https://github.com">
|
|
@@ -30,16 +33,17 @@
|
|
|
30
33
|
<title>Loading...</title>
|
|
31
34
|
<meta name="description" content="Modern web application powered by DoNotDev" />
|
|
32
35
|
|
|
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"> -->
|
|
36
36
|
|
|
37
37
|
<!-- ✅ PERFORMANCE: Critical CSS inlined here by build -->
|
|
38
38
|
<style>
|
|
39
39
|
/* Critical above-the-fold styles */
|
|
40
|
+
html, body {
|
|
41
|
+
margin: 0;
|
|
42
|
+
padding: 0;
|
|
43
|
+
box-sizing: border-box;
|
|
44
|
+
}
|
|
40
45
|
body {
|
|
41
|
-
|
|
42
|
-
font-family: var(--font-family, ui-monospace, 'SF Mono', 'Cascadia Code', 'Roboto Mono', Consolas, Monaco, 'Liberation Mono', monospace);
|
|
46
|
+
font-family: 'Inter', var(--font-family, ui-sans-serif, system-ui, -apple-system, sans-serif);
|
|
43
47
|
line-height: 1.5;
|
|
44
48
|
-webkit-font-smoothing: antialiased;
|
|
45
49
|
-moz-osx-font-smoothing: grayscale;
|
|
@@ -55,54 +59,85 @@
|
|
|
55
59
|
/* Critical shell loader styles - pure CSS, instant render */
|
|
56
60
|
#shell-loader {
|
|
57
61
|
position: fixed;
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
width: 100%;
|
|
61
|
-
height: 100%;
|
|
62
|
-
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
62
|
+
inset: 0;
|
|
63
|
+
background: #000000;
|
|
63
64
|
display: flex;
|
|
64
65
|
align-items: center;
|
|
65
66
|
justify-content: center;
|
|
66
67
|
z-index: 9999;
|
|
67
68
|
opacity: 1;
|
|
68
69
|
transition: opacity 0.3s ease-out;
|
|
70
|
+
will-change: opacity;
|
|
71
|
+
/* Isolate from framework CSS */
|
|
72
|
+
margin: 0;
|
|
73
|
+
padding: 0;
|
|
74
|
+
box-sizing: border-box;
|
|
69
75
|
}
|
|
70
76
|
#shell-loader.shell-loader--fading {
|
|
71
77
|
opacity: 0;
|
|
78
|
+
pointer-events: none;
|
|
72
79
|
}
|
|
73
80
|
.shell-loader__content {
|
|
74
81
|
text-align: center;
|
|
75
82
|
color: white;
|
|
76
|
-
font-family:
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
83
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
|
|
84
|
+
width: 100%;
|
|
85
|
+
max-width: 500px;
|
|
86
|
+
/* Prevent layout shifts from framework CSS */
|
|
87
|
+
margin: 0;
|
|
88
|
+
padding: 0;
|
|
89
|
+
box-sizing: border-box;
|
|
90
|
+
line-height: 1.2;
|
|
80
91
|
}
|
|
81
92
|
.shell-loader__brand {
|
|
82
93
|
display: block;
|
|
94
|
+
font-size: clamp(3rem, 10vw, 5rem);
|
|
95
|
+
font-weight: 800;
|
|
96
|
+
letter-spacing: -0.05em;
|
|
97
|
+
margin: 0 0 1rem 0;
|
|
98
|
+
padding: 0;
|
|
99
|
+
box-sizing: border-box;
|
|
83
100
|
}
|
|
101
|
+
/* ECG Waveform Animation - stroke-dasharray (performant, cross-browser, standard SVG technique) */
|
|
84
102
|
.shell-loader__dots {
|
|
85
|
-
display:
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
width: 12px;
|
|
92
|
-
height: 12px;
|
|
93
|
-
border-radius: 50%;
|
|
94
|
-
background: white;
|
|
95
|
-
animation: blink 1.4s infinite;
|
|
103
|
+
display: block;
|
|
104
|
+
width: 300px;
|
|
105
|
+
height: 60px;
|
|
106
|
+
margin: 0 auto;
|
|
107
|
+
padding: 0;
|
|
108
|
+
box-sizing: border-box;
|
|
96
109
|
}
|
|
97
|
-
.shell-loader__dots
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
.shell-loader__content > :last-child {
|
|
110
|
+
.shell-loader__dots svg {
|
|
111
|
+
width: 100%;
|
|
112
|
+
height: 100%;
|
|
101
113
|
display: block;
|
|
102
114
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
115
|
+
.shell-loader__dots path {
|
|
116
|
+
stroke: #667eea;
|
|
117
|
+
stroke-width: 3;
|
|
118
|
+
fill: none;
|
|
119
|
+
stroke-linecap: round;
|
|
120
|
+
stroke-linejoin: round;
|
|
121
|
+
stroke-dasharray: 400;
|
|
122
|
+
stroke-dashoffset: 400;
|
|
123
|
+
animation: ecg-draw 2s linear infinite;
|
|
124
|
+
}
|
|
125
|
+
@keyframes ecg-draw {
|
|
126
|
+
0% {
|
|
127
|
+
stroke-dashoffset: 400;
|
|
128
|
+
opacity: 0;
|
|
129
|
+
}
|
|
130
|
+
10% {
|
|
131
|
+
opacity: 1;
|
|
132
|
+
}
|
|
133
|
+
70% {
|
|
134
|
+
stroke-dashoffset: 0;
|
|
135
|
+
opacity: 1;
|
|
136
|
+
}
|
|
137
|
+
90%, 100% {
|
|
138
|
+
stroke-dashoffset: 0;
|
|
139
|
+
opacity: 0;
|
|
140
|
+
}
|
|
106
141
|
}
|
|
107
142
|
</style>
|
|
108
143
|
</head>
|
|
@@ -113,11 +148,10 @@
|
|
|
113
148
|
<div class="shell-loader__content">
|
|
114
149
|
<span class="shell-loader__brand">DoNotDev</span>
|
|
115
150
|
<span class="shell-loader__dots">
|
|
116
|
-
<
|
|
117
|
-
|
|
118
|
-
|
|
151
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 60" preserveAspectRatio="xMidYMid meet">
|
|
152
|
+
<path d="M0,30 L100,30 L110,20 L120,30 L130,30 L140,5 L150,55 L160,30 L175,30 L190,20 L205,30 L300,30" />
|
|
153
|
+
</svg>
|
|
119
154
|
</span>
|
|
120
|
-
<span>is loading</span>
|
|
121
155
|
</div>
|
|
122
156
|
</div>
|
|
123
157
|
|
|
@@ -127,4 +161,4 @@
|
|
|
127
161
|
<!-- ✅ PERFORMANCE: Module script with proper attributes -->
|
|
128
162
|
<script type="module" src="/src/main.tsx"></script>
|
|
129
163
|
</body>
|
|
130
|
-
</html>
|
|
164
|
+
</html>
|
|
@@ -1,75 +1,103 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @fileoverview Application
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
2
|
+
* @fileoverview Application Configuration
|
|
3
|
+
*
|
|
4
|
+
* THIS FILE IS YOUR MAIN CONFIGURATION. Update the values below.
|
|
5
|
+
*
|
|
6
|
+
* QUICK START:
|
|
7
|
+
* 1. Set APP_NAME and APP_SHORT_NAME
|
|
8
|
+
* 2. Choose your preset (see guide below)
|
|
9
|
+
* 3. Configure footer links
|
|
10
|
+
* 4. Run `bun dev` - everything else is automatic
|
|
7
11
|
*/
|
|
8
12
|
|
|
9
13
|
import type { AppConfig } from '@donotdev/core';
|
|
10
14
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
* @version 0.0.1
|
|
15
|
-
* @since 0.0.1
|
|
16
|
-
* @author AMBROISE PARK Consulting
|
|
17
|
-
*/
|
|
18
|
-
export const APP_NAME = '{{appName}}';
|
|
15
|
+
// ============================================================================
|
|
16
|
+
// APP IDENTITY - Update these values
|
|
17
|
+
// ============================================================================
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
* Application short name constant
|
|
22
|
-
*
|
|
23
|
-
* @version 0.0.1
|
|
24
|
-
* @since 0.0.1
|
|
25
|
-
* @author AMBROISE PARK Consulting
|
|
26
|
-
*/
|
|
19
|
+
export const APP_NAME = '{{appName}}';
|
|
27
20
|
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
21
|
export const APP_DESCRIPTION = 'Built with DoNotDev Framework';
|
|
37
22
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
* @since 0.0.1
|
|
43
|
-
* @author AMBROISE PARK Consulting
|
|
44
|
-
*/
|
|
23
|
+
// ============================================================================
|
|
24
|
+
// MAIN CONFIGURATION
|
|
25
|
+
// ============================================================================
|
|
26
|
+
|
|
45
27
|
export const appConfig: AppConfig = {
|
|
46
28
|
app: {
|
|
47
29
|
name: APP_NAME,
|
|
48
30
|
shortName: APP_SHORT_NAME,
|
|
49
31
|
description: APP_DESCRIPTION,
|
|
50
|
-
//
|
|
51
|
-
|
|
32
|
+
// url: 'https://yourapp.com', // Uncomment for production
|
|
33
|
+
|
|
34
|
+
// Footer legal links - remove any you don't need
|
|
52
35
|
footer: {
|
|
53
36
|
legalLinks: [
|
|
54
37
|
{ path: '#cookie-settings', label: 'footer.legal.cookieSettings' },
|
|
55
38
|
{ path: '/legal/privacy', label: 'footer.legal.privacyPolicy' },
|
|
56
39
|
{ path: '/legal/terms', label: 'footer.legal.termsOfService' },
|
|
57
|
-
//
|
|
58
|
-
// { path: '/legal/legal-notice', label: 'footer.legal.legalNotice' },
|
|
59
|
-
// { path: '/license', label: 'License' },
|
|
40
|
+
// { path: '/legal/notice', label: 'footer.legal.legalNotice' },
|
|
60
41
|
],
|
|
61
42
|
},
|
|
62
43
|
},
|
|
63
|
-
|
|
44
|
+
|
|
45
|
+
// ==========================================================================
|
|
46
|
+
// PRESET GUIDE - Choose your layout
|
|
47
|
+
// ==========================================================================
|
|
48
|
+
//
|
|
49
|
+
// 'landing' → Marketing site. Full-width sections, centered content, no sidebar.
|
|
50
|
+
// Best for: Homepage, product pages, pricing, landing pages.
|
|
51
|
+
//
|
|
52
|
+
// 'admin' → Dashboard app. Collapsible sidebar, header with user menu.
|
|
53
|
+
// Best for: Admin panels, CRM, internal tools, CRUD apps.
|
|
54
|
+
//
|
|
55
|
+
// 'moolti' → Multi-panel. Left sidebar nav, optional right context sidebar.
|
|
56
|
+
// Best for: Complex apps with nested navigation, settings panels.
|
|
57
|
+
//
|
|
58
|
+
// 'docs' → Documentation. Left sidebar TOC, right sidebar on-page nav.
|
|
59
|
+
// Best for: Documentation sites, knowledge bases, help centers.
|
|
60
|
+
//
|
|
61
|
+
// 'blog' → Blog layout. Wide content area, optional category sidebar.
|
|
62
|
+
// Best for: Blog, news, articles, content-heavy sites.
|
|
63
|
+
//
|
|
64
|
+
// 'game' → Fullscreen. Minimal chrome, focus on content area.
|
|
65
|
+
// Best for: Games, immersive experiences, presentations.
|
|
66
|
+
//
|
|
67
|
+
// 'plain' → No layout. Just your pages, you handle everything.
|
|
68
|
+
// Best for: Custom layouts, embedded widgets, special cases.
|
|
69
|
+
//
|
|
70
|
+
preset: 'landing',
|
|
71
|
+
|
|
72
|
+
// ==========================================================================
|
|
73
|
+
// FEATURES - Uncomment to enable
|
|
74
|
+
// ==========================================================================
|
|
64
75
|
features: {
|
|
65
|
-
//
|
|
66
|
-
// debug: true,
|
|
76
|
+
// debug: true, // Enable debug tools in development
|
|
67
77
|
},
|
|
68
|
-
|
|
78
|
+
|
|
79
|
+
// ==========================================================================
|
|
80
|
+
// AUTH CONFIG - Uncomment to customize
|
|
81
|
+
// ==========================================================================
|
|
69
82
|
// auth: {
|
|
70
|
-
// authRoute: '/signin',
|
|
71
|
-
// roleRoute: '/403',
|
|
72
|
-
// tierRoute: '/pricing',
|
|
83
|
+
// authRoute: '/signin', // Redirect when auth required
|
|
84
|
+
// roleRoute: '/403', // Redirect when role insufficient
|
|
85
|
+
// tierRoute: '/pricing', // Redirect when subscription required
|
|
86
|
+
// profilePath: '/profile', // Profile page path (undefined to hide)
|
|
87
|
+
// authMenuItems: [ // Custom menu items for logged-in users
|
|
88
|
+
// { path: '/dashboard', label: 'Dashboard' },
|
|
89
|
+
// ],
|
|
90
|
+
// },
|
|
91
|
+
|
|
92
|
+
// ==========================================================================
|
|
93
|
+
// QUERY CACHE - Uncomment to enable auto-refetch
|
|
94
|
+
// ==========================================================================
|
|
95
|
+
// Default: Infinite cache (cost-optimized, manual refresh)
|
|
96
|
+
// Uncomment for auto-refetch behavior:
|
|
97
|
+
// query: {
|
|
98
|
+
// staleTime: 1000 * 60 * 5, // 5 minutes
|
|
99
|
+
// refetchOnWindowFocus: true,
|
|
100
|
+
// refetchOnReconnect: true,
|
|
73
101
|
// },
|
|
74
102
|
};
|
|
75
103
|
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Example CRUD Form Page (Create/Edit)
|
|
3
|
+
*
|
|
4
|
+
* COPY THIS FILE and rename (e.g., ProductPage.tsx, CustomerPage.tsx)
|
|
5
|
+
*
|
|
6
|
+
* HOW IT WORKS:
|
|
7
|
+
* 1. Route: /products/:id (edit) or /products/new (create)
|
|
8
|
+
* 2. EntityFormRenderer generates form from entity fields
|
|
9
|
+
* 3. useCrud provides get/add/update operations
|
|
10
|
+
* 4. Optimistic updates - navigation is instant, sync happens in background
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { useEffect, useState } from 'react';
|
|
14
|
+
|
|
15
|
+
import { Section, Button, Alert } from '@donotdev/components';
|
|
16
|
+
import { EntityFormRenderer, useCrud } from '@donotdev/crud';
|
|
17
|
+
import { useTranslation } from '@donotdev/core';
|
|
18
|
+
import type { PageMeta } from '@donotdev/core';
|
|
19
|
+
import { PageContainer, Link, useNavigate } from '@donotdev/ui';
|
|
20
|
+
|
|
21
|
+
// Import your entity from root-level entities folder
|
|
22
|
+
// import { productEntity } from 'entities/Product';
|
|
23
|
+
|
|
24
|
+
// Placeholder - replace with your entity import
|
|
25
|
+
const productEntity = null as any;
|
|
26
|
+
|
|
27
|
+
// Helper to get route param - replace with your routing solution
|
|
28
|
+
const useParam = (name: string) => {
|
|
29
|
+
// For react-router: const { id } = useParams();
|
|
30
|
+
// For TanStack Router: const { id } = Route.useParams();
|
|
31
|
+
return 'new'; // Placeholder
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// ============================================================================
|
|
35
|
+
// PAGE METADATA
|
|
36
|
+
// ============================================================================
|
|
37
|
+
|
|
38
|
+
export const NAMESPACE = 'product';
|
|
39
|
+
|
|
40
|
+
export const meta: PageMeta = {
|
|
41
|
+
namespace: NAMESPACE,
|
|
42
|
+
route: '/products/:id',
|
|
43
|
+
auth: { required: true, role: 'admin' },
|
|
44
|
+
hideFromMenu: true, // Don't show in navigation (accessed via list page)
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// ============================================================================
|
|
48
|
+
// PAGE COMPONENT
|
|
49
|
+
// ============================================================================
|
|
50
|
+
|
|
51
|
+
export default function ProductPage() {
|
|
52
|
+
const { t } = useTranslation(NAMESPACE);
|
|
53
|
+
const id = useParam('id');
|
|
54
|
+
const navigate = useNavigate();
|
|
55
|
+
const isNew = id === 'new';
|
|
56
|
+
|
|
57
|
+
// useCrud provides CRUD operations with optimistic updates
|
|
58
|
+
// backend: 'functions' uses Cloud Functions, 'firestore' uses direct Firestore
|
|
59
|
+
const { get, add, update, error } = useCrud(productEntity, { backend: 'functions' });
|
|
60
|
+
const [formData, setFormData] = useState<any>(null);
|
|
61
|
+
|
|
62
|
+
// ==========================================================================
|
|
63
|
+
// FETCH EXISTING DATA (edit mode only)
|
|
64
|
+
// ==========================================================================
|
|
65
|
+
useEffect(() => {
|
|
66
|
+
if (!isNew && id) {
|
|
67
|
+
get(id).then((data) => {
|
|
68
|
+
if (data) setFormData(data);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}, [id, isNew, get]);
|
|
72
|
+
|
|
73
|
+
// ==========================================================================
|
|
74
|
+
// FORM SUBMISSION - Optimistic Update Pattern
|
|
75
|
+
// ==========================================================================
|
|
76
|
+
const handleSubmit = async (data: any) => {
|
|
77
|
+
// OPTIMISTIC UPDATE: Fire and forget!
|
|
78
|
+
// We don't await the backend. We navigate immediately.
|
|
79
|
+
// CrudStore handles background sync and optimistic cache update.
|
|
80
|
+
|
|
81
|
+
if (isNew) {
|
|
82
|
+
add(data); // No await - fires in background
|
|
83
|
+
} else if (id) {
|
|
84
|
+
update(id, data); // No await - fires in background
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Instant navigation - feels incredibly fast
|
|
88
|
+
navigate('/products');
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
// ==========================================================================
|
|
92
|
+
// ERROR STATE
|
|
93
|
+
// ==========================================================================
|
|
94
|
+
if (!isNew && error) {
|
|
95
|
+
return (
|
|
96
|
+
<PageContainer>
|
|
97
|
+
<Section title={t('error')}>
|
|
98
|
+
<Alert variant="error" description={t('failedToLoadData')} />
|
|
99
|
+
<Link path="/products">
|
|
100
|
+
<Button variant="outline">{t('backToList')}</Button>
|
|
101
|
+
</Link>
|
|
102
|
+
</Section>
|
|
103
|
+
</PageContainer>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// ==========================================================================
|
|
108
|
+
// RENDER FORM
|
|
109
|
+
// ==========================================================================
|
|
110
|
+
return (
|
|
111
|
+
<PageContainer>
|
|
112
|
+
<Section
|
|
113
|
+
gridCols={[1, 1, 2, 2]} // Responsive: 1 col mobile, 2 cols desktop
|
|
114
|
+
title={isNew ? t('addNew') : t('edit')}
|
|
115
|
+
>
|
|
116
|
+
{isNew ? (
|
|
117
|
+
// CREATE MODE
|
|
118
|
+
<EntityFormRenderer
|
|
119
|
+
entity={productEntity}
|
|
120
|
+
operation="create"
|
|
121
|
+
onSubmit={handleSubmit}
|
|
122
|
+
defaultValues={{ status: 'draft' }} // Initial values for new items
|
|
123
|
+
submitText={t('create')}
|
|
124
|
+
/>
|
|
125
|
+
) : (
|
|
126
|
+
// EDIT MODE
|
|
127
|
+
<EntityFormRenderer
|
|
128
|
+
entity={productEntity}
|
|
129
|
+
operation="edit"
|
|
130
|
+
onSubmit={handleSubmit}
|
|
131
|
+
defaultValues={formData} // Loaded data
|
|
132
|
+
submitText={t('update')}
|
|
133
|
+
/>
|
|
134
|
+
)}
|
|
135
|
+
</Section>
|
|
136
|
+
</PageContainer>
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// ============================================================================
|
|
141
|
+
// i18n KEYS NEEDED (add to locales/product_en.json)
|
|
142
|
+
// ============================================================================
|
|
143
|
+
//
|
|
144
|
+
// {
|
|
145
|
+
// "addNew": "Add New Product",
|
|
146
|
+
// "edit": "Edit Product",
|
|
147
|
+
// "create": "Create Product",
|
|
148
|
+
// "update": "Update Product",
|
|
149
|
+
// "error": "Error",
|
|
150
|
+
// "failedToLoadData": "Failed to load product data",
|
|
151
|
+
// "backToList": "Back to Products"
|
|
152
|
+
// }
|