@lastbrain/app 2.0.12 → 2.0.18
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/config/version.d.ts +1 -1
- package/dist/config/version.d.ts.map +1 -1
- package/dist/config/version.js +22 -19
- package/dist/layouts/AdminLayout.js +1 -1
- package/dist/layouts/AuthLayout.js +1 -1
- package/dist/layouts/PublicLayout.d.ts.map +1 -1
- package/dist/layouts/PublicLayout.js +1 -1
- package/dist/layouts/RootLayout.js +1 -1
- package/dist/scripts/init-app.js +8 -53
- package/dist/scripts/module-build.d.ts.map +1 -1
- package/dist/scripts/module-build.js +6 -2
- package/dist/scripts/module-create.d.ts +1 -0
- package/dist/scripts/module-create.d.ts.map +1 -1
- package/dist/scripts/module-create.js +152 -31
- package/dist/styles.css +1 -1
- package/dist/templates/DefaultDoc.d.ts.map +1 -1
- package/dist/templates/DefaultDoc.js +1 -1
- package/package.json +6 -5
- package/src/config/version.ts +29 -0
- package/src/layouts/AdminLayout.tsx +1 -1
- package/src/layouts/AuthLayout.tsx +1 -1
- package/src/layouts/PublicLayout.tsx +3 -1
- package/src/layouts/RootLayout.tsx +1 -1
- package/src/scripts/init-app.ts +2 -2
- package/src/scripts/module-build.ts +7 -2
- package/src/scripts/module-create.ts +230 -70
- package/src/templates/DefaultDoc.tsx +48 -2
package/dist/config/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../config/version.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/config/version.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAsBnD,CAAC"}
|
package/dist/config/version.js
CHANGED
|
@@ -1,25 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* AUTO-GENERATED FILE - Généré par scripts/
|
|
2
|
+
* AUTO-GENERATED FILE - Généré par scripts/sync-versions.js
|
|
3
3
|
* NE PAS MODIFIER MANUELLEMENT
|
|
4
4
|
* Mise à jour automatique lors de pnpm version:patch/minor/major
|
|
5
5
|
*/
|
|
6
6
|
export const PACKAGE_VERSIONS = {
|
|
7
|
-
"@lastbrain-labs/module-billing-pro": "^2.0.
|
|
8
|
-
"@lastbrain-labs/module-
|
|
9
|
-
"@lastbrain-labs/module-core-
|
|
10
|
-
"@lastbrain-labs/module-core-
|
|
11
|
-
"@lastbrain-labs/module-core-
|
|
12
|
-
"@lastbrain-labs/module-core-
|
|
13
|
-
"@lastbrain-labs/module-
|
|
14
|
-
"@lastbrain/
|
|
15
|
-
"@lastbrain/
|
|
16
|
-
"@lastbrain/
|
|
17
|
-
"@lastbrain/
|
|
18
|
-
"@lastbrain/module-
|
|
19
|
-
"@lastbrain/module-
|
|
20
|
-
"@lastbrain/module-
|
|
21
|
-
"@lastbrain/
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"apps/
|
|
7
|
+
"@lastbrain-labs/module-billing-pro": "^2.0.14",
|
|
8
|
+
"@lastbrain-labs/module-cj-analyzer-pro": "^0.1.6",
|
|
9
|
+
"@lastbrain-labs/module-core-cart-pro": "^2.0.14",
|
|
10
|
+
"@lastbrain-labs/module-core-commerce-pro": "^2.0.14",
|
|
11
|
+
"@lastbrain-labs/module-core-order-pro": "^2.0.14",
|
|
12
|
+
"@lastbrain-labs/module-core-payment-pro": "^2.0.14",
|
|
13
|
+
"@lastbrain-labs/module-core-product-pro": "^2.0.14",
|
|
14
|
+
"@lastbrain-labs/module-recipes-pro": "^2.0.14",
|
|
15
|
+
"@lastbrain-labs/module-shop-pro": "^0.1.6",
|
|
16
|
+
"@lastbrain/app": "^2.0.17",
|
|
17
|
+
"@lastbrain/core": "^2.0.15",
|
|
18
|
+
"@lastbrain/module-ai": "^2.0.14",
|
|
19
|
+
"@lastbrain/module-auth": "^2.0.15",
|
|
20
|
+
"@lastbrain/module-legal": "^2.0.14",
|
|
21
|
+
"@lastbrain/module-project-board": "^2.0.14",
|
|
22
|
+
"@lastbrain/module-tasks": "^2.0.14",
|
|
23
|
+
"@lastbrain/ui": "^2.0.15",
|
|
24
|
+
"apps/recipe": "^2.0.10",
|
|
25
|
+
"apps/test-app": "^2.0.10",
|
|
26
|
+
"apps/test-module": "^2.0.10",
|
|
27
|
+
"lastbrain": "^2.0.10",
|
|
25
28
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PublicLayout.d.ts","sourceRoot":"","sources":["../../src/layouts/PublicLayout.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAU,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAE1D,UAAU,iBAAiB;IACzB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE,iBAAiB,
|
|
1
|
+
{"version":3,"file":"PublicLayout.d.ts","sourceRoot":"","sources":["../../src/layouts/PublicLayout.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAU,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAE1D,UAAU,iBAAiB;IACzB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE,iBAAiB,2CASzE"}
|
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { Footer } from "@lastbrain/ui";
|
|
4
4
|
export function PublicLayout({ children, footerConfig }) {
|
|
5
|
-
return (_jsxs(_Fragment, { children: [_jsx("section", { className: "pt-16 min-h-[calc(100vh)]", children: children }), footerConfig && _jsx(Footer, { config: footerConfig })] }));
|
|
5
|
+
return (_jsxs(_Fragment, { children: [_jsx("section", { className: "pt-16 min-h-[calc(100vh)] max-w-screen", children: children }), footerConfig && _jsx(Footer, { config: footerConfig })] }));
|
|
6
6
|
}
|
|
@@ -5,5 +5,5 @@ import { AppProviders } from "./AppProviders";
|
|
|
5
5
|
// Note: L'app Next.js doit importer son propre globals.css dans son layout
|
|
6
6
|
// Note: La configuration realtime doit être fournie par l'app qui utilise ce layout
|
|
7
7
|
export function RootLayout({ children, realtimeConfig = [], }) {
|
|
8
|
-
return (_jsx("html", { lang: "fr", suppressHydrationWarning: true, children: _jsx("body", { className: "min-h-screen", children: _jsx(ThemeProvider, { attribute: "class", defaultTheme: "light", enableSystem: false, storageKey: "lastbrain-theme", children: _jsx(AppProviders, { realtimeConfig: realtimeConfig, children: _jsx("div", { className: " min-h-screen bg-slate-50 text-slate-900 dark:bg-slate-950 dark:text-white", children: children }) }) }) }) }));
|
|
8
|
+
return (_jsx("html", { lang: "fr", suppressHydrationWarning: true, children: _jsx("body", { className: "min-h-screen max-w-screen", children: _jsx(ThemeProvider, { attribute: "class", defaultTheme: "light", enableSystem: false, storageKey: "lastbrain-theme", children: _jsx(AppProviders, { realtimeConfig: realtimeConfig, children: _jsx("div", { className: " min-h-screen bg-slate-50 text-slate-900 dark:bg-slate-950 dark:text-white", children: children }) }) }) }) }));
|
|
9
9
|
}
|
package/dist/scripts/init-app.js
CHANGED
|
@@ -5,6 +5,7 @@ import chalk from "chalk";
|
|
|
5
5
|
import inquirer from "inquirer";
|
|
6
6
|
import { execSync } from "child_process";
|
|
7
7
|
import { AVAILABLE_MODULES } from "@lastbrain/core/config/modules";
|
|
8
|
+
import { PACKAGE_VERSIONS } from "../config/version.js";
|
|
8
9
|
const __filename = fileURLToPath(import.meta.url);
|
|
9
10
|
const __dirname = path.dirname(__filename);
|
|
10
11
|
export async function initApp(options) {
|
|
@@ -250,59 +251,13 @@ function getLastBrainVersions(targetDir) {
|
|
|
250
251
|
moduleAi: "workspace:*",
|
|
251
252
|
};
|
|
252
253
|
}
|
|
253
|
-
// Hors monorepo,
|
|
254
|
-
try {
|
|
255
|
-
// Détecter si on est dans le contexte du package CLI en build
|
|
256
|
-
const cliPkgPath = path.join(__dirname, "../../package.json");
|
|
257
|
-
if (fs.existsSync(cliPkgPath)) {
|
|
258
|
-
const cliPkg = JSON.parse(fs.readFileSync(cliPkgPath, "utf-8"));
|
|
259
|
-
const cliVersion = `^${cliPkg.version}`;
|
|
260
|
-
// Essayer de lire les versions depuis le monorepo (si disponible)
|
|
261
|
-
const monorepoRoot = path.join(__dirname, "../../../../");
|
|
262
|
-
const moduleAuthPkgPath = path.join(monorepoRoot, "packages/module-auth/package.json");
|
|
263
|
-
const moduleAiPkgPath = path.join(monorepoRoot, "packages/module-ai/package.json");
|
|
264
|
-
const corePkgPath = path.join(monorepoRoot, "packages/core/package.json");
|
|
265
|
-
const uiPkgPath = path.join(monorepoRoot, "packages/ui/package.json");
|
|
266
|
-
let moduleAuthVersion = "latest";
|
|
267
|
-
let moduleAiVersion = "latest";
|
|
268
|
-
let coreVersion = "latest";
|
|
269
|
-
let uiVersion = "latest";
|
|
270
|
-
// Lire les vraies versions depuis les package.json du monorepo
|
|
271
|
-
if (fs.existsSync(moduleAuthPkgPath)) {
|
|
272
|
-
const moduleAuthPkg = JSON.parse(fs.readFileSync(moduleAuthPkgPath, "utf-8"));
|
|
273
|
-
moduleAuthVersion = `^${moduleAuthPkg.version}`;
|
|
274
|
-
}
|
|
275
|
-
if (fs.existsSync(moduleAiPkgPath)) {
|
|
276
|
-
const moduleAiPkg = JSON.parse(fs.readFileSync(moduleAiPkgPath, "utf-8"));
|
|
277
|
-
moduleAiVersion = `^${moduleAiPkg.version}`;
|
|
278
|
-
}
|
|
279
|
-
if (fs.existsSync(corePkgPath)) {
|
|
280
|
-
const corePkg = JSON.parse(fs.readFileSync(corePkgPath, "utf-8"));
|
|
281
|
-
coreVersion = `^${corePkg.version}`;
|
|
282
|
-
}
|
|
283
|
-
if (fs.existsSync(uiPkgPath)) {
|
|
284
|
-
const uiPkg = JSON.parse(fs.readFileSync(uiPkgPath, "utf-8"));
|
|
285
|
-
uiVersion = `^${uiPkg.version}`;
|
|
286
|
-
}
|
|
287
|
-
return {
|
|
288
|
-
app: "^2.0.0",
|
|
289
|
-
core: coreVersion === "latest" ? "^2.0.0" : coreVersion,
|
|
290
|
-
ui: uiVersion === "latest" ? "^2.0.0" : uiVersion,
|
|
291
|
-
moduleAuth: moduleAuthVersion === "latest" ? "^2.0.0" : moduleAuthVersion,
|
|
292
|
-
moduleAi: moduleAiVersion,
|
|
293
|
-
};
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
catch (_error) {
|
|
297
|
-
console.warn(chalk.yellow(`⚠️ Impossible de lire les versions locales (${_error}), utilisation de 'latest'`));
|
|
298
|
-
}
|
|
299
|
-
// Fallback: utiliser "latest"
|
|
254
|
+
// Hors monorepo, utiliser les versions publiées
|
|
300
255
|
return {
|
|
301
|
-
app: "latest",
|
|
302
|
-
core: "latest",
|
|
303
|
-
ui: "latest",
|
|
304
|
-
moduleAuth: "latest",
|
|
305
|
-
moduleAi: "latest",
|
|
256
|
+
app: PACKAGE_VERSIONS["@lastbrain/app"] || "latest",
|
|
257
|
+
core: PACKAGE_VERSIONS["@lastbrain/core"] || "latest",
|
|
258
|
+
ui: PACKAGE_VERSIONS["@lastbrain/ui"] || "latest",
|
|
259
|
+
moduleAuth: PACKAGE_VERSIONS["@lastbrain/module-auth"] || "latest",
|
|
260
|
+
moduleAi: PACKAGE_VERSIONS["@lastbrain/module-ai"] || "latest",
|
|
306
261
|
};
|
|
307
262
|
}
|
|
308
263
|
async function addDependencies(targetDir, useHeroUI, withAuth, selectedModules = []) {
|
|
@@ -1838,7 +1793,7 @@ async function addScriptsToPackageJson(targetDir) {
|
|
|
1838
1793
|
start: "next start",
|
|
1839
1794
|
lint: "next lint",
|
|
1840
1795
|
lastbrain: scriptsPrefix,
|
|
1841
|
-
"build:modules": `${scriptsPrefix} module:build`,
|
|
1796
|
+
"build:modules": `${scriptsPrefix} module:build && prettier --write \\"**/*.{js,jsx,ts,tsx,json,md}\\"`,
|
|
1842
1797
|
"db:migrations:sync": `${scriptsPrefix} db:migrations:sync`,
|
|
1843
1798
|
"db:init": `${scriptsPrefix} db:init`,
|
|
1844
1799
|
"readme:create": `${scriptsPrefix} readme:create`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module-build.d.ts","sourceRoot":"","sources":["../../src/scripts/module-build.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"module-build.d.ts","sourceRoot":"","sources":["../../src/scripts/module-build.ts"],"names":[],"mappings":"AAs6CA,wBAAsB,cAAc,kBA+FnC"}
|
|
@@ -236,9 +236,13 @@ export default function ${wrapperName}${hasDynamicParams ? "(props: Record<strin
|
|
|
236
236
|
`;
|
|
237
237
|
}
|
|
238
238
|
else {
|
|
239
|
+
// Déterminer le chemin d'import
|
|
240
|
+
const importPath = page.entryPoint
|
|
241
|
+
? `${moduleConfig.moduleName}/${page.entryPoint}`
|
|
242
|
+
: moduleConfig.moduleName;
|
|
239
243
|
content = `// GENERATED BY LASTBRAIN MODULE BUILD
|
|
240
|
-
import { ${page.componentExport} } from "${
|
|
241
|
-
|
|
244
|
+
import { ${page.componentExport} } from "${importPath}";
|
|
245
|
+
${page.metadataExport ? `\nexport { ${page.metadataExport} as generateMetadata } from "${importPath}";\n` : ""}
|
|
242
246
|
export default function ${wrapperName}${hasDynamicParams ? "(props: Record<string, unknown>)" : "()"} {
|
|
243
247
|
return <${page.componentExport} ${hasDynamicParams ? "{...props}" : ""} />;
|
|
244
248
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module-create.d.ts","sourceRoot":"","sources":["../../src/scripts/module-create.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,CAAC,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC;CAC3C;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,MAAM,EAAE,WAAW,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"module-create.d.ts","sourceRoot":"","sources":["../../src/scripts/module-create.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,CAAC,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC;CAC3C;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AA61CD;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAiB1C;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,MAAM,iBA2MhB;AAED;;GAEG;AACH,wBAAsB,YAAY,kBAuOjC"}
|
|
@@ -73,11 +73,11 @@ function getLastBrainPackageVersions(rootDir) {
|
|
|
73
73
|
/**
|
|
74
74
|
* Génère le contenu du package.json
|
|
75
75
|
*/
|
|
76
|
-
function generatePackageJson(moduleName, slug, rootDir) {
|
|
76
|
+
function generatePackageJson(moduleName, slug, rootDir, isPro = false) {
|
|
77
77
|
const versions = getLastBrainPackageVersions(rootDir);
|
|
78
|
-
const moduleNameOnly = slug.replace("module-", "");
|
|
78
|
+
const moduleNameOnly = slug.replace("module-", "").replace("-pro", "");
|
|
79
79
|
const buildConfigExport = `./${moduleNameOnly}.build.config`;
|
|
80
|
-
|
|
80
|
+
const packageJson = {
|
|
81
81
|
name: moduleName,
|
|
82
82
|
version: "0.1.0",
|
|
83
83
|
private: false,
|
|
@@ -118,7 +118,36 @@ function generatePackageJson(moduleName, slug, rootDir) {
|
|
|
118
118
|
},
|
|
119
119
|
},
|
|
120
120
|
sideEffects: false,
|
|
121
|
-
}
|
|
121
|
+
};
|
|
122
|
+
// Ajouter les champs spécifiques selon le type (Pro ou Public)
|
|
123
|
+
if (isPro) {
|
|
124
|
+
packageJson.publishConfig = {
|
|
125
|
+
registry: "https://npm.pkg.github.com",
|
|
126
|
+
};
|
|
127
|
+
packageJson.release = {
|
|
128
|
+
type: "pro",
|
|
129
|
+
registry: "https://npm.pkg.github.com",
|
|
130
|
+
};
|
|
131
|
+
packageJson.repository = {
|
|
132
|
+
type: "git",
|
|
133
|
+
url: "https://github.com/Lastbrain-labs/starter",
|
|
134
|
+
directory: `packages/${slug}`,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
packageJson.publishConfig = {
|
|
139
|
+
access: "public",
|
|
140
|
+
};
|
|
141
|
+
packageJson.release = {
|
|
142
|
+
type: "public",
|
|
143
|
+
};
|
|
144
|
+
packageJson.repository = {
|
|
145
|
+
type: "git",
|
|
146
|
+
url: "https://github.com/Lastbrain-labs/lb-starter",
|
|
147
|
+
directory: `packages/${slug}`,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
return JSON.stringify(packageJson, null, 2);
|
|
122
151
|
}
|
|
123
152
|
/**
|
|
124
153
|
* Génère le contenu du tsconfig.json
|
|
@@ -301,12 +330,27 @@ function toPascalCase(value) {
|
|
|
301
330
|
.join("");
|
|
302
331
|
}
|
|
303
332
|
function generateIndexTs(pages, moduleNameOnly) {
|
|
333
|
+
// Grouper les pages par nom pour détecter les doublons
|
|
334
|
+
const pagesByName = new Map();
|
|
335
|
+
for (const page of pages) {
|
|
336
|
+
const key = page.name;
|
|
337
|
+
const existing = pagesByName.get(key) || [];
|
|
338
|
+
existing.push(page);
|
|
339
|
+
pagesByName.set(key, existing);
|
|
340
|
+
}
|
|
304
341
|
const exports = pages.map((page) => {
|
|
305
342
|
const componentName = toPascalCase(page.name);
|
|
306
|
-
|
|
307
|
-
|
|
343
|
+
// Si le même nom de page existe dans plusieurs sections, ajouter la section au nom du composant ET du fichier
|
|
344
|
+
const duplicates = pagesByName.get(page.name) || [];
|
|
345
|
+
const hasDuplicates = duplicates.length > 1;
|
|
346
|
+
const componentNameWithSection = hasDuplicates
|
|
347
|
+
? `${componentName}${toPascalCase(page.section)}`
|
|
348
|
+
: componentName;
|
|
349
|
+
return `export { ${componentNameWithSection}Page } from "./web/${page.section}/${componentNameWithSection}Page";`;
|
|
308
350
|
});
|
|
309
|
-
|
|
351
|
+
// Nettoyer le nom pour l'alias d'export (enlever -pro si présent)
|
|
352
|
+
const cleanedNameOnly = moduleNameOnly.replace(/-pro$/, "");
|
|
353
|
+
const moduleAlias = toPascalCase(cleanedNameOnly);
|
|
310
354
|
return `// Client Components
|
|
311
355
|
${exports.join("\n")}
|
|
312
356
|
|
|
@@ -335,21 +379,22 @@ ${exports.join("\n")}
|
|
|
335
379
|
/**
|
|
336
380
|
* Génère le contenu d'une page
|
|
337
381
|
*/
|
|
338
|
-
function generatePageComponent(pageName, section) {
|
|
339
|
-
const
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
382
|
+
function generatePageComponent(pageName, section, componentName) {
|
|
383
|
+
const finalComponentName = componentName ||
|
|
384
|
+
pageName
|
|
385
|
+
.split("-")
|
|
386
|
+
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
|
|
387
|
+
.join("");
|
|
343
388
|
return `"use client";
|
|
344
389
|
|
|
345
390
|
import { Card, CardBody, CardHeader } from "@lastbrain/ui";
|
|
346
391
|
|
|
347
|
-
export function ${
|
|
392
|
+
export function ${finalComponentName}Page() {
|
|
348
393
|
return (
|
|
349
394
|
<div className="container mx-auto p-6">
|
|
350
395
|
<Card>
|
|
351
396
|
<CardHeader>
|
|
352
|
-
<h1 className="text-2xl font-bold">${
|
|
397
|
+
<h1 className="text-2xl font-bold">${finalComponentName}</h1>
|
|
353
398
|
</CardHeader>
|
|
354
399
|
<CardBody>
|
|
355
400
|
<p className="text-default-600">
|
|
@@ -1051,6 +1096,24 @@ async function updateModuleRegistry(config, rootDir) {
|
|
|
1051
1096
|
if (!fs.existsSync(moduleRegistryPath)) {
|
|
1052
1097
|
console.log(chalk.yellow(" ⚠️ Fichier de registre non trouvé, création..."));
|
|
1053
1098
|
// Si le fichier n'existe pas, on le crée avec le module actuel
|
|
1099
|
+
const moduleName = config.slug.replace("module-", "").replace("-pro", "");
|
|
1100
|
+
const moduleNameWithSuffix = config.isPro
|
|
1101
|
+
? `${moduleName}-pro`
|
|
1102
|
+
: moduleName;
|
|
1103
|
+
const moduleEntry = config.isPro
|
|
1104
|
+
? ` {
|
|
1105
|
+
name: "${moduleNameWithSuffix}",
|
|
1106
|
+
package: "${config.moduleName}",
|
|
1107
|
+
description: "Module ${config.moduleName}",
|
|
1108
|
+
emoji: "📦",
|
|
1109
|
+
isPro: true,
|
|
1110
|
+
},`
|
|
1111
|
+
: ` {
|
|
1112
|
+
name: "${moduleNameWithSuffix}",
|
|
1113
|
+
package: "${config.moduleName}",
|
|
1114
|
+
description: "Module ${config.moduleName}",
|
|
1115
|
+
emoji: "📦",
|
|
1116
|
+
},`;
|
|
1054
1117
|
const content = `/**
|
|
1055
1118
|
* Configuration centralisée des modules LastBrain
|
|
1056
1119
|
* Ce fichier est auto-généré et maintenu par les scripts de gestion des modules
|
|
@@ -1062,15 +1125,11 @@ export interface ModuleMetadata {
|
|
|
1062
1125
|
description: string;
|
|
1063
1126
|
emoji: string;
|
|
1064
1127
|
version?: string;
|
|
1128
|
+
isPro?: boolean;
|
|
1065
1129
|
}
|
|
1066
1130
|
|
|
1067
1131
|
export const AVAILABLE_MODULES: ModuleMetadata[] = [
|
|
1068
|
-
|
|
1069
|
-
name: "${config.slug.replace("module-", "")}",
|
|
1070
|
-
package: "@lastbrain/${config.slug}",
|
|
1071
|
-
description: "Module ${config.moduleName}",
|
|
1072
|
-
emoji: "📦",
|
|
1073
|
-
},
|
|
1132
|
+
${moduleEntry}
|
|
1074
1133
|
];
|
|
1075
1134
|
|
|
1076
1135
|
/**
|
|
@@ -1100,18 +1159,33 @@ export function getAvailableModuleNames(): string[] {
|
|
|
1100
1159
|
}
|
|
1101
1160
|
try {
|
|
1102
1161
|
let content = await fs.readFile(moduleRegistryPath, "utf-8");
|
|
1103
|
-
const moduleName = config.slug.replace("module-", "");
|
|
1104
|
-
const
|
|
1105
|
-
|
|
1106
|
-
|
|
1162
|
+
const moduleName = config.slug.replace("module-", "").replace("-pro", "");
|
|
1163
|
+
const moduleNameWithSuffix = config.isPro
|
|
1164
|
+
? `${moduleName}-pro`
|
|
1165
|
+
: moduleName;
|
|
1166
|
+
const moduleEntry = config.isPro
|
|
1167
|
+
? ` {
|
|
1168
|
+
name: "${moduleNameWithSuffix}",
|
|
1169
|
+
package: "${config.moduleName}",
|
|
1170
|
+
description: "Module ${config.moduleName}",
|
|
1171
|
+
emoji: "📦",
|
|
1172
|
+
isPro: true,
|
|
1173
|
+
},`
|
|
1174
|
+
: ` {
|
|
1175
|
+
name: "${moduleNameWithSuffix}",
|
|
1176
|
+
package: "${config.moduleName}",
|
|
1107
1177
|
description: "Module ${config.moduleName}",
|
|
1108
1178
|
emoji: "📦",
|
|
1109
1179
|
},`;
|
|
1110
1180
|
// Vérifier si le module existe déjà
|
|
1111
|
-
if (content.includes(`name: "${
|
|
1112
|
-
console.log(chalk.yellow(` ⚠️ Module ${
|
|
1181
|
+
if (content.includes(`name: "${moduleNameWithSuffix}"`)) {
|
|
1182
|
+
console.log(chalk.yellow(` ⚠️ Module ${moduleNameWithSuffix} déjà présent dans le registre`));
|
|
1113
1183
|
return;
|
|
1114
1184
|
}
|
|
1185
|
+
// Vérifier si l'interface a le champ isPro
|
|
1186
|
+
if (!content.includes("isPro?: boolean;")) {
|
|
1187
|
+
content = content.replace(/version\?: string;\s*\}/, "version?: string;\n isPro?: boolean;\n}");
|
|
1188
|
+
}
|
|
1115
1189
|
// Trouver le tableau AVAILABLE_MODULES et ajouter le module
|
|
1116
1190
|
const arrayMatch = content.match(/export const AVAILABLE_MODULES: ModuleMetadata\[\] = \[([\s\S]*?)\];/);
|
|
1117
1191
|
if (arrayMatch) {
|
|
@@ -1165,7 +1239,7 @@ export async function createModuleStructure(config, rootDir) {
|
|
|
1165
1239
|
await fs.ensureDir(path.join(moduleDir, "supabase", "migrations-down"));
|
|
1166
1240
|
// Créer package.json
|
|
1167
1241
|
console.log(chalk.yellow(" 📄 package.json"));
|
|
1168
|
-
await fs.writeFile(path.join(moduleDir, "package.json"), generatePackageJson(config.moduleName, config.slug, rootDir));
|
|
1242
|
+
await fs.writeFile(path.join(moduleDir, "package.json"), generatePackageJson(config.moduleName, config.slug, rootDir, config.isPro || false));
|
|
1169
1243
|
// Créer tsconfig.json
|
|
1170
1244
|
console.log(chalk.yellow(" 📄 tsconfig.json"));
|
|
1171
1245
|
await fs.writeFile(path.join(moduleDir, "tsconfig.json"), generateTsConfig());
|
|
@@ -1184,16 +1258,30 @@ export async function createModuleStructure(config, rootDir) {
|
|
|
1184
1258
|
await fs.writeFile(path.join(moduleDir, "src", "components", "Doc.tsx"), generateDocComponent(config));
|
|
1185
1259
|
// Créer les pages
|
|
1186
1260
|
console.log(chalk.blue("\n📄 Création des pages..."));
|
|
1261
|
+
// Grouper les pages par nom pour détecter les doublons
|
|
1262
|
+
const pagesByName = new Map();
|
|
1263
|
+
for (const page of config.pages) {
|
|
1264
|
+
const key = page.name;
|
|
1265
|
+
const existing = pagesByName.get(key) || [];
|
|
1266
|
+
existing.push(page);
|
|
1267
|
+
pagesByName.set(key, existing);
|
|
1268
|
+
}
|
|
1187
1269
|
for (const page of config.pages) {
|
|
1188
1270
|
const pagePath = path.join(moduleDir, "src", "web", page.section);
|
|
1189
1271
|
await fs.ensureDir(pagePath);
|
|
1190
|
-
const
|
|
1272
|
+
const baseName = page.name
|
|
1191
1273
|
.split("-")
|
|
1192
1274
|
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
|
|
1193
1275
|
.join("");
|
|
1194
|
-
|
|
1276
|
+
// Si le même nom de page existe dans plusieurs sections, ajouter la section au nom du fichier
|
|
1277
|
+
const duplicates = pagesByName.get(page.name) || [];
|
|
1278
|
+
const hasDuplicates = duplicates.length > 1;
|
|
1279
|
+
const componentNameWithSection = hasDuplicates
|
|
1280
|
+
? `${baseName}${toPascalCase(page.section)}`
|
|
1281
|
+
: baseName;
|
|
1282
|
+
const fileName = `${componentNameWithSection}Page.tsx`;
|
|
1195
1283
|
console.log(chalk.yellow(` 📄 src/web/${page.section}/${fileName}`));
|
|
1196
|
-
await fs.writeFile(path.join(pagePath, fileName), generatePageComponent(page.name, page.section));
|
|
1284
|
+
await fs.writeFile(path.join(pagePath, fileName), generatePageComponent(page.name, page.section, componentNameWithSection));
|
|
1197
1285
|
}
|
|
1198
1286
|
// Créer les routes API
|
|
1199
1287
|
if (config.tables.length > 0) {
|
|
@@ -1401,10 +1489,43 @@ export async function createModule() {
|
|
|
1401
1489
|
sections,
|
|
1402
1490
|
});
|
|
1403
1491
|
}
|
|
1492
|
+
// 🛡️ VALIDATION : Détecter et corriger les collisions de noms de pages
|
|
1493
|
+
const pagesByName = new Map();
|
|
1494
|
+
for (const page of pages) {
|
|
1495
|
+
const existing = pagesByName.get(page.name) || [];
|
|
1496
|
+
existing.push(page);
|
|
1497
|
+
pagesByName.set(page.name, existing);
|
|
1498
|
+
}
|
|
1499
|
+
const correctedPages = [];
|
|
1500
|
+
const collisionsDetected = new Set();
|
|
1501
|
+
for (const page of pages) {
|
|
1502
|
+
const duplicates = pagesByName.get(page.name) || [];
|
|
1503
|
+
if (duplicates.length > 1) {
|
|
1504
|
+
// Collision détectée ! Ajouter un suffixe pour différencier
|
|
1505
|
+
const correctedPage = {
|
|
1506
|
+
...page,
|
|
1507
|
+
name: `${page.name}-${page.section}`,
|
|
1508
|
+
path: `${page.path}-${page.section}`,
|
|
1509
|
+
};
|
|
1510
|
+
// Afficher l'avertissement une fois par groupe de doublons
|
|
1511
|
+
if (!collisionsDetected.has(page.name)) {
|
|
1512
|
+
collisionsDetected.add(page.name);
|
|
1513
|
+
console.log(chalk.yellow(`\n⚠️ Collision détectée pour la page "${page.name}" (existe dans plusieurs sections)`));
|
|
1514
|
+
console.log(chalk.gray(` Les pages seront renommées automatiquement pour éviter les conflits:`));
|
|
1515
|
+
duplicates.forEach((dup) => {
|
|
1516
|
+
console.log(chalk.gray(` - [${dup.section}] ${dup.name} → ${dup.name}-${dup.section}`));
|
|
1517
|
+
});
|
|
1518
|
+
}
|
|
1519
|
+
correctedPages.push(correctedPage);
|
|
1520
|
+
}
|
|
1521
|
+
else {
|
|
1522
|
+
correctedPages.push(page);
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1404
1525
|
const config = {
|
|
1405
1526
|
slug,
|
|
1406
1527
|
moduleName,
|
|
1407
|
-
pages,
|
|
1528
|
+
pages: correctedPages,
|
|
1408
1529
|
tables,
|
|
1409
1530
|
description,
|
|
1410
1531
|
};
|