@promakeai/cli 0.10.0 → 0.10.1

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.
Files changed (137) hide show
  1. package/README.md +111 -111
  2. package/dist/index.js +142 -142
  3. package/dist/registry/about-page.json +3 -3
  4. package/dist/registry/about-section.json +4 -4
  5. package/dist/registry/animations.json +2 -2
  6. package/dist/registry/announcement-bar.json +4 -4
  7. package/dist/registry/api.json +1 -1
  8. package/dist/registry/auth-core.json +2 -2
  9. package/dist/registry/bento-grid-section.json +4 -4
  10. package/dist/registry/blog-core.json +5 -5
  11. package/dist/registry/blog-list-page.json +4 -4
  12. package/dist/registry/blog-section.json +4 -4
  13. package/dist/registry/cards-carousel-section.json +4 -4
  14. package/dist/registry/cart-drawer.json +4 -4
  15. package/dist/registry/cart-page.json +4 -4
  16. package/dist/registry/case-study-page.json +3 -3
  17. package/dist/registry/category-section.json +4 -4
  18. package/dist/registry/checkout-page.json +4 -4
  19. package/dist/registry/coming-soon-page-minimal.json +4 -4
  20. package/dist/registry/coming-soon-page.json +4 -4
  21. package/dist/registry/contact-info-grid.json +4 -4
  22. package/dist/registry/contact-page-centered.json +4 -4
  23. package/dist/registry/contact-page-map-overlay.json +3 -3
  24. package/dist/registry/contact-page-map-split.json +3 -3
  25. package/dist/registry/contact-page-split.json +4 -4
  26. package/dist/registry/contact-page.json +4 -4
  27. package/dist/registry/content-section.json +4 -4
  28. package/dist/registry/cookie-consent.json +4 -4
  29. package/dist/registry/cookies-page.json +3 -3
  30. package/dist/registry/cta-section.json +3 -3
  31. package/dist/registry/ecommerce-core.json +8 -8
  32. package/dist/registry/empty-page.json +3 -3
  33. package/dist/registry/faq-categorized.json +4 -4
  34. package/dist/registry/faq-simple.json +4 -4
  35. package/dist/registry/favorites-blog-block.json +1 -1
  36. package/dist/registry/favorites-blog-page.json +4 -4
  37. package/dist/registry/favorites-ecommerce-block.json +1 -1
  38. package/dist/registry/favorites-ecommerce-page.json +4 -4
  39. package/dist/registry/feature-section.json +3 -3
  40. package/dist/registry/featured-products.json +4 -4
  41. package/dist/registry/footer-detailed.json +4 -4
  42. package/dist/registry/footer-minimal.json +3 -3
  43. package/dist/registry/footer.json +3 -3
  44. package/dist/registry/forgot-password-page-split.json +4 -4
  45. package/dist/registry/forgot-password-page.json +4 -4
  46. package/dist/registry/google-adsense.json +4 -4
  47. package/dist/registry/google-map.json +2 -2
  48. package/dist/registry/header-centered-pill.json +4 -4
  49. package/dist/registry/header-ecommerce.json +4 -4
  50. package/dist/registry/header-mega.json +4 -4
  51. package/dist/registry/header-minimal.json +4 -4
  52. package/dist/registry/header-simple.json +3 -3
  53. package/dist/registry/hero-carousel.json +3 -3
  54. package/dist/registry/hero-cta.json +4 -4
  55. package/dist/registry/hero-gradient.json +4 -4
  56. package/dist/registry/hero-grid.json +4 -4
  57. package/dist/registry/hero-profile.json +3 -3
  58. package/dist/registry/hero.json +3 -3
  59. package/dist/registry/index.json +103 -103
  60. package/dist/registry/landing-page-app.json +3 -3
  61. package/dist/registry/landing-page-saas.json +3 -3
  62. package/dist/registry/login-page-split.json +4 -4
  63. package/dist/registry/login-page.json +4 -4
  64. package/dist/registry/logo-cloud.json +4 -4
  65. package/dist/registry/masonry-grid.json +3 -3
  66. package/dist/registry/my-orders-page.json +4 -4
  67. package/dist/registry/newsletter-section.json +4 -4
  68. package/dist/registry/order-card-compact.json +3 -3
  69. package/dist/registry/order-confirmation-page.json +4 -4
  70. package/dist/registry/order-detail-block.json +1 -1
  71. package/dist/registry/orders-list-block.json +1 -1
  72. package/dist/registry/payment-success-block.json +2 -2
  73. package/dist/registry/portfolio-page.json +4 -4
  74. package/dist/registry/post-card.json +4 -4
  75. package/dist/registry/post-detail-block.json +4 -4
  76. package/dist/registry/post-detail-page.json +4 -4
  77. package/dist/registry/pricing-card.json +3 -3
  78. package/dist/registry/pricing-page.json +4 -4
  79. package/dist/registry/pricing-section.json +4 -4
  80. package/dist/registry/privacy-page.json +3 -3
  81. package/dist/registry/product-card-detailed.json +4 -4
  82. package/dist/registry/product-card-hover.json +4 -4
  83. package/dist/registry/product-card.json +4 -4
  84. package/dist/registry/product-detail-block.json +2 -2
  85. package/dist/registry/product-detail-page.json +4 -4
  86. package/dist/registry/product-detail-section.json +4 -4
  87. package/dist/registry/product-quick-view.json +4 -4
  88. package/dist/registry/products-page.json +4 -4
  89. package/dist/registry/reading-progress.json +4 -4
  90. package/dist/registry/register-page-split.json +4 -4
  91. package/dist/registry/register-page.json +4 -4
  92. package/dist/registry/related-posts-block.json +1 -1
  93. package/dist/registry/related-products-block.json +2 -2
  94. package/dist/registry/reset-password-page-split.json +4 -4
  95. package/dist/registry/reset-password-page.json +4 -4
  96. package/dist/registry/service-card.json +1 -1
  97. package/dist/registry/share-buttons.json +4 -4
  98. package/dist/registry/skill-card.json +1 -1
  99. package/dist/registry/team-page.json +4 -4
  100. package/dist/registry/terms-page.json +3 -3
  101. package/dist/registry/testimonials-carousel.json +4 -4
  102. package/dist/registry/testimonials-grid.json +4 -4
  103. package/dist/registry/timeline-section.json +4 -4
  104. package/dist/registry/verify-email-page.json +4 -4
  105. package/dist/registry/video-hero.json +4 -4
  106. package/dist/registry/youtube-embed.json +4 -4
  107. package/package.json +58 -58
  108. package/template/.env +5 -5
  109. package/template/README.md +54 -54
  110. package/template/eslint.config.js +41 -41
  111. package/template/index.html +237 -237
  112. package/template/package.json +96 -96
  113. package/template/public/_redirects +1 -1
  114. package/template/public/robots.txt +14 -14
  115. package/template/scripts/init-db.ts +18 -18
  116. package/template/src/App.tsx +21 -21
  117. package/template/src/components/FormField.tsx +48 -48
  118. package/template/src/components/FormFileInput.tsx +75 -75
  119. package/template/src/components/GoogleAnalytics.tsx +34 -34
  120. package/template/src/components/LanguageSwitcher.tsx +53 -53
  121. package/template/src/components/MetriaAnalytics.tsx +68 -68
  122. package/template/src/components/PasswordInput.tsx +60 -60
  123. package/template/src/components/ScriptInjector.tsx +62 -62
  124. package/template/src/components/Stack.tsx +39 -39
  125. package/template/src/constants/constants.json +71 -71
  126. package/template/src/db/index.ts +21 -21
  127. package/template/src/db/provider.tsx +152 -172
  128. package/template/src/db/schema.json +278 -278
  129. package/template/src/db/types.ts +195 -195
  130. package/template/src/hooks/use-debounced-value.ts +12 -12
  131. package/template/src/hooks/use-page-title.ts +55 -55
  132. package/template/src/lang/index.ts +90 -90
  133. package/template/src/lib/api.ts +345 -345
  134. package/template/src/lib/env.ts +19 -19
  135. package/template/src/router.tsx +14 -14
  136. package/template/src/vite-env.d.ts +1 -1
  137. package/template/vite.config.ts +225 -225
@@ -1,71 +1,71 @@
1
- {
2
- "site": {
3
- "name": "Site Name",
4
- "tagline": "Your Site Tagline",
5
- "description": "A modern, responsive site template for businesses, blogs, ecommerce stores, or portfolios.",
6
- "logo": "",
7
- "favicon": "./favicon.svg",
8
- "currency": "USD",
9
- "country": "United States",
10
- "countryCode": "US",
11
- "defaultLanguage": "en",
12
- "availableLanguages": {
13
- "en": "EN"
14
- },
15
- "overrideBrowserLanguage": true,
16
- "timezone": "America/New_York",
17
- "slug": "site-name",
18
- "taxName": "Tax"
19
- },
20
- "api": {
21
- "baseUrl": "https://backend.promake.ai/api",
22
- "endpoints": {
23
- "contact": "/contact",
24
- "services": "/services"
25
- },
26
- "timeout": 30000
27
- },
28
- "seo": {
29
- "title": "Site Name",
30
- "description": "Built with Promake — a website created in minutes with AI.",
31
- "author": "Site Name",
32
- "ogTitle": "Site Name",
33
- "ogDescription": "Built with Promake — a website created in minutes with AI.",
34
- "ogImage": "",
35
- "twitterSite": "",
36
- "twitterImage": "",
37
- "googleVerification": ""
38
- },
39
- "scripts": {
40
- "gaId": "",
41
- "headStart": "",
42
- "headEnd": "",
43
- "bodyStart": "",
44
- "bodyEnd": ""
45
- },
46
- "email": "hello@example.com",
47
- "supportEmail": "support@example.com",
48
- "phone": "+1 (555) 010-0000",
49
- "whatsapp": "+1 (555) 010-0001",
50
- "address": {
51
- "line1": "123 Main Street",
52
- "line2": "Suite 100",
53
- "city": "City",
54
- "state": "State",
55
- "postalCode": "00000",
56
- "country": "Country"
57
- },
58
- "socialMedia": {
59
- "twitter": "",
60
- "facebook": "",
61
- "instagram": "",
62
- "linkedin": ""
63
- },
64
- "database": {
65
- "adapter": "rest"
66
- },
67
- "file": {
68
- "maxFiles": 5,
69
- "accept": ".pdf,.doc,.docx,.jpg,.jpeg,.png"
70
- }
71
- }
1
+ {
2
+ "site": {
3
+ "name": "Site Name",
4
+ "tagline": "Your Site Tagline",
5
+ "description": "A modern, responsive site template for businesses, blogs, ecommerce stores, or portfolios.",
6
+ "logo": "",
7
+ "favicon": "./favicon.svg",
8
+ "currency": "USD",
9
+ "country": "United States",
10
+ "countryCode": "US",
11
+ "defaultLanguage": "en",
12
+ "availableLanguages": {
13
+ "en": "EN"
14
+ },
15
+ "overrideBrowserLanguage": true,
16
+ "timezone": "America/New_York",
17
+ "slug": "site-name",
18
+ "taxName": "Tax"
19
+ },
20
+ "api": {
21
+ "baseUrl": "https://backend.promake.ai/api",
22
+ "endpoints": {
23
+ "contact": "/contact",
24
+ "services": "/services"
25
+ },
26
+ "timeout": 30000
27
+ },
28
+ "seo": {
29
+ "title": "Site Name",
30
+ "description": "Built with Promake — a website created in minutes with AI.",
31
+ "author": "Site Name",
32
+ "ogTitle": "Site Name",
33
+ "ogDescription": "Built with Promake — a website created in minutes with AI.",
34
+ "ogImage": "",
35
+ "twitterSite": "",
36
+ "twitterImage": "",
37
+ "googleVerification": ""
38
+ },
39
+ "scripts": {
40
+ "gaId": "",
41
+ "headStart": "",
42
+ "headEnd": "",
43
+ "bodyStart": "",
44
+ "bodyEnd": ""
45
+ },
46
+ "email": "hello@example.com",
47
+ "supportEmail": "support@example.com",
48
+ "phone": "+1 (555) 010-0000",
49
+ "whatsapp": "+1 (555) 010-0001",
50
+ "address": {
51
+ "line1": "123 Main Street",
52
+ "line2": "Suite 100",
53
+ "city": "City",
54
+ "state": "State",
55
+ "postalCode": "00000",
56
+ "country": "Country"
57
+ },
58
+ "socialMedia": {
59
+ "twitter": "",
60
+ "facebook": "",
61
+ "instagram": "",
62
+ "linkedin": ""
63
+ },
64
+ "database": {
65
+ "adapter": "rest"
66
+ },
67
+ "file": {
68
+ "maxFiles": 5,
69
+ "accept": ".pdf,.doc,.docx,.jpg,.jpeg,.png"
70
+ }
71
+ }
@@ -1,21 +1,21 @@
1
- export { AppDbProvider } from "./provider";
2
-
3
- import { parseJSONSchema } from "@promakeai/orm";
4
- import schemaJson from "./schema.json";
5
- export const schema = parseJSONSchema(schemaJson as any);
6
-
7
- export {
8
- useDb,
9
- useAdapter,
10
- useDbLang,
11
- useDbList,
12
- useDbGet,
13
- useDbCreate,
14
- useDbUpdate,
15
- useDbDelete,
16
- SqliteAdapter,
17
- } from "@promakeai/dbreact";
18
-
19
- export { RestAdapter, parseJSONSchema } from "@promakeai/orm";
20
-
21
- export * from "./types";
1
+ export { AppDbProvider } from "./provider";
2
+
3
+ import { parseJSONSchema } from "@promakeai/orm";
4
+ import schemaJson from "./schema.json";
5
+ export const schema = parseJSONSchema(schemaJson as any);
6
+
7
+ export {
8
+ useDb,
9
+ useAdapter,
10
+ useDbLang,
11
+ useDbList,
12
+ useDbGet,
13
+ useDbCreate,
14
+ useDbUpdate,
15
+ useDbDelete,
16
+ SqliteAdapter,
17
+ } from "@promakeai/dbreact";
18
+
19
+ export { RestAdapter, parseJSONSchema } from "@promakeai/orm";
20
+
21
+ export * from "./types";
@@ -1,172 +1,152 @@
1
- import { useEffect, useState, type ReactNode } from 'react';
2
- import { useTranslation } from 'react-i18next';
3
- import { DbProvider, SqliteAdapter } from '@promakeai/dbreact';
4
- import { RestAdapter, parseJSONSchema } from '@promakeai/orm';
5
- import type { IDataAdapter } from '@promakeai/orm';
6
- import constants from '@/constants/constants.json';
7
- import schemaJson from './schema.json';
8
-
9
- const schema = parseJSONSchema(schemaJson as any);
10
-
11
- interface AppDbProviderProps {
12
- children: ReactNode;
13
- }
14
-
15
- const DEFAULT_LANG = constants?.site?.defaultLanguage || 'en';
16
- const DB_CONFIG = (constants as any)?.database;
17
-
18
- /**
19
- * Read auth token from localStorage (where auth-core's Zustand store persists).
20
- * Returns null when auth-core is not installed or user is not logged in.
21
- */
22
- function getAuthToken(): string | null {
23
- try {
24
- const raw = localStorage.getItem('auth-storage');
25
- if (!raw) return null;
26
- const parsed = JSON.parse(raw);
27
- return parsed?.state?.tokens?.accessToken ?? null;
28
- } catch {
29
- return null;
30
- }
31
- }
32
-
33
- /**
34
- * Parse .env-style text (KEY=VALUE lines) into a Record.
35
- * Ignores comments (#) and blank lines, strips surrounding quotes.
36
- */
37
- function parseEnvText(text: string): Record<string, string> {
38
- const result: Record<string, string> = {};
39
- for (const line of text.split('\n')) {
40
- const trimmed = line.trim();
41
- if (!trimmed || trimmed.startsWith('#')) continue;
42
- const eqIndex = trimmed.indexOf('=');
43
- if (eqIndex === -1) continue;
44
- const key = trimmed.slice(0, eqIndex).trim();
45
- let value = trimmed.slice(eqIndex + 1).trim();
46
- if ((value.startsWith('"') && value.endsWith('"')) ||
47
- (value.startsWith("'") && value.endsWith("'"))) {
48
- value = value.slice(1, -1);
49
- }
50
- result[key] = value;
51
- }
52
- return result;
53
- }
54
-
55
- /** Map parsed env keys to HTTP header names */
56
- function envToHeaders(env: Record<string, string>): Record<string, string> {
57
- const headers: Record<string, string> = {};
58
- if (env.DB_VERSION) headers['DB-VERSION'] = env.DB_VERSION;
59
- if (env.DB_MODE) headers['DB-MODE'] = env.DB_MODE;
60
- return headers;
61
- }
62
-
63
- let cachedDbHeaders: Record<string, string> = {};
64
- let refreshInterval: ReturnType<typeof setInterval> | null = null;
65
-
66
- async function refreshDbHeaders(): Promise<void> {
67
- try {
68
- const response = await fetch('/cus-be-db-mode.txt');
69
- if (!response.ok) return;
70
- const text = await response.text();
71
- cachedDbHeaders = envToHeaders(parseEnvText(text));
72
- } catch {
73
- // Keep existing cache on failure
74
- }
75
- }
76
-
77
- function startHeaderRefresh(intervalMs = 30_000): void {
78
- if (refreshInterval) return;
79
- refreshInterval = setInterval(refreshDbHeaders, intervalMs);
80
- }
81
-
82
- function stopHeaderRefresh(): void {
83
- if (refreshInterval) {
84
- clearInterval(refreshInterval);
85
- refreshInterval = null;
86
- }
87
- }
88
-
89
- function getDynamicDbHeaders(): Record<string, string> {
90
- return cachedDbHeaders;
91
- }
92
-
93
- export function AppDbProvider({ children }: AppDbProviderProps) {
94
- const { i18n } = useTranslation();
95
- const [adapter, setAdapter] = useState<IDataAdapter | null>(null);
96
- const [error, setError] = useState<Error | null>(null);
97
-
98
- useEffect(() => {
99
- let cancelled = false;
100
-
101
- async function loadDb() {
102
- try {
103
- if (DB_CONFIG?.adapter === 'rest') {
104
- // Fetch dynamic headers before creating adapter
105
- await refreshDbHeaders();
106
- startHeaderRefresh();
107
-
108
- // REST API mode
109
- const restAdapter = new RestAdapter({
110
- baseUrl: 'https://' + import.meta.env.VITE_TENANT_UUID + '.backend.promake.ai',
111
- databasePrefix: '/database',
112
- schema,
113
- defaultLang: DEFAULT_LANG,
114
- getToken: getAuthToken,
115
- getHeaders: getDynamicDbHeaders,
116
- });
117
-
118
- if (!cancelled) {
119
- setAdapter(restAdapter);
120
- }
121
- } else {
122
- // SQLite mode (default)
123
- const response = await fetch('/data/database.db');
124
- if (!response.ok) {
125
- throw new Error(`Failed to load database: ${response.status} ${response.statusText}`);
126
- }
127
-
128
- const buffer = await response.arrayBuffer();
129
- if (cancelled) return;
130
-
131
- const dbAdapter = new SqliteAdapter({
132
- schema,
133
- defaultLang: DEFAULT_LANG,
134
- wasmPath: '/sql-wasm.wasm',
135
- });
136
-
137
- await dbAdapter.connect();
138
- await dbAdapter.import(new Uint8Array(buffer));
139
-
140
- if (!cancelled) {
141
- setAdapter(dbAdapter);
142
- }
143
- }
144
- } catch (err) {
145
- if (!cancelled) {
146
- setError(err instanceof Error ? err : new Error(String(err)));
147
- }
148
- }
149
- }
150
-
151
- loadDb();
152
-
153
- return () => {
154
- cancelled = true;
155
- stopHeaderRefresh();
156
- };
157
- }, []);
158
-
159
- if (error) {
160
- console.error(error);
161
- }
162
-
163
- if (!adapter) {
164
- return null;
165
- }
166
-
167
- return (
168
- <DbProvider adapter={adapter} lang={i18n?.language || DEFAULT_LANG} fallbackLang={DEFAULT_LANG} autoConnect={false}>
169
- {children}
170
- </DbProvider>
171
- );
172
- }
1
+ import { useEffect, useState, type ReactNode } from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import { DbProvider, SqliteAdapter } from '@promakeai/dbreact';
4
+ import { RestAdapter, parseJSONSchema } from '@promakeai/orm';
5
+ import type { IDataAdapter } from '@promakeai/orm';
6
+ import constants from '@/constants/constants.json';
7
+ import schemaJson from './schema.json';
8
+
9
+ const schema = parseJSONSchema(schemaJson as any);
10
+
11
+ interface AppDbProviderProps {
12
+ children: ReactNode;
13
+ }
14
+
15
+ const DEFAULT_LANG = constants?.site?.defaultLanguage || 'en';
16
+ const DB_CONFIG = (constants as any)?.database;
17
+
18
+ /**
19
+ * Read auth token from localStorage (where auth-core's Zustand store persists).
20
+ * Returns null when auth-core is not installed or user is not logged in.
21
+ */
22
+ function getAuthToken(): string | null {
23
+ try {
24
+ const raw = localStorage.getItem('auth-storage');
25
+ if (!raw) return null;
26
+ const parsed = JSON.parse(raw);
27
+ return parsed?.state?.tokens?.accessToken ?? null;
28
+ } catch {
29
+ return null;
30
+ }
31
+ }
32
+
33
+ let cachedDbHeaders: Record<string, string> = {};
34
+ let refreshInterval: ReturnType<typeof setInterval> | null = null;
35
+
36
+ async function refreshDbHeaders(): Promise<void> {
37
+ try {
38
+ const [modeRes, versionRes] = await Promise.all([
39
+ fetch('/cus-be-db-mode.txt'),
40
+ fetch('/cus-be-db.txt'),
41
+ ]);
42
+ const headers: Record<string, string> = {};
43
+ if (modeRes.ok) {
44
+ const mode = (await modeRes.text()).trim();
45
+ if (mode) headers['DB-MODE'] = mode;
46
+ }
47
+ if (versionRes.ok) {
48
+ const version = (await versionRes.text()).trim();
49
+ if (version) headers['DB-VERSION'] = version;
50
+ }
51
+ cachedDbHeaders = headers;
52
+ } catch {
53
+ // Keep existing cache on failure
54
+ }
55
+ }
56
+
57
+ function startHeaderRefresh(intervalMs = 30_000): void {
58
+ if (refreshInterval) return;
59
+ refreshInterval = setInterval(refreshDbHeaders, intervalMs);
60
+ }
61
+
62
+ function stopHeaderRefresh(): void {
63
+ if (refreshInterval) {
64
+ clearInterval(refreshInterval);
65
+ refreshInterval = null;
66
+ }
67
+ }
68
+
69
+ function getDynamicDbHeaders(): Record<string, string> {
70
+ return cachedDbHeaders;
71
+ }
72
+
73
+ export function AppDbProvider({ children }: AppDbProviderProps) {
74
+ const { i18n } = useTranslation();
75
+ const [adapter, setAdapter] = useState<IDataAdapter | null>(null);
76
+ const [error, setError] = useState<Error | null>(null);
77
+
78
+ useEffect(() => {
79
+ let cancelled = false;
80
+
81
+ async function loadDb() {
82
+ try {
83
+ if (DB_CONFIG?.adapter === 'rest') {
84
+ // Fetch dynamic headers before creating adapter
85
+ await refreshDbHeaders();
86
+ startHeaderRefresh();
87
+
88
+ // REST API mode
89
+ const restAdapter = new RestAdapter({
90
+ baseUrl: 'https://' + import.meta.env.VITE_TENANT_UUID + '.backend.promake.ai',
91
+ databasePrefix: '/database',
92
+ schema,
93
+ defaultLang: DEFAULT_LANG,
94
+ getToken: getAuthToken,
95
+ getHeaders: getDynamicDbHeaders,
96
+ });
97
+
98
+ if (!cancelled) {
99
+ setAdapter(restAdapter);
100
+ }
101
+ } else {
102
+ // SQLite mode (default)
103
+ const response = await fetch('/data/database.db');
104
+ if (!response.ok) {
105
+ throw new Error(`Failed to load database: ${response.status} ${response.statusText}`);
106
+ }
107
+
108
+ const buffer = await response.arrayBuffer();
109
+ if (cancelled) return;
110
+
111
+ const dbAdapter = new SqliteAdapter({
112
+ schema,
113
+ defaultLang: DEFAULT_LANG,
114
+ wasmPath: '/sql-wasm.wasm',
115
+ });
116
+
117
+ await dbAdapter.connect();
118
+ await dbAdapter.import(new Uint8Array(buffer));
119
+
120
+ if (!cancelled) {
121
+ setAdapter(dbAdapter);
122
+ }
123
+ }
124
+ } catch (err) {
125
+ if (!cancelled) {
126
+ setError(err instanceof Error ? err : new Error(String(err)));
127
+ }
128
+ }
129
+ }
130
+
131
+ loadDb();
132
+
133
+ return () => {
134
+ cancelled = true;
135
+ stopHeaderRefresh();
136
+ };
137
+ }, []);
138
+
139
+ if (error) {
140
+ console.error(error);
141
+ }
142
+
143
+ if (!adapter) {
144
+ return null;
145
+ }
146
+
147
+ return (
148
+ <DbProvider adapter={adapter} lang={i18n?.language || DEFAULT_LANG} fallbackLang={DEFAULT_LANG} autoConnect={false}>
149
+ {children}
150
+ </DbProvider>
151
+ );
152
+ }