@mars-stack/cli 1.0.2 → 2.0.0
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 +130 -44
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1165,6 +1165,7 @@ async function generateNotifications(projectRoot) {
|
|
|
1165
1165
|
"src/features/notifications/components/NotificationBell.tsx": notificationBell(),
|
|
1166
1166
|
"src/features/notifications/components/NotificationPanel.tsx": notificationPanel(),
|
|
1167
1167
|
"src/features/notifications/components/index.ts": componentIndex2(),
|
|
1168
|
+
"src/features/notifications/index.ts": featureIndex(),
|
|
1168
1169
|
"src/app/api/protected/notifications/route.ts": listRoute(),
|
|
1169
1170
|
"src/app/api/protected/notifications/[id]/read/route.ts": markReadRoute(),
|
|
1170
1171
|
"src/app/api/protected/notifications/read-all/route.ts": markAllReadRoute(),
|
|
@@ -1179,18 +1180,21 @@ async function generateNotifications(projectRoot) {
|
|
|
1179
1180
|
count++;
|
|
1180
1181
|
}
|
|
1181
1182
|
await addUserRelation(projectRoot, "notifications Notification[]", ctx);
|
|
1183
|
+
await wireProtectedNav2(projectRoot, ctx);
|
|
1182
1184
|
await setConfigFlag3(projectRoot, ctx);
|
|
1183
1185
|
await ctx.commit();
|
|
1184
|
-
log.success(`Generated notifications feature
|
|
1186
|
+
log.success(`Generated and wired notifications feature (${count} files created)`);
|
|
1185
1187
|
log.blank();
|
|
1186
1188
|
log.step("prisma/schema/notification.prisma \u2014 Notification model");
|
|
1187
1189
|
log.step("src/features/notifications/ \u2014 types, validation, server logic, hooks, components");
|
|
1188
1190
|
log.step("src/app/api/protected/notifications/ \u2014 CRUD API routes");
|
|
1189
1191
|
log.blank();
|
|
1192
|
+
log.step("Wired automatically:");
|
|
1193
|
+
log.step(" \u2713 NotificationBell added to navigation bar");
|
|
1194
|
+
log.blank();
|
|
1190
1195
|
log.warn("Next steps:");
|
|
1191
1196
|
log.step("1. Run yarn db:push to sync the Prisma schema");
|
|
1192
|
-
log.step("2.
|
|
1193
|
-
log.step("3. Import createNotification from server to trigger notifications from other features:");
|
|
1197
|
+
log.step("2. Import createNotification from server to trigger notifications from other features:");
|
|
1194
1198
|
log.step(' import { createNotification } from "@/features/notifications/server"');
|
|
1195
1199
|
log.blank();
|
|
1196
1200
|
} catch (error) {
|
|
@@ -1198,6 +1202,23 @@ async function generateNotifications(projectRoot) {
|
|
|
1198
1202
|
throw error;
|
|
1199
1203
|
}
|
|
1200
1204
|
}
|
|
1205
|
+
async function wireProtectedNav2(projectRoot, ctx) {
|
|
1206
|
+
const navPath = path8.join(projectRoot, "src", "app", "(protected)", "layout.tsx");
|
|
1207
|
+
if (!await fs8.pathExists(navPath)) return;
|
|
1208
|
+
await ctx.trackModifiedFile(navPath);
|
|
1209
|
+
let content = await fs8.readFile(navPath, "utf-8");
|
|
1210
|
+
if (content.includes("NotificationBell")) return;
|
|
1211
|
+
content = insertImportAfterDirectives(
|
|
1212
|
+
content,
|
|
1213
|
+
`import { NotificationBell } from '@/features/notifications';
|
|
1214
|
+
`
|
|
1215
|
+
);
|
|
1216
|
+
content = content.replace(
|
|
1217
|
+
/(<div className="flex items-center gap-3">)\s*\n(\s*)(<div className="hidden md:block">)/,
|
|
1218
|
+
"$1\n$2<NotificationBell />\n$2$3"
|
|
1219
|
+
);
|
|
1220
|
+
await fs8.writeFile(navPath, content);
|
|
1221
|
+
}
|
|
1201
1222
|
async function setConfigFlag3(projectRoot, ctx) {
|
|
1202
1223
|
const configPath = path8.join(projectRoot, "src", "config", "app.config.ts");
|
|
1203
1224
|
if (!await fs8.pathExists(configPath)) return;
|
|
@@ -1681,6 +1702,11 @@ export function NotificationPanel({
|
|
|
1681
1702
|
}
|
|
1682
1703
|
`;
|
|
1683
1704
|
}
|
|
1705
|
+
function featureIndex() {
|
|
1706
|
+
return `${STAMP3}
|
|
1707
|
+
export { NotificationBell, NotificationPanel } from './components';
|
|
1708
|
+
`;
|
|
1709
|
+
}
|
|
1684
1710
|
function componentIndex2() {
|
|
1685
1711
|
return `${STAMP3}
|
|
1686
1712
|
export { NotificationBell } from './NotificationBell';
|
|
@@ -1781,6 +1807,7 @@ var GENERATOR_VERSION3, STAMP3;
|
|
|
1781
1807
|
var init_notifications = __esm({
|
|
1782
1808
|
"src/generators/features/notifications.ts"() {
|
|
1783
1809
|
"use strict";
|
|
1810
|
+
init_client_file_patch();
|
|
1784
1811
|
init_logger();
|
|
1785
1812
|
init_rollback();
|
|
1786
1813
|
init_prisma();
|
|
@@ -1819,15 +1846,19 @@ async function generateAnalytics(projectRoot) {
|
|
|
1819
1846
|
await fs9.writeFile(fullPath, content);
|
|
1820
1847
|
count++;
|
|
1821
1848
|
}
|
|
1849
|
+
await wireProviders2(projectRoot, ctx);
|
|
1822
1850
|
await setConfigFlag4(projectRoot, ctx);
|
|
1823
1851
|
await ctx.commit();
|
|
1824
|
-
log.success(`Generated analytics feature
|
|
1852
|
+
log.success(`Generated and wired analytics feature (${count} files created)`);
|
|
1825
1853
|
log.blank();
|
|
1826
1854
|
log.step("src/features/analytics/ \u2014 types and barrel exports");
|
|
1827
1855
|
log.step("src/lib/shared/components/providers/AnalyticsProvider.tsx \u2014 provider wrapper");
|
|
1828
1856
|
log.step("src/lib/shared/utils/analytics.ts \u2014 unified tracking API");
|
|
1829
1857
|
log.step("src/lib/shared/components/patterns/ConsentBanner.tsx \u2014 cookie consent banner");
|
|
1830
1858
|
log.blank();
|
|
1859
|
+
log.step("Wired automatically:");
|
|
1860
|
+
log.step(" \u2713 AnalyticsProvider wrapping app in providers.tsx");
|
|
1861
|
+
log.blank();
|
|
1831
1862
|
log.warn("Install dependencies for your chosen provider:");
|
|
1832
1863
|
log.step("Vercel: yarn add @vercel/analytics @vercel/speed-insights");
|
|
1833
1864
|
log.step("PostHog: yarn add posthog-js");
|
|
@@ -1836,13 +1867,39 @@ async function generateAnalytics(projectRoot) {
|
|
|
1836
1867
|
log.warn("Next steps:");
|
|
1837
1868
|
log.step("Set the provider in appConfig.services.analytics.provider");
|
|
1838
1869
|
log.step("Set required environment variables for the chosen provider");
|
|
1839
|
-
log.step("Add <AnalyticsProvider> and <ConsentBanner /> to your root layout");
|
|
1840
1870
|
log.blank();
|
|
1841
1871
|
} catch (error) {
|
|
1842
1872
|
await ctx.rollback();
|
|
1843
1873
|
throw error;
|
|
1844
1874
|
}
|
|
1845
1875
|
}
|
|
1876
|
+
async function wireProviders2(projectRoot, ctx) {
|
|
1877
|
+
const providersPath = path9.join(projectRoot, "src", "app", "providers.tsx");
|
|
1878
|
+
if (!await fs9.pathExists(providersPath)) return;
|
|
1879
|
+
await ctx.trackModifiedFile(providersPath);
|
|
1880
|
+
let content = await fs9.readFile(providersPath, "utf-8");
|
|
1881
|
+
if (content.includes("AnalyticsProvider")) return;
|
|
1882
|
+
content = insertImportAfterDirectives(
|
|
1883
|
+
content,
|
|
1884
|
+
`import { AnalyticsProvider } from '@/lib/shared/components/providers/AnalyticsProvider';
|
|
1885
|
+
`
|
|
1886
|
+
);
|
|
1887
|
+
content = content.replace(
|
|
1888
|
+
/return\s+(?:\(\s*)?((?:<\w+[^>]*>)[\s\S]*?\{children\}[\s\S]*?(?:<\/\w+>))\s*(?:\)\s*)?;/,
|
|
1889
|
+
(_match, jsx) => {
|
|
1890
|
+
return `return (
|
|
1891
|
+
<AnalyticsProvider>${jsx}</AnalyticsProvider>
|
|
1892
|
+
);`;
|
|
1893
|
+
}
|
|
1894
|
+
);
|
|
1895
|
+
await fs9.writeFile(providersPath, content);
|
|
1896
|
+
const written = await fs9.readFile(providersPath, "utf-8");
|
|
1897
|
+
if (!written.includes("AnalyticsProvider")) {
|
|
1898
|
+
throw new Error(
|
|
1899
|
+
"wireProviders: AnalyticsProvider was not inserted into providers.tsx \u2014 the return statement pattern did not match. Review the template file structure."
|
|
1900
|
+
);
|
|
1901
|
+
}
|
|
1902
|
+
}
|
|
1846
1903
|
async function setConfigFlag4(projectRoot, ctx) {
|
|
1847
1904
|
const configPath = path9.join(projectRoot, "src", "config", "app.config.ts");
|
|
1848
1905
|
if (!await fs9.pathExists(configPath)) return;
|
|
@@ -1872,7 +1929,7 @@ function analyticsProvider() {
|
|
|
1872
1929
|
return `${STAMP4}
|
|
1873
1930
|
'use client';
|
|
1874
1931
|
|
|
1875
|
-
import { useEffect, useState } from 'react';
|
|
1932
|
+
import { Suspense, useEffect, useState } from 'react';
|
|
1876
1933
|
import { usePathname, useSearchParams } from 'next/navigation';
|
|
1877
1934
|
import Script from 'next/script';
|
|
1878
1935
|
import { appConfig } from '@/config/app.config';
|
|
@@ -1895,7 +1952,9 @@ export function AnalyticsProvider({ children }: AnalyticsProviderProps) {
|
|
|
1895
1952
|
{provider === 'vercel' && <VercelAnalyticsProvider />}
|
|
1896
1953
|
{provider === 'posthog' && <PostHogAnalyticsProvider />}
|
|
1897
1954
|
{provider === 'google' && <GoogleAnalyticsProvider />}
|
|
1898
|
-
<
|
|
1955
|
+
<Suspense>
|
|
1956
|
+
<PageViewTracker />
|
|
1957
|
+
</Suspense>
|
|
1899
1958
|
{children}
|
|
1900
1959
|
</>
|
|
1901
1960
|
);
|
|
@@ -2059,22 +2118,18 @@ export function trackEvent(
|
|
|
2059
2118
|
|
|
2060
2119
|
switch (provider) {
|
|
2061
2120
|
case 'vercel': {
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
track(eventName, properties)
|
|
2065
|
-
|
|
2066
|
-
// @vercel/analytics not available
|
|
2067
|
-
}
|
|
2121
|
+
const vercelSpec = '@vercel/analytics';
|
|
2122
|
+
import(/* webpackIgnore: true */ vercelSpec)
|
|
2123
|
+
.then((mod) => mod.track(eventName, properties))
|
|
2124
|
+
.catch(() => {});
|
|
2068
2125
|
break;
|
|
2069
2126
|
}
|
|
2070
2127
|
|
|
2071
2128
|
case 'posthog': {
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
// posthog-js not available
|
|
2077
|
-
}
|
|
2129
|
+
const phSpec = 'posthog-js';
|
|
2130
|
+
import(/* webpackIgnore: true */ phSpec)
|
|
2131
|
+
.then((mod) => mod.default.capture(eventName, properties))
|
|
2132
|
+
.catch(() => {});
|
|
2078
2133
|
break;
|
|
2079
2134
|
}
|
|
2080
2135
|
|
|
@@ -2105,12 +2160,10 @@ export function identifyUser(
|
|
|
2105
2160
|
break;
|
|
2106
2161
|
|
|
2107
2162
|
case 'posthog': {
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
// posthog-js not available
|
|
2113
|
-
}
|
|
2163
|
+
const phSpec = 'posthog-js';
|
|
2164
|
+
import(/* webpackIgnore: true */ phSpec)
|
|
2165
|
+
.then((mod) => mod.default.identify(userId, traits))
|
|
2166
|
+
.catch(() => {});
|
|
2114
2167
|
break;
|
|
2115
2168
|
}
|
|
2116
2169
|
|
|
@@ -2199,6 +2252,7 @@ var GENERATOR_VERSION4, STAMP4;
|
|
|
2199
2252
|
var init_analytics = __esm({
|
|
2200
2253
|
"src/generators/features/analytics.ts"() {
|
|
2201
2254
|
"use strict";
|
|
2255
|
+
init_client_file_patch();
|
|
2202
2256
|
init_logger();
|
|
2203
2257
|
init_rollback();
|
|
2204
2258
|
GENERATOR_VERSION4 = "0.1.0";
|
|
@@ -2229,7 +2283,7 @@ async function generateCommandPalette(projectRoot) {
|
|
|
2229
2283
|
"src/features/command-palette/components/CommandPalette.tsx": commandPalette(),
|
|
2230
2284
|
"src/features/command-palette/components/CommandTrigger.tsx": commandTrigger(),
|
|
2231
2285
|
"src/features/command-palette/components/index.ts": componentIndex3(),
|
|
2232
|
-
"src/features/command-palette/index.ts":
|
|
2286
|
+
"src/features/command-palette/index.ts": featureIndex2()
|
|
2233
2287
|
};
|
|
2234
2288
|
let count = 0;
|
|
2235
2289
|
for (const [filePath, content] of Object.entries(files)) {
|
|
@@ -2240,15 +2294,17 @@ async function generateCommandPalette(projectRoot) {
|
|
|
2240
2294
|
count++;
|
|
2241
2295
|
}
|
|
2242
2296
|
await addDependencies(projectRoot, { cmdk: "^1.0.0" });
|
|
2297
|
+
await wireLayout2(projectRoot, ctx);
|
|
2243
2298
|
await setConfigFlag5(projectRoot, ctx);
|
|
2244
2299
|
await ctx.commit();
|
|
2245
|
-
log.success(`Generated command palette feature
|
|
2300
|
+
log.success(`Generated and wired command palette feature (${count} files created)`);
|
|
2246
2301
|
log.blank();
|
|
2247
2302
|
log.step("src/features/command-palette/ \u2014 types, actions, registry, recent, components");
|
|
2248
2303
|
log.blank();
|
|
2249
|
-
log.
|
|
2250
|
-
log.step("
|
|
2251
|
-
log.step("
|
|
2304
|
+
log.step("Wired automatically:");
|
|
2305
|
+
log.step(" \u2713 CommandPalette overlay mounted in root layout");
|
|
2306
|
+
log.step(" \u2713 Press \u2318K / Ctrl+K to open");
|
|
2307
|
+
log.blank();
|
|
2252
2308
|
log.step("Register custom actions with registerAction() from any feature");
|
|
2253
2309
|
log.blank();
|
|
2254
2310
|
} catch (error) {
|
|
@@ -2256,6 +2312,20 @@ async function generateCommandPalette(projectRoot) {
|
|
|
2256
2312
|
throw error;
|
|
2257
2313
|
}
|
|
2258
2314
|
}
|
|
2315
|
+
async function wireLayout2(projectRoot, ctx) {
|
|
2316
|
+
const layoutPath = path10.join(projectRoot, "src", "app", "layout.tsx");
|
|
2317
|
+
if (!await fs10.pathExists(layoutPath)) return;
|
|
2318
|
+
await ctx.trackModifiedFile(layoutPath);
|
|
2319
|
+
let content = await fs10.readFile(layoutPath, "utf-8");
|
|
2320
|
+
if (content.includes("CommandPalette")) return;
|
|
2321
|
+
content = `import { CommandPalette } from '@/features/command-palette';
|
|
2322
|
+
${content}`;
|
|
2323
|
+
content = content.replace(
|
|
2324
|
+
/(\s*)(<Providers>\{children\}<\/Providers>)/,
|
|
2325
|
+
"$1$2\n$1<CommandPalette />"
|
|
2326
|
+
);
|
|
2327
|
+
await fs10.writeFile(layoutPath, content);
|
|
2328
|
+
}
|
|
2259
2329
|
async function setConfigFlag5(projectRoot, ctx) {
|
|
2260
2330
|
const configPath = path10.join(projectRoot, "src", "config", "app.config.ts");
|
|
2261
2331
|
if (!await fs10.pathExists(configPath)) return;
|
|
@@ -2652,7 +2722,7 @@ export { CommandPalette } from './CommandPalette';
|
|
|
2652
2722
|
export { CommandTrigger } from './CommandTrigger';
|
|
2653
2723
|
`;
|
|
2654
2724
|
}
|
|
2655
|
-
function
|
|
2725
|
+
function featureIndex2() {
|
|
2656
2726
|
return `${STAMP5}
|
|
2657
2727
|
export { CommandPalette, CommandTrigger } from './components';
|
|
2658
2728
|
export { registerAction, getCustomActions } from './registry';
|
|
@@ -2700,7 +2770,7 @@ async function generateOnboarding(projectRoot) {
|
|
|
2700
2770
|
"src/app/(protected)/onboarding/page.tsx": onboardingPage(),
|
|
2701
2771
|
"src/app/api/protected/onboarding/route.ts": getProgressRoute(),
|
|
2702
2772
|
"src/app/api/protected/onboarding/step/route.ts": stepActionRoute(),
|
|
2703
|
-
"src/features/onboarding/index.ts":
|
|
2773
|
+
"src/features/onboarding/index.ts": featureIndex3()
|
|
2704
2774
|
};
|
|
2705
2775
|
let count = 0;
|
|
2706
2776
|
for (const [filePath, content] of Object.entries(files)) {
|
|
@@ -3231,7 +3301,7 @@ export const POST = withAuthNoParams(async (request: AuthenticatedRequest) => {
|
|
|
3231
3301
|
});
|
|
3232
3302
|
`;
|
|
3233
3303
|
}
|
|
3234
|
-
function
|
|
3304
|
+
function featureIndex3() {
|
|
3235
3305
|
return `${STAMP6}
|
|
3236
3306
|
export { ONBOARDING_STEPS } from './config';
|
|
3237
3307
|
export type { OnboardingStep } from './config';
|
|
@@ -3280,7 +3350,7 @@ async function generateSearch(projectRoot) {
|
|
|
3280
3350
|
"src/features/search/hooks/use-search.ts": useSearchHook(),
|
|
3281
3351
|
"src/features/search/components/SearchInput.tsx": searchInput(),
|
|
3282
3352
|
"src/features/search/components/index.ts": componentIndex5(),
|
|
3283
|
-
"src/features/search/index.ts":
|
|
3353
|
+
"src/features/search/index.ts": featureIndex4(),
|
|
3284
3354
|
"src/app/api/protected/search/route.ts": searchRoute()
|
|
3285
3355
|
};
|
|
3286
3356
|
let count = 0;
|
|
@@ -3592,7 +3662,7 @@ function componentIndex5() {
|
|
|
3592
3662
|
export { SearchInput } from './SearchInput';
|
|
3593
3663
|
`;
|
|
3594
3664
|
}
|
|
3595
|
-
function
|
|
3665
|
+
function featureIndex4() {
|
|
3596
3666
|
return `${STAMP7}
|
|
3597
3667
|
export type { SearchResult, SearchOptions, SearchProvider } from './types';
|
|
3598
3668
|
export { searchParamsSchema } from './validation/schemas';
|
|
@@ -3664,7 +3734,7 @@ async function generateRealtime(projectRoot) {
|
|
|
3664
3734
|
"src/features/realtime/server/sse.ts": sseProvider(),
|
|
3665
3735
|
"src/features/realtime/hooks/use-event-source.ts": useEventSourceHook(),
|
|
3666
3736
|
"src/features/realtime/hooks/index.ts": hooksIndex(),
|
|
3667
|
-
"src/features/realtime/index.ts":
|
|
3737
|
+
"src/features/realtime/index.ts": featureIndex5(),
|
|
3668
3738
|
"src/app/api/protected/realtime/stream/route.ts": sseStreamRoute()
|
|
3669
3739
|
};
|
|
3670
3740
|
let count = 0;
|
|
@@ -3912,7 +3982,7 @@ function hooksIndex() {
|
|
|
3912
3982
|
export { useEventSource } from './use-event-source';
|
|
3913
3983
|
`;
|
|
3914
3984
|
}
|
|
3915
|
-
function
|
|
3985
|
+
function featureIndex5() {
|
|
3916
3986
|
return `${STAMP8}
|
|
3917
3987
|
export type {
|
|
3918
3988
|
RealtimeProvider,
|
|
@@ -4522,7 +4592,7 @@ async function generateCookieConsent(projectRoot) {
|
|
|
4522
4592
|
"src/features/cookie-consent/components/CookieConsentBanner.tsx": cookieConsentBanner(),
|
|
4523
4593
|
"src/features/cookie-consent/components/CookiePreferencesDialog.tsx": cookiePreferencesDialog(),
|
|
4524
4594
|
"src/features/cookie-consent/components/index.ts": componentsIndex(),
|
|
4525
|
-
"src/features/cookie-consent/index.ts":
|
|
4595
|
+
"src/features/cookie-consent/index.ts": featureIndex6()
|
|
4526
4596
|
};
|
|
4527
4597
|
let count = 0;
|
|
4528
4598
|
for (const [filePath, content] of Object.entries(files)) {
|
|
@@ -4532,17 +4602,19 @@ async function generateCookieConsent(projectRoot) {
|
|
|
4532
4602
|
await fs15.writeFile(fullPath, content);
|
|
4533
4603
|
count++;
|
|
4534
4604
|
}
|
|
4605
|
+
await wireLayout3(projectRoot, ctx);
|
|
4535
4606
|
await setConfigFlag10(projectRoot, ctx);
|
|
4536
4607
|
await ctx.commit();
|
|
4537
|
-
log.success(`Generated cookie consent feature
|
|
4608
|
+
log.success(`Generated and wired cookie consent feature (${count} files created)`);
|
|
4538
4609
|
log.blank();
|
|
4539
4610
|
log.step("src/features/cookie-consent/types.ts \u2014 ConsentStatus, ConsentPreferences");
|
|
4540
4611
|
log.step("src/features/cookie-consent/hooks/use-consent.ts \u2014 useConsent hook");
|
|
4541
4612
|
log.step("src/features/cookie-consent/components/CookieConsentBanner.tsx \u2014 banner");
|
|
4542
4613
|
log.step("src/features/cookie-consent/components/CookiePreferencesDialog.tsx \u2014 preferences modal");
|
|
4543
4614
|
log.blank();
|
|
4544
|
-
log.
|
|
4545
|
-
log.step("
|
|
4615
|
+
log.step("Wired automatically:");
|
|
4616
|
+
log.step(" \u2713 CookieConsentBanner mounted in root layout");
|
|
4617
|
+
log.blank();
|
|
4546
4618
|
log.step("Optionally add <CookiePreferencesDialog /> for granular consent management");
|
|
4547
4619
|
log.step("Check consent status with useConsent() before loading tracking scripts");
|
|
4548
4620
|
log.blank();
|
|
@@ -4551,6 +4623,20 @@ async function generateCookieConsent(projectRoot) {
|
|
|
4551
4623
|
throw error;
|
|
4552
4624
|
}
|
|
4553
4625
|
}
|
|
4626
|
+
async function wireLayout3(projectRoot, ctx) {
|
|
4627
|
+
const layoutPath = path15.join(projectRoot, "src", "app", "layout.tsx");
|
|
4628
|
+
if (!await fs15.pathExists(layoutPath)) return;
|
|
4629
|
+
await ctx.trackModifiedFile(layoutPath);
|
|
4630
|
+
let content = await fs15.readFile(layoutPath, "utf-8");
|
|
4631
|
+
if (content.includes("CookieConsentBanner")) return;
|
|
4632
|
+
content = `import { CookieConsentBanner } from '@/features/cookie-consent';
|
|
4633
|
+
${content}`;
|
|
4634
|
+
content = content.replace(
|
|
4635
|
+
/(\s*)(<Providers>\{children\}<\/Providers>)/,
|
|
4636
|
+
"$1$2\n$1<CookieConsentBanner />"
|
|
4637
|
+
);
|
|
4638
|
+
await fs15.writeFile(layoutPath, content);
|
|
4639
|
+
}
|
|
4554
4640
|
async function setConfigFlag10(projectRoot, ctx) {
|
|
4555
4641
|
const configPath = path15.join(projectRoot, "src", "config", "app.config.ts");
|
|
4556
4642
|
if (!await fs15.pathExists(configPath)) return;
|
|
@@ -4819,7 +4905,7 @@ export { CookieConsentBanner } from './CookieConsentBanner';
|
|
|
4819
4905
|
export { CookiePreferencesDialog } from './CookiePreferencesDialog';
|
|
4820
4906
|
`;
|
|
4821
4907
|
}
|
|
4822
|
-
function
|
|
4908
|
+
function featureIndex6() {
|
|
4823
4909
|
return `${STAMP10}
|
|
4824
4910
|
export type { ConsentStatus, ConsentPreferences } from './types';
|
|
4825
4911
|
export { useConsent } from './hooks/use-consent';
|
|
@@ -5292,7 +5378,7 @@ async function generateFeatureFlags(projectRoot) {
|
|
|
5292
5378
|
"src/features/feature-flags/hooks/use-feature-flag.ts": useFeatureFlag(),
|
|
5293
5379
|
"src/features/feature-flags/components/FeatureGate.tsx": featureGate(),
|
|
5294
5380
|
"src/features/feature-flags/components/index.ts": componentsIndex3(),
|
|
5295
|
-
"src/features/feature-flags/index.ts":
|
|
5381
|
+
"src/features/feature-flags/index.ts": featureIndex7(),
|
|
5296
5382
|
"src/config/feature-flags.json": featureFlagsJson(),
|
|
5297
5383
|
"src/app/api/protected/feature-flags/route.ts": apiRoute()
|
|
5298
5384
|
};
|
|
@@ -5503,7 +5589,7 @@ function componentsIndex3() {
|
|
|
5503
5589
|
export { FeatureGate } from './FeatureGate';
|
|
5504
5590
|
`;
|
|
5505
5591
|
}
|
|
5506
|
-
function
|
|
5592
|
+
function featureIndex7() {
|
|
5507
5593
|
return `${STAMP13}
|
|
5508
5594
|
export { getFlag } from './server';
|
|
5509
5595
|
export { useFeatureFlag } from './hooks/use-feature-flag';
|